From 9fcb387d403d78c08c7a726f492716e4ea4324b5 Mon Sep 17 00:00:00 2001 From: Joe Walker Date: Wed, 4 Jul 2012 23:37:25 +0100 Subject: [PATCH 01/31] Bug 761481 - GCLI help output does not display the first time; r=dcamp --- browser/devtools/shared/DeveloperToolbar.jsm | 5 ----- 1 file changed, 5 deletions(-) diff --git a/browser/devtools/shared/DeveloperToolbar.jsm b/browser/devtools/shared/DeveloperToolbar.jsm index 73bd6dc45a6a..946af50fe942 100644 --- a/browser/devtools/shared/DeveloperToolbar.jsm +++ b/browser/devtools/shared/DeveloperToolbar.jsm @@ -187,7 +187,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,7 +306,6 @@ 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); @@ -368,9 +366,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); } From 8ffdb2d7a49daddcf7be67014528ddff3bda4c77 Mon Sep 17 00:00:00 2001 From: Joe Walker Date: Wed, 4 Jul 2012 23:37:25 +0100 Subject: [PATCH 02/31] Bug 769234 - [devtb] GCLI has focus issues when embedded in firefox; r=dcamp --- browser/devtools/commandline/gcli.jsm | 8 ++++++++ browser/devtools/shared/DeveloperToolbar.jsm | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/browser/devtools/commandline/gcli.jsm b/browser/devtools/commandline/gcli.jsm index 0ce911139aed..379cb2f9b623 100644 --- a/browser/devtools/commandline/gcli.jsm +++ b/browser/devtools/commandline/gcli.jsm @@ -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' }; } diff --git a/browser/devtools/shared/DeveloperToolbar.jsm b/browser/devtools/shared/DeveloperToolbar.jsm index 946af50fe942..c5dee8a9333d 100644 --- a/browser/devtools/shared/DeveloperToolbar.jsm +++ b/browser/devtools/shared/DeveloperToolbar.jsm @@ -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); @@ -310,6 +313,9 @@ DeveloperToolbar.prototype.destroy = function DT_destroy() 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); From b6a3a3d554b9a37760684f37caf2979a0e3598d8 Mon Sep 17 00:00:00 2001 From: Joe Walker Date: Wed, 4 Jul 2012 23:37:25 +0100 Subject: [PATCH 03/31] Bug 768150 - The developer toolbar should be preffed on by default for testing on nightly only; r=ttaubert --- browser/app/profile/firefox.js | 2 +- browser/base/content/browser-menubar.inc | 1 - browser/base/content/browser-sets.inc | 7 ------- browser/locales/en-US/chrome/browser/browser.dtd | 2 -- 4 files changed, 1 insertion(+), 11 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index cd898b668cd9..41c76e554208 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -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", ""); diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc index 8dd6a3c23385..1f2a77ef927d 100644 --- a/browser/base/content/browser-menubar.inc +++ b/browser/base/content/browser-menubar.inc @@ -519,7 +519,6 @@ autocheck="false" hidden="true" label="&devToolbarMenu.label;" - accesskey="&devToolbarMenu.accesskey;" key="key_devToolbar" command="Tools:DevToolbar"/> - - - From a93cb671b83919e8f5ddf3d1844bad6e6b059293 Mon Sep 17 00:00:00 2001 From: Joe Walker Date: Wed, 4 Jul 2012 23:39:58 +0100 Subject: [PATCH 04/31] =?UTF-8?q?Bug=20760450=20-=20Work=20out=20why=20GCL?= =?UTF-8?q?I=20popup=20panels=20are=20not=20transparent=20on=20mac/linux;?= =?UTF-8?q?=20r=3Ddcamp,d=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- browser/devtools/shared/DeveloperToolbar.jsm | 2 +- browser/devtools/shared/test/browser_toolbar_tooltip.js | 2 +- browser/themes/gnomestripe/browser.css | 1 + browser/themes/gnomestripe/devtools/gcli.css | 2 +- browser/themes/pinstripe/browser.css | 1 + browser/themes/pinstripe/devtools/gcli.css | 3 ++- browser/themes/winstripe/browser.css | 1 + 7 files changed, 8 insertions(+), 4 deletions(-) mode change 100755 => 100644 browser/devtools/shared/test/browser_toolbar_tooltip.js diff --git a/browser/devtools/shared/DeveloperToolbar.jsm b/browser/devtools/shared/DeveloperToolbar.jsm index c5dee8a9333d..e8cb664a856a 100644 --- a/browser/devtools/shared/DeveloperToolbar.jsm +++ b/browser/devtools/shared/DeveloperToolbar.jsm @@ -813,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 diff --git a/browser/devtools/shared/test/browser_toolbar_tooltip.js b/browser/devtools/shared/test/browser_toolbar_tooltip.js old mode 100755 new mode 100644 index 506863c871e9..4bd7e87ce40e --- a/browser/devtools/shared/test/browser_toolbar_tooltip.js +++ b/browser/devtools/shared/test/browser_toolbar_tooltip.js @@ -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); } diff --git a/browser/themes/gnomestripe/browser.css b/browser/themes/gnomestripe/browser.css index a6c19c904a9a..186dc742e1ff 100644 --- a/browser/themes/gnomestripe/browser.css +++ b/browser/themes/gnomestripe/browser.css @@ -2398,6 +2398,7 @@ html|*#gcli-output-frame { #gcli-tooltip { border-width: 0; background-color: transparent; + -moz-appearance: none; margin-bottom: -2px; } diff --git a/browser/themes/gnomestripe/devtools/gcli.css b/browser/themes/gnomestripe/devtools/gcli.css index 737a57c24b89..6865462359f7 100644 --- a/browser/themes/gnomestripe/devtools/gcli.css +++ b/browser/themes/gnomestripe/devtools/gcli.css @@ -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%); diff --git a/browser/themes/pinstripe/browser.css b/browser/themes/pinstripe/browser.css index 5f197c94406b..9f6e0e3216d0 100644 --- a/browser/themes/pinstripe/browser.css +++ b/browser/themes/pinstripe/browser.css @@ -3139,6 +3139,7 @@ html|*#gcli-output-frame { #gcli-tooltip { border-width: 0; background-color: transparent; + -moz-appearance: none; margin-bottom: -2px; } diff --git a/browser/themes/pinstripe/devtools/gcli.css b/browser/themes/pinstripe/devtools/gcli.css index 99653cd7a607..05fc08b36fb3 100644 --- a/browser/themes/pinstripe/devtools/gcli.css +++ b/browser/themes/pinstripe/devtools/gcli.css @@ -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, diff --git a/browser/themes/winstripe/browser.css b/browser/themes/winstripe/browser.css index 5052b0dd2743..777077d39d3b 100644 --- a/browser/themes/winstripe/browser.css +++ b/browser/themes/winstripe/browser.css @@ -3073,6 +3073,7 @@ html|*#gcli-output-frame { #gcli-tooltip { border-width: 0; background-color: transparent; + -moz-appearance: none; margin-bottom: -2px; } From acce5240bddda715cca897652674883e84a7a8d1 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Wed, 4 Jul 2012 19:33:41 -0700 Subject: [PATCH 05/31] Bug 771018 - Replace "const Shape" with "Shape" (r=luke) --- js/src/frontend/Parser.cpp | 4 +- js/src/frontend/TreeContext-inl.h | 2 +- js/src/jsapi.cpp | 2 +- js/src/jsarray.cpp | 2 +- js/src/jscntxt.cpp | 2 +- js/src/jscntxt.h | 8 ++-- js/src/jsinfer.cpp | 26 ++++++------- js/src/jsinferinlines.h | 2 +- js/src/jsinterp.cpp | 2 +- js/src/jsinterpinlines.h | 4 +- js/src/jsiter.cpp | 8 ++-- js/src/jsiter.h | 2 +- js/src/jsobj.cpp | 64 +++++++++++++++---------------- js/src/jsobj.h | 14 +++---- js/src/jsobjinlines.h | 10 ++--- js/src/jsopcode.cpp | 6 +-- js/src/jspropertycache.cpp | 2 +- js/src/jspropertycache.h | 18 ++++----- js/src/jspropertycacheinlines.h | 4 +- js/src/jspropertytree.cpp | 2 +- js/src/jspropertytree.h | 2 +- js/src/jsscope.cpp | 8 ++-- js/src/jsscope.h | 26 ++++++------- js/src/jsscopeinlines.h | 14 +++---- js/src/jsscript.cpp | 8 ++-- js/src/jsscript.h | 2 +- js/src/jswatchpoint.cpp | 2 +- js/src/jsxml.cpp | 4 +- js/src/methodjit/BaseAssembler.h | 4 +- js/src/methodjit/Compiler.cpp | 4 +- js/src/methodjit/MonoIC.cpp | 8 ++-- js/src/methodjit/MonoIC.h | 2 +- js/src/methodjit/PolyIC.cpp | 32 ++++++++-------- js/src/vm/Debugger.cpp | 2 +- js/src/vm/ObjectImpl-inl.h | 8 ++-- js/src/vm/ObjectImpl.cpp | 6 +-- js/src/vm/ObjectImpl.h | 12 +++--- js/src/vm/ScopeObject.cpp | 8 ++-- js/src/vm/ScopeObject.h | 2 +- 39 files changed, 169 insertions(+), 169 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 85ad7b0cce67..ebdf6c7fdb06 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -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())) diff --git a/js/src/frontend/TreeContext-inl.h b/js/src/frontend/TreeContext-inl.h index 1ef086abc409..588c19d38d39 100644 --- a/js/src/frontend/TreeContext-inl.h +++ b/js/src/frontend/TreeContext-inl.h @@ -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()); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 08a875d8c633..9e5767151f2a 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -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); diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index b8d10a408d4c..3a07b66ed85c 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -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 diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index cca8194c6952..8318a8e30d48 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -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 shape = callee->nativeLookup(cx, NameToId(usageAtom)); + DebugOnly shape = callee->nativeLookup(cx, NameToId(usageAtom)); JS_ASSERT(!shape->configurable()); JS_ASSERT(!shape->writable()); JS_ASSERT(shape->hasDefaultGetter()); diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index a51d90901041..f6053a0b0e3e 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -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 JS_DECL_USE_GUARD_OBJECT_NOTIFIER }; -class AutoShapeVector : public AutoVectorRooter +class AutoShapeVector : public AutoVectorRooter { public: explicit AutoShapeVector(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter(cx, SHAPEVECTOR) + : AutoVectorRooter(cx, SHAPEVECTOR) { JS_GUARD_OBJECT_NOTIFIER_INIT; } diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index f7898904bd27..bff8383dbd03 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -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; diff --git a/js/src/jsinferinlines.h b/js/src/jsinferinlines.h index c143d003fbc6..1296c190149f 100644 --- a/js/src/jsinferinlines.h +++ b/js/src/jsinferinlines.h @@ -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(); diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 26a4c08024db..f9821067280b 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -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 */ diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index d817e3d67e64..e39da14f7be5 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -163,7 +163,7 @@ ValuePropertyBearer(JSContext *cx, StackFrame *fp, const Value &v, int spindex) } inline bool -NativeGet(JSContext *cx, Handle obj, Handle pobj, const Shape *shape, +NativeGet(JSContext *cx, Handle obj, Handle 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()); diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 3c6707d7af19..b03fb3da8071 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -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 shapes(cx); + Vector 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; diff --git a/js/src/jsiter.h b/js/src/jsiter.h index 3fd68d45c556..ba3c40abd15f 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -33,7 +33,7 @@ struct NativeIterator { HeapPtr *props_array; HeapPtr *props_cursor; HeapPtr *props_end; - const Shape **shapes_array; + Shape **shapes_array; uint32_t shapes_length; uint32_t shapes_key; uint32_t flags; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 4e308002ed4d..51396a510ebc 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -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 shape(cx, reinterpret_cast(current)); + Rooted shape(cx, reinterpret_cast(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(shape); + shape_ = shape; return true; } if (!updateSlotsForSpan(cx, oldSpan, newSpan)) return false; - shape_ = const_cast(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 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 receiver, JSObject *obj, JSO code->accessGetter = true; } - Rooted shapeRoot(cx, shape); + Rooted shapeRoot(cx, shape); RootedObject pobjRoot(cx, pobj); if (!shape->get(cx, receiver, obj, pobj, vp)) @@ -4573,7 +4573,7 @@ js_NativeGetInline(JSContext *cx, Handle receiver, JSObject *obj, JSO } JSBool -js_NativeGet(JSContext *cx, Handle obj, Handle pobj, const Shape *shape, +js_NativeGet(JSContext *cx, Handle obj, Handle 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 obj, Handle pobj, const JSBool js_NativeSet(JSContext *cx, Handle obj, Handle 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 obj, Handle receiver, return js_ReportGetterOnlyAssignment(cx); } - Rooted shapeRoot(cx, shape); + Rooted 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 props; + Vector props; for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront()) props.append(&r.front()); for (size_t i = props.length(); i-- != 0;) diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 82be64cd678f..4f4374283853 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -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 obj, js::Handle 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 obj, js::Handle receiver, - const js::Shape *shape, bool added, bool strict, js::Value *vp); + js::Shape *shape, bool added, bool strict, js::Value *vp); namespace js { diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 1ec811509aa3..4d4fea02c404 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -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(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 diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 344e75eda6f5..d726aa4c438d 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -423,7 +423,7 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes) Shape::Range::AutoRooter root(cx, &r); while (!r.empty()) { - Rooted shape(cx, &r.front()); + Rooted 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); diff --git a/js/src/jspropertycache.cpp b/js/src/jspropertycache.cpp index c24619b0d53b..9e8e53876e20 100644 --- a/js/src/jspropertycache.cpp +++ b/js/src/jspropertycache.cpp @@ -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); diff --git a/js/src/jspropertycache.h b/js/src/jspropertycache.h index 80822fe48bdb..e7fc77e7024b 100644 --- a/js/src/jspropertycache.h +++ b/js/src/jspropertycache.h @@ -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); diff --git a/js/src/jspropertycacheinlines.h b/js/src/jspropertycacheinlines.h index 2c6b9306d11d..01871a38e161 100644 --- a/js/src/jspropertycacheinlines.h +++ b/js/src/jspropertycacheinlines.h @@ -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); diff --git a/js/src/jspropertytree.cpp b/js/src/jspropertytree.cpp index 47ff489895ef..9952817d3d3c 100644 --- a/js/src/jspropertytree.cpp +++ b/js/src/jspropertytree.cpp @@ -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); diff --git a/js/src/jspropertytree.h b/js/src/jspropertytree.h index 0f0298ca9805..7e0b1f313801 100644 --- a/js/src/jspropertytree.h +++ b/js/src/jspropertytree.h @@ -60,7 +60,7 @@ class KidsPointer { } #ifdef DEBUG - void checkConsistency(const js::Shape *aKid) const; + void checkConsistency(js::Shape *aKid) const; #endif }; diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index cb45328f25b8..d6aad4a9ecbc 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -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); diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 46b404f5502a..0b87f621819f 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -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; } diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index 04a7b92c883d..6a10e0158889 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -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 self(cx, this); + Rooted 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 self(cx, this); + Rooted 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(); diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 88bf04a82ad7..cd796ead15aa 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -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 shapes(cx); + Vector shapes(cx); HashSet 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::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); diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 5c6c9de77b72..2f2699716442 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -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); diff --git a/js/src/jswatchpoint.cpp b/js/src/jswatchpoint.cpp index 903ff62c4da0..6a397241b530 100644 --- a/js/src/jswatchpoint.cpp +++ b/js/src/jswatchpoint.cpp @@ -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()); } diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 05943a0e4182..89c050d0fdb7 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -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) diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index b31def851480..71ae3964fc5e 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -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())) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 33bc95b6196f..d050029306aa 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -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)) { diff --git a/js/src/methodjit/MonoIC.cpp b/js/src/methodjit/MonoIC.cpp index dca1edcab616..acf0efcb4190 100644 --- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -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); diff --git a/js/src/methodjit/MonoIC.h b/js/src/methodjit/MonoIC.h index 61ae56a7c004..148ec3e18cd8 100644 --- a/js/src/methodjit/MonoIC.h +++ b/js/src/methodjit/MonoIC.h @@ -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); diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index c9bd29056971..2eedda0e3e8e 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -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 &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 &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 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 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(); diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index e0b0cd5ea5a7..d11d4a70c4ab 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -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 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(); diff --git a/js/src/vm/ObjectImpl-inl.h b/js/src/vm/ObjectImpl-inl.h index 87124b84efc2..db8943529e72 100644 --- a/js/src/vm/ObjectImpl-inl.h +++ b/js/src/vm/ObjectImpl-inl.h @@ -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)); diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 988b80ac828f..2651ebc90ea7 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -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 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(); diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index 718e119519ff..f64be6e5846b 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -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; diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 99cd8b55059a..4bb2f5286bc5 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -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 *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 *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(); diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 6ff8b265e972..0376d6cfa0ea 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -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 From 4efa4ac7f5439f15206e37bb57faff12d634e08a Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Wed, 4 Jul 2012 19:34:06 -0700 Subject: [PATCH 06/31] Bug 771026 - Replace JSProperty with Shape (r=bhackett) --- js/src/jsapi.cpp | 30 +++--- js/src/jsarray.cpp | 24 ++--- js/src/jsclass.h | 16 +-- js/src/jsclone.cpp | 2 +- js/src/jsinterp.cpp | 20 ++-- js/src/jsinterpinlines.h | 11 +-- js/src/jsiter.cpp | 4 +- js/src/jsobj.cpp | 176 +++++++++++++++------------------ js/src/jsobj.h | 26 ++--- js/src/jsobjinlines.h | 16 +-- js/src/jsproxy.cpp | 16 +-- js/src/jsprvtd.h | 3 +- js/src/jsscope.cpp | 13 +++ js/src/jsscope.h | 3 + js/src/jstypedarray.cpp | 36 ++++--- js/src/jstypedarray.h | 16 +-- js/src/jsxml.cpp | 22 ++--- js/src/methodjit/Compiler.cpp | 7 +- js/src/methodjit/FastOps.cpp | 7 +- js/src/methodjit/PolyIC.cpp | 29 +++--- js/src/methodjit/StubCalls.cpp | 13 ++- js/src/shell/js.cpp | 7 +- js/src/vm/ArgumentsObject.cpp | 4 +- js/src/vm/Debugger.cpp | 2 +- js/src/vm/ScopeObject.cpp | 10 +- 25 files changed, 249 insertions(+), 264 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 9e5767151f2a..061d1be0d95a 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3397,7 +3397,7 @@ JS_DeepFreezeObject(JSContext *cx, JSObject *obj_) static JSBool LookupPropertyById(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { AssertNoGC(cx); CHECK_REQUEST(cx); @@ -3411,17 +3411,15 @@ LookupPropertyById(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, static JSBool LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, jsid id, - JSProperty* prop, Value *vp) + HandleShape shape, Value *vp) { - if (!prop) { + if (!shape) { /* XXX bad API: no way to tell "not defined" from "void value" */ vp->setUndefined(); return JS_TRUE; } if (obj2->isNative()) { - Shape *shape = (Shape *) prop; - /* Peek at the native property's slot value, without doing a Get. */ if (shape->hasSlot()) { *vp = obj2->nativeGetSlot(shape->slot()); @@ -3452,7 +3450,7 @@ JS_LookupPropertyById(JSContext *cx, JSObject *obj_, jsid id_, jsval *vp) RootedId id(cx, id_); RootedObject obj(cx, obj_); RootedObject obj2(cx); - JSProperty* prop; + RootedShape prop(cx); return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) && LookupResult(cx, obj, obj2, id, prop, vp); @@ -3490,7 +3488,7 @@ JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj_, jsid id_, unsigned RootedObject obj(cx, obj_); RootedObject objp(cx, *objp_); RootedId id(cx, id_); - JSProperty* prop; + RootedShape prop(cx); AssertNoGC(cx); CHECK_REQUEST(cx); @@ -3521,7 +3519,7 @@ JS_HasPropertyById(JSContext *cx, JSObject *obj_, jsid id_, JSBool *foundp) RootedObject obj(cx, obj_); RootedId id(cx, id_); RootedObject obj2(cx); - JSProperty* prop; + RootedShape prop(cx); JSBool ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING, &obj2, &prop); *foundp = (prop != NULL); @@ -3566,7 +3564,7 @@ JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj_, jsid id_, JSBool *fo if (!obj->isNative()) { RootedObject obj2(cx); - JSProperty *prop; + RootedShape prop(cx); if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING, &obj2, &prop)) { @@ -3838,12 +3836,12 @@ GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned JSBool own, PropertyDescriptor *desc) { RootedObject obj2(cx); - JSProperty *prop; + RootedShape shape(cx); - if (!LookupPropertyById(cx, obj, id, flags, &obj2, &prop)) + if (!LookupPropertyById(cx, obj, id, flags, &obj2, &shape)) return JS_FALSE; - if (!prop || (own && obj != obj2)) { + if (!shape || (own && obj != obj2)) { desc->obj = NULL; desc->attrs = 0; desc->getter = NULL; @@ -3854,7 +3852,6 @@ GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned desc->obj = obj2; if (obj2->isNative()) { - Shape *shape = (Shape *) prop; desc->attrs = shape->attributes(); desc->getter = shape->getter(); desc->setter = shape->setter(); @@ -3963,15 +3960,14 @@ static JSBool SetPropertyAttributesById(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs, JSBool *foundp) { RootedObject obj2(cx); - JSProperty *prop; + RootedShape shape(cx); - if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop)) + if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &shape)) return false; - if (!prop || obj != obj2) { + if (!shape || obj != obj2) { *foundp = false; return true; } - Shape *shape = (Shape *) prop; JSBool ok = obj->isNative() ? obj->changePropertyAttributes(cx, shape, attrs) : obj->setGenericAttributes(cx, id, &attrs); diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 3a07b66ed85c..26871b1b96ac 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -347,7 +347,7 @@ DoGetElement(JSContext *cx, JSObject *obj_, double index, JSBool *hole, Value *v } RootedObject obj2(cx); - JSProperty *prop; + RootedShape prop(cx); if (!obj->lookupGeneric(cx, id, &obj2, &prop)) return JS_FALSE; if (!prop) { @@ -692,14 +692,14 @@ IsDenseArrayId(JSContext *cx, JSObject *obj, jsid id) } static JSBool -array_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, - JSProperty **propp) +array_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, + MutableHandleObject objp, MutableHandleShape propp) { if (!obj->isDenseArray()) return baseops::LookupProperty(cx, obj, id, objp, propp); if (IsDenseArrayId(cx, obj, id)) { - *propp = (JSProperty *) 1; /* non-null to indicate found */ + MarkNonNativePropertyFound(obj, propp); objp.set(obj); return JS_TRUE; } @@ -707,7 +707,7 @@ array_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleO JSObject *proto = obj->getProto(); if (!proto) { objp.set(NULL); - *propp = NULL; + propp.set(NULL); return JS_TRUE; } return proto->lookupGeneric(cx, id, objp, propp); @@ -715,21 +715,21 @@ array_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleO static JSBool array_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, NameToId(name)); return array_lookupGeneric(cx, obj, id, objp, propp); } static JSBool -array_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, - JSProperty **propp) +array_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, + MutableHandleObject objp, MutableHandleShape propp) { if (!obj->isDenseArray()) return baseops::LookupElement(cx, obj, index, objp, propp); if (IsDenseArrayIndex(obj, index)) { - *propp = (JSProperty *) 1; /* non-null to indicate found */ + MarkNonNativePropertyFound(obj, propp); objp.set(obj); return true; } @@ -738,13 +738,13 @@ array_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHand return proto->lookupElement(cx, index, objp, propp); objp.set(NULL); - *propp = NULL; + propp.set(NULL); return true; } static JSBool -array_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, MutableHandleObject objp, - JSProperty **propp) +array_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return array_lookupGeneric(cx, obj, id, objp, propp); diff --git a/js/src/jsclass.h b/js/src/jsclass.h index b870aa5eeb9e..e5bcacc05e29 100644 --- a/js/src/jsclass.h +++ b/js/src/jsclass.h @@ -149,17 +149,17 @@ typedef JS::Handle HandleSpecialId; /* js::Class operation signatures. */ typedef JSBool -(* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, - JSProperty **propp); +(* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id, + MutableHandleObject objp, MutableHandleShape propp); typedef JSBool -(* LookupPropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleObject objp, - JSProperty **propp); +(* LookupPropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, + MutableHandleObject objp, MutableHandleShape propp); typedef JSBool -(* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, - JSProperty **propp); +(* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index, + MutableHandleObject objp, MutableHandleShape propp); typedef JSBool -(* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, MutableHandleObject objp, - JSProperty **propp); +(* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, + MutableHandleObject objp, MutableHandleShape propp); typedef JSBool (* DefineGenericOp)(JSContext *cx, HandleObject obj, HandleId id, const Value *value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs); diff --git a/js/src/jsclone.cpp b/js/src/jsclone.cpp index 06be21b5205d..2a6520390a1f 100644 --- a/js/src/jsclone.cpp +++ b/js/src/jsclone.cpp @@ -559,7 +559,7 @@ JSStructuredCloneWriter::write(const Value &v) * NativeIterators. */ RootedObject obj2(context()); - JSProperty *prop; + RootedShape prop(context()); if (!js_HasOwnProperty(context(), obj->getOps()->lookupGeneric, obj, id, &obj2, &prop)) { return false; diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index f9821067280b..3acf4eb23fbf 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -954,7 +954,7 @@ js::AssertValidPropertyCacheHit(JSContext *cx, JSObject *start_, RootedObject obj(cx); RootedObject pobj(cx); - JSProperty *prop; + RootedShape prop(cx); JSBool ok; if (JOF_OPMODE(*pc) == JOF_NAME) @@ -967,9 +967,7 @@ js::AssertValidPropertyCacheHit(JSContext *cx, JSObject *start_, JS_PROPERTY_CACHE(cx).restore(&savedEntry); JS_ASSERT(prop); JS_ASSERT(pobj == found); - - Shape *shape = (Shape *) prop; - JS_ASSERT(entry->prop == shape); + JS_ASSERT(entry->prop == prop); } #endif /* DEBUG && !JS_THREADSAFE */ @@ -1281,6 +1279,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) RootedTypeObject rootType0(cx); RootedPropertyName rootName0(cx); RootedId rootId0(cx); + RootedShape rootShape0(cx); if (rt->profilingScripts) ENABLE_INTERRUPTS(); @@ -1746,7 +1745,7 @@ BEGIN_CASE(JSOP_IN) RootedId &id = rootId0; FETCH_ELEMENT_ID(obj, -2, id); RootedObject &obj2 = rootObject1; - JSProperty *prop; + RootedShape &prop = rootShape0; if (!obj->lookupGeneric(cx, id, &obj2, &prop)) goto error; bool cond = prop != NULL; @@ -2206,7 +2205,7 @@ BEGIN_CASE(JSOP_DELNAME) RootedObject &obj = rootObject1; RootedObject &obj2 = rootObject2; - JSProperty *prop; + RootedShape &prop = rootShape0; if (!FindProperty(cx, name, scopeObj, &obj, &obj2, &prop)) goto error; @@ -2553,7 +2552,7 @@ BEGIN_CASE(JSOP_IMPLICITTHIS) RootedObject &obj = rootObject1; RootedObject &obj2 = rootObject2; - JSProperty *prop; + RootedShape &prop = rootShape0; if (!FindPropertyHelper(cx, name, false, scopeObj, &obj, &obj2, &prop)) goto error; @@ -2920,9 +2919,9 @@ BEGIN_CASE(JSOP_DEFFUN) /* ES5 10.5 (NB: with subsequent errata). */ RootedPropertyName &name = rootName0; name = fun->atom->asPropertyName(); - JSProperty *prop = NULL; + RootedShape &shape = rootShape0; RootedObject &pobj = rootObject1; - if (!parent->lookupProperty(cx, name, &pobj, &prop)) + if (!parent->lookupProperty(cx, name, &pobj, &shape)) goto error; RootedValue &rval = rootValue0; @@ -2930,7 +2929,7 @@ BEGIN_CASE(JSOP_DEFFUN) do { /* Steps 5d, 5f. */ - if (!prop || pobj != parent) { + if (!shape || pobj != parent) { if (!parent->defineProperty(cx, name, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs)) { @@ -2941,7 +2940,6 @@ BEGIN_CASE(JSOP_DEFFUN) /* Step 5e. */ JS_ASSERT(parent->isNative()); - Shape *shape = reinterpret_cast(prop); if (parent->isGlobal()) { if (shape->configurable()) { if (!parent->defineProperty(cx, name, rval, diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index e39da14f7be5..87618ac3bd80 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -385,10 +385,10 @@ NameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value *vp) return true; } - JSProperty *prop; - if (!FindPropertyHelper(cx, name, true, obj, &obj, &obj2, &prop)) + RootedShape shape(cx); + if (!FindPropertyHelper(cx, name, true, obj, &obj, &obj2, &shape)) return false; - if (!prop) { + if (!shape) { /* Kludge to allow (typeof foo == "undefined") tests. */ JSOp op2 = JSOp(pc[JSOP_NAME_LENGTH]); if (op2 == JSOP_TYPEOF) { @@ -401,13 +401,12 @@ NameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value *vp) return false; } - /* Take the slow path if prop was not found in a native object. */ + /* Take the slow path if shape was not found in a native object. */ if (!obj->isNative() || !obj2->isNative()) { Rooted id(cx, NameToId(name)); if (!obj->getGeneric(cx, id, vp)) return false; } else { - Shape *shape = (Shape *)prop; Rooted normalized(cx, obj); if (normalized->getClass() == &WithClass && !shape->hasDefaultGetter()) normalized = &normalized->asWith().object(); @@ -424,7 +423,7 @@ DefVarOrConstOperation(JSContext *cx, HandleObject varobj, PropertyName *dn, uns JS_ASSERT(varobj->isVarObj()); JS_ASSERT(!varobj->getOps()->defineProperty || varobj->isDebugScope()); - JSProperty *prop; + RootedShape prop(cx); RootedObject obj2(cx); if (!varobj->lookupProperty(cx, dn, &obj2, &prop)) return false; diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index b03fb3da8071..c29e8b477174 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -993,7 +993,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p if (obj->getProto()) { JSObject *proto = obj->getProto(); RootedObject obj2(cx); - JSProperty *prop; + RootedShape prop(cx); RootedId id(cx); if (!ValueToId(cx, StringValue(*idp), id.address())) return false; @@ -1002,7 +1002,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p if (prop) { unsigned attrs; if (obj2->isNative()) - attrs = ((Shape *) prop)->attributes(); + attrs = prop->attributes(); else if (!obj2->getGenericAttributes(cx, id, &attrs)) return false; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 51396a510ebc..9f22668c86d0 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -179,7 +179,7 @@ MarkSharpObjects(JSContext *cx, HandleObject obj, JSIdArray **idap, JSSharpInfo for (int i = 0, length = ida->length; i < length; i++) { id = ida->vector[i]; RootedObject obj2(cx); - JSProperty *prop; + RootedShape prop(cx); ok = obj->lookupGeneric(cx, id, &obj2, &prop); if (!ok) break; @@ -460,7 +460,7 @@ obj_toSource(JSContext *cx, unsigned argc, Value *vp) JSLinearString *idstr; RootedObject obj2(cx); - JSProperty *prop; + RootedShape prop(cx); if (!obj->lookupGeneric(cx, id, &obj2, &prop)) return false; @@ -807,7 +807,7 @@ js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, unsigned argc, if (!obj) return false; RootedObject obj2(cx); - JSProperty *prop; + RootedShape prop(cx); if (obj->isProxy()) { bool has; if (!Proxy::hasOwn(cx, obj, id, &has)) @@ -823,7 +823,7 @@ js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, unsigned argc, JSBool js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, HandleId id, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING); if (lookup) { @@ -833,7 +833,7 @@ js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, Handl if (!baseops::LookupProperty(cx, obj, id, objp, propp)) return false; } - if (!*propp) + if (!propp) return true; if (objp == obj) @@ -848,7 +848,7 @@ js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, Handl } if (outer != objp) - *propp = NULL; + propp.set(NULL); return true; } @@ -894,7 +894,7 @@ JSBool js_PropertyIsEnumerable(JSContext *cx, HandleObject obj, HandleId id, Value *vp) { RootedObject pobj(cx); - JSProperty *prop; + RootedShape prop(cx); if (!obj->lookupGeneric(cx, id, &pobj, &prop)) return false; @@ -1004,13 +1004,12 @@ obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp) return JS_TRUE; } RootedObject pobj(cx); - JSProperty *prop; - if (!obj->lookupGeneric(cx, id, &pobj, &prop)) + RootedShape shape(cx); + if (!obj->lookupGeneric(cx, id, &pobj, &shape)) return JS_FALSE; vp->setUndefined(); - if (prop) { + if (shape) { if (pobj->isNative()) { - Shape *shape = (Shape *) prop; if (shape->hasGetterValue()) *vp = shape->getterValue(); } @@ -1039,13 +1038,12 @@ obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp) return JS_TRUE; } RootedObject pobj(cx); - JSProperty *prop; - if (!obj->lookupGeneric(cx, id, &pobj, &prop)) + RootedShape shape(cx); + if (!obj->lookupGeneric(cx, id, &pobj, &shape)) return JS_FALSE; vp->setUndefined(); - if (prop) { + if (shape) { if (pobj->isNative()) { - Shape *shape = (Shape *) prop; if (shape->hasSetterValue()) *vp = shape->setterValue(); } @@ -1171,17 +1169,16 @@ GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, PropertyD return Proxy::getOwnPropertyDescriptor(cx, obj, id, false, desc); RootedObject pobj(cx); - JSProperty *prop; - if (!js_HasOwnProperty(cx, obj->getOps()->lookupGeneric, obj, id, &pobj, &prop)) + RootedShape shape(cx); + if (!js_HasOwnProperty(cx, obj->getOps()->lookupGeneric, obj, id, &pobj, &shape)) return false; - if (!prop) { + if (!shape) { desc->obj = NULL; return true; } bool doGet = true; if (pobj->isNative()) { - Shape *shape = (Shape *) prop; desc->attrs = shape->attributes(); if (desc->attrs & (JSPROP_GETTER | JSPROP_SETTER)) { doGet = false; @@ -1509,16 +1506,16 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD bool throwError, bool *rval) { /* 8.12.9 step 1. */ - JSProperty *current; + RootedShape shape(cx); RootedObject obj2(cx); JS_ASSERT(!obj->getOps()->lookupGeneric); - if (!js_HasOwnProperty(cx, NULL, obj, id, &obj2, ¤t)) + if (!js_HasOwnProperty(cx, NULL, obj, id, &obj2, &shape)) return JS_FALSE; JS_ASSERT(!obj->getOps()->defineProperty); /* 8.12.9 steps 2-4. */ - if (!current) { + if (!shape) { if (!obj->isExtensible()) return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval); @@ -1553,7 +1550,6 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD JS_ASSERT(obj == obj2); - Rooted shape(cx, reinterpret_cast(current)); do { if (desc.isAccessorDescriptor()) { if (!shape->isAccessorDescriptor()) @@ -3857,9 +3853,6 @@ js_FindClassObject(JSContext *cx, HandleObject start, JSProtoKey protoKey, MutableHandleValue vp, Class *clasp) { RootedId id(cx); - JSProperty *prop; - Shape *shape; - RootedObject obj(cx); if (start) { @@ -3891,11 +3884,11 @@ js_FindClassObject(JSContext *cx, HandleObject start, JSProtoKey protoKey, JS_ASSERT(obj->isNative()); RootedObject pobj(cx); - if (!LookupPropertyWithFlags(cx, obj, id, 0, &pobj, &prop)) + RootedShape shape(cx); + if (!LookupPropertyWithFlags(cx, obj, id, 0, &pobj, &shape)) return false; RootedValue v(cx, UndefinedValue()); - if (prop && pobj->isNative()) { - shape = (Shape *) prop; + if (shape && pobj->isNative()) { if (shape->hasSlot()) { v = pobj->nativeGetSlot(shape->slot()); if (v.get().isPrimitive()) @@ -4115,8 +4108,6 @@ DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value & */ RootedShape shape(cx); if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) { - JSProperty *prop; - /* Type information for getter/setter properties is unknown. */ AddTypePropertyId(cx, obj, id, types::Type::UnknownType()); MarkTypePropertyConfigured(cx, obj, id); @@ -4127,10 +4118,10 @@ DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value & * property cache line for (obj, id) to map shape. */ RootedObject pobj(cx); - if (!baseops::LookupProperty(cx, obj, id, &pobj, &prop)) + RootedShape shape(cx); + if (!baseops::LookupProperty(cx, obj, id, &pobj, &shape)) return NULL; - if (prop && pobj == obj) { - shape = (Shape *) prop; + if (shape && pobj == obj) { if (shape->isAccessorDescriptor()) { shape = obj->changeProperty(cx, shape, attrs, JSPROP_GETTER | JSPROP_SETTER, @@ -4218,7 +4209,7 @@ DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value & */ static JSBool CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, - MutableHandleObject objp, JSProperty **propp, bool *recursedp) + MutableHandleObject objp, MutableHandleShape propp, bool *recursedp) { Class *clasp = obj->getClass(); JSResolveOp resolve = clasp->resolve; @@ -4239,7 +4230,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, } *recursedp = false; - *propp = NULL; + propp.set(NULL); if (clasp->flags & JSCLASS_NEW_RESOLVE) { JSNewResolveOp newresolve = reinterpret_cast(resolve); @@ -4273,7 +4264,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, if (!obj->nativeEmpty()) { if (Shape *shape = obj->nativeLookup(cx, id)) { objp.set(obj); - *propp = (JSProperty *) shape; + propp.set(shape); } } @@ -4282,7 +4273,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, static JS_ALWAYS_INLINE bool LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { /* Search scopes starting with obj and following the prototype link. */ RootedObject current(cx, obj); @@ -4290,7 +4281,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi Shape *shape = current->nativeLookup(cx, id); if (shape) { objp.set(current); - *propp = (JSProperty *) shape; + propp.set(shape); return true; } @@ -4301,7 +4292,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi return false; if (recursed) break; - if (*propp) { + if (propp) { /* * For stats we do not recalculate protoIndex even if it was * resolved on some other object. @@ -4326,7 +4317,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi * arguments.callee through the delegating |this| object's method * read barrier. */ - if (*propp && objp->isNative()) { + if (propp && objp->isNative()) { while ((proto = proto->getProto()) != objp) JS_ASSERT(proto); } @@ -4338,20 +4329,20 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi } objp.set(NULL); - *propp = NULL; + propp.set(NULL); return true; } JS_FRIEND_API(JSBool) baseops::LookupProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, - JSProperty **propp) + MutableHandleShape propp) { return LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, objp, propp); } JS_FRIEND_API(JSBool) baseops::LookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { RootedId id(cx); if (!IndexToId(cx, index, id.address())) @@ -4362,7 +4353,7 @@ baseops::LookupElement(JSContext *cx, HandleObject obj, uint32_t index, bool js::LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { return LookupPropertyWithFlagsInline(cx, obj, id, flags, objp, propp); } @@ -4370,13 +4361,14 @@ js::LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsign bool js::FindPropertyHelper(JSContext *cx, HandlePropertyName name, bool cacheResult, HandleObject scopeChain, - MutableHandleObject objp, MutableHandleObject pobjp, JSProperty **propp) + MutableHandleObject objp, MutableHandleObject pobjp, + MutableHandleShape propp) { RootedId id(cx, NameToId(name)); RootedObject pobj(cx); int scopeIndex; - JSProperty *prop; + RootedShape prop(cx); /* Scan entries on the scope chain that we can cache across. */ RootedObject obj(cx, scopeChain); @@ -4416,8 +4408,7 @@ js::FindPropertyHelper(JSContext *cx, * non-native prototype. */ if (cacheResult && pobj->isNative()) { - JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, - (Shape *) prop); + JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, prop); } goto out; @@ -4453,7 +4444,7 @@ js::FindPropertyHelper(JSContext *cx, JS_ASSERT(!!pobj == !!prop); objp.set(obj); pobjp.set(pobj); - *propp = prop; + propp.set(prop); return true; } @@ -4463,7 +4454,7 @@ js::FindPropertyHelper(JSContext *cx, */ bool js::FindProperty(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, - MutableHandleObject objp, MutableHandleObject pobjp, JSProperty **propp) + MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp) { return !!FindPropertyHelper(cx, name, false, scopeChain, objp, pobjp, propp); } @@ -4493,16 +4484,16 @@ js::FindIdentifierBase(JSContext *cx, HandleObject scopeChain, HandlePropertyNam scopeIndex++) { RootedObject pobj(cx); - JSProperty *prop; - if (!LookupPropertyWithFlags(cx, obj, name, cx->resolveFlags, &pobj, &prop)) + RootedShape shape(cx); + if (!LookupPropertyWithFlags(cx, obj, name, cx->resolveFlags, &pobj, &shape)) return NULL; - if (prop) { + if (shape) { if (!pobj->isNative()) { JS_ASSERT(obj->isGlobal()); return obj; } JS_ASSERT_IF(obj->isScope(), pobj->getClass() == obj->getClass()); - JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, (Shape *) prop); + JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, shape); return obj; } @@ -4515,10 +4506,10 @@ js::FindIdentifierBase(JSContext *cx, HandleObject scopeChain, HandlePropertyNam /* Loop until we find a property or reach the global object. */ do { RootedObject pobj(cx); - JSProperty *prop; - if (!obj->lookupProperty(cx, name, &pobj, &prop)) + RootedShape shape(cx); + if (!obj->lookupProperty(cx, name, &pobj, &shape)) return NULL; - if (prop) + if (shape) break; /* @@ -4629,16 +4620,15 @@ static JS_ALWAYS_INLINE JSBool js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receiver, jsid id_, uint32_t getHow, Value *vp) { - JSProperty *prop; - RootedId id(cx, id_); /* This call site is hot -- use the always-inlined variant of LookupPropertyWithFlags(). */ RootedObject obj2(cx); - if (!LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, &obj2, &prop)) + RootedShape shape(cx); + if (!LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, &obj2, &shape)) return false; - if (!prop) { + if (!shape) { vp->setUndefined(); if (!CallJSPropertyOp(cx, obj->getClass()->getProperty, obj, id, vp)) @@ -4706,8 +4696,6 @@ js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receive : obj2->getGeneric(cx, id, vp); } - Shape *shape = (Shape *) prop; - if (getHow & JSGET_CACHE_RESULT) JS_PROPERTY_CACHE(cx).fill(cx, obj, 0, obj2, shape); @@ -4745,7 +4733,7 @@ baseops::GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint JSBool baseops::GetPropertyDefault(JSContext *cx, HandleObject obj, HandleId id, const Value &def, Value *vp) { - JSProperty *prop; + RootedShape prop(cx); RootedObject obj2(cx); if (!LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop)) return false; @@ -4836,7 +4824,6 @@ JSBool baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, unsigned defineHow, Value *vp, JSBool strict) { - JSProperty *prop; unsigned attrs, flags; int shortid; Class *clasp; @@ -4854,9 +4841,10 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive } RootedObject pobj(cx); - if (!LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, &pobj, &prop)) + RootedShape shape(cx); + if (!LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, &pobj, &shape)) return false; - if (prop) { + if (shape) { if (!pobj->isNative()) { if (pobj->isProxy()) { AutoPropertyDescriptorRooter pd(cx); @@ -4878,7 +4866,7 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive } } - prop = NULL; + shape = NULL; } } else { /* We should never add properties to lexical blocks. */ @@ -4891,8 +4879,6 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive } } - RootedShape shape(cx, (Shape *) prop); - /* * Now either shape is null, meaning id was not found in obj or one of its * prototypes; or shape is non-null, meaning id was found directly in pobj. @@ -5032,17 +5018,16 @@ JSBool baseops::GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp) { RootedObject nobj(cx); - JSProperty *prop; - if (!baseops::LookupProperty(cx, obj, id, &nobj, &prop)) + RootedShape shape(cx); + if (!baseops::LookupProperty(cx, obj, id, &nobj, &shape)) return false; - if (!prop) { + if (!shape) { *attrsp = 0; return true; } if (!nobj->isNative()) return nobj->getGenericAttributes(cx, id, attrsp); - Shape *shape = (Shape *)prop; *attrsp = shape->attributes(); return true; } @@ -5051,17 +5036,16 @@ JSBool baseops::GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp) { RootedObject nobj(cx); - JSProperty *prop; - if (!baseops::LookupElement(cx, obj, index, &nobj, &prop)) + RootedShape shape(cx); + if (!baseops::LookupElement(cx, obj, index, &nobj, &shape)) return false; - if (!prop) { + if (!shape) { *attrsp = 0; return true; } if (!nobj->isNative()) return nobj->getElementAttributes(cx, index, attrsp); - Shape *shape = (Shape *)prop; *attrsp = shape->attributes(); return true; } @@ -5070,13 +5054,13 @@ JSBool baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp) { RootedObject nobj(cx); - JSProperty *prop; - if (!baseops::LookupProperty(cx, obj, id, &nobj, &prop)) + RootedShape shape(cx); + if (!baseops::LookupProperty(cx, obj, id, &nobj, &shape)) return false; - if (!prop) + if (!shape) return true; return nobj->isNative() - ? nobj->changePropertyAttributes(cx, (Shape *) prop, *attrsp) + ? nobj->changePropertyAttributes(cx, shape, *attrsp) : nobj->setGenericAttributes(cx, id, attrsp); } @@ -5084,28 +5068,26 @@ JSBool baseops::SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp) { RootedObject nobj(cx); - JSProperty *prop; - if (!baseops::LookupElement(cx, obj, index, &nobj, &prop)) + RootedShape shape(cx); + if (!baseops::LookupElement(cx, obj, index, &nobj, &shape)) return false; - if (!prop) + if (!shape) return true; return nobj->isNative() - ? nobj->changePropertyAttributes(cx, (Shape *) prop, *attrsp) + ? nobj->changePropertyAttributes(cx, shape, *attrsp) : nobj->setElementAttributes(cx, index, attrsp); } JSBool baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *rval, JSBool strict) { - JSProperty *prop; - Shape *shape; - rval->setBoolean(true); RootedObject proto(cx); - if (!baseops::LookupProperty(cx, obj, id, &proto, &prop)) + RootedShape shape(cx); + if (!baseops::LookupProperty(cx, obj, id, &proto, &shape)) return false; - if (!prop || proto != obj) { + if (!shape || proto != obj) { /* * If no property, or the property comes from a prototype, call the * class's delProperty hook, passing rval as the result parameter. @@ -5113,7 +5095,6 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *rval return CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, id, rval); } - shape = (Shape *)prop; if (!shape->configurable()) { if (strict) return obj->reportNotConfigurable(cx, id); @@ -5305,9 +5286,6 @@ CheckAccess(JSContext *cx, JSObject *obj_, HandleId id, JSAccessMode mode, Value *vp, unsigned *attrsp) { JSBool writing; - JSProperty *prop; - Shape *shape; - RootedObject obj(cx, obj_), pobj(cx); while (JS_UNLIKELY(obj->isWith())) @@ -5323,9 +5301,10 @@ CheckAccess(JSContext *cx, JSObject *obj_, HandleId id, JSAccessMode mode, break; default: - if (!obj->lookupGeneric(cx, id, &pobj, &prop)) + RootedShape shape(cx); + if (!obj->lookupGeneric(cx, id, &pobj, &shape)) return JS_FALSE; - if (!prop) { + if (!shape) { if (!writing) vp->setUndefined(); *attrsp = 0; @@ -5341,7 +5320,6 @@ CheckAccess(JSContext *cx, JSObject *obj_, HandleId id, JSAccessMode mode, break; } - shape = (Shape *)prop; *attrsp = shape->attributes(); if (!writing) { if (shape->hasSlot()) diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 4f4374283853..8f707e4cf881 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -99,11 +99,11 @@ namespace baseops { */ extern JS_FRIEND_API(JSBool) LookupProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, - JSProperty **propp); + MutableHandleShape propp); inline bool LookupProperty(JSContext *cx, HandleObject obj, PropertyName *name, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, NameToId(name)); return LookupProperty(cx, obj, id, objp, propp); @@ -111,7 +111,7 @@ LookupProperty(JSContext *cx, HandleObject obj, PropertyName *name, extern JS_FRIEND_API(JSBool) LookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, JSProperty **propp); + MutableHandleObject objp, MutableHandleShape propp); extern JSBool DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, const js::Value *value, @@ -785,12 +785,14 @@ struct JSObject : public js::ObjectImpl /* Clear the scope, making it empty. */ void clear(JSContext *cx); - inline JSBool lookupGeneric(JSContext *cx, js::HandleId id, js::MutableHandleObject objp, JSProperty **propp); - inline JSBool lookupProperty(JSContext *cx, js::PropertyName *name, js::MutableHandleObject objp, JSProperty **propp); + inline JSBool lookupGeneric(JSContext *cx, js::HandleId id, + js::MutableHandleObject objp, js::MutableHandleShape propp); + inline JSBool lookupProperty(JSContext *cx, js::PropertyName *name, + js::MutableHandleObject objp, js::MutableHandleShape propp); inline JSBool lookupElement(JSContext *cx, uint32_t index, - js::MutableHandleObject objp, JSProperty **propp); + js::MutableHandleObject objp, js::MutableHandleShape propp); inline JSBool lookupSpecial(JSContext *cx, js::SpecialId sid, - js::MutableHandleObject objp, JSProperty **propp); + js::MutableHandleObject objp, js::MutableHandleShape propp); inline JSBool defineGeneric(JSContext *cx, js::HandleId id, const js::Value &value, JSPropertyOp getter = JS_PropertyStub, @@ -1046,7 +1048,7 @@ js_HasOwnPropertyHelper(JSContext *cx, js::LookupGenericOp lookup, unsigned argc extern JSBool js_HasOwnProperty(JSContext *cx, js::LookupGenericOp lookup, js::HandleObject obj, js::HandleId id, - js::MutableHandleObject objp, JSProperty **propp); + js::MutableHandleObject objp, js::MutableHandleShape propp); extern JSBool js_PropertyIsEnumerable(JSContext *cx, js::HandleObject obj, js::HandleId id, js::Value *vp); @@ -1165,11 +1167,11 @@ DefineNativeProperty(JSContext *cx, HandleObject obj, PropertyName *name, const */ extern bool LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, - js::MutableHandleObject objp, JSProperty **propp); + js::MutableHandleObject objp, js::MutableHandleShape propp); inline bool LookupPropertyWithFlags(JSContext *cx, HandleObject obj, PropertyName *name, unsigned flags, - js::MutableHandleObject objp, JSProperty **propp) + js::MutableHandleObject objp, js::MutableHandleShape propp) { Rooted id(cx, NameToId(name)); return LookupPropertyWithFlags(cx, obj, id, flags, objp, propp); @@ -1208,7 +1210,7 @@ static const unsigned RESOLVE_INFER = 0xffff; extern bool FindPropertyHelper(JSContext *cx, HandlePropertyName name, bool cacheResult, HandleObject scopeChain, - MutableHandleObject objp, MutableHandleObject pobjp, JSProperty **propp); + MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp); /* * Search for name either on the current scope chain or on the scope chain's @@ -1216,7 +1218,7 @@ FindPropertyHelper(JSContext *cx, HandlePropertyName name, */ extern bool FindProperty(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, - MutableHandleObject objp, MutableHandleObject pobjp, JSProperty **propp); + MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp); extern JSObject * FindIdentifierBase(JSContext *cx, HandleObject scopeChain, HandlePropertyName name); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 4d4fea02c404..94bf32aac9fb 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -927,7 +927,7 @@ inline bool JSObject::hasProperty(JSContext *cx, js::HandleId id, bool *foundp, unsigned flags) { js::RootedObject pobj(cx); - JSProperty *prop; + js::RootedShape prop(cx); JSAutoResolveFlags rf(cx, flags); if (!lookupGeneric(cx, id, &pobj, &prop)) return false; @@ -1034,7 +1034,8 @@ JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, } inline JSBool -JSObject::lookupGeneric(JSContext *cx, js::HandleId id, js::MutableHandleObject objp, JSProperty **propp) +JSObject::lookupGeneric(JSContext *cx, js::HandleId id, + js::MutableHandleObject objp, js::MutableHandleShape propp) { js::RootedObject self(cx, this); @@ -1045,7 +1046,8 @@ JSObject::lookupGeneric(JSContext *cx, js::HandleId id, js::MutableHandleObject } inline JSBool -JSObject::lookupProperty(JSContext *cx, js::PropertyName *name, js::MutableHandleObject objp, JSProperty **propp) +JSObject::lookupProperty(JSContext *cx, js::PropertyName *name, + js::MutableHandleObject objp, js::MutableHandleShape propp) { js::Rooted id(cx, js::NameToId(name)); return lookupGeneric(cx, id, objp, propp); @@ -1097,7 +1099,8 @@ JSObject::defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value } inline JSBool -JSObject::lookupElement(JSContext *cx, uint32_t index, js::MutableHandleObject objp, JSProperty **propp) +JSObject::lookupElement(JSContext *cx, uint32_t index, + js::MutableHandleObject objp, js::MutableHandleShape propp) { js::RootedObject self(cx, this); @@ -1106,7 +1109,8 @@ JSObject::lookupElement(JSContext *cx, uint32_t index, js::MutableHandleObject o } inline JSBool -JSObject::lookupSpecial(JSContext *cx, js::SpecialId sid, js::MutableHandleObject objp, JSProperty **propp) +JSObject::lookupSpecial(JSContext *cx, js::SpecialId sid, + js::MutableHandleObject objp, js::MutableHandleShape propp) { js::Rooted id(cx, SPECIALID_TO_JSID(sid)); return lookupGeneric(cx, id, objp, propp); @@ -1154,7 +1158,7 @@ JSObject::getElementIfPresent(JSContext *cx, js::HandleObject receiver, uint32_t return false; js::RootedObject obj2(cx); - JSProperty *prop; + js::RootedShape prop(cx); if (!self->lookupGeneric(cx, id, &obj2, &prop)) return false; diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 0f3daa9c39ff..1082da0a6989 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -1221,34 +1221,34 @@ proxy_innerObject(JSContext *cx, HandleObject obj) } static JSBool -proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, - JSProperty **propp) +proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id, + MutableHandleObject objp, MutableHandleShape propp) { bool found; if (!Proxy::has(cx, obj, id, &found)) return false; if (found) { - *propp = (JSProperty *)0x1; + MarkNonNativePropertyFound(obj, propp); objp.set(obj); } else { objp.set(NULL); - *propp = NULL; + propp.set(NULL); } return true; } static JSBool proxy_LookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, NameToId(name)); return proxy_LookupGeneric(cx, obj, id, objp, propp); } static JSBool -proxy_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, - JSProperty **propp) +proxy_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, + MutableHandleObject objp, MutableHandleShape propp) { RootedId id(cx); if (!IndexToId(cx, index, id.address())) @@ -1258,7 +1258,7 @@ proxy_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHand static JSBool proxy_LookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return proxy_LookupGeneric(cx, obj, id, objp, propp); diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index 8988e0b51f54..b6b1cb168a37 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -51,7 +51,6 @@ typedef struct JSArgumentFormatMap JSArgumentFormatMap; typedef struct JSGCThing JSGCThing; typedef struct JSGenerator JSGenerator; typedef struct JSNativeEnumerator JSNativeEnumerator; -typedef struct JSProperty JSProperty; typedef struct JSSharpObjectMap JSSharpObjectMap; typedef struct JSTryNote JSTryNote; @@ -225,6 +224,8 @@ typedef JS::Handle HandleTypeObject; typedef JS::Handle HandleAtom; typedef JS::Handle HandlePropertyName; +typedef JS::MutableHandle MutableHandleShape; + typedef JS::Rooted RootedShape; typedef JS::Rooted RootedBaseShape; typedef JS::Rooted RootedTypeObject; diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index d6aad4a9ecbc..325c3fda387c 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -1393,3 +1393,16 @@ JSCompartment::sweepInitialShapeTable() } } } + +/* + * Property lookup hooks on non-native objects are required to return a non-NULL + * shape to signify that the property has been found. The actual shape returned + * is arbitrary, and it should never be read from. We use the non-native + * object's shape_ field, since it is readily available. + */ +void +js::MarkNonNativePropertyFound(HandleObject obj, MutableHandleShape propp) +{ + propp.set(obj->lastProperty()); +} + diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 0b87f621819f..b13101db1b63 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -1162,6 +1162,9 @@ Shape::searchNoAllocation(JSContext *cx, Shape *start, jsid id) } #endif /* DEBUG */ +void +MarkNonNativePropertyFound(HandleObject obj, MutableHandleShape propp); + } // namespace js #ifdef _MSC_VER diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 55c9446fc9f4..b959b95c4031 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -295,14 +295,12 @@ ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) } } -static JSProperty * const PROPERTY_FOUND = reinterpret_cast(1); - JSBool ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) { - *propp = PROPERTY_FOUND; + MarkNonNativePropertyFound(obj, propp); objp.set(getArrayBuffer(obj)); return true; } @@ -321,7 +319,7 @@ ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId i if (!delegateResult) return false; - if (*propp != NULL) { + if (propp) { if (objp == delegate) objp.set(obj); return true; @@ -330,7 +328,7 @@ ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId i JSObject *proto = obj->getProto(); if (!proto) { objp.set(NULL); - *propp = NULL; + propp.set(NULL); return true; } @@ -339,7 +337,7 @@ ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId i JSBool ArrayBufferObject::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, NameToId(name)); return obj_lookupGeneric(cx, obj, id, objp, propp); @@ -347,7 +345,7 @@ ArrayBufferObject::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePro JSBool ArrayBufferObject::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { RootedObject delegate(cx, ArrayBufferDelegate(cx, obj)); if (!delegate) @@ -362,7 +360,7 @@ ArrayBufferObject::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t i if (!delegate->lookupElement(cx, index, objp, propp)) return false; - if (*propp != NULL) { + if (propp) { if (objp == delegate) objp.set(obj); return true; @@ -372,13 +370,13 @@ ArrayBufferObject::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t i return proto->lookupElement(cx, index, objp, propp); objp.set(NULL); - *propp = NULL; + propp.set(NULL); return true; } JSBool ArrayBufferObject::obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return obj_lookupGeneric(cx, obj, id, objp, propp); @@ -774,13 +772,13 @@ js::IsDataView(JSObject* obj) JSBool TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { JSObject *tarray = getTypedArray(obj); JS_ASSERT(tarray); if (isArrayIndex(cx, tarray, id)) { - *propp = PROPERTY_FOUND; + MarkNonNativePropertyFound(obj, propp); objp.set(obj); return true; } @@ -788,7 +786,7 @@ TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, JSObject *proto = obj->getProto(); if (!proto) { objp.set(NULL); - *propp = NULL; + propp.set(NULL); return true; } @@ -797,7 +795,7 @@ TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, JSBool TypedArray::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, NameToId(name)); return obj_lookupGeneric(cx, obj, id, objp, propp); @@ -805,13 +803,13 @@ TypedArray::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyNa JSBool TypedArray::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { JSObject *tarray = getTypedArray(obj); JS_ASSERT(tarray); if (index < length(tarray)) { - *propp = PROPERTY_FOUND; + MarkNonNativePropertyFound(obj, propp); objp.set(obj); return true; } @@ -820,13 +818,13 @@ TypedArray::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, return proto->lookupElement(cx, index, objp, propp); objp.set(NULL); - *propp = NULL; + propp.set(NULL); return true; } JSBool TypedArray::obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return obj_lookupGeneric(cx, obj, id, objp, propp); diff --git a/js/src/jstypedarray.h b/js/src/jstypedarray.h index 788f3d631ca9..325607227e78 100644 --- a/js/src/jstypedarray.h +++ b/js/src/jstypedarray.h @@ -47,16 +47,16 @@ class ArrayBufferObject : public JSObject static JSBool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, JSProperty **propp); + MutableHandleObject objp, MutableHandleShape propp); static JSBool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, JSProperty **propp); + MutableHandleObject objp, MutableHandleShape propp); static JSBool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, JSProperty **propp); + MutableHandleObject objp, MutableHandleShape propp); static JSBool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, JSProperty **propp); + MutableHandleObject objp, MutableHandleShape propp); static JSBool obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, const Value *v, @@ -189,13 +189,13 @@ struct TypedArray { static Class protoClasses[TYPE_MAX]; static JSBool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, JSProperty **propp); + MutableHandleObject objp, MutableHandleShape propp); static JSBool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, JSProperty **propp); + MutableHandleObject objp, MutableHandleShape propp); static JSBool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, JSProperty **propp); + MutableHandleObject objp, MutableHandleShape propp); static JSBool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, JSProperty **propp); + MutableHandleObject objp, MutableHandleShape propp); static JSBool obj_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp); static JSBool obj_getPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp); diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 89c050d0fdb7..9a968c28bfb8 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -4632,7 +4632,6 @@ HasSimpleContent(JSXML *xml); static JSBool HasFunctionProperty(JSContext *cx, JSObject *obj_, jsid funid_, JSBool *found) { - JSProperty *prop; JSXML *xml; JS_ASSERT(obj_->getClass() == &XMLClass); @@ -4641,6 +4640,7 @@ HasFunctionProperty(JSContext *cx, JSObject *obj_, jsid funid_, JSBool *found) Rooted obj(cx, obj_); RootedObject pobj(cx); + RootedShape prop(cx); if (!baseops::LookupProperty(cx, obj, funid, &pobj, &prop)) return false; if (!prop) { @@ -4743,8 +4743,8 @@ HasProperty(JSContext *cx, JSObject *obj, jsval id, JSBool *found) * For a proper solution see bug 355257. */ static JSBool -xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, - JSProperty **propp) +xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, + MutableHandleObject objp, MutableHandleShape propp) { JSBool found; JSXML *xml; @@ -4766,7 +4766,7 @@ xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObj } if (!found) { objp.set(NULL); - *propp = NULL; + propp.set(NULL); } else { Shape *shape = js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty, @@ -4776,14 +4776,14 @@ xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObj return JS_FALSE; objp.set(obj); - *propp = (JSProperty *) shape; + propp.set(shape); } return JS_TRUE; } static JSBool xml_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, NameToId(name)); return xml_lookupGeneric(cx, obj, id, objp, propp); @@ -4791,12 +4791,12 @@ xml_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, static JSBool xml_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, - JSProperty **propp) + MutableHandleShape propp) { JSXML *xml = reinterpret_cast(obj->getPrivate()); if (!HasIndexedProperty(xml, index)) { objp.set(NULL); - *propp = NULL; + propp.set(NULL); return true; } @@ -4811,13 +4811,13 @@ xml_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandle return false; objp.set(obj); - *propp = (JSProperty *) shape; + propp.set(shape); return true; } static JSBool xml_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return xml_lookupGeneric(cx, obj, id, objp, propp); @@ -7745,7 +7745,6 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, MutableHandleObject objp JSObject *obj, *target, *proto; JSXML *xml; JSBool found; - JSProperty *prop; JS_ASSERT(nameval.isObject()); nameobj = &nameval.toObject(); @@ -7792,6 +7791,7 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, MutableHandleObject objp } } else if (!JSID_IS_VOID(funid)) { RootedObject pobj(cx); + RootedShape prop(cx); if (!target->lookupGeneric(cx, funid, &pobj, &prop)) return JS_FALSE; if (prop) { diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index d050029306aa..bce0cf77852f 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -5071,13 +5071,12 @@ mjit::Compiler::testSingletonProperty(HandleObject obj, HandleId id) } RootedObject holder(cx); - JSProperty *prop = NULL; - if (!obj->lookupGeneric(cx, id, &holder, &prop)) + RootedShape shape(cx); + if (!obj->lookupGeneric(cx, id, &holder, &shape)) return false; - if (!prop) + if (!shape) return false; - Shape *shape = (Shape *) prop; if (shape->hasDefaultGetter()) { if (!shape->hasSlot()) return false; diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index ccfc69adf9fe..8b4d943873f0 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -2686,18 +2686,17 @@ mjit::Compiler::jsop_initprop() } RootedObject holder(cx); - JSProperty *prop = NULL; + RootedShape shape(cx); Rooted id(cx, NameToId(name)); #ifdef DEBUG bool res = #endif - LookupPropertyWithFlags(cx, baseobj, id, JSRESOLVE_QUALIFIED, &holder, &prop); - JS_ASSERT(res && prop && holder == baseobj); + LookupPropertyWithFlags(cx, baseobj, id, JSRESOLVE_QUALIFIED, &holder, &shape); + JS_ASSERT(res && shape && holder == baseobj); RegisterID objReg = frame.copyDataIntoReg(obj); /* Perform the store. */ - Shape *shape = (Shape *) prop; Address address = masm.objPropAddress(baseobj, objReg, shape->slot()); frame.storeTo(fe, address); frame.freeReg(objReg); diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 2eedda0e3e8e..cf81396e9d81 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -454,19 +454,17 @@ class SetPropCompiler : public PICStubCompiler return disable("ops set property hook"); RootedObject holder(cx); - JSProperty *prop = NULL; + RootedShape shape(cx); /* lookupProperty can trigger recompilations. */ RecompilationMonitor monitor(cx); - if (!obj->lookupProperty(cx, name, &holder, &prop)) + if (!obj->lookupProperty(cx, name, &holder, &shape)) return error(); if (monitor.recompiled()) return Lookup_Uncacheable; /* If the property exists but is on a prototype, treat as addprop. */ - if (prop && holder != obj) { - Shape *shape = (Shape *) prop; - + if (shape && holder != obj) { if (!holder->isNative()) return disable("non-native holder"); @@ -479,10 +477,10 @@ class SetPropCompiler : public PICStubCompiler if (!shape->hasSlot()) return disable("missing slot"); - prop = NULL; + shape = NULL; } - if (!prop) { + if (!shape) { /* Adding a property to the object. */ if (obj->isDelegate()) return disable("delegate"); @@ -523,7 +521,7 @@ class SetPropCompiler : public PICStubCompiler * populate the slot to satisfy the method invariant (in case we * hit an early return below). */ - Shape *shape = + shape = obj->putProperty(cx, name, getter, clasp->setProperty, SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, flags, 0); if (!shape) @@ -575,7 +573,6 @@ class SetPropCompiler : public PICStubCompiler return generateStub(initialShape, shape, true); } - Shape *shape = (Shape *) prop; if (!shape->writable()) return disable("readonly"); if (shape->hasDefaultSetter()) { @@ -661,14 +658,14 @@ struct GetPropHelper { // These fields are set by |bind| and |lookup|. After a call to either // function, these are set exactly as they are in JSOP_GETPROP or JSOP_NAME. RootedObject holder; - JSProperty *prop; + RootedShape prop; // This field is set by |bind| and |lookup| only if they returned // Lookup_Cacheable, otherwise it is NULL. - Shape *shape; + RootedShape 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) + : cx(cx), obj(cx, obj), name(cx, name), ic(ic), f(f), holder(cx), prop(cx), shape(cx) { } public: @@ -687,7 +684,7 @@ struct GetPropHelper { return ic.disable(cx, "non-native"); if (!IsCacheableProtoChain(obj, holder)) return ic.disable(cx, "non-native holder"); - shape = (Shape *)prop; + shape = prop; return Lookup_Cacheable; } @@ -708,7 +705,7 @@ struct GetPropHelper { return ic.disable(f, "lookup failed"); if (!IsCacheableProtoChain(obj, holder)) return ic.disable(f, "non-native holder"); - shape = (Shape *)prop; + shape = prop; return Lookup_Cacheable; } @@ -1675,7 +1672,7 @@ class ScopeNameCompiler : public PICStubCompiler { JSObject *obj = getprop.obj; Rooted holder(cx, getprop.holder); - const JSProperty *prop = getprop.prop; + RootedShape prop(cx, getprop.prop); if (!prop) { /* Kludge to allow (typeof foo == "undefined") tests. */ @@ -1698,7 +1695,7 @@ class ScopeNameCompiler : public PICStubCompiler return true; } - Shape *shape = getprop.shape; + RootedShape shape(cx, getprop.shape); Rooted normalized(cx, obj); if (obj->isWith() && !shape->hasDefaultGetter()) normalized = &obj->asWith().object(); diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 49cde6c015c7..a726fadf2bee 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -193,7 +193,7 @@ stubs::ImplicitThis(VMFrame &f, PropertyName *name_) RootedPropertyName name(f.cx, name_); RootedObject obj(f.cx), obj2(f.cx); - JSProperty *prop; + RootedShape prop(f.cx); if (!FindPropertyHelper(f.cx, name, false, scopeObj, &obj, &obj2, &prop)) THROW(); @@ -338,16 +338,16 @@ stubs::DefFun(VMFrame &f, JSFunction *fun_) /* ES5 10.5 (NB: with subsequent errata). */ PropertyName *name = fun->atom->asPropertyName(); - JSProperty *prop = NULL; + RootedShape shape(cx); RootedObject pobj(cx); - if (!parent->lookupProperty(cx, name, &pobj, &prop)) + if (!parent->lookupProperty(cx, name, &pobj, &shape)) THROW(); Value rval = ObjectValue(*fun); do { /* Steps 5d, 5f. */ - if (!prop || pobj != parent) { + if (!shape || pobj != parent) { if (!parent->defineProperty(cx, name, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs)) { @@ -358,7 +358,6 @@ stubs::DefFun(VMFrame &f, JSFunction *fun_) /* Step 5e. */ JS_ASSERT(parent->isNative()); - Shape *shape = reinterpret_cast(prop); if (parent->isGlobal()) { if (shape->configurable()) { if (!parent->defineProperty(cx, name, rval, @@ -1339,7 +1338,7 @@ stubs::DelName(VMFrame &f, PropertyName *name_) RootedPropertyName name(f.cx, name_); RootedObject obj(f.cx), obj2(f.cx); - JSProperty *prop; + RootedShape prop(f.cx); if (!FindProperty(f.cx, name, scopeObj, &obj, &obj2, &prop)) THROW(); @@ -1439,7 +1438,7 @@ stubs::In(VMFrame &f) THROWV(JS_FALSE); RootedObject obj2(cx); - JSProperty *prop; + RootedShape prop(cx); if (!obj->lookupGeneric(cx, id, &obj2, &prop)) THROWV(JS_FALSE); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 9b32c591ede7..c4b832278ec7 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -2689,19 +2689,18 @@ static JSBool CopyProperty(JSContext *cx, HandleObject obj, HandleObject referent, HandleId id, unsigned lookupFlags, MutableHandleObject objp) { - JSProperty *prop; + RootedShape shape(cx); PropertyDescriptor desc; unsigned propFlags = 0; RootedObject obj2(cx); objp.set(NULL); if (referent->isNative()) { - if (!LookupPropertyWithFlags(cx, referent, id, lookupFlags, &obj2, &prop)) + if (!LookupPropertyWithFlags(cx, referent, id, lookupFlags, &obj2, &shape)) return false; if (obj2 != referent) return true; - const Shape *shape = (Shape *) prop; if (shape->hasSlot()) { desc.value = referent->nativeGetSlot(shape->slot()); } else { @@ -2724,7 +2723,7 @@ CopyProperty(JSContext *cx, HandleObject obj, HandleObject referent, HandleId id if (!desc.obj) return true; } else { - if (!referent->lookupGeneric(cx, id, objp, &prop)) + if (!referent->lookupGeneric(cx, id, objp, &shape)) return false; if (objp != referent) return true; diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp index d246a4d703d3..b9e661e53c26 100644 --- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -259,7 +259,7 @@ args_enumerate(JSContext *cx, HandleObject obj) : INT_TO_JSID(i); RootedObject pobj(cx); - JSProperty *prop; + RootedShape prop(cx); if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; } @@ -369,7 +369,7 @@ strictargs_enumerate(JSContext *cx, HandleObject obj) * js_LookupProperty calls. */ RootedObject pobj(cx); - JSProperty *prop; + RootedShape prop(cx); RootedId id(cx); // length diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index d11d4a70c4ab..3927e93e38f8 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -4413,7 +4413,7 @@ DebuggerEnv_find(JSContext *cx, unsigned argc, Value *vp) /* This can trigger resolve hooks. */ ErrorCopier ec(ac, dbg->toJSObject()); - JSProperty *prop = NULL; + RootedShape prop(cx); RootedObject pobj(cx); for (; env && !prop; env = env->enclosingScope()) { if (!env->lookupGeneric(cx, id, &pobj, &prop)) diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 4bb2f5286bc5..b4de1e3355e9 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -351,22 +351,22 @@ WithObject::create(JSContext *cx, HandleObject proto, HandleObject enclosing, ui static JSBool with_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { return obj->asWith().object().lookupGeneric(cx, id, objp, propp); } static JSBool with_LookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, NameToId(name)); return with_LookupGeneric(cx, obj, id, objp, propp); } static JSBool -with_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, - JSProperty **propp) +with_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, + MutableHandleObject objp, MutableHandleShape propp) { RootedId id(cx); if (!IndexToId(cx, index, id.address())) @@ -376,7 +376,7 @@ with_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandl static JSBool with_LookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, JSProperty **propp) + MutableHandleObject objp, MutableHandleShape propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return with_LookupGeneric(cx, obj, id, objp, propp); From 4ef9c9430fa2d5771b95b53c163f4ef60d48a531 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Wed, 4 Jul 2012 20:22:30 -0700 Subject: [PATCH 07/31] Backed out changeset fe305819d2f2 (bug 771026) for orange --- js/src/jsapi.cpp | 30 +++--- js/src/jsarray.cpp | 24 ++--- js/src/jsclass.h | 16 +-- js/src/jsclone.cpp | 2 +- js/src/jsinterp.cpp | 20 ++-- js/src/jsinterpinlines.h | 11 ++- js/src/jsiter.cpp | 4 +- js/src/jsobj.cpp | 176 ++++++++++++++++++--------------- js/src/jsobj.h | 26 +++-- js/src/jsobjinlines.h | 16 ++- js/src/jsproxy.cpp | 16 +-- js/src/jsprvtd.h | 3 +- js/src/jsscope.cpp | 13 --- js/src/jsscope.h | 3 - js/src/jstypedarray.cpp | 36 +++---- js/src/jstypedarray.h | 16 +-- js/src/jsxml.cpp | 22 ++--- js/src/methodjit/Compiler.cpp | 7 +- js/src/methodjit/FastOps.cpp | 7 +- js/src/methodjit/PolyIC.cpp | 29 +++--- js/src/methodjit/StubCalls.cpp | 13 +-- js/src/shell/js.cpp | 7 +- js/src/vm/ArgumentsObject.cpp | 4 +- js/src/vm/Debugger.cpp | 2 +- js/src/vm/ScopeObject.cpp | 10 +- 25 files changed, 264 insertions(+), 249 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 061d1be0d95a..9e5767151f2a 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3397,7 +3397,7 @@ JS_DeepFreezeObject(JSContext *cx, JSObject *obj_) static JSBool LookupPropertyById(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { AssertNoGC(cx); CHECK_REQUEST(cx); @@ -3411,15 +3411,17 @@ LookupPropertyById(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, static JSBool LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, jsid id, - HandleShape shape, Value *vp) + JSProperty* prop, Value *vp) { - if (!shape) { + if (!prop) { /* XXX bad API: no way to tell "not defined" from "void value" */ vp->setUndefined(); return JS_TRUE; } if (obj2->isNative()) { + Shape *shape = (Shape *) prop; + /* Peek at the native property's slot value, without doing a Get. */ if (shape->hasSlot()) { *vp = obj2->nativeGetSlot(shape->slot()); @@ -3450,7 +3452,7 @@ JS_LookupPropertyById(JSContext *cx, JSObject *obj_, jsid id_, jsval *vp) RootedId id(cx, id_); RootedObject obj(cx, obj_); RootedObject obj2(cx); - RootedShape prop(cx); + JSProperty* prop; return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) && LookupResult(cx, obj, obj2, id, prop, vp); @@ -3488,7 +3490,7 @@ JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj_, jsid id_, unsigned RootedObject obj(cx, obj_); RootedObject objp(cx, *objp_); RootedId id(cx, id_); - RootedShape prop(cx); + JSProperty* prop; AssertNoGC(cx); CHECK_REQUEST(cx); @@ -3519,7 +3521,7 @@ JS_HasPropertyById(JSContext *cx, JSObject *obj_, jsid id_, JSBool *foundp) RootedObject obj(cx, obj_); RootedId id(cx, id_); RootedObject obj2(cx); - RootedShape prop(cx); + JSProperty* prop; JSBool ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING, &obj2, &prop); *foundp = (prop != NULL); @@ -3564,7 +3566,7 @@ JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj_, jsid id_, JSBool *fo if (!obj->isNative()) { RootedObject obj2(cx); - RootedShape prop(cx); + JSProperty *prop; if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING, &obj2, &prop)) { @@ -3836,12 +3838,12 @@ GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned JSBool own, PropertyDescriptor *desc) { RootedObject obj2(cx); - RootedShape shape(cx); + JSProperty *prop; - if (!LookupPropertyById(cx, obj, id, flags, &obj2, &shape)) + if (!LookupPropertyById(cx, obj, id, flags, &obj2, &prop)) return JS_FALSE; - if (!shape || (own && obj != obj2)) { + if (!prop || (own && obj != obj2)) { desc->obj = NULL; desc->attrs = 0; desc->getter = NULL; @@ -3852,6 +3854,7 @@ GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned desc->obj = obj2; if (obj2->isNative()) { + Shape *shape = (Shape *) prop; desc->attrs = shape->attributes(); desc->getter = shape->getter(); desc->setter = shape->setter(); @@ -3960,14 +3963,15 @@ static JSBool SetPropertyAttributesById(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs, JSBool *foundp) { RootedObject obj2(cx); - RootedShape shape(cx); + JSProperty *prop; - if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &shape)) + if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop)) return false; - if (!shape || obj != obj2) { + if (!prop || obj != obj2) { *foundp = false; return true; } + Shape *shape = (Shape *) prop; JSBool ok = obj->isNative() ? obj->changePropertyAttributes(cx, shape, attrs) : obj->setGenericAttributes(cx, id, &attrs); diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 26871b1b96ac..3a07b66ed85c 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -347,7 +347,7 @@ DoGetElement(JSContext *cx, JSObject *obj_, double index, JSBool *hole, Value *v } RootedObject obj2(cx); - RootedShape prop(cx); + JSProperty *prop; if (!obj->lookupGeneric(cx, id, &obj2, &prop)) return JS_FALSE; if (!prop) { @@ -692,14 +692,14 @@ IsDenseArrayId(JSContext *cx, JSObject *obj, jsid id) } static JSBool -array_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) +array_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, + JSProperty **propp) { if (!obj->isDenseArray()) return baseops::LookupProperty(cx, obj, id, objp, propp); if (IsDenseArrayId(cx, obj, id)) { - MarkNonNativePropertyFound(obj, propp); + *propp = (JSProperty *) 1; /* non-null to indicate found */ objp.set(obj); return JS_TRUE; } @@ -707,7 +707,7 @@ array_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, JSObject *proto = obj->getProto(); if (!proto) { objp.set(NULL); - propp.set(NULL); + *propp = NULL; return JS_TRUE; } return proto->lookupGeneric(cx, id, objp, propp); @@ -715,21 +715,21 @@ array_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, static JSBool array_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, NameToId(name)); return array_lookupGeneric(cx, obj, id, objp, propp); } static JSBool -array_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp) +array_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, + JSProperty **propp) { if (!obj->isDenseArray()) return baseops::LookupElement(cx, obj, index, objp, propp); if (IsDenseArrayIndex(obj, index)) { - MarkNonNativePropertyFound(obj, propp); + *propp = (JSProperty *) 1; /* non-null to indicate found */ objp.set(obj); return true; } @@ -738,13 +738,13 @@ array_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, return proto->lookupElement(cx, index, objp, propp); objp.set(NULL); - propp.set(NULL); + *propp = NULL; return true; } static JSBool -array_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp) +array_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, MutableHandleObject objp, + JSProperty **propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return array_lookupGeneric(cx, obj, id, objp, propp); diff --git a/js/src/jsclass.h b/js/src/jsclass.h index e5bcacc05e29..b870aa5eeb9e 100644 --- a/js/src/jsclass.h +++ b/js/src/jsclass.h @@ -149,17 +149,17 @@ typedef JS::Handle HandleSpecialId; /* js::Class operation signatures. */ typedef JSBool -(* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp); +(* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, + JSProperty **propp); typedef JSBool -(* LookupPropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp); +(* LookupPropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleObject objp, + JSProperty **propp); typedef JSBool -(* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp); +(* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, + JSProperty **propp); typedef JSBool -(* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp); +(* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, MutableHandleObject objp, + JSProperty **propp); typedef JSBool (* DefineGenericOp)(JSContext *cx, HandleObject obj, HandleId id, const Value *value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs); diff --git a/js/src/jsclone.cpp b/js/src/jsclone.cpp index 2a6520390a1f..06be21b5205d 100644 --- a/js/src/jsclone.cpp +++ b/js/src/jsclone.cpp @@ -559,7 +559,7 @@ JSStructuredCloneWriter::write(const Value &v) * NativeIterators. */ RootedObject obj2(context()); - RootedShape prop(context()); + JSProperty *prop; if (!js_HasOwnProperty(context(), obj->getOps()->lookupGeneric, obj, id, &obj2, &prop)) { return false; diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 3acf4eb23fbf..f9821067280b 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -954,7 +954,7 @@ js::AssertValidPropertyCacheHit(JSContext *cx, JSObject *start_, RootedObject obj(cx); RootedObject pobj(cx); - RootedShape prop(cx); + JSProperty *prop; JSBool ok; if (JOF_OPMODE(*pc) == JOF_NAME) @@ -967,7 +967,9 @@ js::AssertValidPropertyCacheHit(JSContext *cx, JSObject *start_, JS_PROPERTY_CACHE(cx).restore(&savedEntry); JS_ASSERT(prop); JS_ASSERT(pobj == found); - JS_ASSERT(entry->prop == prop); + + Shape *shape = (Shape *) prop; + JS_ASSERT(entry->prop == shape); } #endif /* DEBUG && !JS_THREADSAFE */ @@ -1279,7 +1281,6 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) RootedTypeObject rootType0(cx); RootedPropertyName rootName0(cx); RootedId rootId0(cx); - RootedShape rootShape0(cx); if (rt->profilingScripts) ENABLE_INTERRUPTS(); @@ -1745,7 +1746,7 @@ BEGIN_CASE(JSOP_IN) RootedId &id = rootId0; FETCH_ELEMENT_ID(obj, -2, id); RootedObject &obj2 = rootObject1; - RootedShape &prop = rootShape0; + JSProperty *prop; if (!obj->lookupGeneric(cx, id, &obj2, &prop)) goto error; bool cond = prop != NULL; @@ -2205,7 +2206,7 @@ BEGIN_CASE(JSOP_DELNAME) RootedObject &obj = rootObject1; RootedObject &obj2 = rootObject2; - RootedShape &prop = rootShape0; + JSProperty *prop; if (!FindProperty(cx, name, scopeObj, &obj, &obj2, &prop)) goto error; @@ -2552,7 +2553,7 @@ BEGIN_CASE(JSOP_IMPLICITTHIS) RootedObject &obj = rootObject1; RootedObject &obj2 = rootObject2; - RootedShape &prop = rootShape0; + JSProperty *prop; if (!FindPropertyHelper(cx, name, false, scopeObj, &obj, &obj2, &prop)) goto error; @@ -2919,9 +2920,9 @@ BEGIN_CASE(JSOP_DEFFUN) /* ES5 10.5 (NB: with subsequent errata). */ RootedPropertyName &name = rootName0; name = fun->atom->asPropertyName(); - RootedShape &shape = rootShape0; + JSProperty *prop = NULL; RootedObject &pobj = rootObject1; - if (!parent->lookupProperty(cx, name, &pobj, &shape)) + if (!parent->lookupProperty(cx, name, &pobj, &prop)) goto error; RootedValue &rval = rootValue0; @@ -2929,7 +2930,7 @@ BEGIN_CASE(JSOP_DEFFUN) do { /* Steps 5d, 5f. */ - if (!shape || pobj != parent) { + if (!prop || pobj != parent) { if (!parent->defineProperty(cx, name, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs)) { @@ -2940,6 +2941,7 @@ BEGIN_CASE(JSOP_DEFFUN) /* Step 5e. */ JS_ASSERT(parent->isNative()); + Shape *shape = reinterpret_cast(prop); if (parent->isGlobal()) { if (shape->configurable()) { if (!parent->defineProperty(cx, name, rval, diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index 87618ac3bd80..e39da14f7be5 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -385,10 +385,10 @@ NameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value *vp) return true; } - RootedShape shape(cx); - if (!FindPropertyHelper(cx, name, true, obj, &obj, &obj2, &shape)) + JSProperty *prop; + if (!FindPropertyHelper(cx, name, true, obj, &obj, &obj2, &prop)) return false; - if (!shape) { + if (!prop) { /* Kludge to allow (typeof foo == "undefined") tests. */ JSOp op2 = JSOp(pc[JSOP_NAME_LENGTH]); if (op2 == JSOP_TYPEOF) { @@ -401,12 +401,13 @@ NameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value *vp) return false; } - /* Take the slow path if shape was not found in a native object. */ + /* Take the slow path if prop was not found in a native object. */ if (!obj->isNative() || !obj2->isNative()) { Rooted id(cx, NameToId(name)); if (!obj->getGeneric(cx, id, vp)) return false; } else { + Shape *shape = (Shape *)prop; Rooted normalized(cx, obj); if (normalized->getClass() == &WithClass && !shape->hasDefaultGetter()) normalized = &normalized->asWith().object(); @@ -423,7 +424,7 @@ DefVarOrConstOperation(JSContext *cx, HandleObject varobj, PropertyName *dn, uns JS_ASSERT(varobj->isVarObj()); JS_ASSERT(!varobj->getOps()->defineProperty || varobj->isDebugScope()); - RootedShape prop(cx); + JSProperty *prop; RootedObject obj2(cx); if (!varobj->lookupProperty(cx, dn, &obj2, &prop)) return false; diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index c29e8b477174..b03fb3da8071 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -993,7 +993,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p if (obj->getProto()) { JSObject *proto = obj->getProto(); RootedObject obj2(cx); - RootedShape prop(cx); + JSProperty *prop; RootedId id(cx); if (!ValueToId(cx, StringValue(*idp), id.address())) return false; @@ -1002,7 +1002,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p if (prop) { unsigned attrs; if (obj2->isNative()) - attrs = prop->attributes(); + attrs = ((Shape *) prop)->attributes(); else if (!obj2->getGenericAttributes(cx, id, &attrs)) return false; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 9f22668c86d0..51396a510ebc 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -179,7 +179,7 @@ MarkSharpObjects(JSContext *cx, HandleObject obj, JSIdArray **idap, JSSharpInfo for (int i = 0, length = ida->length; i < length; i++) { id = ida->vector[i]; RootedObject obj2(cx); - RootedShape prop(cx); + JSProperty *prop; ok = obj->lookupGeneric(cx, id, &obj2, &prop); if (!ok) break; @@ -460,7 +460,7 @@ obj_toSource(JSContext *cx, unsigned argc, Value *vp) JSLinearString *idstr; RootedObject obj2(cx); - RootedShape prop(cx); + JSProperty *prop; if (!obj->lookupGeneric(cx, id, &obj2, &prop)) return false; @@ -807,7 +807,7 @@ js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, unsigned argc, if (!obj) return false; RootedObject obj2(cx); - RootedShape prop(cx); + JSProperty *prop; if (obj->isProxy()) { bool has; if (!Proxy::hasOwn(cx, obj, id, &has)) @@ -823,7 +823,7 @@ js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, unsigned argc, JSBool js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING); if (lookup) { @@ -833,7 +833,7 @@ js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, Handl if (!baseops::LookupProperty(cx, obj, id, objp, propp)) return false; } - if (!propp) + if (!*propp) return true; if (objp == obj) @@ -848,7 +848,7 @@ js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, Handl } if (outer != objp) - propp.set(NULL); + *propp = NULL; return true; } @@ -894,7 +894,7 @@ JSBool js_PropertyIsEnumerable(JSContext *cx, HandleObject obj, HandleId id, Value *vp) { RootedObject pobj(cx); - RootedShape prop(cx); + JSProperty *prop; if (!obj->lookupGeneric(cx, id, &pobj, &prop)) return false; @@ -1004,12 +1004,13 @@ obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp) return JS_TRUE; } RootedObject pobj(cx); - RootedShape shape(cx); - if (!obj->lookupGeneric(cx, id, &pobj, &shape)) + JSProperty *prop; + if (!obj->lookupGeneric(cx, id, &pobj, &prop)) return JS_FALSE; vp->setUndefined(); - if (shape) { + if (prop) { if (pobj->isNative()) { + Shape *shape = (Shape *) prop; if (shape->hasGetterValue()) *vp = shape->getterValue(); } @@ -1038,12 +1039,13 @@ obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp) return JS_TRUE; } RootedObject pobj(cx); - RootedShape shape(cx); - if (!obj->lookupGeneric(cx, id, &pobj, &shape)) + JSProperty *prop; + if (!obj->lookupGeneric(cx, id, &pobj, &prop)) return JS_FALSE; vp->setUndefined(); - if (shape) { + if (prop) { if (pobj->isNative()) { + Shape *shape = (Shape *) prop; if (shape->hasSetterValue()) *vp = shape->setterValue(); } @@ -1169,16 +1171,17 @@ GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, PropertyD return Proxy::getOwnPropertyDescriptor(cx, obj, id, false, desc); RootedObject pobj(cx); - RootedShape shape(cx); - if (!js_HasOwnProperty(cx, obj->getOps()->lookupGeneric, obj, id, &pobj, &shape)) + JSProperty *prop; + if (!js_HasOwnProperty(cx, obj->getOps()->lookupGeneric, obj, id, &pobj, &prop)) return false; - if (!shape) { + if (!prop) { desc->obj = NULL; return true; } bool doGet = true; if (pobj->isNative()) { + Shape *shape = (Shape *) prop; desc->attrs = shape->attributes(); if (desc->attrs & (JSPROP_GETTER | JSPROP_SETTER)) { doGet = false; @@ -1506,16 +1509,16 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD bool throwError, bool *rval) { /* 8.12.9 step 1. */ - RootedShape shape(cx); + JSProperty *current; RootedObject obj2(cx); JS_ASSERT(!obj->getOps()->lookupGeneric); - if (!js_HasOwnProperty(cx, NULL, obj, id, &obj2, &shape)) + if (!js_HasOwnProperty(cx, NULL, obj, id, &obj2, ¤t)) return JS_FALSE; JS_ASSERT(!obj->getOps()->defineProperty); /* 8.12.9 steps 2-4. */ - if (!shape) { + if (!current) { if (!obj->isExtensible()) return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval); @@ -1550,6 +1553,7 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD JS_ASSERT(obj == obj2); + Rooted shape(cx, reinterpret_cast(current)); do { if (desc.isAccessorDescriptor()) { if (!shape->isAccessorDescriptor()) @@ -3853,6 +3857,9 @@ js_FindClassObject(JSContext *cx, HandleObject start, JSProtoKey protoKey, MutableHandleValue vp, Class *clasp) { RootedId id(cx); + JSProperty *prop; + Shape *shape; + RootedObject obj(cx); if (start) { @@ -3884,11 +3891,11 @@ js_FindClassObject(JSContext *cx, HandleObject start, JSProtoKey protoKey, JS_ASSERT(obj->isNative()); RootedObject pobj(cx); - RootedShape shape(cx); - if (!LookupPropertyWithFlags(cx, obj, id, 0, &pobj, &shape)) + if (!LookupPropertyWithFlags(cx, obj, id, 0, &pobj, &prop)) return false; RootedValue v(cx, UndefinedValue()); - if (shape && pobj->isNative()) { + if (prop && pobj->isNative()) { + shape = (Shape *) prop; if (shape->hasSlot()) { v = pobj->nativeGetSlot(shape->slot()); if (v.get().isPrimitive()) @@ -4108,6 +4115,8 @@ DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value & */ RootedShape shape(cx); if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) { + JSProperty *prop; + /* Type information for getter/setter properties is unknown. */ AddTypePropertyId(cx, obj, id, types::Type::UnknownType()); MarkTypePropertyConfigured(cx, obj, id); @@ -4118,10 +4127,10 @@ DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value & * property cache line for (obj, id) to map shape. */ RootedObject pobj(cx); - RootedShape shape(cx); - if (!baseops::LookupProperty(cx, obj, id, &pobj, &shape)) + if (!baseops::LookupProperty(cx, obj, id, &pobj, &prop)) return NULL; - if (shape && pobj == obj) { + if (prop && pobj == obj) { + shape = (Shape *) prop; if (shape->isAccessorDescriptor()) { shape = obj->changeProperty(cx, shape, attrs, JSPROP_GETTER | JSPROP_SETTER, @@ -4209,7 +4218,7 @@ DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value & */ static JSBool CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, - MutableHandleObject objp, MutableHandleShape propp, bool *recursedp) + MutableHandleObject objp, JSProperty **propp, bool *recursedp) { Class *clasp = obj->getClass(); JSResolveOp resolve = clasp->resolve; @@ -4230,7 +4239,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, } *recursedp = false; - propp.set(NULL); + *propp = NULL; if (clasp->flags & JSCLASS_NEW_RESOLVE) { JSNewResolveOp newresolve = reinterpret_cast(resolve); @@ -4264,7 +4273,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, if (!obj->nativeEmpty()) { if (Shape *shape = obj->nativeLookup(cx, id)) { objp.set(obj); - propp.set(shape); + *propp = (JSProperty *) shape; } } @@ -4273,7 +4282,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, static JS_ALWAYS_INLINE bool LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { /* Search scopes starting with obj and following the prototype link. */ RootedObject current(cx, obj); @@ -4281,7 +4290,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi Shape *shape = current->nativeLookup(cx, id); if (shape) { objp.set(current); - propp.set(shape); + *propp = (JSProperty *) shape; return true; } @@ -4292,7 +4301,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi return false; if (recursed) break; - if (propp) { + if (*propp) { /* * For stats we do not recalculate protoIndex even if it was * resolved on some other object. @@ -4317,7 +4326,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi * arguments.callee through the delegating |this| object's method * read barrier. */ - if (propp && objp->isNative()) { + if (*propp && objp->isNative()) { while ((proto = proto->getProto()) != objp) JS_ASSERT(proto); } @@ -4329,20 +4338,20 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi } objp.set(NULL); - propp.set(NULL); + *propp = NULL; return true; } JS_FRIEND_API(JSBool) baseops::LookupProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, - MutableHandleShape propp) + JSProperty **propp) { return LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, objp, propp); } JS_FRIEND_API(JSBool) baseops::LookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { RootedId id(cx); if (!IndexToId(cx, index, id.address())) @@ -4353,7 +4362,7 @@ baseops::LookupElement(JSContext *cx, HandleObject obj, uint32_t index, bool js::LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { return LookupPropertyWithFlagsInline(cx, obj, id, flags, objp, propp); } @@ -4361,14 +4370,13 @@ js::LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsign bool js::FindPropertyHelper(JSContext *cx, HandlePropertyName name, bool cacheResult, HandleObject scopeChain, - MutableHandleObject objp, MutableHandleObject pobjp, - MutableHandleShape propp) + MutableHandleObject objp, MutableHandleObject pobjp, JSProperty **propp) { RootedId id(cx, NameToId(name)); RootedObject pobj(cx); int scopeIndex; - RootedShape prop(cx); + JSProperty *prop; /* Scan entries on the scope chain that we can cache across. */ RootedObject obj(cx, scopeChain); @@ -4408,7 +4416,8 @@ js::FindPropertyHelper(JSContext *cx, * non-native prototype. */ if (cacheResult && pobj->isNative()) { - JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, prop); + JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, + (Shape *) prop); } goto out; @@ -4444,7 +4453,7 @@ js::FindPropertyHelper(JSContext *cx, JS_ASSERT(!!pobj == !!prop); objp.set(obj); pobjp.set(pobj); - propp.set(prop); + *propp = prop; return true; } @@ -4454,7 +4463,7 @@ js::FindPropertyHelper(JSContext *cx, */ bool js::FindProperty(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, - MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp) + MutableHandleObject objp, MutableHandleObject pobjp, JSProperty **propp) { return !!FindPropertyHelper(cx, name, false, scopeChain, objp, pobjp, propp); } @@ -4484,16 +4493,16 @@ js::FindIdentifierBase(JSContext *cx, HandleObject scopeChain, HandlePropertyNam scopeIndex++) { RootedObject pobj(cx); - RootedShape shape(cx); - if (!LookupPropertyWithFlags(cx, obj, name, cx->resolveFlags, &pobj, &shape)) + JSProperty *prop; + if (!LookupPropertyWithFlags(cx, obj, name, cx->resolveFlags, &pobj, &prop)) return NULL; - if (shape) { + if (prop) { if (!pobj->isNative()) { JS_ASSERT(obj->isGlobal()); return obj; } JS_ASSERT_IF(obj->isScope(), pobj->getClass() == obj->getClass()); - JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, shape); + JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, (Shape *) prop); return obj; } @@ -4506,10 +4515,10 @@ js::FindIdentifierBase(JSContext *cx, HandleObject scopeChain, HandlePropertyNam /* Loop until we find a property or reach the global object. */ do { RootedObject pobj(cx); - RootedShape shape(cx); - if (!obj->lookupProperty(cx, name, &pobj, &shape)) + JSProperty *prop; + if (!obj->lookupProperty(cx, name, &pobj, &prop)) return NULL; - if (shape) + if (prop) break; /* @@ -4620,15 +4629,16 @@ static JS_ALWAYS_INLINE JSBool js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receiver, jsid id_, uint32_t getHow, Value *vp) { + JSProperty *prop; + RootedId id(cx, id_); /* This call site is hot -- use the always-inlined variant of LookupPropertyWithFlags(). */ RootedObject obj2(cx); - RootedShape shape(cx); - if (!LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, &obj2, &shape)) + if (!LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, &obj2, &prop)) return false; - if (!shape) { + if (!prop) { vp->setUndefined(); if (!CallJSPropertyOp(cx, obj->getClass()->getProperty, obj, id, vp)) @@ -4696,6 +4706,8 @@ js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receive : obj2->getGeneric(cx, id, vp); } + Shape *shape = (Shape *) prop; + if (getHow & JSGET_CACHE_RESULT) JS_PROPERTY_CACHE(cx).fill(cx, obj, 0, obj2, shape); @@ -4733,7 +4745,7 @@ baseops::GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint JSBool baseops::GetPropertyDefault(JSContext *cx, HandleObject obj, HandleId id, const Value &def, Value *vp) { - RootedShape prop(cx); + JSProperty *prop; RootedObject obj2(cx); if (!LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop)) return false; @@ -4824,6 +4836,7 @@ JSBool baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, unsigned defineHow, Value *vp, JSBool strict) { + JSProperty *prop; unsigned attrs, flags; int shortid; Class *clasp; @@ -4841,10 +4854,9 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive } RootedObject pobj(cx); - RootedShape shape(cx); - if (!LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, &pobj, &shape)) + if (!LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, &pobj, &prop)) return false; - if (shape) { + if (prop) { if (!pobj->isNative()) { if (pobj->isProxy()) { AutoPropertyDescriptorRooter pd(cx); @@ -4866,7 +4878,7 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive } } - shape = NULL; + prop = NULL; } } else { /* We should never add properties to lexical blocks. */ @@ -4879,6 +4891,8 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive } } + RootedShape shape(cx, (Shape *) prop); + /* * Now either shape is null, meaning id was not found in obj or one of its * prototypes; or shape is non-null, meaning id was found directly in pobj. @@ -5018,16 +5032,17 @@ JSBool baseops::GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp) { RootedObject nobj(cx); - RootedShape shape(cx); - if (!baseops::LookupProperty(cx, obj, id, &nobj, &shape)) + JSProperty *prop; + if (!baseops::LookupProperty(cx, obj, id, &nobj, &prop)) return false; - if (!shape) { + if (!prop) { *attrsp = 0; return true; } if (!nobj->isNative()) return nobj->getGenericAttributes(cx, id, attrsp); + Shape *shape = (Shape *)prop; *attrsp = shape->attributes(); return true; } @@ -5036,16 +5051,17 @@ JSBool baseops::GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp) { RootedObject nobj(cx); - RootedShape shape(cx); - if (!baseops::LookupElement(cx, obj, index, &nobj, &shape)) + JSProperty *prop; + if (!baseops::LookupElement(cx, obj, index, &nobj, &prop)) return false; - if (!shape) { + if (!prop) { *attrsp = 0; return true; } if (!nobj->isNative()) return nobj->getElementAttributes(cx, index, attrsp); + Shape *shape = (Shape *)prop; *attrsp = shape->attributes(); return true; } @@ -5054,13 +5070,13 @@ JSBool baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp) { RootedObject nobj(cx); - RootedShape shape(cx); - if (!baseops::LookupProperty(cx, obj, id, &nobj, &shape)) + JSProperty *prop; + if (!baseops::LookupProperty(cx, obj, id, &nobj, &prop)) return false; - if (!shape) + if (!prop) return true; return nobj->isNative() - ? nobj->changePropertyAttributes(cx, shape, *attrsp) + ? nobj->changePropertyAttributes(cx, (Shape *) prop, *attrsp) : nobj->setGenericAttributes(cx, id, attrsp); } @@ -5068,26 +5084,28 @@ JSBool baseops::SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp) { RootedObject nobj(cx); - RootedShape shape(cx); - if (!baseops::LookupElement(cx, obj, index, &nobj, &shape)) + JSProperty *prop; + if (!baseops::LookupElement(cx, obj, index, &nobj, &prop)) return false; - if (!shape) + if (!prop) return true; return nobj->isNative() - ? nobj->changePropertyAttributes(cx, shape, *attrsp) + ? nobj->changePropertyAttributes(cx, (Shape *) prop, *attrsp) : nobj->setElementAttributes(cx, index, attrsp); } JSBool baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *rval, JSBool strict) { + JSProperty *prop; + Shape *shape; + rval->setBoolean(true); RootedObject proto(cx); - RootedShape shape(cx); - if (!baseops::LookupProperty(cx, obj, id, &proto, &shape)) + if (!baseops::LookupProperty(cx, obj, id, &proto, &prop)) return false; - if (!shape || proto != obj) { + if (!prop || proto != obj) { /* * If no property, or the property comes from a prototype, call the * class's delProperty hook, passing rval as the result parameter. @@ -5095,6 +5113,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *rval return CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, id, rval); } + shape = (Shape *)prop; if (!shape->configurable()) { if (strict) return obj->reportNotConfigurable(cx, id); @@ -5286,6 +5305,9 @@ CheckAccess(JSContext *cx, JSObject *obj_, HandleId id, JSAccessMode mode, Value *vp, unsigned *attrsp) { JSBool writing; + JSProperty *prop; + Shape *shape; + RootedObject obj(cx, obj_), pobj(cx); while (JS_UNLIKELY(obj->isWith())) @@ -5301,10 +5323,9 @@ CheckAccess(JSContext *cx, JSObject *obj_, HandleId id, JSAccessMode mode, break; default: - RootedShape shape(cx); - if (!obj->lookupGeneric(cx, id, &pobj, &shape)) + if (!obj->lookupGeneric(cx, id, &pobj, &prop)) return JS_FALSE; - if (!shape) { + if (!prop) { if (!writing) vp->setUndefined(); *attrsp = 0; @@ -5320,6 +5341,7 @@ CheckAccess(JSContext *cx, JSObject *obj_, HandleId id, JSAccessMode mode, break; } + shape = (Shape *)prop; *attrsp = shape->attributes(); if (!writing) { if (shape->hasSlot()) diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 8f707e4cf881..4f4374283853 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -99,11 +99,11 @@ namespace baseops { */ extern JS_FRIEND_API(JSBool) LookupProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, - MutableHandleShape propp); + JSProperty **propp); inline bool LookupProperty(JSContext *cx, HandleObject obj, PropertyName *name, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, NameToId(name)); return LookupProperty(cx, obj, id, objp, propp); @@ -111,7 +111,7 @@ LookupProperty(JSContext *cx, HandleObject obj, PropertyName *name, extern JS_FRIEND_API(JSBool) LookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp); + MutableHandleObject objp, JSProperty **propp); extern JSBool DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, const js::Value *value, @@ -785,14 +785,12 @@ struct JSObject : public js::ObjectImpl /* Clear the scope, making it empty. */ void clear(JSContext *cx); - inline JSBool lookupGeneric(JSContext *cx, js::HandleId id, - js::MutableHandleObject objp, js::MutableHandleShape propp); - inline JSBool lookupProperty(JSContext *cx, js::PropertyName *name, - js::MutableHandleObject objp, js::MutableHandleShape propp); + inline JSBool lookupGeneric(JSContext *cx, js::HandleId id, js::MutableHandleObject objp, JSProperty **propp); + inline JSBool lookupProperty(JSContext *cx, js::PropertyName *name, js::MutableHandleObject objp, JSProperty **propp); inline JSBool lookupElement(JSContext *cx, uint32_t index, - js::MutableHandleObject objp, js::MutableHandleShape propp); + js::MutableHandleObject objp, JSProperty **propp); inline JSBool lookupSpecial(JSContext *cx, js::SpecialId sid, - js::MutableHandleObject objp, js::MutableHandleShape propp); + js::MutableHandleObject objp, JSProperty **propp); inline JSBool defineGeneric(JSContext *cx, js::HandleId id, const js::Value &value, JSPropertyOp getter = JS_PropertyStub, @@ -1048,7 +1046,7 @@ js_HasOwnPropertyHelper(JSContext *cx, js::LookupGenericOp lookup, unsigned argc extern JSBool js_HasOwnProperty(JSContext *cx, js::LookupGenericOp lookup, js::HandleObject obj, js::HandleId id, - js::MutableHandleObject objp, js::MutableHandleShape propp); + js::MutableHandleObject objp, JSProperty **propp); extern JSBool js_PropertyIsEnumerable(JSContext *cx, js::HandleObject obj, js::HandleId id, js::Value *vp); @@ -1167,11 +1165,11 @@ DefineNativeProperty(JSContext *cx, HandleObject obj, PropertyName *name, const */ extern bool LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, - js::MutableHandleObject objp, js::MutableHandleShape propp); + js::MutableHandleObject objp, JSProperty **propp); inline bool LookupPropertyWithFlags(JSContext *cx, HandleObject obj, PropertyName *name, unsigned flags, - js::MutableHandleObject objp, js::MutableHandleShape propp) + js::MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, NameToId(name)); return LookupPropertyWithFlags(cx, obj, id, flags, objp, propp); @@ -1210,7 +1208,7 @@ static const unsigned RESOLVE_INFER = 0xffff; extern bool FindPropertyHelper(JSContext *cx, HandlePropertyName name, bool cacheResult, HandleObject scopeChain, - MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp); + MutableHandleObject objp, MutableHandleObject pobjp, JSProperty **propp); /* * Search for name either on the current scope chain or on the scope chain's @@ -1218,7 +1216,7 @@ FindPropertyHelper(JSContext *cx, HandlePropertyName name, */ extern bool FindProperty(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, - MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp); + MutableHandleObject objp, MutableHandleObject pobjp, JSProperty **propp); extern JSObject * FindIdentifierBase(JSContext *cx, HandleObject scopeChain, HandlePropertyName name); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 94bf32aac9fb..4d4fea02c404 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -927,7 +927,7 @@ inline bool JSObject::hasProperty(JSContext *cx, js::HandleId id, bool *foundp, unsigned flags) { js::RootedObject pobj(cx); - js::RootedShape prop(cx); + JSProperty *prop; JSAutoResolveFlags rf(cx, flags); if (!lookupGeneric(cx, id, &pobj, &prop)) return false; @@ -1034,8 +1034,7 @@ JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, } inline JSBool -JSObject::lookupGeneric(JSContext *cx, js::HandleId id, - js::MutableHandleObject objp, js::MutableHandleShape propp) +JSObject::lookupGeneric(JSContext *cx, js::HandleId id, js::MutableHandleObject objp, JSProperty **propp) { js::RootedObject self(cx, this); @@ -1046,8 +1045,7 @@ JSObject::lookupGeneric(JSContext *cx, js::HandleId id, } inline JSBool -JSObject::lookupProperty(JSContext *cx, js::PropertyName *name, - js::MutableHandleObject objp, js::MutableHandleShape propp) +JSObject::lookupProperty(JSContext *cx, js::PropertyName *name, js::MutableHandleObject objp, JSProperty **propp) { js::Rooted id(cx, js::NameToId(name)); return lookupGeneric(cx, id, objp, propp); @@ -1099,8 +1097,7 @@ JSObject::defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value } inline JSBool -JSObject::lookupElement(JSContext *cx, uint32_t index, - js::MutableHandleObject objp, js::MutableHandleShape propp) +JSObject::lookupElement(JSContext *cx, uint32_t index, js::MutableHandleObject objp, JSProperty **propp) { js::RootedObject self(cx, this); @@ -1109,8 +1106,7 @@ JSObject::lookupElement(JSContext *cx, uint32_t index, } inline JSBool -JSObject::lookupSpecial(JSContext *cx, js::SpecialId sid, - js::MutableHandleObject objp, js::MutableHandleShape propp) +JSObject::lookupSpecial(JSContext *cx, js::SpecialId sid, js::MutableHandleObject objp, JSProperty **propp) { js::Rooted id(cx, SPECIALID_TO_JSID(sid)); return lookupGeneric(cx, id, objp, propp); @@ -1158,7 +1154,7 @@ JSObject::getElementIfPresent(JSContext *cx, js::HandleObject receiver, uint32_t return false; js::RootedObject obj2(cx); - js::RootedShape prop(cx); + JSProperty *prop; if (!self->lookupGeneric(cx, id, &obj2, &prop)) return false; diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 1082da0a6989..0f3daa9c39ff 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -1221,34 +1221,34 @@ proxy_innerObject(JSContext *cx, HandleObject obj) } static JSBool -proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) +proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, + JSProperty **propp) { bool found; if (!Proxy::has(cx, obj, id, &found)) return false; if (found) { - MarkNonNativePropertyFound(obj, propp); + *propp = (JSProperty *)0x1; objp.set(obj); } else { objp.set(NULL); - propp.set(NULL); + *propp = NULL; } return true; } static JSBool proxy_LookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, NameToId(name)); return proxy_LookupGeneric(cx, obj, id, objp, propp); } static JSBool -proxy_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp) +proxy_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, + JSProperty **propp) { RootedId id(cx); if (!IndexToId(cx, index, id.address())) @@ -1258,7 +1258,7 @@ proxy_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, static JSBool proxy_LookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return proxy_LookupGeneric(cx, obj, id, objp, propp); diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index b6b1cb168a37..8988e0b51f54 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -51,6 +51,7 @@ typedef struct JSArgumentFormatMap JSArgumentFormatMap; typedef struct JSGCThing JSGCThing; typedef struct JSGenerator JSGenerator; typedef struct JSNativeEnumerator JSNativeEnumerator; +typedef struct JSProperty JSProperty; typedef struct JSSharpObjectMap JSSharpObjectMap; typedef struct JSTryNote JSTryNote; @@ -224,8 +225,6 @@ typedef JS::Handle HandleTypeObject; typedef JS::Handle HandleAtom; typedef JS::Handle HandlePropertyName; -typedef JS::MutableHandle MutableHandleShape; - typedef JS::Rooted RootedShape; typedef JS::Rooted RootedBaseShape; typedef JS::Rooted RootedTypeObject; diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 325c3fda387c..d6aad4a9ecbc 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -1393,16 +1393,3 @@ JSCompartment::sweepInitialShapeTable() } } } - -/* - * Property lookup hooks on non-native objects are required to return a non-NULL - * shape to signify that the property has been found. The actual shape returned - * is arbitrary, and it should never be read from. We use the non-native - * object's shape_ field, since it is readily available. - */ -void -js::MarkNonNativePropertyFound(HandleObject obj, MutableHandleShape propp) -{ - propp.set(obj->lastProperty()); -} - diff --git a/js/src/jsscope.h b/js/src/jsscope.h index b13101db1b63..0b87f621819f 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -1162,9 +1162,6 @@ Shape::searchNoAllocation(JSContext *cx, Shape *start, jsid id) } #endif /* DEBUG */ -void -MarkNonNativePropertyFound(HandleObject obj, MutableHandleShape propp); - } // namespace js #ifdef _MSC_VER diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index b959b95c4031..55c9446fc9f4 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -295,12 +295,14 @@ ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) } } +static JSProperty * const PROPERTY_FOUND = reinterpret_cast(1); + JSBool ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) { - MarkNonNativePropertyFound(obj, propp); + *propp = PROPERTY_FOUND; objp.set(getArrayBuffer(obj)); return true; } @@ -319,7 +321,7 @@ ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId i if (!delegateResult) return false; - if (propp) { + if (*propp != NULL) { if (objp == delegate) objp.set(obj); return true; @@ -328,7 +330,7 @@ ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId i JSObject *proto = obj->getProto(); if (!proto) { objp.set(NULL); - propp.set(NULL); + *propp = NULL; return true; } @@ -337,7 +339,7 @@ ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId i JSBool ArrayBufferObject::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, NameToId(name)); return obj_lookupGeneric(cx, obj, id, objp, propp); @@ -345,7 +347,7 @@ ArrayBufferObject::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePro JSBool ArrayBufferObject::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { RootedObject delegate(cx, ArrayBufferDelegate(cx, obj)); if (!delegate) @@ -360,7 +362,7 @@ ArrayBufferObject::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t i if (!delegate->lookupElement(cx, index, objp, propp)) return false; - if (propp) { + if (*propp != NULL) { if (objp == delegate) objp.set(obj); return true; @@ -370,13 +372,13 @@ ArrayBufferObject::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t i return proto->lookupElement(cx, index, objp, propp); objp.set(NULL); - propp.set(NULL); + *propp = NULL; return true; } JSBool ArrayBufferObject::obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return obj_lookupGeneric(cx, obj, id, objp, propp); @@ -772,13 +774,13 @@ js::IsDataView(JSObject* obj) JSBool TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { JSObject *tarray = getTypedArray(obj); JS_ASSERT(tarray); if (isArrayIndex(cx, tarray, id)) { - MarkNonNativePropertyFound(obj, propp); + *propp = PROPERTY_FOUND; objp.set(obj); return true; } @@ -786,7 +788,7 @@ TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, JSObject *proto = obj->getProto(); if (!proto) { objp.set(NULL); - propp.set(NULL); + *propp = NULL; return true; } @@ -795,7 +797,7 @@ TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, JSBool TypedArray::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, NameToId(name)); return obj_lookupGeneric(cx, obj, id, objp, propp); @@ -803,13 +805,13 @@ TypedArray::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyNa JSBool TypedArray::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { JSObject *tarray = getTypedArray(obj); JS_ASSERT(tarray); if (index < length(tarray)) { - MarkNonNativePropertyFound(obj, propp); + *propp = PROPERTY_FOUND; objp.set(obj); return true; } @@ -818,13 +820,13 @@ TypedArray::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, return proto->lookupElement(cx, index, objp, propp); objp.set(NULL); - propp.set(NULL); + *propp = NULL; return true; } JSBool TypedArray::obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return obj_lookupGeneric(cx, obj, id, objp, propp); diff --git a/js/src/jstypedarray.h b/js/src/jstypedarray.h index 325607227e78..788f3d631ca9 100644 --- a/js/src/jstypedarray.h +++ b/js/src/jstypedarray.h @@ -47,16 +47,16 @@ class ArrayBufferObject : public JSObject static JSBool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp); + MutableHandleObject objp, JSProperty **propp); static JSBool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp); + MutableHandleObject objp, JSProperty **propp); static JSBool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp); + MutableHandleObject objp, JSProperty **propp); static JSBool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp); + MutableHandleObject objp, JSProperty **propp); static JSBool obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, const Value *v, @@ -189,13 +189,13 @@ struct TypedArray { static Class protoClasses[TYPE_MAX]; static JSBool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp); + MutableHandleObject objp, JSProperty **propp); static JSBool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp); + MutableHandleObject objp, JSProperty **propp); static JSBool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp); + MutableHandleObject objp, JSProperty **propp); static JSBool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp); + MutableHandleObject objp, JSProperty **propp); static JSBool obj_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp); static JSBool obj_getPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp); diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 9a968c28bfb8..89c050d0fdb7 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -4632,6 +4632,7 @@ HasSimpleContent(JSXML *xml); static JSBool HasFunctionProperty(JSContext *cx, JSObject *obj_, jsid funid_, JSBool *found) { + JSProperty *prop; JSXML *xml; JS_ASSERT(obj_->getClass() == &XMLClass); @@ -4640,7 +4641,6 @@ HasFunctionProperty(JSContext *cx, JSObject *obj_, jsid funid_, JSBool *found) Rooted obj(cx, obj_); RootedObject pobj(cx); - RootedShape prop(cx); if (!baseops::LookupProperty(cx, obj, funid, &pobj, &prop)) return false; if (!prop) { @@ -4743,8 +4743,8 @@ HasProperty(JSContext *cx, JSObject *obj, jsval id, JSBool *found) * For a proper solution see bug 355257. */ static JSBool -xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) +xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, + JSProperty **propp) { JSBool found; JSXML *xml; @@ -4766,7 +4766,7 @@ xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, } if (!found) { objp.set(NULL); - propp.set(NULL); + *propp = NULL; } else { Shape *shape = js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty, @@ -4776,14 +4776,14 @@ xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, return JS_FALSE; objp.set(obj); - propp.set(shape); + *propp = (JSProperty *) shape; } return JS_TRUE; } static JSBool xml_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, NameToId(name)); return xml_lookupGeneric(cx, obj, id, objp, propp); @@ -4791,12 +4791,12 @@ xml_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, static JSBool xml_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, - MutableHandleShape propp) + JSProperty **propp) { JSXML *xml = reinterpret_cast(obj->getPrivate()); if (!HasIndexedProperty(xml, index)) { objp.set(NULL); - propp.set(NULL); + *propp = NULL; return true; } @@ -4811,13 +4811,13 @@ xml_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandle return false; objp.set(obj); - propp.set(shape); + *propp = (JSProperty *) shape; return true; } static JSBool xml_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return xml_lookupGeneric(cx, obj, id, objp, propp); @@ -7745,6 +7745,7 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, MutableHandleObject objp JSObject *obj, *target, *proto; JSXML *xml; JSBool found; + JSProperty *prop; JS_ASSERT(nameval.isObject()); nameobj = &nameval.toObject(); @@ -7791,7 +7792,6 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, MutableHandleObject objp } } else if (!JSID_IS_VOID(funid)) { RootedObject pobj(cx); - RootedShape prop(cx); if (!target->lookupGeneric(cx, funid, &pobj, &prop)) return JS_FALSE; if (prop) { diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index bce0cf77852f..d050029306aa 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -5071,12 +5071,13 @@ mjit::Compiler::testSingletonProperty(HandleObject obj, HandleId id) } RootedObject holder(cx); - RootedShape shape(cx); - if (!obj->lookupGeneric(cx, id, &holder, &shape)) + JSProperty *prop = NULL; + if (!obj->lookupGeneric(cx, id, &holder, &prop)) return false; - if (!shape) + if (!prop) return false; + Shape *shape = (Shape *) prop; if (shape->hasDefaultGetter()) { if (!shape->hasSlot()) return false; diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index 8b4d943873f0..ccfc69adf9fe 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -2686,17 +2686,18 @@ mjit::Compiler::jsop_initprop() } RootedObject holder(cx); - RootedShape shape(cx); + JSProperty *prop = NULL; Rooted id(cx, NameToId(name)); #ifdef DEBUG bool res = #endif - LookupPropertyWithFlags(cx, baseobj, id, JSRESOLVE_QUALIFIED, &holder, &shape); - JS_ASSERT(res && shape && holder == baseobj); + LookupPropertyWithFlags(cx, baseobj, id, JSRESOLVE_QUALIFIED, &holder, &prop); + JS_ASSERT(res && prop && holder == baseobj); RegisterID objReg = frame.copyDataIntoReg(obj); /* Perform the store. */ + Shape *shape = (Shape *) prop; Address address = masm.objPropAddress(baseobj, objReg, shape->slot()); frame.storeTo(fe, address); frame.freeReg(objReg); diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index cf81396e9d81..2eedda0e3e8e 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -454,17 +454,19 @@ class SetPropCompiler : public PICStubCompiler return disable("ops set property hook"); RootedObject holder(cx); - RootedShape shape(cx); + JSProperty *prop = NULL; /* lookupProperty can trigger recompilations. */ RecompilationMonitor monitor(cx); - if (!obj->lookupProperty(cx, name, &holder, &shape)) + if (!obj->lookupProperty(cx, name, &holder, &prop)) return error(); if (monitor.recompiled()) return Lookup_Uncacheable; /* If the property exists but is on a prototype, treat as addprop. */ - if (shape && holder != obj) { + if (prop && holder != obj) { + Shape *shape = (Shape *) prop; + if (!holder->isNative()) return disable("non-native holder"); @@ -477,10 +479,10 @@ class SetPropCompiler : public PICStubCompiler if (!shape->hasSlot()) return disable("missing slot"); - shape = NULL; + prop = NULL; } - if (!shape) { + if (!prop) { /* Adding a property to the object. */ if (obj->isDelegate()) return disable("delegate"); @@ -521,7 +523,7 @@ class SetPropCompiler : public PICStubCompiler * populate the slot to satisfy the method invariant (in case we * hit an early return below). */ - shape = + Shape *shape = obj->putProperty(cx, name, getter, clasp->setProperty, SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, flags, 0); if (!shape) @@ -573,6 +575,7 @@ class SetPropCompiler : public PICStubCompiler return generateStub(initialShape, shape, true); } + Shape *shape = (Shape *) prop; if (!shape->writable()) return disable("readonly"); if (shape->hasDefaultSetter()) { @@ -658,14 +661,14 @@ struct GetPropHelper { // These fields are set by |bind| and |lookup|. After a call to either // function, these are set exactly as they are in JSOP_GETPROP or JSOP_NAME. RootedObject holder; - RootedShape prop; + JSProperty *prop; // This field is set by |bind| and |lookup| only if they returned // Lookup_Cacheable, otherwise it is NULL. - RootedShape 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(cx), shape(cx) + : cx(cx), obj(cx, obj), name(cx, name), ic(ic), f(f), holder(cx), prop(NULL), shape(NULL) { } public: @@ -684,7 +687,7 @@ struct GetPropHelper { return ic.disable(cx, "non-native"); if (!IsCacheableProtoChain(obj, holder)) return ic.disable(cx, "non-native holder"); - shape = prop; + shape = (Shape *)prop; return Lookup_Cacheable; } @@ -705,7 +708,7 @@ struct GetPropHelper { return ic.disable(f, "lookup failed"); if (!IsCacheableProtoChain(obj, holder)) return ic.disable(f, "non-native holder"); - shape = prop; + shape = (Shape *)prop; return Lookup_Cacheable; } @@ -1672,7 +1675,7 @@ class ScopeNameCompiler : public PICStubCompiler { JSObject *obj = getprop.obj; Rooted holder(cx, getprop.holder); - RootedShape prop(cx, getprop.prop); + const JSProperty *prop = getprop.prop; if (!prop) { /* Kludge to allow (typeof foo == "undefined") tests. */ @@ -1695,7 +1698,7 @@ class ScopeNameCompiler : public PICStubCompiler return true; } - RootedShape shape(cx, getprop.shape); + Shape *shape = getprop.shape; Rooted normalized(cx, obj); if (obj->isWith() && !shape->hasDefaultGetter()) normalized = &obj->asWith().object(); diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index a726fadf2bee..49cde6c015c7 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -193,7 +193,7 @@ stubs::ImplicitThis(VMFrame &f, PropertyName *name_) RootedPropertyName name(f.cx, name_); RootedObject obj(f.cx), obj2(f.cx); - RootedShape prop(f.cx); + JSProperty *prop; if (!FindPropertyHelper(f.cx, name, false, scopeObj, &obj, &obj2, &prop)) THROW(); @@ -338,16 +338,16 @@ stubs::DefFun(VMFrame &f, JSFunction *fun_) /* ES5 10.5 (NB: with subsequent errata). */ PropertyName *name = fun->atom->asPropertyName(); - RootedShape shape(cx); + JSProperty *prop = NULL; RootedObject pobj(cx); - if (!parent->lookupProperty(cx, name, &pobj, &shape)) + if (!parent->lookupProperty(cx, name, &pobj, &prop)) THROW(); Value rval = ObjectValue(*fun); do { /* Steps 5d, 5f. */ - if (!shape || pobj != parent) { + if (!prop || pobj != parent) { if (!parent->defineProperty(cx, name, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs)) { @@ -358,6 +358,7 @@ stubs::DefFun(VMFrame &f, JSFunction *fun_) /* Step 5e. */ JS_ASSERT(parent->isNative()); + Shape *shape = reinterpret_cast(prop); if (parent->isGlobal()) { if (shape->configurable()) { if (!parent->defineProperty(cx, name, rval, @@ -1338,7 +1339,7 @@ stubs::DelName(VMFrame &f, PropertyName *name_) RootedPropertyName name(f.cx, name_); RootedObject obj(f.cx), obj2(f.cx); - RootedShape prop(f.cx); + JSProperty *prop; if (!FindProperty(f.cx, name, scopeObj, &obj, &obj2, &prop)) THROW(); @@ -1438,7 +1439,7 @@ stubs::In(VMFrame &f) THROWV(JS_FALSE); RootedObject obj2(cx); - RootedShape prop(cx); + JSProperty *prop; if (!obj->lookupGeneric(cx, id, &obj2, &prop)) THROWV(JS_FALSE); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index c4b832278ec7..9b32c591ede7 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -2689,18 +2689,19 @@ static JSBool CopyProperty(JSContext *cx, HandleObject obj, HandleObject referent, HandleId id, unsigned lookupFlags, MutableHandleObject objp) { - RootedShape shape(cx); + JSProperty *prop; PropertyDescriptor desc; unsigned propFlags = 0; RootedObject obj2(cx); objp.set(NULL); if (referent->isNative()) { - if (!LookupPropertyWithFlags(cx, referent, id, lookupFlags, &obj2, &shape)) + if (!LookupPropertyWithFlags(cx, referent, id, lookupFlags, &obj2, &prop)) return false; if (obj2 != referent) return true; + const Shape *shape = (Shape *) prop; if (shape->hasSlot()) { desc.value = referent->nativeGetSlot(shape->slot()); } else { @@ -2723,7 +2724,7 @@ CopyProperty(JSContext *cx, HandleObject obj, HandleObject referent, HandleId id if (!desc.obj) return true; } else { - if (!referent->lookupGeneric(cx, id, objp, &shape)) + if (!referent->lookupGeneric(cx, id, objp, &prop)) return false; if (objp != referent) return true; diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp index b9e661e53c26..d246a4d703d3 100644 --- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -259,7 +259,7 @@ args_enumerate(JSContext *cx, HandleObject obj) : INT_TO_JSID(i); RootedObject pobj(cx); - RootedShape prop(cx); + JSProperty *prop; if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; } @@ -369,7 +369,7 @@ strictargs_enumerate(JSContext *cx, HandleObject obj) * js_LookupProperty calls. */ RootedObject pobj(cx); - RootedShape prop(cx); + JSProperty *prop; RootedId id(cx); // length diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 3927e93e38f8..d11d4a70c4ab 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -4413,7 +4413,7 @@ DebuggerEnv_find(JSContext *cx, unsigned argc, Value *vp) /* This can trigger resolve hooks. */ ErrorCopier ec(ac, dbg->toJSObject()); - RootedShape prop(cx); + JSProperty *prop = NULL; RootedObject pobj(cx); for (; env && !prop; env = env->enclosingScope()) { if (!env->lookupGeneric(cx, id, &pobj, &prop)) diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index b4de1e3355e9..4bb2f5286bc5 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -351,22 +351,22 @@ WithObject::create(JSContext *cx, HandleObject proto, HandleObject enclosing, ui static JSBool with_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { return obj->asWith().object().lookupGeneric(cx, id, objp, propp); } static JSBool with_LookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, NameToId(name)); return with_LookupGeneric(cx, obj, id, objp, propp); } static JSBool -with_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp) +with_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, + JSProperty **propp) { RootedId id(cx); if (!IndexToId(cx, index, id.address())) @@ -376,7 +376,7 @@ with_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, static JSBool with_LookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, JSProperty **propp) { Rooted id(cx, SPECIALID_TO_JSID(sid)); return with_LookupGeneric(cx, obj, id, objp, propp); From 34f16420f2399111bfc1dec3e84da092ddd5de22 Mon Sep 17 00:00:00 2001 From: Mark Banner Date: Thu, 5 Jul 2012 08:42:03 +0100 Subject: [PATCH 08/31] Bug 766264 Fix test failures in test_0201_app_launch_apply_update.js and test_0203_app_launch_apply_update.js when MOZ_MAINTENANCE_SERVICE isn't set for the build by correctly handling the applied state value. Also tidy up some error statements to provide better debug. r=ehsan --- toolkit/mozapps/update/test/Makefile.in | 4 ++++ toolkit/mozapps/update/test/unit/head_update.js.in | 4 ++++ .../test/unit/test_0200_app_launch_apply_update.js | 4 ++-- .../test/unit/test_0201_app_launch_apply_update.js | 4 ++-- .../test/unit/test_0203_app_launch_apply_update.js | 4 ++-- .../unit/test_0200_app_launch_apply_update_svc.js | 2 +- .../unit/test_0201_app_launch_apply_update_svc.js | 12 ++++++------ .../unit/test_0203_app_launch_apply_update_svc.js | 4 ++-- 8 files changed, 23 insertions(+), 15 deletions(-) diff --git a/toolkit/mozapps/update/test/Makefile.in b/toolkit/mozapps/update/test/Makefile.in index f3c0cbc3d18e..eaecc990c8b8 100644 --- a/toolkit/mozapps/update/test/Makefile.in +++ b/toolkit/mozapps/update/test/Makefile.in @@ -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 = \ diff --git a/toolkit/mozapps/update/test/unit/head_update.js.in b/toolkit/mozapps/update/test/unit/head_update.js.in index 3ae2251da137..a5860ad0e762 100644 --- a/toolkit/mozapps/update/test/unit/head_update.js.in +++ b/toolkit/mozapps/update/test/unit/head_update.js.in @@ -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. diff --git a/toolkit/mozapps/update/test/unit/test_0200_app_launch_apply_update.js b/toolkit/mozapps/update/test/unit/test_0200_app_launch_apply_update.js index 5d5dffd17385..8690d18d0235 100644 --- a/toolkit/mozapps/update/test/unit/test_0200_app_launch_apply_update.js +++ b/toolkit/mozapps/update/test/unit/test_0200_app_launch_apply_update.js @@ -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; diff --git a/toolkit/mozapps/update/test/unit/test_0201_app_launch_apply_update.js b/toolkit/mozapps/update/test/unit/test_0201_app_launch_apply_update.js index 8b68250d08d4..0f1bbd083946 100644 --- a/toolkit/mozapps/update/test/unit/test_0201_app_launch_apply_update.js +++ b/toolkit/mozapps/update/test/unit/test_0201_app_launch_apply_update.js @@ -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; diff --git a/toolkit/mozapps/update/test/unit/test_0203_app_launch_apply_update.js b/toolkit/mozapps/update/test/unit/test_0203_app_launch_apply_update.js index 43b18288a5e8..c7862ffe9186 100644 --- a/toolkit/mozapps/update/test/unit/test_0203_app_launch_apply_update.js +++ b/toolkit/mozapps/update/test/unit/test_0203_app_launch_apply_update.js @@ -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; diff --git a/toolkit/mozapps/update/test_svc/unit/test_0200_app_launch_apply_update_svc.js b/toolkit/mozapps/update/test_svc/unit/test_0200_app_launch_apply_update_svc.js index ab25c45f2b2e..02fa71f7fe1b 100644 --- a/toolkit/mozapps/update/test_svc/unit/test_0200_app_launch_apply_update_svc.js +++ b/toolkit/mozapps/update/test_svc/unit/test_0200_app_launch_apply_update_svc.js @@ -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; diff --git a/toolkit/mozapps/update/test_svc/unit/test_0201_app_launch_apply_update_svc.js b/toolkit/mozapps/update/test_svc/unit/test_0201_app_launch_apply_update_svc.js index a44ba3610989..df176e9a03c9 100644 --- a/toolkit/mozapps/update/test_svc/unit/test_0201_app_launch_apply_update_svc.js +++ b/toolkit/mozapps/update/test_svc/unit/test_0201_app_launch_apply_update_svc.js @@ -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); diff --git a/toolkit/mozapps/update/test_svc/unit/test_0203_app_launch_apply_update_svc.js b/toolkit/mozapps/update/test_svc/unit/test_0203_app_launch_apply_update_svc.js index a8d2735b805f..c4547269ecbc 100644 --- a/toolkit/mozapps/update/test_svc/unit/test_0203_app_launch_apply_update_svc.js +++ b/toolkit/mozapps/update/test_svc/unit/test_0203_app_launch_apply_update_svc.js @@ -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; From 38991b7fd2b6255e9e0577d9618bd3331c76ddc9 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Thu, 5 Jul 2012 10:20:07 +0200 Subject: [PATCH 09/31] Bug 764436 - Shared code;r=taras --- toolkit/components/osfile/osfile_shared.jsm | 141 ++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/toolkit/components/osfile/osfile_shared.jsm b/toolkit/components/osfile/osfile_shared.jsm index d4011028c1c1..5f09412c709b 100644 --- a/toolkit/components/osfile/osfile_shared.jsm +++ b/toolkit/components/osfile/osfile_shared.jsm @@ -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 * From fd60ea71313724de8b13e261a14a4eb17edac941 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Thu, 5 Jul 2012 10:20:19 +0200 Subject: [PATCH 10/31] Bug 764436 - Unix back-end;r=taras --- .../components/osfile/osfile_unix_back.jsm | 85 ++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/toolkit/components/osfile/osfile_unix_back.jsm b/toolkit/components/osfile/osfile_unix_back.jsm index fa3bd7700936..b8769b057b95 100644 --- a/toolkit/components/osfile/osfile_unix_back.jsm +++ b/toolkit/components/osfile/osfile_unix_back.jsm @@ -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, From e6435169a7d7b1656278120121b35817b92f2cd6 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Thu, 5 Jul 2012 10:20:30 +0200 Subject: [PATCH 11/31] Bug 764436 - Unix front-end;r=taras --- .../components/osfile/osfile_unix_front.jsm | 122 +++++++++++++++++- 1 file changed, 117 insertions(+), 5 deletions(-) diff --git a/toolkit/components/osfile/osfile_unix_front.jsm b/toolkit/components/osfile/osfile_unix_front.jsm index fd524410032b..f21f415efced 100644 --- a/toolkit/components/osfile/osfile_unix_front.jsm +++ b/toolkit/components/osfile/osfile_unix_front.jsm @@ -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; From 5290f7e64ad7b1f0d39ee16407510ff5dd324772 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Thu, 5 Jul 2012 10:20:38 +0200 Subject: [PATCH 12/31] Bug 764436 - Directory-related constants;r=taras --- dom/system/OSFileConstants.cpp | 58 ++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/dom/system/OSFileConstants.cpp b/dom/system/OSFileConstants.cpp index dac4de9282dc..5ae2128c395c 100644 --- a/dom/system/OSFileConstants.cpp +++ b/dom/system/OSFileConstants.cpp @@ -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 }; From d37c316908760853782c0cf610362e6ae95242c9 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Thu, 5 Jul 2012 10:20:52 +0200 Subject: [PATCH 13/31] Bug 764436 - Companion test suite;r=taras --- .../tests/mochi/worker_test_osfile_front.js | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js index 2a8d59805011..e0e8d25130dd 100644 --- a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js +++ b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js @@ -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"); +} From effd10ae591090ffc81b9fd9890197fb72e0e110 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Thu, 5 Jul 2012 10:21:00 +0200 Subject: [PATCH 14/31] Bug 764436 - Windows front-end;r=taras --- .../components/osfile/osfile_win_front.jsm | 220 +++++++++++++++++- 1 file changed, 219 insertions(+), 1 deletion(-) diff --git a/toolkit/components/osfile/osfile_win_front.jsm b/toolkit/components/osfile/osfile_win_front.jsm index cc0bf93303e9..24bff84fd227 100644 --- a/toolkit/components/osfile/osfile_win_front.jsm +++ b/toolkit/components/osfile/osfile_win_front.jsm @@ -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() { From 2ae8a6e46aeafbee64367611251968ac38434fd7 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Thu, 5 Jul 2012 10:21:09 +0200 Subject: [PATCH 15/31] Bug 764436 - Windows back-end;r=taras --- toolkit/components/osfile/osfile_shared.jsm | 4 + toolkit/components/osfile/osfile_win_back.jsm | 84 +++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/toolkit/components/osfile/osfile_shared.jsm b/toolkit/components/osfile/osfile_shared.jsm index 5f09412c709b..8931234ef776 100644 --- a/toolkit/components/osfile/osfile_shared.jsm +++ b/toolkit/components/osfile/osfile_shared.jsm @@ -614,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 diff --git a/toolkit/components/osfile/osfile_win_back.jsm b/toolkit/components/osfile/osfile_win_back.jsm index 6bbf10839edc..cab600984035 100644 --- a/toolkit/components/osfile/osfile_win_back.jsm +++ b/toolkit/components/osfile/osfile_win_back.jsm @@ -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, From ff25e344eb333781af7dcbb21eddbb449b5362ab Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Thu, 5 Jul 2012 12:12:09 +0200 Subject: [PATCH 16/31] Bug 669603 - Part 1 - Add MODE_RDWR to FileUtils.jsm; r=ted --- toolkit/mozapps/shared/FileUtils.jsm | 1 + 1 file changed, 1 insertion(+) diff --git a/toolkit/mozapps/shared/FileUtils.jsm b/toolkit/mozapps/shared/FileUtils.jsm index ce2d9b9d08c1..72c0b9bdc7ab 100644 --- a/toolkit/mozapps/shared/FileUtils.jsm +++ b/toolkit/mozapps/shared/FileUtils.jsm @@ -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, From 7d954a7579832ef25d18705facaa6b016230ee2d Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Thu, 5 Jul 2012 12:12:55 +0200 Subject: [PATCH 17/31] Bug 669603 - Part 2 - Add sessionStorage helpers to nsIDocShell; r=smaug,mayhemer --- docshell/base/nsDocShell.cpp | 31 +++++++++++++++++++++++++++++++ docshell/base/nsIDocShell.idl | 15 ++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index c497410e776e..bbd275d4a3f9 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -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(aUserArg); + nsCOMPtr pistorage = do_QueryInterface(aStorage); + + if (pistorage) { + nsCOMPtr 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) { diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index 8c74e1ea2f11..c19e63afb042 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -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 From 870e9d272170105b8441f97f7476f41efa68e145 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sun, 10 Jun 2012 22:23:17 +0200 Subject: [PATCH 18/31] Bug 635498 - Make behaves like . r=sicking --HG-- extra : rebase_source : 0754f845fd6223cd48ca8908ebf642636f0fd9ed --- content/events/src/nsEventStateManager.cpp | 1 + content/html/content/public/nsIFormControl.h | 3 +++ .../html/content/src/nsHTMLFormElement.cpp | 1 + .../html/content/src/nsHTMLInputElement.cpp | 23 +++++++++++++++++-- .../test_input_attributes_reflection.html | 4 ++-- .../test/forms/test_mozistextfield.html | 5 +--- .../test/forms/test_pattern_attribute.html | 6 ++--- .../test/forms/test_required_attribute.html | 9 +++++--- content/html/content/test/test_bug549475.html | 4 ++-- .../src/nsWebBrowserPersist.cpp | 1 + layout/base/nsCSSFrameConstructor.cpp | 2 ++ .../satchel/test/test_form_autocomplete.html | 16 ++++++++++--- 12 files changed, 56 insertions(+), 19 deletions(-) diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 387eeb343d26..62b689e34d00 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -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 || diff --git a/content/html/content/public/nsIFormControl.h b/content/html/content/public/nsIFormControl.h index 07231fbaeb73..3d89ada5535a 100644 --- a/content/html/content/public/nsIFormControl.h +++ b/content/html/content/public/nsIFormControl.h @@ -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); } diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index 54ee721c3737..bd842291ea03 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -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 : diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 8aa443f316ff..e9df44380d06 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -119,6 +119,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 +131,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; @@ -646,6 +647,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. @@ -1097,6 +1099,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 +2182,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); @@ -3068,6 +3077,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(); @@ -3245,6 +3255,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 +3480,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 +3524,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 +3560,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,6 +3575,11 @@ 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); } diff --git a/content/html/content/test/forms/test_input_attributes_reflection.html b/content/html/content/test/forms/test_input_attributes_reflection.html index b15f305ef708..806ac4d028a6 100644 --- a/content/html/content/test/forms/test_input_attributes_reflection.html +++ b/content/html/content/test/forms/test_input_attributes_reflection.html @@ -181,11 +181,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 diff --git a/content/html/content/test/forms/test_mozistextfield.html b/content/html/content/test/forms/test_mozistextfield.html index dcdec0795235..87c051939317 100644 --- a/content/html/content/test/forms/test_mozistextfield.html +++ b/content/html/content/test/forms/test_mozistextfield.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], diff --git a/content/html/content/test/forms/test_pattern_attribute.html b/content/html/content/test/forms/test_pattern_attribute.html index c8210e4f9026..b7c0ef02a8b5 100644 --- a/content/html/content/test/forms/test_pattern_attribute.html +++ b/content/html/content/test/forms/test_pattern_attribute.html @@ -261,10 +261,10 @@ 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. for each (type in validTypes) { input.type = type; diff --git a/content/html/content/test/forms/test_required_attribute.html b/content/html/content/test/forms/test_required_attribute.html index 136dbe5228cd..5f33731cf467 100644 --- a/content/html/content/test/forms/test_required_attribute.html +++ b/content/html/content/test/forms/test_required_attribute.html @@ -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); diff --git a/content/html/content/test/test_bug549475.html b/content/html/content/test/test_bug549475.html index 54618c33439e..53da922d10de 100644 --- a/content/html/content/test/test_bug549475.html +++ b/content/html/content/test/test_bug549475.html @@ -30,7 +30,7 @@ var inputTypes = var todoTypes = [ - "number", "range", "color", + "range", "color", "date", "month", "week", "time", "datetime", "datetime-local", ]; @@ -60,7 +60,7 @@ function sanitizeValue(aType, aValue) // TODO: write the sanitize algorithm. return ""; case "number": - // TODO: write the sanitize algorithm. + todo(false, "will be done with bug 635281"); return ""; case "range": // TODO: write the sanitize algorithm. diff --git a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp index 3614cd5ba30b..671ca04805c6 100644 --- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp +++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp @@ -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()) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 222ecd15cffb..7523c21e5358 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -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) }, diff --git a/toolkit/components/satchel/test/test_form_autocomplete.html b/toolkit/components/satchel/test/test_form_autocomplete.html index 2c1b4bc0a0b2..8583f0e10879 100644 --- a/toolkit/components/satchel/test/test_form_autocomplete.html +++ b/toolkit/components/satchel/test/test_form_autocomplete.html @@ -80,8 +80,14 @@ Form History test: form field autocomplete - +
+ + +
+ + +
@@ -127,11 +133,12 @@ fh.addEntry("field6", "value"); fh.addEntry("field7", "value"); fh.addEntry("field8", "value"); fh.addEntry("field9", "value"); +fh.addEntry("field10", "value"); 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; @@ -698,6 +705,7 @@ function runTest(testNum) { case 401: case 402: case 403: + case 404: checkMenuEntries(["value"]); doKey("down"); doKey("return"); @@ -710,6 +718,8 @@ function runTest(testNum) { } else if (testNum == 402) { input = $_(11, "field9"); } else if (testNum == 403) { + input = $_(12, "field10"); + } else if (testNum == 404) { // Go to test 500. fh.addEntry("field1", "value1"); input = $_(1, "field1"); @@ -738,7 +748,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(""); From cc34abdfb9de8957739a8474b018b71884feda4b Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sun, 10 Jun 2012 22:24:03 +0200 Subject: [PATCH 19/31] Bug 635281 - Implement the value sanitizing algorithm for . r=sicking --HG-- extra : rebase_source : b4ca5ff2b2ce873012ba3a8e589130123eb40559 --- .../html/content/src/nsHTMLInputElement.cpp | 9 ++++++++ content/html/content/test/test_bug549475.html | 11 ++++++--- .../satchel/test/test_form_autocomplete.html | 23 +++++++++++++------ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index e9df44380d06..f9fba9883421 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -2459,6 +2459,15 @@ nsHTMLInputElement::SanitizeValue(nsAString& aValue) aValue = nsContentUtils::TrimWhitespace(aValue); } break; + case NS_FORM_INPUT_NUMBER: + { + PRInt32 ec; + PromiseFlatString(aValue).ToDouble(&ec); + if (NS_FAILED(ec)) { + aValue.Truncate(); + } + } + break; } } diff --git a/content/html/content/test/test_bug549475.html b/content/html/content/test/test_bug549475.html index 53da922d10de..3c6bb47ead94 100644 --- a/content/html/content/test/test_bug549475.html +++ b/content/html/content/test/test_bug549475.html @@ -25,7 +25,7 @@ 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 = @@ -60,8 +60,7 @@ function sanitizeValue(aType, aValue) // TODO: write the sanitize algorithm. return ""; case "number": - todo(false, "will be done with bug 635281"); - 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) { diff --git a/toolkit/components/satchel/test/test_form_autocomplete.html b/toolkit/components/satchel/test/test_form_autocomplete.html index 8583f0e10879..cea5efc7dee2 100644 --- a/toolkit/components/satchel/test/test_form_autocomplete.html +++ b/toolkit/components/satchel/test/test_form_autocomplete.html @@ -133,7 +133,7 @@ fh.addEntry("field6", "value"); fh.addEntry("field7", "value"); fh.addEntry("field8", "value"); fh.addEntry("field9", "value"); -fh.addEntry("field10", "value"); +fh.addEntry("field10", "42"); fh.addEntry("searchbar-history", "blacklist test"); // All these non-implemeted types might need autocomplete tests in the future. @@ -705,7 +705,6 @@ function runTest(testNum) { case 401: case 402: case 403: - case 404: checkMenuEntries(["value"]); doKey("down"); doKey("return"); @@ -719,17 +718,27 @@ function runTest(testNum) { input = $_(11, "field9"); } else if (testNum == 403) { input = $_(12, "field10"); - } else if (testNum == 404) { - // Go to test 500. - fh.addEntry("field1", "value1"); - input = $_(1, "field1"); - testNum = 499; } 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) { From ab5c9037ba45edb4306cd61075965b3d129800c0 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Thu, 5 Jul 2012 12:11:31 +0200 Subject: [PATCH 20/31] Bug 635499 (1/2) - Add the max attribute to HTMLInputElement. r=sicking --HG-- extra : rebase_source : 4244148c48e837750bb12d809596d8ec18155f73 --- content/html/content/src/nsHTMLInputElement.cpp | 1 + .../content/test/forms/test_input_attributes_reflection.html | 5 ++++- dom/interfaces/html/nsIDOMHTMLInputElement.idl | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index f9fba9883421..6b0a57a7cb0e 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -838,6 +838,7 @@ 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_ACTION_ATTR(nsHTMLInputElement, FormAction, formaction) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormEnctype, formenctype, kFormDefaultEnctype->tag) diff --git a/content/html/content/test/forms/test_input_attributes_reflection.html b/content/html/content/test/forms/test_input_attributes_reflection.html index 806ac4d028a6..fbb45aade28f 100644 --- a/content/html/content/test/forms/test_input_attributes_reflection.html +++ b/content/html/content/test/forms/test_input_attributes_reflection.html @@ -111,7 +111,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({ diff --git a/dom/interfaces/html/nsIDOMHTMLInputElement.idl b/dom/interfaces/html/nsIDOMHTMLInputElement.idl index 17fc3ea9828c..5bf46c4b51c5 100644 --- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl @@ -20,7 +20,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(ac2e2b14-b987-452c-a071-5823b2406b85)] +[scriptable, uuid(23d5399b-004e-469b-a735-d89009ffe9a6)] interface nsIDOMHTMLInputElement : nsIDOMHTMLElement { attribute DOMString accept; @@ -44,6 +44,7 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement attribute boolean indeterminate; readonly attribute nsIDOMHTMLElement list; + attribute DOMString max; attribute long maxLength; attribute boolean multiple; From d7b22376e51a2fff0c970d454a15df90d615cc7b Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Fri, 22 Jun 2012 11:36:24 +0200 Subject: [PATCH 21/31] Bug 635499 (2/2) - can suffer from a range overflow when @max is set. r=sicking --HG-- extra : rebase_source : 8d5a589b3ab4018de422fb92ab436afc5a083fb7 --- .../html/content/src/nsHTMLInputElement.cpp | 105 ++++++++++++ content/html/content/src/nsHTMLInputElement.h | 15 ++ .../content/src/nsIConstraintValidation.cpp | 2 + content/html/content/test/forms/Makefile.in | 1 + .../test/forms/test_max_attribute.html | 152 ++++++++++++++++++ dom/locales/en-US/chrome/dom/dom.properties | 2 + 6 files changed, 277 insertions(+) create mode 100644 content/html/content/test/forms/test_max_attribute.html diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 6b0a57a7cb0e..547def238e1a 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -90,6 +90,8 @@ #include "nsIIDNService.h" +#include + using namespace mozilla; using namespace mozilla::dom; @@ -811,6 +813,8 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, UpdatePatternMismatchValidityState(); } else if (aName == nsGkAtoms::multiple) { UpdateTypeMismatchValidityState(); + } else if (aName == nsGkAtoms::max) { + UpdateRangeOverflowValidityState(); } UpdateState(aNotify); @@ -975,6 +979,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::quiet_NaN() + : doubleValue; +} + NS_IMETHODIMP nsHTMLInputElement::SetValue(const nsAString& aValue) { @@ -3593,6 +3611,42 @@ nsHTMLInputElement::DoesPatternApply() const 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 + } +} + // nsIConstraintValidation NS_IMETHODIMP @@ -3721,6 +3775,30 @@ 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; +} + void nsHTMLInputElement::UpdateTooLongValidityState() { @@ -3799,6 +3877,12 @@ nsHTMLInputElement::UpdatePatternMismatchValidityState() SetValidityState(VALIDITY_STATE_PATTERN_MISMATCH, HasPatternMismatch()); } +void +nsHTMLInputElement::UpdateRangeOverflowValidityState() +{ + SetValidityState(VALIDITY_STATE_RANGE_OVERFLOW, IsRangeOverflow()); +} + void nsHTMLInputElement::UpdateAllValidityStates(bool aNotify) { @@ -3807,6 +3891,7 @@ nsHTMLInputElement::UpdateAllValidityStates(bool aNotify) UpdateValueMissingValidityState(); UpdateTypeMismatchValidityState(); UpdatePatternMismatchValidityState(); + UpdateRangeOverflowValidityState(); if (validBefore != IsValid()) { UpdateState(aNotify); @@ -3914,6 +3999,26 @@ 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; + } default: rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType); } diff --git a/content/html/content/src/nsHTMLInputElement.h b/content/html/content/src/nsHTMLInputElement.h index 956ed062a22d..015ef1110f0f 100644 --- a/content/html/content/src/nsHTMLInputElement.h +++ b/content/html/content/src/nsHTMLInputElement.h @@ -216,10 +216,12 @@ public: bool IsValueMissing() const; bool HasTypeMismatch() const; bool HasPatternMismatch() const; + bool IsRangeOverflow() const; void UpdateTooLongValidityState(); void UpdateValueMissingValidityState(); void UpdateTypeMismatchValidityState(); void UpdatePatternMismatchValidityState(); + void UpdateRangeOverflowValidityState(); void UpdateAllValidityStates(bool aNotify); void UpdateBarredFromConstraintValidation(); nsresult GetValidationMessage(nsAString& aValidationMessage, @@ -463,6 +465,11 @@ protected: */ bool DoesPatternApply() const; + /** + * Returns if the min and max attributes apply for the current type. + */ + bool DoesMinMaxApply() const; + /** * Returns if the maxlength attribute applies for the current type. */ @@ -533,6 +540,14 @@ 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; + nsCOMPtr mControllers; /* diff --git a/content/html/content/src/nsIConstraintValidation.cpp b/content/html/content/src/nsIConstraintValidation.cpp index 2a87a0dc7758..1a377ccc480a 100644 --- a/content/html/content/src/nsIConstraintValidation.cpp +++ b/content/html/content/src/nsIConstraintValidation.cpp @@ -72,6 +72,8 @@ 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 { // TODO: The other messages have not been written // because related constraint validation are not implemented yet. diff --git a/content/html/content/test/forms/Makefile.in b/content/html/content/test/forms/Makefile.in index 20105b00602a..9e455ff4d2eb 100644 --- a/content/html/content/test/forms/Makefile.in +++ b/content/html/content/test/forms/Makefile.in @@ -42,6 +42,7 @@ _TEST_FILES = \ test_option_disabled.html \ test_meter_element.html \ test_meter_pseudo-classes.html \ + test_max_attribute.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/forms/test_max_attribute.html b/content/html/content/test/forms/test_max_attribute.html new file mode 100644 index 000000000000..400787acd690 --- /dev/null +++ b/content/html/content/test/forms/test_max_attribute.html @@ -0,0 +1,152 @@ + + + + + Test for Bug 635499 + + + + + +Mozilla Bug 635499 +

+ +
+
+
+ + diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index e43a732fbba7..de292d089652 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -40,6 +40,8 @@ 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. 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. From 42f9886c6f50a7d266566d6d9f6904c7a6ab426f Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Thu, 5 Jul 2012 12:11:53 +0200 Subject: [PATCH 22/31] Bug 635553 (1/2) - Add the min attribute to HTMLInputElement. r=sicking --HG-- extra : rebase_source : 071c211fde723cb8d79f5d85bab58d8ef2631f66 --- content/html/content/src/nsHTMLInputElement.cpp | 1 + .../content/test/forms/test_input_attributes_reflection.html | 5 ++++- dom/interfaces/html/nsIDOMHTMLInputElement.idl | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 547def238e1a..183e7a697731 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -843,6 +843,7 @@ 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) diff --git a/content/html/content/test/forms/test_input_attributes_reflection.html b/content/html/content/test/forms/test_input_attributes_reflection.html index fbb45aade28f..94b1a32490bc 100644 --- a/content/html/content/test/forms/test_input_attributes_reflection.html +++ b/content/html/content/test/forms/test_input_attributes_reflection.html @@ -124,7 +124,10 @@ reflectInt({ }); // .min -todo("min" in document.createElement("input"), "min isn't implemented yet"); +reflectString({ + element: document.createElement('input'), + attribute: 'min', +}); // .multiple reflectBoolean({ diff --git a/dom/interfaces/html/nsIDOMHTMLInputElement.idl b/dom/interfaces/html/nsIDOMHTMLInputElement.idl index 5bf46c4b51c5..1c94d43038d3 100644 --- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl @@ -20,7 +20,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(23d5399b-004e-469b-a735-d89009ffe9a6)] +[scriptable, uuid(261b0fa1-dfcc-445d-8ac8-6b3817ec63cb)] interface nsIDOMHTMLInputElement : nsIDOMHTMLElement { attribute DOMString accept; @@ -46,6 +46,7 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement readonly attribute nsIDOMHTMLElement list; attribute DOMString max; attribute long maxLength; + attribute DOMString min; attribute boolean multiple; attribute DOMString name; From 5362c65903bfb2b6bd8a48f235e5c0d5f135139a Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Fri, 22 Jun 2012 11:38:20 +0200 Subject: [PATCH 23/31] Bug 635553 (2/2) - can suffer from a range underflow when @min is set. r=sicking --HG-- extra : rebase_source : 27045996c62489b28c799d11b6cee5f5df3a2359 --- .../html/content/src/nsHTMLInputElement.cpp | 53 ++++++ content/html/content/src/nsHTMLInputElement.h | 2 + .../content/src/nsIConstraintValidation.cpp | 2 + content/html/content/test/forms/Makefile.in | 1 + .../test/forms/test_min_attribute.html | 152 ++++++++++++++++++ dom/locales/en-US/chrome/dom/dom.properties | 2 + 6 files changed, 212 insertions(+) create mode 100644 content/html/content/test/forms/test_min_attribute.html diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 183e7a697731..fc57c148343e 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -815,6 +815,8 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, UpdateTypeMismatchValidityState(); } else if (aName == nsGkAtoms::max) { UpdateRangeOverflowValidityState(); + } else if (aName == nsGkAtoms::min) { + UpdateRangeUnderflowValidityState(); } UpdateState(aNotify); @@ -3800,6 +3802,30 @@ nsHTMLInputElement::IsRangeOverflow() const 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; +} + void nsHTMLInputElement::UpdateTooLongValidityState() { @@ -3884,6 +3910,12 @@ nsHTMLInputElement::UpdateRangeOverflowValidityState() SetValidityState(VALIDITY_STATE_RANGE_OVERFLOW, IsRangeOverflow()); } +void +nsHTMLInputElement::UpdateRangeUnderflowValidityState() +{ + SetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW, IsRangeUnderflow()); +} + void nsHTMLInputElement::UpdateAllValidityStates(bool aNotify) { @@ -3893,6 +3925,7 @@ nsHTMLInputElement::UpdateAllValidityStates(bool aNotify) UpdateTypeMismatchValidityState(); UpdatePatternMismatchValidityState(); UpdateRangeOverflowValidityState(); + UpdateRangeUnderflowValidityState(); if (validBefore != IsValid()) { UpdateState(aNotify); @@ -4020,6 +4053,26 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage, 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; + } default: rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType); } diff --git a/content/html/content/src/nsHTMLInputElement.h b/content/html/content/src/nsHTMLInputElement.h index 015ef1110f0f..3981803d4904 100644 --- a/content/html/content/src/nsHTMLInputElement.h +++ b/content/html/content/src/nsHTMLInputElement.h @@ -217,11 +217,13 @@ public: bool HasTypeMismatch() const; bool HasPatternMismatch() const; bool IsRangeOverflow() const; + bool IsRangeUnderflow() const; void UpdateTooLongValidityState(); void UpdateValueMissingValidityState(); void UpdateTypeMismatchValidityState(); void UpdatePatternMismatchValidityState(); void UpdateRangeOverflowValidityState(); + void UpdateRangeUnderflowValidityState(); void UpdateAllValidityStates(bool aNotify); void UpdateBarredFromConstraintValidation(); nsresult GetValidationMessage(nsAString& aValidationMessage, diff --git a/content/html/content/src/nsIConstraintValidation.cpp b/content/html/content/src/nsIConstraintValidation.cpp index 1a377ccc480a..24919a626df2 100644 --- a/content/html/content/src/nsIConstraintValidation.cpp +++ b/content/html/content/src/nsIConstraintValidation.cpp @@ -74,6 +74,8 @@ nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage) 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 { // TODO: The other messages have not been written // because related constraint validation are not implemented yet. diff --git a/content/html/content/test/forms/Makefile.in b/content/html/content/test/forms/Makefile.in index 9e455ff4d2eb..81a71feadb77 100644 --- a/content/html/content/test/forms/Makefile.in +++ b/content/html/content/test/forms/Makefile.in @@ -43,6 +43,7 @@ _TEST_FILES = \ test_meter_element.html \ test_meter_pseudo-classes.html \ test_max_attribute.html \ + test_min_attribute.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/forms/test_min_attribute.html b/content/html/content/test/forms/test_min_attribute.html new file mode 100644 index 000000000000..7e0af0bf58ee --- /dev/null +++ b/content/html/content/test/forms/test_min_attribute.html @@ -0,0 +1,152 @@ + + + + + Test for Bug 635553 + + + + + +Mozilla Bug 635499 +

+ +
+
+
+ + diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index de292d089652..77db8becfb46 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -42,6 +42,8 @@ FormValidationPatternMismatch=Please match the requested format. 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. 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. From 0ac84a9cf1aa275817430d2d057f1c1a38e8e166 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Fri, 22 Jun 2012 11:41:32 +0200 Subject: [PATCH 24/31] Bug 635554 (1/2) - Keep track of whether an input element has a range applying. r=sicking --HG-- extra : rebase_source : b1f577c5acaa70da105352e4d682f608cf938010 --- .../html/content/src/nsHTMLInputElement.cpp | 35 +++++++++++++++++++ content/html/content/src/nsHTMLInputElement.h | 6 ++++ 2 files changed, 41 insertions(+) diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index fc57c148343e..ece4979ea1f7 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -525,6 +525,7 @@ nsHTMLInputElement::nsHTMLInputElement(already_AddRefed aNodeInfo, , mInhibitRestoration(aFromParser & FROM_PARSER_FRAGMENT) , mCanShowValidUI(true) , mCanShowInvalidUI(true) + , mHasRange(false) { mInputData.mState = new nsTextEditorState(this); @@ -814,8 +815,10 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, } else if (aName == nsGkAtoms::multiple) { UpdateTypeMismatchValidityState(); } else if (aName == nsGkAtoms::max) { + UpdateHasRange(); UpdateRangeOverflowValidityState(); } else if (aName == nsGkAtoms::min) { + UpdateHasRange(); UpdateRangeUnderflowValidityState(); } @@ -2453,6 +2456,8 @@ nsHTMLInputElement::HandleTypeChange(PRUint8 aNewType) } } + UpdateHasRange(); + // Do not notify, it will be done after if needed. UpdateAllValidityStates(false); } @@ -4499,3 +4504,33 @@ nsHTMLInputElement::UpdateValidityUIBits(bool aIsFocused) } } +void +nsHTMLInputElement::UpdateHasRange() +{ + mHasRange = false; + + if (mType != NS_FORM_INPUT_NUMBER) { + return; + } + + // 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; + } + } +} diff --git a/content/html/content/src/nsHTMLInputElement.h b/content/html/content/src/nsHTMLInputElement.h index 3981803d4904..de737826a5a1 100644 --- a/content/html/content/src/nsHTMLInputElement.h +++ b/content/html/content/src/nsHTMLInputElement.h @@ -550,6 +550,11 @@ protected: */ double GetValueAsDouble() const; + /** + * Update the HAS_RANGE bit field value. + */ + void UpdateHasRange(); + nsCOMPtr mControllers; /* @@ -613,6 +618,7 @@ protected: bool mInhibitRestoration : 1; bool mCanShowValidUI : 1; bool mCanShowInvalidUI : 1; + bool mHasRange : 1; private: struct nsFilePickerFilter { From c3bb27524d6702e72cf2ab8bdbad1d374b85149c Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sat, 9 Jun 2012 19:44:47 +0200 Subject: [PATCH 25/31] Bug 635554 (2/2) - Implement :in-range and :out-of-range for . r=sicking --HG-- extra : rebase_source : 0c107ddf81fc899dfdeb602bcdc3818dd2d3c541 --- .../html/content/src/nsHTMLInputElement.cpp | 8 ++++ .../test/forms/test_max_attribute.html | 41 ++++++++++++------- .../test/forms/test_min_attribute.html | 41 ++++++++++++------- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index ece4979ea1f7..b0ac0ebadeee 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -3262,6 +3262,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; } diff --git a/content/html/content/test/forms/test_max_attribute.html b/content/html/content/test/forms/test_max_attribute.html index 400787acd690..22908606af95 100644 --- a/content/html/content/test/forms/test_max_attribute.html +++ b/content/html/content/test/forms/test_max_attribute.html @@ -48,8 +48,10 @@ var types = [ var input = document.createElement("input"); document.getElementById('content').appendChild(input); -function checkValidity(aElement, aValidity) +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, @@ -63,7 +65,16 @@ function checkValidity(aElement, aValidity) is(aElement.mozMatchesSelector(":invalid"), aElement.willValidate && !aValidity, (aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply"); - // TODO: Add tests for out-of-range / in-range selectors, see bug 635554. + 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); + } } for each (var data in types) { @@ -75,17 +86,17 @@ for each (var data in types) { continue; } - checkValidity(input, true); + checkValidity(input, true, apply, false); input.max = '2'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); if (input.type == 'url') { input.value = 'http://mozilla.org'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); } else if (input.type == 'email') { input.value = 'foo@bar.com'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); } else if (input.type == 'file') { // Need privileges to set a filename with .value. netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); @@ -103,34 +114,34 @@ for each (var data in types) { outStream.close(); input.value = file.path; - checkValidity(input, true); + checkValidity(input, true, apply, apply); file.remove(false); } else { input.value = '1'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); input.value = '2'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); input.value = 'foo'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); input.value = '2.1'; - checkValidity(input, !apply); + checkValidity(input, false, apply, apply); input.max = '5'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); input.value = '42'; - checkValidity(input, !apply); + checkValidity(input, false, apply, apply); } input.max = ''; - checkValidity(input, true); + checkValidity(input, true, apply, false); input.max = 'foo'; - checkValidity(input, true); + checkValidity(input, true, apply, false); // Check that we correctly convert input.max to a double in validationMessage. if (input.type == 'number') { diff --git a/content/html/content/test/forms/test_min_attribute.html b/content/html/content/test/forms/test_min_attribute.html index 7e0af0bf58ee..2f56cb7c4262 100644 --- a/content/html/content/test/forms/test_min_attribute.html +++ b/content/html/content/test/forms/test_min_attribute.html @@ -48,8 +48,10 @@ var types = [ var input = document.createElement("input"); document.getElementById('content').appendChild(input); -function checkValidity(aElement, aValidity) +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, @@ -63,7 +65,16 @@ function checkValidity(aElement, aValidity) is(aElement.mozMatchesSelector(":invalid"), aElement.willValidate && !aValidity, (aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply"); - // TODO: Add tests for out-of-range / in-range selectors, see bug 635554. + 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); + } } for each (var data in types) { @@ -75,17 +86,17 @@ for each (var data in types) { continue; } - checkValidity(input, true); + checkValidity(input, true, apply, false); input.min = '0'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); if (input.type == 'url') { input.value = 'http://mozilla.org'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); } else if (input.type == 'email') { input.value = 'foo@bar.com'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); } else if (input.type == 'file') { // Need privileges to set a filename with .value. netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); @@ -103,34 +114,34 @@ for each (var data in types) { outStream.close(); input.value = file.path; - checkValidity(input, true); + checkValidity(input, true, apply, apply); file.remove(false); } else { input.value = '1'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); input.value = '0'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); input.value = 'foo'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); input.value = '-0.1'; - checkValidity(input, !apply); + checkValidity(input, false, apply, apply); input.min = '-1'; - checkValidity(input, true); + checkValidity(input, true, apply, apply); input.value = '-42'; - checkValidity(input, !apply); + checkValidity(input, false, apply, apply); } input.min = ''; - checkValidity(input, true); + checkValidity(input, true, apply, false); input.min = 'foo'; - checkValidity(input, true); + checkValidity(input, true, apply, false); // Check that we correctly convert input.min to a double in validationMessage. if (input.type == 'number') { From d289e5146ae27c3f58158c79bc4774710fd8ba4e Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Thu, 5 Jul 2012 12:12:14 +0200 Subject: [PATCH 26/31] Bug 556009 (1/2) - Add the step attribute to HTMLInputElement. r=sicking --HG-- extra : rebase_source : 7288832870ee9c6a7964f5f8b3e619c2b2b81c70 --- content/base/src/nsGkAtomList.h | 1 + content/html/content/src/nsHTMLInputElement.cpp | 1 + .../content/test/forms/test_input_attributes_reflection.html | 5 ++++- dom/interfaces/html/nsIDOMHTMLInputElement.idl | 3 ++- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index abce1f00dc28..4824a948b598 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -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") diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index b0ac0ebadeee..f0c4645596a0 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -862,6 +862,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) diff --git a/content/html/content/test/forms/test_input_attributes_reflection.html b/content/html/content/test/forms/test_input_attributes_reflection.html index 94b1a32490bc..ab77ab872a10 100644 --- a/content/html/content/test/forms/test_input_attributes_reflection.html +++ b/content/html/content/test/forms/test_input_attributes_reflection.html @@ -179,7 +179,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({ diff --git a/dom/interfaces/html/nsIDOMHTMLInputElement.idl b/dom/interfaces/html/nsIDOMHTMLInputElement.idl index 1c94d43038d3..9313260b6112 100644 --- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl @@ -20,7 +20,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(261b0fa1-dfcc-445d-8ac8-6b3817ec63cb)] +[scriptable, uuid(e20b7e26-e952-4bba-9192-99bd1a4b3816)] interface nsIDOMHTMLInputElement : nsIDOMHTMLElement { attribute DOMString accept; @@ -55,6 +55,7 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement attribute DOMString placeholder; attribute boolean readOnly; attribute boolean required; + attribute DOMString step; attribute DOMString align; From d09719cb786a2466c9f6a0d6ac55e865f06065f6 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Fri, 22 Jun 2012 21:02:20 +0200 Subject: [PATCH 27/31] Bug 556009 (2/2) - can suffer from a step mismatch when @step is set. r=sicking --HG-- extra : rebase_source : ebe773a2bd9ade8a1a9cd9b4a6a3aa077fad54b2 --- .../html/content/src/nsHTMLInputElement.cpp | 130 +++++++++ content/html/content/src/nsHTMLInputElement.h | 20 ++ .../content/src/nsIConstraintValidation.cpp | 6 +- content/html/content/test/forms/Makefile.in | 1 + .../test/forms/test_max_attribute.html | 2 +- .../test/forms/test_min_attribute.html | 2 +- .../test/forms/test_step_attribute.html | 254 ++++++++++++++++++ dom/locales/en-US/chrome/dom/dom.properties | 4 + 8 files changed, 414 insertions(+), 5 deletions(-) create mode 100644 content/html/content/test/forms/test_step_attribute.html diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index f0c4645596a0..78568dc350f8 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -149,6 +149,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, \ @@ -820,6 +823,9 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, } else if (aName == nsGkAtoms::min) { UpdateHasRange(); UpdateRangeUnderflowValidityState(); + UpdateStepMismatchValidityState(); + } else if (aName == nsGkAtoms::step) { + UpdateStepMismatchValidityState(); } UpdateState(aNotify); @@ -3664,6 +3670,39 @@ nsHTMLInputElement::DoesMinMaxApply() const } } +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 @@ -3840,6 +3879,41 @@ nsHTMLInputElement::IsRangeUnderflow() const 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; + } + + double stepBase = kDefaultStepBase; + + if (HasAttr(kNameSpaceID_None, nsGkAtoms::min)) { + nsAutoString minStr; + GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr); + + PRInt32 ec; + stepBase = minStr.ToDouble(&ec); + if (NS_FAILED(ec)) { + stepBase = kDefaultStepBase; + } + } + + // Value has to be an integral multiple of step. + return fmod(value - stepBase, step) != 0; +} + void nsHTMLInputElement::UpdateTooLongValidityState() { @@ -3930,6 +4004,12 @@ nsHTMLInputElement::UpdateRangeUnderflowValidityState() SetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW, IsRangeUnderflow()); } +void +nsHTMLInputElement::UpdateStepMismatchValidityState() +{ + SetValidityState(VALIDITY_STATE_STEP_MISMATCH, HasStepMismatch()); +} + void nsHTMLInputElement::UpdateAllValidityStates(bool aNotify) { @@ -3940,6 +4020,7 @@ nsHTMLInputElement::UpdateAllValidityStates(bool aNotify) UpdatePatternMismatchValidityState(); UpdateRangeOverflowValidityState(); UpdateRangeUnderflowValidityState(); + UpdateStepMismatchValidityState(); if (validBefore != IsValid()) { UpdateState(aNotify); @@ -4087,6 +4168,55 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage, 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); } diff --git a/content/html/content/src/nsHTMLInputElement.h b/content/html/content/src/nsHTMLInputElement.h index de737826a5a1..9406a0c937e6 100644 --- a/content/html/content/src/nsHTMLInputElement.h +++ b/content/html/content/src/nsHTMLInputElement.h @@ -218,12 +218,14 @@ public: 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, @@ -472,6 +474,11 @@ protected: */ bool DoesMinMaxApply() const; + /** + * Returns if the step attribute apply for the current type. + */ + bool DoesStepApply() const { return DoesMinMaxApply(); } + /** * Returns if the maxlength attribute applies for the current type. */ @@ -555,6 +562,14 @@ protected: */ void UpdateHasRange(); + /** + * Returns the current step value. + * Returns kStepAny if the current step is "any" string. + * + * @return the current step value. + */ + double GetStep() const; + nsCOMPtr mControllers; /* @@ -600,6 +615,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 () as an integer. * @see nsIFormControl.h (specifically NS_FORM_INPUT_*) diff --git a/content/html/content/src/nsIConstraintValidation.cpp b/content/html/content/src/nsIConstraintValidation.cpp index 24919a626df2..9b02c8d6a844 100644 --- a/content/html/content/src/nsIConstraintValidation.cpp +++ b/content/html/content/src/nsIConstraintValidation.cpp @@ -76,10 +76,10 @@ nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage) 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 { diff --git a/content/html/content/test/forms/Makefile.in b/content/html/content/test/forms/Makefile.in index 81a71feadb77..3586a5af1bf6 100644 --- a/content/html/content/test/forms/Makefile.in +++ b/content/html/content/test/forms/Makefile.in @@ -44,6 +44,7 @@ _TEST_FILES = \ test_meter_pseudo-classes.html \ test_max_attribute.html \ test_min_attribute.html \ + test_step_attribute.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/forms/test_max_attribute.html b/content/html/content/test/forms/test_max_attribute.html index 22908606af95..4953038eb2f4 100644 --- a/content/html/content/test/forms/test_max_attribute.html +++ b/content/html/content/test/forms/test_max_attribute.html @@ -127,7 +127,7 @@ for each (var data in types) { input.value = 'foo'; checkValidity(input, true, apply, apply); - input.value = '2.1'; + input.value = '3'; checkValidity(input, false, apply, apply); input.max = '5'; diff --git a/content/html/content/test/forms/test_min_attribute.html b/content/html/content/test/forms/test_min_attribute.html index 2f56cb7c4262..94f98af1c4df 100644 --- a/content/html/content/test/forms/test_min_attribute.html +++ b/content/html/content/test/forms/test_min_attribute.html @@ -127,7 +127,7 @@ for each (var data in types) { input.value = 'foo'; checkValidity(input, true, apply, apply); - input.value = '-0.1'; + input.value = '-1'; checkValidity(input, false, apply, apply); input.min = '-1'; diff --git a/content/html/content/test/forms/test_step_attribute.html b/content/html/content/test/forms/test_step_attribute.html new file mode 100644 index 000000000000..a00d92947400 --- /dev/null +++ b/content/html/content/test/forms/test_step_attribute.html @@ -0,0 +1,254 @@ + + + + + Test for Bug 635553 + + + + + +Mozilla Bug 635499 +

+ +
+
+
+ + diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index 77db8becfb46..7619e2250c35 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -44,6 +44,10 @@ FormValidationPatternMismatchWithTitle=Please match the requested format: %S. 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. From a643785d84771cb4b7fd6a9d9608c1d49991c2f0 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Thu, 5 Jul 2012 16:18:37 +0200 Subject: [PATCH 28/31] Bug 767519 - Add NS_flooredModulo to nsMathUtils. r=bz --HG-- extra : rebase_source : d16e5d8e94a50c1e3319d866e3aa27ae6160edd8 --- xpcom/ds/nsMathUtils.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xpcom/ds/nsMathUtils.h b/xpcom/ds/nsMathUtils.h index 29ffd949b421..4d1af2229864 100644 --- a/xpcom/ds/nsMathUtils.h +++ b/xpcom/ds/nsMathUtils.h @@ -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 From 2e4b9d817ecf9b72480808eb714281151b831da1 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Thu, 5 Jul 2012 16:33:47 +0200 Subject: [PATCH 29/31] Bug 636627 - Implement stepDown() and stepUp() for . r=sicking --HG-- extra : rebase_source : 94d0543e68d5c2aa021e07b8b62d674e280f10dd --- .../html/content/src/nsHTMLInputElement.cpp | 138 ++++++- content/html/content/src/nsHTMLInputElement.h | 28 ++ content/html/content/test/forms/Makefile.in | 1 + .../test/forms/test_stepup_stepdown.html | 347 ++++++++++++++++++ .../html/nsIDOMHTMLInputElement.idl | 5 +- 5 files changed, 504 insertions(+), 15 deletions(-) create mode 100644 content/html/content/test/forms/test_stepup_stepdown.html diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 78568dc350f8..f67d8c78739a 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -1060,6 +1060,129 @@ nsHTMLInputElement::GetList(nsIDOMHTMLElement** aValue) return NS_OK; } +void +nsHTMLInputElement::SetValue(double aValue) +{ + nsAutoString value; + value.AppendFloat(aValue); + SetValue(value); +} + +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::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::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) { @@ -3897,21 +4020,8 @@ nsHTMLInputElement::HasStepMismatch() const return false; } - double stepBase = kDefaultStepBase; - - if (HasAttr(kNameSpaceID_None, nsGkAtoms::min)) { - nsAutoString minStr; - GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr); - - PRInt32 ec; - stepBase = minStr.ToDouble(&ec); - if (NS_FAILED(ec)) { - stepBase = kDefaultStepBase; - } - } - // Value has to be an integral multiple of step. - return fmod(value - stepBase, step) != 0; + return fmod(value - GetStepBase(), step) != 0; } void diff --git a/content/html/content/src/nsHTMLInputElement.h b/content/html/content/src/nsHTMLInputElement.h index 9406a0c937e6..101212142a28 100644 --- a/content/html/content/src/nsHTMLInputElement.h +++ b/content/html/content/src/nsHTMLInputElement.h @@ -479,6 +479,11 @@ protected: */ bool DoesStepApply() const { return DoesMinMaxApply(); } + /** + * Returns if stepDown and stepUp methods apply for the current type. + */ + bool DoStepDownStepUpApply() const { return DoesStepApply(); } + /** * Returns if the maxlength attribute applies for the current type. */ @@ -557,6 +562,13 @@ protected: */ 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. */ @@ -570,6 +582,22 @@ protected: */ 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 mControllers; /* diff --git a/content/html/content/test/forms/Makefile.in b/content/html/content/test/forms/Makefile.in index 3586a5af1bf6..386df96530a9 100644 --- a/content/html/content/test/forms/Makefile.in +++ b/content/html/content/test/forms/Makefile.in @@ -45,6 +45,7 @@ _TEST_FILES = \ test_max_attribute.html \ test_min_attribute.html \ test_step_attribute.html \ + test_stepup_stepdown.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/forms/test_stepup_stepdown.html b/content/html/content/test/forms/test_stepup_stepdown.html new file mode 100644 index 000000000000..c0163e7dfe60 --- /dev/null +++ b/content/html/content/test/forms/test_stepup_stepdown.html @@ -0,0 +1,347 @@ + + + + + Test for Bug 636627 + + + + + +Mozilla Bug 636627 +

+
+
+
+ + diff --git a/dom/interfaces/html/nsIDOMHTMLInputElement.idl b/dom/interfaces/html/nsIDOMHTMLInputElement.idl index 9313260b6112..04104f3579df 100644 --- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl @@ -20,7 +20,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(e20b7e26-e952-4bba-9192-99bd1a4b3816)] +[scriptable, uuid(71fb50df-5470-4e88-9a28-6ff2912e3ca7)] interface nsIDOMHTMLInputElement : nsIDOMHTMLElement { attribute DOMString accept; @@ -67,6 +67,9 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement attribute DOMString defaultValue; attribute DOMString value; + [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 readonly attribute boolean willValidate; From 3fce1ed8f004d861373c3774f9153190f3439f2b Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Thu, 5 Jul 2012 12:13:41 +0200 Subject: [PATCH 30/31] Bug 636737 - Implement valueAsNumber for . r=sicking --HG-- extra : rebase_source : 5c77f49a870c6223f46e0259de09b80bbeceef3d --- .../html/content/src/nsHTMLInputElement.cpp | 19 ++ content/html/content/src/nsHTMLInputElement.h | 5 + content/html/content/test/forms/Makefile.in | 1 + .../test_input_attributes_reflection.html | 6 +- .../forms/test_valueasnumber_attribute.html | 176 ++++++++++++++++++ .../html/nsIDOMHTMLInputElement.idl | 3 +- 6 files changed, 206 insertions(+), 4 deletions(-) create mode 100644 content/html/content/test/forms/test_valueasnumber_attribute.html diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index f67d8c78739a..87931dc8d7fc 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -1068,6 +1068,25 @@ nsHTMLInputElement::SetValue(double aValue) SetValue(value); } +NS_IMETHODIMP +nsHTMLInputElement::GetValueAsNumber(double* aValueAsNumber) +{ + *aValueAsNumber = DoesValueAsNumberApply() ? GetValueAsDouble() + : std::numeric_limits::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 { diff --git a/content/html/content/src/nsHTMLInputElement.h b/content/html/content/src/nsHTMLInputElement.h index 101212142a28..e57e8df27187 100644 --- a/content/html/content/src/nsHTMLInputElement.h +++ b/content/html/content/src/nsHTMLInputElement.h @@ -484,6 +484,11 @@ protected: */ 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. */ diff --git a/content/html/content/test/forms/Makefile.in b/content/html/content/test/forms/Makefile.in index 386df96530a9..082762bb3980 100644 --- a/content/html/content/test/forms/Makefile.in +++ b/content/html/content/test/forms/Makefile.in @@ -46,6 +46,7 @@ _TEST_FILES = \ test_min_attribute.html \ test_step_attribute.html \ test_stepup_stepdown.html \ + test_valueasnumber_attribute.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/forms/test_input_attributes_reflection.html b/content/html/content/test/forms/test_input_attributes_reflection.html index ab77ab872a10..bd4fdd099b74 100644 --- a/content/html/content/test/forms/test_input_attributes_reflection.html +++ b/content/html/content/test/forms/test_input_attributes_reflection.html @@ -210,9 +210,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"), diff --git a/content/html/content/test/forms/test_valueasnumber_attribute.html b/content/html/content/test/forms/test_valueasnumber_attribute.html new file mode 100644 index 000000000000..e74f63d94869 --- /dev/null +++ b/content/html/content/test/forms/test_valueasnumber_attribute.html @@ -0,0 +1,176 @@ + + + + + Test for Bug 636737 + + + + + +Mozilla Bug 636737 +

+
+
+
+ + diff --git a/dom/interfaces/html/nsIDOMHTMLInputElement.idl b/dom/interfaces/html/nsIDOMHTMLInputElement.idl index 04104f3579df..b199a2e53498 100644 --- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl @@ -20,7 +20,7 @@ interface nsIDOMValidityState; * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(71fb50df-5470-4e88-9a28-6ff2912e3ca7)] +[scriptable, uuid(c12471c8-155f-4368-9e8b-13a231e85f3b)] interface nsIDOMHTMLInputElement : nsIDOMHTMLElement { attribute DOMString accept; @@ -66,6 +66,7 @@ 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); From 4837dc9c41828e2883982958ea14c6f0c9d9f3ba Mon Sep 17 00:00:00 2001 From: Raphael Catolino Date: Sat, 23 Jun 2012 14:32:54 +0200 Subject: [PATCH 31/31] Bug 764481 - Add a pref to enable/disable experimental form features. r=mounir --HG-- extra : rebase_source : 43b03c409b9cc52a991ca753c1848d453afbbb33 --- .../html/content/src/nsHTMLInputElement.cpp | 6 +++ content/html/content/test/forms/Makefile.in | 1 + .../forms/test_experimental_forms_pref.html | 43 +++++++++++++++++++ .../test_input_attributes_reflection.html | 5 +++ .../test/forms/test_max_attribute.html | 5 +++ .../test/forms/test_min_attribute.html | 5 +++ .../test/forms/test_mozistextfield.html | 5 +++ .../test/forms/test_pattern_attribute.html | 5 +++ .../test/forms/test_step_attribute.html | 5 +++ .../test/forms/test_stepup_stepdown.html | 6 +++ .../content/test/forms/test_validation.html | 5 +++ .../forms/test_valueasnumber_attribute.html | 5 +++ content/html/content/test/test_bug549475.html | 4 ++ modules/libpref/src/init/all.js | 3 ++ 14 files changed, 103 insertions(+) create mode 100644 content/html/content/test/forms/test_experimental_forms_pref.html diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 87931dc8d7fc..9a09c0ef65a8 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -87,6 +87,7 @@ #include "mozilla/LookAndFeel.h" #include "mozilla/Util.h" // DebugOnly +#include "mozilla/Preferences.h" #include "nsIIDNService.h" @@ -2661,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; } diff --git a/content/html/content/test/forms/Makefile.in b/content/html/content/test/forms/Makefile.in index 082762bb3980..e1fb87c4b988 100644 --- a/content/html/content/test/forms/Makefile.in +++ b/content/html/content/test/forms/Makefile.in @@ -47,6 +47,7 @@ _TEST_FILES = \ test_step_attribute.html \ test_stepup_stepdown.html \ test_valueasnumber_attribute.html \ + test_experimental_forms_pref.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/forms/test_experimental_forms_pref.html b/content/html/content/test/forms/test_experimental_forms_pref.html new file mode 100644 index 000000000000..dc13baa1b3ff --- /dev/null +++ b/content/html/content/test/forms/test_experimental_forms_pref.html @@ -0,0 +1,43 @@ + + + + + Test for Bug 764481 + + + + + +Mozilla Bug 764481 +

+ +
+
+
+ + diff --git a/content/html/content/test/forms/test_input_attributes_reflection.html b/content/html/content/test/forms/test_input_attributes_reflection.html index bd4fdd099b74..1573afaa0903 100644 --- a/content/html/content/test/forms/test_input_attributes_reflection.html +++ b/content/html/content/test/forms/test_input_attributes_reflection.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"), @@ -230,6 +232,9 @@ reflectUnsignedInt({ // .validationMessage doesn't reflect a content attribute. // .labels doesn't reflect a content attribute. +SimpleTest.finish(); +}); + diff --git a/content/html/content/test/forms/test_max_attribute.html b/content/html/content/test/forms/test_max_attribute.html index 4953038eb2f4..d8e22bcd84aa 100644 --- a/content/html/content/test/forms/test_max_attribute.html +++ b/content/html/content/test/forms/test_max_attribute.html @@ -77,6 +77,8 @@ function checkValidity(aElement, aValidity, aApply, aRangeApply) } } +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() { for each (var data in types) { input.type = data[0]; var apply = data[1]; @@ -157,6 +159,9 @@ for each (var data in types) { input.value = ''; } +SimpleTest.finish(); +}); + diff --git a/content/html/content/test/forms/test_min_attribute.html b/content/html/content/test/forms/test_min_attribute.html index 94f98af1c4df..647726033767 100644 --- a/content/html/content/test/forms/test_min_attribute.html +++ b/content/html/content/test/forms/test_min_attribute.html @@ -77,6 +77,8 @@ function checkValidity(aElement, aValidity, aApply, aRangeApply) } } +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() { for each (var data in types) { input.type = data[0]; var apply = data[1]; @@ -157,6 +159,9 @@ for each (var data in types) { input.value = ''; } +SimpleTest.finish(); +}); + diff --git a/content/html/content/test/forms/test_mozistextfield.html b/content/html/content/test/forms/test_mozistextfield.html index 87c051939317..f27ce45be96c 100644 --- a/content/html/content/test/forms/test_mozistextfield.html +++ b/content/html/content/test/forms/test_mozistextfield.html @@ -102,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]); @@ -120,6 +122,9 @@ for each (data in gInputTodoData) { checkMozIsTextFieldValueTodo(input, data[1]); } +SimpleTest.finish(); +}); + diff --git a/content/html/content/test/forms/test_pattern_attribute.html b/content/html/content/test/forms/test_pattern_attribute.html index b7c0ef02a8b5..ed11a93f3e85 100644 --- a/content/html/content/test/forms/test_pattern_attribute.html +++ b/content/html/content/test/forms/test_pattern_attribute.html @@ -266,6 +266,8 @@ var invalidTypes = Array('checkbox', 'radio', 'file', 'number'); // '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(); +}); + diff --git a/content/html/content/test/forms/test_step_attribute.html b/content/html/content/test/forms/test_step_attribute.html index a00d92947400..0e7f5fdbbef2 100644 --- a/content/html/content/test/forms/test_step_attribute.html +++ b/content/html/content/test/forms/test_step_attribute.html @@ -78,6 +78,8 @@ function checkValidity(aElement, aValidity, aApply) (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]; @@ -248,6 +250,9 @@ for each (var data in types) { input.value = ''; } +SimpleTest.finish(); +}); + diff --git a/content/html/content/test/forms/test_stepup_stepdown.html b/content/html/content/test/forms/test_stepup_stepdown.html index c0163e7dfe60..00b3b6439be2 100644 --- a/content/html/content/test/forms/test_stepup_stepdown.html +++ b/content/html/content/test/forms/test_stepup_stepdown.html @@ -336,11 +336,17 @@ function checkStepUpForNumber() } } +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() { + checkPresence(); checkAvailability(); checkStepDownForNumber(); checkStepUpForNumber(); +SimpleTest.finish(); +}); + diff --git a/content/html/content/test/forms/test_validation.html b/content/html/content/test/forms/test_validation.html index d2c5e8f10217..f67de8fcf7d5 100644 --- a/content/html/content/test/forms/test_validation.html +++ b/content/html/content/test/forms/test_validation.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(); +}); + diff --git a/content/html/content/test/forms/test_valueasnumber_attribute.html b/content/html/content/test/forms/test_valueasnumber_attribute.html index e74f63d94869..1a66660c81a6 100644 --- a/content/html/content/test/forms/test_valueasnumber_attribute.html +++ b/content/html/content/test/forms/test_valueasnumber_attribute.html @@ -166,10 +166,15 @@ function checkSet() } } +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() { checkAvailability(); checkGet(); checkSet(); +SimpleTest.finish(); +}); + diff --git a/content/html/content/test/test_bug549475.html b/content/html/content/test/test_bug549475.html index 3c6bb47ead94..063bb8c4b2c7 100644 --- a/content/html/content/test/test_bug549475.html +++ b/content/html/content/test/test_bug549475.html @@ -131,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"); @@ -166,6 +168,8 @@ for each (type in todoTypes) { form.removeChild(element); } +SpecialPowers.setBoolPref("dom.experimental_forms", pref); + diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 4f29c5df57dd..0c9e8a25e4bf 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -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);