From e4e84f1b5253a432c6625fdf0b02d252d42d481e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 1 Dec 2009 10:37:30 -0800 Subject: [PATCH 001/179] Recursion needs to fix up argsobj when it pops frames on trace (bug 531298, r=dmandelin). --- js/src/jsbuiltins.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index 8b03f748ab81..07459d0b0e85 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -400,6 +400,8 @@ js_PopInterpFrame(JSContext* cx, InterpState* state) return JS_FALSE; if (cx->fp->imacpc) return JS_FALSE; + + cx->fp->putActivationObjects(cx); /* Update display table. */ if (cx->fp->script->staticLevel < JS_DISPLAY_SIZE) From d8a40bbfc45b9d6cdc641efa70c1c69a1a13a62e Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Mon, 30 Nov 2009 16:05:44 -0500 Subject: [PATCH 002/179] Bug 468506 - JS_GetFrameThis needs to call js_ComputeThis in more cases. r=brendan --HG-- extra : rebase_source : 2a107feb26544159f04b60c27508338cef8fdf7f --- js/src/jsdbgapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 0da2bab11ed3..b87317dc2639 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -1218,7 +1218,7 @@ JS_GetFrameThis(JSContext *cx, JSStackFrame *fp) afp = NULL; } - if (JSVAL_IS_NULL(fp->thisv) && fp->argv) + if (fp->argv) fp->thisv = OBJECT_TO_JSVAL(js_ComputeThis(cx, JS_TRUE, fp->argv)); if (afp) { From 1c1ae69c8b654b632a3360f2ccc4664919173f9d Mon Sep 17 00:00:00 2001 From: Robert Sayre Date: Tue, 1 Dec 2009 15:49:15 -0500 Subject: [PATCH 003/179] Relanding: Bye-bye middle-deletes and their O(n^2) worst case complexity; hello dictionary-mode scopes (473228, r=jorendorff). Backed out changeset ee7bfc1923ad --- js/src/jsapi.cpp | 23 +- js/src/jsarray.cpp | 4 +- js/src/jsbuiltins.cpp | 24 +- js/src/jscntxt.h | 5 +- js/src/jsdbgapi.cpp | 53 +- js/src/jsinterp.cpp | 8 +- js/src/jsobj.cpp | 63 +-- js/src/jsopcode.cpp | 6 +- js/src/jsops.cpp | 34 +- js/src/jsparse.cpp | 2 +- js/src/jsscope.cpp | 1143 ++++++++++++++++++++------------------- js/src/jsscope.h | 228 ++++++-- js/src/jsscopeinlines.h | 24 +- js/src/jsstr.cpp | 2 +- js/src/jstracer.cpp | 8 +- 15 files changed, 906 insertions(+), 721 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 61a26a382e9c..00de732cc37d 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1618,15 +1618,11 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id, static JSBool AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom) { - JSScopeProperty *sprop; - JSScope *scope; - - JS_ASSERT(OBJ_IS_NATIVE(obj)); JS_LOCK_OBJ(cx, obj); - scope = OBJ_SCOPE(obj); - sprop = scope->lookup(ATOM_TO_JSID(atom)); + JSScope *scope = OBJ_SCOPE(obj); + bool found = scope->hasProperty(ATOM_TO_JSID(atom)); JS_UNLOCK_SCOPE(cx, scope); - return sprop != NULL; + return found; } JS_PUBLIC_API(JSBool) @@ -3402,7 +3398,7 @@ AlreadyHasOwnPropertyHelper(JSContext *cx, JSObject *obj, jsid id, JS_LOCK_OBJ(cx, obj); scope = OBJ_SCOPE(obj); - *foundp = (scope->lookup(id) != NULL); + *foundp = scope->hasProperty(id); JS_UNLOCK_SCOPE(cx, scope); return JS_TRUE; } @@ -4086,7 +4082,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj) if (OBJ_IS_NATIVE(obj)) { /* Native case: start with the last property in obj's own scope. */ scope = OBJ_SCOPE(obj); - pdata = scope->lastProp; + pdata = scope->lastProperty(); index = -1; } else { /* @@ -4129,15 +4125,12 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp) /* * If the next property mapped by scope in the property tree ancestor - * line is not enumerable, or it's an alias, or one or more properties - * were deleted from the "middle" of the scope-mapped ancestor line - * and the next property was among those deleted, skip it and keep on - * trying to find an enumerable property that is still in scope. + * line is not enumerable, or it's an alias, skip it and keep on trying + * to find an enumerable property that is still in scope. */ while (sprop && (!(sprop->attrs & JSPROP_ENUMERATE) || - (sprop->flags & SPROP_IS_ALIAS) || - (scope->hadMiddleDelete() && !scope->has(sprop)))) { + (sprop->flags & SPROP_IS_ALIAS))) { sprop = sprop->parent; } diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 03941dd06d34..4638a5ca8982 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -1327,8 +1327,8 @@ js_MakeArraySlow(JSContext *cx, JSObject *obj) continue; } - sprop = scope->add(cx, id, NULL, NULL, i + JS_INITIAL_NSLOTS, - JSPROP_ENUMERATE, 0, 0); + sprop = scope->addDataProperty(cx, id, JS_INITIAL_NSLOTS + i, + JSPROP_ENUMERATE); if (!sprop) goto out_bad; } diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index 0e3e86e3e1e7..7a604e59d533 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -209,7 +209,7 @@ js_StringToInt32(JSContext* cx, JSString* str) const jschar* end; const jschar* ep; jsdouble d; - + if (str->length() == 1) { jschar c = str->chars()[0]; if ('0' <= c && c <= '9') @@ -271,21 +271,22 @@ JS_DEFINE_CALLINFO_2(extern, SIDEEXIT, js_CallTree, INTERPSTATE, FRAGMENT, 0, 0) JSBool FASTCALL js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) { - JS_ASSERT(OBJ_IS_NATIVE(obj)); JS_LOCK_OBJ(cx, obj); + uint32 slot = sprop->slot; JSScope* scope = OBJ_SCOPE(obj); - uint32 slot; + JS_ASSERT(slot == scope->freeslot); + JS_ASSERT(sprop->parent == scope->lastProperty()); + if (scope->owned()) { - JS_ASSERT(!scope->has(sprop)); + JS_ASSERT(!scope->hasProperty(sprop)); } else { scope = js_GetMutableScope(cx, obj); if (!scope) goto exit_trace; } - slot = sprop->slot; - if (!scope->table && sprop->parent == scope->lastProp && slot == scope->freeslot) { + if (!scope->table) { if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) { JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->freeslot))); ++scope->freeslot; @@ -301,10 +302,9 @@ js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) scope->extend(cx, sprop); } else { - JSScopeProperty *sprop2 = scope->add(cx, sprop->id, - sprop->getter, sprop->setter, - SPROP_INVALID_SLOT, sprop->attrs, - sprop->flags, sprop->shortid); + JSScopeProperty *sprop2 = + scope->addProperty(cx, sprop->id, sprop->getter, sprop->setter, SPROP_INVALID_SLOT, + sprop->attrs, sprop->flags, sprop->shortid); if (sprop2 != sprop) goto exit_trace; } @@ -440,11 +440,11 @@ js_PopInterpFrame(JSContext* cx, InterpState* state) return JS_FALSE; if (cx->fp->imacpc) return JS_FALSE; - + /* Update display table. */ if (cx->fp->script->staticLevel < JS_DISPLAY_SIZE) cx->display[cx->fp->script->staticLevel] = cx->fp->displaySave; - + /* Pop the frame and its memory. */ cx->fp = cx->fp->down; JS_ASSERT(cx->fp->regs == &ifp->callerRegs); diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 830024b47dbe..978f8723873d 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -820,7 +820,7 @@ struct JSRuntime { JSBasicStats loopStats; #endif -#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS +#ifdef DEBUG /* Function invocation metering. */ jsrefcount inlineCalls; jsrefcount nativeCalls; @@ -842,7 +842,6 @@ struct JSRuntime { jsrefcount duplicatePropTreeNodes; jsrefcount totalPropTreeNodes; jsrefcount propTreeKidsChunks; - jsrefcount middleDeleteFixups; /* String instrumentation. */ jsrefcount liveStrings; @@ -860,7 +859,7 @@ struct JSRuntime { jsrefcount totalScripts; jsrefcount liveEmptyScripts; jsrefcount totalEmptyScripts; -#endif /* DEBUG || JS_DUMP_PROPTREE_STATS */ +#endif /* DEBUG */ #ifdef JS_SCOPE_DEPTH_METER /* diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 0da2bab11ed3..a7f83eee50d7 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -64,6 +64,7 @@ #include "jsstr.h" #include "jsatominlines.h" +#include "jsscopeinlines.h" #include "jsautooplen.h" @@ -422,13 +423,16 @@ typedef struct JSWatchPoint { #define JSWP_LIVE 0x1 /* live because set and not cleared */ #define JSWP_HELD 0x2 /* held while running handler/setter */ +static bool +IsWatchedProperty(JSContext *cx, JSScopeProperty *sprop); + /* * NB: DropWatchPointAndUnlock releases cx->runtime->debuggerLock in all cases. */ static JSBool DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag) { - JSBool ok, found; + JSBool ok; JSScopeProperty *sprop; JSScope *scope; JSPropertyOp setter; @@ -459,20 +463,22 @@ DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag) if (!setter) { JS_LOCK_OBJ(cx, wp->object); scope = OBJ_SCOPE(wp->object); - found = (scope->lookup(sprop->id) != NULL); - JS_UNLOCK_SCOPE(cx, scope); /* - * If the property wasn't found on wp->object or didn't exist, then - * someone else has dealt with this sprop, and we don't need to change - * the property attributes. + * If the property wasn't found on wp->object, or it isn't still being + * watched, then someone else must have deleted or unwatched it, and we + * don't need to change the property attributes. */ - if (found) { - sprop = scope->change(cx, sprop, 0, sprop->attrs, - sprop->getter, wp->setter); + JSScopeProperty *wprop = scope->lookup(sprop->id); + if (wprop && + ((wprop->attrs ^ sprop->attrs) & JSPROP_SETTER) == 0 && + IsWatchedProperty(cx, wprop)) { + sprop = scope->changeProperty(cx, wprop, 0, wprop->attrs, + wprop->getter, wp->setter); if (!sprop) ok = JS_FALSE; } + JS_UNLOCK_SCOPE(cx, scope); } cx->free(wp); @@ -762,6 +768,18 @@ js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, return js_watch_set(cx, obj, userid, rval); } +static bool +IsWatchedProperty(JSContext *cx, JSScopeProperty *sprop) +{ + if (sprop->attrs & JSPROP_SETTER) { + JSObject *funobj = js_CastAsObject(sprop->setter); + JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj); + + return FUN_NATIVE(fun) == js_watch_set_wrapper; + } + return sprop->setter == js_watch_set; +} + JSPropertyOp js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter) { @@ -1432,16 +1450,7 @@ JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp) scope = OBJ_SCOPE(obj); /* XXXbe minor(?) incompatibility: iterate in reverse definition order */ - if (!sprop) { - sprop = SCOPE_LAST_PROP(scope); - } else { - while ((sprop = sprop->parent) != NULL) { - if (!scope->hadMiddleDelete()) - break; - if (scope->has(sprop)) - break; - } - } + sprop = sprop ? sprop->parent : scope->lastProperty(); *iteratorp = sprop; return sprop; } @@ -1490,7 +1499,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, JSScope *scope = OBJ_SCOPE(obj); if (SPROP_HAS_VALID_SLOT(sprop, scope)) { JSScopeProperty *aprop; - for (aprop = SCOPE_LAST_PROP(scope); aprop; aprop = aprop->parent) { + for (aprop = scope->lastProperty(); aprop; aprop = aprop->parent) { if (aprop != sprop && aprop->slot == sprop->slot) { pd->alias = ID_TO_VALUE(aprop->id); break; @@ -1531,9 +1540,7 @@ JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda) if (!pd) return JS_FALSE; i = 0; - for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) { - if (scope->hadMiddleDelete() && !scope->has(sprop)) - continue; + for (sprop = scope->lastProperty(); sprop; sprop = sprop->parent) { if (!js_AddRoot(cx, &pd[i].id, NULL)) goto bad; if (!js_AddRoot(cx, &pd[i].value, NULL)) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 925f3e41f217..a87fdef75a0e 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -122,7 +122,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj, * from pobj's scope (via unwatch or delete, e.g.). */ scope = OBJ_SCOPE(pobj); - if (!scope->has(sprop)) { + if (!scope->hasProperty(sprop)) { PCMETER(cache->oddfills++); return JS_NO_PROP_CACHE_FILL; } @@ -132,8 +132,8 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj, * and setter hooks can change the prototype chain using JS_SetPrototype * after js_LookupPropertyWithFlags has returned the nominal protoIndex, * we have to validate protoIndex if it is non-zero. If it is zero, then - * we know thanks to the scope->has test above, combined with the fact that - * obj == pobj, that protoIndex is invariant. + * we know thanks to the scope->hasProperty test above, combined with the + * fact that obj == pobj, that protoIndex is invariant. * * The scopeIndex can't be wrong. We require JS_SetParent calls to happen * before any running script might consult a parent-linked scope chain. If @@ -251,7 +251,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj, /* Best we can do is to cache sprop (still a nice speedup). */ vword = SPROP_TO_PCVAL(sprop); if (adding && - sprop == scope->lastProp && + sprop == scope->lastProperty() && scope->shape == sprop->shape) { /* * Our caller added a new property. We also know that a setter diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 3d7d03a19f37..c8ac745f8479 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2957,7 +2957,7 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp) /* Find a property to XDR. */ do { /* If sprop is NULL, this is the first property. */ - sprop = sprop ? sprop->parent : OBJ_SCOPE(obj)->lastProp; + sprop = sprop ? sprop->parent : OBJ_SCOPE(obj)->lastProperty(); } while (!(sprop->flags & SPROP_HAS_SHORTID)); JS_ASSERT(sprop->getter == block_getProperty); @@ -3725,7 +3725,7 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id, } else { /* Convert string indices to integers if appropriate. */ id = js_CheckForStringIndex(id); - sprop = scope->add(cx, id, getter, setter, slot, attrs, flags, shortid); + sprop = scope->putProperty(cx, id, getter, setter, slot, attrs, flags, shortid); } JS_UNLOCK_OBJ(cx, obj); return sprop; @@ -3743,7 +3743,7 @@ js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj, if (!scope) { sprop = NULL; } else { - sprop = scope->change(cx, sprop, attrs, mask, getter, setter); + sprop = scope->changeProperty(cx, sprop, attrs, mask, getter, setter); } JS_UNLOCK_OBJ(cx, obj); return sprop; @@ -3822,14 +3822,14 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, if (sprop && pobj == obj && (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER))) { - sprop = OBJ_SCOPE(obj)->change(cx, sprop, attrs, - JSPROP_GETTER | JSPROP_SETTER, - (attrs & JSPROP_GETTER) - ? getter - : sprop->getter, - (attrs & JSPROP_SETTER) - ? setter - : sprop->setter); + sprop = OBJ_SCOPE(obj)->changeProperty(cx, sprop, attrs, + JSPROP_GETTER | JSPROP_SETTER, + (attrs & JSPROP_GETTER) + ? getter + : sprop->getter, + (attrs & JSPROP_SETTER) + ? setter + : sprop->setter); /* NB: obj == pobj, so we can share unlock code at the bottom. */ if (!sprop) @@ -3895,9 +3895,9 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, } } - added = !scope->lookup(id); - sprop = scope->add(cx, id, getter, setter, SPROP_INVALID_SLOT, attrs, - flags, shortid); + added = !scope->hasProperty(id); + sprop = scope->putProperty(cx, id, getter, setter, SPROP_INVALID_SLOT, + attrs, flags, shortid); if (!sprop) goto error; } @@ -3908,7 +3908,7 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, /* XXXbe called with lock held */ if (!AddPropertyHelper(cx, clasp, obj, scope, sprop, &value)) { - scope->remove(cx, id); + scope->removeProperty(cx, id); goto error; } @@ -4329,7 +4329,7 @@ js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj, JS_LOCK_SCOPE(cx, scope); if (SLOT_IN_SCOPE(slot, scope) && (JS_LIKELY(cx->runtime->propertyRemovals == sample) || - scope->has(sprop))) { + scope->hasProperty(sprop))) { jsval v = *vp; if (!scope->methodWriteBarrier(cx, sprop, v)) { JS_UNLOCK_SCOPE(cx, scope); @@ -4391,7 +4391,7 @@ js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, bool added, JS_LOCK_SCOPE(cx, scope); if (SLOT_IN_SCOPE(slot, scope) && (JS_LIKELY(cx->runtime->propertyRemovals == sample) || - scope->has(sprop))) { + scope->hasProperty(sprop))) { jsval v = *vp; if (!added && !scope->methodWriteBarrier(cx, sprop, v)) { JS_UNLOCK_SCOPE(cx, scope); @@ -4759,8 +4759,8 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, } } - sprop = scope->add(cx, id, getter, setter, SPROP_INVALID_SLOT, attrs, - flags, shortid); + sprop = scope->addProperty(cx, id, getter, setter, SPROP_INVALID_SLOT, + attrs, flags, shortid); if (!sprop) { JS_UNLOCK_SCOPE(cx, scope); return JS_FALSE; @@ -4776,7 +4776,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, /* XXXbe called with obj locked */ if (!AddPropertyHelper(cx, clasp, obj, scope, sprop, vp)) { - scope->remove(cx, id); + scope->removeProperty(cx, id); JS_UNLOCK_SCOPE(cx, scope); return JS_FALSE; } @@ -4923,7 +4923,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval) if (SPROP_HAS_VALID_SLOT(sprop, scope)) GC_POKE(cx, LOCKED_OBJ_GET_SLOT(obj, sprop->slot)); - ok = scope->remove(cx, id); + ok = scope->removeProperty(cx, id); obj->dropProperty(cx, prop); return ok; } @@ -5158,12 +5158,9 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, /* Count all enumerable properties in object's scope. */ JSScope *scope = OBJ_SCOPE(obj); length = 0; - for (JSScopeProperty *sprop = SCOPE_LAST_PROP(scope); - sprop; - sprop = sprop->parent) { + for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) { if ((sprop->attrs & JSPROP_ENUMERATE) && - !(sprop->flags & SPROP_IS_ALIAS) && - (!scope->hadMiddleDelete() || scope->has(sprop))) { + !(sprop->flags & SPROP_IS_ALIAS)) { length++; } } @@ -5194,12 +5191,9 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, ne->shape = shape; jsid *ids = ne->ids; - for (JSScopeProperty *sprop = SCOPE_LAST_PROP(scope); - sprop; - sprop = sprop->parent) { + for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) { if ((sprop->attrs & JSPROP_ENUMERATE) && - !(sprop->flags & SPROP_IS_ALIAS) && - (!scope->hadMiddleDelete() || scope->has(sprop))) { + !(sprop->flags & SPROP_IS_ALIAS)) { JS_ASSERT(ids < ne->ids + length); *ids++ = sprop->id; } @@ -5868,7 +5862,7 @@ js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize) JSScopeProperty *sprop; if (OBJ_IS_NATIVE(obj)) { JSScope *scope = OBJ_SCOPE(obj); - sprop = SCOPE_LAST_PROP(scope); + sprop = scope->lastProperty(); while (sprop && sprop->slot != slot) sprop = sprop->parent; } else { @@ -6299,10 +6293,9 @@ js_DumpObject(JSObject *obj) fprintf(stderr, "sealed\n"); fprintf(stderr, "properties:\n"); - for (JSScopeProperty *sprop = SCOPE_LAST_PROP(scope); sprop; + for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) { - if (!scope->hadMiddleDelete() || scope->has(sprop)) - dumpScopeProp(sprop); + dumpScopeProp(sprop); } } else { if (!OBJ_IS_NATIVE(obj)) diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 9c7ae533a96b..f7c8574d97bc 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -277,7 +277,7 @@ ToDisassemblySource(JSContext *cx, jsval v) if (clasp == &js_BlockClass) { char *source = JS_sprintf_append(NULL, "depth %d {", OBJ_BLOCK_DEPTH(cx, obj)); - for (JSScopeProperty *sprop = OBJ_SCOPE(obj)->lastProp; + for (JSScopeProperty *sprop = OBJ_SCOPE(obj)->lastProperty(); sprop; sprop = sprop->parent) { const char *bytes = js_AtomToPrintableString(cx, JSID_TO_ATOM(sprop->id)); @@ -1311,7 +1311,7 @@ GetLocal(SprintStack *ss, jsint i) } i -= depth; - for (sprop = OBJ_SCOPE(obj)->lastProp; sprop; sprop = sprop->parent) { + for (sprop = OBJ_SCOPE(obj)->lastProperty(); sprop; sprop = sprop->parent) { if (sprop->shortid == i) break; } @@ -2629,7 +2629,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) MUST_FLOW_THROUGH("enterblock_out"); #define LOCAL_ASSERT_OUT(expr) LOCAL_ASSERT_CUSTOM(expr, ok = JS_FALSE; \ goto enterblock_out) - for (sprop = OBJ_SCOPE(obj)->lastProp; sprop; + for (sprop = OBJ_SCOPE(obj)->lastProperty(); sprop; sprop = sprop->parent) { if (!(sprop->flags & SPROP_HAS_SHORTID)) continue; diff --git a/js/src/jsops.cpp b/js/src/jsops.cpp index 6c49ef3759a6..997bc9e542cf 100644 --- a/js/src/jsops.cpp +++ b/js/src/jsops.cpp @@ -1756,7 +1756,7 @@ BEGIN_CASE(JSOP_SETMETHOD) /* The cache entry doesn't apply. vshape mismatch. */ checkForAdd = false; } else if (scope->owned()) { - if (sprop == scope->lastProp || scope->has(sprop)) { + if (sprop == scope->lastProperty() || scope->hasProperty(sprop)) { fast_set_propcache_hit: PCMETER(cache->pchits++); PCMETER(cache->setpchits++); @@ -1766,8 +1766,7 @@ BEGIN_CASE(JSOP_SETMETHOD) } checkForAdd = !(sprop->attrs & JSPROP_SHARED) && - sprop->parent == scope->lastProp && - !scope->hadMiddleDelete(); + sprop->parent == scope->lastProperty(); } else { scope = js_GetMutableScope(cx, obj); if (!scope) { @@ -1814,7 +1813,7 @@ BEGIN_CASE(JSOP_SETMETHOD) /* * If this obj's number of reserved slots differed, or * if something created a hash table for scope, we must - * pay the price of JSScope::add. + * pay the price of JSScope::putProperty. * * If slot does not match the cached sprop's slot, * update the cache entry in the hope that obj and @@ -1823,10 +1822,10 @@ BEGIN_CASE(JSOP_SETMETHOD) */ if (slot != sprop->slot || scope->table) { JSScopeProperty *sprop2 = - scope->add(cx, sprop->id, - sprop->getter, sprop->setter, - slot, sprop->attrs, - sprop->flags, sprop->shortid); + scope->putProperty(cx, sprop->id, + sprop->getter, sprop->setter, + slot, sprop->attrs, + sprop->flags, sprop->shortid); if (!sprop2) { js_FreeSlot(cx, obj, slot); JS_UNLOCK_SCOPE(cx, scope); @@ -3537,10 +3536,10 @@ BEGIN_CASE(JSOP_INITMETHOD) /* * Detect a repeated property name and force a miss to share the - * strict warning code and cope with complexity managed by - * JSScope::add. + * strict warning code and consolidate all the complexity managed + * by JSScope::addProperty. */ - if (sprop->parent != scope->lastProp) + if (sprop->parent != scope->lastProperty()) goto do_initprop_miss; /* @@ -3548,8 +3547,8 @@ BEGIN_CASE(JSOP_INITMETHOD) * proto-property, and there cannot have been any deletions of * prior properties. */ - JS_ASSERT(!scope->hadMiddleDelete()); - JS_ASSERT_IF(scope->table, !scope->has(sprop)); + JS_ASSERT(!scope->inDictionaryMode()); + JS_ASSERT_IF(scope->table, !scope->hasProperty(sprop)); slot = sprop->slot; JS_ASSERT(slot == scope->freeslot); @@ -3563,14 +3562,11 @@ BEGIN_CASE(JSOP_INITMETHOD) JS_ASSERT(slot == sprop->slot); } - JS_ASSERT(!scope->lastProp || - scope->shape == scope->lastProp->shape); + JS_ASSERT(!scope->lastProperty() || + scope->shape == scope->lastProperty()->shape); if (scope->table) { JSScopeProperty *sprop2 = - scope->add(cx, sprop->id, - sprop->getter, sprop->setter, - slot, sprop->attrs, - sprop->flags, sprop->shortid); + scope->addDataProperty(cx, sprop->id, slot, sprop->attrs); if (!sprop2) { js_FreeSlot(cx, obj, slot); JS_UNLOCK_SCOPE(cx, scope); diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index f2dd41cbfcf3..0f27a02194fa 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -3261,7 +3261,7 @@ PopStatement(JSTreeContext *tc) JSScope *scope = OBJ_SCOPE(obj); JS_ASSERT(!OBJ_IS_CLONED_BLOCK(obj)); - for (JSScopeProperty *sprop = scope->lastProp; sprop; sprop = sprop->parent) { + for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) { JSAtom *atom = JSID_TO_ATOM(sprop->id); /* Beware the empty destructuring dummy. */ diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index ba15a07c86ea..659b3aabdcc0 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -146,6 +146,14 @@ JSScope::initMinimal(JSContext *cx, uint32 newShape) lastProp = NULL; } +#ifdef DEBUG +JS_FRIEND_DATA(JSScopeStats) js_scope_stats = {0}; + +# define METER(x) JS_ATOMIC_INCREMENT(&js_scope_stats.x) +#else +# define METER(x) /* nothing */ +#endif + bool JSScope::createTable(JSContext *cx, bool report) { @@ -174,6 +182,7 @@ JSScope::createTable(JSContext *cx, bool report) if (!table) { if (report) JS_ReportOutOfMemory(cx); + METER(tableAllocFails); return false; } cx->updateMallocCounter(JS_BIT(sizeLog2) * sizeof(JSScopeProperty *)); @@ -200,7 +209,6 @@ JSScope::create(JSContext *cx, const JSObjectOps *ops, JSClass *clasp, scope->nrefs = 1; scope->freeslot = JSSLOT_FREE(clasp); scope->flags = cx->runtime->gcRegenShapesScopeFlag; - js_LeaveTraceIfGlobalObject(cx, obj); scope->initMinimal(cx, shape); #ifdef JS_THREADSAFE @@ -238,7 +246,7 @@ JSScope::createEmptyScope(JSContext *cx, JSClass *clasp) return scope; } -#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS +#ifdef DEBUG # include "jsprf.h" # define LIVE_SCOPE_METER(cx,expr) JS_LOCK_RUNTIME_VOID(cx->runtime,expr) #else @@ -261,14 +269,6 @@ JSScope::destroy(JSContext *cx, JSScope *scope) cx->free(scope); } -#ifdef JS_DUMP_PROPTREE_STATS -JS_FRIEND_DATA(JSScopeStats) js_scope_stats = {0}; - -# define METER(x) JS_ATOMIC_INCREMENT(&js_scope_stats.x) -#else -# define METER(x) /* nothing */ -#endif - JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4); JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD); @@ -383,8 +383,10 @@ JSScope::changeTable(JSContext *cx, int change) newsize = JS_BIT(newlog2); nbytes = SCOPE_TABLE_NBYTES(newsize); newtable = (JSScopeProperty **) cx->calloc(nbytes); - if (!newtable) + if (!newtable) { + METER(tableAllocFails); return false; + } /* Now that we have newtable allocated, update members. */ hashShift = JS_DHASH_BITS - newlog2; @@ -830,7 +832,7 @@ HashChunks(PropTreeKidsChunk *chunk, uintN n) */ static JSScopeProperty * GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent, - JSScopeProperty *child) + const JSScopeProperty &child) { JSRuntime *rt; JSDHashTable *table; @@ -839,15 +841,13 @@ GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent, PropTreeKidsChunk *chunk; uintN i, n; - JS_ASSERT(!JSVAL_IS_NULL(child->id)); - rt = cx->runtime; if (!parent) { JS_LOCK_GC(rt); table = &rt->propertyTreeHash; entry = (JSPropertyTreeEntry *) - JS_DHashTableOperate(table, child, JS_DHASH_ADD); + JS_DHashTableOperate(table, &child, JS_DHASH_ADD); if (!entry) goto out_of_memory; @@ -880,12 +880,10 @@ GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent, if (table) { JS_LOCK_GC(rt); entry = (JSPropertyTreeEntry *) - JS_DHashTableOperate(table, child, JS_DHASH_LOOKUP); + JS_DHashTableOperate(table, &child, JS_DHASH_LOOKUP); sprop = entry->child; - if (sprop) { - JS_UNLOCK_GC(rt); - return sprop; - } + if (sprop) + goto out; goto locked_not_found; } @@ -912,13 +910,13 @@ GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent, goto not_found; } - if (SPROP_MATCH(sprop, child)) + if (SPROP_MATCH(sprop, &child)) return sprop; } n += MAX_KIDS_PER_CHUNK; } while ((chunk = chunk->next) != NULL); } else { - if (SPROP_MATCH(sprop, child)) + if (SPROP_MATCH(sprop, &child)) return sprop; } } @@ -932,13 +930,13 @@ locked_not_found: if (!sprop) goto out_of_memory; - sprop->id = child->id; - sprop->getter = child->getter; - sprop->setter = child->setter; - sprop->slot = child->slot; - sprop->attrs = child->attrs; - sprop->flags = child->flags; - sprop->shortid = child->shortid; + sprop->id = child.id; + sprop->getter = child.getter; + sprop->setter = child.setter; + sprop->slot = child.slot; + sprop->attrs = child.attrs; + sprop->flags = child.flags; + sprop->shortid = child.shortid; sprop->parent = sprop->kids = NULL; sprop->shape = js_GenerateShape(cx, true); @@ -949,32 +947,89 @@ locked_not_found: goto out_of_memory; } -out: + out: JS_UNLOCK_GC(rt); return sprop; -out_of_memory: + out_of_memory: JS_UNLOCK_GC(rt); JS_ReportOutOfMemory(cx); return NULL; } +/* + * Get or create a property-tree or dictionary child property of parent, which + * must be lastProp if inDictionaryMode(), else parent must be one of lastProp + * or lastProp->parent. + */ +JSScopeProperty * +JSScope::getChildProperty(JSContext *cx, JSScopeProperty *parent, + JSScopeProperty &child) +{ + JS_ASSERT(!JSVAL_IS_NULL(child.id)); + + /* + * Aliases share another property's slot, passed in the |slot| parameter. + * Shared properties have no slot. Unshared properties that do not alias + * another property's slot allocate a slot here, but may lose it due to a + * JS_ClearScope call. + */ + if (!(child.flags & SPROP_IS_ALIAS)) { + if (child.attrs & JSPROP_SHARED) { + child.slot = SPROP_INVALID_SLOT; + } else { + /* + * We may have set slot from a nearly-matching sprop, above. + * If so, we're overwriting that nearly-matching sprop, so we + * can reuse its slot -- we don't need to allocate a new one. + * Similarly, we use a specific slot if provided by the caller. + */ + if (child.slot == SPROP_INVALID_SLOT && + !js_AllocSlot(cx, object, &child.slot)) { + return NULL; + } + } + } + + if (inDictionaryMode()) { + JS_ASSERT(parent == lastProp); + if (newDictionaryProperty(cx, child, &lastProp)) { + updateShape(cx); + return lastProp; + } + return NULL; + } + + JSScopeProperty *sprop = GetPropertyTreeChild(cx, parent, child); + if (sprop) { + JS_ASSERT(sprop->parent == parent); + if (parent == lastProp) { + extend(cx, sprop); + } else { + JS_ASSERT(parent == lastProp->parent); + setLastProperty(sprop); + updateShape(cx); + } + } + return sprop; +} + #ifdef DEBUG_notbrendan #define CHECK_ANCESTOR_LINE(scope, sparse) \ JS_BEGIN_MACRO \ - if ((scope)->table) CheckAncestorLine(scope, sparse); \ + if ((scope)->table) CheckAncestorLine(scope); \ JS_END_MACRO static void -CheckAncestorLine(JSScope *scope, bool sparse) +CheckAncestorLine(JSScope *scope) { uint32 size; JSScopeProperty **spp, **start, **end, *ancestorLine, *sprop, *aprop; uint32 entryCount, ancestorCount; - ancestorLine = SCOPE_LAST_PROP(scope); + ancestorLine = scope->lastProperty(); if (ancestorLine) - JS_ASSERT(scope->has(ancestorLine)); + JS_ASSERT(scope->hasProperty(ancestorLine)); entryCount = 0; size = SCOPE_CAPACITY(scope); @@ -982,7 +1037,7 @@ CheckAncestorLine(JSScope *scope, bool sparse) for (spp = start, end = start + size; spp < end; spp++) { sprop = SPROP_FETCH(spp); if (sprop) { - entryCount++; + ++entryCount; for (aprop = ancestorLine; aprop; aprop = aprop->parent) { if (aprop == sprop) break; @@ -993,13 +1048,8 @@ CheckAncestorLine(JSScope *scope, bool sparse) JS_ASSERT(entryCount == scope->entryCount); ancestorCount = 0; - for (sprop = ancestorLine; sprop; sprop = sprop->parent) { - if (scope->hadMiddleDelete() && !scope->has(sprop)) { - JS_ASSERT(sparse); - continue; - } + for (sprop = ancestorLine; sprop; sprop = sprop->parent) ancestorCount++; - } JS_ASSERT(ancestorCount == scope->entryCount); } #else @@ -1051,27 +1101,122 @@ JSScope::generateOwnShape(JSContext *cx) } JSScopeProperty * -JSScope::add(JSContext *cx, jsid id, - JSPropertyOp getter, JSPropertyOp setter, - uint32 slot, uintN attrs, - uintN flags, intN shortid) +JSScope::newDictionaryProperty(JSContext *cx, const JSScopeProperty &child, + JSScopeProperty **childp) { - JSScopeProperty **spp, *sprop, *overwriting, **spvec, **spp2, child; - uint32 size, splen, i; - int change; - JSTempValueRooter tvr; + JSScopeProperty *dprop = NewScopeProperty(cx->runtime); + if (!dprop) { + JS_ReportOutOfMemory(cx); + return NULL; + } + dprop->id = child.id; + dprop->getter = child.getter; + dprop->setter = child.setter; + dprop->slot = child.slot; + dprop->attrs = child.attrs; + dprop->flags = child.flags | SPROP_IN_DICTIONARY; + dprop->shortid = child.shortid; + dprop->shape = js_GenerateShape(cx, false); + + dprop->childp = NULL; + insertDictionaryProperty(dprop, childp); + return dprop; +} + +bool +JSScope::toDictionaryMode(JSContext *cx, JSScopeProperty *&aprop) +{ + JS_ASSERT(!inDictionaryMode()); + + JSScopeProperty **oldTable = table; + uint32 saveRemovedCount = removedCount; + if (oldTable) { + int sizeLog2 = JS_DHASH_BITS - hashShift; + JSScopeProperty **newTable = (JSScopeProperty **) + js_calloc(JS_BIT(sizeLog2) * sizeof(JSScopeProperty *)); + + if (!newTable) { + JS_ReportOutOfMemory(cx); + METER(toDictFails); + return false; + } + table = newTable; + removedCount = 0; + } + + /* + * We are committed from here on. If we fail due to OOM in the loop below, + * we'll restore saveEntryCount, oldTable, oldLastProp. + */ + JSScopeProperty *oldLastProp = lastProp; + lastProp = NULL; + + /* + * Clear entryCount because JSScope::insertDictionaryProperty called from + * JSScope::newDictionaryProperty bumps it. + */ + uint32 saveEntryCount = entryCount; + entryCount = 0; + + for (JSScopeProperty *sprop = oldLastProp, **childp = &lastProp; sprop; sprop = sprop->parent) { + JSScopeProperty *dprop = newDictionaryProperty(cx, *sprop, childp); + if (!dprop) { + entryCount = saveEntryCount; + removedCount = saveRemovedCount; + if (table) + js_free(table); + table = oldTable; + lastProp = oldLastProp; + METER(toDictFails); + return false; + } + + if (table) { + JSScopeProperty **spp = search(dprop->id, true); + JS_ASSERT(!SPROP_FETCH(spp)); + SPROP_STORE_PRESERVING_COLLISION(spp, dprop); + } + + if (aprop == sprop) + aprop = dprop; + childp = &dprop->parent; + } + + if (oldTable) + js_free(oldTable); + setDictionaryMode(); + clearOwnShape(); + + if (lastProp) { + /* + * This scope may get OWN_SHAPE set again, but for now its shape must + * be the shape of its lastProp. If it is empty, its initial shape is + * still valid. See JSScope::updateShape's definition in jsscope.h. + */ + shape = lastProp->shape; + } + return true; +} + +JSScopeProperty * +JSScope::addProperty(JSContext *cx, jsid id, + JSPropertyOp getter, JSPropertyOp setter, + uint32 slot, uintN attrs, + uintN flags, intN shortid) +{ JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, this)); CHECK_ANCESTOR_LINE(this, true); JS_ASSERT(!JSVAL_IS_NULL(id)); JS_ASSERT_IF(attrs & JSPROP_GETTER, getter); JS_ASSERT_IF(attrs & JSPROP_SETTER, setter); + JS_ASSERT_IF(!cx->runtime->gcRegenShapes, hasRegenFlag(cx->runtime->gcRegenShapesScopeFlag)); /* - * You can't add properties to a sealed scope. But note well that you can + * You can't add properties to a sealed scope. But note well that you can * change property attributes in a sealed scope, even though that replaces * a JSScopeProperty * in the scope's hash table -- but no id is added, so * the scope remains sealed. @@ -1081,10 +1226,22 @@ JSScope::add(JSContext *cx, jsid id, return NULL; } - /* - * Normalize stub getter and setter values for faster is-stub testing in - * the SPROP_CALL_[GS]ETTER macros. - */ + /* Search for id with adding = true in order to claim its entry. */ + JSScopeProperty **spp = search(id, true); + JS_ASSERT(!SPROP_FETCH(spp)); + return addPropertyHelper(cx, id, getter, setter, slot, attrs, flags, shortid, spp); +} + +/* + * Normalize stub getter and setter values for faster is-stub testing in the + * SPROP_CALL_[GS]ETTER macros. + */ +static inline bool +NormalizeGetterAndSetter(JSContext *cx, JSScope *scope, + jsid id, uintN attrs, uintN flags, + JSPropertyOp &getter, + JSPropertyOp &setter) +{ if (setter == JS_PropertyStub) setter = NULL; if (flags & SPROP_IS_METHOD) { @@ -1098,240 +1255,49 @@ JSScope::add(JSContext *cx, jsid id, } /* - * Search for id in order to claim its entry, allocating a property tree - * node if one doesn't already exist for our parameters. + * Check for a watchpoint on a deleted property; if one exists, change + * setter to js_watch_set or js_watch_set_wrapper. + * XXXbe this could get expensive with lots of watchpoints... */ - spp = search(id, true); - sprop = overwriting = SPROP_FETCH(spp); - if (!sprop) { - /* Check whether we need to grow, if the load factor is >= .75. */ - size = SCOPE_CAPACITY(this); - if (entryCount + removedCount >= size - (size >> 2)) { - if (removedCount >= size >> 2) { - METER(compresses); - change = 0; - } else { - METER(grows); - change = 1; - } - if (!changeTable(cx, change) && - entryCount + removedCount == size - 1) { - METER(addFailures); - return NULL; - } - spp = search(id, true); - JS_ASSERT(!SPROP_FETCH(spp)); + if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList) && + js_FindWatchPoint(cx->runtime, scope, id)) { + setter = js_WrapWatchedSetter(cx, id, attrs, setter); + if (!setter) { + METER(wrapWatchFails); + return false; } - } else { - /* Property exists: JSScope::search must have returned a valid *spp. */ - JS_ASSERT(!SPROP_IS_REMOVED(*spp)); + } + return true; +} - /* - * If all property members match, this is a redundant add and we can - * return early. If the caller wants to allocate a slot, but doesn't - * care which slot, copy sprop->slot into slot so we can match sprop, - * if all other members match. - */ - if (!(attrs & JSPROP_SHARED) && - slot == SPROP_INVALID_SLOT && - SPROP_HAS_VALID_SLOT(sprop, this)) { - slot = sprop->slot; - } - if (SPROP_MATCH_PARAMS_AFTER_ID(sprop, getter, setter, slot, attrs, - flags, shortid)) { - METER(redundantAdds); - return sprop; - } +JSScopeProperty * +JSScope::addPropertyHelper(JSContext *cx, jsid id, + JSPropertyOp getter, JSPropertyOp setter, + uint32 slot, uintN attrs, + uintN flags, intN shortid, + JSScopeProperty **spp) +{ + NormalizeGetterAndSetter(cx, this, id, attrs, flags, getter, setter); - /* - * If we are clearing sprop to force the existing property that it - * describes to be overwritten, then we have to unlink sprop from the - * ancestor line at this->lastProp, lazily if sprop is not lastProp. - * And we must remove the entry at *spp, precisely so the lazy "middle - * delete" fixup code further below won't find sprop in this->table, - * in spite of sprop being on the ancestor line. - * - * When we finally succeed in finding or creating a new sprop - * and storing its pointer at *spp, we'll use the |overwriting| - * local saved when we first looked up id to decide whether we're - * indeed creating a new entry, or merely overwriting an existing - * property. - */ - if (sprop == SCOPE_LAST_PROP(this)) { - do { - SCOPE_REMOVE_LAST_PROP(this); - if (!hadMiddleDelete()) - break; - sprop = SCOPE_LAST_PROP(this); - } while (sprop && !has(sprop)); - } else if (!hadMiddleDelete()) { - /* - * If we have no hash table yet, we need one now. The middle - * delete code is simple-minded that way! - */ - if (!table) { - if (!createTable(cx, true)) - return NULL; - spp = search(id, true); - sprop = overwriting = SPROP_FETCH(spp); - } - setMiddleDelete(); - } - - /* - * If we fail later on trying to find or create a new sprop, we will - * goto fail_overwrite and restore *spp from |overwriting|. Note that - * we don't bother to keep this->removedCount in sync, because we'll - * fix up *spp and this->entryCount shortly, no matter how control - * flow returns from this function. - */ - if (table) - SPROP_STORE_PRESERVING_COLLISION(spp, NULL); - entryCount--; - CHECK_ANCESTOR_LINE(this, true); - sprop = NULL; + /* Check whether we need to grow, if the load factor is >= .75. */ + uint32 size = SCOPE_CAPACITY(this); + if (entryCount + removedCount >= size - (size >> 2)) { + int change = removedCount < size >> 2; + if (!change) + METER(compresses); + else + METER(grows); + if (!changeTable(cx, change) && entryCount + removedCount == size - 1) + return NULL; + spp = search(id, true); + JS_ASSERT(!SPROP_FETCH(spp)); } - if (!sprop) { - /* - * If properties were deleted from the middle of the list starting at - * this->lastProp, we may need to fork the property tree and squeeze - * all deleted properties out of this scope's ancestor line. Otherwise - * we risk adding a node with the same id as a "middle" node, violating - * the rule that properties along an ancestor line have distinct ids. - */ - if (hadMiddleDelete()) { - JS_ASSERT(table); - CHECK_ANCESTOR_LINE(this, true); + /* Find or create a property tree node labeled by our arguments. */ + JSScopeProperty *sprop; + { + JSScopeProperty child; - /* - * Our forking heuristic tries to balance the desire to avoid - * over-compacting (over-forking) against the desire to - * *periodically* fork anyways, in order to prevent paying scan - * penalties on each insert indefinitely, on a lineage with only - * a few old middle-deletions. So we fork if either: - * - * - A quick scan finds a true conflict. - * - We are passing through a doubling-threshold in size and - * have accumulated a nonzero count of uncompacted deletions. - */ - - bool conflicts = false; - uint32 count = 0; - uint32 threshold = JS_BIT(JS_CeilingLog2(entryCount)); - for (sprop = SCOPE_LAST_PROP(this); sprop; sprop = sprop->parent) { - ++count; - if (sprop->id == id) { - conflicts = true; - break; - } - } - - if (conflicts || count > threshold) { - /* - * Enumerate live entries in this->table using a temporary - * vector, by walking the (possibly sparse, due to deletions) - * ancestor line from this->lastProp. - */ - splen = entryCount; - JS_ASSERT(splen != 0); - spvec = (JSScopeProperty **) - cx->malloc(SCOPE_TABLE_NBYTES(splen)); - if (!spvec) - goto fail_overwrite; - i = splen; - sprop = SCOPE_LAST_PROP(this); - JS_ASSERT(sprop); - do { - /* - * NB: use JSScope::lookup, not JSScope::has, as the latter - * macro insists that sprop->id maps to sprop, while the - * former simply tests whether sprop->id is bound in this - * scope. - */ - if (!lookup(sprop->id)) - continue; - - JS_ASSERT(sprop != overwriting); - JS_ASSERT(i != 0); - spvec[--i] = sprop; - } while ((sprop = sprop->parent) != NULL); - JS_ASSERT(i == 0); - - /* - * Now loop forward through spvec, forking the property tree - * whenever we see a "parent gap" due to deletions from this - * scope. NB: sprop is null on first entry to the loop body. - */ - do { - if (spvec[i]->parent == sprop) { - sprop = spvec[i]; - } else { - sprop = GetPropertyTreeChild(cx, sprop, spvec[i]); - if (!sprop) { - cx->free(spvec); - goto fail_overwrite; - } - - spp2 = search(sprop->id, false); - JS_ASSERT(SPROP_FETCH(spp2) == spvec[i]); - SPROP_STORE_PRESERVING_COLLISION(spp2, sprop); - } - } while (++i < splen); - cx->free(spvec); - - /* - * Now sprop points to the last property in this scope, where - * the ancestor line from sprop to the root is dense w.r.t. - * this scope: it contains no nodes not mapped by this->table. - */ - lastProp = sprop; - CHECK_ANCESTOR_LINE(this, false); - JS_RUNTIME_METER(cx->runtime, middleDeleteFixups); - clearMiddleDelete(); - } - } - - /* - * Aliases share another property's slot, passed in the |slot| param. - * Shared properties have no slot. Unshared properties that do not - * alias another property's slot get one here, but may lose it due to - * a JS_ClearScope call. - */ - if (!(flags & SPROP_IS_ALIAS)) { - if (attrs & JSPROP_SHARED) { - slot = SPROP_INVALID_SLOT; - } else { - /* - * We may have set slot from a nearly-matching sprop, above. - * If so, we're overwriting that nearly-matching sprop, so we - * can reuse its slot -- we don't need to allocate a new one. - * Similarly, we use a specific slot if provided by the caller. - */ - if (slot == SPROP_INVALID_SLOT && - !js_AllocSlot(cx, object, &slot)) { - goto fail_overwrite; - } - } - } - - /* - * Check for a watchpoint on a deleted property; if one exists, change - * setter to js_watch_set. - * XXXbe this could get expensive with lots of watchpoints... - */ - if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList) && - js_FindWatchPoint(cx->runtime, this, id)) { - if (overwriting) - JS_PUSH_TEMP_ROOT_SPROP(cx, overwriting, &tvr); - setter = js_WrapWatchedSetter(cx, id, attrs, setter); - if (overwriting) - JS_POP_TEMP_ROOT(cx, &tvr); - if (!setter) - goto fail_overwrite; - } - - /* Find or create a property tree node labeled by our arguments. */ child.id = id; child.getter = getter; child.setter = setter; @@ -1339,26 +1305,17 @@ JSScope::add(JSContext *cx, jsid id, child.attrs = attrs; child.flags = flags; child.shortid = shortid; - sprop = GetPropertyTreeChild(cx, lastProp, &child); - if (!sprop) - goto fail_overwrite; - - /* - * This scope's shape defaults to its last property's shape, but may be - * regenerated later as this scope diverges (from the property cache - * point of view) from the structural type associated with sprop. - */ - extend(cx, sprop); + sprop = getChildProperty(cx, lastProp, child); + } + if (sprop) { /* Store the tree node pointer in the table entry for id. */ if (table) SPROP_STORE_PRESERVING_COLLISION(spp, sprop); CHECK_ANCESTOR_LINE(this, false); #ifdef DEBUG - if (!overwriting) { - LIVE_SCOPE_METER(cx, ++cx->runtime->liveScopeProps); - JS_RUNTIME_METER(cx->runtime, totalScopeProps); - } + LIVE_SCOPE_METER(cx, ++cx->runtime->liveScopeProps); + JS_RUNTIME_METER(cx->runtime, totalScopeProps); #endif /* @@ -1371,65 +1328,156 @@ JSScope::add(JSContext *cx, jsid id, */ if (!table && entryCount >= SCOPE_HASH_THRESHOLD) (void) createTable(cx, false); + + METER(adds); + return sprop; } - METER(adds); - return sprop; - -fail_overwrite: - if (overwriting) { - /* - * We may or may not have forked overwriting out of this scope's - * ancestor line, so we must check (the alternative is to set a flag - * above, but that hurts the common, non-error case). If we did fork - * overwriting out, we'll add it back at scope->lastProp. This means - * enumeration order can change due to a failure to overwrite an id. - * XXXbe minor(?) incompatibility - */ - for (sprop = SCOPE_LAST_PROP(this); ; sprop = sprop->parent) { - if (!sprop) { - sprop = SCOPE_LAST_PROP(this); - if (overwriting->parent == sprop) { - lastProp = overwriting; - } else { - sprop = GetPropertyTreeChild(cx, sprop, overwriting); - if (sprop) { - JS_ASSERT(sprop != overwriting); - lastProp = sprop; - } - overwriting = sprop; - } - break; - } - if (sprop == overwriting) - break; - } - if (overwriting) { - if (table) - SPROP_STORE_PRESERVING_COLLISION(spp, overwriting); - entryCount++; - } - CHECK_ANCESTOR_LINE(this, true); - } - METER(addFailures); + METER(addFails); return NULL; } JSScopeProperty * -JSScope::change(JSContext *cx, JSScopeProperty *sprop, - uintN attrs, uintN mask, - JSPropertyOp getter, JSPropertyOp setter) +JSScope::putProperty(JSContext *cx, jsid id, + JSPropertyOp getter, JSPropertyOp setter, + uint32 slot, uintN attrs, + uintN flags, intN shortid) { - JSScopeProperty child, *newsprop, **spp; + JSScopeProperty **spp, *sprop, *overwriting; + JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, this)); + CHECK_ANCESTOR_LINE(this, true); + + JS_ASSERT(!JSVAL_IS_NULL(id)); + JS_ASSERT_IF(attrs & JSPROP_GETTER, getter); + JS_ASSERT_IF(attrs & JSPROP_SETTER, setter); + + JS_ASSERT_IF(!cx->runtime->gcRegenShapes, + hasRegenFlag(cx->runtime->gcRegenShapesScopeFlag)); + + if (sealed()) { + reportReadOnlyScope(cx); + return NULL; + } + + /* Search for id in order to claim its entry if table has been allocated. */ + spp = search(id, true); + sprop = SPROP_FETCH(spp); + if (!sprop) + return addPropertyHelper(cx, id, getter, setter, slot, attrs, flags, shortid, spp); + + /* Property exists: JSScope::search must have returned a valid *spp. */ + JS_ASSERT(!SPROP_IS_REMOVED(*spp)); + overwriting = sprop; + + NormalizeGetterAndSetter(cx, this, id, attrs, flags, getter, setter); + + /* + * If all property members match, this is a redundant add and we can + * return early. If the caller wants to allocate a slot, but doesn't + * care which slot, copy sprop->slot into slot so we can match sprop, + * if all other members match. + */ + if (!(attrs & JSPROP_SHARED) && + slot == SPROP_INVALID_SLOT && + SPROP_HAS_VALID_SLOT(sprop, this)) { + slot = sprop->slot; + } + if (SPROP_MATCH_PARAMS_AFTER_ID(sprop, getter, setter, slot, attrs, + flags, shortid)) { + METER(redundantPuts); + return sprop; + } + + /* + * If we are clearing sprop to force the existing property that it + * describes to be overwritten, then we have to unlink sprop from the + * ancestor line at this->lastProp. + * + * If sprop is not lastProp and this scope is not in dictionary mode, + * we must switch to dictionary mode so we can unlink the non-terminal + * sprop without breaking anyone sharing the property lineage via the + * runtime's property tree. + */ + if (sprop == lastProp && !inDictionaryMode()) { + removeLastProperty(); + } else { + if (!inDictionaryMode()) { + if (!toDictionaryMode(cx, sprop)) + return NULL; + spp = search(id, false); + } + removeDictionaryProperty(sprop); + } + + /* + * If we fail later on trying to find or create a new sprop, we will + * restore *spp from |overwriting|. Note that we don't bother to keep + * this->removedCount in sync, because we will fix up both *spp and + * this->entryCount shortly. + */ + if (table) + SPROP_STORE_PRESERVING_COLLISION(spp, NULL); + CHECK_ANCESTOR_LINE(this, true); + + { + JSScopeProperty child; + + /* Find or create a property tree node labeled by our arguments. */ + child.id = id; + child.getter = getter; + child.setter = setter; + child.slot = slot; + child.attrs = attrs; + child.flags = flags; + child.shortid = shortid; + sprop = getChildProperty(cx, lastProp, child); + } + + if (sprop) { + /* Store the tree node pointer in the table entry for id. */ + if (table) + SPROP_STORE_PRESERVING_COLLISION(spp, sprop); + CHECK_ANCESTOR_LINE(this, false); + + /* See comment in JSScope::addPropertyHelper about ignoring OOM here. */ + if (!table && entryCount >= SCOPE_HASH_THRESHOLD) + (void) createTable(cx, false); + + METER(puts); + return sprop; + } + + if (table) + SPROP_STORE_PRESERVING_COLLISION(spp, overwriting); + ++entryCount; + CHECK_ANCESTOR_LINE(this, true); + METER(putFails); + return NULL; +} + +JSScopeProperty * +JSScope::changeProperty(JSContext *cx, JSScopeProperty *sprop, + uintN attrs, uintN mask, + JSPropertyOp getter, JSPropertyOp setter) +{ + JSScopeProperty child, *newsprop; + + JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, this)); CHECK_ANCESTOR_LINE(this, true); JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); + JS_ASSERT(hasProperty(sprop)); + + attrs |= sprop->attrs & mask; /* Allow only shared (slot-less) => unshared (slot-full) transition. */ - attrs |= sprop->attrs & mask; JS_ASSERT(!((attrs ^ sprop->attrs) & JSPROP_SHARED) || !(attrs & JSPROP_SHARED)); + + /* Don't allow method properties to be changed to accessor properties. */ + JS_ASSERT(!(sprop->flags & SPROP_IS_METHOD)); + if (getter == JS_PropertyStub) getter = NULL; if (setter == JS_PropertyStub) @@ -1448,53 +1496,48 @@ JSScope::change(JSContext *cx, JSScopeProperty *sprop, child.flags = sprop->flags; child.shortid = sprop->shortid; - if (SCOPE_LAST_PROP(this) == sprop) { - /* - * Optimize the case where the last property added to this scope is - * changed to have a different attrs, getter, or setter. In the last - * property case, we need not fork the property tree. But since we do - * not call JSScope::add, we may need to allocate a new slot directly. - */ - if ((sprop->attrs & JSPROP_SHARED) && !(attrs & JSPROP_SHARED)) { - JS_ASSERT(child.slot == SPROP_INVALID_SLOT); - if (!js_AllocSlot(cx, object, &child.slot)) - return NULL; - } - - newsprop = GetPropertyTreeChild(cx, sprop->parent, &child); + if (inDictionaryMode()) { + removeDictionaryProperty(sprop); + newsprop = newDictionaryProperty(cx, child, &lastProp); if (newsprop) { - spp = search(sprop->id, false); - JS_ASSERT(SPROP_FETCH(spp) == sprop); - - if (table) + if (table) { + JSScopeProperty **spp = search(sprop->id, false); SPROP_STORE_PRESERVING_COLLISION(spp, newsprop); - lastProp = newsprop; + } + updateShape(cx); + } + } else if (sprop == lastProp) { + newsprop = getChildProperty(cx, sprop->parent, child); + if (newsprop) { + if (table) { + JSScopeProperty **spp = search(sprop->id, false); + JS_ASSERT(SPROP_FETCH(spp) == sprop); + SPROP_STORE_PRESERVING_COLLISION(spp, newsprop); + } CHECK_ANCESTOR_LINE(this, true); } } else { /* - * Let JSScope::add handle this |overwriting| case, including the - * conservation of sprop->slot (if it's valid). We must not call + * Let JSScope::putProperty handle this |overwriting| case, including + * the conservation of sprop->slot (if it's valid). We must not call * JSScope::remove here, because it will free a valid sprop->slot and - * JSScope::add won't re-allocate it. + * JSScope::putProperty won't re-allocate it. */ - newsprop = add(cx, child.id, child.getter, child.setter, child.slot, - child.attrs, child.flags, child.shortid); + newsprop = putProperty(cx, child.id, child.getter, child.setter, child.slot, + child.attrs, child.flags, child.shortid); } - if (newsprop) { - js_LeaveTraceIfGlobalObject(cx, object); - replacingShapeChange(cx, sprop, newsprop); - } -#ifdef JS_DUMP_PROPTREE_STATS +#ifdef DEBUG + if (newsprop) + METER(changes); else - METER(changeFailures); + METER(changeFails); #endif return newsprop; } bool -JSScope::remove(JSContext *cx, jsid id) +JSScope::removeProperty(JSContext *cx, jsid id) { JSScopeProperty **spp, *stored, *sprop; uint32 size; @@ -1505,7 +1548,6 @@ JSScope::remove(JSContext *cx, jsid id) reportReadOnlyScope(cx); return false; } - METER(removes); spp = search(id, false); stored = *spp; @@ -1515,13 +1557,14 @@ JSScope::remove(JSContext *cx, jsid id) return true; } - /* Convert from a list to a hash so we can handle "middle deletes". */ - if (!table && sprop != lastProp) { - if (!createTable(cx, true)) - return false; - spp = search(id, false); - stored = *spp; - sprop = SPROP_CLEAR_COLLISION(stored); + /* If sprop is not the last property added, switch to dictionary mode. */ + if (sprop != lastProp) { + if (!inDictionaryMode()) { + if (!toDictionaryMode(cx, sprop)) + return false; + spp = search(id, false); + } + JS_ASSERT(SPROP_FETCH(spp) == sprop); } /* First, if sprop is unshared and not cleared, free its slot number. */ @@ -1534,29 +1577,28 @@ JSScope::remove(JSContext *cx, jsid id) if (SPROP_HAD_COLLISION(stored)) { JS_ASSERT(table); *spp = SPROP_REMOVED; - removedCount++; + ++removedCount; } else { METER(removeFrees); if (table) *spp = NULL; } - entryCount--; LIVE_SCOPE_METER(cx, --cx->runtime->liveScopeProps); - /* Update this->lastProp directly, or set its deferred update flag. */ - if (sprop == SCOPE_LAST_PROP(this)) { - do { - SCOPE_REMOVE_LAST_PROP(this); - if (!hadMiddleDelete()) - break; - sprop = SCOPE_LAST_PROP(this); - } while (sprop && !has(sprop)); - if (!SCOPE_LAST_PROP(this)) - clearMiddleDelete(); - } else if (!hadMiddleDelete()) { - setMiddleDelete(); + if (inDictionaryMode()) { + /* + * Remove sprop from its scope-owned doubly linked list, setting this + * scope's OWN_SHAPE flag first if sprop is lastProp so updateShape(cx) + * after this if-else will generate a fresh shape for this scope. + */ + if (sprop != lastProp) + setOwnShape(); + removeDictionaryProperty(sprop); + } else { + JS_ASSERT(sprop == lastProp); + removeLastProperty(); } - generateOwnShape(cx); + updateShape(cx); CHECK_ANCESTOR_LINE(this, true); /* Last, consider shrinking this->table if its load factor is <= .25. */ @@ -1566,6 +1608,7 @@ JSScope::remove(JSContext *cx, jsid id) (void) changeTable(cx, -1); } + METER(removes); return true; } @@ -1577,7 +1620,8 @@ JSScope::clear(JSContext *cx) if (table) js_free(table); - clearMiddleDelete(); + clearDictionaryMode(); + clearOwnShape(); js_LeaveTraceIfGlobalObject(cx, object); JSClass *clasp = object->getClass(); @@ -1629,9 +1673,9 @@ JSScope::methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval) * despecializing from a method memoized in the property tree to a * plain old function-valued property. */ - sprop = add(cx, sprop->id, NULL, sprop->setter, sprop->slot, - sprop->attrs, sprop->flags & ~SPROP_IS_METHOD, - sprop->shortid); + sprop = putProperty(cx, sprop->id, NULL, sprop->setter, sprop->slot, + sprop->attrs, sprop->flags & ~SPROP_IS_METHOD, + sprop->shortid); if (!sprop) return false; } @@ -1648,7 +1692,7 @@ JSScope::methodShapeChange(JSContext *cx, uint32 slot, jsval toval) } else { for (JSScopeProperty *sprop = lastProp; sprop; sprop = sprop->parent) { JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); - if (sprop->slot == slot && (!hadMiddleDelete() || has(sprop))) + if (sprop->slot == slot) return methodShapeChange(cx, sprop, toval); } } @@ -1661,16 +1705,6 @@ JSScope::protoShapeChange(JSContext *cx) generateOwnShape(cx); } -void -JSScope::replacingShapeChange(JSContext *cx, JSScopeProperty *sprop, JSScopeProperty *newsprop) -{ - JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); - if (shape == sprop->shape) - shape = newsprop->shape; - else - generateOwnShape(cx); -} - void JSScope::sealingShapeChange(JSContext *cx) { @@ -1765,7 +1799,7 @@ JSScopeProperty::trace(JSTracer *trc) } } -#ifdef JS_DUMP_PROPTREE_STATS +#ifdef DEBUG #include @@ -1868,7 +1902,7 @@ DumpSubtree(JSContext *cx, JSScopeProperty *sprop, int level, FILE *fp) } } -#endif /* JS_DUMP_PROPTREE_STATS */ +#endif /* DEBUG */ void js_SweepScopeProperties(JSContext *cx) @@ -1880,18 +1914,20 @@ js_SweepScopeProperties(JSContext *cx) PropTreeKidsChunk *chunk, *nextChunk, *freeChunk; uintN i; -#ifdef JS_DUMP_PROPTREE_STATS +#ifdef DEBUG JSBasicStats bs; uint32 livePropCapacity = 0, totalLiveCount = 0; static FILE *logfp; - if (!logfp) - logfp = fopen("/tmp/proptree.stats", "w"); + if (!logfp) { + if (const char *filename = getenv("JS_PROPTREE_STATFILE")) + logfp = fopen(filename, "w"); + } - JS_BASIC_STATS_INIT(&bs); - MeterKidCount(&bs, rt->propertyTreeHash.entryCount); - JS_DHashTableEnumerate(&rt->propertyTreeHash, js_MeterPropertyTree, &bs); + if (logfp) { + JS_BASIC_STATS_INIT(&bs); + MeterKidCount(&bs, rt->propertyTreeHash.entryCount); + JS_DHashTableEnumerate(&rt->propertyTreeHash, js_MeterPropertyTree, &bs); - { double props, nodes, mean, sigma; props = rt->liveScopePropsPreSweep; @@ -1902,9 +1938,9 @@ js_SweepScopeProperties(JSContext *cx) fprintf(logfp, "props %g nodes %g beta %g meankids %g sigma %g max %u\n", props, nodes, nodes / props, mean, sigma, bs.max); - } - JS_DumpHistogram(&bs, logfp); + JS_DumpHistogram(&bs, logfp); + } #endif ap = &rt->propertyArenaPool.first.next; @@ -1936,90 +1972,92 @@ js_SweepScopeProperties(JSContext *cx) continue; } - /* Ok, sprop is garbage to collect: unlink it from its parent. */ - freeChunk = RemovePropertyTreeChild(rt, sprop); + if (!(sprop->flags & SPROP_IN_DICTIONARY)) { + /* Ok, sprop is garbage to collect: unlink it from its parent. */ + freeChunk = RemovePropertyTreeChild(rt, sprop); - /* - * Take care to reparent all sprop's kids to their grandparent. - * InsertPropertyTreeChild can potentially fail for two reasons: - * - * 1. If parent is null, insertion into the root property hash - * table may fail. We are forced to leave the kid out of the - * table (as can already happen with duplicates) but ensure - * that the kid's parent pointer is set to null. - * - * 2. If parent is non-null, allocation of a new KidsChunk can - * fail. To prevent this from happening, we allow sprops's own - * chunks to be reused by the grandparent, which removes the - * need for InsertPropertyTreeChild to malloc a new KidsChunk. - * - * If sprop does not have chunky kids, then we rely on the - * RemovePropertyTreeChild call above (which removed sprop from - * its parent) either leaving one free entry, or else returning - * the now-unused chunk to us so we can reuse it. - * - * We also require the grandparent to have either no kids or else - * chunky kids. A single non-chunky kid would force a new chunk to - * be malloced in some cases (if sprop had a single non-chunky - * kid, or a multiple of MAX_KIDS_PER_CHUNK kids). Note that - * RemovePropertyTreeChild never converts a single-entry chunky - * kid back to a non-chunky kid, so we are assured of correct - * behaviour. - */ - kids = sprop->kids; - if (kids) { - sprop->kids = NULL; - parent = sprop->parent; + /* + * Take care to reparent all sprop's kids to their grandparent. + * InsertPropertyTreeChild can potentially fail for two reasons: + * + * 1. If parent is null, insertion into the root property hash + * table may fail. We are forced to leave the kid out of the + * table (as can already happen with duplicates) but ensure + * that the kid's parent pointer is set to null. + * + * 2. If parent is non-null, allocation of a new KidsChunk can + * fail. To prevent this from happening, we allow sprops's own + * chunks to be reused by the grandparent, which removes the + * need for InsertPropertyTreeChild to malloc a new KidsChunk. + * + * If sprop does not have chunky kids, then we rely on the + * RemovePropertyTreeChild call above (which removed sprop from + * its parent) either leaving one free entry, or else returning + * the now-unused chunk to us so we can reuse it. + * + * We also require the grandparent to have either no kids or else + * chunky kids. A single non-chunky kid would force a new chunk to + * be malloced in some cases (if sprop had a single non-chunky + * kid, or a multiple of MAX_KIDS_PER_CHUNK kids). Note that + * RemovePropertyTreeChild never converts a single-entry chunky + * kid back to a non-chunky kid, so we are assured of correct + * behaviour. + */ + kids = sprop->kids; + if (kids) { + sprop->kids = NULL; + parent = sprop->parent; - /* The grandparent must have either no kids or chunky kids. */ - JS_ASSERT(!parent || !parent->kids || - KIDS_IS_CHUNKY(parent->kids)); - if (KIDS_IS_CHUNKY(kids)) { - chunk = KIDS_TO_CHUNK(kids); - do { - nextChunk = chunk->next; - chunk->next = NULL; - for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) { - kid = chunk->kids[i]; - if (!kid) - break; - JS_ASSERT(kid->parent == sprop); + /* The grandparent must have either no kids or chunky kids. */ + JS_ASSERT(!parent || !parent->kids || + KIDS_IS_CHUNKY(parent->kids)); + if (KIDS_IS_CHUNKY(kids)) { + chunk = KIDS_TO_CHUNK(kids); + do { + nextChunk = chunk->next; + chunk->next = NULL; + for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) { + kid = chunk->kids[i]; + if (!kid) + break; + JS_ASSERT(kid->parent == sprop); - /* - * Clear a space in the kids array for possible - * re-use by InsertPropertyTreeChild. - */ - chunk->kids[i] = NULL; - if (!InsertPropertyTreeChild(rt, parent, kid, chunk)) { /* - * This can happen only if we failed to add an - * entry to the root property hash table. + * Clear a space in the kids array for possible + * re-use by InsertPropertyTreeChild. */ - JS_ASSERT(!parent); - kid->parent = NULL; + chunk->kids[i] = NULL; + if (!InsertPropertyTreeChild(rt, parent, kid, chunk)) { + /* + * This can happen only if we failed to add an + * entry to the root property hash table. + */ + JS_ASSERT(!parent); + kid->parent = NULL; + } } + if (!chunk->kids[0]) { + /* The chunk wasn't reused, so we must free it. */ + DestroyPropTreeKidsChunk(rt, chunk); + } + } while ((chunk = nextChunk) != NULL); + } else { + kid = kids; + if (!InsertPropertyTreeChild(rt, parent, kid, freeChunk)) { + /* + * This can happen only if we failed to add an entry + * to the root property hash table. + */ + JS_ASSERT(!parent); + kid->parent = NULL; } - if (!chunk->kids[0]) { - /* The chunk wasn't reused, so we must free it. */ - DestroyPropTreeKidsChunk(rt, chunk); - } - } while ((chunk = nextChunk) != NULL); - } else { - kid = kids; - if (!InsertPropertyTreeChild(rt, parent, kid, freeChunk)) { - /* - * This can happen only if we failed to add an entry - * to the root property hash table. - */ - JS_ASSERT(!parent); - kid->parent = NULL; } } - } - if (freeChunk && !freeChunk->kids[0]) { - /* The chunk wasn't reused, so we must free it. */ - DestroyPropTreeKidsChunk(rt, freeChunk); + if (freeChunk && !freeChunk->kids[0]) { + /* The chunk wasn't reused, so we must free it. */ + DestroyPropTreeKidsChunk(rt, freeChunk); + } } /* Clear id so we know (above) that sprop is on the freelist. */ @@ -2034,7 +2072,7 @@ js_SweepScopeProperties(JSContext *cx) FREENODE_REMOVE(sprop); JS_ARENA_DESTROY(&rt->propertyArenaPool, a, ap); } else { -#ifdef JS_DUMP_PROPTREE_STATS +#ifdef DEBUG livePropCapacity += limit - (JSScopeProperty *) a->base; totalLiveCount += liveCount; #endif @@ -2042,60 +2080,79 @@ js_SweepScopeProperties(JSContext *cx) } } -#ifdef JS_DUMP_PROPTREE_STATS - fprintf(logfp, "arenautil %g%%\n", - (totalLiveCount && livePropCapacity) - ? (totalLiveCount * 100.0) / livePropCapacity - : 0.0); +#ifdef DEBUG + if (logfp) { + fprintf(logfp, + "\nProperty tree stats for gcNumber %lu\n", + (unsigned long) rt->gcNumber); + + fprintf(logfp, "arenautil %g%%\n", + (totalLiveCount && livePropCapacity) + ? (totalLiveCount * 100.0) / livePropCapacity + : 0.0); #define RATE(f1, f2) (((double)js_scope_stats.f1 / js_scope_stats.f2) * 100.0) - fprintf(logfp, "Scope search stats:\n" - " searches: %6u\n" - " hits: %6u %5.2f%% of searches\n" - " misses: %6u %5.2f%%\n" - " hashes: %6u %5.2f%%\n" - " steps: %6u %5.2f%% %5.2f%% of hashes\n" - " stepHits: %6u %5.2f%% %5.2f%%\n" - " stepMisses: %6u %5.2f%% %5.2f%%\n" - " adds: %6u\n" - " redundantAdds: %6u\n" - " addFailures: %6u\n" - " changeFailures: %6u\n" - " compresses: %6u\n" - " grows: %6u\n" - " removes: %6u\n" - " removeFrees: %6u\n" - " uselessRemoves: %6u\n" - " shrinks: %6u\n", - js_scope_stats.searches, - js_scope_stats.hits, RATE(hits, searches), - js_scope_stats.misses, RATE(misses, searches), - js_scope_stats.hashes, RATE(hashes, searches), - js_scope_stats.steps, RATE(steps, searches), RATE(steps, hashes), - js_scope_stats.stepHits, - RATE(stepHits, searches), RATE(stepHits, hashes), - js_scope_stats.stepMisses, - RATE(stepMisses, searches), RATE(stepMisses, hashes), - js_scope_stats.adds, - js_scope_stats.redundantAdds, - js_scope_stats.addFailures, - js_scope_stats.changeFailures, - js_scope_stats.compresses, - js_scope_stats.grows, - js_scope_stats.removes, - js_scope_stats.removeFrees, - js_scope_stats.uselessRemoves, - js_scope_stats.shrinks); + fprintf(logfp, + "Scope search stats:\n" + " searches: %6u\n" + " hits: %6u %5.2f%% of searches\n" + " misses: %6u %5.2f%%\n" + " hashes: %6u %5.2f%%\n" + " steps: %6u %5.2f%% %5.2f%% of hashes\n" + " stepHits: %6u %5.2f%% %5.2f%%\n" + " stepMisses: %6u %5.2f%% %5.2f%%\n" + " tableAllocFails %6u\n" + " toDictFails %6u\n" + " wrapWatchFails %6u\n" + " adds: %6u\n" + " addFails: %6u\n" + " puts: %6u\n" + " redundantPuts: %6u\n" + " putFails: %6u\n" + " changes: %6u\n" + " changeFails: %6u\n" + " compresses: %6u\n" + " grows: %6u\n" + " removes: %6u\n" + " removeFrees: %6u\n" + " uselessRemoves: %6u\n" + " shrinks: %6u\n", + js_scope_stats.searches, + js_scope_stats.hits, RATE(hits, searches), + js_scope_stats.misses, RATE(misses, searches), + js_scope_stats.hashes, RATE(hashes, searches), + js_scope_stats.steps, RATE(steps, searches), RATE(steps, hashes), + js_scope_stats.stepHits, + RATE(stepHits, searches), RATE(stepHits, hashes), + js_scope_stats.stepMisses, + RATE(stepMisses, searches), RATE(stepMisses, hashes), + js_scope_stats.tableAllocFails, + js_scope_stats.toDictFails, + js_scope_stats.wrapWatchFails, + js_scope_stats.adds, + js_scope_stats.addFails, + js_scope_stats.puts, + js_scope_stats.redundantPuts, + js_scope_stats.putFails, + js_scope_stats.changes, + js_scope_stats.changeFails, + js_scope_stats.compresses, + js_scope_stats.grows, + js_scope_stats.removes, + js_scope_stats.removeFrees, + js_scope_stats.uselessRemoves, + js_scope_stats.shrinks); #undef RATE - fflush(logfp); -#endif + fflush(logfp); + } -#ifdef DUMP_PROPERTY_TREE - { - FILE *dumpfp = fopen("/tmp/proptree.dump", "w"); + if (const char *filename = getenv("JS_PROPTREE_DUMPFILE")) { + char pathname[1024]; + JS_snprintf(pathname, sizeof pathname, "%s.%lu", filename, (unsigned long)rt->gcNumber); + FILE *dumpfp = fopen(pathname, "w"); if (dumpfp) { JSPropertyTreeEntry *pte, *end; @@ -2109,7 +2166,7 @@ js_SweepScopeProperties(JSContext *cx) fclose(dumpfp); } } -#endif +#endif /* DEBUG */ } bool diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 0988606a4ed4..9044c49b796b 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -114,10 +114,10 @@ JS_BEGIN_EXTERN_C * skipping nodes that lack entries. * * What if we add Y again? X->Y->Z->Y is wrong and we'll enumerate Y twice. - * Therefore we must fork in such a case, if not earlier. Because delete is - * "bursty", we should not fork eagerly. Delaying a fork till we are at risk - * of adding Y after it was deleted already requires a flag in the JSScope, to - * wit, SCOPE_MIDDLE_DELETE. + * Therefore we must fork in such a case if not earlier, or do something else. + * We used to fork on the theory that set after delete is rare, but the Web is + * a harsh mistress, and we now convert the scope to a "dictionary" on first + * delete, to avoid O(n^2) growth in the property tree. * * What about thread safety? If the property tree operations done by requests * are find-node and insert-node, then the only hazard is duplicate insertion. @@ -195,13 +195,15 @@ JS_BEGIN_EXTERN_C * in Mozilla is < 5, with a large standard deviation (~8). Instead of always * allocating scope->table, we leave it null while initializing all the other * scope members as if it were non-null and minimal-length. Until a property - * is added that crosses the threshold of 6 or more entries for hashing, or - * until a "middle delete" occurs, we use linear search from scope->lastProp - * to find a given id, and save on the space overhead of a hash table. + * is added that crosses the threshold of 6 or more entries for hashing, we use + * linear search from scope->lastProp to find a given id, and save on the space + * overhead of a hash table. */ struct JSEmptyScope; +#define SPROP_INVALID_SLOT 0xffffffff + struct JSScope : public JSObjectMap { #ifdef JS_THREADSAFE @@ -218,9 +220,44 @@ struct JSScope : public JSObjectMap uint32 entryCount; /* number of entries in table */ uint32 removedCount; /* removed entry sentinels in table */ JSScopeProperty **table; /* table of ptrs to shared tree nodes */ - JSScopeProperty *lastProp; /* pointer to last property added */ + + /* + * A little information hiding for scope->lastProp, in case it ever becomes + * a tagged pointer again. + */ + inline JSScopeProperty *lastProperty() const; private: + JSScopeProperty *getChildProperty(JSContext *cx, JSScopeProperty *parent, + JSScopeProperty &child); + + JSScopeProperty *newDictionaryProperty(JSContext *cx, const JSScopeProperty &child, + JSScopeProperty **childp); + + bool toDictionaryMode(JSContext *cx, JSScopeProperty *&aprop); + + /* + * Private pointer to the last added property and methods to manipulate the + * list it links among properties in this scope. The {remove,insert} pair + * for DictionaryProperties assert that the scope is in dictionary mode and + * any reachable properties are flagged as dictionary properties. + * + * NB: these private methods do *not* update this scope's shape to track + * lastProp->shape after they finish updating the linked list in the case + * where lastProp is updated. It is up to calling code in jsscope.cpp to + * call updateShape(cx) after updating lastProp. + */ + JSScopeProperty *lastProp; + + /* These four inline methods are defined further below in this .h file. */ + inline void setLastProperty(JSScopeProperty *sprop); + inline void removeLastProperty(); + inline void removeDictionaryProperty(JSScopeProperty *sprop); + inline void insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **childp); + + /* Defined in jsscopeinlines.h to avoid including implementation dependencies here. */ + inline void updateShape(JSContext *cx); + void initMinimal(JSContext *cx, uint32 newShape); bool createTable(JSContext *cx, bool report); bool changeTable(JSContext *cx, int change); @@ -230,6 +267,12 @@ struct JSScope : public JSObjectMap inline JSScopeProperty **search(jsid id, bool adding); JSEmptyScope *createEmptyScope(JSContext *cx, JSClass *clasp); + JSScopeProperty *addPropertyHelper(JSContext *cx, jsid id, + JSPropertyOp getter, JSPropertyOp setter, + uint32 slot, uintN attrs, + uintN flags, intN shortid, + JSScopeProperty **spp); + public: explicit JSScope(const JSObjectOps *ops, JSObject *obj = NULL) : JSObjectMap(ops, 0), object(obj) {} @@ -253,27 +296,48 @@ struct JSScope : public JSObjectMap inline JSEmptyScope *getEmptyScope(JSContext *cx, JSClass *clasp); inline bool canProvideEmptyScope(JSObjectOps *ops, JSClass *clasp); - + JSScopeProperty *lookup(jsid id); - bool has(JSScopeProperty *sprop); - JSScopeProperty *add(JSContext *cx, jsid id, - JSPropertyOp getter, JSPropertyOp setter, - uint32 slot, uintN attrs, - uintN flags, intN shortid); + inline bool hasProperty(jsid id) { return lookup(id) != NULL; } + inline bool hasProperty(JSScopeProperty *sprop); - JSScopeProperty *change(JSContext *cx, JSScopeProperty *sprop, - uintN attrs, uintN mask, - JSPropertyOp getter, JSPropertyOp setter); + /* Add a property whose id is not yet in this scope. */ + JSScopeProperty *addProperty(JSContext *cx, jsid id, + JSPropertyOp getter, JSPropertyOp setter, + uint32 slot, uintN attrs, + uintN flags, intN shortid); - bool remove(JSContext *cx, jsid id); + /* Add a data property whose id is not yet in this scope. */ + JSScopeProperty *addDataProperty(JSContext *cx, jsid id, uint32 slot, uintN attrs) { + JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER))); + return addProperty(cx, id, NULL, NULL, slot, attrs, 0, 0); + } + + /* Add or overwrite a property for id in this scope. */ + JSScopeProperty *putProperty(JSContext *cx, jsid id, + JSPropertyOp getter, JSPropertyOp setter, + uint32 slot, uintN attrs, + uintN flags, intN shortid); + + /* Change the given property into a sibling with the same id in this scope. */ + JSScopeProperty *changeProperty(JSContext *cx, JSScopeProperty *sprop, + uintN attrs, uintN mask, + JSPropertyOp getter, JSPropertyOp setter); + + /* Remove id from this scope. */ + bool removeProperty(JSContext *cx, jsid id); + + /* Clear the scope, making it empty. */ void clear(JSContext *cx); + /* Extend this scope to have sprop as its last-added property. */ void extend(JSContext *cx, JSScopeProperty *sprop); /* * Read barrier to clone a joined function object stored as a method. - * Defined inline further below. + * Defined in jsscopeinlines.h, but not declared inline per standard style + * in order to avoid gcc warnings. */ bool methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp); @@ -294,15 +358,14 @@ struct JSScope : public JSObjectMap bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval); bool methodShapeChange(JSContext *cx, uint32 slot, jsval toval); void protoShapeChange(JSContext *cx); - void replacingShapeChange(JSContext *cx, JSScopeProperty *sprop, JSScopeProperty *newsprop); void sealingShapeChange(JSContext *cx); void shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop); /* By definition, hashShift = JS_DHASH_BITS - log2(capacity). */ -#define SCOPE_CAPACITY(scope) JS_BIT(JS_DHASH_BITS-(scope)->hashShift) +#define SCOPE_CAPACITY(scope) JS_BIT(JS_DHASH_BITS-(scope)->hashShift) enum { - MIDDLE_DELETE = 0x0001, + DICTIONARY_MODE = 0x0001, SEALED = 0x0002, BRANDED = 0x0004, INDEXED_PROPERTIES = 0x0008, @@ -316,9 +379,9 @@ struct JSScope : public JSObjectMap SHAPE_REGEN = 0x0040 }; - bool hadMiddleDelete() { return flags & MIDDLE_DELETE; } - void setMiddleDelete() { flags |= MIDDLE_DELETE; } - void clearMiddleDelete() { flags &= ~MIDDLE_DELETE; } + bool inDictionaryMode() { return flags & DICTIONARY_MODE; } + void setDictionaryMode() { flags |= DICTIONARY_MODE; } + void clearDictionaryMode() { flags &= ~DICTIONARY_MODE; } /* * Don't define clearSealed, as it can't be done safely because JS_LOCK_OBJ @@ -341,6 +404,7 @@ struct JSScope : public JSObjectMap bool hasOwnShape() { return flags & OWN_SHAPE; } void setOwnShape() { flags |= OWN_SHAPE; } + void clearOwnShape() { flags &= ~OWN_SHAPE; } bool hasRegenFlag(uint8 regenFlag) { return (flags & SHAPE_REGEN) == regenFlag; } @@ -427,18 +491,6 @@ OBJ_SHAPE(JSObject *obj) return obj->map->shape; } -/* - * A little information hiding for scope->lastProp, in case it ever becomes - * a tagged pointer again. - */ -#define SCOPE_LAST_PROP(scope) \ - (JS_ASSERT_IF((scope)->lastProp, !JSVAL_IS_NULL((scope)->lastProp->id)), \ - (scope)->lastProp) -#define SCOPE_REMOVE_LAST_PROP(scope) \ - (JS_ASSERT_IF((scope)->lastProp->parent, \ - !JSVAL_IS_NULL((scope)->lastProp->parent->id)), \ - (scope)->lastProp = (scope)->lastProp->parent) - /* * Helpers for reinterpreting JSPropertyOp as JSObject* for scripted getters * and setters. @@ -471,8 +523,14 @@ struct JSScopeProperty { uint8 flags; /* flags, see below for defines */ int16 shortid; /* tinyid, or local arg/var index */ JSScopeProperty *parent; /* parent node, reverse for..in order */ - JSScopeProperty *kids; /* null, single child, or a tagged ptr + union { + JSScopeProperty *kids; /* null, single child, or a tagged ptr to many-kids data structure */ + JSScopeProperty **childp; /* dictionary list starting at lastProp + has a double-indirect back pointer, + either to sprop->parent if not last, + else to scope->lastProp */ + }; uint32 shape; /* property cache shape identifier */ /* Bits stored in sprop->flags. */ @@ -481,6 +539,7 @@ struct JSScopeProperty { #define SPROP_HAS_SHORTID 0x04 #define SPROP_FLAG_SHAPE_REGEN 0x08 #define SPROP_IS_METHOD 0x10 +#define SPROP_IN_DICTIONARY 0x20 bool isMethod() const { return flags & SPROP_IS_METHOD; @@ -551,11 +610,85 @@ JSScope::lookup(jsid id) } inline bool -JSScope::has(JSScopeProperty *sprop) +JSScope::hasProperty(JSScopeProperty *sprop) { return lookup(sprop->id) == sprop; } +inline JSScopeProperty * +JSScope::lastProperty() const +{ + JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id)); + return lastProp; +} + +/* + * Note that sprop must not be null, as emptying a scope requires extra work + * done only by methods in jsscope.cpp. + */ +inline void +JSScope::setLastProperty(JSScopeProperty *sprop) +{ + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); + JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id)); + + lastProp = sprop; +} + +inline void +JSScope::removeLastProperty() +{ + JS_ASSERT(!inDictionaryMode()); + JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id)); + + lastProp = lastProp->parent; + --entryCount; +} + +inline void +JSScope::removeDictionaryProperty(JSScopeProperty *sprop) +{ + JS_ASSERT(inDictionaryMode()); + JS_ASSERT(sprop->flags & SPROP_IN_DICTIONARY); + JS_ASSERT(sprop->childp); + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); + + JS_ASSERT(lastProp->flags & SPROP_IN_DICTIONARY); + JS_ASSERT(lastProp->childp == &lastProp); + JS_ASSERT_IF(lastProp != sprop, !JSVAL_IS_NULL(lastProp->id)); + JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id)); + + if (sprop->parent) + sprop->parent->childp = sprop->childp; + *sprop->childp = sprop->parent; + --entryCount; + sprop->childp = NULL; +} + +inline void +JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **childp) +{ + /* + * Don't assert inDictionaryMode() here because we may be called from + * toDictionaryMode via newDictionaryProperty. + */ + JS_ASSERT(sprop->flags & SPROP_IN_DICTIONARY); + JS_ASSERT(!sprop->childp); + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); + + JS_ASSERT_IF(*childp, (*childp)->flags & SPROP_IN_DICTIONARY); + JS_ASSERT_IF(lastProp, lastProp->flags & SPROP_IN_DICTIONARY); + JS_ASSERT_IF(lastProp, lastProp->childp == &lastProp); + JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id)); + + sprop->parent = *childp; + *childp = sprop; + if (sprop->parent) + sprop->parent->childp = &sprop->parent; + sprop->childp = childp; + ++entryCount; +} + /* * If SPROP_HAS_SHORTID is set in sprop->flags, we use sprop->shortid rather * than id when calling sprop's getter or setter. @@ -564,8 +697,6 @@ JSScope::has(JSScopeProperty *sprop) (((sprop)->flags & SPROP_HAS_SHORTID) ? INT_TO_JSVAL((sprop)->shortid) \ : ID_TO_VALUE((sprop)->id)) -#define SPROP_INVALID_SLOT 0xffffffff - #define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot) #define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope) @@ -582,7 +713,7 @@ JSScope::has(JSScopeProperty *sprop) extern uint32 js_GenerateShape(JSContext *cx, bool gcLocked); -#ifdef JS_DUMP_PROPTREE_STATS +#ifdef DEBUG struct JSScopeStats { jsrefcount searches; jsrefcount hits; @@ -591,10 +722,16 @@ struct JSScopeStats { jsrefcount steps; jsrefcount stepHits; jsrefcount stepMisses; + jsrefcount tableAllocFails; + jsrefcount toDictFails; + jsrefcount wrapWatchFails; jsrefcount adds; - jsrefcount redundantAdds; - jsrefcount addFailures; - jsrefcount changeFailures; + jsrefcount addFails; + jsrefcount puts; + jsrefcount redundantPuts; + jsrefcount putFails; + jsrefcount changes; + jsrefcount changeFails; jsrefcount compresses; jsrefcount grows; jsrefcount removes; @@ -618,7 +755,6 @@ JSScope::search(jsid id, bool adding) METER(searches); if (!table) { /* Not enough properties to justify hashing: search from lastProp. */ - JS_ASSERT(!hadMiddleDelete()); for (spp = &lastProp; (sprop = *spp); spp = &sprop->parent) { if (sprop->id == id) { METER(hits); diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index 46c7b960a744..b572d332b038 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -41,20 +41,26 @@ #define jsscopeinlines_h___ #include "jscntxt.h" +#include "jsdbgapi.h" #include "jsfun.h" -#include "jsinterp.h" #include "jsobj.h" #include "jsscope.h" +inline void +JSScope::updateShape(JSContext *cx) +{ + JS_ASSERT(object); + js_LeaveTraceIfGlobalObject(cx, object); + + shape = (hasOwnShape() || !lastProp) ? js_GenerateShape(cx, false) : lastProp->shape; +} + inline void JSScope::extend(JSContext *cx, JSScopeProperty *sprop) { - js_LeaveTraceIfGlobalObject(cx, object); - shape = (!lastProp || shape == lastProp->shape) - ? sprop->shape - : js_GenerateShape(cx, false); ++entryCount; - lastProp = sprop; + setLastProperty(sprop); + updateShape(cx); jsuint index; if (js_IdIsIndex(sprop->id, &index)) @@ -72,7 +78,7 @@ inline bool JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp) { JS_ASSERT(hasMethodBarrier()); - JS_ASSERT(has(sprop)); + JS_ASSERT(hasProperty(sprop)); JS_ASSERT(sprop->isMethod()); JS_ASSERT(sprop->methodValue() == *vp); JS_ASSERT(object->getClass() == &js_ObjectClass); @@ -148,12 +154,10 @@ JSScope::trace(JSTracer *trc) } } if (sprop) { - JS_ASSERT(has(sprop)); + JS_ASSERT(hasProperty(sprop)); /* Trace scope's property tree ancestor line. */ do { - if (hadMiddleDelete() && !has(sprop)) - continue; sprop->trace(trc); } while ((sprop = sprop->parent) != NULL); } diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 50afdd6ef9bd..08c9f3f104e1 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -5482,7 +5482,7 @@ Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length) return ucs4Char; } -#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS +#ifdef DEBUG JS_FRIEND_API(size_t) js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp, diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 637976b58a57..4ec2a54ac396 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -8937,7 +8937,7 @@ DumpShape(JSObject* obj, const char* prefix) } fprintf(shapefp, "\n%s: shape %u flags %x\n", prefix, scope->shape, scope->flags); - for (JSScopeProperty* sprop = scope->lastProp; sprop; sprop = sprop->parent) { + for (JSScopeProperty* sprop = scope->lastProperty(); sprop; sprop = sprop->parent) { if (JSID_IS_ATOM(sprop->id)) { fprintf(shapefp, " %s", JS_GetStringBytes(JSVAL_TO_STRING(ID_TO_VALUE(sprop->id)))); } else { @@ -11151,7 +11151,7 @@ TraceRecorder::setProp(jsval &l, JSPropCacheEntry* entry, JSScopeProperty* sprop LIns* obj_ins = get(&l); JSScope* scope = OBJ_SCOPE(obj); - JS_ASSERT_IF(entry->vcap == PCVCAP_MAKE(entry->kshape, 0, 0), scope->has(sprop)); + JS_ASSERT_IF(entry->vcap == PCVCAP_MAKE(entry->kshape, 0, 0), scope->hasProperty(sprop)); // Fast path for CallClass. This is about 20% faster than the general case. v_ins = get(&v); @@ -11173,7 +11173,7 @@ TraceRecorder::setProp(jsval &l, JSPropCacheEntry* entry, JSScopeProperty* sprop jsuword pcval; CHECK_STATUS(guardPropertyCacheHit(obj_ins, map_ins, obj, obj2, entry, pcval)); JS_ASSERT(scope->object == obj2); - JS_ASSERT(scope->has(sprop)); + JS_ASSERT(scope->hasProperty(sprop)); JS_ASSERT_IF(obj2 != obj, sprop->attrs & JSPROP_SHARED); /* @@ -12479,7 +12479,7 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32 *slotp, LIns** v_insp, if (PCVAL_IS_SPROP(pcval)) { sprop = PCVAL_TO_SPROP(pcval); - JS_ASSERT(OBJ_SCOPE(obj2)->has(sprop)); + JS_ASSERT(OBJ_SCOPE(obj2)->hasProperty(sprop)); if (setflags && !SPROP_HAS_STUB_SETTER(sprop)) RETURN_STOP_A("non-stub setter"); From 714f5e019145ed69d5fef5dad2486ed2cba55bf9 Mon Sep 17 00:00:00 2001 From: Robert Sayre Date: Tue, 1 Dec 2009 15:54:01 -0500 Subject: [PATCH 004/179] Relanding Tolerate race condition or broken resolve hook (530507, r=jorendorff). Backed out changeset fb34a7163a43 --- js/src/jsobj.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index c8ac745f8479..f713010aa865 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -4759,7 +4759,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, } } - sprop = scope->addProperty(cx, id, getter, setter, SPROP_INVALID_SLOT, + sprop = scope->putProperty(cx, id, getter, setter, SPROP_INVALID_SLOT, attrs, flags, shortid); if (!sprop) { JS_UNLOCK_SCOPE(cx, scope); From bba7cc30d6a8e2425bbbf6c910dd63c5c8829491 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 1 Dec 2009 13:32:02 -0800 Subject: [PATCH 005/179] Remove TreeInfo (bug 525371, r=lw). --- js/src/jscntxt.h | 5 +- js/src/jsrecursion.cpp | 48 ++-- js/src/jstracer.cpp | 636 +++++++++++++++++++---------------------- js/src/jstracer.h | 161 +++++------ 4 files changed, 394 insertions(+), 456 deletions(-) diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 978f8723873d..5618301244da 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -113,7 +113,6 @@ static const size_t MAX_GLOBAL_SLOTS = 4096; static const size_t GLOBAL_SLOTS_BUFFER_SIZE = MAX_GLOBAL_SLOTS + 1; /* Forward declarations of tracer types. */ -class TreeInfo; class VMAllocator; class TraceRecorder; class FrameInfoCache; @@ -149,7 +148,7 @@ struct InterpState // call exit guard mismatched void* rpAtLastTreeCall; // value of rp at innermost tree call guard VMSideExit* outermostTreeExitGuard; // the last side exit returned by js_CallTree - TreeInfo* outermostTree; // the outermost tree we initially invoked + TreeFragment* outermostTree; // the outermost tree we initially invoked uintN* inlineCallCountp; // inline call count counter VMSideExit** innermostNestedGuardp; VMSideExit* innermost; @@ -168,7 +167,7 @@ struct InterpState uintN nativeVpLen; jsval* nativeVp; - InterpState(JSContext *cx, JSTraceMonitor *tm, TreeInfo *ti, + InterpState(JSContext *cx, JSTraceMonitor *tm, TreeFragment *ti, uintN &inlineCallCountp, VMSideExit** innermostNestedGuardp); ~InterpState(); }; diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp index d06430e094a1..2ad62fdc407c 100644 --- a/js/src/jsrecursion.cpp +++ b/js/src/jsrecursion.cpp @@ -70,7 +70,7 @@ class RecursiveSlotMap : public SlotMap * Store at exit->sp_adj - sizeof(double) */ ptrdiff_t retOffset = downPostSlots * sizeof(double) - - mRecorder.treeInfo->nativeStackBase; + mRecorder.tree->nativeStackBase; mRecorder.lir->insStorei(mRecorder.addName(rval_ins, "rval_ins"), mRecorder.lirbuf->sp, retOffset); } @@ -93,7 +93,7 @@ class UpRecursiveSlotMap : public RecursiveSlotMap /* * The native stack offset of the return value once this frame has * returned, is: - * -treeInfo->nativeStackBase + downPostSlots * sizeof(double) + * -tree->nativeStackBase + downPostSlots * sizeof(double) * * Note, not +1, since the offset is 0-based. * @@ -101,15 +101,15 @@ class UpRecursiveSlotMap : public RecursiveSlotMap * be the amount down recursion added, which was just guarded as * |downPostSlots|. So the offset is: * - * -treeInfo->nativeStackBase + downPostSlots * sizeof(double) - + * -tree->nativeStackBase + downPostSlots * sizeof(double) - * downPostSlots * sizeof(double) * Or: - * -treeInfo->nativeStackBase + * -tree->nativeStackBase * * This makes sense because this slot is just above the highest sp for * the down frame. */ - lir->insStorei(rval_ins, lirbuf->sp, -mRecorder.treeInfo->nativeStackBase); + lir->insStorei(rval_ins, lirbuf->sp, -mRecorder.tree->nativeStackBase); lirbuf->sp = lir->ins2(LIR_piadd, lirbuf->sp, lir->insImmWord(-int(downPostSlots) * sizeof(double))); @@ -152,7 +152,7 @@ TraceRecorder::downSnapshot(FrameInfo* downFrame) /* Build the typemap the exit will have. Note extra stack slot for return value. */ unsigned downPostSlots = downFrame->callerHeight; - unsigned ngslots = treeInfo->globalSlots->length(); + unsigned ngslots = tree->globalSlots->length(); unsigned exitTypeMapLen = downPostSlots + 1 + ngslots; JSTraceType* exitTypeMap = (JSTraceType*)alloca(sizeof(JSTraceType) * exitTypeMapLen); JSTraceType* typeMap = downFrame->get_typemap(); @@ -176,7 +176,7 @@ TraceRecorder::downSnapshot(FrameInfo* downFrame) exit->block = cx->fp->down->blockChain; exit->pc = downFrame->pc + JSOP_CALL_LENGTH; exit->imacpc = NULL; - exit->sp_adj = ((downPostSlots + 1) * sizeof(double)) - treeInfo->nativeStackBase; + exit->sp_adj = ((downPostSlots + 1) * sizeof(double)) - tree->nativeStackBase; exit->rp_adj = exit->calldepth * sizeof(FrameInfo*); exit->nativeCalleeWord = 0; exit->lookupFlags = js_InferFlags(cx, 0); @@ -257,11 +257,11 @@ TraceRecorder::upRecursion() */ js_CaptureStackTypes(cx, 1, fi->get_typemap()); } else { - /* Case 2: Guess that up-recursion is backing out, infer types from our TreeInfo. */ - JS_ASSERT(treeInfo->nStackTypes == downPostSlots + 1); + /* Case 2: Guess that up-recursion is backing out, infer types from our Tree. */ + JS_ASSERT(tree->nStackTypes == downPostSlots + 1); JSTraceType* typeMap = fi->get_typemap(); for (unsigned i = 0; i < downPostSlots; i++) - typeMap[i] = treeInfo->typeMap[i]; + typeMap[i] = tree->typeMap[i]; } fi = traceMonitor->frameCache->memoize(fi); @@ -311,7 +311,7 @@ TraceRecorder::upRecursion() for (unsigned i = 0; i < downPostSlots; i++) slotMap.addSlot(exit->stackType(i)); slotMap.addSlot(&stackval(-1)); - VisitGlobalSlots(slotMap, cx, *treeInfo->globalSlots); + VisitGlobalSlots(slotMap, cx, *tree->globalSlots); if (recursive_pc == (jsbytecode*)fragment->root->ip) { debug_only_print0(LC_TMTracer, "Compiling up-recursive loop...\n"); } else { @@ -319,9 +319,9 @@ TraceRecorder::upRecursion() exit->exitType = RECURSIVE_UNLINKED_EXIT; exit->recursive_pc = recursive_pc; } - JS_ASSERT(treeInfo->recursion != Recursion_Disallowed); - if (treeInfo->recursion != Recursion_Detected) - treeInfo->recursion = Recursion_Unwinds; + JS_ASSERT(tree->recursion != Recursion_Disallowed); + if (tree->recursion != Recursion_Detected) + tree->recursion = Recursion_Unwinds; return closeLoop(slotMap, exit); } @@ -424,7 +424,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) * value. The slurpSlot variable keeps track of the last slot that has been * unboxed, as to avoid re-unboxing when taking a SLURP_FAIL exit. */ - unsigned numGlobalSlots = treeInfo->globalSlots->length(); + unsigned numGlobalSlots = tree->globalSlots->length(); unsigned safeSlots = NativeStackSlots(cx, frameDepth) + 1 + numGlobalSlots; jsbytecode* recursive_pc = return_pc + JSOP_CALL_LENGTH; VMSideExit* exit = (VMSideExit*) @@ -435,7 +435,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) exit->exitType = RECURSIVE_SLURP_FAIL_EXIT; exit->numStackSlots = downPostSlots + 1; exit->numGlobalSlots = numGlobalSlots; - exit->sp_adj = ((downPostSlots + 1) * sizeof(double)) - treeInfo->nativeStackBase; + exit->sp_adj = ((downPostSlots + 1) * sizeof(double)) - tree->nativeStackBase; exit->recursive_pc = recursive_pc; /* @@ -557,7 +557,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) for (unsigned i = 0; i < downPostSlots; i++) slotMap.addSlot(typeMap[i]); slotMap.addSlot(&stackval(-1), typeMap[downPostSlots]); - VisitGlobalSlots(slotMap, cx, *treeInfo->globalSlots); + VisitGlobalSlots(slotMap, cx, *tree->globalSlots); debug_only_print0(LC_TMTracer, "Compiling up-recursive slurp...\n"); exit = copy(exit); if (exit->recursive_pc == fragment->root->ip) @@ -566,7 +566,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) exit->exitType = RECURSIVE_UNLINKED_EXIT; debug_only_printf(LC_TMTreeVis, "TREEVIS CHANGEEXIT EXIT=%p TYPE=%s\n", (void*)exit, getExitName(exit->exitType)); - JS_ASSERT(treeInfo->recursion >= Recursion_Unwinds); + JS_ASSERT(tree->recursion >= Recursion_Unwinds); return closeLoop(slotMap, exit); } @@ -584,9 +584,9 @@ TraceRecorder::downRecursion() JS_ASSERT(unsigned(slots) == NativeStackSlots(cx, 1) - fp->argc - 2 - fp->script->nfixed - 1); /* Guard that there is enough stack space. */ - JS_ASSERT(treeInfo->maxNativeStackSlots >= treeInfo->nativeStackBase / sizeof(double)); - int guardSlots = slots + treeInfo->maxNativeStackSlots - - treeInfo->nativeStackBase / sizeof(double); + JS_ASSERT(tree->maxNativeStackSlots >= tree->nativeStackBase / sizeof(double)); + int guardSlots = slots + tree->maxNativeStackSlots - + tree->nativeStackBase / sizeof(double); LIns* sp_top = lir->ins2(LIR_piadd, lirbuf->sp, lir->insImmWord(guardSlots * sizeof(double))); guard(true, lir->ins2(LIR_plt, sp_top, eos_ins), OOM_EXIT); @@ -618,8 +618,8 @@ TraceRecorder::downRecursion() exit = snapshot(RECURSIVE_UNLINKED_EXIT); exit->recursive_pc = fp->script->code; debug_only_print0(LC_TMTracer, "Compiling down-recursive function call.\n"); - JS_ASSERT(treeInfo->recursion != Recursion_Disallowed); - treeInfo->recursion = Recursion_Detected; + JS_ASSERT(tree->recursion != Recursion_Disallowed); + tree->recursion = Recursion_Detected; return closeLoop(exit); } @@ -783,7 +783,7 @@ TraceRecorder::slurpSlot(LIns* val_ins, jsval* vp, SlurpInfo* info) LIns* val = slurpSlot(val_ins, vp, exit); lir->insStorei(val, lirbuf->sp, - -treeInfo->nativeStackBase + ptrdiff_t(info->curSlot) * sizeof(double)); + -tree->nativeStackBase + ptrdiff_t(info->curSlot) * sizeof(double)); info->curSlot++; } diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index ca09522a14d1..6d8387237deb 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -1153,43 +1153,43 @@ Oracle::clearDemotability() } JS_REQUIRES_STACK static JS_INLINE void -MarkSlotUndemotable(JSContext* cx, TreeInfo* ti, unsigned slot) +MarkSlotUndemotable(JSContext* cx, LinkableFragment* f, unsigned slot) { - if (slot < ti->nStackTypes) { + if (slot < f->nStackTypes) { oracle.markStackSlotUndemotable(cx, slot); return; } - uint16* gslots = ti->globalSlots->data(); - oracle.markGlobalSlotUndemotable(cx, gslots[slot - ti->nStackTypes]); + uint16* gslots = f->globalSlots->data(); + oracle.markGlobalSlotUndemotable(cx, gslots[slot - f->nStackTypes]); } JS_REQUIRES_STACK static JS_INLINE void -MarkSlotUndemotable(JSContext* cx, TreeInfo* ti, unsigned slot, const void* pc) +MarkSlotUndemotable(JSContext* cx, LinkableFragment* f, unsigned slot, const void* pc) { - if (slot < ti->nStackTypes) { + if (slot < f->nStackTypes) { oracle.markStackSlotUndemotable(cx, slot, pc); return; } - uint16* gslots = ti->globalSlots->data(); - oracle.markGlobalSlotUndemotable(cx, gslots[slot - ti->nStackTypes]); + uint16* gslots = f->globalSlots->data(); + oracle.markGlobalSlotUndemotable(cx, gslots[slot - f->nStackTypes]); } static JS_REQUIRES_STACK inline bool -IsSlotUndemotable(JSContext* cx, TreeInfo* ti, unsigned slot, const void* ip) +IsSlotUndemotable(JSContext* cx, LinkableFragment* f, unsigned slot, const void* ip) { - if (slot < ti->nStackTypes) + if (slot < f->nStackTypes) return oracle.isStackSlotUndemotable(cx, slot, ip); - uint16* gslots = ti->globalSlots->data(); - return oracle.isGlobalSlotUndemotable(cx, gslots[slot - ti->nStackTypes]); + uint16* gslots = f->globalSlots->data(); + return oracle.isGlobalSlotUndemotable(cx, gslots[slot - f->nStackTypes]); } static JS_REQUIRES_STACK inline bool -IsSlotUndemotable(JSContext* cx, TreeInfo* ti, unsigned slot) +IsSlotUndemotable(JSContext* cx, LinkableFragment* f, unsigned slot) { - return IsSlotUndemotable(cx, ti, slot, cx->fp->regs->pc); + return IsSlotUndemotable(cx, f, slot, cx->fp->regs->pc); } class FrameInfoCache @@ -1417,8 +1417,8 @@ LookupOrAddLoop(JSTraceMonitor* tm, const void *ip, JSObject* globalObj, uint32_t profFragID = (js_LogController.lcbits & LC_FragProfile) ? (++(tm->lastFragID)) : 0; ) - TreeFragment* f = new (*tm->dataAlloc) TreeFragment(ip, globalObj, globalShape, argc - verbose_only(, profFragID)); + TreeFragment* f = new (*tm->dataAlloc) TreeFragment(ip, tm->dataAlloc, globalObj, globalShape, + argc verbose_only(, profFragID)); f->root = f; /* f is the root of a new tree */ *prevTreeNextp = f; /* insert f at the end of the vmfragments bucket-list */ f->next = NULL; @@ -1435,9 +1435,9 @@ AddNewPeerToPeerList(JSTraceMonitor* tm, TreeFragment* peer) uint32_t profFragID = (js_LogController.lcbits & LC_FragProfile) ? (++(tm->lastFragID)) : 0; ) - TreeFragment* f = new (*tm->dataAlloc) TreeFragment(peer->ip, peer->globalObj, - peer->globalShape, peer->argc - verbose_only(, profFragID)); + TreeFragment* f = new (*tm->dataAlloc) TreeFragment(peer->ip, tm->dataAlloc, peer->globalObj, + peer->globalShape, peer->argc + verbose_only(, profFragID)); f->root = f; /* f is the root of a new tree */ f->first = peer->first; /* add f to peer list */ f->peer = peer->peer; @@ -1447,9 +1447,55 @@ AddNewPeerToPeerList(JSTraceMonitor* tm, TreeFragment* peer) return f; } +void +TreeFragment::initialize(JSContext* cx, SlotList *globalSlots) +{ + this->dependentTrees.clear(); + this->linkedTrees.clear(); + this->globalSlots = globalSlots; + + /* Capture the coerced type of each active slot in the type map. */ + this->typeMap.captureTypes(cx, globalObj, *globalSlots, 0 /* callDepth */); + this->nStackTypes = this->typeMap.length() - globalSlots->length(); + +#ifdef DEBUG + this->treeFileName = cx->fp->script->filename; + this->treeLineNumber = js_FramePCToLineNumber(cx, cx->fp); + this->treePCOffset = FramePCOffset(cx->fp); +#endif + this->script = cx->fp->script; + this->recursion = Recursion_None; + this->gcthings.clear(); + this->sprops.clear(); + this->unstableExits = NULL; + this->sideExits.clear(); + + /* Determine the native frame layout at the entry point. */ + this->nativeStackBase = (nStackTypes - (cx->fp->regs->sp - StackBase(cx->fp))) * + sizeof(double); + this->maxNativeStackSlots = nStackTypes; + this->maxCallDepth = 0; +} + +UnstableExit* +TreeFragment::removeUnstableExit(VMSideExit* exit) +{ + /* Now erase this exit from the unstable exit list. */ + UnstableExit** tail = &this->unstableExits; + for (UnstableExit* uexit = this->unstableExits; uexit != NULL; uexit = uexit->next) { + if (uexit->exit == exit) { + *tail = uexit->next; + return *tail; + } + tail = &uexit->next; + } + JS_NOT_REACHED("exit not in unstable exit list"); + return NULL; +} + #ifdef DEBUG static void -AssertTreeIsUnique(JSTraceMonitor* tm, TreeFragment* f, TreeInfo* ti) +AssertTreeIsUnique(JSTraceMonitor* tm, TreeFragment* f) { JS_ASSERT(f->root == f); @@ -1458,15 +1504,12 @@ AssertTreeIsUnique(JSTraceMonitor* tm, TreeFragment* f, TreeInfo* ti) * trace explosion since we are trying to stabilize something without * properly connecting peer edges. */ - TreeInfo* ti_other; for (TreeFragment* peer = LookupLoop(tm, f->ip, f->globalObj, f->globalShape, f->argc); peer != NULL; peer = peer->peer) { if (!peer->code() || peer == f) continue; - ti_other = peer->treeInfo; - JS_ASSERT(ti_other); - JS_ASSERT(!ti->typeMap.matches(ti_other->typeMap)); + JS_ASSERT(!f->typeMap.matches(peer->typeMap)); } } #endif @@ -2002,10 +2045,10 @@ VisitGlobalSlots(Visitor &visitor, JSContext *cx, JSObject *globalObj, template static JS_REQUIRES_STACK JS_ALWAYS_INLINE void -VisitGlobalSlots(Visitor &visitor, JSContext *cx, TreeInfo *ti) +VisitGlobalSlots(Visitor &visitor, JSContext *cx, TreeFragment *f) { - JSObject* globalObj = ti->globalObj(); - SlotList& gslots = *ti->globalSlots; + JSObject* globalObj = f->globalObj(); + SlotList& gslots = *f->globalSlots; VisitGlobalSlots(visitor, cx, globalObj, gslots.length(), gslots.data()); } @@ -2253,24 +2296,22 @@ MergeTypeMaps(JSTraceType** partial, unsigned* plength, JSTraceType* complete, u /* Specializes a tree to any missing globals, including any dependent trees. */ static JS_REQUIRES_STACK void -SpecializeTreesToMissingGlobals(JSContext* cx, JSObject* globalObj, TreeInfo* root) +SpecializeTreesToMissingGlobals(JSContext* cx, JSObject* globalObj, TreeFragment* root) { - TreeInfo* ti = root; - - ti->typeMap.captureMissingGlobalTypes(cx, globalObj, *ti->globalSlots, ti->nStackTypes); - JS_ASSERT(ti->globalSlots->length() == ti->typeMap.length() - ti->nStackTypes); + root->typeMap.captureMissingGlobalTypes(cx, globalObj, *root->globalSlots, root->nStackTypes); + JS_ASSERT(root->globalSlots->length() == root->typeMap.length() - root->nStackTypes); for (unsigned i = 0; i < root->dependentTrees.length(); i++) { - ti = root->dependentTrees[i]->treeInfo; + TreeFragment* f = root->dependentTrees[i]; - /* ti can be NULL if we hit the recording tree in emitTreeCall; this is harmless. */ - if (ti && ti->nGlobalTypes() < ti->globalSlots->length()) - SpecializeTreesToMissingGlobals(cx, globalObj, ti); + /* code() can be NULL if we hit the recording tree in emitTreeCall; this is harmless. */ + if (f->code() && f->nGlobalTypes() < f->globalSlots->length()) + SpecializeTreesToMissingGlobals(cx, globalObj, f); } for (unsigned i = 0; i < root->linkedTrees.length(); i++) { - ti = root->linkedTrees[i]->treeInfo; - if (ti && ti->nGlobalTypes() < ti->globalSlots->length()) - SpecializeTreesToMissingGlobals(cx, globalObj, ti); + TreeFragment* f = root->linkedTrees[i]; + if (f->code() && f->nGlobalTypes() < f->globalSlots->length()) + SpecializeTreesToMissingGlobals(cx, globalObj, f); } } @@ -2300,15 +2341,15 @@ InitConst(const T &t) JS_REQUIRES_STACK TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* fragment, - TreeInfo* ti, unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap, + unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap, VMSideExit* innermost, jsbytecode* outer, uint32 outerArgc, RecordReason recordReason) : cx(cx), traceMonitor(&JS_TRACE_MONITOR(cx)), fragment(fragment), - treeInfo(ti), + tree(fragment->root), recordReason(recordReason), - globalObj(ti->globalObj()), + globalObj(tree->globalObj), outer(outer), outerArgc(outerArgc), lexicalBlock(cx->fp->blockChain), @@ -2320,7 +2361,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag loopLabel(NULL), lirbuf(traceMonitor->lirbuf), mark(*traceMonitor->traceAlloc), - numSideExitsBefore(treeInfo->sideExits.length()), + numSideExitsBefore(tree->sideExits.length()), tracker(), nativeFrameTracker(), global_dslots(NULL), @@ -2341,9 +2382,6 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag { JS_ASSERT(globalObj == JS_GetGlobalForObject(cx, cx->fp->scopeChain)); JS_ASSERT(cx->fp->regs->pc == (jsbytecode*)fragment->ip); - JS_ASSERT(fragment->root == treeInfo->rootFragment); - JS_ASSERT_IF(fragment->root == fragment, !fragment->root->treeInfo); - JS_ASSERT(ti); /* * Reset the fragment state we care about in case we got a recycled @@ -2371,7 +2409,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag #ifdef JS_JIT_SPEW debug_only_print0(LC_TMMinimal, "\n"); debug_only_printf(LC_TMMinimal, "Recording starting from %s:%u@%u (FragID=%06u)\n", - ti->treeFileName, ti->treeLineNumber, ti->treePCOffset, + tree->treeFileName, tree->treeLineNumber, tree->treePCOffset, fragment->profFragID); debug_only_printf(LC_TMTracer, "globalObj=%p, shape=%d\n", @@ -2437,11 +2475,11 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag InitConst(eor_ins) = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, eor)), "eor"); /* If we came from exit, we might not have enough global types. */ - if (ti->globalSlots->length() > ti->nGlobalTypes()) - SpecializeTreesToMissingGlobals(cx, globalObj, ti); + if (tree->globalSlots->length() > tree->nGlobalTypes()) + SpecializeTreesToMissingGlobals(cx, globalObj, tree); /* read into registers all values on the stack and all globals we know so far */ - import(treeInfo, lirbuf->sp, stackSlots, ngslots, callDepth, typeMap); + import(tree, lirbuf->sp, stackSlots, ngslots, callDepth, typeMap); /* Finish handling RECURSIVE_SLURP_FAIL_EXIT in startRecorder. */ if (anchor && anchor->exitType == RECURSIVE_SLURP_FAIL_EXIT) @@ -2472,7 +2510,6 @@ TraceRecorder::~TraceRecorder() { /* Should already have been adjusted by callers before calling delete. */ JS_ASSERT(traceMonitor->recorder != this); - JS_ASSERT(fragment->root == treeInfo->rootFragment); if (trashSelf) TrashTree(cx, fragment->root); @@ -2504,7 +2541,6 @@ TraceRecorder::finishSuccessfully() { JS_ASSERT(traceMonitor->recorder == this); JS_ASSERT(fragment->lastIns && fragment->code()); - JS_ASSERT_IF(fragment == fragment->root, fragment->toTreeFragment()->treeInfo); AUDIT(traceCompleted); mark.commit(); @@ -2530,15 +2566,14 @@ TraceRecorder::finishAbort(const char* reason) { JS_ASSERT(traceMonitor->recorder == this); JS_ASSERT(!fragment->code()); - JS_ASSERT_IF(fragment == fragment->root, !fragment->toTreeFragment()->treeInfo); AUDIT(recorderAborted); #ifdef DEBUG debug_only_printf(LC_TMAbort, "Abort recording of tree %s:%d@%d at %s:%d@%d: %s.\n", - treeInfo->treeFileName, - treeInfo->treeLineNumber, - treeInfo->treePCOffset, + tree->treeFileName, + tree->treeLineNumber, + tree->treePCOffset, cx->fp->script->filename, js_FramePCToLineNumber(cx, cx->fp), FramePCOffset(cx->fp), @@ -2548,8 +2583,8 @@ TraceRecorder::finishAbort(const char* reason) /* * If this is the primary trace and we didn't succeed compiling, trash the - * TreeInfo object. Otherwise, remove the VMSideExits we added while - * recording, which are about to be invalid. + * tree. Otherwise, remove the VMSideExits we added while recording, which + * are about to be invalid. * * BIG FAT WARNING: resetting the length is only a valid strategy as long as * there may be only one recorder active for a single TreeInfo at a time. @@ -2558,8 +2593,8 @@ TraceRecorder::finishAbort(const char* reason) if (fragment->root == fragment) { TrashTree(cx, fragment->toTreeFragment()); } else { - JS_ASSERT(numSideExitsBefore <= fragment->root->treeInfo->sideExits.length()); - fragment->root->treeInfo->sideExits.setLength(numSideExitsBefore); + JS_ASSERT(numSideExitsBefore <= fragment->root->sideExits.length()); + fragment->root->sideExits.setLength(numSideExitsBefore); } /* Grab local copies of members needed after |delete this|. */ @@ -2592,35 +2627,35 @@ inline LIns* TraceRecorder::insImmVal(jsval val) { if (JSVAL_IS_TRACEABLE(val)) - treeInfo->gcthings.addUnique(val); + tree->gcthings.addUnique(val); return lir->insImmWord(val); } inline LIns* TraceRecorder::insImmObj(JSObject* obj) { - treeInfo->gcthings.addUnique(OBJECT_TO_JSVAL(obj)); + tree->gcthings.addUnique(OBJECT_TO_JSVAL(obj)); return lir->insImmPtr((void*)obj); } inline LIns* TraceRecorder::insImmFun(JSFunction* fun) { - treeInfo->gcthings.addUnique(OBJECT_TO_JSVAL(FUN_OBJECT(fun))); + tree->gcthings.addUnique(OBJECT_TO_JSVAL(FUN_OBJECT(fun))); return lir->insImmPtr((void*)fun); } inline LIns* TraceRecorder::insImmStr(JSString* str) { - treeInfo->gcthings.addUnique(STRING_TO_JSVAL(str)); + tree->gcthings.addUnique(STRING_TO_JSVAL(str)); return lir->insImmPtr((void*)str); } inline LIns* TraceRecorder::insImmSprop(JSScopeProperty* sprop) { - treeInfo->sprops.addUnique(sprop); + tree->sprops.addUnique(sprop); return lir->insImmPtr((void*)sprop); } @@ -2657,7 +2692,7 @@ TraceRecorder::isGlobal(jsval* p) const * |p| must be the address of a jsval that is represented in the native stack * area. The return value is the offset, from InterpState::stackBase, in bytes, * where the native representation of |*p| is stored. To get the offset - * relative to InterpState::sp, subtract TreeInfo::nativeStackBase. + * relative to InterpState::sp, subtract TreeFragment::nativeStackBase. */ JS_REQUIRES_STACK ptrdiff_t TraceRecorder::nativeStackOffset(jsval* p) const @@ -2678,20 +2713,20 @@ TraceRecorder::nativeStackOffset(jsval* p) const } /* * Return the offset, from InterpState:sp, for the given jsval. Shorthand for: - * -TreeInfo::nativeStackBase + nativeStackOffset(p). + * -TreeFragment::nativeStackBase + nativeStackOffset(p). */ inline JS_REQUIRES_STACK ptrdiff_t TraceRecorder::nativespOffset(jsval* p) const { - return -treeInfo->nativeStackBase + nativeStackOffset(p); + return -tree->nativeStackBase + nativeStackOffset(p); } /* Track the maximum number of native frame slots we need during execution. */ inline void TraceRecorder::trackNativeStackUse(unsigned slots) { - if (slots > treeInfo->maxNativeStackSlots) - treeInfo->maxNativeStackSlots = slots; + if (slots > tree->maxNativeStackSlots) + tree->maxNativeStackSlots = slots; } /* @@ -2834,17 +2869,17 @@ JSTraceMonitor::flush() } static inline void -MarkTreeInfo(JSTracer* trc, TreeInfo *ti) +MarkTree(JSTracer* trc, TreeFragment *f) { - jsval* vp = ti->gcthings.data(); - unsigned len = ti->gcthings.length(); + jsval* vp = f->gcthings.data(); + unsigned len = f->gcthings.length(); while (len--) { jsval v = *vp++; JS_SET_TRACING_NAME(trc, "jitgcthing"); JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v)); } - JSScopeProperty** spropp = ti->sprops.data(); - len = ti->sprops.length(); + JSScopeProperty** spropp = f->sprops.data(); + len = f->sprops.length(); while (len--) { JSScopeProperty* sprop = *spropp++; sprop->trace(trc); @@ -2858,19 +2893,19 @@ JSTraceMonitor::mark(JSTracer* trc) for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) { TreeFragment* f = vmfragments[i]; while (f) { - if (TreeInfo* ti = f->treeInfo) - MarkTreeInfo(trc, ti); + if (f->code()) + MarkTree(trc, f); TreeFragment* peer = f->peer; while (peer) { - if (TreeInfo* ti = peer->treeInfo) - MarkTreeInfo(trc, ti); + if (peer->code()) + MarkTree(trc, peer); peer = peer->peer; } f = f->next; } } if (recorder) - MarkTreeInfo(trc, recorder->getTreeInfo()); + MarkTree(trc, recorder->getTree()); } } @@ -3150,7 +3185,7 @@ GetUpvarOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, // Next search the trace entry frame, which is not in the FrameInfo stack. if (state->outermostTree->script->staticLevel == upvarLevel) { - uint32 argc = state->outermostTree->rootFragment->argc; + uint32 argc = state->outermostTree->argc; uint32 native_slot = T::native_slot(argc, slot); *result = state->stackBase[native_slot]; return state->callstackBase[0]->get_typemap()[native_slot]; @@ -3576,7 +3611,7 @@ public: }; JS_REQUIRES_STACK void -TraceRecorder::import(TreeInfo* treeInfo, LIns* sp, unsigned stackSlots, unsigned ngslots, +TraceRecorder::import(TreeFragment* tree, LIns* sp, unsigned stackSlots, unsigned ngslots, unsigned callDepth, JSTraceType* typeMap) { /* @@ -3595,7 +3630,7 @@ TraceRecorder::import(TreeInfo* treeInfo, LIns* sp, unsigned stackSlots, unsigne */ JSTraceType* globalTypeMap = typeMap + stackSlots; - unsigned length = treeInfo->nGlobalTypes(); + unsigned length = tree->nGlobalTypes(); /* * This is potentially the typemap of the side exit and thus shorter than @@ -3603,11 +3638,11 @@ TraceRecorder::import(TreeInfo* treeInfo, LIns* sp, unsigned stackSlots, unsigne */ if (ngslots < length) { MergeTypeMaps(&globalTypeMap /* out param */, &ngslots /* out param */, - treeInfo->globalTypeMap(), length, + tree->globalTypeMap(), length, (JSTraceType*)alloca(sizeof(JSTraceType) * length)); } - JS_ASSERT(ngslots == treeInfo->nGlobalTypes()); - ptrdiff_t offset = -treeInfo->nativeStackBase; + JS_ASSERT(ngslots == tree->nGlobalTypes()); + ptrdiff_t offset = -tree->nativeStackBase; /* * Check whether there are any values on the stack we have to unbox and do @@ -3620,7 +3655,7 @@ TraceRecorder::import(TreeInfo* treeInfo, LIns* sp, unsigned stackSlots, unsigne ImportGlobalSlotVisitor globalVisitor(*this, eos_ins, globalTypeMap); VisitGlobalSlots(globalVisitor, cx, globalObj, ngslots, - treeInfo->globalSlots->data()); + tree->globalSlots->data()); if (!anchor || anchor->exitType != RECURSIVE_SLURP_FAIL_EXIT) { ImportUnboxedStackSlotVisitor unboxedStackVisitor(*this, sp, offset, @@ -3669,17 +3704,17 @@ TraceRecorder::lazilyImportGlobalSlot(unsigned slot) jsval* vp = &STOBJ_GET_SLOT(globalObj, slot); if (known(vp)) return true; /* we already have it */ - unsigned index = treeInfo->globalSlots->length(); + unsigned index = tree->globalSlots->length(); /* Add the slot to the list of interned global slots. */ - JS_ASSERT(treeInfo->nGlobalTypes() == treeInfo->globalSlots->length()); - treeInfo->globalSlots->add(slot); + JS_ASSERT(tree->nGlobalTypes() == tree->globalSlots->length()); + tree->globalSlots->add(slot); JSTraceType type = getCoercedType(*vp); if (type == TT_INT32 && oracle.isGlobalSlotUndemotable(cx, slot)) type = TT_DOUBLE; - treeInfo->typeMap.add(type); + tree->typeMap.add(type); import(eos_ins, slot*sizeof(double), vp, type, "global", index, NULL); - SpecializeTreesToMissingGlobals(cx, globalObj, treeInfo); + SpecializeTreesToMissingGlobals(cx, globalObj, tree); return true; } @@ -3905,12 +3940,10 @@ public: JS_REQUIRES_STACK void TraceRecorder::adjustCallerTypes(TreeFragment* f) { - TreeInfo* ti = f->treeInfo; + AdjustCallerGlobalTypesVisitor globalVisitor(*this, f->globalTypeMap()); + VisitGlobalSlots(globalVisitor, cx, *tree->globalSlots); - AdjustCallerGlobalTypesVisitor globalVisitor(*this, ti->globalTypeMap()); - VisitGlobalSlots(globalVisitor, cx, *treeInfo->globalSlots); - - AdjustCallerStackTypesVisitor stackVisitor(*this, ti->stackTypeMap()); + AdjustCallerStackTypesVisitor stackVisitor(*this, f->stackTypeMap()); VisitStackSlots(stackVisitor, cx, 0); JS_ASSERT(f == f->root); @@ -4028,7 +4061,7 @@ TraceRecorder::snapshot(ExitType exitType) trackNativeStackUse(stackSlots + 1); /* Capture the type map into a temporary location. */ - unsigned ngslots = treeInfo->globalSlots->length(); + unsigned ngslots = tree->globalSlots->length(); unsigned typemap_size = (stackSlots + ngslots) * sizeof(JSTraceType); /* Use the recorder-local temporary type map. */ @@ -4044,7 +4077,7 @@ TraceRecorder::snapshot(ExitType exitType) */ DetermineTypesVisitor detVisitor(*this, typemap); VisitSlots(detVisitor, cx, callDepth, ngslots, - treeInfo->globalSlots->data()); + tree->globalSlots->data()); JS_ASSERT(unsigned(detVisitor.getTypeMap() - typemap) == ngslots + stackSlots); @@ -4083,8 +4116,8 @@ TraceRecorder::snapshot(ExitType exitType) * Check if we already have a matching side exit; if so we can return that * side exit instead of creating a new one. */ - VMSideExit** exits = treeInfo->sideExits.data(); - unsigned nexits = treeInfo->sideExits.length(); + VMSideExit** exits = tree->sideExits.data(); + unsigned nexits = tree->sideExits.length(); if (exitType == LOOP_EXIT) { for (unsigned n = 0; n < nexits; ++n) { VMSideExit* e = exits[n]; @@ -4115,10 +4148,10 @@ TraceRecorder::snapshot(ExitType exitType) exit->exitType = exitType; exit->block = fp->blockChain; if (fp->blockChain) - treeInfo->gcthings.addUnique(OBJECT_TO_JSVAL(fp->blockChain)); + tree->gcthings.addUnique(OBJECT_TO_JSVAL(fp->blockChain)); exit->pc = pc; exit->imacpc = fp->imacpc; - exit->sp_adj = (stackSlots * sizeof(double)) - treeInfo->nativeStackBase; + exit->sp_adj = (stackSlots * sizeof(double)) - tree->nativeStackBase; exit->rp_adj = exit->calldepth * sizeof(FrameInfo*); exit->nativeCalleeWord = 0; exit->lookupFlags = js_InferFlags(cx, 0); @@ -4163,7 +4196,7 @@ TraceRecorder::guard(bool expected, LIns* cond, VMSideExit* exit) GuardRecord* guardRec = createGuardRecord(exit); if (exit->exitType == LOOP_EXIT) - treeInfo->sideExits.add(exit); + tree->sideExits.add(exit); if (!cond->isCond()) { expected = !expected; @@ -4192,7 +4225,7 @@ TraceRecorder::copy(VMSideExit* copy) exit->target = NULL; if (exit->exitType == LOOP_EXIT) - treeInfo->sideExits.add(exit); + tree->sideExits.add(exit); #if defined JS_JIT_SPEW TreevisLogExit(cx, exit); #endif @@ -4271,7 +4304,7 @@ TraceRecorder::compile() ResetJIT(cx, FR_DEEP_BAIL); return ARECORD_ABORTED; } - if (treeInfo->maxNativeStackSlots >= MAX_NATIVE_STACK_SLOTS) { + if (tree->maxNativeStackSlots >= MAX_NATIVE_STACK_SLOTS) { debug_only_print0(LC_TMTracer, "Blacklist: excessive stack use.\n"); Blacklist((jsbytecode*) fragment->root->ip); return ARECORD_STOP; @@ -4316,9 +4349,7 @@ TraceRecorder::compile() assm->patch(anchor); } JS_ASSERT(fragment->code()); - JS_ASSERT_IF(fragment == fragment->root, !fragment->root->treeInfo); - if (fragment == fragment->root) - fragment->root->treeInfo = treeInfo; + JS_ASSERT_IF(fragment == fragment->root, fragment->root == tree); return ARECORD_CONTINUE; } @@ -4334,8 +4365,8 @@ JoinPeers(Assembler* assm, VMSideExit* exit, TreeFragment* target) if (exit->root() == target) return; - target->treeInfo->dependentTrees.addUnique(exit->root()); - exit->root()->treeInfo->linkedTrees.addUnique(target); + target->dependentTrees.addUnique(exit->root()); + exit->root()->linkedTrees.addUnique(target); } /* Results of trying to connect an arbitrary type A with arbitrary type B */ @@ -4410,14 +4441,14 @@ class SlotMap : public SlotVisitorBase * such slots as undemotable. */ JS_REQUIRES_STACK TypeConsensus - checkTypes(TreeInfo* ti) + checkTypes(LinkableFragment* f) { - if (length() != ti->typeMap.length()) + if (length() != f->typeMap.length()) return TypeConsensus_Bad; bool has_undemotes = false; for (unsigned i = 0; i < length(); i++) { - TypeCheckResult result = checkType(i, ti->typeMap[i]); + TypeCheckResult result = checkType(i, f->typeMap[i]); if (result == TypeCheck_Bad) return TypeConsensus_Bad; if (result == TypeCheck_Undemote) @@ -4452,7 +4483,7 @@ class SlotMap : public SlotVisitorBase { for (unsigned i = 0; i < length(); i++) { if (get(i).lastCheck == TypeCheck_Undemote) - MarkSlotUndemotable(mRecorder.cx, mRecorder.treeInfo, i); + MarkSlotUndemotable(mRecorder.cx, mRecorder.tree, i); } } @@ -4542,7 +4573,7 @@ JS_REQUIRES_STACK TypeConsensus TraceRecorder::selfTypeStability(SlotMap& slotMap) { debug_only_printf(LC_TMTracer, "Checking type stability against self=%p\n", (void*)fragment); - TypeConsensus consensus = slotMap.checkTypes(treeInfo); + TypeConsensus consensus = slotMap.checkTypes(tree); /* Best case: loop jumps back to its own header */ if (consensus == TypeConsensus_Okay) @@ -4570,10 +4601,10 @@ TraceRecorder::peerTypeStability(SlotMap& slotMap, const void* ip, TreeFragment* return TypeConsensus_Bad; bool onlyUndemotes = false; for (; peer != NULL; peer = peer->peer) { - if (!peer->treeInfo || peer == fragment) + if (!peer->code() || peer == fragment) continue; debug_only_printf(LC_TMTracer, "Checking type stability against peer=%p\n", (void*)peer); - TypeConsensus consensus = slotMap.checkTypes(peer->treeInfo); + TypeConsensus consensus = slotMap.checkTypes(peer); if (consensus == TypeConsensus_Okay) { *pPeer = peer; /* Return this even though there will be linkage; the trace itself is not stable. @@ -4598,7 +4629,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::closeLoop(VMSideExit* exit) { DefaultSlotMap slotMap(*this); - VisitSlots(slotMap, cx, 0, *treeInfo->globalSlots); + VisitSlots(slotMap, cx, 0, *tree->globalSlots); return closeLoop(slotMap, exit); } @@ -4627,7 +4658,7 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) } JS_ASSERT_IF(exit->exitType == UNSTABLE_LOOP_EXIT, - exit->numStackSlots == treeInfo->nStackTypes); + exit->numStackSlots == tree->nStackTypes); JS_ASSERT_IF(exit->exitType != UNSTABLE_LOOP_EXIT, exit->exitType == RECURSIVE_UNLINKED_EXIT); JS_ASSERT_IF(exit->exitType == RECURSIVE_UNLINKED_EXIT, exit->recursive_pc != fragment->root->ip); @@ -4684,16 +4715,16 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) UnstableExit* uexit = new (traceAlloc()) UnstableExit; uexit->fragment = fragment; uexit->exit = exit; - uexit->next = treeInfo->unstableExits; - treeInfo->unstableExits = uexit; + uexit->next = tree->unstableExits; + tree->unstableExits = uexit; } else { JS_ASSERT(peer->code()); exit->target = peer; debug_only_printf(LC_TMTracer, "Joining type-unstable trace to target fragment %p.\n", (void*)peer); - peer->treeInfo->dependentTrees.addUnique(fragment->root); - treeInfo->linkedTrees.addUnique(peer); + peer->dependentTrees.addUnique(fragment->root); + tree->linkedTrees.addUnique(peer); } } else { exit->exitType = LOOP_EXIT; @@ -4723,8 +4754,8 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) debug_only_print0(LC_TMTracer, "updating specializations on dependent and linked trees\n"); - if (fragment->root->treeInfo) - SpecializeTreesToMissingGlobals(cx, globalObj, fragment->root->treeInfo); + if (fragment->root->code()) + SpecializeTreesToMissingGlobals(cx, globalObj, fragment->root); /* * If this is a newly formed tree, and the outer tree has not been compiled yet, we @@ -4752,23 +4783,23 @@ FullMapFromExit(TypeMap& typeMap, VMSideExit* exit) typeMap.fromRaw(exit->stackTypeMap(), exit->numStackSlots); typeMap.fromRaw(exit->globalTypeMap(), exit->numGlobalSlots); /* Include globals that were later specialized at the root of the tree. */ - if (exit->numGlobalSlots < exit->root()->treeInfo->nGlobalTypes()) { - typeMap.fromRaw(exit->root()->treeInfo->globalTypeMap() + exit->numGlobalSlots, - exit->root()->treeInfo->nGlobalTypes() - exit->numGlobalSlots); + if (exit->numGlobalSlots < exit->root()->nGlobalTypes()) { + typeMap.fromRaw(exit->root()->globalTypeMap() + exit->numGlobalSlots, + exit->root()->nGlobalTypes() - exit->numGlobalSlots); } } static JS_REQUIRES_STACK TypeConsensus TypeMapLinkability(JSContext* cx, const TypeMap& typeMap, TreeFragment* peer) { - const TypeMap& peerMap = peer->treeInfo->typeMap; + const TypeMap& peerMap = peer->typeMap; unsigned minSlots = JS_MIN(typeMap.length(), peerMap.length()); TypeConsensus consensus = TypeConsensus_Okay; for (unsigned i = 0; i < minSlots; i++) { if (typeMap[i] == peerMap[i]) continue; if (typeMap[i] == TT_INT32 && peerMap[i] == TT_DOUBLE && - IsSlotUndemotable(cx, peer->treeInfo, i, peer->ip)) { + IsSlotUndemotable(cx, peer, i, peer->ip)) { consensus = TypeConsensus_Undemotes; } else { return TypeConsensus_Bad; @@ -4778,20 +4809,20 @@ TypeMapLinkability(JSContext* cx, const TypeMap& typeMap, TreeFragment* peer) } static JS_REQUIRES_STACK unsigned -FindUndemotesInTypemaps(JSContext* cx, const TypeMap& typeMap, TreeInfo* treeInfo, +FindUndemotesInTypemaps(JSContext* cx, const TypeMap& typeMap, LinkableFragment* f, Queue& undemotes) { undemotes.setLength(0); - unsigned minSlots = JS_MIN(typeMap.length(), treeInfo->typeMap.length()); + unsigned minSlots = JS_MIN(typeMap.length(), f->typeMap.length()); for (unsigned i = 0; i < minSlots; i++) { - if (typeMap[i] == TT_INT32 && treeInfo->typeMap[i] == TT_DOUBLE) { + if (typeMap[i] == TT_INT32 && f->typeMap[i] == TT_DOUBLE) { undemotes.add(i); - } else if (typeMap[i] != treeInfo->typeMap[i]) { + } else if (typeMap[i] != f->typeMap[i]) { return 0; } } for (unsigned i = 0; i < undemotes.length(); i++) - MarkSlotUndemotable(cx, treeInfo, undemotes[i]); + MarkSlotUndemotable(cx, f, undemotes[i]); return undemotes.length(); } @@ -4805,10 +4836,9 @@ TraceRecorder::joinEdgesToEntry(TreeFragment* peer_root) Queue undemotes(NULL); for (TreeFragment* peer = peer_root; peer; peer = peer->peer) { - TreeInfo* ti = peer->treeInfo; - if (!ti) + if (!peer->code()) continue; - UnstableExit* uexit = ti->unstableExits; + UnstableExit* uexit = peer->unstableExits; while (uexit != NULL) { /* :TODO: these exits go somewhere else. */ if (uexit->exit->exitType == RECURSIVE_UNLINKED_EXIT) { @@ -4826,10 +4856,10 @@ TraceRecorder::joinEdgesToEntry(TreeFragment* peer_root) (void*)uexit->fragment, (void*)uexit->exit); /* It's okay! Link together and remove the unstable exit. */ JoinPeers(traceMonitor->assembler, uexit->exit, (TreeFragment*)fragment); - uexit = ti->removeUnstableExit(uexit->exit); + uexit = peer->removeUnstableExit(uexit->exit); } else { /* Check for int32->double slots that suggest trashing. */ - if (FindUndemotesInTypemaps(cx, typeMap, treeInfo, undemotes)) { + if (FindUndemotesInTypemaps(cx, typeMap, tree, undemotes)) { JS_ASSERT(peer == uexit->fragment->root); if (fragment == peer) trashSelf = true; @@ -4882,8 +4912,8 @@ TraceRecorder::endLoop(VMSideExit* exit) */ debug_only_print0(LC_TMTracer, "updating specializations on dependent and linked trees\n"); - if (fragment->root->treeInfo) - SpecializeTreesToMissingGlobals(cx, globalObj, fragment->root->treeInfo); + if (fragment->root->code()) + SpecializeTreesToMissingGlobals(cx, globalObj, fragment->root); /* * If this is a newly formed tree, and the outer tree has not been compiled @@ -4908,7 +4938,6 @@ TraceRecorder::endLoop(VMSideExit* exit) JS_REQUIRES_STACK void TraceRecorder::prepareTreeCall(TreeFragment* inner, LIns*& inner_sp_ins) { - TreeInfo* ti = inner->treeInfo; inner_sp_ins = lirbuf->sp; VMSideExit* exit = snapshot(OOM_EXIT); @@ -4937,24 +4966,24 @@ TraceRecorder::prepareTreeCall(TreeFragment* inner, LIns*& inner_sp_ins) debug_only_printf(LC_TMTracer, "sp_adj=%lld outer=%lld inner=%lld\n", (long long int)sp_adj, - (long long int)treeInfo->nativeStackBase, - (long long int)ti->nativeStackBase); + (long long int)tree->nativeStackBase, + (long long int)inner->nativeStackBase); ptrdiff_t sp_offset = - - treeInfo->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + - tree->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + sp_adj /* adjust for stack in outer frame inner tree can't see */ - + ti->maxNativeStackSlots * sizeof(double); /* plus the inner tree's stack */ + + inner->maxNativeStackSlots * sizeof(double); /* plus the inner tree's stack */ LIns* sp_top = lir->ins2(LIR_piadd, lirbuf->sp, INS_CONSTWORD(sp_offset)); guard(true, lir->ins2(LIR_plt, sp_top, eos_ins), exit); /* Guard that we have enough call stack space. */ - ptrdiff_t rp_offset = rp_adj + ti->maxCallDepth * sizeof(FrameInfo*); + ptrdiff_t rp_offset = rp_adj + inner->maxCallDepth * sizeof(FrameInfo*); LIns* rp_top = lir->ins2(LIR_piadd, lirbuf->rp, INS_CONSTWORD(rp_offset)); guard(true, lir->ins2(LIR_plt, rp_top, eor_ins), exit); sp_offset = - - treeInfo->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + - tree->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + sp_adj /* adjust for stack in outer frame inner tree can't see */ - + ti->nativeStackBase; /* plus the inner tree's stack base */ + + inner->nativeStackBase; /* plus the inner tree's stack base */ /* We have enough space, so adjust sp and rp to their new level. */ lir->insStorei(inner_sp_ins = lir->ins2(LIR_piadd, lirbuf->sp, INS_CONSTWORD(sp_offset)), lirbuf->state, offsetof(InterpState, sp)); @@ -4982,11 +5011,11 @@ BuildGlobalTypeMapFromInnerTree(Queue& typeMap, VMSideExit* inner) typeMap.add(inner->globalTypeMap(), inner->numGlobalSlots); /* Add missing global types from the innermost exit's tree. */ - TreeInfo* innerTree = inner->root()->treeInfo; + TreeFragment* innerFrag = inner->root(); unsigned slots = inner->numGlobalSlots; - if (slots < innerTree->nGlobalTypes()) { - typeMap.add(innerTree->globalTypeMap() + slots, innerTree->nGlobalTypes() - slots); - slots = innerTree->nGlobalTypes(); + if (slots < innerFrag->nGlobalTypes()) { + typeMap.add(innerFrag->globalTypeMap() + slots, innerFrag->nGlobalTypes() - slots); + slots = innerFrag->nGlobalTypes(); } JS_ASSERT(typeMap.length() - initialSlots == slots); return slots; @@ -5073,8 +5102,7 @@ TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit, LIns* inner_s fullMap.add(exit->stackTypeMap(), exit->numStackSlots); BuildGlobalTypeMapFromInnerTree(fullMap, exit); - TreeInfo* ti = inner->treeInfo; - import(ti, inner_sp_ins, exit->numStackSlots, fullMap.length() - exit->numStackSlots, + import(inner, inner_sp_ins, exit->numStackSlots, fullMap.length() - exit->numStackSlots, exit->calldepth, fullMap.data()); /* Restore sp and rp to their original values (we still have them in a register). */ @@ -5094,8 +5122,8 @@ TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit, LIns* inner_s (void*)nestedExit, (void*)exit); /* Register us as a dependent tree of the inner tree. */ - inner->treeInfo->dependentTrees.addUnique(fragment->root); - treeInfo->linkedTrees.addUnique(inner); + inner->dependentTrees.addUnique(fragment->root); + tree->linkedTrees.addUnique(inner); } /* Add a if/if-else control-flow merge point to the list of known merge points. */ @@ -5289,7 +5317,6 @@ CheckGlobalObjectShape(JSContext* cx, JSTraceMonitor* tm, JSObject* globalObj, if (tm->recorder) { TreeFragment* root = tm->recorder->getFragment()->root; - TreeInfo* ti = tm->recorder->getTreeInfo(); /* Check the global shape matches the recorder's treeinfo's shape. */ if (globalObj != root->globalObj || globalShape != root->globalShape) { @@ -5305,7 +5332,7 @@ CheckGlobalObjectShape(JSContext* cx, JSTraceMonitor* tm, JSObject* globalObj, if (shape) *shape = globalShape; if (slots) - *slots = ti->globalSlots; + *slots = root->globalSlots; return true; } @@ -5344,7 +5371,7 @@ CheckGlobalObjectShape(JSContext* cx, JSTraceMonitor* tm, JSObject* globalObj, */ bool JS_REQUIRES_STACK TraceRecorder::startRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* f, - TreeInfo* ti, unsigned stackSlots, unsigned ngslots, + unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap, VMSideExit* expectedInnerExit, jsbytecode* outer, uint32 outerArgc, RecordReason recordReason) { @@ -5352,9 +5379,8 @@ TraceRecorder::startRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* f, JS_ASSERT(!tm->needFlush); JS_ASSERT_IF(cx->fp->imacpc, f->root != f); - tm->recorder = new TraceRecorder(cx, anchor, f, ti, stackSlots, - ngslots, typeMap, expectedInnerExit, - outer, outerArgc, recordReason); + tm->recorder = new TraceRecorder(cx, anchor, f, stackSlots, ngslots, typeMap, + expectedInnerExit, outer, outerArgc, recordReason); if (!tm->recorder || tm->outOfMemory() || js_OverfullJITCache(tm)) { ResetJIT(cx, FR_OOM); @@ -5378,7 +5404,6 @@ TraceRecorder::startRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* f, static void TrashTree(JSContext* cx, TreeFragment* f) { - JS_ASSERT((!f->code()) == (!f->treeInfo)); JS_ASSERT(f == f->root); debug_only_printf(LC_TMTreeVis, "TREEVIS TRASH FRAG=%p\n", (void*)f); @@ -5386,15 +5411,13 @@ TrashTree(JSContext* cx, TreeFragment* f) return; AUDIT(treesTrashed); debug_only_print0(LC_TMTracer, "Trashing tree info.\n"); - TreeInfo* ti = f->treeInfo; - f->treeInfo = NULL; f->setCode(NULL); - TreeFragment** data = ti->dependentTrees.data(); - unsigned length = ti->dependentTrees.length(); + TreeFragment** data = f->dependentTrees.data(); + unsigned length = f->dependentTrees.length(); for (unsigned n = 0; n < length; ++n) TrashTree(cx, data[n]); - data = ti->linkedTrees.data(); - length = ti->linkedTrees.length(); + data = f->linkedTrees.data(); + length = f->linkedTrees.length(); for (unsigned n = 0; n < length; ++n) TrashTree(cx, data[n]); } @@ -5596,53 +5619,6 @@ SynthesizeSlowNativeFrame(InterpState& state, JSContext *cx, VMSideExit *exit) cx->fp = fp; } -/* - * Create a TreeInfo in preparation for starting a recorder. If one cannot be - * allocated, reset the JIT and return NULL. - */ -static JS_REQUIRES_STACK TreeInfo* -CreateTreeInfo(JSContext* cx, TreeFragment* f, JSObject* globalObj, SlotList* globalSlots) -{ - JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx); - - /* Set up the VM-private treeInfo structure for this fragment. */ - TreeInfo* ti = new (*tm->traceAlloc) TreeInfo(tm->dataAlloc, f, globalSlots); - - /* Capture the coerced type of each active slot in the type map. */ - ti->typeMap.captureTypes(cx, globalObj, *globalSlots, 0 /* callDepth */); - ti->nStackTypes = ti->typeMap.length() - globalSlots->length(); - -#ifdef DEBUG - AssertTreeIsUnique(tm, f, ti); - ti->treeFileName = cx->fp->script->filename; - ti->treeLineNumber = js_FramePCToLineNumber(cx, cx->fp); - ti->treePCOffset = FramePCOffset(cx->fp); -#endif -#ifdef JS_JIT_SPEW - debug_only_printf(LC_TMTreeVis, "TREEVIS CREATETREE ROOT=%p PC=%p FILE=\"%s\" LINE=%d OFFS=%d", - (void*)f, f->ip, ti->treeFileName, ti->treeLineNumber, - FramePCOffset(cx->fp)); - debug_only_print0(LC_TMTreeVis, " STACK=\""); - for (unsigned i = 0; i < ti->nStackTypes; i++) - debug_only_printf(LC_TMTreeVis, "%c", typeChar[ti->typeMap[i]]); - debug_only_print0(LC_TMTreeVis, "\" GLOBALS=\""); - for (unsigned i = 0; i < ti->nGlobalTypes(); i++) - debug_only_printf(LC_TMTreeVis, "%c", typeChar[ti->typeMap[ti->nStackTypes + i]]); - debug_only_print0(LC_TMTreeVis, "\"\n"); -#endif - - /* Determine the native frame layout at the entry point. */ - unsigned entryNativeStackSlots = ti->nStackTypes; - JS_ASSERT(entryNativeStackSlots == NativeStackSlots(cx, 0 /* callDepth */)); - ti->nativeStackBase = (entryNativeStackSlots - - (cx->fp->regs->sp - StackBase(cx->fp))) * sizeof(double); - ti->maxNativeStackSlots = entryNativeStackSlots; - ti->maxCallDepth = 0; - ti->script = cx->fp->script; - - return ti; -} - static JS_REQUIRES_STACK bool RecordTree(JSContext* cx, JSTraceMonitor* tm, TreeFragment* peer, jsbytecode* outer, uint32 outerArgc, JSObject* globalObj, uint32 globalShape, @@ -5675,17 +5651,30 @@ RecordTree(JSContext* cx, JSTraceMonitor* tm, TreeFragment* peer, jsbytecode* ou return false; } - JS_ASSERT(!f->code() && !f->treeInfo); + JS_ASSERT(!f->code()); - TreeInfo* ti = CreateTreeInfo(cx, f, globalObj, globalSlots); - if (!ti) - return false; + f->initialize(cx, globalSlots); +#ifdef DEBUG + AssertTreeIsUnique(tm, f); +#endif +#ifdef JS_JIT_SPEW + debug_only_printf(LC_TMTreeVis, "TREEVIS CREATETREE ROOT=%p PC=%p FILE=\"%s\" LINE=%d OFFS=%d", + (void*)f, f->ip, f->treeFileName, f->treeLineNumber, + FramePCOffset(cx->fp)); + debug_only_print0(LC_TMTreeVis, " STACK=\""); + for (unsigned i = 0; i < f->nStackTypes; i++) + debug_only_printf(LC_TMTreeVis, "%c", typeChar[f->typeMap[i]]); + debug_only_print0(LC_TMTreeVis, "\" GLOBALS=\""); + for (unsigned i = 0; i < f->nGlobalTypes(); i++) + debug_only_printf(LC_TMTreeVis, "%c", typeChar[f->typeMap[f->nStackTypes + i]]); + debug_only_print0(LC_TMTreeVis, "\"\n"); +#endif + /* Recording primary trace. */ - return TraceRecorder::startRecorder(cx, NULL, f, ti, - ti->nStackTypes, - ti->globalSlots->length(), - ti->typeMap.data(), NULL, + return TraceRecorder::startRecorder(cx, NULL, f, f->nStackTypes, + f->globalSlots->length(), + f->typeMap.data(), NULL, outer, outerArgc, reason); } @@ -5693,16 +5682,15 @@ static JS_REQUIRES_STACK TypeConsensus FindLoopEdgeTarget(JSContext* cx, VMSideExit* exit, TreeFragment** peerp) { TreeFragment* from = exit->root(); - TreeInfo* from_ti = from->treeInfo; JS_ASSERT(from->code()); TypeMap typeMap(NULL); FullMapFromExit(typeMap, exit); - JS_ASSERT(typeMap.length() - exit->numStackSlots == from_ti->nGlobalTypes()); + JS_ASSERT(typeMap.length() - exit->numStackSlots == from->nGlobalTypes()); /* Mark all double slots as undemotable */ - uint16* gslots = from_ti->globalSlots->data(); + uint16* gslots = from->globalSlots->data(); for (unsigned i = 0; i < typeMap.length(); i++) { if (typeMap[i] == TT_DOUBLE) { if (exit->exitType == RECURSIVE_UNLINKED_EXIT) { @@ -5711,7 +5699,7 @@ FindLoopEdgeTarget(JSContext* cx, VMSideExit* exit, TreeFragment** peerp) else oracle.markGlobalSlotUndemotable(cx, gslots[i - exit->numStackSlots]); } - if (i < from_ti->nStackTypes) + if (i < from->nStackTypes) oracle.markStackSlotUndemotable(cx, i, from->ip); else if (i >= exit->numStackSlots) oracle.markGlobalSlotUndemotable(cx, gslots[i - exit->numStackSlots]); @@ -5730,11 +5718,10 @@ FindLoopEdgeTarget(JSContext* cx, VMSideExit* exit, TreeFragment** peerp) } for (TreeFragment* peer = firstPeer; peer; peer = peer->peer) { - TreeInfo* peer_ti = peer->treeInfo; - if (!peer_ti) + if (!peer->code()) continue; JS_ASSERT(peer->argc == from->argc); - JS_ASSERT(exit->numStackSlots == peer_ti->nStackTypes); + JS_ASSERT(exit->numStackSlots == peer->nStackTypes); TypeConsensus consensus = TypeMapLinkability(cx, typeMap, peer); if (consensus == TypeConsensus_Okay || consensus == TypeConsensus_Undemotes) { *peerp = peer; @@ -5745,22 +5732,6 @@ FindLoopEdgeTarget(JSContext* cx, VMSideExit* exit, TreeFragment** peerp) return TypeConsensus_Bad; } -UnstableExit* -TreeInfo::removeUnstableExit(VMSideExit* exit) -{ - /* Now erase this exit from the unstable exit list. */ - UnstableExit** tail = &this->unstableExits; - for (UnstableExit* uexit = this->unstableExits; uexit != NULL; uexit = uexit->next) { - if (uexit->exit == exit) { - *tail = uexit->next; - return *tail; - } - tail = &uexit->next; - } - JS_NOT_REACHED("exit not in unstable exit list"); - return NULL; -} - static JS_REQUIRES_STACK bool AttemptToStabilizeTree(JSContext* cx, JSObject* globalObj, VMSideExit* exit, jsbytecode* outer, uint32 outerArgc) @@ -5772,29 +5743,27 @@ AttemptToStabilizeTree(JSContext* cx, JSObject* globalObj, VMSideExit* exit, jsb } TreeFragment* from = exit->root(); - TreeInfo* from_ti = from->treeInfo; TreeFragment* peer = NULL; TypeConsensus consensus = FindLoopEdgeTarget(cx, exit, &peer); if (consensus == TypeConsensus_Okay) { - TreeInfo* peer_ti = peer->treeInfo; - JS_ASSERT(from_ti->globalSlots == peer_ti->globalSlots); + JS_ASSERT(from->globalSlots == peer->globalSlots); JS_ASSERT_IF(exit->exitType == UNSTABLE_LOOP_EXIT, - from_ti->nStackTypes == peer_ti->nStackTypes); - JS_ASSERT(exit->numStackSlots == peer_ti->nStackTypes); + from->nStackTypes == peer->nStackTypes); + JS_ASSERT(exit->numStackSlots == peer->nStackTypes); /* Patch this exit to its peer */ JoinPeers(tm->assembler, exit, peer); /* * Update peer global types. The |from| fragment should already be updated because it on * the execution path, and somehow connected to the entry trace. */ - if (peer_ti->nGlobalTypes() < peer_ti->globalSlots->length()) - SpecializeTreesToMissingGlobals(cx, globalObj, peer_ti); - JS_ASSERT(from_ti->nGlobalTypes() == from_ti->globalSlots->length()); + if (peer->nGlobalTypes() < peer->globalSlots->length()) + SpecializeTreesToMissingGlobals(cx, globalObj, peer); + JS_ASSERT(from->nGlobalTypes() == from->globalSlots->length()); /* This exit is no longer unstable, so remove it. */ if (exit->exitType == UNSTABLE_LOOP_EXIT) - from_ti->removeUnstableExit(exit); - debug_only_stmt(DumpPeerStability(tm, peer->ip, from->globalObj, from->globalShape, from->argc);) + from->removeUnstableExit(exit); + debug_only_stmt(DumpPeerStability(tm, peer->ip, globalObj, from->globalShape, from->argc);) return false; } else if (consensus == TypeConsensus_Undemotes) { /* The original tree is unconnectable, so trash it. */ @@ -5802,6 +5771,9 @@ AttemptToStabilizeTree(JSContext* cx, JSObject* globalObj, VMSideExit* exit, jsb return false; } + uint32 globalShape = from->globalShape; + SlotList *globalSlots = from->globalSlots; + /* Don't bother recording if the exit doesn't expect this PC */ if (exit->exitType == RECURSIVE_UNLINKED_EXIT) { if (++exit->hitcount >= MAX_RECURSIVE_UNLINK_HITS) { @@ -5811,7 +5783,7 @@ AttemptToStabilizeTree(JSContext* cx, JSObject* globalObj, VMSideExit* exit, jsb } if (exit->recursive_pc != cx->fp->regs->pc) return false; - from = LookupLoop(tm, exit->recursive_pc, from->globalObj, from->globalShape, cx->fp->argc); + from = LookupLoop(tm, exit->recursive_pc, globalObj, globalShape, cx->fp->argc); if (!from) return false; /* use stale TI for RecordTree - since from might not have one anymore. */ @@ -5823,8 +5795,8 @@ AttemptToStabilizeTree(JSContext* cx, JSObject* globalObj, VMSideExit* exit, jsb if (*(jsbytecode*)from->ip == JSOP_NOP) return false; - return RecordTree(cx, tm, from->first, outer, outerArgc, from->globalObj, - from->globalShape, from_ti->globalSlots, cx->fp->argc, + return RecordTree(cx, tm, from->first, outer, outerArgc, globalObj, + globalShape, globalSlots, cx->fp->argc, Record_Branch); } @@ -5872,7 +5844,7 @@ AttemptToExtendTree(JSContext* cx, VMSideExit* anchor, VMSideExit* exitedFrom, j } TreeFragment* f = anchor->root(); - JS_ASSERT(f->treeInfo); + JS_ASSERT(f->code()); /* * Don't grow trees above a certain size to avoid code explosion due to @@ -5936,9 +5908,8 @@ AttemptToExtendTree(JSContext* cx, VMSideExit* anchor, VMSideExit* exitedFrom, j typeMap = fullMap.data(); } JS_ASSERT(ngslots >= anchor->numGlobalSlots); - bool rv = TraceRecorder::startRecorder(cx, anchor, c, f->treeInfo, - stackSlots, ngslots, typeMap, exitedFrom, - outer, cx->fp->argc, Record_Branch); + bool rv = TraceRecorder::startRecorder(cx, anchor, c, stackSlots, ngslots, typeMap, + exitedFrom, outer, cx->fp->argc, Record_Branch); #ifdef MOZ_TRACEVIS if (!rv && tvso) tvso->r = R_FAIL_EXTEND_START; @@ -6027,13 +5998,13 @@ TraceRecorder::attemptTreeCall(TreeFragment* f, uintN& inlineCallCount) * In the interim, just do tree calls knowing that they won't go into * recursive trees that can pop parent frames. */ - if (f->treeInfo->script == cx->fp->script) { - if (f->treeInfo->recursion >= Recursion_Unwinds) { + if (f->script == cx->fp->script) { + if (f->recursion >= Recursion_Unwinds) { Blacklist(cx->fp->script->code); js_AbortRecording(cx, "Inner tree is an unsupported type of recursion"); return ARECORD_ABORTED; } else { - f->treeInfo->recursion = Recursion_Disallowed; + f->recursion = Recursion_Disallowed; } } @@ -6228,19 +6199,16 @@ TraceRecorder::findNestedCompatiblePeer(TreeFragment* f) JSTraceMonitor* tm; tm = &JS_TRACE_MONITOR(cx); - unsigned int ngslots = treeInfo->globalSlots->length(); + unsigned int ngslots = tree->globalSlots->length(); - TreeInfo* ti; for (; f != NULL; f = f->peer) { if (!f->code()) continue; - ti = f->treeInfo; - debug_only_printf(LC_TMTracer, "checking nested types %p: ", (void*)f); - if (ngslots > ti->nGlobalTypes()) - SpecializeTreesToMissingGlobals(cx, globalObj, ti); + if (ngslots > f->nGlobalTypes()) + SpecializeTreesToMissingGlobals(cx, globalObj, f); /* * Determine whether the typemap of the inner tree matches the outer @@ -6251,8 +6219,8 @@ TraceRecorder::findNestedCompatiblePeer(TreeFragment* f) * expects a double, but the outer tree has an integer, we can proceed, * but we mark the location undemotable. */ - TypeCompatibilityVisitor visitor(*this, ti->typeMap.data()); - VisitSlots(visitor, cx, 0, *treeInfo->globalSlots); + TypeCompatibilityVisitor visitor(*this, f->typeMap.data()); + VisitSlots(visitor, cx, 0, *tree->globalSlots); debug_only_printf(LC_TMTracer, " %s\n", visitor.isOk() ? "match" : ""); if (visitor.isOk()) @@ -6303,25 +6271,25 @@ public: * Check if types are usable for trace execution. * * @param cx Context. - * @param ti Tree info of peer we're testing. + * @param f Tree of peer we're testing. * @return True if compatible (with or without demotions), false otherwise. */ static JS_REQUIRES_STACK bool -CheckEntryTypes(JSContext* cx, JSObject* globalObj, TreeInfo* ti) +CheckEntryTypes(JSContext* cx, JSObject* globalObj, TreeFragment* f) { - unsigned int ngslots = ti->globalSlots->length(); + unsigned int ngslots = f->globalSlots->length(); - JS_ASSERT(ti->nStackTypes == NativeStackSlots(cx, 0)); + JS_ASSERT(f->nStackTypes == NativeStackSlots(cx, 0)); - if (ngslots > ti->nGlobalTypes()) - SpecializeTreesToMissingGlobals(cx, globalObj, ti); + if (ngslots > f->nGlobalTypes()) + SpecializeTreesToMissingGlobals(cx, globalObj, f); - JS_ASSERT(ti->typeMap.length() == NativeStackSlots(cx, 0) + ngslots); - JS_ASSERT(ti->typeMap.length() == ti->nStackTypes + ngslots); - JS_ASSERT(ti->nGlobalTypes() == ngslots); + JS_ASSERT(f->typeMap.length() == NativeStackSlots(cx, 0) + ngslots); + JS_ASSERT(f->typeMap.length() == f->nStackTypes + ngslots); + JS_ASSERT(f->nGlobalTypes() == ngslots); - CheckEntryTypeVisitor visitor(ti->typeMap.data()); - VisitSlots(visitor, cx, 0, *ti->globalSlots); + CheckEntryTypeVisitor visitor(f->typeMap.data()); + VisitSlots(visitor, cx, 0, *f->globalSlots); debug_only_print0(LC_TMTracer, "\n"); return visitor.isOk(); @@ -6341,11 +6309,11 @@ FindVMCompatiblePeer(JSContext* cx, JSObject* globalObj, TreeFragment* f, uintN& { count = 0; for (; f != NULL; f = f->peer) { - if (!f->treeInfo) + if (!f->code()) continue; debug_only_printf(LC_TMTracer, "checking vm types %p (ip: %p): ", (void*)f, f->ip); - if (CheckEntryTypes(cx, globalObj, f->treeInfo)) + if (CheckEntryTypes(cx, globalObj, f)) return f; ++count; } @@ -6359,11 +6327,11 @@ FindVMCompatiblePeer(JSContext* cx, JSObject* globalObj, TreeFragment* f, uintN& * |deepBailSp| in js_DeepBail. */ JS_ALWAYS_INLINE -InterpState::InterpState(JSContext* cx, JSTraceMonitor* tm, TreeInfo* ti, +InterpState::InterpState(JSContext* cx, JSTraceMonitor* tm, TreeFragment* f, uintN& inlineCallCount, VMSideExit** innermostNestedGuardp) : cx(cx), stackBase(tm->storage.stack()), - sp(stackBase + ti->nativeStackBase / sizeof(double)), + sp(stackBase + f->nativeStackBase / sizeof(double)), eos(tm->storage.global()), callstackBase(tm->storage.callstack()), sor(callstackBase), @@ -6373,7 +6341,7 @@ InterpState::InterpState(JSContext* cx, JSTraceMonitor* tm, TreeInfo* ti, lastTreeExitGuard(NULL), lastTreeCallGuard(NULL), rpAtLastTreeCall(NULL), - outermostTree(ti), + outermostTree(f), inlineCallCountp(&inlineCallCount), innermostNestedGuardp(innermostNestedGuardp), #ifdef EXECUTE_TREE_TIMER @@ -6435,10 +6403,9 @@ ExecuteTrace(JSContext* cx, Fragment* f, InterpState& state) /* Check whether our assumptions about the incoming scope-chain are upheld. */ static JS_REQUIRES_STACK JS_ALWAYS_INLINE bool -ScopeChainCheck(JSContext* cx, TreeInfo* ti, TreeFragment* f) +ScopeChainCheck(JSContext* cx, TreeFragment* f) { - JS_ASSERT(ti->globalObj() == f->globalObj); - JS_ASSERT(ti->globalObj() == JS_GetGlobalForObject(cx, cx->fp->scopeChain)); + JS_ASSERT(f->globalObj == JS_GetGlobalForObject(cx, cx->fp->scopeChain)); /* * The JIT records and expects to execute with two scope-chain @@ -6475,8 +6442,8 @@ ScopeChainCheck(JSContext* cx, TreeInfo* ti, TreeFragment* f) /* Make sure the global object is sane. */ JS_ASSERT(STOBJ_NSLOTS(f->globalObj) <= MAX_GLOBAL_SLOTS); - JS_ASSERT(ti->nGlobalTypes() == ti->globalSlots->length()); - JS_ASSERT_IF(ti->globalSlots->length() != 0, + JS_ASSERT(f->nGlobalTypes() == f->globalSlots->length()); + JS_ASSERT_IF(f->globalSlots->length() != 0, OBJ_SHAPE(f->globalObj) == f->globalShape); return true; } @@ -6491,23 +6458,22 @@ ExecuteTree(JSContext* cx, TreeFragment* f, uintN& inlineCallCount, #ifdef MOZ_TRACEVIS TraceVisStateObj tvso(cx, S_EXECUTE); #endif - JS_ASSERT(f->root == f && f->code() && f->treeInfo); + JS_ASSERT(f->root == f && f->code()); JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx); - TreeInfo* ti = f->treeInfo; - if (!ScopeChainCheck(cx, ti, f)) + if (!ScopeChainCheck(cx, f)) return NULL; /* Initialize trace state. */ - InterpState state(cx, tm, ti, inlineCallCount, innermostNestedGuardp); + InterpState state(cx, tm, f, inlineCallCount, innermostNestedGuardp); double* stack = tm->storage.stack(); double* global = tm->storage.global(); JSObject* globalObj = f->globalObj; - unsigned ngslots = ti->globalSlots->length(); - uint16* gslots = ti->globalSlots->data(); + unsigned ngslots = f->globalSlots->length(); + uint16* gslots = f->globalSlots->data(); BuildNativeFrame(cx, globalObj, 0 /* callDepth */, ngslots, gslots, - ti->typeMap.data(), global, stack); + f->typeMap.data(), global, stack); AUDIT(traceTriggered); debug_only_printf(LC_TMTracer, @@ -6515,7 +6481,7 @@ ExecuteTree(JSContext* cx, TreeFragment* f, uintN& inlineCallCount, cx->fp->script->filename, js_FramePCToLineNumber(cx, cx->fp), FramePCOffset(cx->fp), - ti->maxNativeStackSlots, + f->maxNativeStackSlots, f->code()); debug_only_stmt(uint32 globalSlots = STOBJ_NSLOTS(globalObj);) @@ -6828,7 +6794,7 @@ LeaveTree(InterpState& state, VMSideExit* lr) * type-map. See also the comment in the constructor of TraceRecorder * regarding why this is always safe to do. */ - TreeInfo* outermostTree = state.outermostTree; + TreeFragment* outermostTree = state.outermostTree; uint16* gslots = outermostTree->globalSlots->data(); unsigned ngslots = outermostTree->globalSlots->length(); JS_ASSERT(ngslots == outermostTree->nGlobalTypes()); @@ -6847,8 +6813,8 @@ LeaveTree(InterpState& state, VMSideExit* lr) * is lazily added into a tree, all dependent and linked trees are * immediately specialized (see bug 476653). */ - JS_ASSERT(innermost->root()->treeInfo->nGlobalTypes() == ngslots); - JS_ASSERT(innermost->root()->treeInfo->nGlobalTypes() > innermost->numGlobalSlots); + JS_ASSERT(innermost->root()->nGlobalTypes() == ngslots); + JS_ASSERT(innermost->root()->nGlobalTypes() > innermost->numGlobalSlots); typeMap.ensure(ngslots); #ifdef DEBUG unsigned check_ngslots = @@ -6874,7 +6840,7 @@ LeaveTree(InterpState& state, VMSideExit* lr) /* Write back interned globals. */ JS_ASSERT(state.eos == state.stackBase + MAX_NATIVE_STACK_SLOTS); - JSObject* globalObj = outermostTree->globalObj(); + JSObject* globalObj = outermostTree->globalObj; FlushNativeGlobalFrame(cx, globalObj, state.eos, ngslots, gslots, globalTypeMap); #ifdef DEBUG /* Verify that our state restoration worked. */ @@ -7009,7 +6975,7 @@ js_MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount, RecordReason reason) * most time will be spent entering and exiting ExecuteTree(). There's no * benefit to doing this until the down-recursive side completes. */ - if (match->treeInfo->recursion == Recursion_Unwinds) + if (match->recursion == Recursion_Unwinds) return false; VMSideExit* lr = NULL; @@ -9759,10 +9725,10 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) * concerned about. That should pass through below to not regress pre-recursion * functionality. */ - if (IsTraceableRecursion(cx) && treeInfo->script == cx->fp->script) { - if (treeInfo->recursion == Recursion_Disallowed) + if (IsTraceableRecursion(cx) && tree->script == cx->fp->script) { + if (tree->recursion == Recursion_Disallowed) RETURN_STOP_A("recursion not allowed in this tree"); - if (treeInfo->script != cx->fp->script) + if (tree->script != cx->fp->script) RETURN_STOP_A("recursion does not match original tree"); return InjectStatus(downRecursion()); } @@ -9786,14 +9752,14 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) * recursive. */ for (f = first; f; f = f->peer) { - if (f->treeInfo && f->treeInfo->recursion == Recursion_Detected) { + if (f->code() && f->recursion == Recursion_Detected) { /* Since this recorder is about to die, save its values. */ if (++first->hits() <= HOTLOOP) return ARECORD_STOP; if (IsBlacklisted((jsbytecode*)f->ip)) RETURN_STOP_A("inner recursive tree is blacklisted"); JSContext* _cx = cx; - SlotList* globalSlots = treeInfo->globalSlots; + SlotList* globalSlots = tree->globalSlots; JSTraceMonitor* tm = traceMonitor; js_AbortRecording(cx, "trying to compile inner recursive tree"); if (RecordTree(_cx, tm, first, NULL, 0, first->globalObj, first->globalShape, @@ -9882,8 +9848,8 @@ TraceRecorder::record_JSOP_RETURN() { /* A return from callDepth 0 terminates the current loop, except for recursion. */ if (callDepth == 0) { - if (IsTraceableRecursion(cx) && treeInfo->recursion != Recursion_Disallowed && - treeInfo->script == cx->fp->script) { + if (IsTraceableRecursion(cx) && tree->recursion != Recursion_Disallowed && + tree->script == cx->fp->script) { return InjectStatus(upRecursion()); } else { AUDIT(returnLoopExits); @@ -10523,7 +10489,7 @@ TraceRecorder::emitNativeCall(JSSpecializedNative* sn, uintN argc, LIns* args[], JSObject* funobj = JSVAL_TO_OBJECT(stackval(0 - (2 + argc))); if (FUN_SLOW_NATIVE(GET_FUNCTION_PRIVATE(cx, funobj))) { exit->setNativeCallee(funobj, constructing); - treeInfo->gcthings.addUnique(OBJECT_TO_JSVAL(funobj)); + tree->gcthings.addUnique(OBJECT_TO_JSVAL(funobj)); } } @@ -12076,7 +12042,7 @@ TraceRecorder::guardCallee(jsval& callee) JSObject* callee_obj = JSVAL_TO_OBJECT(callee); LIns* callee_ins = get(&callee); - treeInfo->gcthings.addUnique(callee); + tree->gcthings.addUnique(callee); guard(true, lir->ins2(LIR_peq, stobj_get_private(callee_ins), @@ -12153,10 +12119,10 @@ TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc, JS_ASSERT(argc < FrameInfo::CONSTRUCTING_FLAG); - treeInfo->gcthings.addUnique(fval); + tree->gcthings.addUnique(fval); fi->block = fp->blockChain; if (fp->blockChain) - treeInfo->gcthings.addUnique(OBJECT_TO_JSVAL(fp->blockChain)); + tree->gcthings.addUnique(OBJECT_TO_JSVAL(fp->blockChain)); fi->pc = fp->regs->pc; fi->imacpc = fp->imacpc; fi->spdist = fp->regs->sp - fp->slots; @@ -12164,8 +12130,8 @@ TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc, fi->callerHeight = stackSlots - (2 + argc); fi->callerArgc = fp->argc; - if (callDepth >= treeInfo->maxCallDepth) - treeInfo->maxCallDepth = callDepth + 1; + if (callDepth >= tree->maxCallDepth) + tree->maxCallDepth = callDepth + 1; fi = traceMonitor->frameCache->memoize(fi); if (!fi) @@ -14696,24 +14662,22 @@ DumpPeerStability(JSTraceMonitor* tm, const void* ip, JSObject* globalObj, uint3 uint32 argc) { TreeFragment* f; - TreeInfo* ti; bool looped = false; unsigned length = 0; for (f = LookupLoop(tm, ip, globalObj, globalShape, argc); f != NULL; f = f->peer) { - if (!f->treeInfo) + if (!f->code()) continue; debug_only_printf(LC_TMRecorder, "Stability of fragment %p:\nENTRY STACK=", (void*)f); - ti = f->treeInfo; if (looped) - JS_ASSERT(ti->nStackTypes == length); - for (unsigned i = 0; i < ti->nStackTypes; i++) - debug_only_printf(LC_TMRecorder, "%c", typeChar[ti->stackTypeMap()[i]]); + JS_ASSERT(f->nStackTypes == length); + for (unsigned i = 0; i < f->nStackTypes; i++) + debug_only_printf(LC_TMRecorder, "%c", typeChar[f->stackTypeMap()[i]]); debug_only_print0(LC_TMRecorder, " GLOBALS="); - for (unsigned i = 0; i < ti->nGlobalTypes(); i++) - debug_only_printf(LC_TMRecorder, "%c", typeChar[ti->globalTypeMap()[i]]); + for (unsigned i = 0; i < f->nGlobalTypes(); i++) + debug_only_printf(LC_TMRecorder, "%c", typeChar[f->globalTypeMap()[i]]); debug_only_print0(LC_TMRecorder, "\n"); - UnstableExit* uexit = ti->unstableExits; + UnstableExit* uexit = f->unstableExits; while (uexit != NULL) { debug_only_print0(LC_TMRecorder, "EXIT "); JSTraceType* m = uexit->exit->fullTypeMap(); @@ -14728,7 +14692,7 @@ DumpPeerStability(JSTraceMonitor* tm, const void* ip, JSObject* globalObj, uint3 debug_only_print0(LC_TMRecorder, "\n"); uexit = uexit->next; } - length = ti->nStackTypes; + length = f->nStackTypes; looped = true; } } @@ -14820,7 +14784,7 @@ JS_REQUIRES_STACK void TraceRecorder::determineGlobalTypes(JSTraceType* typeMap) { DetermineTypesVisitor detVisitor(*this, typeMap); - VisitGlobalSlots(detVisitor, cx, *treeInfo->globalSlots); + VisitGlobalSlots(detVisitor, cx, *tree->globalSlots); } #include "jsrecursion.cpp" diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 285bf71c6591..96e8cfaf13f1 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -217,54 +217,6 @@ public: TreeFragment* toTreeFragment(); }; -struct LinkableFragment : public VMFragment -{ - LinkableFragment(const void* _ip verbose_only(, uint32_t profFragID)) - : VMFragment(_ip verbose_only(, profFragID)) - { } - - uint32 branchCount; -}; - -/* - * argc is cx->fp->argc at the trace loop header, i.e., the number of arguments - * pushed for the innermost JS frame. This is required as part of the fragment - * key because the fragment will write those arguments back to the interpreter - * stack when it exits, using its typemap, which implicitly incorporates a - * given value of argc. Without this feature, a fragment could be called as an - * inner tree with two different values of argc, and entry type checking or - * exit frame synthesis could crash. - */ -struct TreeFragment : public LinkableFragment -{ - TreeFragment(const void* _ip, JSObject* _globalObj, uint32 _globalShape, uint32 _argc - verbose_only(, uint32_t profFragID)) : - LinkableFragment(_ip verbose_only(, profFragID)), - treeInfo(NULL), - first(NULL), - next(NULL), - peer(NULL), - globalObj(_globalObj), - globalShape(_globalShape), - argc(_argc) - { } - - TreeInfo *treeInfo; - TreeFragment* first; - TreeFragment* next; - TreeFragment* peer; - JSObject* globalObj; - uint32 globalShape; - uint32 argc; -}; - -inline TreeFragment* -VMFragment::toTreeFragment() -{ - JS_ASSERT(root == this); - return static_cast(this); -} - #if defined(JS_JIT_SPEW) || defined(NJ_NO_VARIADIC_MACROS) enum LC_TMBits { @@ -633,8 +585,6 @@ struct REHashFn { } }; -class TreeInfo; - struct FrameInfo { JSObject* block; // caller block chain head jsbytecode* pc; // caller fp->regs->pc @@ -695,51 +645,71 @@ enum RecursionStatus Recursion_Detected /* Tree has down recursion and maybe up recursion. */ }; -class TreeInfo { -public: - TreeFragment* const rootFragment; - JSScript* script; - unsigned maxNativeStackSlots; - ptrdiff_t nativeStackBase; - unsigned maxCallDepth; +struct LinkableFragment : public VMFragment +{ + LinkableFragment(const void* _ip, nanojit::Allocator* alloc + verbose_only(, uint32_t profFragID)) + : VMFragment(_ip verbose_only(, profFragID)), typeMap(alloc), nStackTypes(0) + { } + + uint32 branchCount; TypeMap typeMap; unsigned nStackTypes; SlotList* globalSlots; +}; + +/* + * argc is cx->fp->argc at the trace loop header, i.e., the number of arguments + * pushed for the innermost JS frame. This is required as part of the fragment + * key because the fragment will write those arguments back to the interpreter + * stack when it exits, using its typemap, which implicitly incorporates a + * given value of argc. Without this feature, a fragment could be called as an + * inner tree with two different values of argc, and entry type checking or + * exit frame synthesis could crash. + */ +struct TreeFragment : public LinkableFragment +{ + TreeFragment(const void* _ip, nanojit::Allocator* alloc, JSObject* _globalObj, + uint32 _globalShape, uint32 _argc verbose_only(, uint32_t profFragID)): + LinkableFragment(_ip, alloc verbose_only(, profFragID)), + first(NULL), + next(NULL), + peer(NULL), + globalObj(_globalObj), + globalShape(_globalShape), + argc(_argc), + dependentTrees(alloc), + linkedTrees(alloc), + sideExits(alloc), + gcthings(alloc), + sprops(alloc) + { } + + TreeFragment* first; + TreeFragment* next; + TreeFragment* peer; + JSObject* globalObj; + uint32 globalShape; + uint32 argc; /* Dependent trees must be trashed if this tree dies, and updated on missing global types */ - Queue dependentTrees; + Queue dependentTrees; /* Linked trees must be updated on missing global types, but are not dependent */ - Queue linkedTrees; - Queue sideExits; - UnstableExit* unstableExits; - /* All embedded GC things are registered here so the GC can scan them. */ - Queue gcthings; - Queue sprops; + Queue linkedTrees; #ifdef DEBUG const char* treeFileName; uintN treeLineNumber; uintN treePCOffset; #endif + JSScript* script; RecursionStatus recursion; - - TreeInfo(nanojit::Allocator* alloc, - TreeFragment* fragment, - SlotList* globalSlots) - : rootFragment(fragment), - script(NULL), - maxNativeStackSlots(0), - nativeStackBase(0), - maxCallDepth(0), - typeMap(alloc), - nStackTypes(0), - globalSlots(globalSlots), - dependentTrees(alloc), - linkedTrees(alloc), - sideExits(alloc), - unstableExits(NULL), - gcthings(alloc), - sprops(alloc), - recursion(Recursion_None) - {} + UnstableExit* unstableExits; + Queue sideExits; + ptrdiff_t nativeStackBase; + unsigned maxCallDepth; + /* All embedded GC things are registered here so the GC can scan them. */ + Queue gcthings; + Queue sprops; + unsigned maxNativeStackSlots; inline unsigned nGlobalTypes() { return typeMap.length() - nStackTypes; @@ -750,13 +720,18 @@ public: inline JSTraceType* stackTypeMap() { return typeMap.data(); } - inline JSObject* globalObj() { - return rootFragment->globalObj; - } + void initialize(JSContext* cx, SlotList *globalSlots); UnstableExit* removeUnstableExit(VMSideExit* exit); }; +inline TreeFragment* +VMFragment::toTreeFragment() +{ + JS_ASSERT(root == this); + return static_cast(this); +} + typedef enum JSBuiltinStatus { JSBUILTIN_BAILED = 1, JSBUILTIN_ERROR = 2 @@ -935,8 +910,8 @@ class TraceRecorder /* The Fragment being recorded by this recording session. */ VMFragment* const fragment; - /* The tree to which this |fragment| will belong when finished. */ - TreeInfo* const treeInfo; + /* The root fragment representing the tree. */ + TreeFragment* const tree; /* The reason we started recording. */ RecordReason const recordReason; @@ -1069,7 +1044,7 @@ class TraceRecorder JS_REQUIRES_STACK ptrdiff_t nativespOffset(jsval* p) const; JS_REQUIRES_STACK void import(nanojit::LIns* base, ptrdiff_t offset, jsval* p, JSTraceType t, const char *prefix, uintN index, JSStackFrame *fp); - JS_REQUIRES_STACK void import(TreeInfo* treeInfo, nanojit::LIns* sp, unsigned stackSlots, + JS_REQUIRES_STACK void import(TreeFragment* tree, nanojit::LIns* sp, unsigned stackSlots, unsigned callDepth, unsigned ngslots, JSTraceType* typeMap); void trackNativeStackUse(unsigned slots); @@ -1365,7 +1340,7 @@ class TraceRecorder inline void operator delete(void *p) { free(p); } JS_REQUIRES_STACK - TraceRecorder(JSContext* cx, VMSideExit*, VMFragment*, TreeInfo*, + TraceRecorder(JSContext* cx, VMSideExit*, VMFragment*, unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap, VMSideExit* expectedInnerExit, jsbytecode* outerTree, uint32 outerArgc, RecordReason reason); @@ -1392,14 +1367,14 @@ class TraceRecorder public: static bool JS_REQUIRES_STACK - startRecorder(JSContext*, VMSideExit*, VMFragment*, TreeInfo*, + startRecorder(JSContext*, VMSideExit*, VMFragment*, unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap, VMSideExit* expectedInnerExit, jsbytecode* outerTree, uint32 outerArgc, RecordReason reason); /* Accessors. */ VMFragment* getFragment() const { return fragment; } - TreeInfo* getTreeInfo() const { return treeInfo; } + TreeFragment* getTree() const { return tree; } bool outOfMemory() const { return traceMonitor->outOfMemory(); } /* Entry points / callbacks from the interpreter. */ From ce944c8a1559bd41180ed0d7fca8b3c711f50115 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Tue, 1 Dec 2009 14:48:05 -0800 Subject: [PATCH 006/179] Fix js_FindDuplicateFormal to crack the fun->u.i.names union correctly, and spruce it up with C++ (532041, r=jimb). --- js/src/jsfun.cpp | 19 ++++++++++--------- js/src/jsfun.h | 13 ++++++------- js/src/jsparse.cpp | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 6323fcc6cffb..821bb348f234 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -112,7 +112,7 @@ GetArgsLength(JSObject *obj) return argc; } -static inline void +static inline void SetArgsPrivateNative(JSObject *argsobj, js_ArgsPrivateNative *apn) { JS_ASSERT(STOBJ_GET_CLASS(argsobj) == &js_ArgumentsClass); @@ -292,7 +292,7 @@ js_Arguments(JSContext *cx, JSObject *parent, uint32 argc, JSObject *callee, } #endif -JS_DEFINE_CALLINFO_6(extern, OBJECT, js_Arguments, CONTEXT, OBJECT, UINT32, OBJECT, +JS_DEFINE_CALLINFO_6(extern, OBJECT, js_Arguments, CONTEXT, OBJECT, UINT32, OBJECT, DOUBLEPTR, APNPTR, 0, 0) /* FIXME change the return type to void. */ @@ -3062,16 +3062,17 @@ js_FreezeLocalNames(JSContext *cx, JSFunction *fun) #endif } -extern JSAtom * -js_FindDuplicateFormal(JSFunction *fun) +JSAtom * +JSFunction::findDuplicateFormal() const { - unsigned nargs = fun->nargs; if (nargs <= 1) return NULL; /* Function with two to MAX_ARRAY_LOCALS parameters use an aray. */ - if (nargs <= MAX_ARRAY_LOCALS) { - jsuword *array = fun->u.i.names.array; + unsigned n = nargs + u.i.nvars + u.i.nupvars; + if (n <= MAX_ARRAY_LOCALS) { + jsuword *array = u.i.names.array; + /* Quadratic, but MAX_ARRAY_LOCALS is 8, so at most 28 comparisons. */ for (unsigned i = 0; i < nargs; i++) { for (unsigned j = i + 1; j < nargs; j++) { @@ -3082,11 +3083,11 @@ js_FindDuplicateFormal(JSFunction *fun) return NULL; } - /* + /* * Functions with more than MAX_ARRAY_LOCALS parameters use a hash * table. Hashed local name maps have already made a list of any * duplicate argument names for us. */ - JSNameIndexPair *dup = fun->u.i.names.map->lastdup; + JSNameIndexPair *dup = u.i.names.map->lastdup; return dup ? dup->name : NULL; } diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 0df1360a5046..5b44391237a9 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -180,6 +180,12 @@ struct JSFunction : public JSObject { int sharpSlotBase(JSContext *cx); + /* + * If fun's formal parameters include any duplicate names, return one + * of them (chosen arbitrarily). If they are all unique, return NULL. + */ + JSAtom *findDuplicateFormal() const; + uint32 countInterpretedReservedSlots() const; }; @@ -436,13 +442,6 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, struct JSArenaPool *pool); extern void js_FreezeLocalNames(JSContext *cx, JSFunction *fun); -/* - * If fun's formal parameters include any duplicate names, return one - * of them (chosen arbitrarily). If they are all unique, return NULL. - */ -extern JSAtom * -js_FindDuplicateFormal(JSFunction *fun); - extern JSBool js_fun_apply(JSContext *cx, uintN argc, jsval *vp); diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index 6b6aea8522ee..2e0fbcd4b42b 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -1263,7 +1263,7 @@ CheckStrictFormals(JSContext *cx, JSTreeContext *tc, JSFunction *fun, if (!tc->needStrictChecks()) return true; - atom = js_FindDuplicateFormal(fun); + atom = fun->findDuplicateFormal(); if (atom) { /* * We have found a duplicate parameter name. If we can find the From 8d3e7e4f8b6c085953f432dec29266e50315fe30 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 1 Dec 2009 16:32:45 -0800 Subject: [PATCH 007/179] Backed out changeset 0082849624a5, potential orange. --- js/src/jscntxt.h | 5 +- js/src/jsrecursion.cpp | 48 ++-- js/src/jstracer.cpp | 636 ++++++++++++++++++++++------------------- js/src/jstracer.h | 161 ++++++----- 4 files changed, 456 insertions(+), 394 deletions(-) diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 5618301244da..978f8723873d 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -113,6 +113,7 @@ static const size_t MAX_GLOBAL_SLOTS = 4096; static const size_t GLOBAL_SLOTS_BUFFER_SIZE = MAX_GLOBAL_SLOTS + 1; /* Forward declarations of tracer types. */ +class TreeInfo; class VMAllocator; class TraceRecorder; class FrameInfoCache; @@ -148,7 +149,7 @@ struct InterpState // call exit guard mismatched void* rpAtLastTreeCall; // value of rp at innermost tree call guard VMSideExit* outermostTreeExitGuard; // the last side exit returned by js_CallTree - TreeFragment* outermostTree; // the outermost tree we initially invoked + TreeInfo* outermostTree; // the outermost tree we initially invoked uintN* inlineCallCountp; // inline call count counter VMSideExit** innermostNestedGuardp; VMSideExit* innermost; @@ -167,7 +168,7 @@ struct InterpState uintN nativeVpLen; jsval* nativeVp; - InterpState(JSContext *cx, JSTraceMonitor *tm, TreeFragment *ti, + InterpState(JSContext *cx, JSTraceMonitor *tm, TreeInfo *ti, uintN &inlineCallCountp, VMSideExit** innermostNestedGuardp); ~InterpState(); }; diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp index 2ad62fdc407c..d06430e094a1 100644 --- a/js/src/jsrecursion.cpp +++ b/js/src/jsrecursion.cpp @@ -70,7 +70,7 @@ class RecursiveSlotMap : public SlotMap * Store at exit->sp_adj - sizeof(double) */ ptrdiff_t retOffset = downPostSlots * sizeof(double) - - mRecorder.tree->nativeStackBase; + mRecorder.treeInfo->nativeStackBase; mRecorder.lir->insStorei(mRecorder.addName(rval_ins, "rval_ins"), mRecorder.lirbuf->sp, retOffset); } @@ -93,7 +93,7 @@ class UpRecursiveSlotMap : public RecursiveSlotMap /* * The native stack offset of the return value once this frame has * returned, is: - * -tree->nativeStackBase + downPostSlots * sizeof(double) + * -treeInfo->nativeStackBase + downPostSlots * sizeof(double) * * Note, not +1, since the offset is 0-based. * @@ -101,15 +101,15 @@ class UpRecursiveSlotMap : public RecursiveSlotMap * be the amount down recursion added, which was just guarded as * |downPostSlots|. So the offset is: * - * -tree->nativeStackBase + downPostSlots * sizeof(double) - + * -treeInfo->nativeStackBase + downPostSlots * sizeof(double) - * downPostSlots * sizeof(double) * Or: - * -tree->nativeStackBase + * -treeInfo->nativeStackBase * * This makes sense because this slot is just above the highest sp for * the down frame. */ - lir->insStorei(rval_ins, lirbuf->sp, -mRecorder.tree->nativeStackBase); + lir->insStorei(rval_ins, lirbuf->sp, -mRecorder.treeInfo->nativeStackBase); lirbuf->sp = lir->ins2(LIR_piadd, lirbuf->sp, lir->insImmWord(-int(downPostSlots) * sizeof(double))); @@ -152,7 +152,7 @@ TraceRecorder::downSnapshot(FrameInfo* downFrame) /* Build the typemap the exit will have. Note extra stack slot for return value. */ unsigned downPostSlots = downFrame->callerHeight; - unsigned ngslots = tree->globalSlots->length(); + unsigned ngslots = treeInfo->globalSlots->length(); unsigned exitTypeMapLen = downPostSlots + 1 + ngslots; JSTraceType* exitTypeMap = (JSTraceType*)alloca(sizeof(JSTraceType) * exitTypeMapLen); JSTraceType* typeMap = downFrame->get_typemap(); @@ -176,7 +176,7 @@ TraceRecorder::downSnapshot(FrameInfo* downFrame) exit->block = cx->fp->down->blockChain; exit->pc = downFrame->pc + JSOP_CALL_LENGTH; exit->imacpc = NULL; - exit->sp_adj = ((downPostSlots + 1) * sizeof(double)) - tree->nativeStackBase; + exit->sp_adj = ((downPostSlots + 1) * sizeof(double)) - treeInfo->nativeStackBase; exit->rp_adj = exit->calldepth * sizeof(FrameInfo*); exit->nativeCalleeWord = 0; exit->lookupFlags = js_InferFlags(cx, 0); @@ -257,11 +257,11 @@ TraceRecorder::upRecursion() */ js_CaptureStackTypes(cx, 1, fi->get_typemap()); } else { - /* Case 2: Guess that up-recursion is backing out, infer types from our Tree. */ - JS_ASSERT(tree->nStackTypes == downPostSlots + 1); + /* Case 2: Guess that up-recursion is backing out, infer types from our TreeInfo. */ + JS_ASSERT(treeInfo->nStackTypes == downPostSlots + 1); JSTraceType* typeMap = fi->get_typemap(); for (unsigned i = 0; i < downPostSlots; i++) - typeMap[i] = tree->typeMap[i]; + typeMap[i] = treeInfo->typeMap[i]; } fi = traceMonitor->frameCache->memoize(fi); @@ -311,7 +311,7 @@ TraceRecorder::upRecursion() for (unsigned i = 0; i < downPostSlots; i++) slotMap.addSlot(exit->stackType(i)); slotMap.addSlot(&stackval(-1)); - VisitGlobalSlots(slotMap, cx, *tree->globalSlots); + VisitGlobalSlots(slotMap, cx, *treeInfo->globalSlots); if (recursive_pc == (jsbytecode*)fragment->root->ip) { debug_only_print0(LC_TMTracer, "Compiling up-recursive loop...\n"); } else { @@ -319,9 +319,9 @@ TraceRecorder::upRecursion() exit->exitType = RECURSIVE_UNLINKED_EXIT; exit->recursive_pc = recursive_pc; } - JS_ASSERT(tree->recursion != Recursion_Disallowed); - if (tree->recursion != Recursion_Detected) - tree->recursion = Recursion_Unwinds; + JS_ASSERT(treeInfo->recursion != Recursion_Disallowed); + if (treeInfo->recursion != Recursion_Detected) + treeInfo->recursion = Recursion_Unwinds; return closeLoop(slotMap, exit); } @@ -424,7 +424,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) * value. The slurpSlot variable keeps track of the last slot that has been * unboxed, as to avoid re-unboxing when taking a SLURP_FAIL exit. */ - unsigned numGlobalSlots = tree->globalSlots->length(); + unsigned numGlobalSlots = treeInfo->globalSlots->length(); unsigned safeSlots = NativeStackSlots(cx, frameDepth) + 1 + numGlobalSlots; jsbytecode* recursive_pc = return_pc + JSOP_CALL_LENGTH; VMSideExit* exit = (VMSideExit*) @@ -435,7 +435,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) exit->exitType = RECURSIVE_SLURP_FAIL_EXIT; exit->numStackSlots = downPostSlots + 1; exit->numGlobalSlots = numGlobalSlots; - exit->sp_adj = ((downPostSlots + 1) * sizeof(double)) - tree->nativeStackBase; + exit->sp_adj = ((downPostSlots + 1) * sizeof(double)) - treeInfo->nativeStackBase; exit->recursive_pc = recursive_pc; /* @@ -557,7 +557,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) for (unsigned i = 0; i < downPostSlots; i++) slotMap.addSlot(typeMap[i]); slotMap.addSlot(&stackval(-1), typeMap[downPostSlots]); - VisitGlobalSlots(slotMap, cx, *tree->globalSlots); + VisitGlobalSlots(slotMap, cx, *treeInfo->globalSlots); debug_only_print0(LC_TMTracer, "Compiling up-recursive slurp...\n"); exit = copy(exit); if (exit->recursive_pc == fragment->root->ip) @@ -566,7 +566,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) exit->exitType = RECURSIVE_UNLINKED_EXIT; debug_only_printf(LC_TMTreeVis, "TREEVIS CHANGEEXIT EXIT=%p TYPE=%s\n", (void*)exit, getExitName(exit->exitType)); - JS_ASSERT(tree->recursion >= Recursion_Unwinds); + JS_ASSERT(treeInfo->recursion >= Recursion_Unwinds); return closeLoop(slotMap, exit); } @@ -584,9 +584,9 @@ TraceRecorder::downRecursion() JS_ASSERT(unsigned(slots) == NativeStackSlots(cx, 1) - fp->argc - 2 - fp->script->nfixed - 1); /* Guard that there is enough stack space. */ - JS_ASSERT(tree->maxNativeStackSlots >= tree->nativeStackBase / sizeof(double)); - int guardSlots = slots + tree->maxNativeStackSlots - - tree->nativeStackBase / sizeof(double); + JS_ASSERT(treeInfo->maxNativeStackSlots >= treeInfo->nativeStackBase / sizeof(double)); + int guardSlots = slots + treeInfo->maxNativeStackSlots - + treeInfo->nativeStackBase / sizeof(double); LIns* sp_top = lir->ins2(LIR_piadd, lirbuf->sp, lir->insImmWord(guardSlots * sizeof(double))); guard(true, lir->ins2(LIR_plt, sp_top, eos_ins), OOM_EXIT); @@ -618,8 +618,8 @@ TraceRecorder::downRecursion() exit = snapshot(RECURSIVE_UNLINKED_EXIT); exit->recursive_pc = fp->script->code; debug_only_print0(LC_TMTracer, "Compiling down-recursive function call.\n"); - JS_ASSERT(tree->recursion != Recursion_Disallowed); - tree->recursion = Recursion_Detected; + JS_ASSERT(treeInfo->recursion != Recursion_Disallowed); + treeInfo->recursion = Recursion_Detected; return closeLoop(exit); } @@ -783,7 +783,7 @@ TraceRecorder::slurpSlot(LIns* val_ins, jsval* vp, SlurpInfo* info) LIns* val = slurpSlot(val_ins, vp, exit); lir->insStorei(val, lirbuf->sp, - -tree->nativeStackBase + ptrdiff_t(info->curSlot) * sizeof(double)); + -treeInfo->nativeStackBase + ptrdiff_t(info->curSlot) * sizeof(double)); info->curSlot++; } diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 6d8387237deb..ca09522a14d1 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -1153,43 +1153,43 @@ Oracle::clearDemotability() } JS_REQUIRES_STACK static JS_INLINE void -MarkSlotUndemotable(JSContext* cx, LinkableFragment* f, unsigned slot) +MarkSlotUndemotable(JSContext* cx, TreeInfo* ti, unsigned slot) { - if (slot < f->nStackTypes) { + if (slot < ti->nStackTypes) { oracle.markStackSlotUndemotable(cx, slot); return; } - uint16* gslots = f->globalSlots->data(); - oracle.markGlobalSlotUndemotable(cx, gslots[slot - f->nStackTypes]); + uint16* gslots = ti->globalSlots->data(); + oracle.markGlobalSlotUndemotable(cx, gslots[slot - ti->nStackTypes]); } JS_REQUIRES_STACK static JS_INLINE void -MarkSlotUndemotable(JSContext* cx, LinkableFragment* f, unsigned slot, const void* pc) +MarkSlotUndemotable(JSContext* cx, TreeInfo* ti, unsigned slot, const void* pc) { - if (slot < f->nStackTypes) { + if (slot < ti->nStackTypes) { oracle.markStackSlotUndemotable(cx, slot, pc); return; } - uint16* gslots = f->globalSlots->data(); - oracle.markGlobalSlotUndemotable(cx, gslots[slot - f->nStackTypes]); + uint16* gslots = ti->globalSlots->data(); + oracle.markGlobalSlotUndemotable(cx, gslots[slot - ti->nStackTypes]); } static JS_REQUIRES_STACK inline bool -IsSlotUndemotable(JSContext* cx, LinkableFragment* f, unsigned slot, const void* ip) +IsSlotUndemotable(JSContext* cx, TreeInfo* ti, unsigned slot, const void* ip) { - if (slot < f->nStackTypes) + if (slot < ti->nStackTypes) return oracle.isStackSlotUndemotable(cx, slot, ip); - uint16* gslots = f->globalSlots->data(); - return oracle.isGlobalSlotUndemotable(cx, gslots[slot - f->nStackTypes]); + uint16* gslots = ti->globalSlots->data(); + return oracle.isGlobalSlotUndemotable(cx, gslots[slot - ti->nStackTypes]); } static JS_REQUIRES_STACK inline bool -IsSlotUndemotable(JSContext* cx, LinkableFragment* f, unsigned slot) +IsSlotUndemotable(JSContext* cx, TreeInfo* ti, unsigned slot) { - return IsSlotUndemotable(cx, f, slot, cx->fp->regs->pc); + return IsSlotUndemotable(cx, ti, slot, cx->fp->regs->pc); } class FrameInfoCache @@ -1417,8 +1417,8 @@ LookupOrAddLoop(JSTraceMonitor* tm, const void *ip, JSObject* globalObj, uint32_t profFragID = (js_LogController.lcbits & LC_FragProfile) ? (++(tm->lastFragID)) : 0; ) - TreeFragment* f = new (*tm->dataAlloc) TreeFragment(ip, tm->dataAlloc, globalObj, globalShape, - argc verbose_only(, profFragID)); + TreeFragment* f = new (*tm->dataAlloc) TreeFragment(ip, globalObj, globalShape, argc + verbose_only(, profFragID)); f->root = f; /* f is the root of a new tree */ *prevTreeNextp = f; /* insert f at the end of the vmfragments bucket-list */ f->next = NULL; @@ -1435,9 +1435,9 @@ AddNewPeerToPeerList(JSTraceMonitor* tm, TreeFragment* peer) uint32_t profFragID = (js_LogController.lcbits & LC_FragProfile) ? (++(tm->lastFragID)) : 0; ) - TreeFragment* f = new (*tm->dataAlloc) TreeFragment(peer->ip, tm->dataAlloc, peer->globalObj, - peer->globalShape, peer->argc - verbose_only(, profFragID)); + TreeFragment* f = new (*tm->dataAlloc) TreeFragment(peer->ip, peer->globalObj, + peer->globalShape, peer->argc + verbose_only(, profFragID)); f->root = f; /* f is the root of a new tree */ f->first = peer->first; /* add f to peer list */ f->peer = peer->peer; @@ -1447,55 +1447,9 @@ AddNewPeerToPeerList(JSTraceMonitor* tm, TreeFragment* peer) return f; } -void -TreeFragment::initialize(JSContext* cx, SlotList *globalSlots) -{ - this->dependentTrees.clear(); - this->linkedTrees.clear(); - this->globalSlots = globalSlots; - - /* Capture the coerced type of each active slot in the type map. */ - this->typeMap.captureTypes(cx, globalObj, *globalSlots, 0 /* callDepth */); - this->nStackTypes = this->typeMap.length() - globalSlots->length(); - -#ifdef DEBUG - this->treeFileName = cx->fp->script->filename; - this->treeLineNumber = js_FramePCToLineNumber(cx, cx->fp); - this->treePCOffset = FramePCOffset(cx->fp); -#endif - this->script = cx->fp->script; - this->recursion = Recursion_None; - this->gcthings.clear(); - this->sprops.clear(); - this->unstableExits = NULL; - this->sideExits.clear(); - - /* Determine the native frame layout at the entry point. */ - this->nativeStackBase = (nStackTypes - (cx->fp->regs->sp - StackBase(cx->fp))) * - sizeof(double); - this->maxNativeStackSlots = nStackTypes; - this->maxCallDepth = 0; -} - -UnstableExit* -TreeFragment::removeUnstableExit(VMSideExit* exit) -{ - /* Now erase this exit from the unstable exit list. */ - UnstableExit** tail = &this->unstableExits; - for (UnstableExit* uexit = this->unstableExits; uexit != NULL; uexit = uexit->next) { - if (uexit->exit == exit) { - *tail = uexit->next; - return *tail; - } - tail = &uexit->next; - } - JS_NOT_REACHED("exit not in unstable exit list"); - return NULL; -} - #ifdef DEBUG static void -AssertTreeIsUnique(JSTraceMonitor* tm, TreeFragment* f) +AssertTreeIsUnique(JSTraceMonitor* tm, TreeFragment* f, TreeInfo* ti) { JS_ASSERT(f->root == f); @@ -1504,12 +1458,15 @@ AssertTreeIsUnique(JSTraceMonitor* tm, TreeFragment* f) * trace explosion since we are trying to stabilize something without * properly connecting peer edges. */ + TreeInfo* ti_other; for (TreeFragment* peer = LookupLoop(tm, f->ip, f->globalObj, f->globalShape, f->argc); peer != NULL; peer = peer->peer) { if (!peer->code() || peer == f) continue; - JS_ASSERT(!f->typeMap.matches(peer->typeMap)); + ti_other = peer->treeInfo; + JS_ASSERT(ti_other); + JS_ASSERT(!ti->typeMap.matches(ti_other->typeMap)); } } #endif @@ -2045,10 +2002,10 @@ VisitGlobalSlots(Visitor &visitor, JSContext *cx, JSObject *globalObj, template static JS_REQUIRES_STACK JS_ALWAYS_INLINE void -VisitGlobalSlots(Visitor &visitor, JSContext *cx, TreeFragment *f) +VisitGlobalSlots(Visitor &visitor, JSContext *cx, TreeInfo *ti) { - JSObject* globalObj = f->globalObj(); - SlotList& gslots = *f->globalSlots; + JSObject* globalObj = ti->globalObj(); + SlotList& gslots = *ti->globalSlots; VisitGlobalSlots(visitor, cx, globalObj, gslots.length(), gslots.data()); } @@ -2296,22 +2253,24 @@ MergeTypeMaps(JSTraceType** partial, unsigned* plength, JSTraceType* complete, u /* Specializes a tree to any missing globals, including any dependent trees. */ static JS_REQUIRES_STACK void -SpecializeTreesToMissingGlobals(JSContext* cx, JSObject* globalObj, TreeFragment* root) +SpecializeTreesToMissingGlobals(JSContext* cx, JSObject* globalObj, TreeInfo* root) { - root->typeMap.captureMissingGlobalTypes(cx, globalObj, *root->globalSlots, root->nStackTypes); - JS_ASSERT(root->globalSlots->length() == root->typeMap.length() - root->nStackTypes); + TreeInfo* ti = root; + + ti->typeMap.captureMissingGlobalTypes(cx, globalObj, *ti->globalSlots, ti->nStackTypes); + JS_ASSERT(ti->globalSlots->length() == ti->typeMap.length() - ti->nStackTypes); for (unsigned i = 0; i < root->dependentTrees.length(); i++) { - TreeFragment* f = root->dependentTrees[i]; + ti = root->dependentTrees[i]->treeInfo; - /* code() can be NULL if we hit the recording tree in emitTreeCall; this is harmless. */ - if (f->code() && f->nGlobalTypes() < f->globalSlots->length()) - SpecializeTreesToMissingGlobals(cx, globalObj, f); + /* ti can be NULL if we hit the recording tree in emitTreeCall; this is harmless. */ + if (ti && ti->nGlobalTypes() < ti->globalSlots->length()) + SpecializeTreesToMissingGlobals(cx, globalObj, ti); } for (unsigned i = 0; i < root->linkedTrees.length(); i++) { - TreeFragment* f = root->linkedTrees[i]; - if (f->code() && f->nGlobalTypes() < f->globalSlots->length()) - SpecializeTreesToMissingGlobals(cx, globalObj, f); + ti = root->linkedTrees[i]->treeInfo; + if (ti && ti->nGlobalTypes() < ti->globalSlots->length()) + SpecializeTreesToMissingGlobals(cx, globalObj, ti); } } @@ -2341,15 +2300,15 @@ InitConst(const T &t) JS_REQUIRES_STACK TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* fragment, - unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap, + TreeInfo* ti, unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap, VMSideExit* innermost, jsbytecode* outer, uint32 outerArgc, RecordReason recordReason) : cx(cx), traceMonitor(&JS_TRACE_MONITOR(cx)), fragment(fragment), - tree(fragment->root), + treeInfo(ti), recordReason(recordReason), - globalObj(tree->globalObj), + globalObj(ti->globalObj()), outer(outer), outerArgc(outerArgc), lexicalBlock(cx->fp->blockChain), @@ -2361,7 +2320,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag loopLabel(NULL), lirbuf(traceMonitor->lirbuf), mark(*traceMonitor->traceAlloc), - numSideExitsBefore(tree->sideExits.length()), + numSideExitsBefore(treeInfo->sideExits.length()), tracker(), nativeFrameTracker(), global_dslots(NULL), @@ -2382,6 +2341,9 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag { JS_ASSERT(globalObj == JS_GetGlobalForObject(cx, cx->fp->scopeChain)); JS_ASSERT(cx->fp->regs->pc == (jsbytecode*)fragment->ip); + JS_ASSERT(fragment->root == treeInfo->rootFragment); + JS_ASSERT_IF(fragment->root == fragment, !fragment->root->treeInfo); + JS_ASSERT(ti); /* * Reset the fragment state we care about in case we got a recycled @@ -2409,7 +2371,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag #ifdef JS_JIT_SPEW debug_only_print0(LC_TMMinimal, "\n"); debug_only_printf(LC_TMMinimal, "Recording starting from %s:%u@%u (FragID=%06u)\n", - tree->treeFileName, tree->treeLineNumber, tree->treePCOffset, + ti->treeFileName, ti->treeLineNumber, ti->treePCOffset, fragment->profFragID); debug_only_printf(LC_TMTracer, "globalObj=%p, shape=%d\n", @@ -2475,11 +2437,11 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag InitConst(eor_ins) = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, eor)), "eor"); /* If we came from exit, we might not have enough global types. */ - if (tree->globalSlots->length() > tree->nGlobalTypes()) - SpecializeTreesToMissingGlobals(cx, globalObj, tree); + if (ti->globalSlots->length() > ti->nGlobalTypes()) + SpecializeTreesToMissingGlobals(cx, globalObj, ti); /* read into registers all values on the stack and all globals we know so far */ - import(tree, lirbuf->sp, stackSlots, ngslots, callDepth, typeMap); + import(treeInfo, lirbuf->sp, stackSlots, ngslots, callDepth, typeMap); /* Finish handling RECURSIVE_SLURP_FAIL_EXIT in startRecorder. */ if (anchor && anchor->exitType == RECURSIVE_SLURP_FAIL_EXIT) @@ -2510,6 +2472,7 @@ TraceRecorder::~TraceRecorder() { /* Should already have been adjusted by callers before calling delete. */ JS_ASSERT(traceMonitor->recorder != this); + JS_ASSERT(fragment->root == treeInfo->rootFragment); if (trashSelf) TrashTree(cx, fragment->root); @@ -2541,6 +2504,7 @@ TraceRecorder::finishSuccessfully() { JS_ASSERT(traceMonitor->recorder == this); JS_ASSERT(fragment->lastIns && fragment->code()); + JS_ASSERT_IF(fragment == fragment->root, fragment->toTreeFragment()->treeInfo); AUDIT(traceCompleted); mark.commit(); @@ -2566,14 +2530,15 @@ TraceRecorder::finishAbort(const char* reason) { JS_ASSERT(traceMonitor->recorder == this); JS_ASSERT(!fragment->code()); + JS_ASSERT_IF(fragment == fragment->root, !fragment->toTreeFragment()->treeInfo); AUDIT(recorderAborted); #ifdef DEBUG debug_only_printf(LC_TMAbort, "Abort recording of tree %s:%d@%d at %s:%d@%d: %s.\n", - tree->treeFileName, - tree->treeLineNumber, - tree->treePCOffset, + treeInfo->treeFileName, + treeInfo->treeLineNumber, + treeInfo->treePCOffset, cx->fp->script->filename, js_FramePCToLineNumber(cx, cx->fp), FramePCOffset(cx->fp), @@ -2583,8 +2548,8 @@ TraceRecorder::finishAbort(const char* reason) /* * If this is the primary trace and we didn't succeed compiling, trash the - * tree. Otherwise, remove the VMSideExits we added while recording, which - * are about to be invalid. + * TreeInfo object. Otherwise, remove the VMSideExits we added while + * recording, which are about to be invalid. * * BIG FAT WARNING: resetting the length is only a valid strategy as long as * there may be only one recorder active for a single TreeInfo at a time. @@ -2593,8 +2558,8 @@ TraceRecorder::finishAbort(const char* reason) if (fragment->root == fragment) { TrashTree(cx, fragment->toTreeFragment()); } else { - JS_ASSERT(numSideExitsBefore <= fragment->root->sideExits.length()); - fragment->root->sideExits.setLength(numSideExitsBefore); + JS_ASSERT(numSideExitsBefore <= fragment->root->treeInfo->sideExits.length()); + fragment->root->treeInfo->sideExits.setLength(numSideExitsBefore); } /* Grab local copies of members needed after |delete this|. */ @@ -2627,35 +2592,35 @@ inline LIns* TraceRecorder::insImmVal(jsval val) { if (JSVAL_IS_TRACEABLE(val)) - tree->gcthings.addUnique(val); + treeInfo->gcthings.addUnique(val); return lir->insImmWord(val); } inline LIns* TraceRecorder::insImmObj(JSObject* obj) { - tree->gcthings.addUnique(OBJECT_TO_JSVAL(obj)); + treeInfo->gcthings.addUnique(OBJECT_TO_JSVAL(obj)); return lir->insImmPtr((void*)obj); } inline LIns* TraceRecorder::insImmFun(JSFunction* fun) { - tree->gcthings.addUnique(OBJECT_TO_JSVAL(FUN_OBJECT(fun))); + treeInfo->gcthings.addUnique(OBJECT_TO_JSVAL(FUN_OBJECT(fun))); return lir->insImmPtr((void*)fun); } inline LIns* TraceRecorder::insImmStr(JSString* str) { - tree->gcthings.addUnique(STRING_TO_JSVAL(str)); + treeInfo->gcthings.addUnique(STRING_TO_JSVAL(str)); return lir->insImmPtr((void*)str); } inline LIns* TraceRecorder::insImmSprop(JSScopeProperty* sprop) { - tree->sprops.addUnique(sprop); + treeInfo->sprops.addUnique(sprop); return lir->insImmPtr((void*)sprop); } @@ -2692,7 +2657,7 @@ TraceRecorder::isGlobal(jsval* p) const * |p| must be the address of a jsval that is represented in the native stack * area. The return value is the offset, from InterpState::stackBase, in bytes, * where the native representation of |*p| is stored. To get the offset - * relative to InterpState::sp, subtract TreeFragment::nativeStackBase. + * relative to InterpState::sp, subtract TreeInfo::nativeStackBase. */ JS_REQUIRES_STACK ptrdiff_t TraceRecorder::nativeStackOffset(jsval* p) const @@ -2713,20 +2678,20 @@ TraceRecorder::nativeStackOffset(jsval* p) const } /* * Return the offset, from InterpState:sp, for the given jsval. Shorthand for: - * -TreeFragment::nativeStackBase + nativeStackOffset(p). + * -TreeInfo::nativeStackBase + nativeStackOffset(p). */ inline JS_REQUIRES_STACK ptrdiff_t TraceRecorder::nativespOffset(jsval* p) const { - return -tree->nativeStackBase + nativeStackOffset(p); + return -treeInfo->nativeStackBase + nativeStackOffset(p); } /* Track the maximum number of native frame slots we need during execution. */ inline void TraceRecorder::trackNativeStackUse(unsigned slots) { - if (slots > tree->maxNativeStackSlots) - tree->maxNativeStackSlots = slots; + if (slots > treeInfo->maxNativeStackSlots) + treeInfo->maxNativeStackSlots = slots; } /* @@ -2869,17 +2834,17 @@ JSTraceMonitor::flush() } static inline void -MarkTree(JSTracer* trc, TreeFragment *f) +MarkTreeInfo(JSTracer* trc, TreeInfo *ti) { - jsval* vp = f->gcthings.data(); - unsigned len = f->gcthings.length(); + jsval* vp = ti->gcthings.data(); + unsigned len = ti->gcthings.length(); while (len--) { jsval v = *vp++; JS_SET_TRACING_NAME(trc, "jitgcthing"); JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v)); } - JSScopeProperty** spropp = f->sprops.data(); - len = f->sprops.length(); + JSScopeProperty** spropp = ti->sprops.data(); + len = ti->sprops.length(); while (len--) { JSScopeProperty* sprop = *spropp++; sprop->trace(trc); @@ -2893,19 +2858,19 @@ JSTraceMonitor::mark(JSTracer* trc) for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) { TreeFragment* f = vmfragments[i]; while (f) { - if (f->code()) - MarkTree(trc, f); + if (TreeInfo* ti = f->treeInfo) + MarkTreeInfo(trc, ti); TreeFragment* peer = f->peer; while (peer) { - if (peer->code()) - MarkTree(trc, peer); + if (TreeInfo* ti = peer->treeInfo) + MarkTreeInfo(trc, ti); peer = peer->peer; } f = f->next; } } if (recorder) - MarkTree(trc, recorder->getTree()); + MarkTreeInfo(trc, recorder->getTreeInfo()); } } @@ -3185,7 +3150,7 @@ GetUpvarOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, // Next search the trace entry frame, which is not in the FrameInfo stack. if (state->outermostTree->script->staticLevel == upvarLevel) { - uint32 argc = state->outermostTree->argc; + uint32 argc = state->outermostTree->rootFragment->argc; uint32 native_slot = T::native_slot(argc, slot); *result = state->stackBase[native_slot]; return state->callstackBase[0]->get_typemap()[native_slot]; @@ -3611,7 +3576,7 @@ public: }; JS_REQUIRES_STACK void -TraceRecorder::import(TreeFragment* tree, LIns* sp, unsigned stackSlots, unsigned ngslots, +TraceRecorder::import(TreeInfo* treeInfo, LIns* sp, unsigned stackSlots, unsigned ngslots, unsigned callDepth, JSTraceType* typeMap) { /* @@ -3630,7 +3595,7 @@ TraceRecorder::import(TreeFragment* tree, LIns* sp, unsigned stackSlots, unsigne */ JSTraceType* globalTypeMap = typeMap + stackSlots; - unsigned length = tree->nGlobalTypes(); + unsigned length = treeInfo->nGlobalTypes(); /* * This is potentially the typemap of the side exit and thus shorter than @@ -3638,11 +3603,11 @@ TraceRecorder::import(TreeFragment* tree, LIns* sp, unsigned stackSlots, unsigne */ if (ngslots < length) { MergeTypeMaps(&globalTypeMap /* out param */, &ngslots /* out param */, - tree->globalTypeMap(), length, + treeInfo->globalTypeMap(), length, (JSTraceType*)alloca(sizeof(JSTraceType) * length)); } - JS_ASSERT(ngslots == tree->nGlobalTypes()); - ptrdiff_t offset = -tree->nativeStackBase; + JS_ASSERT(ngslots == treeInfo->nGlobalTypes()); + ptrdiff_t offset = -treeInfo->nativeStackBase; /* * Check whether there are any values on the stack we have to unbox and do @@ -3655,7 +3620,7 @@ TraceRecorder::import(TreeFragment* tree, LIns* sp, unsigned stackSlots, unsigne ImportGlobalSlotVisitor globalVisitor(*this, eos_ins, globalTypeMap); VisitGlobalSlots(globalVisitor, cx, globalObj, ngslots, - tree->globalSlots->data()); + treeInfo->globalSlots->data()); if (!anchor || anchor->exitType != RECURSIVE_SLURP_FAIL_EXIT) { ImportUnboxedStackSlotVisitor unboxedStackVisitor(*this, sp, offset, @@ -3704,17 +3669,17 @@ TraceRecorder::lazilyImportGlobalSlot(unsigned slot) jsval* vp = &STOBJ_GET_SLOT(globalObj, slot); if (known(vp)) return true; /* we already have it */ - unsigned index = tree->globalSlots->length(); + unsigned index = treeInfo->globalSlots->length(); /* Add the slot to the list of interned global slots. */ - JS_ASSERT(tree->nGlobalTypes() == tree->globalSlots->length()); - tree->globalSlots->add(slot); + JS_ASSERT(treeInfo->nGlobalTypes() == treeInfo->globalSlots->length()); + treeInfo->globalSlots->add(slot); JSTraceType type = getCoercedType(*vp); if (type == TT_INT32 && oracle.isGlobalSlotUndemotable(cx, slot)) type = TT_DOUBLE; - tree->typeMap.add(type); + treeInfo->typeMap.add(type); import(eos_ins, slot*sizeof(double), vp, type, "global", index, NULL); - SpecializeTreesToMissingGlobals(cx, globalObj, tree); + SpecializeTreesToMissingGlobals(cx, globalObj, treeInfo); return true; } @@ -3940,10 +3905,12 @@ public: JS_REQUIRES_STACK void TraceRecorder::adjustCallerTypes(TreeFragment* f) { - AdjustCallerGlobalTypesVisitor globalVisitor(*this, f->globalTypeMap()); - VisitGlobalSlots(globalVisitor, cx, *tree->globalSlots); + TreeInfo* ti = f->treeInfo; - AdjustCallerStackTypesVisitor stackVisitor(*this, f->stackTypeMap()); + AdjustCallerGlobalTypesVisitor globalVisitor(*this, ti->globalTypeMap()); + VisitGlobalSlots(globalVisitor, cx, *treeInfo->globalSlots); + + AdjustCallerStackTypesVisitor stackVisitor(*this, ti->stackTypeMap()); VisitStackSlots(stackVisitor, cx, 0); JS_ASSERT(f == f->root); @@ -4061,7 +4028,7 @@ TraceRecorder::snapshot(ExitType exitType) trackNativeStackUse(stackSlots + 1); /* Capture the type map into a temporary location. */ - unsigned ngslots = tree->globalSlots->length(); + unsigned ngslots = treeInfo->globalSlots->length(); unsigned typemap_size = (stackSlots + ngslots) * sizeof(JSTraceType); /* Use the recorder-local temporary type map. */ @@ -4077,7 +4044,7 @@ TraceRecorder::snapshot(ExitType exitType) */ DetermineTypesVisitor detVisitor(*this, typemap); VisitSlots(detVisitor, cx, callDepth, ngslots, - tree->globalSlots->data()); + treeInfo->globalSlots->data()); JS_ASSERT(unsigned(detVisitor.getTypeMap() - typemap) == ngslots + stackSlots); @@ -4116,8 +4083,8 @@ TraceRecorder::snapshot(ExitType exitType) * Check if we already have a matching side exit; if so we can return that * side exit instead of creating a new one. */ - VMSideExit** exits = tree->sideExits.data(); - unsigned nexits = tree->sideExits.length(); + VMSideExit** exits = treeInfo->sideExits.data(); + unsigned nexits = treeInfo->sideExits.length(); if (exitType == LOOP_EXIT) { for (unsigned n = 0; n < nexits; ++n) { VMSideExit* e = exits[n]; @@ -4148,10 +4115,10 @@ TraceRecorder::snapshot(ExitType exitType) exit->exitType = exitType; exit->block = fp->blockChain; if (fp->blockChain) - tree->gcthings.addUnique(OBJECT_TO_JSVAL(fp->blockChain)); + treeInfo->gcthings.addUnique(OBJECT_TO_JSVAL(fp->blockChain)); exit->pc = pc; exit->imacpc = fp->imacpc; - exit->sp_adj = (stackSlots * sizeof(double)) - tree->nativeStackBase; + exit->sp_adj = (stackSlots * sizeof(double)) - treeInfo->nativeStackBase; exit->rp_adj = exit->calldepth * sizeof(FrameInfo*); exit->nativeCalleeWord = 0; exit->lookupFlags = js_InferFlags(cx, 0); @@ -4196,7 +4163,7 @@ TraceRecorder::guard(bool expected, LIns* cond, VMSideExit* exit) GuardRecord* guardRec = createGuardRecord(exit); if (exit->exitType == LOOP_EXIT) - tree->sideExits.add(exit); + treeInfo->sideExits.add(exit); if (!cond->isCond()) { expected = !expected; @@ -4225,7 +4192,7 @@ TraceRecorder::copy(VMSideExit* copy) exit->target = NULL; if (exit->exitType == LOOP_EXIT) - tree->sideExits.add(exit); + treeInfo->sideExits.add(exit); #if defined JS_JIT_SPEW TreevisLogExit(cx, exit); #endif @@ -4304,7 +4271,7 @@ TraceRecorder::compile() ResetJIT(cx, FR_DEEP_BAIL); return ARECORD_ABORTED; } - if (tree->maxNativeStackSlots >= MAX_NATIVE_STACK_SLOTS) { + if (treeInfo->maxNativeStackSlots >= MAX_NATIVE_STACK_SLOTS) { debug_only_print0(LC_TMTracer, "Blacklist: excessive stack use.\n"); Blacklist((jsbytecode*) fragment->root->ip); return ARECORD_STOP; @@ -4349,7 +4316,9 @@ TraceRecorder::compile() assm->patch(anchor); } JS_ASSERT(fragment->code()); - JS_ASSERT_IF(fragment == fragment->root, fragment->root == tree); + JS_ASSERT_IF(fragment == fragment->root, !fragment->root->treeInfo); + if (fragment == fragment->root) + fragment->root->treeInfo = treeInfo; return ARECORD_CONTINUE; } @@ -4365,8 +4334,8 @@ JoinPeers(Assembler* assm, VMSideExit* exit, TreeFragment* target) if (exit->root() == target) return; - target->dependentTrees.addUnique(exit->root()); - exit->root()->linkedTrees.addUnique(target); + target->treeInfo->dependentTrees.addUnique(exit->root()); + exit->root()->treeInfo->linkedTrees.addUnique(target); } /* Results of trying to connect an arbitrary type A with arbitrary type B */ @@ -4441,14 +4410,14 @@ class SlotMap : public SlotVisitorBase * such slots as undemotable. */ JS_REQUIRES_STACK TypeConsensus - checkTypes(LinkableFragment* f) + checkTypes(TreeInfo* ti) { - if (length() != f->typeMap.length()) + if (length() != ti->typeMap.length()) return TypeConsensus_Bad; bool has_undemotes = false; for (unsigned i = 0; i < length(); i++) { - TypeCheckResult result = checkType(i, f->typeMap[i]); + TypeCheckResult result = checkType(i, ti->typeMap[i]); if (result == TypeCheck_Bad) return TypeConsensus_Bad; if (result == TypeCheck_Undemote) @@ -4483,7 +4452,7 @@ class SlotMap : public SlotVisitorBase { for (unsigned i = 0; i < length(); i++) { if (get(i).lastCheck == TypeCheck_Undemote) - MarkSlotUndemotable(mRecorder.cx, mRecorder.tree, i); + MarkSlotUndemotable(mRecorder.cx, mRecorder.treeInfo, i); } } @@ -4573,7 +4542,7 @@ JS_REQUIRES_STACK TypeConsensus TraceRecorder::selfTypeStability(SlotMap& slotMap) { debug_only_printf(LC_TMTracer, "Checking type stability against self=%p\n", (void*)fragment); - TypeConsensus consensus = slotMap.checkTypes(tree); + TypeConsensus consensus = slotMap.checkTypes(treeInfo); /* Best case: loop jumps back to its own header */ if (consensus == TypeConsensus_Okay) @@ -4601,10 +4570,10 @@ TraceRecorder::peerTypeStability(SlotMap& slotMap, const void* ip, TreeFragment* return TypeConsensus_Bad; bool onlyUndemotes = false; for (; peer != NULL; peer = peer->peer) { - if (!peer->code() || peer == fragment) + if (!peer->treeInfo || peer == fragment) continue; debug_only_printf(LC_TMTracer, "Checking type stability against peer=%p\n", (void*)peer); - TypeConsensus consensus = slotMap.checkTypes(peer); + TypeConsensus consensus = slotMap.checkTypes(peer->treeInfo); if (consensus == TypeConsensus_Okay) { *pPeer = peer; /* Return this even though there will be linkage; the trace itself is not stable. @@ -4629,7 +4598,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::closeLoop(VMSideExit* exit) { DefaultSlotMap slotMap(*this); - VisitSlots(slotMap, cx, 0, *tree->globalSlots); + VisitSlots(slotMap, cx, 0, *treeInfo->globalSlots); return closeLoop(slotMap, exit); } @@ -4658,7 +4627,7 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) } JS_ASSERT_IF(exit->exitType == UNSTABLE_LOOP_EXIT, - exit->numStackSlots == tree->nStackTypes); + exit->numStackSlots == treeInfo->nStackTypes); JS_ASSERT_IF(exit->exitType != UNSTABLE_LOOP_EXIT, exit->exitType == RECURSIVE_UNLINKED_EXIT); JS_ASSERT_IF(exit->exitType == RECURSIVE_UNLINKED_EXIT, exit->recursive_pc != fragment->root->ip); @@ -4715,16 +4684,16 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) UnstableExit* uexit = new (traceAlloc()) UnstableExit; uexit->fragment = fragment; uexit->exit = exit; - uexit->next = tree->unstableExits; - tree->unstableExits = uexit; + uexit->next = treeInfo->unstableExits; + treeInfo->unstableExits = uexit; } else { JS_ASSERT(peer->code()); exit->target = peer; debug_only_printf(LC_TMTracer, "Joining type-unstable trace to target fragment %p.\n", (void*)peer); - peer->dependentTrees.addUnique(fragment->root); - tree->linkedTrees.addUnique(peer); + peer->treeInfo->dependentTrees.addUnique(fragment->root); + treeInfo->linkedTrees.addUnique(peer); } } else { exit->exitType = LOOP_EXIT; @@ -4754,8 +4723,8 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) debug_only_print0(LC_TMTracer, "updating specializations on dependent and linked trees\n"); - if (fragment->root->code()) - SpecializeTreesToMissingGlobals(cx, globalObj, fragment->root); + if (fragment->root->treeInfo) + SpecializeTreesToMissingGlobals(cx, globalObj, fragment->root->treeInfo); /* * If this is a newly formed tree, and the outer tree has not been compiled yet, we @@ -4783,23 +4752,23 @@ FullMapFromExit(TypeMap& typeMap, VMSideExit* exit) typeMap.fromRaw(exit->stackTypeMap(), exit->numStackSlots); typeMap.fromRaw(exit->globalTypeMap(), exit->numGlobalSlots); /* Include globals that were later specialized at the root of the tree. */ - if (exit->numGlobalSlots < exit->root()->nGlobalTypes()) { - typeMap.fromRaw(exit->root()->globalTypeMap() + exit->numGlobalSlots, - exit->root()->nGlobalTypes() - exit->numGlobalSlots); + if (exit->numGlobalSlots < exit->root()->treeInfo->nGlobalTypes()) { + typeMap.fromRaw(exit->root()->treeInfo->globalTypeMap() + exit->numGlobalSlots, + exit->root()->treeInfo->nGlobalTypes() - exit->numGlobalSlots); } } static JS_REQUIRES_STACK TypeConsensus TypeMapLinkability(JSContext* cx, const TypeMap& typeMap, TreeFragment* peer) { - const TypeMap& peerMap = peer->typeMap; + const TypeMap& peerMap = peer->treeInfo->typeMap; unsigned minSlots = JS_MIN(typeMap.length(), peerMap.length()); TypeConsensus consensus = TypeConsensus_Okay; for (unsigned i = 0; i < minSlots; i++) { if (typeMap[i] == peerMap[i]) continue; if (typeMap[i] == TT_INT32 && peerMap[i] == TT_DOUBLE && - IsSlotUndemotable(cx, peer, i, peer->ip)) { + IsSlotUndemotable(cx, peer->treeInfo, i, peer->ip)) { consensus = TypeConsensus_Undemotes; } else { return TypeConsensus_Bad; @@ -4809,20 +4778,20 @@ TypeMapLinkability(JSContext* cx, const TypeMap& typeMap, TreeFragment* peer) } static JS_REQUIRES_STACK unsigned -FindUndemotesInTypemaps(JSContext* cx, const TypeMap& typeMap, LinkableFragment* f, +FindUndemotesInTypemaps(JSContext* cx, const TypeMap& typeMap, TreeInfo* treeInfo, Queue& undemotes) { undemotes.setLength(0); - unsigned minSlots = JS_MIN(typeMap.length(), f->typeMap.length()); + unsigned minSlots = JS_MIN(typeMap.length(), treeInfo->typeMap.length()); for (unsigned i = 0; i < minSlots; i++) { - if (typeMap[i] == TT_INT32 && f->typeMap[i] == TT_DOUBLE) { + if (typeMap[i] == TT_INT32 && treeInfo->typeMap[i] == TT_DOUBLE) { undemotes.add(i); - } else if (typeMap[i] != f->typeMap[i]) { + } else if (typeMap[i] != treeInfo->typeMap[i]) { return 0; } } for (unsigned i = 0; i < undemotes.length(); i++) - MarkSlotUndemotable(cx, f, undemotes[i]); + MarkSlotUndemotable(cx, treeInfo, undemotes[i]); return undemotes.length(); } @@ -4836,9 +4805,10 @@ TraceRecorder::joinEdgesToEntry(TreeFragment* peer_root) Queue undemotes(NULL); for (TreeFragment* peer = peer_root; peer; peer = peer->peer) { - if (!peer->code()) + TreeInfo* ti = peer->treeInfo; + if (!ti) continue; - UnstableExit* uexit = peer->unstableExits; + UnstableExit* uexit = ti->unstableExits; while (uexit != NULL) { /* :TODO: these exits go somewhere else. */ if (uexit->exit->exitType == RECURSIVE_UNLINKED_EXIT) { @@ -4856,10 +4826,10 @@ TraceRecorder::joinEdgesToEntry(TreeFragment* peer_root) (void*)uexit->fragment, (void*)uexit->exit); /* It's okay! Link together and remove the unstable exit. */ JoinPeers(traceMonitor->assembler, uexit->exit, (TreeFragment*)fragment); - uexit = peer->removeUnstableExit(uexit->exit); + uexit = ti->removeUnstableExit(uexit->exit); } else { /* Check for int32->double slots that suggest trashing. */ - if (FindUndemotesInTypemaps(cx, typeMap, tree, undemotes)) { + if (FindUndemotesInTypemaps(cx, typeMap, treeInfo, undemotes)) { JS_ASSERT(peer == uexit->fragment->root); if (fragment == peer) trashSelf = true; @@ -4912,8 +4882,8 @@ TraceRecorder::endLoop(VMSideExit* exit) */ debug_only_print0(LC_TMTracer, "updating specializations on dependent and linked trees\n"); - if (fragment->root->code()) - SpecializeTreesToMissingGlobals(cx, globalObj, fragment->root); + if (fragment->root->treeInfo) + SpecializeTreesToMissingGlobals(cx, globalObj, fragment->root->treeInfo); /* * If this is a newly formed tree, and the outer tree has not been compiled @@ -4938,6 +4908,7 @@ TraceRecorder::endLoop(VMSideExit* exit) JS_REQUIRES_STACK void TraceRecorder::prepareTreeCall(TreeFragment* inner, LIns*& inner_sp_ins) { + TreeInfo* ti = inner->treeInfo; inner_sp_ins = lirbuf->sp; VMSideExit* exit = snapshot(OOM_EXIT); @@ -4966,24 +4937,24 @@ TraceRecorder::prepareTreeCall(TreeFragment* inner, LIns*& inner_sp_ins) debug_only_printf(LC_TMTracer, "sp_adj=%lld outer=%lld inner=%lld\n", (long long int)sp_adj, - (long long int)tree->nativeStackBase, - (long long int)inner->nativeStackBase); + (long long int)treeInfo->nativeStackBase, + (long long int)ti->nativeStackBase); ptrdiff_t sp_offset = - - tree->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + - treeInfo->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + sp_adj /* adjust for stack in outer frame inner tree can't see */ - + inner->maxNativeStackSlots * sizeof(double); /* plus the inner tree's stack */ + + ti->maxNativeStackSlots * sizeof(double); /* plus the inner tree's stack */ LIns* sp_top = lir->ins2(LIR_piadd, lirbuf->sp, INS_CONSTWORD(sp_offset)); guard(true, lir->ins2(LIR_plt, sp_top, eos_ins), exit); /* Guard that we have enough call stack space. */ - ptrdiff_t rp_offset = rp_adj + inner->maxCallDepth * sizeof(FrameInfo*); + ptrdiff_t rp_offset = rp_adj + ti->maxCallDepth * sizeof(FrameInfo*); LIns* rp_top = lir->ins2(LIR_piadd, lirbuf->rp, INS_CONSTWORD(rp_offset)); guard(true, lir->ins2(LIR_plt, rp_top, eor_ins), exit); sp_offset = - - tree->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + - treeInfo->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + sp_adj /* adjust for stack in outer frame inner tree can't see */ - + inner->nativeStackBase; /* plus the inner tree's stack base */ + + ti->nativeStackBase; /* plus the inner tree's stack base */ /* We have enough space, so adjust sp and rp to their new level. */ lir->insStorei(inner_sp_ins = lir->ins2(LIR_piadd, lirbuf->sp, INS_CONSTWORD(sp_offset)), lirbuf->state, offsetof(InterpState, sp)); @@ -5011,11 +4982,11 @@ BuildGlobalTypeMapFromInnerTree(Queue& typeMap, VMSideExit* inner) typeMap.add(inner->globalTypeMap(), inner->numGlobalSlots); /* Add missing global types from the innermost exit's tree. */ - TreeFragment* innerFrag = inner->root(); + TreeInfo* innerTree = inner->root()->treeInfo; unsigned slots = inner->numGlobalSlots; - if (slots < innerFrag->nGlobalTypes()) { - typeMap.add(innerFrag->globalTypeMap() + slots, innerFrag->nGlobalTypes() - slots); - slots = innerFrag->nGlobalTypes(); + if (slots < innerTree->nGlobalTypes()) { + typeMap.add(innerTree->globalTypeMap() + slots, innerTree->nGlobalTypes() - slots); + slots = innerTree->nGlobalTypes(); } JS_ASSERT(typeMap.length() - initialSlots == slots); return slots; @@ -5102,7 +5073,8 @@ TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit, LIns* inner_s fullMap.add(exit->stackTypeMap(), exit->numStackSlots); BuildGlobalTypeMapFromInnerTree(fullMap, exit); - import(inner, inner_sp_ins, exit->numStackSlots, fullMap.length() - exit->numStackSlots, + TreeInfo* ti = inner->treeInfo; + import(ti, inner_sp_ins, exit->numStackSlots, fullMap.length() - exit->numStackSlots, exit->calldepth, fullMap.data()); /* Restore sp and rp to their original values (we still have them in a register). */ @@ -5122,8 +5094,8 @@ TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit, LIns* inner_s (void*)nestedExit, (void*)exit); /* Register us as a dependent tree of the inner tree. */ - inner->dependentTrees.addUnique(fragment->root); - tree->linkedTrees.addUnique(inner); + inner->treeInfo->dependentTrees.addUnique(fragment->root); + treeInfo->linkedTrees.addUnique(inner); } /* Add a if/if-else control-flow merge point to the list of known merge points. */ @@ -5317,6 +5289,7 @@ CheckGlobalObjectShape(JSContext* cx, JSTraceMonitor* tm, JSObject* globalObj, if (tm->recorder) { TreeFragment* root = tm->recorder->getFragment()->root; + TreeInfo* ti = tm->recorder->getTreeInfo(); /* Check the global shape matches the recorder's treeinfo's shape. */ if (globalObj != root->globalObj || globalShape != root->globalShape) { @@ -5332,7 +5305,7 @@ CheckGlobalObjectShape(JSContext* cx, JSTraceMonitor* tm, JSObject* globalObj, if (shape) *shape = globalShape; if (slots) - *slots = root->globalSlots; + *slots = ti->globalSlots; return true; } @@ -5371,7 +5344,7 @@ CheckGlobalObjectShape(JSContext* cx, JSTraceMonitor* tm, JSObject* globalObj, */ bool JS_REQUIRES_STACK TraceRecorder::startRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* f, - unsigned stackSlots, unsigned ngslots, + TreeInfo* ti, unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap, VMSideExit* expectedInnerExit, jsbytecode* outer, uint32 outerArgc, RecordReason recordReason) { @@ -5379,8 +5352,9 @@ TraceRecorder::startRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* f, JS_ASSERT(!tm->needFlush); JS_ASSERT_IF(cx->fp->imacpc, f->root != f); - tm->recorder = new TraceRecorder(cx, anchor, f, stackSlots, ngslots, typeMap, - expectedInnerExit, outer, outerArgc, recordReason); + tm->recorder = new TraceRecorder(cx, anchor, f, ti, stackSlots, + ngslots, typeMap, expectedInnerExit, + outer, outerArgc, recordReason); if (!tm->recorder || tm->outOfMemory() || js_OverfullJITCache(tm)) { ResetJIT(cx, FR_OOM); @@ -5404,6 +5378,7 @@ TraceRecorder::startRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* f, static void TrashTree(JSContext* cx, TreeFragment* f) { + JS_ASSERT((!f->code()) == (!f->treeInfo)); JS_ASSERT(f == f->root); debug_only_printf(LC_TMTreeVis, "TREEVIS TRASH FRAG=%p\n", (void*)f); @@ -5411,13 +5386,15 @@ TrashTree(JSContext* cx, TreeFragment* f) return; AUDIT(treesTrashed); debug_only_print0(LC_TMTracer, "Trashing tree info.\n"); + TreeInfo* ti = f->treeInfo; + f->treeInfo = NULL; f->setCode(NULL); - TreeFragment** data = f->dependentTrees.data(); - unsigned length = f->dependentTrees.length(); + TreeFragment** data = ti->dependentTrees.data(); + unsigned length = ti->dependentTrees.length(); for (unsigned n = 0; n < length; ++n) TrashTree(cx, data[n]); - data = f->linkedTrees.data(); - length = f->linkedTrees.length(); + data = ti->linkedTrees.data(); + length = ti->linkedTrees.length(); for (unsigned n = 0; n < length; ++n) TrashTree(cx, data[n]); } @@ -5619,6 +5596,53 @@ SynthesizeSlowNativeFrame(InterpState& state, JSContext *cx, VMSideExit *exit) cx->fp = fp; } +/* + * Create a TreeInfo in preparation for starting a recorder. If one cannot be + * allocated, reset the JIT and return NULL. + */ +static JS_REQUIRES_STACK TreeInfo* +CreateTreeInfo(JSContext* cx, TreeFragment* f, JSObject* globalObj, SlotList* globalSlots) +{ + JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx); + + /* Set up the VM-private treeInfo structure for this fragment. */ + TreeInfo* ti = new (*tm->traceAlloc) TreeInfo(tm->dataAlloc, f, globalSlots); + + /* Capture the coerced type of each active slot in the type map. */ + ti->typeMap.captureTypes(cx, globalObj, *globalSlots, 0 /* callDepth */); + ti->nStackTypes = ti->typeMap.length() - globalSlots->length(); + +#ifdef DEBUG + AssertTreeIsUnique(tm, f, ti); + ti->treeFileName = cx->fp->script->filename; + ti->treeLineNumber = js_FramePCToLineNumber(cx, cx->fp); + ti->treePCOffset = FramePCOffset(cx->fp); +#endif +#ifdef JS_JIT_SPEW + debug_only_printf(LC_TMTreeVis, "TREEVIS CREATETREE ROOT=%p PC=%p FILE=\"%s\" LINE=%d OFFS=%d", + (void*)f, f->ip, ti->treeFileName, ti->treeLineNumber, + FramePCOffset(cx->fp)); + debug_only_print0(LC_TMTreeVis, " STACK=\""); + for (unsigned i = 0; i < ti->nStackTypes; i++) + debug_only_printf(LC_TMTreeVis, "%c", typeChar[ti->typeMap[i]]); + debug_only_print0(LC_TMTreeVis, "\" GLOBALS=\""); + for (unsigned i = 0; i < ti->nGlobalTypes(); i++) + debug_only_printf(LC_TMTreeVis, "%c", typeChar[ti->typeMap[ti->nStackTypes + i]]); + debug_only_print0(LC_TMTreeVis, "\"\n"); +#endif + + /* Determine the native frame layout at the entry point. */ + unsigned entryNativeStackSlots = ti->nStackTypes; + JS_ASSERT(entryNativeStackSlots == NativeStackSlots(cx, 0 /* callDepth */)); + ti->nativeStackBase = (entryNativeStackSlots - + (cx->fp->regs->sp - StackBase(cx->fp))) * sizeof(double); + ti->maxNativeStackSlots = entryNativeStackSlots; + ti->maxCallDepth = 0; + ti->script = cx->fp->script; + + return ti; +} + static JS_REQUIRES_STACK bool RecordTree(JSContext* cx, JSTraceMonitor* tm, TreeFragment* peer, jsbytecode* outer, uint32 outerArgc, JSObject* globalObj, uint32 globalShape, @@ -5651,30 +5675,17 @@ RecordTree(JSContext* cx, JSTraceMonitor* tm, TreeFragment* peer, jsbytecode* ou return false; } - JS_ASSERT(!f->code()); + JS_ASSERT(!f->code() && !f->treeInfo); - f->initialize(cx, globalSlots); + TreeInfo* ti = CreateTreeInfo(cx, f, globalObj, globalSlots); + if (!ti) + return false; -#ifdef DEBUG - AssertTreeIsUnique(tm, f); -#endif -#ifdef JS_JIT_SPEW - debug_only_printf(LC_TMTreeVis, "TREEVIS CREATETREE ROOT=%p PC=%p FILE=\"%s\" LINE=%d OFFS=%d", - (void*)f, f->ip, f->treeFileName, f->treeLineNumber, - FramePCOffset(cx->fp)); - debug_only_print0(LC_TMTreeVis, " STACK=\""); - for (unsigned i = 0; i < f->nStackTypes; i++) - debug_only_printf(LC_TMTreeVis, "%c", typeChar[f->typeMap[i]]); - debug_only_print0(LC_TMTreeVis, "\" GLOBALS=\""); - for (unsigned i = 0; i < f->nGlobalTypes(); i++) - debug_only_printf(LC_TMTreeVis, "%c", typeChar[f->typeMap[f->nStackTypes + i]]); - debug_only_print0(LC_TMTreeVis, "\"\n"); -#endif - /* Recording primary trace. */ - return TraceRecorder::startRecorder(cx, NULL, f, f->nStackTypes, - f->globalSlots->length(), - f->typeMap.data(), NULL, + return TraceRecorder::startRecorder(cx, NULL, f, ti, + ti->nStackTypes, + ti->globalSlots->length(), + ti->typeMap.data(), NULL, outer, outerArgc, reason); } @@ -5682,15 +5693,16 @@ static JS_REQUIRES_STACK TypeConsensus FindLoopEdgeTarget(JSContext* cx, VMSideExit* exit, TreeFragment** peerp) { TreeFragment* from = exit->root(); + TreeInfo* from_ti = from->treeInfo; JS_ASSERT(from->code()); TypeMap typeMap(NULL); FullMapFromExit(typeMap, exit); - JS_ASSERT(typeMap.length() - exit->numStackSlots == from->nGlobalTypes()); + JS_ASSERT(typeMap.length() - exit->numStackSlots == from_ti->nGlobalTypes()); /* Mark all double slots as undemotable */ - uint16* gslots = from->globalSlots->data(); + uint16* gslots = from_ti->globalSlots->data(); for (unsigned i = 0; i < typeMap.length(); i++) { if (typeMap[i] == TT_DOUBLE) { if (exit->exitType == RECURSIVE_UNLINKED_EXIT) { @@ -5699,7 +5711,7 @@ FindLoopEdgeTarget(JSContext* cx, VMSideExit* exit, TreeFragment** peerp) else oracle.markGlobalSlotUndemotable(cx, gslots[i - exit->numStackSlots]); } - if (i < from->nStackTypes) + if (i < from_ti->nStackTypes) oracle.markStackSlotUndemotable(cx, i, from->ip); else if (i >= exit->numStackSlots) oracle.markGlobalSlotUndemotable(cx, gslots[i - exit->numStackSlots]); @@ -5718,10 +5730,11 @@ FindLoopEdgeTarget(JSContext* cx, VMSideExit* exit, TreeFragment** peerp) } for (TreeFragment* peer = firstPeer; peer; peer = peer->peer) { - if (!peer->code()) + TreeInfo* peer_ti = peer->treeInfo; + if (!peer_ti) continue; JS_ASSERT(peer->argc == from->argc); - JS_ASSERT(exit->numStackSlots == peer->nStackTypes); + JS_ASSERT(exit->numStackSlots == peer_ti->nStackTypes); TypeConsensus consensus = TypeMapLinkability(cx, typeMap, peer); if (consensus == TypeConsensus_Okay || consensus == TypeConsensus_Undemotes) { *peerp = peer; @@ -5732,6 +5745,22 @@ FindLoopEdgeTarget(JSContext* cx, VMSideExit* exit, TreeFragment** peerp) return TypeConsensus_Bad; } +UnstableExit* +TreeInfo::removeUnstableExit(VMSideExit* exit) +{ + /* Now erase this exit from the unstable exit list. */ + UnstableExit** tail = &this->unstableExits; + for (UnstableExit* uexit = this->unstableExits; uexit != NULL; uexit = uexit->next) { + if (uexit->exit == exit) { + *tail = uexit->next; + return *tail; + } + tail = &uexit->next; + } + JS_NOT_REACHED("exit not in unstable exit list"); + return NULL; +} + static JS_REQUIRES_STACK bool AttemptToStabilizeTree(JSContext* cx, JSObject* globalObj, VMSideExit* exit, jsbytecode* outer, uint32 outerArgc) @@ -5743,27 +5772,29 @@ AttemptToStabilizeTree(JSContext* cx, JSObject* globalObj, VMSideExit* exit, jsb } TreeFragment* from = exit->root(); + TreeInfo* from_ti = from->treeInfo; TreeFragment* peer = NULL; TypeConsensus consensus = FindLoopEdgeTarget(cx, exit, &peer); if (consensus == TypeConsensus_Okay) { - JS_ASSERT(from->globalSlots == peer->globalSlots); + TreeInfo* peer_ti = peer->treeInfo; + JS_ASSERT(from_ti->globalSlots == peer_ti->globalSlots); JS_ASSERT_IF(exit->exitType == UNSTABLE_LOOP_EXIT, - from->nStackTypes == peer->nStackTypes); - JS_ASSERT(exit->numStackSlots == peer->nStackTypes); + from_ti->nStackTypes == peer_ti->nStackTypes); + JS_ASSERT(exit->numStackSlots == peer_ti->nStackTypes); /* Patch this exit to its peer */ JoinPeers(tm->assembler, exit, peer); /* * Update peer global types. The |from| fragment should already be updated because it on * the execution path, and somehow connected to the entry trace. */ - if (peer->nGlobalTypes() < peer->globalSlots->length()) - SpecializeTreesToMissingGlobals(cx, globalObj, peer); - JS_ASSERT(from->nGlobalTypes() == from->globalSlots->length()); + if (peer_ti->nGlobalTypes() < peer_ti->globalSlots->length()) + SpecializeTreesToMissingGlobals(cx, globalObj, peer_ti); + JS_ASSERT(from_ti->nGlobalTypes() == from_ti->globalSlots->length()); /* This exit is no longer unstable, so remove it. */ if (exit->exitType == UNSTABLE_LOOP_EXIT) - from->removeUnstableExit(exit); - debug_only_stmt(DumpPeerStability(tm, peer->ip, globalObj, from->globalShape, from->argc);) + from_ti->removeUnstableExit(exit); + debug_only_stmt(DumpPeerStability(tm, peer->ip, from->globalObj, from->globalShape, from->argc);) return false; } else if (consensus == TypeConsensus_Undemotes) { /* The original tree is unconnectable, so trash it. */ @@ -5771,9 +5802,6 @@ AttemptToStabilizeTree(JSContext* cx, JSObject* globalObj, VMSideExit* exit, jsb return false; } - uint32 globalShape = from->globalShape; - SlotList *globalSlots = from->globalSlots; - /* Don't bother recording if the exit doesn't expect this PC */ if (exit->exitType == RECURSIVE_UNLINKED_EXIT) { if (++exit->hitcount >= MAX_RECURSIVE_UNLINK_HITS) { @@ -5783,7 +5811,7 @@ AttemptToStabilizeTree(JSContext* cx, JSObject* globalObj, VMSideExit* exit, jsb } if (exit->recursive_pc != cx->fp->regs->pc) return false; - from = LookupLoop(tm, exit->recursive_pc, globalObj, globalShape, cx->fp->argc); + from = LookupLoop(tm, exit->recursive_pc, from->globalObj, from->globalShape, cx->fp->argc); if (!from) return false; /* use stale TI for RecordTree - since from might not have one anymore. */ @@ -5795,8 +5823,8 @@ AttemptToStabilizeTree(JSContext* cx, JSObject* globalObj, VMSideExit* exit, jsb if (*(jsbytecode*)from->ip == JSOP_NOP) return false; - return RecordTree(cx, tm, from->first, outer, outerArgc, globalObj, - globalShape, globalSlots, cx->fp->argc, + return RecordTree(cx, tm, from->first, outer, outerArgc, from->globalObj, + from->globalShape, from_ti->globalSlots, cx->fp->argc, Record_Branch); } @@ -5844,7 +5872,7 @@ AttemptToExtendTree(JSContext* cx, VMSideExit* anchor, VMSideExit* exitedFrom, j } TreeFragment* f = anchor->root(); - JS_ASSERT(f->code()); + JS_ASSERT(f->treeInfo); /* * Don't grow trees above a certain size to avoid code explosion due to @@ -5908,8 +5936,9 @@ AttemptToExtendTree(JSContext* cx, VMSideExit* anchor, VMSideExit* exitedFrom, j typeMap = fullMap.data(); } JS_ASSERT(ngslots >= anchor->numGlobalSlots); - bool rv = TraceRecorder::startRecorder(cx, anchor, c, stackSlots, ngslots, typeMap, - exitedFrom, outer, cx->fp->argc, Record_Branch); + bool rv = TraceRecorder::startRecorder(cx, anchor, c, f->treeInfo, + stackSlots, ngslots, typeMap, exitedFrom, + outer, cx->fp->argc, Record_Branch); #ifdef MOZ_TRACEVIS if (!rv && tvso) tvso->r = R_FAIL_EXTEND_START; @@ -5998,13 +6027,13 @@ TraceRecorder::attemptTreeCall(TreeFragment* f, uintN& inlineCallCount) * In the interim, just do tree calls knowing that they won't go into * recursive trees that can pop parent frames. */ - if (f->script == cx->fp->script) { - if (f->recursion >= Recursion_Unwinds) { + if (f->treeInfo->script == cx->fp->script) { + if (f->treeInfo->recursion >= Recursion_Unwinds) { Blacklist(cx->fp->script->code); js_AbortRecording(cx, "Inner tree is an unsupported type of recursion"); return ARECORD_ABORTED; } else { - f->recursion = Recursion_Disallowed; + f->treeInfo->recursion = Recursion_Disallowed; } } @@ -6199,16 +6228,19 @@ TraceRecorder::findNestedCompatiblePeer(TreeFragment* f) JSTraceMonitor* tm; tm = &JS_TRACE_MONITOR(cx); - unsigned int ngslots = tree->globalSlots->length(); + unsigned int ngslots = treeInfo->globalSlots->length(); + TreeInfo* ti; for (; f != NULL; f = f->peer) { if (!f->code()) continue; + ti = f->treeInfo; + debug_only_printf(LC_TMTracer, "checking nested types %p: ", (void*)f); - if (ngslots > f->nGlobalTypes()) - SpecializeTreesToMissingGlobals(cx, globalObj, f); + if (ngslots > ti->nGlobalTypes()) + SpecializeTreesToMissingGlobals(cx, globalObj, ti); /* * Determine whether the typemap of the inner tree matches the outer @@ -6219,8 +6251,8 @@ TraceRecorder::findNestedCompatiblePeer(TreeFragment* f) * expects a double, but the outer tree has an integer, we can proceed, * but we mark the location undemotable. */ - TypeCompatibilityVisitor visitor(*this, f->typeMap.data()); - VisitSlots(visitor, cx, 0, *tree->globalSlots); + TypeCompatibilityVisitor visitor(*this, ti->typeMap.data()); + VisitSlots(visitor, cx, 0, *treeInfo->globalSlots); debug_only_printf(LC_TMTracer, " %s\n", visitor.isOk() ? "match" : ""); if (visitor.isOk()) @@ -6271,25 +6303,25 @@ public: * Check if types are usable for trace execution. * * @param cx Context. - * @param f Tree of peer we're testing. + * @param ti Tree info of peer we're testing. * @return True if compatible (with or without demotions), false otherwise. */ static JS_REQUIRES_STACK bool -CheckEntryTypes(JSContext* cx, JSObject* globalObj, TreeFragment* f) +CheckEntryTypes(JSContext* cx, JSObject* globalObj, TreeInfo* ti) { - unsigned int ngslots = f->globalSlots->length(); + unsigned int ngslots = ti->globalSlots->length(); - JS_ASSERT(f->nStackTypes == NativeStackSlots(cx, 0)); + JS_ASSERT(ti->nStackTypes == NativeStackSlots(cx, 0)); - if (ngslots > f->nGlobalTypes()) - SpecializeTreesToMissingGlobals(cx, globalObj, f); + if (ngslots > ti->nGlobalTypes()) + SpecializeTreesToMissingGlobals(cx, globalObj, ti); - JS_ASSERT(f->typeMap.length() == NativeStackSlots(cx, 0) + ngslots); - JS_ASSERT(f->typeMap.length() == f->nStackTypes + ngslots); - JS_ASSERT(f->nGlobalTypes() == ngslots); + JS_ASSERT(ti->typeMap.length() == NativeStackSlots(cx, 0) + ngslots); + JS_ASSERT(ti->typeMap.length() == ti->nStackTypes + ngslots); + JS_ASSERT(ti->nGlobalTypes() == ngslots); - CheckEntryTypeVisitor visitor(f->typeMap.data()); - VisitSlots(visitor, cx, 0, *f->globalSlots); + CheckEntryTypeVisitor visitor(ti->typeMap.data()); + VisitSlots(visitor, cx, 0, *ti->globalSlots); debug_only_print0(LC_TMTracer, "\n"); return visitor.isOk(); @@ -6309,11 +6341,11 @@ FindVMCompatiblePeer(JSContext* cx, JSObject* globalObj, TreeFragment* f, uintN& { count = 0; for (; f != NULL; f = f->peer) { - if (!f->code()) + if (!f->treeInfo) continue; debug_only_printf(LC_TMTracer, "checking vm types %p (ip: %p): ", (void*)f, f->ip); - if (CheckEntryTypes(cx, globalObj, f)) + if (CheckEntryTypes(cx, globalObj, f->treeInfo)) return f; ++count; } @@ -6327,11 +6359,11 @@ FindVMCompatiblePeer(JSContext* cx, JSObject* globalObj, TreeFragment* f, uintN& * |deepBailSp| in js_DeepBail. */ JS_ALWAYS_INLINE -InterpState::InterpState(JSContext* cx, JSTraceMonitor* tm, TreeFragment* f, +InterpState::InterpState(JSContext* cx, JSTraceMonitor* tm, TreeInfo* ti, uintN& inlineCallCount, VMSideExit** innermostNestedGuardp) : cx(cx), stackBase(tm->storage.stack()), - sp(stackBase + f->nativeStackBase / sizeof(double)), + sp(stackBase + ti->nativeStackBase / sizeof(double)), eos(tm->storage.global()), callstackBase(tm->storage.callstack()), sor(callstackBase), @@ -6341,7 +6373,7 @@ InterpState::InterpState(JSContext* cx, JSTraceMonitor* tm, TreeFragment* f, lastTreeExitGuard(NULL), lastTreeCallGuard(NULL), rpAtLastTreeCall(NULL), - outermostTree(f), + outermostTree(ti), inlineCallCountp(&inlineCallCount), innermostNestedGuardp(innermostNestedGuardp), #ifdef EXECUTE_TREE_TIMER @@ -6403,9 +6435,10 @@ ExecuteTrace(JSContext* cx, Fragment* f, InterpState& state) /* Check whether our assumptions about the incoming scope-chain are upheld. */ static JS_REQUIRES_STACK JS_ALWAYS_INLINE bool -ScopeChainCheck(JSContext* cx, TreeFragment* f) +ScopeChainCheck(JSContext* cx, TreeInfo* ti, TreeFragment* f) { - JS_ASSERT(f->globalObj == JS_GetGlobalForObject(cx, cx->fp->scopeChain)); + JS_ASSERT(ti->globalObj() == f->globalObj); + JS_ASSERT(ti->globalObj() == JS_GetGlobalForObject(cx, cx->fp->scopeChain)); /* * The JIT records and expects to execute with two scope-chain @@ -6442,8 +6475,8 @@ ScopeChainCheck(JSContext* cx, TreeFragment* f) /* Make sure the global object is sane. */ JS_ASSERT(STOBJ_NSLOTS(f->globalObj) <= MAX_GLOBAL_SLOTS); - JS_ASSERT(f->nGlobalTypes() == f->globalSlots->length()); - JS_ASSERT_IF(f->globalSlots->length() != 0, + JS_ASSERT(ti->nGlobalTypes() == ti->globalSlots->length()); + JS_ASSERT_IF(ti->globalSlots->length() != 0, OBJ_SHAPE(f->globalObj) == f->globalShape); return true; } @@ -6458,22 +6491,23 @@ ExecuteTree(JSContext* cx, TreeFragment* f, uintN& inlineCallCount, #ifdef MOZ_TRACEVIS TraceVisStateObj tvso(cx, S_EXECUTE); #endif - JS_ASSERT(f->root == f && f->code()); + JS_ASSERT(f->root == f && f->code() && f->treeInfo); JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx); + TreeInfo* ti = f->treeInfo; - if (!ScopeChainCheck(cx, f)) + if (!ScopeChainCheck(cx, ti, f)) return NULL; /* Initialize trace state. */ - InterpState state(cx, tm, f, inlineCallCount, innermostNestedGuardp); + InterpState state(cx, tm, ti, inlineCallCount, innermostNestedGuardp); double* stack = tm->storage.stack(); double* global = tm->storage.global(); JSObject* globalObj = f->globalObj; - unsigned ngslots = f->globalSlots->length(); - uint16* gslots = f->globalSlots->data(); + unsigned ngslots = ti->globalSlots->length(); + uint16* gslots = ti->globalSlots->data(); BuildNativeFrame(cx, globalObj, 0 /* callDepth */, ngslots, gslots, - f->typeMap.data(), global, stack); + ti->typeMap.data(), global, stack); AUDIT(traceTriggered); debug_only_printf(LC_TMTracer, @@ -6481,7 +6515,7 @@ ExecuteTree(JSContext* cx, TreeFragment* f, uintN& inlineCallCount, cx->fp->script->filename, js_FramePCToLineNumber(cx, cx->fp), FramePCOffset(cx->fp), - f->maxNativeStackSlots, + ti->maxNativeStackSlots, f->code()); debug_only_stmt(uint32 globalSlots = STOBJ_NSLOTS(globalObj);) @@ -6794,7 +6828,7 @@ LeaveTree(InterpState& state, VMSideExit* lr) * type-map. See also the comment in the constructor of TraceRecorder * regarding why this is always safe to do. */ - TreeFragment* outermostTree = state.outermostTree; + TreeInfo* outermostTree = state.outermostTree; uint16* gslots = outermostTree->globalSlots->data(); unsigned ngslots = outermostTree->globalSlots->length(); JS_ASSERT(ngslots == outermostTree->nGlobalTypes()); @@ -6813,8 +6847,8 @@ LeaveTree(InterpState& state, VMSideExit* lr) * is lazily added into a tree, all dependent and linked trees are * immediately specialized (see bug 476653). */ - JS_ASSERT(innermost->root()->nGlobalTypes() == ngslots); - JS_ASSERT(innermost->root()->nGlobalTypes() > innermost->numGlobalSlots); + JS_ASSERT(innermost->root()->treeInfo->nGlobalTypes() == ngslots); + JS_ASSERT(innermost->root()->treeInfo->nGlobalTypes() > innermost->numGlobalSlots); typeMap.ensure(ngslots); #ifdef DEBUG unsigned check_ngslots = @@ -6840,7 +6874,7 @@ LeaveTree(InterpState& state, VMSideExit* lr) /* Write back interned globals. */ JS_ASSERT(state.eos == state.stackBase + MAX_NATIVE_STACK_SLOTS); - JSObject* globalObj = outermostTree->globalObj; + JSObject* globalObj = outermostTree->globalObj(); FlushNativeGlobalFrame(cx, globalObj, state.eos, ngslots, gslots, globalTypeMap); #ifdef DEBUG /* Verify that our state restoration worked. */ @@ -6975,7 +7009,7 @@ js_MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount, RecordReason reason) * most time will be spent entering and exiting ExecuteTree(). There's no * benefit to doing this until the down-recursive side completes. */ - if (match->recursion == Recursion_Unwinds) + if (match->treeInfo->recursion == Recursion_Unwinds) return false; VMSideExit* lr = NULL; @@ -9725,10 +9759,10 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) * concerned about. That should pass through below to not regress pre-recursion * functionality. */ - if (IsTraceableRecursion(cx) && tree->script == cx->fp->script) { - if (tree->recursion == Recursion_Disallowed) + if (IsTraceableRecursion(cx) && treeInfo->script == cx->fp->script) { + if (treeInfo->recursion == Recursion_Disallowed) RETURN_STOP_A("recursion not allowed in this tree"); - if (tree->script != cx->fp->script) + if (treeInfo->script != cx->fp->script) RETURN_STOP_A("recursion does not match original tree"); return InjectStatus(downRecursion()); } @@ -9752,14 +9786,14 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) * recursive. */ for (f = first; f; f = f->peer) { - if (f->code() && f->recursion == Recursion_Detected) { + if (f->treeInfo && f->treeInfo->recursion == Recursion_Detected) { /* Since this recorder is about to die, save its values. */ if (++first->hits() <= HOTLOOP) return ARECORD_STOP; if (IsBlacklisted((jsbytecode*)f->ip)) RETURN_STOP_A("inner recursive tree is blacklisted"); JSContext* _cx = cx; - SlotList* globalSlots = tree->globalSlots; + SlotList* globalSlots = treeInfo->globalSlots; JSTraceMonitor* tm = traceMonitor; js_AbortRecording(cx, "trying to compile inner recursive tree"); if (RecordTree(_cx, tm, first, NULL, 0, first->globalObj, first->globalShape, @@ -9848,8 +9882,8 @@ TraceRecorder::record_JSOP_RETURN() { /* A return from callDepth 0 terminates the current loop, except for recursion. */ if (callDepth == 0) { - if (IsTraceableRecursion(cx) && tree->recursion != Recursion_Disallowed && - tree->script == cx->fp->script) { + if (IsTraceableRecursion(cx) && treeInfo->recursion != Recursion_Disallowed && + treeInfo->script == cx->fp->script) { return InjectStatus(upRecursion()); } else { AUDIT(returnLoopExits); @@ -10489,7 +10523,7 @@ TraceRecorder::emitNativeCall(JSSpecializedNative* sn, uintN argc, LIns* args[], JSObject* funobj = JSVAL_TO_OBJECT(stackval(0 - (2 + argc))); if (FUN_SLOW_NATIVE(GET_FUNCTION_PRIVATE(cx, funobj))) { exit->setNativeCallee(funobj, constructing); - tree->gcthings.addUnique(OBJECT_TO_JSVAL(funobj)); + treeInfo->gcthings.addUnique(OBJECT_TO_JSVAL(funobj)); } } @@ -12042,7 +12076,7 @@ TraceRecorder::guardCallee(jsval& callee) JSObject* callee_obj = JSVAL_TO_OBJECT(callee); LIns* callee_ins = get(&callee); - tree->gcthings.addUnique(callee); + treeInfo->gcthings.addUnique(callee); guard(true, lir->ins2(LIR_peq, stobj_get_private(callee_ins), @@ -12119,10 +12153,10 @@ TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc, JS_ASSERT(argc < FrameInfo::CONSTRUCTING_FLAG); - tree->gcthings.addUnique(fval); + treeInfo->gcthings.addUnique(fval); fi->block = fp->blockChain; if (fp->blockChain) - tree->gcthings.addUnique(OBJECT_TO_JSVAL(fp->blockChain)); + treeInfo->gcthings.addUnique(OBJECT_TO_JSVAL(fp->blockChain)); fi->pc = fp->regs->pc; fi->imacpc = fp->imacpc; fi->spdist = fp->regs->sp - fp->slots; @@ -12130,8 +12164,8 @@ TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc, fi->callerHeight = stackSlots - (2 + argc); fi->callerArgc = fp->argc; - if (callDepth >= tree->maxCallDepth) - tree->maxCallDepth = callDepth + 1; + if (callDepth >= treeInfo->maxCallDepth) + treeInfo->maxCallDepth = callDepth + 1; fi = traceMonitor->frameCache->memoize(fi); if (!fi) @@ -14662,22 +14696,24 @@ DumpPeerStability(JSTraceMonitor* tm, const void* ip, JSObject* globalObj, uint3 uint32 argc) { TreeFragment* f; + TreeInfo* ti; bool looped = false; unsigned length = 0; for (f = LookupLoop(tm, ip, globalObj, globalShape, argc); f != NULL; f = f->peer) { - if (!f->code()) + if (!f->treeInfo) continue; debug_only_printf(LC_TMRecorder, "Stability of fragment %p:\nENTRY STACK=", (void*)f); + ti = f->treeInfo; if (looped) - JS_ASSERT(f->nStackTypes == length); - for (unsigned i = 0; i < f->nStackTypes; i++) - debug_only_printf(LC_TMRecorder, "%c", typeChar[f->stackTypeMap()[i]]); + JS_ASSERT(ti->nStackTypes == length); + for (unsigned i = 0; i < ti->nStackTypes; i++) + debug_only_printf(LC_TMRecorder, "%c", typeChar[ti->stackTypeMap()[i]]); debug_only_print0(LC_TMRecorder, " GLOBALS="); - for (unsigned i = 0; i < f->nGlobalTypes(); i++) - debug_only_printf(LC_TMRecorder, "%c", typeChar[f->globalTypeMap()[i]]); + for (unsigned i = 0; i < ti->nGlobalTypes(); i++) + debug_only_printf(LC_TMRecorder, "%c", typeChar[ti->globalTypeMap()[i]]); debug_only_print0(LC_TMRecorder, "\n"); - UnstableExit* uexit = f->unstableExits; + UnstableExit* uexit = ti->unstableExits; while (uexit != NULL) { debug_only_print0(LC_TMRecorder, "EXIT "); JSTraceType* m = uexit->exit->fullTypeMap(); @@ -14692,7 +14728,7 @@ DumpPeerStability(JSTraceMonitor* tm, const void* ip, JSObject* globalObj, uint3 debug_only_print0(LC_TMRecorder, "\n"); uexit = uexit->next; } - length = f->nStackTypes; + length = ti->nStackTypes; looped = true; } } @@ -14784,7 +14820,7 @@ JS_REQUIRES_STACK void TraceRecorder::determineGlobalTypes(JSTraceType* typeMap) { DetermineTypesVisitor detVisitor(*this, typeMap); - VisitGlobalSlots(detVisitor, cx, *tree->globalSlots); + VisitGlobalSlots(detVisitor, cx, *treeInfo->globalSlots); } #include "jsrecursion.cpp" diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 96e8cfaf13f1..285bf71c6591 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -217,6 +217,54 @@ public: TreeFragment* toTreeFragment(); }; +struct LinkableFragment : public VMFragment +{ + LinkableFragment(const void* _ip verbose_only(, uint32_t profFragID)) + : VMFragment(_ip verbose_only(, profFragID)) + { } + + uint32 branchCount; +}; + +/* + * argc is cx->fp->argc at the trace loop header, i.e., the number of arguments + * pushed for the innermost JS frame. This is required as part of the fragment + * key because the fragment will write those arguments back to the interpreter + * stack when it exits, using its typemap, which implicitly incorporates a + * given value of argc. Without this feature, a fragment could be called as an + * inner tree with two different values of argc, and entry type checking or + * exit frame synthesis could crash. + */ +struct TreeFragment : public LinkableFragment +{ + TreeFragment(const void* _ip, JSObject* _globalObj, uint32 _globalShape, uint32 _argc + verbose_only(, uint32_t profFragID)) : + LinkableFragment(_ip verbose_only(, profFragID)), + treeInfo(NULL), + first(NULL), + next(NULL), + peer(NULL), + globalObj(_globalObj), + globalShape(_globalShape), + argc(_argc) + { } + + TreeInfo *treeInfo; + TreeFragment* first; + TreeFragment* next; + TreeFragment* peer; + JSObject* globalObj; + uint32 globalShape; + uint32 argc; +}; + +inline TreeFragment* +VMFragment::toTreeFragment() +{ + JS_ASSERT(root == this); + return static_cast(this); +} + #if defined(JS_JIT_SPEW) || defined(NJ_NO_VARIADIC_MACROS) enum LC_TMBits { @@ -585,6 +633,8 @@ struct REHashFn { } }; +class TreeInfo; + struct FrameInfo { JSObject* block; // caller block chain head jsbytecode* pc; // caller fp->regs->pc @@ -645,71 +695,51 @@ enum RecursionStatus Recursion_Detected /* Tree has down recursion and maybe up recursion. */ }; -struct LinkableFragment : public VMFragment -{ - LinkableFragment(const void* _ip, nanojit::Allocator* alloc - verbose_only(, uint32_t profFragID)) - : VMFragment(_ip verbose_only(, profFragID)), typeMap(alloc), nStackTypes(0) - { } - - uint32 branchCount; +class TreeInfo { +public: + TreeFragment* const rootFragment; + JSScript* script; + unsigned maxNativeStackSlots; + ptrdiff_t nativeStackBase; + unsigned maxCallDepth; TypeMap typeMap; unsigned nStackTypes; SlotList* globalSlots; -}; - -/* - * argc is cx->fp->argc at the trace loop header, i.e., the number of arguments - * pushed for the innermost JS frame. This is required as part of the fragment - * key because the fragment will write those arguments back to the interpreter - * stack when it exits, using its typemap, which implicitly incorporates a - * given value of argc. Without this feature, a fragment could be called as an - * inner tree with two different values of argc, and entry type checking or - * exit frame synthesis could crash. - */ -struct TreeFragment : public LinkableFragment -{ - TreeFragment(const void* _ip, nanojit::Allocator* alloc, JSObject* _globalObj, - uint32 _globalShape, uint32 _argc verbose_only(, uint32_t profFragID)): - LinkableFragment(_ip, alloc verbose_only(, profFragID)), - first(NULL), - next(NULL), - peer(NULL), - globalObj(_globalObj), - globalShape(_globalShape), - argc(_argc), - dependentTrees(alloc), - linkedTrees(alloc), - sideExits(alloc), - gcthings(alloc), - sprops(alloc) - { } - - TreeFragment* first; - TreeFragment* next; - TreeFragment* peer; - JSObject* globalObj; - uint32 globalShape; - uint32 argc; /* Dependent trees must be trashed if this tree dies, and updated on missing global types */ - Queue dependentTrees; + Queue dependentTrees; /* Linked trees must be updated on missing global types, but are not dependent */ - Queue linkedTrees; + Queue linkedTrees; + Queue sideExits; + UnstableExit* unstableExits; + /* All embedded GC things are registered here so the GC can scan them. */ + Queue gcthings; + Queue sprops; #ifdef DEBUG const char* treeFileName; uintN treeLineNumber; uintN treePCOffset; #endif - JSScript* script; RecursionStatus recursion; - UnstableExit* unstableExits; - Queue sideExits; - ptrdiff_t nativeStackBase; - unsigned maxCallDepth; - /* All embedded GC things are registered here so the GC can scan them. */ - Queue gcthings; - Queue sprops; - unsigned maxNativeStackSlots; + + TreeInfo(nanojit::Allocator* alloc, + TreeFragment* fragment, + SlotList* globalSlots) + : rootFragment(fragment), + script(NULL), + maxNativeStackSlots(0), + nativeStackBase(0), + maxCallDepth(0), + typeMap(alloc), + nStackTypes(0), + globalSlots(globalSlots), + dependentTrees(alloc), + linkedTrees(alloc), + sideExits(alloc), + unstableExits(NULL), + gcthings(alloc), + sprops(alloc), + recursion(Recursion_None) + {} inline unsigned nGlobalTypes() { return typeMap.length() - nStackTypes; @@ -720,18 +750,13 @@ struct TreeFragment : public LinkableFragment inline JSTraceType* stackTypeMap() { return typeMap.data(); } + inline JSObject* globalObj() { + return rootFragment->globalObj; + } - void initialize(JSContext* cx, SlotList *globalSlots); UnstableExit* removeUnstableExit(VMSideExit* exit); }; -inline TreeFragment* -VMFragment::toTreeFragment() -{ - JS_ASSERT(root == this); - return static_cast(this); -} - typedef enum JSBuiltinStatus { JSBUILTIN_BAILED = 1, JSBUILTIN_ERROR = 2 @@ -910,8 +935,8 @@ class TraceRecorder /* The Fragment being recorded by this recording session. */ VMFragment* const fragment; - /* The root fragment representing the tree. */ - TreeFragment* const tree; + /* The tree to which this |fragment| will belong when finished. */ + TreeInfo* const treeInfo; /* The reason we started recording. */ RecordReason const recordReason; @@ -1044,7 +1069,7 @@ class TraceRecorder JS_REQUIRES_STACK ptrdiff_t nativespOffset(jsval* p) const; JS_REQUIRES_STACK void import(nanojit::LIns* base, ptrdiff_t offset, jsval* p, JSTraceType t, const char *prefix, uintN index, JSStackFrame *fp); - JS_REQUIRES_STACK void import(TreeFragment* tree, nanojit::LIns* sp, unsigned stackSlots, + JS_REQUIRES_STACK void import(TreeInfo* treeInfo, nanojit::LIns* sp, unsigned stackSlots, unsigned callDepth, unsigned ngslots, JSTraceType* typeMap); void trackNativeStackUse(unsigned slots); @@ -1340,7 +1365,7 @@ class TraceRecorder inline void operator delete(void *p) { free(p); } JS_REQUIRES_STACK - TraceRecorder(JSContext* cx, VMSideExit*, VMFragment*, + TraceRecorder(JSContext* cx, VMSideExit*, VMFragment*, TreeInfo*, unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap, VMSideExit* expectedInnerExit, jsbytecode* outerTree, uint32 outerArgc, RecordReason reason); @@ -1367,14 +1392,14 @@ class TraceRecorder public: static bool JS_REQUIRES_STACK - startRecorder(JSContext*, VMSideExit*, VMFragment*, + startRecorder(JSContext*, VMSideExit*, VMFragment*, TreeInfo*, unsigned stackSlots, unsigned ngslots, JSTraceType* typeMap, VMSideExit* expectedInnerExit, jsbytecode* outerTree, uint32 outerArgc, RecordReason reason); /* Accessors. */ VMFragment* getFragment() const { return fragment; } - TreeFragment* getTree() const { return tree; } + TreeInfo* getTreeInfo() const { return treeInfo; } bool outOfMemory() const { return traceMonitor->outOfMemory(); } /* Entry points / callbacks from the interpreter. */ From 71c721069fadecc46652866bd56d3a6eb7ead9d1 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Wed, 2 Dec 2009 19:22:34 +0300 Subject: [PATCH 008/179] bug 531682 - fixing eval(source, scope) to match 191, 192 semantics. r=mrbkap --- js/src/jsobj.cpp | 4 ++- js/src/tests/js1_4/Eval/regress-531682.js | 35 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 js/src/tests/js1_4/Eval/regress-531682.js diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 05c1463d5c49..0050f28add76 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1404,7 +1404,9 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) * with object to maintain invariants in the engine (see bug 520164). */ if (scopeobj->getParent()) { - withObject = js_NewWithObject(cx, scopeobj, scopeobj->getParent(), 0); + withObject = js_NewWithObject(cx, scopeobj, + JS_GetGlobalForObject(cx, scopeobj), + 0); if (!withObject) { ok = JS_FALSE; goto out; diff --git a/js/src/tests/js1_4/Eval/regress-531682.js b/js/src/tests/js1_4/Eval/regress-531682.js new file mode 100644 index 000000000000..25f5778807a8 --- /dev/null +++ b/js/src/tests/js1_4/Eval/regress-531682.js @@ -0,0 +1,35 @@ +/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'regress-531682.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 531682; +var summary = 'Checking proper wrapping of scope in eval(source, scope)'; +var actual; +var expect; + +//----------------------------------------------------------------------------- +var x = 0; + +test(); +//----------------------------------------------------------------------------- + +function scope1() { + eval('var x = 1;'); + return function() { return x; } +} + +function test() { + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + // The scope chain in eval should be just scope1() and the global object. + actual = eval('x', scope1()); + expect = 0; + reportCompare(expect, actual, summary); + exitFunc ('test'); +} From add6ceee8c77a419412c3582fc7ae7476e0f7b59 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Wed, 2 Dec 2009 09:54:51 -0800 Subject: [PATCH 009/179] Bug 532041: Test that duplicate argument checks use JSFunction::u.i.names correctly. r=sayrer --- js/src/tests/ecma_5/strict/jstests.list | 1 + js/src/tests/ecma_5/strict/regress-532041.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 js/src/tests/ecma_5/strict/regress-532041.js diff --git a/js/src/tests/ecma_5/strict/jstests.list b/js/src/tests/ecma_5/strict/jstests.list index 280f921b334f..908959927bf9 100644 --- a/js/src/tests/ecma_5/strict/jstests.list +++ b/js/src/tests/ecma_5/strict/jstests.list @@ -15,3 +15,4 @@ script 12.14.1.js script 13.1.js script B.1.1.js script B.1.2.js +script regress-532041.js diff --git a/js/src/tests/ecma_5/strict/regress-532041.js b/js/src/tests/ecma_5/strict/regress-532041.js new file mode 100644 index 000000000000..684686d929dd --- /dev/null +++ b/js/src/tests/ecma_5/strict/regress-532041.js @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + + +/* + * JSFunction::findDuplicateFormal (nee js_FindDuplicateFormal), used + * by strict checks, sometimes failed to choose the correct branch of + * the fun->u.i.names union: it used the argument count, not the + * overall name count. + */ +function f(a1,a2,a3,a4,a5) { "use strict"; var v1, v2, v3, v4, v5, v6, v7; } From d559284d274bdbb303378b3a1f7b5a9098c3694d Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Wed, 2 Dec 2009 15:13:14 -0800 Subject: [PATCH 010/179] Bug 531972: Add parent dir jstests.list entries; call reportCompare as needed; fix anonymous function objects in js/src/tests/ecma_5/strict/13.1.js. r=bclary, r=mrbkap While prior patches created new test directories js/src/tests/ecma_5/strict and js/src/tests/js1_8_1/strict, they failed to add jstests.list entries to their parent directories. This adds them. The strict tests generally were written to use assertEq, which is simple and gives nice source positions in failure messages under the JS shell. However, the jsreftests require each test file to call reportCompare at least once. This adds a dummy call to reportCompare to each file. It would be nice to make everything work in both environments, perhaps using arguments.caller. The test script js/src/tests/ecma_5/strict/13.1.js tried parsing statements of the form 'function(x,x){}'. However, anonymous function expressions are not allowed in a statement context when JSOPTION_ANONFUNFIX is set. This is set under the browser, but clear in the shell; bug 532233 suggests that the two be reconciled. --- js/src/tests/ecma_5/jstests.list | 1 + js/src/tests/ecma_5/strict/10.4.2.js | 2 ++ js/src/tests/ecma_5/strict/11.1.5.js | 2 ++ js/src/tests/ecma_5/strict/11.13.1.js | 2 ++ js/src/tests/ecma_5/strict/11.13.2.js | 2 ++ js/src/tests/ecma_5/strict/11.3.1.js | 2 ++ js/src/tests/ecma_5/strict/11.3.2.js | 2 ++ js/src/tests/ecma_5/strict/11.4.1.js | 2 ++ js/src/tests/ecma_5/strict/11.4.4.js | 2 ++ js/src/tests/ecma_5/strict/11.4.5.js | 2 ++ js/src/tests/ecma_5/strict/12.10.1.js | 2 ++ js/src/tests/ecma_5/strict/12.14.1.js | 2 ++ js/src/tests/ecma_5/strict/12.2.1.js | 2 ++ js/src/tests/ecma_5/strict/13.1.js | 18 ++++++++++-------- js/src/tests/ecma_5/strict/8.7.2.js | 2 ++ js/src/tests/ecma_5/strict/B.1.1.js | 2 ++ js/src/tests/ecma_5/strict/B.1.2.js | 2 ++ js/src/tests/js1_8/regress/regress-499524.js | 4 +++- js/src/tests/js1_8_1/jstests.list | 1 + js/src/tests/js1_8_1/regress/regress-522123.js | 2 ++ js/src/tests/js1_8_1/strict/12.2.1.js | 2 ++ js/src/tests/js1_8_1/strict/8.7.2.js | 2 ++ .../js1_8_1/strict/generator-eval-arguments.js | 2 ++ .../js1_8_1/strict/let-block-eval-arguments.js | 2 ++ 24 files changed, 55 insertions(+), 9 deletions(-) diff --git a/js/src/tests/ecma_5/jstests.list b/js/src/tests/ecma_5/jstests.list index 7af95c439566..e6b81cbd7e7a 100644 --- a/js/src/tests/ecma_5/jstests.list +++ b/js/src/tests/ecma_5/jstests.list @@ -1,2 +1,3 @@ include Date/jstests.list include Object/jstests.list +include strict/jstests.list diff --git a/js/src/tests/ecma_5/strict/10.4.2.js b/js/src/tests/ecma_5/strict/10.4.2.js index 9500c7eccef4..1ddbe3535f3e 100644 --- a/js/src/tests/ecma_5/strict/10.4.2.js +++ b/js/src/tests/ecma_5/strict/10.4.2.js @@ -34,3 +34,5 @@ assertEq(completesNormally("Function('010')"), true); assertEq(raisesException(SyntaxError)("Function('\"use strict\"; 010')"), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/11.1.5.js b/js/src/tests/ecma_5/strict/11.1.5.js index f14b8ed34702..9c8bb597d630 100644 --- a/js/src/tests/ecma_5/strict/11.1.5.js +++ b/js/src/tests/ecma_5/strict/11.1.5.js @@ -138,3 +138,5 @@ assertEq(testLenientAndStrict('({x getter: function() {}, x getter: function() { parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/11.13.1.js b/js/src/tests/ecma_5/strict/11.13.1.js index af26edbece79..299a24018c09 100644 --- a/js/src/tests/ecma_5/strict/11.13.1.js +++ b/js/src/tests/ecma_5/strict/11.13.1.js @@ -25,3 +25,5 @@ assertEq(testLenientAndStrict('(eval)=1', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/11.13.2.js b/js/src/tests/ecma_5/strict/11.13.2.js index 61fa49a219e0..b4cf054c9de8 100644 --- a/js/src/tests/ecma_5/strict/11.13.2.js +++ b/js/src/tests/ecma_5/strict/11.13.2.js @@ -25,3 +25,5 @@ assertEq(testLenientAndStrict('(eval)+=1', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/11.3.1.js b/js/src/tests/ecma_5/strict/11.3.1.js index afbcd81ed022..62a97e1721aa 100644 --- a/js/src/tests/ecma_5/strict/11.3.1.js +++ b/js/src/tests/ecma_5/strict/11.3.1.js @@ -25,3 +25,5 @@ assertEq(testLenientAndStrict('(eval)++', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/11.3.2.js b/js/src/tests/ecma_5/strict/11.3.2.js index 7a21a85fd68e..b44d5a4dbe31 100644 --- a/js/src/tests/ecma_5/strict/11.3.2.js +++ b/js/src/tests/ecma_5/strict/11.3.2.js @@ -25,3 +25,5 @@ assertEq(testLenientAndStrict('(eval)--', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/11.4.1.js b/js/src/tests/ecma_5/strict/11.4.1.js index fc4ff0b5be5c..f882555f33d0 100644 --- a/js/src/tests/ecma_5/strict/11.4.1.js +++ b/js/src/tests/ecma_5/strict/11.4.1.js @@ -37,3 +37,5 @@ assertEq(testLenientAndStrict('function f() { "use strict"; delete x; }', parseRaisesException(SyntaxError), parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/11.4.4.js b/js/src/tests/ecma_5/strict/11.4.4.js index 319ec4731c1f..5d4cbb9377e1 100644 --- a/js/src/tests/ecma_5/strict/11.4.4.js +++ b/js/src/tests/ecma_5/strict/11.4.4.js @@ -25,3 +25,5 @@ assertEq(testLenientAndStrict('++(eval)', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/11.4.5.js b/js/src/tests/ecma_5/strict/11.4.5.js index 5dc689e103c9..d4cfba89e87b 100644 --- a/js/src/tests/ecma_5/strict/11.4.5.js +++ b/js/src/tests/ecma_5/strict/11.4.5.js @@ -25,3 +25,5 @@ assertEq(testLenientAndStrict('--(eval)', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/12.10.1.js b/js/src/tests/ecma_5/strict/12.10.1.js index 6cb4b6ed681a..161c08016201 100644 --- a/js/src/tests/ecma_5/strict/12.10.1.js +++ b/js/src/tests/ecma_5/strict/12.10.1.js @@ -26,3 +26,5 @@ assertEq(testLenientAndStrict('function f() { "use strict"; with (1) {} }', */ assertEq(parsesSuccessfully('function f() { "use strict"; }; with (1) {}'), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/12.14.1.js b/js/src/tests/ecma_5/strict/12.14.1.js index 8c5bb58e0a64..e6227884b6d2 100644 --- a/js/src/tests/ecma_5/strict/12.14.1.js +++ b/js/src/tests/ecma_5/strict/12.14.1.js @@ -33,3 +33,5 @@ assertEq(testLenientAndStrict('try{}catch({x:arguments}){}', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/12.2.1.js b/js/src/tests/ecma_5/strict/12.2.1.js index 63f2e5cad6e4..376c40bbe60d 100644 --- a/js/src/tests/ecma_5/strict/12.2.1.js +++ b/js/src/tests/ecma_5/strict/12.2.1.js @@ -21,3 +21,5 @@ assertEq(testLenientAndStrict('var x,arguments;', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/13.1.js b/js/src/tests/ecma_5/strict/13.1.js index c4438173c641..d9f0d65517c7 100644 --- a/js/src/tests/ecma_5/strict/13.1.js +++ b/js/src/tests/ecma_5/strict/13.1.js @@ -14,21 +14,21 @@ * The parameters of ordinary function definitions should not contain * duplicate identifiers. */ -assertEq(testLenientAndStrict('function(x,y) {}', +assertEq(testLenientAndStrict('function f(x,y) {}', parsesSuccessfully, parsesSuccessfully), true); -assertEq(testLenientAndStrict('function(x,x) {}', +assertEq(testLenientAndStrict('function f(x,x) {}', parsesSuccessfully, parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('function(x,y,z,y) {}', +assertEq(testLenientAndStrict('function f(x,y,z,y) {}', parsesSuccessfully, parseRaisesException(SyntaxError)), true); /* Exercise the hashed local name map case. */ -assertEq(testLenientAndStrict('function(a,b,c,d,e,f,g,h,d) {}', +assertEq(testLenientAndStrict('function f(a,b,c,d,e,f,g,h,d) {}', parsesSuccessfully, parseRaisesException(SyntaxError)), true); @@ -37,15 +37,15 @@ assertEq(testLenientAndStrict('function(a,b,c,d,e,f,g,h,d) {}', * SpiderMonkey has always treated duplicates in destructuring * patterns as an error. Strict mode should not affect this. */ -assertEq(testLenientAndStrict('function([x,y]) {}', +assertEq(testLenientAndStrict('function f([x,y]) {}', parsesSuccessfully, parsesSuccessfully), true); -assertEq(testLenientAndStrict('function([x,x]){}', +assertEq(testLenientAndStrict('function f([x,x]){}', parseRaisesException(SyntaxError), parseRaisesException(SyntaxError)), true); -assertEq(testLenientAndStrict('function(x,[x]){}', +assertEq(testLenientAndStrict('function f(x,[x]){}', parseRaisesException(SyntaxError), parseRaisesException(SyntaxError)), true); @@ -54,7 +54,7 @@ assertEq(testLenientAndStrict('function(x,[x]){}', * Strict rules apply to the parameters if the function's body is * strict. */ -assertEq(testLenientAndStrict('function(x,x) { "use strict" };', +assertEq(testLenientAndStrict('function f(x,x) { "use strict" };', parseRaisesException(SyntaxError), parseRaisesException(SyntaxError)), true); @@ -410,3 +410,5 @@ assertEq(testLenientAndStrict('Function("arguments","\'use strict\';")', raisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/8.7.2.js b/js/src/tests/ecma_5/strict/8.7.2.js index 0d9bff1f36bc..835ca7f9abc7 100644 --- a/js/src/tests/ecma_5/strict/8.7.2.js +++ b/js/src/tests/ecma_5/strict/8.7.2.js @@ -35,3 +35,5 @@ assertEq(testLenientAndStrict('undeclared_at_compiletime=1', parsesSuccessfully, parsesSuccessfully), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/B.1.1.js b/js/src/tests/ecma_5/strict/B.1.1.js index 63d5c4a101a3..bda0ba54d4a4 100644 --- a/js/src/tests/ecma_5/strict/B.1.1.js +++ b/js/src/tests/ecma_5/strict/B.1.1.js @@ -27,3 +27,5 @@ assertEq(parsesSuccessfully('function f() { "use strict"; }; 010'), /* Octal integer literal in function body */ assertEq(parsesSuccessfully('function f() { 010; }'), true); + +reportCompare(true, true); diff --git a/js/src/tests/ecma_5/strict/B.1.2.js b/js/src/tests/ecma_5/strict/B.1.2.js index a1a51d4376cb..570741e7655b 100644 --- a/js/src/tests/ecma_5/strict/B.1.2.js +++ b/js/src/tests/ecma_5/strict/B.1.2.js @@ -34,3 +34,5 @@ assertEq(testLenientAndStrict('"\\0x"', parsesSuccessfully, parsesSuccessfully), true); + +reportCompare(true, true); diff --git a/js/src/tests/js1_8/regress/regress-499524.js b/js/src/tests/js1_8/regress/regress-499524.js index c45508ece604..6c7a09d8093a 100644 --- a/js/src/tests/js1_8/regress/regress-499524.js +++ b/js/src/tests/js1_8/regress/regress-499524.js @@ -45,4 +45,6 @@ assertEq(isSyntaxError("function f(a,b,c,d,e,f,g,h,b,[y]){}"), true); assertEq(isSyntaxError("function f([y],a,b,c,d,e,f,g,h,a){}"), true); assertEq(isSyntaxError("function f([a],b,c,d,e,f,g,h,i,a){}"), true); assertEq(isSyntaxError("function f(a,b,c,d,e,f,g,h,i,[a]){}"), true); -reportCompare(isSyntaxError("function f(a,b,c,d,e,f,g,h,i,[a]){}"), true); +assertEq(isSyntaxError("function f(a,b,c,d,e,f,g,h,i,[a]){}"), true); + +reportCompare(true, true); diff --git a/js/src/tests/js1_8_1/jstests.list b/js/src/tests/js1_8_1/jstests.list index 1c313d3a70a3..8973b1c576e4 100644 --- a/js/src/tests/js1_8_1/jstests.list +++ b/js/src/tests/js1_8_1/jstests.list @@ -3,4 +3,5 @@ include extensions/jstests.list include JSON/jstests.list include regress/jstests.list include String/jstests.list +include strict/jstests.list include trace/jstests.list diff --git a/js/src/tests/js1_8_1/regress/regress-522123.js b/js/src/tests/js1_8_1/regress/regress-522123.js index 9704a967ad99..5d92ae8d3d74 100644 --- a/js/src/tests/js1_8_1/regress/regress-522123.js +++ b/js/src/tests/js1_8_1/regress/regress-522123.js @@ -66,3 +66,5 @@ function test() exitFunc ('test'); } + +reportCompare(true, true); diff --git a/js/src/tests/js1_8_1/strict/12.2.1.js b/js/src/tests/js1_8_1/strict/12.2.1.js index afd069b6c4e4..7cde4d0e63a0 100644 --- a/js/src/tests/js1_8_1/strict/12.2.1.js +++ b/js/src/tests/js1_8_1/strict/12.2.1.js @@ -70,3 +70,5 @@ assertEq(testLenientAndStrict('for (let {x:arguments} in [])break;', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/js1_8_1/strict/8.7.2.js b/js/src/tests/js1_8_1/strict/8.7.2.js index 4f12fe3969dd..dbf0b50f0fe5 100644 --- a/js/src/tests/js1_8_1/strict/8.7.2.js +++ b/js/src/tests/js1_8_1/strict/8.7.2.js @@ -12,3 +12,5 @@ assertEq(testLenientAndStrict('let let_declared; let_declared=1', completesNormally, completesNormally), true); + +reportCompare(true, true); diff --git a/js/src/tests/js1_8_1/strict/generator-eval-arguments.js b/js/src/tests/js1_8_1/strict/generator-eval-arguments.js index b705700a9821..60470f9e1790 100644 --- a/js/src/tests/js1_8_1/strict/generator-eval-arguments.js +++ b/js/src/tests/js1_8_1/strict/generator-eval-arguments.js @@ -33,3 +33,5 @@ assertEq(testLenientAndStrict('(1 for ({x:arguments} in []))', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); diff --git a/js/src/tests/js1_8_1/strict/let-block-eval-arguments.js b/js/src/tests/js1_8_1/strict/let-block-eval-arguments.js index e8a506ce204f..295ee8091835 100644 --- a/js/src/tests/js1_8_1/strict/let-block-eval-arguments.js +++ b/js/src/tests/js1_8_1/strict/let-block-eval-arguments.js @@ -30,3 +30,5 @@ assertEq(testLenientAndStrict('let ({x:arguments}=1) {}', parsesSuccessfully, parseRaisesException(SyntaxError)), true); + +reportCompare(true, true); From 1027223ec11638dbc58c61a77735a441524a3689 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Wed, 2 Dec 2009 15:17:02 -0800 Subject: [PATCH 011/179] Bug 532254: Give TCF_FUN_PARAM_EVAL a distinct value. r=mrbkap Regression test included. --- js/src/jsemit.h | 6 ++++-- js/src/tests/ecma_5/strict/jstests.list | 1 + js/src/tests/ecma_5/strict/regress-532254.js | 13 +++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 js/src/tests/ecma_5/strict/regress-532254.js diff --git a/js/src/jsemit.h b/js/src/jsemit.h index b94dcdcc5703..5593ce0e1a3b 100644 --- a/js/src/jsemit.h +++ b/js/src/jsemit.h @@ -257,7 +257,6 @@ struct JSTreeContext { /* tree context for semantic checks */ #define TCF_NO_SCRIPT_RVAL 0x4000 /* API caller does not want result value from global script */ #define TCF_HAS_SHARPS 0x8000 /* source contains sharp defs or uses */ -#define TCF_FUN_PARAM_EVAL 0x10000 /* function has parameter named 'eval' */ /* * Set when parsing a declaration-like destructuring pattern. This @@ -286,7 +285,10 @@ struct JSTreeContext { /* tree context for semantic checks */ * the use of 'with'. See also TSF_STRICT_MODE_CODE, * JSScript::strictModeCode, and JSREPORT_STRICT_ERROR. */ -#define TCF_STRICT_MODE_CODE 0x40000 +#define TCF_STRICT_MODE_CODE 0x40000 + +/* Function has parameter named 'eval'. */ +#define TCF_FUN_PARAM_EVAL 0x80000 /* * Flags to propagate out of the blocks. diff --git a/js/src/tests/ecma_5/strict/jstests.list b/js/src/tests/ecma_5/strict/jstests.list index 908959927bf9..43588b8ce29f 100644 --- a/js/src/tests/ecma_5/strict/jstests.list +++ b/js/src/tests/ecma_5/strict/jstests.list @@ -15,4 +15,5 @@ script 12.14.1.js script 13.1.js script B.1.1.js script B.1.2.js +script regress-532254.js script regress-532041.js diff --git a/js/src/tests/ecma_5/strict/regress-532254.js b/js/src/tests/ecma_5/strict/regress-532254.js new file mode 100644 index 000000000000..e91e05b1a6a5 --- /dev/null +++ b/js/src/tests/ecma_5/strict/regress-532254.js @@ -0,0 +1,13 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(testLenientAndStrict('function f(eval,[x]){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); From 3fbaa3e0933a71be662a81a816457b84d11a7113 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Wed, 2 Dec 2009 19:13:31 -0800 Subject: [PATCH 012/179] Extra assertions, control flow cleanup in putProperty, and a crucial scope hashtable fix to removeProperty (stored was not reloaded from *spp; got rid of this ancient over-optimization by hand-coded 'register allocation'; 532096, r=mrbkap). --- js/src/jsscope.cpp | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 659b3aabdcc0..ad39c6f58786 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -326,6 +326,10 @@ JSScope::searchTable(jsid id, bool adding) hash2 = SCOPE_HASH2(hash0, sizeLog2, hashShift); sizeMask = JS_BITMASK(sizeLog2); +#ifdef DEBUG + jsuword collision_flag = SPROP_COLLISION; +#endif + /* Save the first removed entry pointer so we can recycle it if adding. */ if (SPROP_IS_REMOVED(stored)) { firstRemoved = spp; @@ -333,6 +337,9 @@ JSScope::searchTable(jsid id, bool adding) firstRemoved = NULL; if (adding && !SPROP_HAD_COLLISION(stored)) SPROP_FLAG_COLLISION(spp, sprop); +#ifdef DEBUG + collision_flag &= jsuword(*spp) & SPROP_COLLISION; +#endif } for (;;) { @@ -350,6 +357,7 @@ JSScope::searchTable(jsid id, bool adding) sprop = SPROP_CLEAR_COLLISION(stored); if (sprop && sprop->id == id) { METER(stepHits); + JS_ASSERT(collision_flag); return spp; } @@ -359,6 +367,9 @@ JSScope::searchTable(jsid id, bool adding) } else { if (adding && !SPROP_HAD_COLLISION(stored)) SPROP_FLAG_COLLISION(spp, sprop); +#ifdef DEBUG + collision_flag &= jsuword(*spp) & SPROP_COLLISION; +#endif } } @@ -1435,14 +1446,15 @@ JSScope::putProperty(JSContext *cx, jsid id, } if (sprop) { - /* Store the tree node pointer in the table entry for id. */ - if (table) - SPROP_STORE_PRESERVING_COLLISION(spp, sprop); CHECK_ANCESTOR_LINE(this, false); - /* See comment in JSScope::addPropertyHelper about ignoring OOM here. */ - if (!table && entryCount >= SCOPE_HASH_THRESHOLD) + if (table) { + /* Store the tree node pointer in the table entry for id. */ + SPROP_STORE_PRESERVING_COLLISION(spp, sprop); + } else if (entryCount >= SCOPE_HASH_THRESHOLD) { + /* See comment in JSScope::addPropertyHelper about ignoring OOM here. */ (void) createTable(cx, false); + } METER(puts); return sprop; @@ -1520,7 +1532,7 @@ JSScope::changeProperty(JSContext *cx, JSScopeProperty *sprop, /* * Let JSScope::putProperty handle this |overwriting| case, including * the conservation of sprop->slot (if it's valid). We must not call - * JSScope::remove here, because it will free a valid sprop->slot and + * JSScope::removeProperty because it will free a valid sprop->slot and * JSScope::putProperty won't re-allocate it. */ newsprop = putProperty(cx, child.id, child.getter, child.setter, child.slot, @@ -1539,7 +1551,7 @@ JSScope::changeProperty(JSContext *cx, JSScopeProperty *sprop, bool JSScope::removeProperty(JSContext *cx, jsid id) { - JSScopeProperty **spp, *stored, *sprop; + JSScopeProperty **spp, *sprop; uint32 size; JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, this)); @@ -1550,8 +1562,7 @@ JSScope::removeProperty(JSContext *cx, jsid id) } spp = search(id, false); - stored = *spp; - sprop = SPROP_CLEAR_COLLISION(stored); + sprop = SPROP_CLEAR_COLLISION(*spp); if (!sprop) { METER(uselessRemoves); return true; @@ -1574,14 +1585,19 @@ JSScope::removeProperty(JSContext *cx, jsid id) } /* Next, remove id by setting its entry to a removed or free sentinel. */ - if (SPROP_HAD_COLLISION(stored)) { + if (SPROP_HAD_COLLISION(*spp)) { JS_ASSERT(table); *spp = SPROP_REMOVED; ++removedCount; } else { METER(removeFrees); - if (table) + if (table) { *spp = NULL; +#ifdef DEBUG + for (JSScopeProperty *aprop = lastProp; aprop; aprop = aprop->parent) + JS_ASSERT_IF(aprop != sprop, hasProperty(aprop)); +#endif + } } LIVE_SCOPE_METER(cx, --cx->runtime->liveScopeProps); From 3804b7e35300e87cf9b9514d3a2200813ee8dee3 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Wed, 2 Dec 2009 21:50:04 -0800 Subject: [PATCH 013/179] Trace JSOP_ENUMELEM, for the group-assignment special case of destructuring assignment (532043, r=gal). --- js/src/jstracer.cpp | 22 ++++++++++++++++------ js/src/jstracer.h | 2 ++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index ca09522a14d1..cc784679bea2 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -11825,11 +11825,11 @@ TraceRecorder::initOrSetPropertyByIndex(LIns* obj_ins, LIns* index_ins, jsval* r } JS_REQUIRES_STACK AbortableRecordingStatus -TraceRecorder::record_JSOP_SETELEM() +TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) { - jsval& v = stackval(-1); - jsval& idx = stackval(-2); - jsval& lval = stackval(-3); + jsval& v = stackval(v_spindex); + jsval& idx = stackval(idx_spindex); + jsval& lval = stackval(lval_spindex); if (JSVAL_IS_PRIMITIVE(lval)) RETURN_STOP_A("left JSOP_SETELEM operand is not an object"); @@ -11889,6 +11889,12 @@ TraceRecorder::record_JSOP_SETELEM() return ARECORD_CONTINUE; } +JS_REQUIRES_STACK AbortableRecordingStatus +TraceRecorder::record_JSOP_SETELEM() +{ + return setElem(-3, -2, -1); +} + JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_CALLNAME() { @@ -12957,7 +12963,7 @@ TraceRecorder::record_JSOP_INITPROP() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_INITELEM() { - return record_JSOP_SETELEM(); + return setElem(-3, -2, -1); } JS_REQUIRES_STACK AbortableRecordingStatus @@ -13415,7 +13421,11 @@ TraceRecorder::record_JSOP_EVAL() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_ENUMELEM() { - return ARECORD_STOP; + /* + * To quote from jsops.cpp's JSOP_ENUMELEM case: + * Funky: the value to set is under the [obj, id] pair. + */ + return setElem(-2, -1, -3); } JS_REQUIRES_STACK AbortableRecordingStatus diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 285bf71c6591..2ec8352ff204 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1273,6 +1273,8 @@ class TraceRecorder JS_REQUIRES_STACK RecordingStatus initOrSetPropertyByIndex(nanojit::LIns* obj_ins, nanojit::LIns* index_ins, jsval* rvalp, bool init); + JS_REQUIRES_STACK AbortableRecordingStatus setElem(int lval_spindex, int idx_spindex, + int v_spindex); JS_REQUIRES_STACK nanojit::LIns* box_jsval(jsval v, nanojit::LIns* v_ins); JS_REQUIRES_STACK nanojit::LIns* unbox_jsval(jsval v, nanojit::LIns* v_ins, VMSideExit* exit); From b9e72b82eae7889f6469121539132e69d438427d Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Wed, 2 Dec 2009 21:51:18 -0800 Subject: [PATCH 014/179] Test for last checkin (532043). --- .../tests/basic/testGroupAssignment.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 js/src/trace-test/tests/basic/testGroupAssignment.js diff --git a/js/src/trace-test/tests/basic/testGroupAssignment.js b/js/src/trace-test/tests/basic/testGroupAssignment.js new file mode 100644 index 000000000000..11ef77ae0727 --- /dev/null +++ b/js/src/trace-test/tests/basic/testGroupAssignment.js @@ -0,0 +1,22 @@ +assertEq( + (function () { + var arr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 ]; + + for (var i = 0; i < 4; ++i) { + var src = i * 8; + var dst = i * 8 + 7; + for (var j = 0; j < 4; ++j) { + [arr[dst--], arr[src++]] = [arr[src], arr[dst]]; + } + } + return arr; + })().toSource(), + "[7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 32]"); + +checkStats({ + recorderStarted: 2, + traceCompleted: 2, + sideExitIntoInterpreter: 3, + traceTriggered: 3 +}); From 690f055918147f1890be115c10ab14a7b2c00fce Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Thu, 3 Dec 2009 01:25:17 -0800 Subject: [PATCH 015/179] Bug 532041: Add missing call to reportCompare. r=orange jsreftests --- js/src/tests/ecma_5/strict/regress-532041.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/tests/ecma_5/strict/regress-532041.js b/js/src/tests/ecma_5/strict/regress-532041.js index 684686d929dd..5591264bf079 100644 --- a/js/src/tests/ecma_5/strict/regress-532041.js +++ b/js/src/tests/ecma_5/strict/regress-532041.js @@ -13,3 +13,5 @@ * overall name count. */ function f(a1,a2,a3,a4,a5) { "use strict"; var v1, v2, v3, v4, v5, v6, v7; } + +reportCompare(true, true); From d7ed73bf717f299f01c0f3316a6b1f564e2b9e1a Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Thu, 3 Dec 2009 09:27:26 -0800 Subject: [PATCH 016/179] Bug 532176: Fix 'make jstestbrowser EXTRA_TEST_ARGS=...'; allow command line to override test list. r=bclary --- testing/testsuite-targets.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/testsuite-targets.mk b/testing/testsuite-targets.mk index fd23c2e32dbb..7c2948ef5098 100644 --- a/testing/testsuite-targets.mk +++ b/testing/testsuite-targets.mk @@ -96,9 +96,9 @@ crashtest: $(call RUN_REFTEST,$(topsrcdir)/$(TEST_PATH)) $(CHECK_TEST_ERROR) -jstestbrowser: EXTRA_TEST_ARGS += --extra-profile-file=$(topsrcdir)/js/src/tests/user.js +jstestbrowser: TEST_PATH=js/src/tests/jstests.list jstestbrowser: - $(call RUN_REFTEST,$(topsrcdir)/js/src/tests/jstests.list) + $(call RUN_REFTEST,$(topsrcdir)/$(TEST_PATH) --extra-profile-file=$(topsrcdir)/js/src/tests/user.js) $(CHECK_TEST_ERROR) # Execute all xpcshell tests in the directories listed in the manifest. From dd8b2e8519b69bf6604af345da92e19dfe9d3a30 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 3 Dec 2009 14:39:42 -0500 Subject: [PATCH 017/179] Bug 521423. Make JSString 4 words instead of 2; make substring() and company never have to copy. r=brendan --- js/src/jsatom.cpp | 2 +- js/src/jsstr.cpp | 31 +++------- js/src/jsstr.h | 138 +++++++++++++------------------------------- js/src/jstracer.cpp | 40 ++----------- js/src/jstracer.h | 2 - 5 files changed, 56 insertions(+), 157 deletions(-) diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 6b6eaf953b33..8ccbfde0a8ee 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -748,7 +748,7 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags) if (!key) return NULL; } - } else { + } else { JS_ASSERT(str->isDependent()); if (!js_UndependString(cx, str)) return NULL; diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 08c9f3f104e1..1fc43664869f 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -101,13 +101,8 @@ MinimizeDependentStrings(JSString *str, int level, JSString **basep) base = base->dependentBase(); } while (base->isDependent()); } - if (start == 0) { - JS_ASSERT(str->dependentIsPrefix()); - str->prefixSetBase(base); - } else if (start <= JSString::MAX_DEPENDENT_START) { - length = str->dependentLength(); - str->reinitDependent(base, start, length); - } + length = str->dependentLength(); + str->reinitDependent(base, start, length); } *basep = base; return start; @@ -188,9 +183,9 @@ js_ConcatStrings(JSContext *cx, JSString *left, JSString *right) } else { str->flatSetMutable(); - /* Morph left into a dependent prefix if we realloc'd its buffer. */ + /* Morph left into a dependent string if we realloc'd its buffer. */ if (ldep) { - ldep->reinitPrefix(str, ln); + ldep->reinitDependent(str, 0, ln); #ifdef DEBUG { JSRuntime *rt = cx->runtime; @@ -2636,7 +2631,7 @@ static const jschar UnitStringData[] = { C(0xf8), C(0xf9), C(0xfa), C(0xfb), C(0xfc), C(0xfd), C(0xfe), C(0xff) }; -#define U(c) { 1 | JSString::ATOMIZED, {(jschar *)UnitStringData + (c) * 2} } +#define U(c) { 1, 0, JSString::ATOMIZED, {(jschar *)UnitStringData + (c) * 2} } #ifdef __SUNPRO_CC #pragma pack(8) @@ -2743,9 +2738,9 @@ static const jschar Hundreds[] = { O25(0x30), O25(0x31), O25(0x32), O25(0x33), O25(0x34), O25(0x35) }; -#define L1(c) { 1 | JSString::ATOMIZED, {(jschar *)Hundreds + 2 + (c) * 4} } /* length 1: 0..9 */ -#define L2(c) { 2 | JSString::ATOMIZED, {(jschar *)Hundreds + 41 + (c - 10) * 4} } /* length 2: 10..99 */ -#define L3(c) { 3 | JSString::ATOMIZED, {(jschar *)Hundreds + (c - 100) * 4} } /* length 3: 100..255 */ +#define L1(c) { 1, 0, JSString::ATOMIZED, {(jschar *)Hundreds + 2 + (c) * 4} } /* length 1: 0..9 */ +#define L2(c) { 2, 0, JSString::ATOMIZED, {(jschar *)Hundreds + 41 + (c - 10) * 4} } /* length 2: 10..99 */ +#define L3(c) { 3, 0, JSString::ATOMIZED, {(jschar *)Hundreds + (c - 100) * 4} } /* length 3: 100..255 */ #ifdef __SUNPRO_CC #pragma pack(8) @@ -3156,18 +3151,10 @@ js_NewDependentString(JSContext *cx, JSString *base, size_t start, if (start == 0 && length == base->length()) return base; - if (start > JSString::MAX_DEPENDENT_START || - (start != 0 && length > JSString::MAX_DEPENDENT_LENGTH)) { - return js_NewStringCopyN(cx, base->chars() + start, length); - } - ds = js_NewGCString(cx); if (!ds) return NULL; - if (start == 0) - ds->initPrefix(base, length); - else - ds->initDependent(base, start, length); + ds->initDependent(base, start, length); #ifdef DEBUG { JSRuntime *rt = cx->runtime; diff --git a/js/src/jsstr.h b/js/src/jsstr.h index e9bd8059c2e9..f031a3d87e3e 100644 --- a/js/src/jsstr.h +++ b/js/src/jsstr.h @@ -73,7 +73,7 @@ JS_STATIC_ASSERT(JS_BITS_PER_WORD >= 32); /* * The GC-thing "string" type. * - * When the DEPENDENT bit of the mLength field is unset, the mChars field + * When the DEPENDENT bit of the mFlags field is unset, the mChars field * points to a flat character array owned by its GC-thing descriptor. The * array is terminated at index length by a zero character and the size of the * array in bytes is (length + 1) * sizeof(jschar). The terminator is purely a @@ -97,16 +97,6 @@ JS_STATIC_ASSERT(JS_BITS_PER_WORD >= 32); * string strongly referenced by the mBase field. The base member may point to * another dependent string if chars() has not been called yet. * - * The PREFIX flag determines the kind of the dependent string. When the flag - * is unset, the mLength field encodes both starting position relative to the - * base string and the number of characters in the dependent string, see - * DEPENDENT_START_MASK and DEPENDENT_LENGTH_MASK below for details. - * - * When the PREFIX flag is set, the dependent string is a prefix of the base - * string. The number of characters in the prefix is encoded using all non-flag - * bits of the mLength field and spans the same 0 .. SIZE_T_MAX/4 range as the - * length of the flat string. - * * NB: Always use the length() and chars() accessor methods. */ struct JSString { @@ -118,46 +108,33 @@ struct JSString { friend JSString * JS_FASTCALL js_ConcatStrings(JSContext *cx, JSString *left, JSString *right); + // Not private because we want to be able to use static + // initializers for them. Don't use these directly! size_t mLength; + size_t mOffset; + jsword mFlags; union { jschar *mChars; JSString *mBase; }; /* - * Definitions for flags stored in the high order bits of mLength. - * - * PREFIX and MUTABLE are two aliases for the same bit. PREFIX should be - * used only if DEPENDENT is set and MUTABLE should be used only if the - * string is flat. + * Definitions for flags stored in mFlags. * * ATOMIZED is used only with flat, immutable strings. */ - static const size_t DEPENDENT = JSSTRING_BIT(JS_BITS_PER_WORD - 1); - static const size_t PREFIX = JSSTRING_BIT(JS_BITS_PER_WORD - 2); - static const size_t MUTABLE = PREFIX; - static const size_t ATOMIZED = JSSTRING_BIT(JS_BITS_PER_WORD - 3); - static const size_t DEFLATED = JSSTRING_BIT(JS_BITS_PER_WORD - 4); -#if JS_BITS_PER_WORD > 32 - static const size_t LENGTH_BITS = 28; -#else - static const size_t LENGTH_BITS = JS_BITS_PER_WORD - 4; -#endif - static const size_t LENGTH_MASK = JSSTRING_BITMASK(LENGTH_BITS); - static const size_t DEPENDENT_LENGTH_BITS = 8; - static const size_t DEPENDENT_LENGTH_MASK = JSSTRING_BITMASK(DEPENDENT_LENGTH_BITS); - static const size_t DEPENDENT_START_BITS = LENGTH_BITS - DEPENDENT_LENGTH_BITS; - static const size_t DEPENDENT_START_SHIFT = DEPENDENT_LENGTH_BITS; - static const size_t DEPENDENT_START_MASK = JSSTRING_BITMASK(DEPENDENT_START_BITS); + static const size_t DEPENDENT = JSSTRING_BIT(1); + static const size_t MUTABLE = JSSTRING_BIT(2); + static const size_t ATOMIZED = JSSTRING_BIT(3); + static const size_t DEFLATED = JSSTRING_BIT(4); bool hasFlag(size_t flag) const { - return (mLength & flag) != 0; + return (mFlags & flag) != 0; } public: - static const size_t MAX_LENGTH = LENGTH_MASK; - static const size_t MAX_DEPENDENT_START = DEPENDENT_START_MASK; - static const size_t MAX_DEPENDENT_LENGTH = DEPENDENT_LENGTH_MASK; + /* Generous but sane length bound. */ + static const size_t MAX_LENGTH = (1 << 28); bool isDependent() const { return hasFlag(DEPENDENT); @@ -172,7 +149,7 @@ struct JSString { } void setDeflated() { - JS_ATOMIC_SET_MASK((jsword *) &mLength, DEFLATED); + JS_ATOMIC_SET_MASK(&mFlags, DEFLATED); } bool isMutable() const { @@ -188,7 +165,7 @@ struct JSString { } JS_ALWAYS_INLINE size_t length() const { - return isDependent() ? dependentLength() : flatLength(); + return mLength; } JS_ALWAYS_INLINE bool empty() const { @@ -196,25 +173,20 @@ struct JSString { } JS_ALWAYS_INLINE void getCharsAndLength(const jschar *&chars, size_t &length) { - if (isDependent()) { - length = dependentLength(); - chars = dependentChars(); - } else { - length = flatLength(); - chars = flatChars(); - } + chars = this->chars(); + length = this->length(); } JS_ALWAYS_INLINE void getCharsAndEnd(const jschar *&chars, const jschar *&end) { - end = isDependent() - ? dependentLength() + (chars = dependentChars()) - : flatLength() + (chars = flatChars()); + end = length() + (chars = this->chars()); } /* Specific flat string initializer and accessor methods. */ void initFlat(jschar *chars, size_t length) { JS_ASSERT(length <= MAX_LENGTH); mLength = length; + mOffset = 0; + mFlags = 0; mChars = chars; } @@ -223,19 +195,20 @@ struct JSString { return mChars; } - size_t flatLength() const { + JS_ALWAYS_INLINE size_t flatLength() const { JS_ASSERT(isFlat()); - return mLength & LENGTH_MASK; + return length(); } /* - * Special flat string initializer that preserves the JSSTR_DEFLATED flag. + * Special flat string initializer that preserves the DEFLATED flag. * Use this method when reinitializing an existing string which may be * hashed to its deflated bytes. Newborn strings must use initFlat. */ void reinitFlat(jschar *chars, size_t length) { - JS_ASSERT(length <= MAX_LENGTH); - mLength = (mLength & DEFLATED) | (length & ~DEFLATED); + mLength = length; + mOffset = 0; + mFlags = mFlags & DEFLATED; mChars = chars; } @@ -255,7 +228,7 @@ struct JSString { * only one thread can access the string (see previous property). * * Thus, when multiple threads access the string, JSString::flatSetAtomized - * is the only function that can update the mLength field of the string by + * is the only function that can update the mFlags field of the string by * changing the mutable bit from 0 to 1. We call the method only after the * string has been hashed. When some threads in js_ValueToStringId see that * the flag is set, it knows that the string was atomized. @@ -268,33 +241,34 @@ struct JSString { */ void flatSetAtomized() { JS_ASSERT(isFlat() && !isMutable()); - JS_STATIC_ASSERT(sizeof(mLength) == sizeof(jsword)); - JS_ATOMIC_SET_MASK((jsword *) &mLength, ATOMIZED); + JS_ATOMIC_SET_MASK(&mFlags, ATOMIZED); } void flatSetMutable() { JS_ASSERT(isFlat() && !isAtomized()); - mLength |= MUTABLE; + mFlags |= MUTABLE; } void flatClearMutable() { JS_ASSERT(isFlat()); if (hasFlag(MUTABLE)) - mLength &= ~MUTABLE; + mFlags &= ~MUTABLE; } void initDependent(JSString *bstr, size_t off, size_t len) { - JS_ASSERT(off <= MAX_DEPENDENT_START); - JS_ASSERT(len <= MAX_DEPENDENT_LENGTH); - mLength = DEPENDENT | (off << DEPENDENT_START_SHIFT) | len; + JS_ASSERT(len <= MAX_LENGTH); + mLength = len; + mOffset = off; + mFlags = DEPENDENT; mBase = bstr; } /* See JSString::reinitFlat. */ void reinitDependent(JSString *bstr, size_t off, size_t len) { - JS_ASSERT(off <= MAX_DEPENDENT_START); - JS_ASSERT(len <= MAX_DEPENDENT_LENGTH); - mLength = DEPENDENT | (mLength & DEFLATED) | (off << DEPENDENT_START_SHIFT) | len; + JS_ASSERT(len <= MAX_LENGTH); + mLength = len; + mOffset = off; + mFlags = DEPENDENT | (mFlags & DEFLATED); mBase = bstr; } @@ -303,11 +277,6 @@ struct JSString { return mBase; } - bool dependentIsPrefix() const { - JS_ASSERT(isDependent()); - return hasFlag(PREFIX); - } - JS_ALWAYS_INLINE jschar *dependentChars() { return dependentBase()->isDependent() ? js_GetDependentStringChars(this) @@ -315,39 +284,12 @@ struct JSString { } JS_ALWAYS_INLINE size_t dependentStart() const { - return dependentIsPrefix() - ? 0 - : ((mLength >> DEPENDENT_START_SHIFT) & DEPENDENT_START_MASK); + return mOffset; } JS_ALWAYS_INLINE size_t dependentLength() const { JS_ASSERT(isDependent()); - if (dependentIsPrefix()) - return mLength & LENGTH_MASK; - return mLength & DEPENDENT_LENGTH_MASK; - } - - void initPrefix(JSString *bstr, size_t len) { - JS_ASSERT(len <= MAX_LENGTH); - mLength = DEPENDENT | PREFIX | len; - mBase = bstr; - } - - /* See JSString::reinitFlat. */ - void reinitPrefix(JSString *bstr, size_t len) { - JS_ASSERT(len <= MAX_LENGTH); - mLength = DEPENDENT | PREFIX | (mLength & DEFLATED) | len; - mBase = bstr; - } - - JSString *prefixBase() const { - JS_ASSERT(isDependent() && dependentIsPrefix()); - return dependentBase(); - } - - void prefixSetBase(JSString *bstr) { - JS_ASSERT(isDependent() && dependentIsPrefix()); - mBase = bstr; + return length(); } static inline bool isUnitString(void *ptr) { diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index cc784679bea2..5bdc768ec1de 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -8324,11 +8324,7 @@ TraceRecorder::ifop() lir->ins_eq0(lir->ins2(LIR_feq, v_ins, lir->insImmf(0)))); } else if (JSVAL_IS_STRING(v)) { cond = JSVAL_TO_STRING(v)->length() != 0; - x = lir->ins2(LIR_piand, - lir->insLoad(LIR_ldp, - v_ins, - (int)offsetof(JSString, mLength)), - INS_CONSTWORD(JSString::LENGTH_MASK)); + x = lir->insLoad(LIR_ldp, v_ins, offsetof(JSString, mLength)); } else { JS_NOT_REACHED("ifop"); return ARECORD_STOP; @@ -9552,31 +9548,6 @@ TraceRecorder::getThis(LIns*& this_ins) } -LIns* -TraceRecorder::getStringLength(LIns* str_ins) -{ - LIns* len_ins = lir->insLoad(LIR_ldp, str_ins, (int)offsetof(JSString, mLength)); - - LIns* masked_len_ins = lir->ins2(LIR_piand, - len_ins, - INS_CONSTWORD(JSString::LENGTH_MASK)); - - LIns* real_len = - lir->ins_choose(lir->ins_peq0(lir->ins2(LIR_piand, - len_ins, - INS_CONSTWORD(JSString::DEPENDENT))), - masked_len_ins, - lir->ins_choose(lir->ins_peq0(lir->ins2(LIR_piand, - len_ins, - INS_CONSTWORD(JSString::PREFIX))), - lir->ins2(LIR_piand, - len_ins, - INS_CONSTWORD(JSString::DEPENDENT_LENGTH_MASK)), - masked_len_ins, avmplus::AvmCore::use_cmov()), - avmplus::AvmCore::use_cmov()); - return p2i(real_len); -} - JS_REQUIRES_STACK bool TraceRecorder::guardClass(JSObject* obj, LIns* obj_ins, JSClass* clasp, VMSideExit* exit) { @@ -10189,9 +10160,8 @@ TraceRecorder::record_JSOP_NOT() return ARECORD_CONTINUE; } JS_ASSERT(JSVAL_IS_STRING(v)); - set(&v, lir->ins_peq0(lir->ins2(LIR_piand, - lir->insLoad(LIR_ldp, get(&v), (int)offsetof(JSString, mLength)), - INS_CONSTWORD(JSString::LENGTH_MASK)))); + set(&v, lir->ins_peq0(lir->insLoad(LIR_ldp, get(&v), + offsetof(JSString, mLength)))); return ARECORD_CONTINUE; } @@ -14466,7 +14436,9 @@ TraceRecorder::record_JSOP_LENGTH() if (JSVAL_IS_PRIMITIVE(l)) { if (!JSVAL_IS_STRING(l)) RETURN_STOP_A("non-string primitive JSOP_LENGTH unsupported"); - set(&l, lir->ins1(LIR_i2f, getStringLength(get(&l)))); + set(&l, lir->ins1(LIR_i2f, + p2i(lir->insLoad(LIR_ldp, get(&l), + offsetof(JSString, mLength))))); return ARECORD_CONTINUE; } diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 2ec8352ff204..830bf8338d88 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1231,8 +1231,6 @@ class TraceRecorder return stobj_get_fslot(obj_ins, JSSLOT_PARENT); } - nanojit::LIns* getStringLength(nanojit::LIns* str_ins); - JS_REQUIRES_STACK AbortableRecordingStatus name(jsval*& vp, nanojit::LIns*& ins, NameResult& nr); JS_REQUIRES_STACK AbortableRecordingStatus prop(JSObject* obj, nanojit::LIns* obj_ins, uint32 *slotp, nanojit::LIns** v_insp, jsval* outp); From 8b65f5443b89a42d0342fda50faf1f115c3efca7 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 3 Dec 2009 14:39:55 -0500 Subject: [PATCH 018/179] Bug 530240. Faster NormalizeThis for String objects. r=brendan --- js/src/jsstr.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 1fc43664869f..2f4124c6fbe5 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -649,9 +649,21 @@ NormalizeThis(JSContext *cx, jsval *vp) if (JSVAL_IS_NULL(vp[1]) && JSVAL_IS_NULL(JS_THIS(cx, vp))) return NULL; - str = js_ValueToString(cx, vp[1]); - if (!str) - return NULL; + + /* + * js_GetPrimitiveThis seems to do a bunch of work (like calls to + * JS_THIS_OBJECT) which we don't need in the common case (where + * vp[1] is a String object) here. + */ + JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1])); + JSObject *obj = JSVAL_TO_OBJECT(vp[1]); + if (obj->getClass() == &js_StringClass) { + str = JSVAL_TO_STRING(obj->fslots[JSSLOT_PRIMITIVE_THIS]); + } else { + str = js_ValueToString(cx, vp[1]); + if (!str) + return NULL; + } vp[1] = STRING_TO_JSVAL(str); return str; } @@ -928,9 +940,7 @@ str_charAt(JSContext *cx, uintN argc, jsval *vp) if ((size_t)i >= str->length()) goto out_of_range; } else { - str = NormalizeThis(cx, vp); - if (!str) - return JS_FALSE; + NORMALIZE_THIS(cx, vp, str); if (argc == 0) { d = 0.0; @@ -972,9 +982,7 @@ str_charCodeAt(JSContext *cx, uintN argc, jsval *vp) if ((size_t)i >= str->length()) goto out_of_range; } else { - str = NormalizeThis(cx, vp); - if (!str) - return JS_FALSE; + NORMALIZE_THIS(cx, vp, str); if (argc == 0) { d = 0.0; From d7f9f271714a9c362f421ad2e4e16629080d7f95 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Thu, 3 Dec 2009 12:12:39 -0800 Subject: [PATCH 019/179] Only consider an eval cache entry if the static level matches (532491, r=igor). --- js/src/jsobj.cpp | 3 +- js/src/tests/js1_8/regress/regress-532491.js | 71 ++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 js/src/tests/js1_8/regress/regress-532491.js diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 0050f28add76..8ef1433cf9e1 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1444,13 +1444,14 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) * calls to eval from global code are not cached. */ bucket = EvalCacheHash(cx, str); - if (!indirectCall && argc == 1 && caller->fun) { + if (!indirectCall && caller->fun) { uintN count = 0; JSScript **scriptp = bucket; EVAL_CACHE_METER(probe); while ((script = *scriptp) != NULL) { if (script->savedCallerFun && + script->staticLevel == staticLevel && script->version == cx->version && (script->principals == principals || (principals->subsume(principals, script->principals) && diff --git a/js/src/tests/js1_8/regress/regress-532491.js b/js/src/tests/js1_8/regress/regress-532491.js new file mode 100644 index 000000000000..6a65a5124732 --- /dev/null +++ b/js/src/tests/js1_8/regress/regress-532491.js @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Andreas Gal + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +var gTestfile = 'regress-532491.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 466128; +var summary = 'Assertion failure: staticLevel == script->staticLevel, at ../jsobj.cpp'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + jit(false); + function f(foo) { + if (a % 2 == 1) { + try { + eval(foo); + } catch(e) {} + } + } + a = 1; + f("eval(\"x\")"); + f("x"); + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} From 2037f692ae69d3f1a2ad0aa9ad4d309c8b85482d Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Thu, 3 Dec 2009 13:02:36 -0800 Subject: [PATCH 020/179] Bug 530489: don't (incorrectly) trace custom equality ops, r=jorendorff --- js/src/jsapi-tests/Makefile.in | 1 + js/src/jsapi-tests/testExtendedEq.cpp | 45 +++++++++++++++++++++++++++ js/src/jstracer.cpp | 5 +++ 3 files changed, 51 insertions(+) create mode 100644 js/src/jsapi-tests/testExtendedEq.cpp diff --git a/js/src/jsapi-tests/Makefile.in b/js/src/jsapi-tests/Makefile.in index 341ecec27abb..48ff8baa141a 100644 --- a/js/src/jsapi-tests/Makefile.in +++ b/js/src/jsapi-tests/Makefile.in @@ -51,6 +51,7 @@ CPPSRCS = \ testContexts.cpp \ testDebugger.cpp \ testDefineGetterSetterNonEnumerable.cpp \ + testExtendedEq.cpp \ testIntString.cpp \ testLookup.cpp \ testPropCache.cpp \ diff --git a/js/src/jsapi-tests/testExtendedEq.cpp b/js/src/jsapi-tests/testExtendedEq.cpp new file mode 100644 index 000000000000..649c0cd630b1 --- /dev/null +++ b/js/src/jsapi-tests/testExtendedEq.cpp @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=4 sw=4 et tw=99: + * + * This tests user-specified (via JSExtendedClass) equality operations on + * trace. + */ + +#include "tests.h" + +static JSBool +my_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) +{ + *bp = JS_TRUE; + return JS_TRUE; +} + +JSExtendedClass TestExtendedEq_JSClass = { + { "TestExtendedEq", + JSCLASS_IS_EXTENDED, + JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL + }, + // JSExtendedClass initialization + my_Equality, + NULL, NULL, NULL, NULL, JSCLASS_NO_RESERVED_MEMBERS +}; + +BEGIN_TEST(testExtendedEq_bug530489) +{ + JSClass *clasp = (JSClass *) &TestExtendedEq_JSClass; + + JSObject *global = JS_GetGlobalObject(cx); + JS_InitClass(cx, global, global, clasp, NULL, 0, NULL, NULL, NULL, NULL); + + JS_DefineObject(cx, global, "obj1", clasp, NULL, 0); + JS_DefineObject(cx, global, "obj2", clasp, NULL, 0); + + jsval v; + EVAL("(function() { var r; for (var i = 0; i < 10; ++i) r = obj1 == obj2; return r; })()", &v); + CHECK_SAME(v, JSVAL_TRUE); + return true; +} +END_TEST(testExtendedEq_bug530489) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 5bdc768ec1de..05359832aa72 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -8637,6 +8637,11 @@ TraceRecorder::equalityHelper(jsval l, jsval r, LIns* l_ins, LIns* r_ins, if (GetPromotedType(l) == GetPromotedType(r)) { if (JSVAL_TAG(l) == JSVAL_OBJECT || JSVAL_IS_SPECIAL(l)) { + if (JSVAL_TAG(l) == JSVAL_OBJECT && l) { + JSClass *clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(l)); + if ((clasp->flags & JSCLASS_IS_EXTENDED) && ((JSExtendedClass*) clasp)->equality) + RETURN_STOP_A("Can't trace extended class equality operator"); + } if (JSVAL_TAG(l) == JSVAL_OBJECT) op = LIR_peq; cond = (l == r); From 61d4096a55132f8adfd8fd63641be21eef2473e1 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Thu, 3 Dec 2009 16:12:09 -0600 Subject: [PATCH 021/179] Bug 530879 - Generators get incorrect arguments.length. Discovered by Donny Viszneki. r=brendan. --- js/src/jsiter.cpp | 2 +- js/src/tests/js1_8_1/regress/jstests.list | 1 + js/src/tests/js1_8_1/regress/regress-530879.js | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 js/src/tests/js1_8_1/regress/regress-530879.js diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 46772cc3739a..82f6b45551a4 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -766,7 +766,7 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp) /* Copy rval, argv and vars. */ gen->frame.rval = fp->rval; memcpy(slots, fp->argv - 2, (2 + nargs) * sizeof(jsval)); - gen->frame.argc = nargs; + gen->frame.argc = fp->argc; gen->frame.argv = slots + 2; slots += 2 + nargs; memcpy(slots, fp->slots, fp->script->nfixed * sizeof(jsval)); diff --git a/js/src/tests/js1_8_1/regress/jstests.list b/js/src/tests/js1_8_1/regress/jstests.list index 979779255031..5ec1a4917afd 100644 --- a/js/src/tests/js1_8_1/regress/jstests.list +++ b/js/src/tests/js1_8_1/regress/jstests.list @@ -83,3 +83,4 @@ script regress-515885.js skip-if(isDebugBuild&&!xulRuntime.shell) script regress-524743.js # hang script regress-522123.js script regress-524264.js +script regress-530879.js diff --git a/js/src/tests/js1_8_1/regress/regress-530879.js b/js/src/tests/js1_8_1/regress/regress-530879.js new file mode 100644 index 000000000000..23dd1c73d065 --- /dev/null +++ b/js/src/tests/js1_8_1/regress/regress-530879.js @@ -0,0 +1,10 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: Jason Orendorff + */ +gTestfile = 'regress-530879'; +function f(a, b, c, d) { + yield arguments.length; +} +reportCompare(0, f().next(), "bug 530879"); From 6500db42b9467cf2c26b2846716cf548d49ad0c3 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Thu, 3 Dec 2009 18:48:45 -0800 Subject: [PATCH 022/179] Bug 532823: fix slot computation for JSOP_NAME accessing outer vars defined in trace entry frame, r=bz --- js/src/jstracer.cpp | 8 ++++++-- js/src/trace-test/tests/basic/bug532823.js | 23 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 js/src/trace-test/tests/basic/bug532823.js diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 05359832aa72..131782f1dfc4 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -3301,7 +3301,9 @@ GetFromClosure(JSContext* cx, JSObject* call, const ClosureVarInfo* cv, double* struct ArgClosureTraits { - static inline uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return fp->argc + slot; } + static inline uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return 2 + slot; } + + // See also UpvarArgTraits. static inline jsval* slots(JSStackFrame* fp) { return fp->argv; } private: ArgClosureTraits(); @@ -3316,7 +3318,9 @@ GetClosureArg(JSContext* cx, JSObject* callee, const ClosureVarInfo* cv, double* struct VarClosureTraits { static inline uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return slot; } - static inline jsval* slots(JSStackFrame* fp) { return fp->slots; } + + // See also UpvarVarTraits. + static inline jsval* slots(JSStackFrame* fp) { return 3 + fp->argc + fp->slots; } private: VarClosureTraits(); }; diff --git a/js/src/trace-test/tests/basic/bug532823.js b/js/src/trace-test/tests/basic/bug532823.js new file mode 100644 index 000000000000..c2b2dc6d5fbc --- /dev/null +++ b/js/src/trace-test/tests/basic/bug532823.js @@ -0,0 +1,23 @@ +function loop(f) { + var p; + for (var i = 0; i < 10; ++i) { + p = f(); + } + return p; +} + +function f(j, k) { + var g = function() { return k; } + + var ans = ''; + + for (k = 0; k < 5; ++k) { + ans += loop(g); + } + return ans; +} + +var t0 = new Date; +var actual = f(1); + +assertEq(actual, '01234'); From f0030b3d9b2ff89808f02edfc8e5456fd7ebd614 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 3 Dec 2009 22:43:13 -0500 Subject: [PATCH 023/179] Bug 532823 followup. Fix where we add the 3+fp->argc. r=brendan --- js/src/jstracer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 131782f1dfc4..17d862e8dd89 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -3301,6 +3301,7 @@ GetFromClosure(JSContext* cx, JSObject* call, const ClosureVarInfo* cv, double* struct ArgClosureTraits { + // See also UpvarArgTraits. static inline uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return 2 + slot; } // See also UpvarArgTraits. @@ -3317,10 +3318,11 @@ GetClosureArg(JSContext* cx, JSObject* callee, const ClosureVarInfo* cv, double* struct VarClosureTraits { - static inline uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return slot; } + // See also UpvarVarTraits. + static inline uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return 3 + fp->argc + slot; } // See also UpvarVarTraits. - static inline jsval* slots(JSStackFrame* fp) { return 3 + fp->argc + fp->slots; } + static inline jsval* slots(JSStackFrame* fp) { return fp->slots; } private: VarClosureTraits(); }; From da4e13efda5b26ad023b2cb496b7b266d3b9a026 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Thu, 3 Dec 2009 19:47:19 -0800 Subject: [PATCH 024/179] Add JSOP_ENUMELEM to gigundo-assert in LeaveTree (532787, r=me). --- js/src/jstracer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 131782f1dfc4..e12b6dc4025b 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -6661,7 +6661,7 @@ LeaveTree(InterpState& state, VMSideExit* lr) op == JSOP_GETLOCALPROP || op == JSOP_LENGTH || op == JSOP_GETELEM || op == JSOP_CALLELEM || op == JSOP_SETPROP || op == JSOP_SETNAME || op == JSOP_SETMETHOD || - op == JSOP_SETELEM || op == JSOP_INITELEM || + op == JSOP_SETELEM || op == JSOP_INITELEM || op == JSOP_ENUMELEM || op == JSOP_INSTANCEOF); /* From 7fc041981d1fa7a82df161f5d2e7dcd0b5b0f1cd Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 3 Dec 2009 23:03:46 -0500 Subject: [PATCH 025/179] Bug 530255. Replace GetFromClosure/GetClosureVar/GetClosureArg with hand-crafted LIR in the common easycase of a Call object whose frame is no longer active at record time, and make GetFromClosure use a direct read from the object's dslots if we discover that the frame became inactive between record and trace. r=dmandelin,brendan --- js/src/jsfun.h | 1 + js/src/jstracer.cpp | 155 ++++++++++++++++++++++++++++++++------------ 2 files changed, 116 insertions(+), 40 deletions(-) diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 5b44391237a9..77c49be8cdba 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -207,6 +207,7 @@ struct JSFunction : public JSObject { extern JSClass js_ArgumentsClass; extern JS_FRIEND_DATA(JSClass) js_CallClass; extern JSClass js_DeclEnvClass; +extern const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS; /* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */ extern JS_FRIEND_DATA(JSClass) js_FunctionClass; diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index b64db04c1c9b..9f5a177666ad 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -3232,10 +3232,10 @@ GetUpvarStackOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDe // Parameters needed to access a value from a closure on trace. struct ClosureVarInfo { - jsid id; uint32 slot; +#ifdef DEBUG uint32 callDepth; - uint32 resolveFlags; +#endif }; /* @@ -3286,13 +3286,15 @@ GetFromClosure(JSContext* cx, JSObject* call, const ClosureVarInfo* cv, double* if (fp) { v = T::slots(fp)[slot]; } else { - JS_ASSERT(cv->resolveFlags != JSRESOLVE_INFER); - JSAutoResolveFlags rf(cx, cv->resolveFlags); -#ifdef DEBUG - JSBool rv = -#endif - js_GetPropertyHelper(cx, call, cv->id, JSGET_METHOD_BARRIER, &v); - JS_ASSERT(rv); + /* + * Get the value from the object. We know we have a Call object, and + * that our slot index is fine, so don't monkey around with calling the + * property getter (which just looks in the slot) or calling + * js_GetReservedSlot. Just get the slot directly. Note the static + * asserts in jsfun.cpp which make sure Call objects use dslots. + */ + JS_ASSERT(slot < T::slot_count(call)); + v = T::slots(call)[slot]; } JSTraceType type = getCoercedType(v); ValueToNative(cx, v, type, result); @@ -3301,11 +3303,28 @@ GetFromClosure(JSContext* cx, JSObject* call, const ClosureVarInfo* cv, double* struct ArgClosureTraits { + // Adjust our slot to point to the correct slot on the native stack. // See also UpvarArgTraits. static inline uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return 2 + slot; } + // Get the right frame slots to use our slot index with. // See also UpvarArgTraits. static inline jsval* slots(JSStackFrame* fp) { return fp->argv; } + + // Get the right object slots to use our slot index with. + static inline jsval* slots(JSObject* obj) { + // We know Call objects use dslots. + return obj->dslots + slot_offset(obj); + } + // Get the offset of our object slots from the object's dslots pointer. + static inline uint32 slot_offset(JSObject* obj) { + return JSSLOT_START(&js_CallClass) + + CALL_CLASS_FIXED_RESERVED_SLOTS - JS_INITIAL_NSLOTS; + } + // Get the maximum slot index of this type that should be allowed + static inline uint16 slot_count(JSObject* obj) { + return js_GetCallObjectFunction(obj)->nargs; + } private: ArgClosureTraits(); }; @@ -3318,11 +3337,25 @@ GetClosureArg(JSContext* cx, JSObject* callee, const ClosureVarInfo* cv, double* struct VarClosureTraits { + // See documentation on ArgClosureTraits for what these functions + // should be doing. // See also UpvarVarTraits. static inline uint32 adj_slot(JSStackFrame* fp, uint32 slot) { return 3 + fp->argc + slot; } // See also UpvarVarTraits. static inline jsval* slots(JSStackFrame* fp) { return fp->slots; } + static inline jsval* slots(JSObject* obj) { + // We know Call objects use dslots. + return obj->dslots + slot_offset(obj); + } + static inline uint32 slot_offset(JSObject* obj) { + return JSSLOT_START(&js_CallClass) + + CALL_CLASS_FIXED_RESERVED_SLOTS - JS_INITIAL_NSLOTS + + js_GetCallObjectFunction(obj)->nargs; + } + static inline uint16 slot_count(JSObject* obj) { + return js_GetCallObjectFunction(obj)->u.i.nvars; + } private: VarClosureTraits(); }; @@ -7947,8 +7980,12 @@ TraceRecorder::scopeChainProp(JSObject* chainHead, jsval*& vp, LIns*& ins, NameR return ARECORD_CONTINUE; } - if (obj == obj2 && OBJ_GET_CLASS(cx, obj) == &js_CallClass) - return InjectStatus(callProp(obj, prop, ATOM_TO_JSID(atom), vp, ins, nr)); + if (obj == obj2 && OBJ_GET_CLASS(cx, obj) == &js_CallClass) { + AbortableRecordingStatus status = + InjectStatus(callProp(obj, prop, ATOM_TO_JSID(atom), vp, ins, nr)); + obj->dropProperty(cx, prop); + return status; + } obj2->dropProperty(cx, prop); RETURN_STOP_A("fp->scopeChain is not global or active call object"); @@ -7968,6 +8005,7 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, if (setflags && (sprop->attrs & JSPROP_READONLY)) RETURN_STOP("writing to a read-only property"); + JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); uintN slot = sprop->shortid; vp = NULL; @@ -7979,7 +8017,8 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, vp = &cfp->argv[slot]; upvar_slot = slot; nr.v = *vp; - } else if (sprop->getter == js_GetCallVar) { + } else if (sprop->getter == js_GetCallVar || + sprop->getter == js_GetCallVarChecked) { JS_ASSERT(slot < cfp->script->nslots); vp = &cfp->slots[slot]; upvar_slot = cx->fp->fun->nargs + slot; @@ -7987,7 +8026,6 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, } else { RETURN_STOP("dynamic property of Call object"); } - obj->dropProperty(cx, prop); if (frameIfInRange(obj)) { // At this point we are guaranteed to be looking at an active call oject @@ -8009,7 +8047,6 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, : JSGET_METHOD_BARRIER, &nr.v); JS_ASSERT(rv); - obj->dropProperty(cx, prop); } LIns* obj_ins; @@ -8017,34 +8054,62 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, LIns* parent_ins = stobj_get_parent(get(&cx->fp->argv[-2])); CHECK_STATUS(traverseScopeChain(parent, parent_ins, obj, obj_ins)); - ClosureVarInfo* cv = new (traceAlloc()) ClosureVarInfo(); - cv->id = id; - cv->slot = slot; - cv->callDepth = callDepth; - cv->resolveFlags = cx->resolveFlags == JSRESOLVE_INFER - ? js_InferFlags(cx, 0) - : cx->resolveFlags; + LIns* call_ins; + if (!cfp) { + // Because the parent guard in guardCallee ensures this Call object + // will be the same object now and on trace, and because once a Call + // object loses its frame it never regains one, on trace we will also + // have a null private in the Call object. So all we need to do is + // write the value to the Call object's slot. + int32 offset = slot; + if (sprop->getter == js_GetCallArg) { + JS_ASSERT(offset < ArgClosureTraits::slot_count(obj)); + offset += ArgClosureTraits::slot_offset(obj); + } else if (sprop->getter == js_GetCallVar || + sprop->getter == js_GetCallVarChecked) { + JS_ASSERT(offset < VarClosureTraits::slot_count(obj)); + offset += VarClosureTraits::slot_offset(obj); + } else { + RETURN_STOP("dynamic property of Call object"); + } - LIns* outp = lir->insAlloc(sizeof(double)); - LIns* args[] = { - outp, - INS_CONSTPTR(cv), - obj_ins, - cx_ins - }; - const CallInfo* ci; - if (sprop->getter == js_GetCallArg) - ci = &GetClosureArg_ci; - else - ci = &GetClosureVar_ci; + LIns* base = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots)); + LIns* val_ins = lir->insLoad(LIR_ldp, base, offset * sizeof(jsval)); + ins = unbox_jsval(obj->dslots[offset], val_ins, snapshot(BRANCH_EXIT)); + } + else { + ClosureVarInfo* cv = new (traceAlloc()) ClosureVarInfo(); + cv->slot = slot; +#ifdef DEBUG + cv->callDepth = callDepth; +#endif - LIns* call_ins = lir->insCall(ci, args); - JSTraceType type = getCoercedType(nr.v); - guard(true, - addName(lir->ins2(LIR_eq, call_ins, lir->insImm(type)), - "guard(type-stable name access)"), - BRANCH_EXIT); - ins = stackLoad(outp, type); + LIns* outp = lir->insAlloc(sizeof(double)); + LIns* args[] = { + outp, + INS_CONSTPTR(cv), + obj_ins, + cx_ins + }; + const CallInfo* ci; + if (sprop->getter == js_GetCallArg) { + ci = &GetClosureArg_ci; + } else if (sprop->getter == js_GetCallVar || + sprop->getter == js_GetCallVarChecked) { + ci = &GetClosureVar_ci; + } else { + RETURN_STOP("dynamic property of Call object"); + } + + call_ins = lir->insCall(ci, args); + + JSTraceType type = getCoercedType(nr.v); + guard(true, + addName(lir->ins2(LIR_eq, call_ins, lir->insImm(type)), + "guard(type-stable name access)"), + BRANCH_EXIT); + ins = stackLoad(outp, type); + } nr.tracked = false; nr.obj = obj; nr.obj_ins = obj_ins; @@ -12069,6 +12134,16 @@ TraceRecorder::guardCallee(jsval& callee) stobj_get_private(callee_ins), INS_CONSTPTR(callee_obj->getPrivate())), branchExit); + + /* + * As long as we have this parent guard, we're guaranteed that if we record + * with a Call object which has a null getPrivate(), then on trace that + * Call object will continue to have a null private, because we're + * effectively guarding on Call object identity and Call objects can't pick + * up a stack frame once they have none. callProp and setCallProp depend + * on this and document where; if this guard is removed make sure to fix + * those methods. Search for the "parent guard" comments in them. + */ guard(true, lir->ins2(LIR_peq, stobj_get_parent(callee_ins), From 4ef3c22c164517e78f98e9cabf17384a91f679bc Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 3 Dec 2009 23:03:47 -0500 Subject: [PATCH 026/179] Bug 532477. Replace js_SetCallArg/js_SetCallVar with hand-crafted LIR in the common easy case of a Call object whose frame is no longer active at record time. r=dmandelin,brendan --- js/src/jstracer.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 9f5a177666ad..010db9e704a7 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -11339,6 +11339,33 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty RETURN_STOP("can't trace special CallClass setter"); } + if (!callobj->getPrivate()) { + // Because the parent guard in guardCallee ensures this Call object + // will be the same object now and on trace, and because once a Call + // object loses its frame it never regains one, on trace we will also + // have a null private in the Call object. So all we need to do is + // write the value to the Call object's slot. + JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); + int32 offset = sprop->shortid; + if (sprop->setter == SetCallArg) { + JS_ASSERT(offset < ArgClosureTraits::slot_count(callobj)); + offset += ArgClosureTraits::slot_offset(callobj); + } else if (sprop->setter == SetCallVar) { + JS_ASSERT(offset < VarClosureTraits::slot_count(obj)); + offset += VarClosureTraits::slot_offset(callobj); + } else { + RETURN_STOP("can't trace special CallClass setter"); + } + + LIns* base = lir->insLoad(LIR_ldp, callobj_ins, offsetof(JSObject, dslots)); + lir->insStorei(box_jsval(v, v_ins), base, offset * sizeof(jsval)); + return RECORD_CONTINUE; + } + + // This is the hard case: we have a JSStackFrame private, but it's not in + // range. During trace execution we may or may not have a JSStackFrame + // anymore. Call the standard builtins, which handle that situation. + // Set variables in off-trace-stack call objects by calling standard builtins. const CallInfo* ci = NULL; if (sprop->setter == SetCallArg) From 820ab9924ced4e23d0818d8690a52f814a13c47f Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 3 Dec 2009 23:10:08 -0500 Subject: [PATCH 027/179] Bug 532477 followup to fix bustage. --- js/src/jstracer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 010db9e704a7..79c46ba76303 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -11351,7 +11351,7 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty JS_ASSERT(offset < ArgClosureTraits::slot_count(callobj)); offset += ArgClosureTraits::slot_offset(callobj); } else if (sprop->setter == SetCallVar) { - JS_ASSERT(offset < VarClosureTraits::slot_count(obj)); + JS_ASSERT(offset < VarClosureTraits::slot_count(callobj)); offset += VarClosureTraits::slot_offset(callobj); } else { RETURN_STOP("can't trace special CallClass setter"); From f6ebee8fe0b28e3c6c5472c4b41b04a22fcdad16 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 3 Dec 2009 23:35:36 -0500 Subject: [PATCH 028/179] Bug 530240 followup. Can't assume vp[1] is an object here, in fact. Fixes orange. --- js/src/jsstr.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 2f4124c6fbe5..d7534fdb2894 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -653,17 +653,20 @@ NormalizeThis(JSContext *cx, jsval *vp) /* * js_GetPrimitiveThis seems to do a bunch of work (like calls to * JS_THIS_OBJECT) which we don't need in the common case (where - * vp[1] is a String object) here. + * vp[1] is a String object) here. Note that vp[1] can still be a + * primitive value at this point. */ - JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1])); - JSObject *obj = JSVAL_TO_OBJECT(vp[1]); - if (obj->getClass() == &js_StringClass) { - str = JSVAL_TO_STRING(obj->fslots[JSSLOT_PRIMITIVE_THIS]); - } else { - str = js_ValueToString(cx, vp[1]); - if (!str) - return NULL; + if (!JSVAL_IS_PRIMITIVE(vp[1])) { + JSObject *obj = JSVAL_TO_OBJECT(vp[1]); + if (obj->getClass() == &js_StringClass) { + vp[1] = obj->fslots[JSSLOT_PRIMITIVE_THIS]; + return JSVAL_TO_STRING(vp[1]); + } } + + str = js_ValueToString(cx, vp[1]); + if (!str) + return NULL; vp[1] = STRING_TO_JSVAL(str); return str; } From 351c2588f689491350d9c2f09feda091545dd0a9 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 4 Dec 2009 01:08:22 -0500 Subject: [PATCH 029/179] Bug 532847. Can't assert that sprop has a shortid in callProp/setCallProp until we know the prop is special. r=brendan --- js/src/jstracer.cpp | 53 ++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 79c46ba76303..2d98bce14044 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -8005,8 +8005,7 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, if (setflags && (sprop->attrs & JSPROP_READONLY)) RETURN_STOP("writing to a read-only property"); - JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); - uintN slot = sprop->shortid; + uintN slot = uint16(sprop->shortid); vp = NULL; uintN upvar_slot = SPROP_INVALID_SLOT; @@ -8027,6 +8026,9 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, RETURN_STOP("dynamic property of Call object"); } + // Now assert that our use of sprop->shortid was in fact kosher. + JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); + if (frameIfInRange(obj)) { // At this point we are guaranteed to be looking at an active call oject // whose properties are stored in the corresponding JSStackFrame. @@ -8061,23 +8063,25 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, // object loses its frame it never regains one, on trace we will also // have a null private in the Call object. So all we need to do is // write the value to the Call object's slot. - int32 offset = slot; + int32 dslot_index = slot; if (sprop->getter == js_GetCallArg) { - JS_ASSERT(offset < ArgClosureTraits::slot_count(obj)); - offset += ArgClosureTraits::slot_offset(obj); + JS_ASSERT(dslot_index < ArgClosureTraits::slot_count(obj)); + dslot_index += ArgClosureTraits::slot_offset(obj); } else if (sprop->getter == js_GetCallVar || sprop->getter == js_GetCallVarChecked) { - JS_ASSERT(offset < VarClosureTraits::slot_count(obj)); - offset += VarClosureTraits::slot_offset(obj); + JS_ASSERT(dslot_index < VarClosureTraits::slot_count(obj)); + dslot_index += VarClosureTraits::slot_offset(obj); } else { RETURN_STOP("dynamic property of Call object"); } + // Now assert that our use of sprop->shortid was in fact kosher. + JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); + LIns* base = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots)); - LIns* val_ins = lir->insLoad(LIR_ldp, base, offset * sizeof(jsval)); - ins = unbox_jsval(obj->dslots[offset], val_ins, snapshot(BRANCH_EXIT)); - } - else { + LIns* val_ins = lir->insLoad(LIR_ldp, base, dslot_index * sizeof(jsval)); + ins = unbox_jsval(obj->dslots[dslot_index], val_ins, snapshot(BRANCH_EXIT)); + } else { ClosureVarInfo* cv = new (traceAlloc()) ClosureVarInfo(); cv->slot = slot; #ifdef DEBUG @@ -8101,6 +8105,9 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, RETURN_STOP("dynamic property of Call object"); } + // Now assert that our use of sprop->shortid was in fact kosher. + JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); + call_ins = lir->insCall(ci, args); JSTraceType type = getCoercedType(nr.v); @@ -11325,13 +11332,15 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty JSStackFrame *fp = frameIfInRange(callobj); if (fp) { if (sprop->setter == SetCallArg) { - jsint slot = JSVAL_TO_INT(SPROP_USERID(sprop)); + JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); + uintN slot = uint16(sprop->shortid); jsval *vp2 = &fp->argv[slot]; set(vp2, v_ins); return RECORD_CONTINUE; } if (sprop->setter == SetCallVar) { - jsint slot = JSVAL_TO_INT(SPROP_USERID(sprop)); + JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); + uintN slot = uint16(sprop->shortid); jsval *vp2 = &fp->slots[slot]; set(vp2, v_ins); return RECORD_CONTINUE; @@ -11345,20 +11354,24 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty // object loses its frame it never regains one, on trace we will also // have a null private in the Call object. So all we need to do is // write the value to the Call object's slot. - JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); - int32 offset = sprop->shortid; + int32 dslot_index = uint16(sprop->shortid); if (sprop->setter == SetCallArg) { - JS_ASSERT(offset < ArgClosureTraits::slot_count(callobj)); - offset += ArgClosureTraits::slot_offset(callobj); + JS_ASSERT(dslot_index < ArgClosureTraits::slot_count(callobj)); + dslot_index += ArgClosureTraits::slot_offset(callobj); } else if (sprop->setter == SetCallVar) { - JS_ASSERT(offset < VarClosureTraits::slot_count(callobj)); - offset += VarClosureTraits::slot_offset(callobj); + JS_ASSERT(dslot_index < VarClosureTraits::slot_count(callobj)); + dslot_index += VarClosureTraits::slot_offset(callobj); } else { RETURN_STOP("can't trace special CallClass setter"); } + // Now assert that the shortid get we did above was ok. Have to do it + // after the RETURN_STOP above, since in that case we may in fact not + // have a valid shortid; but we don't use it in that case anyway. + JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); + LIns* base = lir->insLoad(LIR_ldp, callobj_ins, offsetof(JSObject, dslots)); - lir->insStorei(box_jsval(v, v_ins), base, offset * sizeof(jsval)); + lir->insStorei(box_jsval(v, v_ins), base, dslot_index * sizeof(jsval)); return RECORD_CONTINUE; } From eb9d6d017aaf0d6e8d9f09d6ef85dcdde065d099 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Fri, 4 Dec 2009 13:46:52 -0800 Subject: [PATCH 030/179] Disable test for bug 354998 in browser debug builds. --- js/src/tests/e4x/Regress/jstests.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/tests/e4x/Regress/jstests.list b/js/src/tests/e4x/Regress/jstests.list index 331a3861fdb0..5a5793a1afb3 100644 --- a/js/src/tests/e4x/Regress/jstests.list +++ b/js/src/tests/e4x/Regress/jstests.list @@ -52,7 +52,7 @@ script regress-354145-03.js script regress-354145-04.js script regress-354145-05.js script regress-354145-07.js -script regress-354998.js +skip-if(!xulRuntime.shell&&isDebugBuild) script regress-354998.js # very slow; test needs revising script regress-355474-02.js script regress-355478.js script regress-355569.js From 059c6b337fe2694337d4761d3c57cc069614976b Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Fri, 4 Dec 2009 14:25:31 -0800 Subject: [PATCH 031/179] automation.py no longer needs to set this SMIL pref, since it is now the default. Bug 532997, r=dholbert --- build/automation.py.in | 1 - 1 file changed, 1 deletion(-) diff --git a/build/automation.py.in b/build/automation.py.in index 35b2be65967a..43b19c2b64f8 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -259,7 +259,6 @@ user_pref("network.manage-offline-status", false); user_pref("test.mousescroll", true); user_pref("security.default_personal_cert", "Select Automatically"); // Need to client auth test be w/o any dialogs user_pref("network.http.prompt-temp-redirect", false); -user_pref("svg.smil.enabled", true); // Needed for SMIL mochitests until bug 482402 lands user_pref("media.cache_size", 100); user_pref("security.warn_viewing_mixed", false); From cde2129b6ee1c94175056b34986cb6d690b3dd31 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Sun, 6 Dec 2009 16:07:56 -0800 Subject: [PATCH 032/179] b=532541; [webgl] drawElements needs to support ubyte as well as ushort index arrays; r=mwsteele --- content/canvas/src/WebGLContextGL.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 6fee5328f3fe..8e43416f7f43 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -605,7 +605,7 @@ WebGLContext::BufferSubData(GLenum target, GLsizeiptr offset) boundBuffer->Count(), offset, arrayBuf->NativeSize()); return NS_ERROR_FAILURE; } -#ifdef DEBUG +#ifdef DEBUG_mwsteele LogMessage("bufferSubData: buffer (%d) for data at offset (%d+%d)", boundBuffer->Count(), offset, arrayBuf->NativeSize()); #endif // all good @@ -621,7 +621,7 @@ WebGLContext::BufferSubData(GLenum target, GLsizeiptr offset) boundBuffer->Count(), offset, canvasArrayObj->NativeCount()); return NS_ERROR_FAILURE; } -#ifdef DEBUG +#ifdef DEBUG_mwsteele LogMessage("bufferSubData: buffer (%d) for data at offset (%d+%d)", boundBuffer->Count(), offset, canvasArrayObj->NativeSize()); #endif // all good @@ -991,6 +991,8 @@ WebGLContext::DrawArrays(GLenum mode, GLint offset, GLsizei count) NS_IMETHODIMP WebGLContext::DrawElements(GLenum mode, GLuint count, GLenum type, GLuint offset) { + int elementSize = 0; + switch (mode) { case LOCAL_GL_TRIANGLES: case LOCAL_GL_TRIANGLE_STRIP: @@ -1006,9 +1008,17 @@ WebGLContext::DrawElements(GLenum mode, GLuint count, GLenum type, GLuint offset switch (type) { case LOCAL_GL_UNSIGNED_SHORT: + elementSize = 2; + if (offset % 2 != 0) + return ErrorMessage("drawElements: invalid offset (must be a multiple of 2) for UNSIGNED_SHORT"); break; + + case LOCAL_GL_UNSIGNED_BYTE: + elementSize = 1; + break; + default: - return ErrorMessage("drawElements: type must be UNSIGNED_SHORT"); + return ErrorMessage("drawElements: type must be UNSIGNED_SHORT or UNSIGNED_BYTE"); } if (!mBoundElementArrayBuffer) @@ -1017,12 +1027,13 @@ WebGLContext::DrawElements(GLenum mode, GLuint count, GLenum type, GLuint offset if (offset+count < offset || offset+count < count) return ErrorMessage("glDrawElements: overflow in offset+count"); - if (count + offset > mBoundElementArrayBuffer->Count()) + if (count*elementSize + offset > mBoundElementArrayBuffer->ByteCount()) return ErrorMessage("glDrawElements: bound element array buffer is too small for given count and offset"); MakeContextCurrent(); // XXXmark fix validation + // XXX either GLushort or GLubyte; just put this calculation as a method on the array object #if 0 GLuint maxindex = 0; GLushort *ubuf = (GLushort*) gl->fMapBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER, LOCAL_GL_READ_ONLY); @@ -1040,7 +1051,7 @@ WebGLContext::DrawElements(GLenum mode, GLuint count, GLenum type, GLuint offset if (!ValidateBuffers(maxindex)) return ErrorMessage("glDrawElements: ValidateBuffers failed"); #endif - // XXX uh, is this offset, or offset * elementsize? + gl->fDrawElements(mode, count, type, (GLvoid*) (offset)); Invalidate(); From 7e80dba7f5f945f6bde3e42d99d009c27b4df44f Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Sun, 6 Dec 2009 16:07:58 -0800 Subject: [PATCH 033/179] b=523959; [webgl] enable WebGL with EGL on Maemo and WinCE; r=stuart --- configure.in | 21 +- content/canvas/src/Makefile.in | 46 ++-- content/canvas/src/WebGLContext.cpp | 16 +- content/canvas/src/WebGLContextGL.cpp | 23 +- content/canvas/src/glwrap.cpp | 7 +- content/canvas/src/glwrap.h | 6 +- content/canvas/src/localgl.h | 72 ++++++ content/canvas/src/nsGLPbuffer.h | 40 ++- content/canvas/src/nsGLPbufferEGL.cpp | 335 +++++++++++++++++++++++--- gfx/thebes/public/gfxXlibSurface.h | 10 +- gfx/thebes/src/gfxXlibSurface.cpp | 4 +- 11 files changed, 478 insertions(+), 102 deletions(-) diff --git a/configure.in b/configure.in index c6ad75e1c9a5..8c85b6a67409 100644 --- a/configure.in +++ b/configure.in @@ -4781,9 +4781,7 @@ photon) cairo-windows) MOZ_WIDGET_TOOLKIT=windows - if test -z "$WINCE"; then - MOZ_WEBGL=1 - fi + MOZ_WEBGL=1 ;; cairo-gtk2|cairo-gtk2-x11) @@ -4791,6 +4789,7 @@ cairo-gtk2|cairo-gtk2-x11) MOZ_ENABLE_GTK2=1 MOZ_ENABLE_XREMOTE=1 MOZ_WEBGL=1 + MOZ_WEBGL_GLX=1 AC_DEFINE(MOZ_X11) MOZ_X11=1 @@ -4804,7 +4803,7 @@ cairo-gtk2|cairo-gtk2-x11) cairo-gtk2-dfb) MOZ_WIDGET_TOOLKIT=gtk2 MOZ_ENABLE_GTK2=1 - MOZ_WEBGL=1 + MOZ_WEBGL= AC_DEFINE(MOZ_DFB) MOZ_DFB=1 @@ -6260,7 +6259,7 @@ if test $NS_OSSO; then fi AC_DEFINE(NS_OSSO) MOZ_GFX_OPTIMIZE_MOBILE=1 - MOZ_WEBGL= + MOZ_WEBGL_GLX= fi AC_SUBST(LIBOSSO_CFLAGS) AC_SUBST(LIBOSSO_LIBS) @@ -8100,14 +8099,12 @@ if test "$MOZ_X11"; then fi # MOZ_X11 dnl Check for headers, etc. needed by WebGL. -if test -n "$MOZ_WEBGL"; then - if test "$MOZ_WIDGET_TOOLKIT" = gtk2; then - AC_CHECK_HEADER(GL/glx.h) - if test "$ac_cv_header_GL_glx_h" != "yes"; then - AC_MSG_ERROR([Can't find header GL/glx.h for WebGL (install mesa-common-dev (Ubuntu), mesa-libGL-devel (Fedora), or Mesa (SuSE))]) - fi +if test -n "$MOZ_WEBGL_GLX"; then + AC_CHECK_HEADER(GL/glx.h) + if test "$ac_cv_header_GL_glx_h" != "yes"; then + AC_MSG_ERROR([Can't find header GL/glx.h for WebGL (install mesa-common-dev (Ubuntu), mesa-libGL-devel (Fedora), or Mesa (SuSE))]) fi -fi # MOZ_WEBGL +fi # MOZ_WEBGL_GLX fi # COMPILE_ENVIRONMENT if test "$USE_FC_FREETYPE"; then diff --git a/content/canvas/src/Makefile.in b/content/canvas/src/Makefile.in index bc0a1417f681..7e3d0636d954 100644 --- a/content/canvas/src/Makefile.in +++ b/content/canvas/src/Makefile.in @@ -57,6 +57,30 @@ CPPSRCS = \ ifdef MOZ_WEBGL +ifeq (1_1,$(MOZ_X11)_$(NS_OSSO)) +WEBGL_PLATFORM = EGL +DEFINES += -DUSE_GLES2 +endif + +ifeq (1_,$(MOZ_X11)_$(NS_OSSO)) +WEBGL_PLATFORM = GLX +EXTRA_DSO_LIBS += X11 +endif + + +ifeq (windows,$(MOZ_WIDGET_TOOLKIT)) +ifdef WINCE +WEBGL_PLATFORM = EGL +DEFINES += -DUSE_GLES2 +else +WEBGL_PLATFORM = WGL +endif +endif + +ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) +WEBGL_PLATFORM = CGL +endif + CPPSRCS += \ WebGLArrays.cpp \ WebGLContext.cpp \ @@ -70,26 +94,8 @@ CPPSRCS += \ SimpleBuffer.cpp \ $(NULL) -ifdef MOZ_X11 -EXTRA_DSO_LIBS += X11 -CPPSRCS += nsGLPbufferGLX.cpp -DEFINES += -DUSE_GLX -endif - -ifeq ($(MOZ_WIDGET_TOOLKIT),windows) -ifdef WINCE -CPPSRCS += nsGLPbufferEGL.cpp -DEFINES += -DUSE_EGL -else -CPPSRCS += nsGLPbufferWGL.cpp -DEFINES += -DUSE_WGL -endif -endif - -ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) -CPPSRCS += nsGLPbufferCGL.cpp -DEFINES += -DUSE_CGL -endif +CPPSRCS += nsGLPbuffer$(WEBGL_PLATFORM).cpp +DEFINES += -DUSE_$(WEBGL_PLATFORM) else diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index 8d804a15181c..1d13f611d5da 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -100,13 +100,13 @@ WebGLContext::SetCanvasElement(nsICanvasElement* aParentCanvas) LogMessage("Canvas 3D: creating PBuffer..."); if (!forceSoftware) { -#if defined(WINCE) +#if defined(USE_EGL) mGLPbuffer = new nsGLPbufferEGL(); -#elif defined(XP_WIN) +#elif defined(USE_WGL) mGLPbuffer = new nsGLPbufferWGL(); -#elif defined(XP_UNIX) && defined(MOZ_X11) +#elif defined(USE_GLX) mGLPbuffer = new nsGLPbufferGLX(); -#elif defined(XP_MACOSX) +#elif defined(USE_CGL) mGLPbuffer = new nsGLPbufferCGL(); #else mGLPbuffer = nsnull; @@ -253,14 +253,20 @@ WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f) nsRefPtr surf = mGLPbuffer->ThebesSurface(); if (!surf) return NS_OK; - // XXX we can optimize this on win32 at least, by creating an upside-down // DIB. nsRefPtr pat = new gfxPattern(surf); + +#if defined(USE_EGL) && defined(MOZ_X11) + if (getenv("IMAGE")) { +#endif gfxMatrix m; m.Translate(gfxPoint(0.0, mGLPbuffer->Height())); m.Scale(1.0, -1.0); pat->SetMatrix(m); +#if defined(USE_EGL) && defined(MOZ_X11) + } +#endif // XXX I don't want to use PixelSnapped here, but layout doesn't guarantee // pixel alignment for this stuff! diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 8e43416f7f43..96a6151bb44e 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -382,6 +382,8 @@ WebGLContext::BindBuffer(GLenum target, nsIWebGLBuffer *buffer) MakeContextCurrent(); + //printf ("BindBuffer0: %04x\n", gl->fGetError()); + if (target == LOCAL_GL_ARRAY_BUFFER) { mBoundArrayBuffer = wbuf; } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) { @@ -392,6 +394,8 @@ WebGLContext::BindBuffer(GLenum target, nsIWebGLBuffer *buffer) gl->fBindBuffer(target, wbuf ? wbuf->GLName() : 0); + //printf ("BindBuffer: %04x\n", gl->fGetError()); + return NS_OK; } @@ -981,8 +985,12 @@ WebGLContext::DrawArrays(GLenum mode, GLint offset, GLsizei count) MakeContextCurrent(); + //printf ("DrawArrays0: %04x\n", gl->fGetError()); + gl->fDrawArrays(mode, offset, count); + //printf ("DrawArrays: %04x\n", gl->fGetError()); + Invalidate(); return NS_OK; @@ -2038,7 +2046,6 @@ WebGLContext::GetUniform(nsIWebGLProgram *prog, GLint location) GLint uArraySize = 0; GLenum uType = 0; - fprintf (stderr, "GetUniform: program: %d location: %d\n", program, location); gl->fGetActiveUniform(program, location, 0, NULL, &uArraySize, &uType, NULL); if (uArraySize == 0) return NS_ERROR_FAILURE; @@ -2902,16 +2909,30 @@ WebGLContext::ValidateGL() // make sure that the opengl stuff that we need is supported GLint val = 0; + MakeContextCurrent(); + gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &val); mAttribBuffers.SetLength(val); + //fprintf(stderr, "GL_MAX_VERTEX_ATTRIBS: %d\n", val); + gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_UNITS, &val); mBound2DTextures.SetLength(val); mBoundCubeMapTextures.SetLength(val); + //fprintf(stderr, "GL_MAX_TEXTURE_UNITS: %d\n", val); + gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &val); mBoundColorFramebuffers.SetLength(val); +#ifdef DEBUG_vladimir + gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &val); + fprintf(stderr, "GL_IMPLEMENTATION_COLOR_READ_FORMAT: 0x%04x\n", val); + + gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, &val); + fprintf(stderr, "GL_IMPLEMENTATION_COLOR_READ_TYPE: 0x%04x\n", val); +#endif + #ifndef USE_GLES2 // gl_PointSize is always available in ES2 GLSL gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE); diff --git a/content/canvas/src/glwrap.cpp b/content/canvas/src/glwrap.cpp index d979e00546ae..8f6a221d5a02 100644 --- a/content/canvas/src/glwrap.cpp +++ b/content/canvas/src/glwrap.cpp @@ -50,11 +50,6 @@ #define MAX_SYMBOL_LENGTH 128 #define MAX_SYMBOL_NAMES 5 -#ifdef MOZ_X11 -#define GLX_GLXEXT_LEGACY -#include -#endif - bool LibrarySymbolLoader::OpenLibrary(const char *library) { @@ -333,8 +328,10 @@ GLES20Wrap::InitWithPrefix(const char *prefix, bool trygl) { (PRFuncPtr*) &fIsFramebuffer, { "IsFramebuffer", "IsFramebufferEXT", NULL } }, { (PRFuncPtr*) &fIsRenderbuffer, { "IsRenderbuffer", "IsRenderbufferEXT", NULL } }, { (PRFuncPtr*) &fRenderbufferStorage, { "RenderbufferStorage", "RenderbufferStorageEXT", NULL } }, +#if 0 { (PRFuncPtr*) &fMapBuffer, { "MapBuffer", NULL } }, { (PRFuncPtr*) &fUnmapBuffer, { "UnmapBuffer", NULL } }, +#endif { NULL, { NULL } }, diff --git a/content/canvas/src/glwrap.h b/content/canvas/src/glwrap.h index e852dfe9b248..a1934b669239 100644 --- a/content/canvas/src/glwrap.h +++ b/content/canvas/src/glwrap.h @@ -56,10 +56,6 @@ #define GLAPI #endif -#ifdef WINCE -#define USE_GLES2 -#endif - typedef char realGLboolean; class LibrarySymbolLoader @@ -301,10 +297,12 @@ public: PFNGLLINEWIDTHPROC fLineWidth; typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program); PFNGLLINKPROGRAMPROC fLinkProgram; +#if 0 typedef void * (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); PFNGLMAPBUFFERPROC fMapBuffer; typedef realGLboolean (GLAPIENTRY * PFNGLUNAMPBUFFERPROC) (GLenum target); PFNGLUNAMPBUFFERPROC fUnmapBuffer; +#endif typedef void (GLAPIENTRY * PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param); PFNGLPIXELSTOREIPROC fPixelStorei; typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat bias); diff --git a/content/canvas/src/localgl.h b/content/canvas/src/localgl.h index 1abc93caea9f..1773ea6ab73f 100644 --- a/content/canvas/src/localgl.h +++ b/content/canvas/src/localgl.h @@ -3025,6 +3025,9 @@ typedef PRInt32 GLintptr; #define LOCAL_GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC #define LOCAL_GL_WIN_swap_hint 1 +#define LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B + #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_DRAW_TO_BITMAP_ARB 0x2002 @@ -3087,4 +3090,73 @@ typedef PRInt32 GLintptr; #define WGL_SAMPLE_BUFFERS_ARB 0x2041 #define WGL_SAMPLES_ARB 0x2042 + +#define EGL_BUFFER_SIZE 0x3020 +#define EGL_ALPHA_SIZE 0x3021 +#define EGL_BLUE_SIZE 0x3022 +#define EGL_GREEN_SIZE 0x3023 +#define EGL_RED_SIZE 0x3024 +#define EGL_DEPTH_SIZE 0x3025 +#define EGL_STENCIL_SIZE 0x3026 +#define EGL_CONFIG_CAVEAT 0x3027 +#define EGL_CONFIG_ID 0x3028 +#define EGL_LEVEL 0x3029 +#define EGL_MAX_PBUFFER_HEIGHT 0x302A +#define EGL_MAX_PBUFFER_PIXELS 0x302B +#define EGL_MAX_PBUFFER_WIDTH 0x302C +#define EGL_NATIVE_RENDERABLE 0x302D +#define EGL_NATIVE_VISUAL_ID 0x302E +#define EGL_NATIVE_VISUAL_TYPE 0x302F +#define EGL_PRESERVED_RESOURCES 0x3030 +#define EGL_SAMPLES 0x3031 +#define EGL_SAMPLE_BUFFERS 0x3032 +#define EGL_SURFACE_TYPE 0x3033 +#define EGL_TRANSPARENT_TYPE 0x3034 +#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 +#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 +#define EGL_TRANSPARENT_RED_VALUE 0x3037 +#define EGL_NONE 0x3038 +#define EGL_BIND_TO_TEXTURE_RGB 0x3039 +#define EGL_BIND_TO_TEXTURE_RGBA 0x303A +#define EGL_MIN_SWAP_INTERVAL 0x303B +#define EGL_MAX_SWAP_INTERVAL 0x303C +#define EGL_LUMINANCE_SIZE 0x303D +#define EGL_ALPHA_MASK_SIZE 0x303E +#define EGL_COLOR_BUFFER_TYPE 0x303F +#define EGL_RENDERABLE_TYPE 0x3040 +#define EGL_MATCH_NATIVE_PIXMAP 0x3041 +#define EGL_CONFORMANT 0x3042 +#define EGL_OPENGL_ES_BIT 0x0001 +#define EGL_OPENVG_BIT 0x0002 +#define EGL_OPENGL_ES2_BIT 0x0004 +#define EGL_OPENGL_ES_API 0x30A0 +#define EGL_PBUFFER_BIT 0x0001 +#define EGL_PIXMAP_BIT 0x0002 +#define EGL_WINDOW_BIT 0x0004 +#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 +#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 +#define EGL_VENDOR 0x3053 +#define EGL_VERSION 0x3054 +#define EGL_EXTENSIONS 0x3055 +#define EGL_CLIENT_APIS 0x308D +#define EGL_HEIGHT 0x3056 +#define EGL_WIDTH 0x3057 +#define EGL_LARGEST_PBUFFER 0x3058 +#define EGL_TEXTURE_FORMAT 0x3080 +#define EGL_TEXTURE_TARGET 0x3081 +#define EGL_MIPMAP_TEXTURE 0x3082 +#define EGL_MIPMAP_LEVEL 0x3083 +#define EGL_RENDER_BUFFER 0x3086 +#define EGL_VG_COLORSPACE 0x3087 +#define EGL_VG_ALPHA_FORMAT 0x3088 +#define EGL_HORIZONTAL_RESOLUTION 0x3090 +#define EGL_VERTICAL_RESOLUTION 0x3091 +#define EGL_PIXEL_ASPECT_RATIO 0x3092 +#define EGL_SWAP_BEHAVIOR 0x3093 +#define EGL_MULTISAMPLE_RESOLVE 0x3099 +#define EGL_CONTEXT_CLIENT_TYPE 0x3097 +#define EGL_CONTEXT_CLIENT_VERSION 0x3098 +#define EGL_FALSE 0 +#define EGL_TRUE 1 + #endif diff --git a/content/canvas/src/nsGLPbuffer.h b/content/canvas/src/nsGLPbuffer.h index b2fce87e6a5e..03b24da7091e 100644 --- a/content/canvas/src/nsGLPbuffer.h +++ b/content/canvas/src/nsGLPbuffer.h @@ -48,21 +48,35 @@ #include "gfxASurface.h" #include "gfxImageSurface.h" -#if defined(WINCE) -#include -#include "gfxDDrawSurface.h" +#ifdef USE_EGL +typedef int EGLint; +typedef unsigned int EGLBoolean; +typedef unsigned int EGLenum; +typedef void *EGLConfig; +typedef void *EGLContext; +typedef void *EGLDisplay; +typedef void *EGLSurface; +typedef void *EGLClientBuffer; #endif -#if defined(XP_WIN) +#ifdef XP_WIN #include "gfxWindowsSurface.h" #endif -#if defined(XP_UNIX) && defined(MOZ_X11) +#ifdef MOZ_X11 +#include "gfxXlibSurface.h" +#endif + +#if defined(WINCE) && defined(CAIRO_HAS_DDRAW_SURFACE) +#include "gfxDDrawSurface.h" +#endif + +#ifdef USE_GLX #define GLX_GLXEXT_LEGACY #include "GL/glx.h" #endif -#ifdef XP_MACOSX +#ifdef USE_CGL #include "gfxQuartzImageSurface.h" #include #endif @@ -126,7 +140,7 @@ protected: PrivateOSMesaContext mMesaContext; }; -#ifdef XP_MACOSX +#ifdef USE_CGL class nsGLPbufferCGL : public nsGLPbuffer { @@ -161,7 +175,7 @@ protected: }; #endif -#if defined(XP_UNIX) && defined(MOZ_X11) +#ifdef USE_GLX class nsGLPbufferGLX : public nsGLPbuffer { @@ -188,7 +202,7 @@ protected: }; #endif -#if defined(WINCE) +#ifdef USE_EGL class nsGLPbufferEGL : public nsGLPbuffer { @@ -211,12 +225,18 @@ protected: EGLSurface mSurface; EGLContext mContext; +#if defined(XP_WIN) nsRefPtr mThebesSurface; nsRefPtr mWindowsSurface; +#elif defined(MOZ_X11) + nsRefPtr mThebesSurface; + nsRefPtr mXlibSurface; + Visual *mVisual; +#endif }; #endif -#if defined(XP_WIN) && !defined(WINCE) +#ifdef USE_WGL class nsGLPbufferWGL : public nsGLPbuffer { diff --git a/content/canvas/src/nsGLPbufferEGL.cpp b/content/canvas/src/nsGLPbufferEGL.cpp index f77b65ccb92f..a850578bfbfc 100644 --- a/content/canvas/src/nsGLPbufferEGL.cpp +++ b/content/canvas/src/nsGLPbufferEGL.cpp @@ -37,87 +37,275 @@ * ***** END LICENSE BLOCK ***** */ // this must be first, else windows.h breaks us -#include "nsICanvasRenderingContextGL.h" +#include "WebGLContext.h" +#include "nsGLPbuffer.h" #include "nsDirectoryServiceUtils.h" #include "nsAppDirectoryServiceDefs.h" #include "nsIPrefService.h" -#include "nsGLPbuffer.h" -#include "nsCanvasRenderingContextGL.h" - #include "gfxContext.h" #include "glwrap.h" -#include -#include -#include -#include +#ifdef MOZ_X11 +#include + +typedef Display* EGLNativeDisplayType; +typedef Window EGLNativeWindowType; +typedef Pixmap EGLNativePixmapType; +#endif + +#ifdef WINCE +typedef HDC EGLNativeDisplayType; +typedef HWND EGLNativeWindowType; +typedef HDC EGLNativePixmapType; +#endif + +// some EGL defines +#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) +#define EGL_NO_CONTEXT ((EGLContext)0) +#define EGL_NO_DISPLAY ((EGLDisplay)0) +#define EGL_NO_SURFACE ((EGLSurface)0) + +using namespace mozilla; static PRUint32 gActiveBuffers = 0; +class EGLWrap + : public LibrarySymbolLoader +{ +public: + EGLWrap() : fGetCurrentContext(0) { } + + bool Init(); + +public: + typedef EGLDisplay (*pfnGetDisplay)(void *display_id); + pfnGetDisplay fGetDisplay; + typedef EGLContext (*pfnGetCurrentContext)(void); + pfnGetCurrentContext fGetCurrentContext; + typedef EGLBoolean (*pfnMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); + pfnMakeCurrent fMakeCurrent; + typedef EGLBoolean (*pfnDestroyContext)(EGLDisplay dpy, EGLContext ctx); + pfnDestroyContext fDestroyContext; + typedef EGLContext (*pfnCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); + pfnCreateContext fCreateContext; + typedef EGLBoolean (*pfnDestroySurface)(EGLDisplay dpy, EGLSurface surface); + pfnDestroySurface fDestroySurface; + typedef EGLSurface (*pfnCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); + pfnCreatePbufferSurface fCreatePbufferSurface; + typedef EGLSurface (*pfnCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list); + pfnCreatePixmapSurface fCreatePixmapSurface; + typedef EGLBoolean (*pfnBindAPI)(EGLenum api); + pfnBindAPI fBindAPI; + typedef EGLBoolean (*pfnInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor); + pfnInitialize fInitialize; + typedef EGLBoolean (*pfnChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); + pfnChooseConfig fChooseConfig; + typedef EGLint (*pfnGetError)(void); + pfnGetError fGetError; + typedef EGLBoolean (*pfnGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); + pfnGetConfigAttrib fGetConfigAttrib; + typedef EGLBoolean (*pfnGetConfigs)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); + pfnGetConfigs fGetConfigs; + typedef EGLBoolean (*pfnWaitNative)(EGLint engine); + pfnWaitNative fWaitNative; +}; + +bool +EGLWrap::Init() +{ + if (fGetDisplay) + return true; + + SymLoadStruct symbols[] = { + { (PRFuncPtr*) &fGetDisplay, { "eglGetDisplay", NULL } }, + { (PRFuncPtr*) &fGetCurrentContext, { "eglGetCurrentContext", NULL } }, + { (PRFuncPtr*) &fMakeCurrent, { "eglMakeCurrent", NULL } }, + { (PRFuncPtr*) &fDestroyContext, { "eglDestroyContext", NULL } }, + { (PRFuncPtr*) &fCreateContext, { "eglCreateContext", NULL } }, + { (PRFuncPtr*) &fDestroySurface, { "eglDestroySurface", NULL } }, + { (PRFuncPtr*) &fCreatePbufferSurface, { "eglCreatePbufferSurface", NULL } }, + { (PRFuncPtr*) &fCreatePixmapSurface, { "eglCreatePixmapSurface", NULL } }, + { (PRFuncPtr*) &fBindAPI, { "eglBindAPI", NULL } }, + { (PRFuncPtr*) &fInitialize, { "eglInitialize", NULL } }, + { (PRFuncPtr*) &fChooseConfig, { "eglChooseConfig", NULL } }, + { (PRFuncPtr*) &fGetError, { "eglGetError", NULL } }, + { (PRFuncPtr*) &fGetConfigs, { "eglGetConfigs", NULL } }, + { (PRFuncPtr*) &fGetConfigAttrib, { "eglGetConfigAttrib", NULL } }, + { (PRFuncPtr*) &fWaitNative, { "eglWaitNative", NULL } }, + { NULL, { NULL } } + }; + + return LoadSymbols(&symbols[0], true); +} + +static EGLWrap gEGLWrap; + nsGLPbufferEGL::nsGLPbufferEGL() : mDisplay(0), mConfig(0), mSurface(0) { gActiveBuffers++; - fprintf (stderr, "nsGLPbufferEGL: gActiveBuffers: %d\n", gActiveBuffers); } +#ifdef WINCE +// XXX wrong +#define EGL_LIB "\\windows\\libEGL.dll" +#define GLES2_LIB "\\windows\\libGLESv2.dll" +#else +#define EGL_LIB "/usr/lib/libEGL.so" +#define GLES2_LIB "/usr/lib/libGLESv2.so" +#endif + PRBool -nsGLPbufferEGL::Init(nsCanvasRenderingContextGLPrivate *priv) +nsGLPbufferEGL::Init(mozilla::WebGLContext *priv) { mPriv = priv; - nsresult rv; +#ifdef NS_OSSO + // Maemo has missing DSO dependencies on their OpenGL libraries; + // so ensure that the prerequisite libs are loaded in the process + // before loading GL. An alternate approach is to use LD_PRELOAD. - mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + // We'll just leak these libs; pvr_um.so seems to have been + // present on an older OS image, and now pvr2d.so is used. + PRLibSpec lspec; + lspec.type = PR_LibSpec_Pathname; - if (!eglInitialize(mDisplay, NULL, NULL)) { - LogMessage(NS_LITERAL_CSTRING("egl init failed")); + lspec.value.pathname = "/usr/lib/libpvr_um.so"; + PR_LoadLibraryWithFlags(lspec, PR_LD_LAZY | PR_LD_GLOBAL); + + lspec.value.pathname = "/usr/lib/libpvr2d.so"; + PR_LoadLibraryWithFlags(lspec, PR_LD_LAZY | PR_LD_GLOBAL); +#endif + + if (!gEGLWrap.OpenLibrary(EGL_LIB)) { + LogMessage("egl OpenLibrary failed"); return PR_FALSE; } - eglBindAPI (EGL_OPENGL_ES_API); + if (!gEGLWrap.Init()) { + LogMessage("eglWrap init failed"); + return PR_FALSE; + } + mDisplay = gEGLWrap.fGetDisplay(0); + + if (!gEGLWrap.fInitialize(mDisplay, NULL, NULL)) { + LogMessage("egl init failed"); + return PR_FALSE; + } + + gEGLWrap.fBindAPI (EGL_OPENGL_ES_API); + +#if defined(MOZ_X11) && defined(NS_OSSO) EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, -#if 0 + EGL_SURFACE_TYPE, EGL_PIXMAP_BIT, EGL_RED_SIZE, 3, EGL_GREEN_SIZE, 3, EGL_BLUE_SIZE, 3, - /* EGL_ALPHA_SIZE, 3, */ + EGL_ALPHA_SIZE, 3, EGL_DEPTH_SIZE, 1, -#endif EGL_NONE }; - EGLConfig cfg; EGLint ncfg = 0; + EGLConfig cfg; - if (!eglChooseConfig(mDisplay, attribs, &cfg, 1, &ncfg) || - ncfg != 1) + if (!gEGLWrap.fChooseConfig(mDisplay, attribs, &cfg, 1, &ncfg) || + ncfg < 1) { - LogMessage(NS_LITERAL_CSTRING("Canvas 3D: eglChooseConfig failed")); + LogMessage("Canvas 3D: eglChooseConfig failed (ncfg: %d err: 0x%04x)", ncfg, gEGLWrap.fGetError()); return PR_FALSE; } - mConfig = cfg; + EGLint visid; + gEGLWrap.fGetConfigAttrib(mDisplay, cfg, EGL_NATIVE_VISUAL_ID, &visid); + + XVisualInfo vinfo; + vinfo.visualid = visid; + int pad; + + LogMessage("Visual ID: %d\n", visid); + + XVisualInfo *vf = XGetVisualInfo(gdk_x11_get_default_xdisplay(), VisualIDMask, &vinfo, &pad); + + if (!vf) { + LogMessage("Null VisualInfo!"); + return PR_FALSE; + } + + LogMessage("Visual: 0x%08x\n", vf->visual); + + mVisual = vf->visual; + mConfig = cfg; +#elif defined(WINCE) +#define MAX_CONFIGS 32 + EGLConfig configs[MAX_CONFIGS]; + EGLint numConfigs; + + gEGLWrap.fGetConfigs(mDisplay, configs, MAX_CONFIGS, &numConfigs); + + mConfig = 0; + + for (int i = 0; i < numConfigs; ++i) { + EGLint id; + EGLint surfaces, renderables; + EGLint rsize, gsize, bsize, asize, dsize; + + gEGLWrap.fGetConfigAttrib(mDisplay, configs[i], EGL_CONFIG_ID, &id); + gEGLWrap.fGetConfigAttrib(mDisplay, configs[i], EGL_SURFACE_TYPE, &surfaces); + gEGLWrap.fGetConfigAttrib(mDisplay, configs[i], EGL_RENDERABLE_TYPE, &renderables); + gEGLWrap.fGetConfigAttrib(mDisplay, configs[i], EGL_RED_SIZE, &rsize); + gEGLWrap.fGetConfigAttrib(mDisplay, configs[i], EGL_GREEN_SIZE, &gsize); + gEGLWrap.fGetConfigAttrib(mDisplay, configs[i], EGL_BLUE_SIZE, &bsize); + gEGLWrap.fGetConfigAttrib(mDisplay, configs[i], EGL_ALPHA_SIZE, &asize); + gEGLWrap.fGetConfigAttrib(mDisplay, configs[i], EGL_DEPTH_SIZE, &dsize); + +#ifdef DEBUG_vladimir + fprintf(stderr, "config 0x%02x: s %x api %x rgba %d %d %d %d d %d\n", id, surfaces, renderables, rsize, gsize, bsize, asize, dsize); +#endif + + if ((surfaces & EGL_PBUFFER_BIT) && + (renderables & EGL_OPENGL_ES2_BIT) && + (rsize > 3) && + (gsize > 3) && + (bsize > 3) && + (asize > 3) && + (dsize > 1)) + { + mConfig = configs[i]; + break; + } + } + + if (mConfig == 0) { + LogMessage("Failed to find config!"); + return PR_FALSE; + } +#else +#error need some boilerplate code for EGL +#endif + + LogMessage("Resize 2,2"); Resize(2, 2); - if (!mGLWrap.OpenLibrary("\\windows\\libglesv2.dll")) { - LogMessage(NS_LITERAL_CSTRING("Canvas 3D: Couldn't open opengl lib [1]")); + LogMessage("OpenLibrary"); + if (!mGLWrap.OpenLibrary(GLES2_LIB)) { + LogMessage("Canvas 3D: Couldn't open EGL lib [1]"); return PR_FALSE; } + LogMessage("GLWrap.Init"); if (!mGLWrap.Init(GLES20Wrap::TRY_NATIVE_GL)) { - LogMessage(NS_LITERAL_CSTRING("Canvas 3D: GLWrap init failed")); + LogMessage("Canvas 3D: GLWrap init failed"); return PR_FALSE; } - + LogMessage("Init done"); return PR_TRUE; } @@ -130,12 +318,19 @@ nsGLPbufferEGL::Resize(PRInt32 width, PRInt32 height) return PR_TRUE; } + LogMessage("Resize %d %d start", width, height); + Destroy(); + LogMessage("Destroyed"); + +#ifdef XP_WIN mWindowsSurface = new gfxWindowsSurface(gfxIntSize(width, height), gfxASurface::ImageFormatARGB32); if (mWindowsSurface->CairoStatus() != 0) { +#ifdef DEBUG_vladimir fprintf (stderr, "image surface failed\n"); +#endif return PR_FALSE; } @@ -147,20 +342,56 @@ nsGLPbufferEGL::Resize(PRInt32 width, PRInt32 height) EGL_NONE }; - mSurface = eglCreatePbufferSurface(mDisplay, mConfig, attrs); + mSurface = gEGLWrap.fCreatePbufferSurface(mDisplay, mConfig, attrs); if (!mSurface) { - LogMessage(NS_LITERAL_CSTRING("Canvas 3D: eglCreatePbufferSurface failed")); + LogMessage("Canvas 3D: eglCreatePbufferSurface failed"); + return PR_FALSE; + } +#else + + mXlibSurface = new gfxXlibSurface(gdk_x11_get_default_xdisplay(), + mVisual, + gfxIntSize(width, height), + 32); + if (!mXlibSurface || mXlibSurface->CairoStatus() != 0) { +#ifdef DEBUG_vladimir + fprintf (stderr, "Failed to create gfxXlibSurface"); +#endif return PR_FALSE; } - eglBindAPI(EGL_OPENGL_ES_API); + LogMessage("Created gfxXlibSurface, Drawable: 0x%08x", mXlibSurface->XDrawable()); + + // we need to XSync to ensure that the Pixmap is created on the server side, + // otherwise eglCreatePixmapSurface will fail (because it isn't part of the normal + // X protocol). + XSync(gdk_x11_get_default_xdisplay(), 0); + + EGLint attrs[] = { + EGL_NONE + }; + + Pixmap px = (Pixmap) mXlibSurface->XDrawable(); + + mSurface = gEGLWrap.fCreatePixmapSurface(mDisplay, mConfig, (EGLNativePixmapType) px, attrs); + if (!mSurface) { +#ifdef DEBUG_vladimir + fprintf (stderr, "Failed to create Pixmap EGLSurface\n"); +#endif + return PR_FALSE; + } + + LogMessage("mSurface: %p", mSurface); +#endif + + gEGLWrap.fBindAPI(EGL_OPENGL_ES_API); EGLint cxattrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - mContext = eglCreateContext(mDisplay, mConfig, EGL_NO_CONTEXT, cxattrs); + mContext = gEGLWrap.fCreateContext(mDisplay, mConfig, EGL_NO_CONTEXT, cxattrs); if (!mContext) { Destroy(); return PR_FALSE; @@ -169,7 +400,10 @@ nsGLPbufferEGL::Resize(PRInt32 width, PRInt32 height) mWidth = width; mHeight = height; - fprintf (stderr, "Resize: %d %d\n", width, height); +#ifdef MOZ_X11 + mThebesSurface = new gfxImageSurface(gfxIntSize(width, height), gfxASurface::ImageFormatARGB32); +#endif + return PR_TRUE; } @@ -177,17 +411,27 @@ void nsGLPbufferEGL::Destroy() { if (mContext) { - eglDestroyContext(mDisplay, mContext); + gEGLWrap.fDestroyContext(mDisplay, mContext); mContext = 0; } if (mSurface) { - eglDestroySurface(mDisplay, mSurface); + gEGLWrap.fDestroySurface(mDisplay, mSurface); mSurface = 0; } sCurrentContextToken = nsnull; + + // leak this +#ifdef MOZ_X11 + NS_IF_ADDREF(mXlibSurface.get()); + mXlibSurface = nsnull; +#else + mWindowsSurface = nsnull; +#endif + mThebesSurface = nsnull; + } nsGLPbufferEGL::~nsGLPbufferEGL() @@ -195,17 +439,16 @@ nsGLPbufferEGL::~nsGLPbufferEGL() Destroy(); gActiveBuffers--; - fprintf (stderr, "nsGLPbufferEGL: gActiveBuffers: %d\n", gActiveBuffers); fflush (stderr); } void nsGLPbufferEGL::MakeContextCurrent() { - if (eglGetCurrentContext() == mContext) + if (gEGLWrap.fGetCurrentContext() == mContext) return; - eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); + gEGLWrap.fMakeCurrent(mDisplay, mSurface, mSurface, mContext); } void @@ -213,7 +456,15 @@ nsGLPbufferEGL::SwapBuffers() { // eglCopyBuffers(mDisplay, mSurface, mWindowsSurface->GetDC()); MakeContextCurrent(); - mGLWrap.fReadPixels (0, 0, mWidth, mHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, mThebesSurface->Data()); + + //printf ("SwapBuffers0: %04x\n", mGLWrap.fGetError()); + + // this is wrong, we need to figure out a way to swap this, but we don't do anything here + mGLWrap.fFinish (); + + mGLWrap.fReadPixels (0, 0, mWidth, mHeight, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, mThebesSurface->Data()); + + //printf ("SwapBuffers: %04x\n", mGLWrap.fGetError()); #if 0 // premultiply the image @@ -226,5 +477,11 @@ nsGLPbufferEGL::SwapBuffers() gfxASurface* nsGLPbufferEGL::ThebesSurface() { +#if defined(MOZ_X11) && defined(NS_OSSO) + if (getenv("IMAGE")) + return mThebesSurface; + return mXlibSurface; +#elif defined(WINCE) return mThebesSurface; +#endif } diff --git a/gfx/thebes/public/gfxXlibSurface.h b/gfx/thebes/public/gfxXlibSurface.h index 078dc73b9168..9dfdccce4d5b 100644 --- a/gfx/thebes/public/gfxXlibSurface.h +++ b/gfx/thebes/public/gfxXlibSurface.h @@ -54,10 +54,12 @@ public: // with explicitly provided width/height. gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual, const gfxIntSize& size); - // create a new Pixmap on the display dpy, with - // the root window as the parent and the default depth - // for the default screen, and attach the given visual - gfxXlibSurface(Display *dpy, Visual *visual, const gfxIntSize& size); + // create a new Pixmap on the display dpy, with the root window as + // the parent and the default depth for the default screen, and + // attach the given visual. The depth argument is optional, and + // if not specified (or 0), the default depth of the default + // screen of dpy is used. + gfxXlibSurface(Display *dpy, Visual *visual, const gfxIntSize& size, int depth = 0); gfxXlibSurface(Display* dpy, Drawable drawable, XRenderPictFormat *format, const gfxIntSize& size); diff --git a/gfx/thebes/src/gfxXlibSurface.cpp b/gfx/thebes/src/gfxXlibSurface.cpp index dc2a19f6b9f6..356acf1732b5 100644 --- a/gfx/thebes/src/gfxXlibSurface.cpp +++ b/gfx/thebes/src/gfxXlibSurface.cpp @@ -71,7 +71,7 @@ gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual, Init(surf); } -gfxXlibSurface::gfxXlibSurface(Display *dpy, Visual *visual, const gfxIntSize& size) +gfxXlibSurface::gfxXlibSurface(Display *dpy, Visual *visual, const gfxIntSize& size, int depth) : mPixmapTaken(PR_FALSE), mDisplay(dpy), mSize(size) { @@ -81,7 +81,7 @@ gfxXlibSurface::gfxXlibSurface(Display *dpy, Visual *visual, const gfxIntSize& s mDrawable = (Drawable)XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), mSize.width, mSize.height, - DefaultDepth(dpy, DefaultScreen(dpy))); + depth ? depth : DefaultDepth(dpy, DefaultScreen(dpy))); cairo_surface_t *surf = cairo_xlib_surface_create(dpy, mDrawable, visual, mSize.width, mSize.height); From 8fadba32e8b6bc0eccf7ca1b71bc58a89961cbbd Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Sun, 6 Dec 2009 16:54:07 -0800 Subject: [PATCH 034/179] Add crashtests for several bugs --- gfx/thebes/crashtests/334735-1.html | 11 +++++++ gfx/thebes/crashtests/crashtests.list | 1 + layout/generic/crashtests/499857-1.html | 33 +++++++++++++++++++ layout/generic/crashtests/513394-1.html | 16 +++++++++ layout/generic/crashtests/crashtests.list | 2 ++ layout/xul/base/src/crashtests/508927-2.xul | 6 ++++ .../xul/base/src/crashtests/crashtests.list | 1 + .../htmlparser/tests/crashtests/515278-1.html | 3 ++ .../htmlparser/tests/crashtests/522326-1.html | 1 + .../tests/crashtests/crashtests.list | 2 ++ 10 files changed, 76 insertions(+) create mode 100644 gfx/thebes/crashtests/334735-1.html create mode 100644 layout/generic/crashtests/499857-1.html create mode 100644 layout/generic/crashtests/513394-1.html create mode 100644 layout/xul/base/src/crashtests/508927-2.xul create mode 100644 parser/htmlparser/tests/crashtests/515278-1.html create mode 100644 parser/htmlparser/tests/crashtests/522326-1.html diff --git a/gfx/thebes/crashtests/334735-1.html b/gfx/thebes/crashtests/334735-1.html new file mode 100644 index 000000000000..f1a2c04a5a46 --- /dev/null +++ b/gfx/thebes/crashtests/334735-1.html @@ -0,0 +1,11 @@ + + + +demo 1 + + +These unusual characters, 􀂉, +cause Firefox to crash 􀂉 + + + \ No newline at end of file diff --git a/gfx/thebes/crashtests/crashtests.list b/gfx/thebes/crashtests/crashtests.list index 7d26b46f6386..89219a85c980 100644 --- a/gfx/thebes/crashtests/crashtests.list +++ b/gfx/thebes/crashtests/crashtests.list @@ -6,6 +6,7 @@ load 206561-1.html load 248518-1.html load 306649-1.xml load 333861-1.html +load 334735-1.html load 345576-1.html load 345629-1.html load 369688-1.html diff --git a/layout/generic/crashtests/499857-1.html b/layout/generic/crashtests/499857-1.html new file mode 100644 index 000000000000..f105e1b394bf --- /dev/null +++ b/layout/generic/crashtests/499857-1.html @@ -0,0 +1,33 @@ + + + + + + + + + +
+a b c d
+ + diff --git a/layout/generic/crashtests/513394-1.html b/layout/generic/crashtests/513394-1.html new file mode 100644 index 000000000000..7296695d7dcb --- /dev/null +++ b/layout/generic/crashtests/513394-1.html @@ -0,0 +1,16 @@ + + + + + + +
+ + diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index 67534c05d47e..75e2f02abdcb 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -271,10 +271,12 @@ load 494300-1.xul load 494332-1.html load 495875-1.html load 495875-2.html +load 499857-1.html load 501535-1.html load 503961-1.xhtml load 503961-2.html load 508908-1.html load 505912-1.html load 511482.html +load 513394-1.html load 517968.html diff --git a/layout/xul/base/src/crashtests/508927-2.xul b/layout/xul/base/src/crashtests/508927-2.xul new file mode 100644 index 000000000000..5bf4f9a0c775 --- /dev/null +++ b/layout/xul/base/src/crashtests/508927-2.xul @@ -0,0 +1,6 @@ + + + + + + diff --git a/layout/xul/base/src/crashtests/crashtests.list b/layout/xul/base/src/crashtests/crashtests.list index 850eabf89144..14b720a86df3 100644 --- a/layout/xul/base/src/crashtests/crashtests.list +++ b/layout/xul/base/src/crashtests/crashtests.list @@ -64,3 +64,4 @@ load 475133.html load 488210-1.xhtml load 495728-1.xul load 508927-1.xul +load 508927-2.xul diff --git a/parser/htmlparser/tests/crashtests/515278-1.html b/parser/htmlparser/tests/crashtests/515278-1.html new file mode 100644 index 000000000000..33e01f2224a0 --- /dev/null +++ b/parser/htmlparser/tests/crashtests/515278-1.html @@ -0,0 +1,3 @@ + + + diff --git a/parser/htmlparser/tests/crashtests/522326-1.html b/parser/htmlparser/tests/crashtests/522326-1.html new file mode 100644 index 000000000000..d06ab6cf7def --- /dev/null +++ b/parser/htmlparser/tests/crashtests/522326-1.html @@ -0,0 +1 @@ +abcd diff --git a/parser/htmlparser/tests/crashtests/crashtests.list b/parser/htmlparser/tests/crashtests/crashtests.list index e0bc87254d74..357636ff2e89 100644 --- a/parser/htmlparser/tests/crashtests/crashtests.list +++ b/parser/htmlparser/tests/crashtests/crashtests.list @@ -35,4 +35,6 @@ load 408939-1.html load 423373-1.html skip load 460706-1.xhtml # Bug 479499 load 468538-1.xhtml +load 515278-1.html load 515816-1.html +load 522326-1.html From f2543149d643171f3b2b8632abae47b4492c3554 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Sun, 6 Dec 2009 16:54:34 -0800 Subject: [PATCH 035/179] Crashtest for bug 509602 --- .../src/tree/src/crashtests/509602-1-overlay.xul | 12 ++++++++++++ layout/xul/base/src/tree/src/crashtests/509602-1.xul | 3 +++ .../xul/base/src/tree/src/crashtests/crashtests.list | 1 + 3 files changed, 16 insertions(+) create mode 100644 layout/xul/base/src/tree/src/crashtests/509602-1-overlay.xul create mode 100644 layout/xul/base/src/tree/src/crashtests/509602-1.xul diff --git a/layout/xul/base/src/tree/src/crashtests/509602-1-overlay.xul b/layout/xul/base/src/tree/src/crashtests/509602-1-overlay.xul new file mode 100644 index 000000000000..f5cecd40ed92 --- /dev/null +++ b/layout/xul/base/src/tree/src/crashtests/509602-1-overlay.xul @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/layout/xul/base/src/tree/src/crashtests/509602-1.xul b/layout/xul/base/src/tree/src/crashtests/509602-1.xul new file mode 100644 index 000000000000..a1cdcf1ccc1d --- /dev/null +++ b/layout/xul/base/src/tree/src/crashtests/509602-1.xul @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/layout/xul/base/src/tree/src/crashtests/crashtests.list b/layout/xul/base/src/tree/src/crashtests/crashtests.list index 326c5c17fc9f..58e1dc509a96 100644 --- a/layout/xul/base/src/tree/src/crashtests/crashtests.list +++ b/layout/xul/base/src/tree/src/crashtests/crashtests.list @@ -14,3 +14,4 @@ load 399715-1.xhtml load 409807-1.xul load 430394-1.xul load 454186-1.xul +load 509602-1.xul From 38f061b3b9280ebf8646c3c9904e7376e7c5364e Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Sun, 6 Dec 2009 17:53:38 -0800 Subject: [PATCH 036/179] Add crashtests for a few bugs --- content/base/crashtests/450383-1.html | 9 ++++++ content/base/crashtests/450385-1.html | 11 ++++++++ content/base/crashtests/crashtests.list | 2 ++ .../src/crashtests/257752-1-recursion.rdf | 13 +++++++++ .../src/crashtests/257752-1-recursion.xul | 28 +++++++++++++++++++ .../templates/src/crashtests/crashtests.list | 1 + layout/tables/crashtests/513732-1.html | 7 +++++ layout/tables/crashtests/crashtests.list | 1 + layout/xul/base/src/crashtests/237787-1.xul | 9 ++++++ .../xul/base/src/crashtests/crashtests.list | 1 + .../tests/crashtests/515533-1-inner.html | 12 ++++++++ .../htmlparser/tests/crashtests/515533-1.html | 1 + .../tests/crashtests/crashtests.list | 1 + 13 files changed, 96 insertions(+) create mode 100644 content/base/crashtests/450383-1.html create mode 100644 content/base/crashtests/450385-1.html create mode 100644 content/xul/templates/src/crashtests/257752-1-recursion.rdf create mode 100644 content/xul/templates/src/crashtests/257752-1-recursion.xul create mode 100644 layout/tables/crashtests/513732-1.html create mode 100644 layout/xul/base/src/crashtests/237787-1.xul create mode 100644 parser/htmlparser/tests/crashtests/515533-1-inner.html create mode 100644 parser/htmlparser/tests/crashtests/515533-1.html diff --git a/content/base/crashtests/450383-1.html b/content/base/crashtests/450383-1.html new file mode 100644 index 000000000000..3c95b966ced8 --- /dev/null +++ b/content/base/crashtests/450383-1.html @@ -0,0 +1,9 @@ + + + + diff --git a/content/base/crashtests/450385-1.html b/content/base/crashtests/450385-1.html new file mode 100644 index 000000000000..e75159c51d44 --- /dev/null +++ b/content/base/crashtests/450385-1.html @@ -0,0 +1,11 @@ + + + + diff --git a/content/base/crashtests/crashtests.list b/content/base/crashtests/crashtests.list index 3a64c283a78e..430d259f072f 100644 --- a/content/base/crashtests/crashtests.list +++ b/content/base/crashtests/crashtests.list @@ -48,6 +48,8 @@ load 420620-1.html load 424276-1.html load 426987-1.html load 443538-1.svg +load 450383-1.html +load 450385-1.html skip load 458637-1.html # sporadically fails -- see bug 473680 load 472593-1.html load 474041-1.svg diff --git a/content/xul/templates/src/crashtests/257752-1-recursion.rdf b/content/xul/templates/src/crashtests/257752-1-recursion.rdf new file mode 100644 index 000000000000..a6eeb104bedf --- /dev/null +++ b/content/xul/templates/src/crashtests/257752-1-recursion.rdf @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/content/xul/templates/src/crashtests/257752-1-recursion.xul b/content/xul/templates/src/crashtests/257752-1-recursion.xul new file mode 100644 index 000000000000..fad5abfb601b --- /dev/null +++ b/content/xul/templates/src/crashtests/257752-1-recursion.xul @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/content/xul/templates/src/crashtests/crashtests.list b/content/xul/templates/src/crashtests/crashtests.list index badb4eaae4b5..8c09672dc27e 100644 --- a/content/xul/templates/src/crashtests/crashtests.list +++ b/content/xul/templates/src/crashtests/crashtests.list @@ -1,3 +1,4 @@ +load 257752-1-recursion.xul load 329335-1.xul load 329884-1.xul HTTP load 330010-1.xul diff --git a/layout/tables/crashtests/513732-1.html b/layout/tables/crashtests/513732-1.html new file mode 100644 index 000000000000..7ca35ddcebe0 --- /dev/null +++ b/layout/tables/crashtests/513732-1.html @@ -0,0 +1,7 @@ + + + + +
+ + diff --git a/layout/tables/crashtests/crashtests.list b/layout/tables/crashtests/crashtests.list index 5053b2791a98..641905fb905f 100644 --- a/layout/tables/crashtests/crashtests.list +++ b/layout/tables/crashtests/crashtests.list @@ -98,3 +98,4 @@ load 456041.html load 457115.html load 467141-1.html load 488388-1.html +load 513732-1.html diff --git a/layout/xul/base/src/crashtests/237787-1.xul b/layout/xul/base/src/crashtests/237787-1.xul new file mode 100644 index 000000000000..96cebca9ff5f --- /dev/null +++ b/layout/xul/base/src/crashtests/237787-1.xul @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/layout/xul/base/src/crashtests/crashtests.list b/layout/xul/base/src/crashtests/crashtests.list index 14b720a86df3..6ecb45685695 100644 --- a/layout/xul/base/src/crashtests/crashtests.list +++ b/layout/xul/base/src/crashtests/crashtests.list @@ -3,6 +3,7 @@ load 137216-1.xul load 140218-1.xml load 151826-1.xul load 168724-1.xul +load 237787-1.xul load 289410-1.xul load 291702-1.xul load 291702-2.xul diff --git a/parser/htmlparser/tests/crashtests/515533-1-inner.html b/parser/htmlparser/tests/crashtests/515533-1-inner.html new file mode 100644 index 000000000000..6bd0684e2103 --- /dev/null +++ b/parser/htmlparser/tests/crashtests/515533-1-inner.html @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/parser/htmlparser/tests/crashtests/515533-1.html b/parser/htmlparser/tests/crashtests/515533-1.html new file mode 100644 index 000000000000..b0d5b570b878 --- /dev/null +++ b/parser/htmlparser/tests/crashtests/515533-1.html @@ -0,0 +1 @@ + diff --git a/parser/htmlparser/tests/crashtests/crashtests.list b/parser/htmlparser/tests/crashtests/crashtests.list index 357636ff2e89..8623e7069162 100644 --- a/parser/htmlparser/tests/crashtests/crashtests.list +++ b/parser/htmlparser/tests/crashtests/crashtests.list @@ -36,5 +36,6 @@ load 423373-1.html skip load 460706-1.xhtml # Bug 479499 load 468538-1.xhtml load 515278-1.html +load 515533-1.html load 515816-1.html load 522326-1.html From 31637c44b8fc99d3d02526edab8eaba639d2c112 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Sun, 6 Dec 2009 19:29:17 -0800 Subject: [PATCH 037/179] [webgl] revert part of previous commit, exposes strange latent bug --- content/canvas/src/WebGLContextGL.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 96a6151bb44e..6c0c37d2d88f 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -2909,14 +2909,25 @@ WebGLContext::ValidateGL() // make sure that the opengl stuff that we need is supported GLint val = 0; - MakeContextCurrent(); + // XXX this exposes some strange latent bug; what's going on? + //MakeContextCurrent(); gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &val); + if (val == 0) { + LogMessage("GL_MAX_VERTEX_ATTRIBS is 0!"); + return PR_FALSE; + } + mAttribBuffers.SetLength(val); //fprintf(stderr, "GL_MAX_VERTEX_ATTRIBS: %d\n", val); gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_UNITS, &val); + if (val == 0) { + LogMessage("GL_MAX_TEXTURE_UNITS is 0!"); + return PR_FALSE; + } + mBound2DTextures.SetLength(val); mBoundCubeMapTextures.SetLength(val); From e611094cfcdfcac40cc479ff38c114da3c152b88 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Mon, 7 Dec 2009 10:49:46 +0000 Subject: [PATCH 038/179] Bug 533079 Actually land patch addressing review comments from bug 507970 a=shaver r=biesi --- netwerk/base/public/nsIStreamLoader.idl | 4 ++-- netwerk/base/src/nsStreamLoader.cpp | 12 +++++------- netwerk/base/src/nsStreamLoader.h | 8 +++++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/netwerk/base/public/nsIStreamLoader.idl b/netwerk/base/public/nsIStreamLoader.idl index 1a9995c8e65d..4e8fc9dc8047 100644 --- a/netwerk/base/public/nsIStreamLoader.idl +++ b/netwerk/base/public/nsIStreamLoader.idl @@ -59,8 +59,8 @@ interface nsIStreamLoaderObserver : nsISupports * If the observer wants to take over responsibility for the * data buffer (result), it returns NS_SUCCESS_ADOPTED_DATA * in place of NS_OK as its success code. The loader will then - * "forget" about the data, and not free() it in its own - * destructor; observer must call free() when the data is + * "forget" about the data, and not NS_Free() it in its own + * destructor; observer must call NS_Free() when the data is * no longer required. */ void onStreamComplete(in nsIStreamLoader loader, diff --git a/netwerk/base/src/nsStreamLoader.cpp b/netwerk/base/src/nsStreamLoader.cpp index 01bee7a69f9b..7878a07641fd 100644 --- a/netwerk/base/src/nsStreamLoader.cpp +++ b/netwerk/base/src/nsStreamLoader.cpp @@ -40,8 +40,6 @@ #include "nsIChannel.h" #include "nsNetError.h" -#include - nsStreamLoader::nsStreamLoader() : mData(nsnull), mAllocated(0), @@ -52,7 +50,7 @@ nsStreamLoader::nsStreamLoader() nsStreamLoader::~nsStreamLoader() { if (mData) { - ::free(mData); + NS_Free(mData); } } @@ -105,7 +103,7 @@ nsStreamLoader::OnStartRequest(nsIRequest* request, nsISupports *ctxt) chan->GetContentLength(&contentLength); if (contentLength >= 0) { // preallocate buffer - mData = static_cast(::malloc(contentLength)); + mData = static_cast(NS_Alloc(contentLength)); if (!mData) { return NS_ERROR_OUT_OF_MEMORY; } @@ -150,13 +148,13 @@ nsStreamLoader::WriteSegmentFun(nsIInputStream *inStr, { nsStreamLoader *self = (nsStreamLoader *) closure; - if (count > 0xffffffffU - self->mLength) { + if (count > PR_UINT32_MAX - self->mLength) { return NS_ERROR_ILLEGAL_VALUE; // is there a better error to use here? } if (self->mLength + count > self->mAllocated) { - self->mData = static_cast(::realloc(self->mData, - self->mLength + count)); + self->mData = static_cast(NS_Realloc(self->mData, + self->mLength + count)); if (!self->mData) { self->mLength = 0; self->mAllocated = 0; diff --git a/netwerk/base/src/nsStreamLoader.h b/netwerk/base/src/nsStreamLoader.h index 6b091eb79861..e9290a9f1a84 100644 --- a/netwerk/base/src/nsStreamLoader.h +++ b/netwerk/base/src/nsStreamLoader.h @@ -65,9 +65,11 @@ protected: nsCOMPtr mContext; // the observer's context nsCOMPtr mRequest; - PRUint8 *mData; - PRUint32 mAllocated; - PRUint32 mLength; + PRUint8 *mData; // buffer to accumulate incoming data + PRUint32 mAllocated; // allocated size of data buffer (we preallocate if + // contentSize is available) + PRUint32 mLength; // actual length of data in buffer + // (must be <= mAllocated) }; #endif // nsStreamLoader_h__ From 7712877b103d35ae4d1c917fb3fccbe94246741a Mon Sep 17 00:00:00 2001 From: "mwsteele@gmail.com" Date: Mon, 7 Dec 2009 15:10:04 -0800 Subject: [PATCH 039/179] b=528013; [webgl] BindFramebuffer checking target against wrong constants; r=vlad --- content/canvas/src/WebGLContext.h | 8 ++++--- content/canvas/src/WebGLContextGL.cpp | 33 +++++++++++---------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 07133022a382..441b7d7c445b 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -284,10 +284,12 @@ protected: WebGLObjectRefPtr mBoundElementArrayBuffer; WebGLObjectRefPtr mCurrentProgram; - nsTArray > mBoundColorFramebuffers; - nsRefPtr mBoundDepthFramebuffer; - nsRefPtr mBoundStencilFramebuffer; + // XXX these 3 are wrong types, and aren't used atm (except for the length of the attachments) + nsTArray > mFramebufferColorAttachments; + nsRefPtr mFramebufferDepthAttachment; + nsRefPtr mFramebufferStencilAttachment; + nsRefPtr mBoundFramebuffer; nsRefPtr mBoundRenderbuffer; // lookup tables for GL name -> object wrapper diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 6c0c37d2d88f..fceabd6c8fe5 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -409,17 +409,8 @@ WebGLContext::BindFramebuffer(GLenum target, nsIWebGLFramebuffer *fb) MakeContextCurrent(); - if (target >= LOCAL_GL_COLOR_ATTACHMENT0 && - target < (LOCAL_GL_COLOR_ATTACHMENT0 + mBoundColorFramebuffers.Length())) - { - int targetOffset = target - LOCAL_GL_COLOR_ATTACHMENT0; - mBoundColorFramebuffers[targetOffset] = wfb; - } else if (target == LOCAL_GL_DEPTH_ATTACHMENT) { - mBoundDepthFramebuffer = wfb; - } else if (target == LOCAL_GL_STENCIL_ATTACHMENT) { - mBoundStencilFramebuffer = wfb; - } else { - return ErrorMessage("glBindFramebuffer: invalid target"); + if (target != LOCAL_GL_FRAMEBUFFER) { + return ErrorMessage("glBindFramebuffer: target must be GL_FRAMEBUFFER"); } gl->fBindFramebuffer(target, wfb ? wfb->GLName() : 0); @@ -436,7 +427,7 @@ WebGLContext::BindRenderbuffer(GLenum target, nsIWebGLRenderbuffer *rb) return ErrorMessage("glBindRenderbuffer: renderbuffer has already been deleted!"); if (target != LOCAL_GL_RENDERBUFFER) - return ErrorMessage("glBindRenderbuffer: invalid target"); + return ErrorMessage("glBindRenderbuffer: target must be GL_RENDERBUFFER"); MakeContextCurrent(); @@ -1094,9 +1085,9 @@ WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum r return ErrorMessage("glFramebufferRenderbuffer: renderbuffer has already been deleted!"); if (target != LOCAL_GL_FRAMEBUFFER) - return ErrorMessage("glFramebufferRenderbuffer: target must be LOCAL_GL_FRAMEBUFFER"); + return ErrorMessage("glFramebufferRenderbuffer: target must be GL_FRAMEBUFFER"); - if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 || attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mBoundColorFramebuffers.Length()) && + if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 || attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mFramebufferColorAttachments.Length()) && attachment != LOCAL_GL_DEPTH_ATTACHMENT && attachment != LOCAL_GL_STENCIL_ATTACHMENT) return ErrorMessage("glFramebufferRenderbuffer: invalid attachment"); @@ -1115,10 +1106,10 @@ WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum r NS_IMETHODIMP WebGLContext::FramebufferTexture2D(GLenum target, - GLenum attachment, - GLenum textarget, - nsIWebGLTexture *wtex, - GLint level) + GLenum attachment, + GLenum textarget, + nsIWebGLTexture *wtex, + GLint level) { WebGLTexture *tex = static_cast(wtex); @@ -1128,7 +1119,7 @@ WebGLContext::FramebufferTexture2D(GLenum target, if (target != LOCAL_GL_FRAMEBUFFER) return ErrorMessage("glFramebufferTexture2D: target must be GL_FRAMEBUFFER"); - if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 || attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mBoundColorFramebuffers.Length()) && + if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 || attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mFramebufferColorAttachments.Length()) && attachment != LOCAL_GL_DEPTH_ATTACHMENT && attachment != LOCAL_GL_STENCIL_ATTACHMENT) return ErrorMessage("glFramebufferTexture2D: invalid attachment"); @@ -1141,6 +1132,8 @@ WebGLContext::FramebufferTexture2D(GLenum target, if (level != 0) return ErrorMessage("glFramebufferTexture2D: level must be 0"); + // XXXXX we need to store/reference this attachment! + MakeContextCurrent(); gl->fFramebufferTexture2D(target, attachment, textarget, tex->GLName(), level); @@ -2934,7 +2927,7 @@ WebGLContext::ValidateGL() //fprintf(stderr, "GL_MAX_TEXTURE_UNITS: %d\n", val); gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &val); - mBoundColorFramebuffers.SetLength(val); + mFramebufferColorAttachments.SetLength(val); #ifdef DEBUG_vladimir gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &val); From 65579e54711c8e9edcda54edf5e1cdd96c43d709 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 8 Dec 2009 10:54:48 -0800 Subject: [PATCH 040/179] Bug 532328 - plugin bustage on Qt. r=karlt --- layout/generic/nsObjectFrame.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index cfcf49afc079..5f3a9152eaab 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -413,7 +413,7 @@ public: return strncmp(GetPluginName(), aPluginName, strlen(aPluginName)) == 0; } -#ifdef MOZ_PLATFORM_HILDON +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) nsresult SetAbsoluteScreenPosition(nsIDOMElement* element, nsIDOMClientRect* position, nsIDOMClientRect* clip); @@ -509,7 +509,8 @@ private: const nsIntRect& mDirtyRect; }; #endif -#ifdef MOZ_PLATFORM_HILDON + +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) // On hildon, we attempt to use NPImageExpose which allows us faster // painting. @@ -1224,7 +1225,7 @@ nsObjectFrame::SetAbsoluteScreenPosition(nsIDOMElement* element, nsIDOMClientRect* position, nsIDOMClientRect* clip) { -#ifdef MOZ_PLATFORM_HILDON +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) if (!mInstanceOwner) return NS_ERROR_NOT_AVAILABLE; return mInstanceOwner->SetAbsoluteScreenPosition(element, position, clip); @@ -2108,7 +2109,7 @@ GetMIMEType(nsIPluginInstance *aPluginInstance) static PRBool DoDelayedStop(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop) { -#ifdef MOZ_PLATFORM_HILDON +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) // Don't delay stop on Maemo/Hildon (bug 530739). if (aDelayedStop && aInstanceOwner->MatchPluginName("Shockwave Flash")) return PR_FALSE; @@ -2421,7 +2422,7 @@ nsPluginInstanceOwner::nsPluginInstanceOwner() mLastPoint = nsIntPoint(0,0); #endif -#ifdef MOZ_PLATFORM_HILDON +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) mPluginSize = nsIntSize(0,0); mXlibSurfGC = None; mSharedXImage = nsnull; @@ -2489,7 +2490,7 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner() mInstance->InvalidateOwner(); } -#ifdef MOZ_PLATFORM_HILDON +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) ReleaseXShm(); #endif } @@ -2711,7 +2712,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRect(NPRect *invalidRect) if (!mObjectFrame || !invalidRect || !mWidgetVisible) return NS_ERROR_FAILURE; -#ifdef MOZ_PLATFORM_HILDON +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) PRBool simpleImageRender = PR_FALSE; mInstance->GetValueFromPlugin(NPPVpluginWindowlessLocalBool, &simpleImageRender); @@ -4800,7 +4801,7 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext, if (!mInstance || !mObjectFrame) return; -#ifdef MOZ_PLATFORM_HILDON +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) // through to be able to paint the context passed in. This allows // us to handle plugins that do not self invalidate (slowly, but // accurately), and it allows us to reduce flicker. @@ -4889,7 +4890,7 @@ DepthOfVisual(const Screen* screen, const Visual* visual) } #endif -#ifdef MOZ_PLATFORM_HILDON +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) static GdkWindow* GetClosestWindow(nsIDOMElement *element) { @@ -5602,7 +5603,7 @@ void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost* aHost) mPluginHost = aHost; } -#ifdef MOZ_PLATFORM_HILDON +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) PRBool nsPluginInstanceOwner::UpdateVisibility() { if (!mInstance) @@ -5759,7 +5760,7 @@ void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value) } } -#ifdef MOZ_PLATFORM_HILDON +#if defined(MOZ_PLATFORM_HILDON) && defined(MOZ_WIDGET_GTK2) nsresult nsPluginInstanceOwner::SetAbsoluteScreenPosition(nsIDOMElement* element, nsIDOMClientRect* position, From 980aebc27907d6f4739ac406b65cac84b4336759 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 8 Dec 2009 13:06:35 -0800 Subject: [PATCH 041/179] minor fixes to comments in nsSMILAnimationFunction.h. b=no_bug r+a=comments_only --- content/smil/nsSMILAnimationFunction.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/content/smil/nsSMILAnimationFunction.h b/content/smil/nsSMILAnimationFunction.h index 80ec0f6abd7e..877b002b9bbf 100644 --- a/content/smil/nsSMILAnimationFunction.h +++ b/content/smil/nsSMILAnimationFunction.h @@ -85,7 +85,7 @@ public: * parsed result. * @param aParseResult Outparam used for reporting parse errors. Will be set * to NS_OK if everything succeeds. - * @returns PR_TRUE if aAttribute is a recognized animation-related + * @return PR_TRUE if aAttribute is a recognized animation-related * attribute; PR_FALSE otherwise. */ virtual PRBool SetAttr(nsIAtom* aAttribute, const nsAString& aValue, @@ -139,8 +139,8 @@ public: * the animation function that it should no longer add its result to the * animation sandwich. * - * @param aIsFrozen True if this animation should continue to contribute to - * the animation sandwich using the most recent sample + * @param aIsFrozen PR_TRUE if this animation should continue to contribute + * to the animation sandwich using the most recent sample * parameters. */ void Inactivate(PRBool aIsFrozen); @@ -179,7 +179,7 @@ public: * Indicates if the animation is currently active or frozen. Inactive * animations will not contribute to the composed result. * - * @return True if the animation is active or frozen, false otherwise. + * @return PR_TRUE if the animation is active or frozen, PR_FALSE otherwise. */ PRBool IsActiveOrFrozen() const { @@ -210,7 +210,8 @@ public: * Note that the caller is responsible for determining if the animation target * has changed. * - * @return True if the animation parameters have changed, false otherwise. + * @return PR_TRUE if the animation parameters have changed, PR_FALSE + * otherwise. */ PRBool HasChanged() const; From 16718495b08bb678922fe5055eb83d8c27c38754 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Tue, 8 Dec 2009 13:46:42 -0800 Subject: [PATCH 042/179] Fix for bug 533401 (Names added through external DOM classinfo don't resolve on global object). r=jst, a=beltzner. --- dom/base/nsDOMClassInfo.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 989bab09b2ae..5afc42700a39 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -4325,14 +4325,6 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto) JS_ClearPendingException(cx); } - static const nsIID *sSupportsIID = &NS_GET_IID(nsISupports); - - // This is safe because... - if (mData->mProtoChainInterface == sSupportsIID || - !mData->mProtoChainInterface) { - return NS_OK; - } - // This is called before any other location that requires // sObjectClass, so compute it here. We assume that nobody has had a // chance to monkey around with proto's prototype chain before this. @@ -4345,9 +4337,10 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto) NS_ASSERTION(::JS_GetPrototype(cx, proto) && JS_GET_CLASS(cx, ::JS_GetPrototype(cx, proto)) == sObjectClass, "Hmm, somebody did something evil?"); - + #ifdef DEBUG - if (mData->mHasClassInterface) { + if (mData->mHasClassInterface && mData->mProtoChainInterface && + mData->mProtoChainInterface != &NS_GET_IID(nsISupports)) { nsCOMPtr iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); From c1a07f2b2711aca0e0cfe6ec95eb6ae697e17be1 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Tue, 8 Dec 2009 21:50:27 -0800 Subject: [PATCH 043/179] Part 2 of fix for bug 533401 (Names added through external DOM classinfo don't resolve on global object). r=jst, a=beltzner. --- dom/base/nsDOMClassInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 5afc42700a39..7e8c81177a55 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -5509,7 +5509,7 @@ private: static PRBool IsConstructable(const nsDOMClassInfoData *aData) { - if (IS_EXTERNAL(aData)) { + if (IS_EXTERNAL(aData->mCachedClassInfo)) { const nsExternalDOMClassInfoData* data = static_cast(aData); return data->mConstructorCID != nsnull; From 8fa3b15d89854be1332df8dcf56f16d3d4c1b1fd Mon Sep 17 00:00:00 2001 From: Neil Deakin Date: Wed, 9 Dec 2009 11:34:14 -0500 Subject: [PATCH 044/179] Bug 520535, activate event should fire only at windows and dialogs, r=jmathies --- widget/src/windows/nsWindow.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 8674d6ef8927..af40e5e1d814 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -3422,10 +3422,23 @@ PRBool nsWindow::DispatchFocusToTopLevelWindow(PRUint32 aEventType) sJustGotActivate = PR_FALSE; sJustGotDeactivate = PR_FALSE; - // clear the flags, and retrieve the toplevel window. This way, it doesn't - // mattter what child widget received the focus event and it will always be - // fired at the toplevel window. - HWND toplevelWnd = GetTopLevelHWND(mWnd); + // retrive the toplevel window or dialog + HWND curWnd = mWnd; + HWND toplevelWnd = NULL; + while (curWnd) { + toplevelWnd = curWnd; + + nsWindow *win = GetNSWindowPtr(curWnd); + if (win) { + nsWindowType wintype; + win->GetWindowType(wintype); + if (wintype == eWindowType_toplevel || wintype == eWindowType_dialog) + break; + } + + curWnd = ::GetParent(curWnd); // Parent or owner (if has no parent) + } + if (toplevelWnd) { nsWindow *win = GetNSWindowPtr(toplevelWnd); if (win) From 8d12e79ac7236dc595ca920eaf662edac92683f5 Mon Sep 17 00:00:00 2001 From: Bob Clary Date: Wed, 9 Dec 2009 14:41:45 -0800 Subject: [PATCH 045/179] bug 496127 - relax timing comparison to eliminate random failures in js1_8_1/trace/regress-452498-01.js. --- js/src/tests/js1_8_1/trace/regress-452498-01.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/tests/js1_8_1/trace/regress-452498-01.js b/js/src/tests/js1_8_1/trace/regress-452498-01.js index 59a04c8434cb..862c3dc004b3 100644 --- a/js/src/tests/js1_8_1/trace/regress-452498-01.js +++ b/js/src/tests/js1_8_1/trace/regress-452498-01.js @@ -99,7 +99,7 @@ var timenonjit = f(false); var timejit = f(true); expect = true; -actual = timejit < timenonjit/2; +actual = timejit < timenonjit; print('time nonjit: ' + timenonjit + ', time jit: ' + timejit); From 1412c46b08fb4818349f338bd6e65b057be41035 Mon Sep 17 00:00:00 2001 From: Bob Clary Date: Wed, 9 Dec 2009 14:41:45 -0800 Subject: [PATCH 046/179] bug 528717 - relax timing comparison to eliminate random failures in js1_8_1/trace/regress-470739.js. --- js/src/tests/js1_8_1/trace/regress-470739.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/tests/js1_8_1/trace/regress-470739.js b/js/src/tests/js1_8_1/trace/regress-470739.js index 0ad2b9a2f5bb..f48c66c1ae1b 100644 --- a/js/src/tests/js1_8_1/trace/regress-470739.js +++ b/js/src/tests/js1_8_1/trace/regress-470739.js @@ -73,7 +73,7 @@ function test() print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); expect = true; - actual = timejit < timenonjit/2; + actual = timejit < timenonjit; reportCompare(expect, actual, summary); From fa1b7b7fcc98a08852aa44934b6caa036b319b6f Mon Sep 17 00:00:00 2001 From: Bob Clary Date: Wed, 9 Dec 2009 14:41:45 -0800 Subject: [PATCH 047/179] bug 531325 - relax timing comparison to eliminate random failures in js1_8_1/trace/regress-469927.js. --- js/src/tests/js1_8_1/trace/regress-469927.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/tests/js1_8_1/trace/regress-469927.js b/js/src/tests/js1_8_1/trace/regress-469927.js index 1c3579a2bac4..4d0651f0dbdf 100644 --- a/js/src/tests/js1_8_1/trace/regress-469927.js +++ b/js/src/tests/js1_8_1/trace/regress-469927.js @@ -71,7 +71,7 @@ function test() print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); expect = true; - actual = timejit < timenonjit/2; + actual = timejit < timenonjit; reportCompare(expect, actual, summary); From 1a488578301fe4080c6aba5f0186bb364a3c7db6 Mon Sep 17 00:00:00 2001 From: Bob Clary Date: Wed, 9 Dec 2009 14:41:45 -0800 Subject: [PATCH 048/179] bug 533027 - skip js1_5/Regress/regress-3649-n.js due to random oom related failures. --- js/src/tests/js1_5/Regress/jstests.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/tests/js1_5/Regress/jstests.list b/js/src/tests/js1_5/Regress/jstests.list index 5e967d21d29d..29208f6c5fc2 100644 --- a/js/src/tests/js1_5/Regress/jstests.list +++ b/js/src/tests/js1_5/Regress/jstests.list @@ -209,7 +209,7 @@ script regress-360969-06.js script regress-361467.js script regress-361617.js skip script regress-362583.js # obsolete test -fails-if(xulRuntime.OS=="WINNT") random-if(xulRuntime.OS=="Linux"&&!xulRuntime.XPCOMABI.match(/x86_64/)) skip-if(xulRuntime.OS=="Linux"&&xulRuntime.XPCOMABI.match(/x86_64/)) script regress-3649-n.js # No test results on windows, sometimes no test results on 32 bit linux, hangs os/consumes ram/swap on 64bit linux. +skip script regress-3649-n.js # skip test due to random oom related errors. script regress-366122.js script regress-366468.js script regress-366601.js From 1d8f4e8f5be71fc20173a92b4f6397093b1f60d4 Mon Sep 17 00:00:00 2001 From: Justin Dolske Date: Wed, 9 Dec 2009 14:59:37 -0800 Subject: [PATCH 049/179] Bug 533665 - Avoid the need to build NSPR for L10N repacks. r=robert.bugzilla a192=beltzner --- modules/libmar/src/mar.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/libmar/src/mar.h b/modules/libmar/src/mar.h index 45f46e835a75..2ffd4ddbe97a 100644 --- a/modules/libmar/src/mar.h +++ b/modules/libmar/src/mar.h @@ -40,7 +40,13 @@ #define MAR_H__ /* We use NSPR here just to import the definition of PRUint32 */ +#ifndef WINCE #include "prtypes.h" +#else +typedef int PRInt32; +typedef unsigned int PRUint32; +typedef wchar_t PRUnichar; +#endif #ifdef __cplusplus extern "C" { From d661759e9bbff69b1063fc9c48a0d256bff880cb Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Thu, 10 Dec 2009 09:21:27 -0800 Subject: [PATCH 050/179] Bug 527311 - Addressbar suggests adaptive results even if they have no visits and we want "history" behavior, r=sdwilsh --- .../places/src/nsPlacesAutoComplete.js | 20 ++- .../tests/unit/test_adaptive_bug527311.js | 161 ++++++++++++++++++ 2 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 toolkit/components/places/tests/unit/test_adaptive_bug527311.js diff --git a/toolkit/components/places/src/nsPlacesAutoComplete.js b/toolkit/components/places/src/nsPlacesAutoComplete.js index 3b4fac52eab9..bb8ee23e6b9e 100644 --- a/toolkit/components/places/src/nsPlacesAutoComplete.js +++ b/toolkit/components/places/src/nsPlacesAutoComplete.js @@ -306,10 +306,12 @@ function nsPlacesAutoComplete() // title). return this._db.createStatement( "/* do not warn (bug 487789) */ " + - "SELECT IFNULL(h_t.url, h.url), IFNULL(h_t.title, h.title), f.url, " + - kBookTagSQLFragment + ", IFNULL(h_t.visit_count, h.visit_count), " + - "IFNULL(h_t.typed, h.typed), IFNULL(h_t.id, h.id), " + - ":query_type, rank " + + "SELECT IFNULL(h_t.url, h.url) AS c_url, " + + "IFNULL(h_t.title, h.title) AS c_title, f.url, " + + kBookTagSQLFragment + ", " + + "IFNULL(h_t.visit_count, h.visit_count) AS c_visit_count, " + + "IFNULL(h_t.typed, h.typed) AS c_typed, " + + "IFNULL(h_t.id, h.id), :query_type, rank " + "FROM ( " + "SELECT ROUND(MAX(((i.input = :search_string) + " + "(SUBSTR(i.input, 1, LENGTH(:search_string)) = :search_string)) * " + @@ -320,11 +322,11 @@ function nsPlacesAutoComplete() ") AS i " + "LEFT JOIN moz_places h ON h.id = i.place_id " + "LEFT JOIN moz_places_temp h_t ON h_t.id = i.place_id " + - "LEFT JOIN moz_favicons f ON f.id = IFNULL(h_t.favicon_id, h.favicon_id) "+ - "WHERE IFNULL(h_t.url, h.url) NOTNULL " + - "AND AUTOCOMPLETE_MATCH(:searchString, 0 /* url */, " + - "IFNULL(bookmark, 1 /* title */), tags, " + - "6 /* visit_count */, 7 /* typed */, parent, " + + "LEFT JOIN moz_favicons f ON f.id = IFNULL(h_t.favicon_id, h.favicon_id) " + + "WHERE c_url NOTNULL " + + "AND AUTOCOMPLETE_MATCH(:searchString, c_url, " + + "IFNULL(bookmark, c_title), tags, " + + "c_visit_count, c_typed, parent, " + ":matchBehavior, :searchBehavior) " + "ORDER BY rank DESC, IFNULL(h_t.frecency, h.frecency) DESC" ); diff --git a/toolkit/components/places/tests/unit/test_adaptive_bug527311.js b/toolkit/components/places/tests/unit/test_adaptive_bug527311.js new file mode 100644 index 000000000000..d91422331c53 --- /dev/null +++ b/toolkit/components/places/tests/unit/test_adaptive_bug527311.js @@ -0,0 +1,161 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Places Unit Test Code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Marco Bonardo + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +const TEST_URL = "http://adapt.mozilla.org/"; +const SEARCH_STRING = "adapt"; + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsINavHistoryService); +let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. + getService(Ci.nsINavBookmarksService); +let os = Cc["@mozilla.org/observer-service;1"]. + getService(Ci.nsIObserverService); +let ps = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + +const PLACES_AUTOCOMPLETE_FEEDBACK_UPDATED_TOPIC = + "places-autocomplete-feedback-updated"; + +function AutoCompleteInput(aSearches) { + this.searches = aSearches; +} +AutoCompleteInput.prototype = { + constructor: AutoCompleteInput, + searches: null, + minResultsForPopup: 0, + timeout: 10, + searchParam: "", + textValue: "", + disableAutoComplete: false, + completeDefaultIndex: false, + + get searchCount() { + return this.searches.length; + }, + + getSearchAt: function ACI_getSearchAt(aIndex) { + return this.searches[aIndex]; + }, + + onSearchComplete: function ACI_onSearchComplete() {}, + + popupOpen: false, + + popup: { + setSelectedIndex: function() {}, + invalidate: function() {}, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsISupports) || + iid.equals(Ci.nsIAutoCompletePopup)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } + }, + + onSearchBegin: function() {}, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsISupports) || + iid.equals(Ci.nsIAutoCompleteInput)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +} + + +function check_results() { + let controller = Cc["@mozilla.org/autocomplete/controller;1"]. + getService(Ci.nsIAutoCompleteController); + let input = new AutoCompleteInput(["history"]); + controller.input = input; + + input.onSearchComplete = function() { + do_check_eq(controller.searchStatus, + Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH); + do_check_eq(controller.matchCount, 0); + + remove_all_bookmarks(); + do_test_finished(); + }; + + controller.startSearch(SEARCH_STRING); +} + + +function addAdaptiveFeedback(aUrl, aSearch, aCallback) { + let observer = { + observe: function(aSubject, aTopic, aData) { + os.removeObserver(observer, PLACES_AUTOCOMPLETE_FEEDBACK_UPDATED_TOPIC); + do_timeout(0, aCallback); + } + }; + os.addObserver(observer, PLACES_AUTOCOMPLETE_FEEDBACK_UPDATED_TOPIC, false); + + let thing = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteInput, + Ci.nsIAutoCompletePopup, + Ci.nsIAutoCompleteController]), + get popup() { return thing; }, + get controller() { return thing; }, + popupOpen: true, + selectedIndex: 0, + getValueAt: function() aUrl, + searchString: aSearch + }; + + os.notifyObservers(thing, "autocomplete-will-enter-text", null); +} + + +function run_test() { + do_test_pending(); + + // Add a bookmark to our url. + bs.insertBookmark(bs.unfiledBookmarksFolder, uri(TEST_URL), + bs.DEFAULT_INDEX, "test_book"); + // We want to search only history. + ps.setIntPref("browser.urlbar.default.behavior", + Ci.mozIPlacesAutoComplete.BEHAVIOR_HISTORY); + // Add an adaptive entry. + addAdaptiveFeedback(TEST_URL, SEARCH_STRING, check_results); +} From 9dea1baf516764251e6203e84f213530a9acf8fb Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 051/179] Bug 530639: Fix build warnings in TestXPTCInvoke.cpp. r=bsmedberg --- .../reflect/xptcall/tests/TestXPTCInvoke.cpp | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp b/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp index dc4725e56ca4..8ac823d24cee 100644 --- a/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp +++ b/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp @@ -46,10 +46,17 @@ #include "prinrval.h" #include "nsMemory.h" +// Allows us to mark unused functions as known-unused +#ifdef __GNUC__ +#define UNUSED __attribute__ ((unused)) +#else +#define UNUSED +#endif + // forward declration static void DoMultipleInheritenceTest(); static void DoMultipleInheritenceTest2(); -static void DoSpeedTest(); +static void UNUSED DoSpeedTest(); // {AAC1FB90-E099-11d2-984E-006008962422} #define INVOKETESTTARGET_IID \ @@ -317,7 +324,7 @@ InvokeTestTarget::AddMixedInts3(PRInt64 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4, printf("P8 : %lld\n", p8); printf("P9 : %d\n", p9); printf("P10: %lld\n", p10); - printf("ret: %p\n", retval); + printf("ret: %p\n", static_cast(retval)); *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10; return NS_OK; } @@ -946,7 +953,7 @@ int main() var[2].ptr = &var[2].val.p; if(NS_SUCCEEDED(NS_InvokeByIndex(test, 15, 3, var))) - printf(" = %s\n", var[2].val.p); + printf(" = %s\n", static_cast(var[2].val.p)); else printf("\tFAILED"); @@ -1209,9 +1216,9 @@ static void DoMultipleInheritenceTest() if(NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIFoo), (void**)&foo)) && NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIBar), (void**)&bar))) { - printf("impl == %p\n", impl); - printf("foo == %p\n", foo); - printf("bar == %p\n", bar); + printf("impl == %p\n", static_cast(impl)); + printf("foo == %p\n", static_cast(foo)); + printf("bar == %p\n", static_cast(bar)); printf("Calling Foo...\n"); printf("direct calls:\n"); @@ -1379,9 +1386,9 @@ static void DoMultipleInheritenceTest2() if(NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIFoo), (void**)&foo)) && NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIBar), (void**)&bar))) { - printf("impl == %p\n", impl); - printf("foo == %p\n", foo); - printf("bar == %p\n", bar); + printf("impl == %p\n", static_cast(impl)); + printf("foo == %p\n", static_cast(foo)); + printf("bar == %p\n", static_cast(bar)); printf("Calling Foo...\n"); printf("direct calls:\n"); From 46777d73204c1e5f509341506bd60181e2a2bb1d Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 052/179] Bug 526423: Remove unused variables in WebGLContextValidate.cpp to fix build warning. r=mwsteele --- content/canvas/src/WebGLContextValidate.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/content/canvas/src/WebGLContextValidate.cpp b/content/canvas/src/WebGLContextValidate.cpp index 7e44217d19df..ab21f7a123bf 100644 --- a/content/canvas/src/WebGLContextValidate.cpp +++ b/content/canvas/src/WebGLContextValidate.cpp @@ -48,9 +48,6 @@ using namespace mozilla; PRBool WebGLContext::ValidateBuffers(PRUint32 count) { - GLint len = 0; - GLint enabled = 0, size = 4, type = LOCAL_GL_FLOAT, binding = 0; - PRBool someEnabled = PR_FALSE; GLint currentProgram = -1; GLint numAttributes = -1; From 275d09e60475b5bbcd92d93da51c8d6e4e4428fc Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 053/179] Bug 529950: remove unused variable 'frames' to fix build warning. r=bz --- layout/xul/base/src/tree/src/nsTreeColFrame.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/layout/xul/base/src/tree/src/nsTreeColFrame.cpp b/layout/xul/base/src/tree/src/nsTreeColFrame.cpp index 4daab7079f5a..fa672bec5cd2 100644 --- a/layout/xul/base/src/tree/src/nsTreeColFrame.cpp +++ b/layout/xul/base/src/tree/src/nsTreeColFrame.cpp @@ -127,7 +127,6 @@ nsDisplayXULTreeColSplitterTarget::HitTest(nsDisplayListBuilder* aBuilder, if (left || right) { // We are a header. Look for the correct splitter. - const nsFrameList& frames(mFrame->GetParent()->GetChildList(nsnull)); nsIFrame* child; if (left) child = mFrame->GetPrevSibling(); From 3fe8b28b26e219ccc37d035eaf5545c4946e5794 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 054/179] Bug 529356: Add 'default' case in a switch statement in nsStyleAnimation, to fix build warning. r=dbaron --- layout/style/nsStyleAnimation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/layout/style/nsStyleAnimation.cpp b/layout/style/nsStyleAnimation.cpp index 0b6367b23a7b..136fbec872dc 100644 --- a/layout/style/nsStyleAnimation.cpp +++ b/layout/style/nsStyleAnimation.cpp @@ -948,8 +948,6 @@ static PRBool StyleCoordToValue(const nsStyleCoord& aCoord, nsStyleAnimation::Value& aValue) { switch (aCoord.GetUnit()) { - case eStyleUnit_Null: - return PR_FALSE; case eStyleUnit_Normal: aValue.SetNormalValue(); break; @@ -976,6 +974,8 @@ StyleCoordToValue(const nsStyleCoord& aCoord, nsStyleAnimation::Value& aValue) aValue.SetIntValue(aCoord.GetIntValue(), nsStyleAnimation::eUnit_Integer); break; + default: + return PR_FALSE; } return PR_TRUE; } From 42be6a5054f9a944cfb56f21feaed8fd92f14ff7 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 055/179] Bug 529387: Don't create SMIL animation controller for data documents. r=roc --- content/base/src/nsDocument.cpp | 5 +++-- content/smil/crashtests/529387-1-helper.svg | 5 +++++ content/smil/crashtests/529387-1.xhtml | 7 +++++++ content/smil/crashtests/crashtests.list | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 content/smil/crashtests/529387-1-helper.svg create mode 100644 content/smil/crashtests/529387-1.xhtml diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 92c928dfa79c..138ca8a574fd 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -5344,8 +5344,9 @@ nsDocument::GetAnimationController() // one and only SVG documents and the like will call this if (mAnimationController) return mAnimationController; - // Refuse to create an Animation Controller if SMIL is disabled - if (!NS_SMILEnabled()) + // Refuse to create an Animation Controller if SMIL is disabled, and also + // for data documents. + if (!NS_SMILEnabled() || mLoadedAsData) return nsnull; mAnimationController = NS_NewSMILAnimationController(this); diff --git a/content/smil/crashtests/529387-1-helper.svg b/content/smil/crashtests/529387-1-helper.svg new file mode 100644 index 000000000000..7885ab71fd4a --- /dev/null +++ b/content/smil/crashtests/529387-1-helper.svg @@ -0,0 +1,5 @@ + + abc + + + diff --git a/content/smil/crashtests/529387-1.xhtml b/content/smil/crashtests/529387-1.xhtml new file mode 100644 index 000000000000..de3dbec34cff --- /dev/null +++ b/content/smil/crashtests/529387-1.xhtml @@ -0,0 +1,7 @@ + + + diff --git a/content/smil/crashtests/crashtests.list b/content/smil/crashtests/crashtests.list index 4ca09fa7ac0d..2533a13b5aa1 100644 --- a/content/smil/crashtests/crashtests.list +++ b/content/smil/crashtests/crashtests.list @@ -2,3 +2,4 @@ load 523188-1.svg load 525099-1.svg load 526875-1.svg load 526875-2.svg +load 529387-1.xhtml From 00a19349073cf99dfde908af5982b60928c81400 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 056/179] Add mochitest for bug 529387. (test only) --- content/smil/test/Makefile.in | 2 + content/smil/test/smilXHR_helper.svg | 8 +++ content/smil/test/test_smilXHR.xhtml | 89 ++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 content/smil/test/smilXHR_helper.svg create mode 100644 content/smil/test/test_smilXHR.xhtml diff --git a/content/smil/test/Makefile.in b/content/smil/test/Makefile.in index 8ff8c40e0e04..6416ab66c7e1 100644 --- a/content/smil/test/Makefile.in +++ b/content/smil/test/Makefile.in @@ -50,6 +50,7 @@ _TEST_FILES = \ db_smilCSSPaced.js \ db_smilCSSPropertyList.js \ smilTestUtils.js \ + smilXHR_helper.svg \ test_smilCSSFontStretchRelative.xhtml \ test_smilCSSFromBy.xhtml \ test_smilCSSFromTo.xhtml \ @@ -65,6 +66,7 @@ _TEST_FILES = \ test_smilTextZoom.xhtml \ test_smilTiming.xhtml \ test_smilTimingZeroIntervals.xhtml \ + test_smilXHR.xhtml \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/smil/test/smilXHR_helper.svg b/content/smil/test/smilXHR_helper.svg new file mode 100644 index 000000000000..cb0b51c36052 --- /dev/null +++ b/content/smil/test/smilXHR_helper.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/content/smil/test/test_smilXHR.xhtml b/content/smil/test/test_smilXHR.xhtml new file mode 100644 index 000000000000..85c86114d94a --- /dev/null +++ b/content/smil/test/test_smilXHR.xhtml @@ -0,0 +1,89 @@ + + + Test for SMIL Behavior in Data Documents + + + + + + +Mozilla Bug 529387 +

+ +
+
+
+ + From 1cb5b1c508b901fb47c148c28c0eb3f3247fc49e Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 057/179] Bug 520239, patch 1: Split out a chunk of nsStyleAnimation::ComputeValue into its own function. r=dbaron --- content/smil/test/Makefile.in | 1 + content/smil/test/smilTestUtils.js | 16 +++- .../smil/test/test_smilCSSInvalidValues.xhtml | 65 +++++++++++++++ layout/style/nsStyleAnimation.cpp | 81 ++++++++++++++----- 4 files changed, 139 insertions(+), 24 deletions(-) create mode 100644 content/smil/test/test_smilCSSInvalidValues.xhtml diff --git a/content/smil/test/Makefile.in b/content/smil/test/Makefile.in index 6416ab66c7e1..fbbca01663d3 100644 --- a/content/smil/test/Makefile.in +++ b/content/smil/test/Makefile.in @@ -55,6 +55,7 @@ _TEST_FILES = \ test_smilCSSFromBy.xhtml \ test_smilCSSFromTo.xhtml \ test_smilCSSInherit.xhtml \ + test_smilCSSInvalidValues.xhtml \ test_smilCSSPaced.xhtml \ test_smilRestart.xhtml \ test_smilGetStartTime.xhtml \ diff --git a/content/smil/test/smilTestUtils.js b/content/smil/test/smilTestUtils.js index 95a145d0cf14..32a5e045602b 100644 --- a/content/smil/test/smilTestUtils.js +++ b/content/smil/test/smilTestUtils.js @@ -359,6 +359,10 @@ AnimTestcase.prototype = return this.buildSeekListStatic(aAnimAttr, aBaseVal, aTimeData, "defined as non-animatable in SVG spec"); } + if (this.computedValMap.noEffect) { + return this.buildSeekListStatic(aAnimAttr, aBaseVal, aTimeData, + "testcase specified to have no effect"); + } return this.buildSeekListAnimated(aAnimAttr, aBaseVal, aTimeData, aIsFreeze) }, @@ -457,6 +461,9 @@ extend(AnimTestcaseFrom, AnimTestcase); * - midComp: Computed value that we expect to visit halfway through the * animation (if different from |aTo|) * - toComp: Computed value version of |aTo| (if different from |aTo|) + * - noEffect: Special flag -- if set, indicates that this testcase is + * expected to have no effect on the computed value. (e.g. the + * given values are invalid.) * @param aSkipReason If this test-case is known to currently fail, this * parameter should be a string explaining why. * Otherwise, this value should be null (or omitted). @@ -498,9 +505,10 @@ extend(AnimTestcaseFromTo, AnimTestcaseFrom); * animation (|aFrom| + |aBy|/2) * - toComp: Computed value of the animation endpoint (|aFrom| + |aBy|) * - noEffect: Special flag -- if set, indicates that this testcase is - * expected to have no effect on the computed value. (i.e. the - * attribute may be animatable and additive, but the particular - * "from" & "by" values that are used don't support addition.) + * expected to have no effect on the computed value. (e.g. the + * given values are invalid. Or the attribute may be animatable + * and additive, but the particular "from" & "by" values that + * are used don't support addition.) * @param aSkipReason If this test-case is known to currently fail, this * parameter should be a string explaining why. * Otherwise, this value should be null (or omitted). @@ -532,7 +540,7 @@ AnimTestcaseFromBy.prototype = }, buildSeekList : function(aAnimAttr, aBaseVal, aTimeData, aIsFreeze) { - if (!aAnimAttr.isAdditive || this.computedValMap.noEffect) { + if (!aAnimAttr.isAdditive) { return this.buildSeekListStatic(aAnimAttr, aBaseVal, aTimeData, "defined as non-additive in SVG spec"); } diff --git a/content/smil/test/test_smilCSSInvalidValues.xhtml b/content/smil/test/test_smilCSSInvalidValues.xhtml new file mode 100644 index 000000000000..d00770c79b97 --- /dev/null +++ b/content/smil/test/test_smilCSSInvalidValues.xhtml @@ -0,0 +1,65 @@ + + + Test for Animation Behavior on CSS Properties + + + + + + + +

+
+ + + +
+
+
+
+ + diff --git a/layout/style/nsStyleAnimation.cpp b/layout/style/nsStyleAnimation.cpp index 136fbec872dc..f0fb90042528 100644 --- a/layout/style/nsStyleAnimation.cpp +++ b/layout/style/nsStyleAnimation.cpp @@ -749,6 +749,63 @@ LookupStyleContext(nsIContent* aElement) return nsComputedDOMStyle::GetStyleContextForContent(aElement, nsnull, shell); } + +/** + * Helper function: StyleWithDeclarationAdded + * Creates a nsStyleRule with the specified property set to the specified + * value, and returns a nsStyleContext for this rule, as a sibling of the + * given element's nsStyleContext. + * + * If we fail to parse |aSpecifiedValue| for |aProperty|, this method will + * return nsnull. + * + * NOTE: This method uses GetPrimaryShell() to access the style system, + * so it should only be used for style that applies to all presentations, + * rather than for style that only applies to a particular presentation. + * XXX Once we get rid of multiple presentations, we can remove the above + * note. + * + * @param aProperty The property whose value we're customizing in the + * custom style context. + * @param aTargetElement The element whose style context we'll use as a + * sibling for our custom style context. + * @param aSpecifiedValue The value for |aProperty| in our custom style + * context. + * @return The generated custom nsStyleContext, or nsnull on failure. + */ +already_AddRefed +StyleWithDeclarationAdded(nsCSSProperty aProperty, + nsIContent* aTargetElement, + const nsAString& aSpecifiedValue) +{ + NS_ABORT_IF_FALSE(aTargetElement, "null target element"); + NS_ABORT_IF_FALSE(aTargetElement->GetCurrentDoc(), + "element needs to be in a document " + "if we're going to look up its style context"); + + // Look up style context for our target element + nsRefPtr styleContext = LookupStyleContext(aTargetElement); + if (!styleContext) { + return nsnull; + } + + // Parse specified value into a temporary nsICSSStyleRule + nsCOMPtr styleRule = + BuildStyleRule(aProperty, aTargetElement, aSpecifiedValue); + if (!styleRule) { + return nsnull; + } + + // Create a temporary nsStyleContext for the style rule + nsCOMArray ruleArray; + ruleArray.AppendObject(styleRule); + nsStyleSet* styleSet = styleContext->PresContext()->StyleSet(); + return styleSet->ResolveStyleForRules(styleContext->GetParent(), + styleContext->GetPseudo(), + styleContext->GetRuleNode(), + ruleArray); +} + PRBool nsStyleAnimation::ComputeValue(nsCSSProperty aProperty, nsIContent* aTargetElement, @@ -760,27 +817,11 @@ nsStyleAnimation::ComputeValue(nsCSSProperty aProperty, "we should only be able to actively animate nodes that " "are in a document"); - // Look up style context for our target element - nsRefPtr styleContext = LookupStyleContext(aTargetElement); - if (!styleContext) { - return PR_FALSE; - } - - // Parse specified value into a temporary nsICSSStyleRule - nsCOMPtr styleRule = - BuildStyleRule(aProperty, aTargetElement, aSpecifiedValue); - if (!styleRule) { - return PR_FALSE; - } - - // Create a temporary nsStyleContext for the style rule - nsCOMArray ruleArray; - ruleArray.AppendObject(styleRule); - nsStyleSet* styleSet = styleContext->PresContext()->StyleSet(); nsRefPtr tmpStyleContext = - styleSet->ResolveStyleForRules(styleContext->GetParent(), - styleContext->GetPseudo(), - styleContext->GetRuleNode(), ruleArray); + StyleWithDeclarationAdded(aProperty, aTargetElement, aSpecifiedValue); + if (!tmpStyleContext) { + return PR_FALSE; + } // Extract computed value of our property from the temporary style rule return ExtractComputedValue(aProperty, tmpStyleContext, aComputedValue); From e06110f8e813bd1caf5b80a28a55b5abe524710d Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 058/179] Bug 524539, patch 1: In nsStyleAnimation, represent "stroke-dasharray: none" with single-value nsCSSValueList. r=dbaron --- layout/style/nsStyleAnimation.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/layout/style/nsStyleAnimation.cpp b/layout/style/nsStyleAnimation.cpp index f0fb90042528..98d87e44195c 100644 --- a/layout/style/nsStyleAnimation.cpp +++ b/layout/style/nsStyleAnimation.cpp @@ -596,6 +596,15 @@ nsStyleAnimation::AddWeighted(nsCSSProperty aProperty, ++len2; } NS_ABORT_IF_FALSE(len1 > 0 && len2 > 0, "unexpected length"); + if (list1->mValue.GetUnit() == eCSSUnit_None || + list2->mValue.GetUnit() == eCSSUnit_None) { + // One of our values is "none". Can't do addition with that. + NS_ABORT_IF_FALSE( + (list1->mValue.GetUnit() != eCSSUnit_None || len1 == 1) && + (list2->mValue.GetUnit() != eCSSUnit_None || len2 == 1), + "multi-value valuelist with 'none' as first element"); + return PR_FALSE; + } nsAutoPtr result; nsCSSValueList **resultTail = getter_Transfers(result); @@ -1107,8 +1116,10 @@ nsStyleAnimation::ExtractComputedValue(nsCSSProperty aProperty, NS_ABORT_IF_FALSE((svg->mStrokeDasharray != nsnull) == (svg->mStrokeDasharrayLength != 0), "pointer/length mismatch"); + nsAutoPtr result; if (svg->mStrokeDasharray) { - nsAutoPtr result; + NS_ABORT_IF_FALSE(svg->mStrokeDasharrayLength > 0, + "non-null list should have positive length"); nsCSSValueList **resultTail = getter_Transfers(result); for (PRUint32 i = 0, i_end = svg->mStrokeDasharrayLength; i != i_end; ++i) { @@ -1142,11 +1153,15 @@ nsStyleAnimation::ExtractComputedValue(nsCSSProperty aProperty, return PR_FALSE; } } - aComputedValue.SetAndAdoptCSSValueListValue(result.forget(), - eUnit_Dasharray); } else { - aComputedValue.SetNoneValue(); + result = new nsCSSValueList; + if (!result) { + return PR_FALSE; + } + result->mValue.SetNoneValue(); } + aComputedValue.SetAndAdoptCSSValueListValue(result.forget(), + eUnit_Dasharray); break; } From e4eadae38fdaf76ca0737ecf6c8eb9b5333b09c3 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 059/179] Bug 524539, patch 2: Support "stroke-dasharray" property in SVG/SMIL. r=roc --- content/smil/nsSMILCSSProperty.cpp | 16 ++++------------ content/smil/nsSMILCSSValueType.cpp | 11 ++++++++--- content/smil/test/db_smilCSSFromBy.js | 7 +++++++ content/smil/test/db_smilCSSFromTo.js | 18 +++++++++++------- content/smil/test/db_smilCSSPaced.js | 10 ++++++++++ content/smil/test/db_smilCSSPropertyList.js | 2 +- 6 files changed, 41 insertions(+), 23 deletions(-) diff --git a/content/smil/nsSMILCSSProperty.cpp b/content/smil/nsSMILCSSProperty.cpp index aa4b00c853ac..327d4d35a518 100644 --- a/content/smil/nsSMILCSSProperty.cpp +++ b/content/smil/nsSMILCSSProperty.cpp @@ -223,18 +223,6 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID) // XXXdholbert Rect type not yet supported by nsStyleAnimation return PR_FALSE; - // PROPERTIES OF TYPE eCSSType_ValueList - case eCSSProperty_cursor: - case eCSSProperty_stroke_dasharray: - // XXXdholbert List type not yet supported by nsStyleAnimation - return PR_FALSE; - - // PROPERTIES OF TYPE eCSSType_ValuePair - case eCSSProperty_fill: - case eCSSProperty_stroke: - return PR_TRUE; - - // PROPERTIES OF TYPE eCSSType_Value // XXXdholbert: Some properties' types aren't yet supported by // nsStyleAnimation (due to using URI values or string values). I'm // commenting those properties out here for the time being, so that we @@ -244,8 +232,10 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID) case eCSSProperty_color: case eCSSProperty_color_interpolation: case eCSSProperty_color_interpolation_filters: + // case eCSSProperty_cursor: case eCSSProperty_display: case eCSSProperty_dominant_baseline: + case eCSSProperty_fill: case eCSSProperty_fill_opacity: case eCSSProperty_fill_rule: // case eCSSProperty_filter: @@ -270,6 +260,8 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID) case eCSSProperty_shape_rendering: case eCSSProperty_stop_color: case eCSSProperty_stop_opacity: + case eCSSProperty_stroke: + case eCSSProperty_stroke_dasharray: case eCSSProperty_stroke_dashoffset: case eCSSProperty_stroke_linecap: case eCSSProperty_stroke_linejoin: diff --git a/content/smil/nsSMILCSSValueType.cpp b/content/smil/nsSMILCSSValueType.cpp index b92dd907091e..bca04a0e3f4a 100644 --- a/content/smil/nsSMILCSSValueType.cpp +++ b/content/smil/nsSMILCSSValueType.cpp @@ -208,9 +208,14 @@ nsSMILCSSValueType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd, } } - // Special case: font-size-adjust is explicitly non-additive - if (destWrapper->mPropID == eCSSProperty_font_size_adjust) { - return NS_ERROR_FAILURE; + // Special case: font-size-adjust and stroke-dasharray are explicitly + // non-additive (even though nsStyleAnimation *could* support adding them) + switch(valueToAddWrapper->mPropID) { + case eCSSProperty_font_size_adjust: + case eCSSProperty_stroke_dasharray: + return NS_ERROR_FAILURE; + default: + break; } return nsStyleAnimation::Add(destWrapper->mPropID, destWrapper->mCSSValue, *realValueToAdd, aCount) ? diff --git a/content/smil/test/db_smilCSSFromBy.js b/content/smil/test/db_smilCSSFromBy.js index 9fb68bf12089..54e332dc11b0 100644 --- a/content/smil/test/db_smilCSSFromBy.js +++ b/content/smil/test/db_smilCSSFromBy.js @@ -96,5 +96,12 @@ var gFromByBundles = new AnimTestcaseFromBy("1", "1", { midComp: "1.5", toComp: "2" }), new AnimTestcaseFromBy("20.1", "-10", { midComp: "15.1", toComp: "10.1" }), ]), + new TestcaseBundle(gPropList.stroke_dasharray, [ + // These testcases implicitly have no effect, because stroke-dasharray is + // non-additive (and is declared as such in db_smilCSSPropertyList.js) + new AnimTestcaseFromBy("none", "5"), + new AnimTestcaseFromBy("10", "5"), + new AnimTestcaseFromBy("1", "2, 3"), + ]), new TestcaseBundle(gPropList.stroke_width, _fromByTestLists.lengthPx), ]; diff --git a/content/smil/test/db_smilCSSFromTo.js b/content/smil/test/db_smilCSSFromTo.js index 4cd7a6ca8e07..b44a7da7769b 100644 --- a/content/smil/test/db_smilCSSFromTo.js +++ b/content/smil/test/db_smilCSSFromTo.js @@ -365,14 +365,18 @@ var gFromToBundles = [ new AnimTestcaseFromTo("inherit", "rgb(200, 200, 200)", { fromComp: "none"})])), new TestcaseBundle(gPropList.stroke_dasharray, - [].concat(_fromToTestLists.lengthPx, - _fromToTestLists.lengthPxPctSVG, - _fromToTestLists.lengthPctSVG, + [].concat(_fromToTestLists.lengthPctSVG, [ - new AnimTestcaseFromTo("10px", "20px"), - new AnimTestcaseFromTo("1px, 5px", "1px"), - new AnimTestcaseFromTo("1px, 15px", "1px, 2px, 3px, 4px, 5px"), - ]), "need support for CSS value-lists"), + new AnimTestcaseFromTo("inherit", "20", { fromComp: "none"}), + new AnimTestcaseFromTo("1", "none"), + new AnimTestcaseFromTo("10", "20", { midComp: "15"}), + new AnimTestcaseFromTo("1", "2, 3", { fromComp: "1, 1", + midComp: "1.5, 2"}), + new AnimTestcaseFromTo("2, 8", "6", { midComp: "4, 7"}), + new AnimTestcaseFromTo("1, 3", "1, 3, 5, 7, 9", + { fromComp: "1, 3, 1, 3, 1, 3, 1, 3, 1, 3", + midComp: "1, 3, 3, 5, 5, 2, 2, 4, 4, 6"}), + ])), new TestcaseBundle(gPropList.stroke_dashoffset, [].concat(_fromToTestLists.lengthPx, _fromToTestLists.lengthPxPctSVG, diff --git a/content/smil/test/db_smilCSSPaced.js b/content/smil/test/db_smilCSSPaced.js index 4db515d64d8f..7747813c21ad 100644 --- a/content/smil/test/db_smilCSSPaced.js +++ b/content/smil/test/db_smilCSSPaced.js @@ -227,6 +227,16 @@ var gPacedBundles = "need support for more font properties"), ]), new TestcaseBundle(gPropList.opacity, _pacedTestLists.opacity), + new TestcaseBundle(gPropList.stroke_dasharray, + [].concat(_pacedTestLists.lengthPctSVG, [ + new AnimTestcasePaced("7, 7, 7; 7, 10, 3; 1, 2, 3", + { comp0: "7, 7, 7", + comp1_6: "7, 8.5, 5", + comp1_3: "7, 10, 3", + comp2_3: "4, 6, 3", + comp1: "1, 2, 3" + }), + ])), new TestcaseBundle(gPropList.stroke_dashoffset, [].concat(_pacedTestLists.lengthPx, _pacedTestLists.lengthPctSVG, diff --git a/content/smil/test/db_smilCSSPropertyList.js b/content/smil/test/db_smilCSSPropertyList.js index 4b9438098ce6..c98bc227440f 100644 --- a/content/smil/test/db_smilCSSPropertyList.js +++ b/content/smil/test/db_smilCSSPropertyList.js @@ -105,7 +105,7 @@ var gPropList = stop_color: new AdditiveAttribute("stop-color", "CSS", "stop"), stop_opacity: new AdditiveAttribute("stop-opacity", "CSS", "stop"), stroke: new AdditiveAttribute("stroke", "CSS", "rect"), - stroke_dasharray: new AdditiveAttribute("stroke-dasharray", "CSS", "rect"), + stroke_dasharray: new NonAdditiveAttribute("stroke-dasharray", "CSS", "rect"), stroke_dashoffset: new AdditiveAttribute("stroke-dashoffset", "CSS", "rect"), stroke_linecap: new NonAdditiveAttribute("stroke-linecap", "CSS", "rect"), stroke_linejoin: new NonAdditiveAttribute("stroke-linejoin", "CSS", "rect"), From e6e85fc399fa043c162958707dcaa27cdd35b7e8 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 060/179] Bug 529934: Add "UnparsedString" unit to nsStyleAnimation, as catch-all for otherwise-unanimatable properties. r=dbaron --- layout/style/nsStyleAnimation.cpp | 35 +++++++++++++++++++++++++++++++ layout/style/nsStyleAnimation.h | 26 ++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/layout/style/nsStyleAnimation.cpp b/layout/style/nsStyleAnimation.cpp index 98d87e44195c..4c2b33a9f587 100644 --- a/layout/style/nsStyleAnimation.cpp +++ b/layout/style/nsStyleAnimation.cpp @@ -128,6 +128,7 @@ nsStyleAnimation::ComputeDistance(nsCSSProperty aProperty, switch (commonUnit) { case eUnit_Null: case eUnit_None: + case eUnit_UnparsedString: success = PR_FALSE; break; case eUnit_Enumerated: @@ -459,6 +460,7 @@ nsStyleAnimation::AddWeighted(nsCSSProperty aProperty, switch (commonUnit) { case eUnit_Null: case eUnit_None: + case eUnit_UnparsedString: success = PR_FALSE; break; case eUnit_Enumerated: @@ -832,6 +834,11 @@ nsStyleAnimation::ComputeValue(nsCSSProperty aProperty, return PR_FALSE; } + if (nsCSSProps::kAnimTypeTable[aProperty] == eStyleAnimType_None) { + // Just capture the specified value + aComputedValue.SetUnparsedStringValue(nsString(aSpecifiedValue)); + return PR_TRUE; + } // Extract computed value of our property from the temporary style rule return ExtractComputedValue(aProperty, tmpStyleContext, aComputedValue); } @@ -934,6 +941,10 @@ nsStyleAnimation::UncomputeValue(nsCSSProperty aProperty, NS_ABORT_IF_FALSE(aPresContext, "null pres context"); aSpecifiedValue.Truncate(); // Clear outparam, if it's not already empty + if (aComputedValue.GetUnit() == eUnit_UnparsedString) { + aComputedValue.GetStringValue(aSpecifiedValue); + return PR_TRUE; + } nsCSSValuePair vp; nsCSSRect rect; void *ptr = nsnull; @@ -1413,6 +1424,11 @@ nsStyleAnimation::Value::operator=(const Value& aOther) mValue.mCSSValueList = nsnull; } break; + case eUnit_UnparsedString: + NS_ABORT_IF_FALSE(aOther.mValue.mString, "expecting non-null string"); + mValue.mString = aOther.mValue.mString; + mValue.mString->AddRef(); + break; } return *this; @@ -1480,6 +1496,19 @@ nsStyleAnimation::Value::SetColorValue(nscolor aColor) mValue.mColor = aColor; } +void +nsStyleAnimation::Value::SetUnparsedStringValue(const nsString& aString) +{ + FreeValue(); + mUnit = eUnit_UnparsedString; + mValue.mString = nsCSSValue::BufferFromString(aString); + if (NS_UNLIKELY(!mValue.mString)) { + // not much we can do here; just make sure that our promise of a + // non-null mValue.mString holds for string units. + mUnit = eUnit_Null; + } +} + void nsStyleAnimation::Value::SetAndAdoptCSSValuePairValue( nsCSSValuePair *aValuePair, Unit aUnit) @@ -1510,6 +1539,9 @@ nsStyleAnimation::Value::FreeValue() delete mValue.mCSSValueList; } else if (IsCSSValuePairUnit(mUnit)) { delete mValue.mCSSValuePair; + } else if (mUnit == eUnit_UnparsedString) { + NS_ABORT_IF_FALSE(mValue.mString, "expecting non-null string"); + mValue.mString->Release(); } } @@ -1542,6 +1574,9 @@ nsStyleAnimation::Value::operator==(const Value& aOther) const case eUnit_Shadow: return nsCSSValueList::Equal(mValue.mCSSValueList, aOther.mValue.mCSSValueList); + case eUnit_UnparsedString: + return (NS_strcmp(GetStringBufferValue(), + aOther.GetStringBufferValue()) == 0); } NS_NOTREACHED("incomplete case"); diff --git a/layout/style/nsStyleAnimation.h b/layout/style/nsStyleAnimation.h index f7d9726a1413..97cb6d53c9c2 100644 --- a/layout/style/nsStyleAnimation.h +++ b/layout/style/nsStyleAnimation.h @@ -44,6 +44,8 @@ #include "prtypes.h" #include "nsAString.h" +#include "nsCRTGlue.h" +#include "nsStringBuffer.h" #include "nsCSSProperty.h" #include "nsCoord.h" #include "nsColor.h" @@ -233,7 +235,8 @@ public: eUnit_Color, eUnit_CSSValuePair, // nsCSSValuePair* (never null) eUnit_Dasharray, // nsCSSValueList* (never null) - eUnit_Shadow // nsCSSValueList* (may be null) + eUnit_Shadow, // nsCSSValueList* (may be null) + eUnit_UnparsedString // nsStringBuffer* (never null) }; class Value { @@ -246,6 +249,7 @@ public: nscolor mColor; nsCSSValuePair* mCSSValuePair; nsCSSValueList* mCSSValueList; + nsStringBuffer* mString; } mValue; public: Unit GetUnit() const { @@ -287,6 +291,17 @@ public: NS_ASSERTION(IsCSSValueListUnit(mUnit), "unit mismatch"); return mValue.mCSSValueList; } + const PRUnichar* GetStringBufferValue() const { + NS_ASSERTION(IsStringUnit(mUnit), "unit mismatch"); + return GetBufferValue(mValue.mString); + } + + void GetStringValue(nsAString& aBuffer) const { + NS_ASSERTION(IsStringUnit(mUnit), "unit mismatch"); + aBuffer.Truncate(); + PRUint32 len = NS_strlen(GetBufferValue(mValue.mString)); + mValue.mString->ToString(len, aBuffer); + } explicit Value(Unit aUnit = eUnit_Null) : mUnit(aUnit) { NS_ASSERTION(aUnit == eUnit_Null || aUnit == eUnit_Normal || @@ -315,6 +330,8 @@ public: void SetPercentValue(float aPercent); void SetFloatValue(float aFloat); void SetColorValue(nscolor aColor); + void SetUnparsedStringValue(const nsString& aString); + // These setters take ownership of |aValue|, and are therefore named // "SetAndAdopt*". void SetAndAdoptCSSValueListValue(nsCSSValueList *aValue, Unit aUnit); @@ -329,6 +346,10 @@ public: private: void FreeValue(); + static const PRUnichar* GetBufferValue(nsStringBuffer* aBuffer) { + return static_cast(aBuffer->Data()); + } + static PRBool IsIntUnit(Unit aUnit) { return aUnit == eUnit_Enumerated || aUnit == eUnit_Integer; } @@ -338,6 +359,9 @@ public: static PRBool IsCSSValueListUnit(Unit aUnit) { return aUnit == eUnit_Dasharray || aUnit == eUnit_Shadow; } + static PRBool IsStringUnit(Unit aUnit) { + return aUnit == eUnit_UnparsedString; + } }; }; From 10c93fe33cdfe5d0baf031e3dd4ca4822b7df490 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 061/179] Bug 528656: Support "font-family" property in SVG/SMIL. r=roc --- content/smil/nsSMILCSSProperty.cpp | 2 +- content/smil/test/db_smilCSSFromTo.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/smil/nsSMILCSSProperty.cpp b/content/smil/nsSMILCSSProperty.cpp index 327d4d35a518..ec8517ebae97 100644 --- a/content/smil/nsSMILCSSProperty.cpp +++ b/content/smil/nsSMILCSSProperty.cpp @@ -241,7 +241,7 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID) // case eCSSProperty_filter: case eCSSProperty_flood_color: case eCSSProperty_flood_opacity: - // case eCSSProperty_font_family: + case eCSSProperty_font_family: case eCSSProperty_font_size: case eCSSProperty_font_size_adjust: case eCSSProperty_font_stretch: diff --git a/content/smil/test/db_smilCSSFromTo.js b/content/smil/test/db_smilCSSFromTo.js index b44a7da7769b..001fb1b78197 100644 --- a/content/smil/test/db_smilCSSFromTo.js +++ b/content/smil/test/db_smilCSSFromTo.js @@ -255,7 +255,7 @@ var gFromToBundles = [ new TestcaseBundle(gPropList.font_family, [ new AnimTestcaseFromTo("serif", "sans-serif"), new AnimTestcaseFromTo("cursive", "monospace"), - ], "need support for all properties that get stored in nsFont"), + ]), new TestcaseBundle(gPropList.font_size, [].concat(_fromToTestLists.lengthPx, [ new AnimTestcaseFromTo("10px", "40%", { midComp: "15px", toComp: "20px" }), From 43014f2ee6368513b36068ff258a71ad6951fc82 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:27 -0800 Subject: [PATCH 062/179] Bug 520487: Support URI-valued properties in SVG/SMIL. r=roc --- content/smil/nsSMILCSSProperty.cpp | 12 ++++++------ content/smil/test/db_smilCSSFromBy.js | 11 ++++++++++- content/smil/test/db_smilCSSFromTo.js | 12 +++++------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/content/smil/nsSMILCSSProperty.cpp b/content/smil/nsSMILCSSProperty.cpp index ec8517ebae97..f5876951c934 100644 --- a/content/smil/nsSMILCSSProperty.cpp +++ b/content/smil/nsSMILCSSProperty.cpp @@ -228,7 +228,7 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID) // commenting those properties out here for the time being, so that we // don't try to animate them yet. case eCSSProperty_clip_rule: - // case eCSSProperty_clip_path: + case eCSSProperty_clip_path: case eCSSProperty_color: case eCSSProperty_color_interpolation: case eCSSProperty_color_interpolation_filters: @@ -238,7 +238,7 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID) case eCSSProperty_fill: case eCSSProperty_fill_opacity: case eCSSProperty_fill_rule: - // case eCSSProperty_filter: + case eCSSProperty_filter: case eCSSProperty_flood_color: case eCSSProperty_flood_opacity: case eCSSProperty_font_family: @@ -251,10 +251,10 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID) case eCSSProperty_image_rendering: case eCSSProperty_letter_spacing: case eCSSProperty_lighting_color: - // case eCSSProperty_marker_end: - // case eCSSProperty_marker_mid: - // case eCSSProperty_marker_start: - // case eCSSProperty_mask: + case eCSSProperty_marker_end: + case eCSSProperty_marker_mid: + case eCSSProperty_marker_start: + case eCSSProperty_mask: case eCSSProperty_opacity: case eCSSProperty_pointer_events: case eCSSProperty_shape_rendering: diff --git a/content/smil/test/db_smilCSSFromBy.js b/content/smil/test/db_smilCSSFromBy.js index 54e332dc11b0..8fb0bceb14ef 100644 --- a/content/smil/test/db_smilCSSFromBy.js +++ b/content/smil/test/db_smilCSSFromBy.js @@ -74,7 +74,14 @@ var _fromByTestLists = new AnimTestcaseFromBy("url(#gradA)", "url(#gradB) red", { noEffect: 1 }), new AnimTestcaseFromBy("url(#gradA)", "none", { noEffect: 1 }), new AnimTestcaseFromBy("red", "url(#gradA)", { noEffect: 1 }), - ] + ], + URIsAndNone: [ + // No need to specify { noEffect: 1 }, since plain URI-valued properties + // aren't additive + new AnimTestcaseFromBy("url(#idA)", "url(#idB)"), + new AnimTestcaseFromBy("none", "url(#idB)"), + new AnimTestcaseFromBy("url(#idB)", "inherit"), + ], }; // List of attribute/testcase-list bundles to be tested @@ -82,6 +89,8 @@ var gFromByBundles = [ new TestcaseBundle(gPropList.fill, [].concat(_fromByTestLists.color, _fromByTestLists.paint)), + // Check that 'by' animations involving URIs have no effect + new TestcaseBundle(gPropList.filter, _fromByTestLists.URIsAndNone), new TestcaseBundle(gPropList.font_size, _fromByTestLists.lengthPx), new TestcaseBundle(gPropList.font_size_adjust, [ // These testcases implicitly have no effect, because font-size-adjust is diff --git a/content/smil/test/db_smilCSSFromTo.js b/content/smil/test/db_smilCSSFromTo.js index 001fb1b78197..7900e986531d 100644 --- a/content/smil/test/db_smilCSSFromTo.js +++ b/content/smil/test/db_smilCSSFromTo.js @@ -139,15 +139,12 @@ var _fromToTestLists = { URIsAndNone: [ new AnimTestcaseFromTo("url(#idA)", "url(#idB)", { fromComp: "url(\"" + document.URL + "#idA\")", - toComp: "url(\"" + document.URL + "#idB\")"}, - "need support for URI values"), + toComp: "url(\"" + document.URL + "#idB\")"}), new AnimTestcaseFromTo("none", "url(#idB)", - { toComp: "url(\"" + document.URL + "#idB\")"}, - "need support for URI values"), + { toComp: "url(\"" + document.URL + "#idB\")"}), new AnimTestcaseFromTo("url(#idB)", "inherit", { fromComp: "url(\"" + document.URL + "#idB\")", - toComp: "none"}, - "need support for URI values"), + toComp: "none"}), ], }; @@ -331,7 +328,8 @@ var gFromToBundles = [ new TestcaseBundle(gPropList.lighting_color, [].concat(_fromToTestLists.color, _fromToTestLists.colorFromInheritWhite)), - new TestcaseBundle(gPropList.marker, _fromToTestLists.URIsAndNone), + new TestcaseBundle(gPropList.marker, _fromToTestLists.URIsAndNone, + "need support for 'marker' shorthand property"), new TestcaseBundle(gPropList.marker_end, _fromToTestLists.URIsAndNone), new TestcaseBundle(gPropList.marker_mid, _fromToTestLists.URIsAndNone), new TestcaseBundle(gPropList.marker_start, _fromToTestLists.URIsAndNone), From cc4d1f91295ec13e3800eae434c25dc164ac1ca1 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:28 -0800 Subject: [PATCH 063/179] Bug 530199: Cleanup in nsSMILCSSValueType - postpone allocation of ValueWrappers until they're needed. r=roc --- content/smil/nsSMILCSSValueType.cpp | 239 +++++++++++++--------------- 1 file changed, 108 insertions(+), 131 deletions(-) diff --git a/content/smil/nsSMILCSSValueType.cpp b/content/smil/nsSMILCSSValueType.cpp index bca04a0e3f4a..b7955c33fe2e 100644 --- a/content/smil/nsSMILCSSValueType.cpp +++ b/content/smil/nsSMILCSSValueType.cpp @@ -52,11 +52,12 @@ /*static*/ nsSMILCSSValueType nsSMILCSSValueType::sSingleton; struct ValueWrapper { - ValueWrapper() : mCSSValue(), mPropID(eCSSProperty_UNKNOWN), - mPresContext(nsnull) {} + ValueWrapper(nsCSSProperty aPropID, const nsStyleAnimation::Value& aValue, + nsPresContext* aPresContext) : + mPropID(aPropID), mCSSValue(aValue), mPresContext(aPresContext) {} + nsCSSProperty mPropID; nsStyleAnimation::Value mCSSValue; - nsCSSProperty mPropID; nsPresContext* mPresContext; }; @@ -128,14 +129,9 @@ ExtractValueWrapper(const nsSMILValue& aValue) nsresult nsSMILCSSValueType::Init(nsSMILValue& aValue) const { - NS_ABORT_IF_FALSE(aValue.IsNull(), - "Unexpected value type"); - - aValue.mU.mPtr = new ValueWrapper(); - if (!aValue.mU.mPtr) { - return NS_ERROR_OUT_OF_MEMORY; - } + NS_ABORT_IF_FALSE(aValue.IsNull(), "Unexpected SMIL value type"); + aValue.mU.mPtr = nsnull; aValue.mType = this; return NS_OK; } @@ -144,12 +140,8 @@ void nsSMILCSSValueType::Destroy(nsSMILValue& aValue) const { NS_ABORT_IF_FALSE(aValue.mType == this, "Unexpected SMIL value type"); - NS_ABORT_IF_FALSE(aValue.mU.mPtr, - "nsSMILValue for CSS val should have non-null pointer"); - delete static_cast(aValue.mU.mPtr); - aValue.mU.mPtr = nsnull; - aValue.mType = &nsSMILNullType::sSingleton; + aValue.mType = &nsSMILNullType::sSingleton; } nsresult @@ -157,13 +149,25 @@ nsSMILCSSValueType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const { NS_ABORT_IF_FALSE(aDest.mType == aSrc.mType, "Incompatible SMIL types"); NS_ABORT_IF_FALSE(aDest.mType == this, "Unexpected SMIL value type"); - NS_ABORT_IF_FALSE(aDest.mU.mPtr, - "nsSMILValue for CSS val should have non-null pointer"); - NS_ABORT_IF_FALSE(aSrc.mU.mPtr, - "nsSMILValue for CSS val should have non-null pointer"); const ValueWrapper* srcWrapper = ExtractValueWrapper(aSrc); ValueWrapper* destWrapper = ExtractValueWrapper(aDest); - *destWrapper = *srcWrapper; // Directly copy prop ID & CSS value + + if (srcWrapper) { + if (!destWrapper) { + // barely-initialized dest -- need to alloc & copy + aDest.mU.mPtr = new ValueWrapper(*srcWrapper); + if (!aDest.mU.mPtr) { + return NS_ERROR_OUT_OF_MEMORY; + } + } else { + // both already fully-initialized -- just copy straight across + *destWrapper = *srcWrapper; + } + } else if (destWrapper) { + // fully-initialized dest, barely-initialized src -- clear dest + delete destWrapper; + aDest.mU.mPtr = destWrapper = nsnull; + } // else, both are barely-initialized -- nothing to do. return NS_OK; } @@ -178,46 +182,44 @@ nsSMILCSSValueType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd, ValueWrapper* destWrapper = ExtractValueWrapper(aDest); const ValueWrapper* valueToAddWrapper = ExtractValueWrapper(aValueToAdd); + NS_ABORT_IF_FALSE(destWrapper || valueToAddWrapper, + "need at least one fully-initialized value"); - NS_ABORT_IF_FALSE(destWrapper && valueToAddWrapper, - "these pointers shouldn't be null"); + nsCSSProperty property = (valueToAddWrapper ? valueToAddWrapper->mPropID : + destWrapper->mPropID); + // Special case: font-size-adjust and stroke-dasharray are explicitly + // non-additive (even though nsStyleAnimation *could* support adding them) + if (property == eCSSProperty_font_size_adjust || + property == eCSSProperty_stroke_dasharray) { + return NS_ERROR_FAILURE; + } - const nsStyleAnimation::Value* realValueToAdd = &valueToAddWrapper->mCSSValue; - if (destWrapper->mPropID == eCSSProperty_UNKNOWN) { - NS_ABORT_IF_FALSE(destWrapper->mCSSValue.IsNull() && - !destWrapper->mPresContext, - "Partially-initialized ValueWrapper"); - // We need to update destWrapper, since it's part of an outparam. + // Handle barely-initialized "zero" added value. + const nsStyleAnimation::Value* realValueToAdd = valueToAddWrapper ? + &valueToAddWrapper->mCSSValue : + GetZeroValueForUnit(destWrapper->mCSSValue.GetUnit()); + if (!realValueToAdd) { + // No zero value for this unit --> doesn't support addition. + return NS_ERROR_FAILURE; + } + + // Handle barely-initialized "zero" destination. + if (!destWrapper) { + // Need to fully initialize destination, since it's an outparam const nsStyleAnimation::Value* zeroVal = GetZeroValueForUnit(valueToAddWrapper->mCSSValue.GetUnit()); if (!zeroVal) { // No zero value for this unit --> doesn't support addition. return NS_ERROR_FAILURE; } - destWrapper->mCSSValue = *zeroVal; - destWrapper->mPropID = valueToAddWrapper->mPropID; - destWrapper->mPresContext = valueToAddWrapper->mPresContext; - } else if (valueToAddWrapper->mPropID == eCSSProperty_UNKNOWN) { - NS_ABORT_IF_FALSE(valueToAddWrapper->mCSSValue.IsNull() && - !valueToAddWrapper->mPresContext, - "Partially-initialized ValueWrapper"); - realValueToAdd = GetZeroValueForUnit(destWrapper->mCSSValue.GetUnit()); - if (!realValueToAdd) { - // No zero value for this unit --> doesn't support addition. - return NS_ERROR_FAILURE; - } + aDest.mU.mPtr = destWrapper = + new ValueWrapper(property, *zeroVal, valueToAddWrapper->mPresContext); + if (!destWrapper) { + return NS_ERROR_OUT_OF_MEMORY; + } } - // Special case: font-size-adjust and stroke-dasharray are explicitly - // non-additive (even though nsStyleAnimation *could* support adding them) - switch(valueToAddWrapper->mPropID) { - case eCSSProperty_font_size_adjust: - case eCSSProperty_stroke_dasharray: - return NS_ERROR_FAILURE; - default: - break; - } - return nsStyleAnimation::Add(destWrapper->mPropID, destWrapper->mCSSValue, + return nsStyleAnimation::Add(property, destWrapper->mCSSValue, *realValueToAdd, aCount) ? NS_OK : NS_ERROR_FAILURE; } @@ -233,29 +235,18 @@ nsSMILCSSValueType::ComputeDistance(const nsSMILValue& aFrom, const ValueWrapper* fromWrapper = ExtractValueWrapper(aFrom); const ValueWrapper* toWrapper = ExtractValueWrapper(aTo); - NS_ABORT_IF_FALSE(fromWrapper && toWrapper, - "These pointers shouldn't be null"); + NS_ABORT_IF_FALSE(toWrapper, "expecting non-null endpoint"); - const nsStyleAnimation::Value* fromCSSValue; - if (fromWrapper->mPropID == eCSSProperty_UNKNOWN) { - NS_ABORT_IF_FALSE(fromWrapper->mCSSValue.IsNull() && - !fromWrapper->mPresContext, - "Partially-initialized ValueWrapper"); - fromCSSValue = GetZeroValueForUnit(toWrapper->mCSSValue.GetUnit()); - if (!fromCSSValue) { - // No zero value for this unit --> doesn't support distance-computation. - return NS_ERROR_FAILURE; - } - } else { - fromCSSValue = &fromWrapper->mCSSValue; + const nsStyleAnimation::Value* fromCSSValue = fromWrapper ? + &fromWrapper->mCSSValue : + GetZeroValueForUnit(toWrapper->mCSSValue.GetUnit()); + if (!fromCSSValue) { + // No zero value for this unit --> doesn't support distance-computation. + return NS_ERROR_FAILURE; } - NS_ABORT_IF_FALSE(toWrapper->mPropID != eCSSProperty_UNKNOWN && - !toWrapper->mCSSValue.IsNull() && toWrapper->mPresContext, - "ComputeDistance endpoint should be a parsed value"); - return nsStyleAnimation::ComputeDistance(toWrapper->mPropID, - *fromCSSValue, toWrapper->mCSSValue, - aDistance) ? + return nsStyleAnimation::ComputeDistance(toWrapper->mPropID, *fromCSSValue, + toWrapper->mCSSValue, aDistance) ? NS_OK : NS_ERROR_FAILURE; } @@ -275,40 +266,39 @@ nsSMILCSSValueType::Interpolate(const nsSMILValue& aStartVal, const ValueWrapper* startWrapper = ExtractValueWrapper(aStartVal); const ValueWrapper* endWrapper = ExtractValueWrapper(aEndVal); - ValueWrapper* resultWrapper = ExtractValueWrapper(aResult); + NS_ABORT_IF_FALSE(endWrapper, "expecting non-null endpoint"); + NS_ABORT_IF_FALSE(!aResult.mU.mPtr, "expecting barely-initialized outparam"); - NS_ABORT_IF_FALSE(startWrapper && endWrapper && resultWrapper, - "These pointers shouldn't be null"); - - const nsStyleAnimation::Value* startCSSValue; - if (startWrapper->mPropID == eCSSProperty_UNKNOWN) { - NS_ABORT_IF_FALSE(startWrapper->mCSSValue.IsNull() && - !startWrapper->mPresContext, - "Partially-initialized ValueWrapper"); - startCSSValue = GetZeroValueForUnit(endWrapper->mCSSValue.GetUnit()); - if (!startCSSValue) { - // No zero value for this unit --> doesn't support interpolation. - return NS_ERROR_FAILURE; - } - } else { - startCSSValue = &startWrapper->mCSSValue; + const nsStyleAnimation::Value* startCSSValue = startWrapper ? + &startWrapper->mCSSValue : + GetZeroValueForUnit(endWrapper->mCSSValue.GetUnit()); + if (!startCSSValue) { + // No zero value for this unit --> doesn't support interpolation. + return NS_ERROR_FAILURE; } - NS_ABORT_IF_FALSE(endWrapper->mPropID != eCSSProperty_UNKNOWN && - !endWrapper->mCSSValue.IsNull() && endWrapper->mPresContext, - "Interpolate endpoint should be a parsed value"); - - if (nsStyleAnimation::Interpolate(endWrapper->mPropID, - *startCSSValue, - endWrapper->mCSSValue, - aUnitDistance, - resultWrapper->mCSSValue)) { - resultWrapper->mPropID = endWrapper->mPropID; - resultWrapper->mPresContext = endWrapper->mPresContext; - return NS_OK; + + nsStyleAnimation::Value resultValue; + if (nsStyleAnimation::Interpolate(endWrapper->mPropID, *startCSSValue, + endWrapper->mCSSValue, aUnitDistance, + resultValue)) { + aResult.mU.mPtr = new ValueWrapper(endWrapper->mPropID, resultValue, + endWrapper->mPresContext); + return aResult.mU.mPtr ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } return NS_ERROR_FAILURE; } +// Helper function to extract presContext +static nsPresContext* +GetPresContextForElement(nsIContent* aElem) +{ + nsIDocument* doc = aElem->GetCurrentDoc(); + NS_ABORT_IF_FALSE(doc, "active animations should only be able to " + "target elements that are in a document"); + nsIPresShell* shell = doc->GetPrimaryShell(); + return shell ? shell->GetPresContext() : nsnull; +} + PRBool nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID, nsIContent* aTargetElement, @@ -320,6 +310,13 @@ nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID, NS_ABORT_IF_FALSE(aPropID < eCSSProperty_COUNT_no_shorthands, "nsSMILCSSValueType shouldn't be used with " "shorthand properties"); + NS_ABORT_IF_FALSE(!aValue.mU.mPtr, "expecting barely-initialized outparam"); + + nsPresContext* presContext = GetPresContextForElement(aTargetElement); + if (!presContext) { + NS_WARNING("Not parsing animation value; unable to get PresContext"); + return PR_FALSE; + } // If value is negative, we'll strip off the "-" so the CSS parser won't // barf, and then manually make the parsed value negative. (This is a partial @@ -333,40 +330,21 @@ nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID, isNegative = PR_TRUE; } nsDependentSubstring subString(aString, subStringBegin); - ValueWrapper* wrapper = ExtractValueWrapper(aValue); - NS_ABORT_IF_FALSE(wrapper, "Wrapper should be non-null if type is set."); - + nsStyleAnimation::Value parsedValue; if (nsStyleAnimation::ComputeValue(aPropID, aTargetElement, - subString, wrapper->mCSSValue)) { - wrapper->mPropID = aPropID; + subString, parsedValue)) { if (isNegative) { - InvertSign(wrapper->mCSSValue); + InvertSign(parsedValue); } - // Cache a reference to the PresContext, if we've got one - nsIDocument* doc = aTargetElement->GetCurrentDoc(); - NS_ABORT_IF_FALSE(doc, "active animations should only be able to " - "target elements that are in a document"); - nsIPresShell* shell = doc->GetPrimaryShell(); - if (shell) { - wrapper->mPresContext = shell->GetPresContext(); - } - if (wrapper->mPresContext) { + if (aPropID == eCSSProperty_font_size) { // Divide out text-zoom, since SVG is supposed to ignore it - if (aPropID == eCSSProperty_font_size) { - NS_ABORT_IF_FALSE(wrapper->mCSSValue.GetUnit() == - nsStyleAnimation::eUnit_Coord, - "'font-size' value with unexpected style unit"); - wrapper->mCSSValue.SetCoordValue(wrapper->mCSSValue.GetCoordValue() / - wrapper->mPresContext->TextZoom()); - } - return PR_TRUE; + NS_ABORT_IF_FALSE(parsedValue.GetUnit() == nsStyleAnimation::eUnit_Coord, + "'font-size' value with unexpected style unit"); + parsedValue.SetCoordValue(parsedValue.GetCoordValue() / + presContext->TextZoom()); } - // Crap! We lack a PresContext or a PresShell - NS_NOTREACHED("Not parsing animation value; unable to get PresContext"); - // Destroy & re-initialize aValue to make sure we leave it in a - // consistent state - Destroy(aValue); - Init(aValue); + aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue, presContext); + return aValue.mU.mPtr != nsnull; } return PR_FALSE; } @@ -377,9 +355,8 @@ nsSMILCSSValueType::ValueToString(const nsSMILValue& aValue, { NS_ABORT_IF_FALSE(aValue.mType == &nsSMILCSSValueType::sSingleton, "Passed-in value is wrong type"); - const ValueWrapper* wrapper = ExtractValueWrapper(aValue); - return nsStyleAnimation::UncomputeValue(wrapper->mPropID, - wrapper->mPresContext, - wrapper->mCSSValue, aString); + return !wrapper || + nsStyleAnimation::UncomputeValue(wrapper->mPropID, wrapper->mPresContext, + wrapper->mCSSValue, aString); } From 45a32254c2e29747a3c41beff3c13fffa25975b8 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:28 -0800 Subject: [PATCH 064/179] Bug 520239, patch 2: Add support for shorthand properties in nsStyleAnimation's helper function 'BuildStyleRule'. r=dbaron --- layout/style/nsStyleAnimation.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/layout/style/nsStyleAnimation.cpp b/layout/style/nsStyleAnimation.cpp index 4c2b33a9f587..c70d54f54479 100644 --- a/layout/style/nsStyleAnimation.cpp +++ b/layout/style/nsStyleAnimation.cpp @@ -725,10 +725,13 @@ BuildStyleRule(nsCSSProperty aProperty, nsCOMPtr parser; nsCOMPtr styleRule; - // The next statement performs the following, in sequence: Get parser, use - // parser to parse property, check that parsing succeeded, and build a rule - // for the resulting declaration. If any of these steps fails, we bail out - // and delete the declaration. + nsCSSProperty propertyToCheck = nsCSSProps::IsShorthand(aProperty) ? + nsCSSProps::SubpropertyEntryFor(aProperty)[0] : aProperty; + + // The next clause performs the following, in sequence: Initialize our + // declaration, get a parser, parse property, check that parsing succeeded, + // and build a rule for the resulting declaration. If any of these steps + // fails, we bail out and delete the declaration. if (!declaration->InitializeEmpty() || NS_FAILED(doc->CSSLoader()->GetParserFor(nsnull, getter_AddRefs(parser))) || @@ -737,7 +740,7 @@ BuildStyleRule(nsCSSProperty aProperty, aTargetElement->NodePrincipal(), declaration, &changed)) || // SlotForValue checks whether property parsed w/out CSS parsing errors - !declaration->SlotForValue(aProperty) || + !declaration->SlotForValue(propertyToCheck) || NS_FAILED(NS_NewCSSStyleRule(getter_AddRefs(styleRule), nsnull, declaration))) { NS_WARNING("failure in BuildStyleRule"); @@ -834,7 +837,8 @@ nsStyleAnimation::ComputeValue(nsCSSProperty aProperty, return PR_FALSE; } - if (nsCSSProps::kAnimTypeTable[aProperty] == eStyleAnimType_None) { + if (nsCSSProps::IsShorthand(aProperty) || + nsCSSProps::kAnimTypeTable[aProperty] == eStyleAnimType_None) { // Just capture the specified value aComputedValue.SetUnparsedStringValue(nsString(aSpecifiedValue)); return PR_TRUE; From 17ce1f0741098ed6f4aecf63ebc5c1def7612432 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:28 -0800 Subject: [PATCH 065/179] Bug 520239, patch 5: Enable SVG/SMIL animation of shorthand properties, and remove unneeded nsISMILCSSValueType interface. r=roc --- content/smil/nsISMILCSSValueType.h | 118 -------------------- content/smil/nsSMILCSSProperty.cpp | 43 +++---- content/smil/nsSMILCSSValueType.cpp | 3 - content/smil/nsSMILCSSValueType.h | 49 ++++++-- content/smil/test/db_smilCSSFromBy.js | 12 ++ content/smil/test/db_smilCSSFromTo.js | 8 +- content/smil/test/test_smilCSSFromBy.xhtml | 1 + layout/reftests/svg/smil/style/reftest.list | 3 +- 8 files changed, 68 insertions(+), 169 deletions(-) delete mode 100644 content/smil/nsISMILCSSValueType.h diff --git a/content/smil/nsISMILCSSValueType.h b/content/smil/nsISMILCSSValueType.h deleted file mode 100644 index 8b6b2b24d352..000000000000 --- a/content/smil/nsISMILCSSValueType.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Mozilla SMIL module. - * - * The Initial Developer of the Original Code is the Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Daniel Holbert - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* interface for accessing CSS values stored in nsSMILValue objects */ - -#ifndef NS_ISMILCSSVALUETYPE_H_ -#define NS_ISMILCSSVALUETYPE_H_ - -#include "nsISMILType.h" -#include "nsCSSProperty.h" -#include "nscore.h" // For NS_OVERRIDE - -class nsPresContext; -class nsIContent; -class nsAString; - -////////////////////////////////////////////////////////////////////////////// -// nsISMILCSSValueType: Customized version of the nsISMILType interface, with -// some additional methods for parsing & extracting CSS values, so that the -// details of the value-storage representation can be abstracted away. - -class nsISMILCSSValueType : public nsISMILType -{ -public: - // Methods inherited from nsISMILType - // ---------------------------------- - NS_OVERRIDE virtual nsresult Init(nsSMILValue& aValue) const = 0; - NS_OVERRIDE virtual void Destroy(nsSMILValue& aValue) const = 0; - NS_OVERRIDE virtual nsresult Assign(nsSMILValue& aDest, - const nsSMILValue& aSrc) const = 0; - NS_OVERRIDE virtual nsresult Add(nsSMILValue& aDest, - const nsSMILValue& aValueToAdd, - PRUint32 aCount) const = 0; - NS_OVERRIDE virtual nsresult ComputeDistance(const nsSMILValue& aFrom, - const nsSMILValue& aTo, - double& aDistance) const = 0; - NS_OVERRIDE virtual nsresult Interpolate(const nsSMILValue& aStartVal, - const nsSMILValue& aEndVal, - double aUnitDistance, - nsSMILValue& aResult) const = 0; - - /* - * Virtual destructor: nothing to do here, but subclasses - * may need it. - */ - virtual ~nsISMILCSSValueType() {}; - - // Methods introduced in this interface - // ------------------------------------ - // These are helper methods used by nsSMILCSSProperty - these let us keep - // our data representation private. - - /** - * Sets up the given nsSMILValue to represent the given string value. The - * string is interpreted as a value for the given property on the given - * element. - * - * Note: aValue is expected to be freshly initialized (i.e. it should have - * been passed into the "Init()" method of some nsISMILCSSValueType subclass) - * - * @param aPropID The property for which we're parsing a value. - * @param aTargetElement The target element to whom the property/value - * setting applies. - * @param aString The string to be parsed as a CSS value. - * @param [out] aValue The nsSMILValue to be populated. - * @return PR_TRUE on success, PR_FALSE on failure. - */ - virtual PRBool ValueFromString(nsCSSProperty aPropID, - nsIContent* aTargetElement, - const nsAString& aString, - nsSMILValue& aValue) const = 0; - - /** - * Creates a string representation of the given nsSMILValue. - * - * @param aValue The nsSMILValue to be converted into a string. - * @param [out] aString The string to be populated with the given value. - * @return PR_TRUE on success, PR_FALSE on failure. - */ - virtual PRBool ValueToString(const nsSMILValue& aValue, - nsAString& aString) const = 0; -}; - -#endif // NS_ISMILCSSVALUETYPE_H_ diff --git a/content/smil/nsSMILCSSProperty.cpp b/content/smil/nsSMILCSSProperty.cpp index f5876951c934..1415e8c2b0f0 100644 --- a/content/smil/nsSMILCSSProperty.cpp +++ b/content/smil/nsSMILCSSProperty.cpp @@ -38,7 +38,6 @@ /* representation of a SMIL-animatable CSS property on an element */ #include "nsSMILCSSProperty.h" -#include "nsISMILCSSValueType.h" #include "nsSMILCSSValueType.h" #include "nsSMILValue.h" #include "nsCSSDeclaration.h" @@ -47,20 +46,6 @@ #include "nsIContent.h" #include "nsPIDOMWindow.h" -// Helper Functions -static nsISMILCSSValueType* -GetSMILTypeForProperty(nsCSSProperty aPropID) -{ - if (!nsSMILCSSProperty::IsPropertyAnimatable(aPropID)) { - NS_NOTREACHED("Attempting to animate an un-animatable property"); - return nsnull; - } - if (aPropID < eCSSProperty_COUNT_no_shorthands) { - return &nsSMILCSSValueType::sSingleton; - } - return nsnull; // XXXdholbert Return shorthand type here, when we add it -} - static PRBool GetCSSComputedValue(nsIContent* aElem, nsCSSProperty aPropID, @@ -125,13 +110,12 @@ nsSMILCSSProperty::GetBaseValue() const nsSMILValue baseValue; if (didGetComputedVal) { // (4) Create the nsSMILValue from the computed style value - nsISMILCSSValueType* smilType = GetSMILTypeForProperty(mPropID); - NS_ABORT_IF_FALSE(smilType, "animating an unsupported type"); - - smilType->Init(baseValue); - if (!smilType->ValueFromString(mPropID, mElement, - computedStyleVal, baseValue)) { - smilType->Destroy(baseValue); + nsSMILCSSValueType::sSingleton.Init(baseValue); + if (!nsCSSProps::IsShorthand(mPropID) && + !nsSMILCSSValueType::sSingleton.ValueFromString(mPropID, mElement, + computedStyleVal, + baseValue)) { + nsSMILCSSValueType::sSingleton.Destroy(baseValue); NS_ABORT_IF_FALSE(baseValue.IsNull(), "Destroy should leave us with null-typed value"); } @@ -145,11 +129,12 @@ nsSMILCSSProperty::ValueFromString(const nsAString& aStr, nsSMILValue& aValue) const { NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE); - nsISMILCSSValueType* smilType = GetSMILTypeForProperty(mPropID); - smilType->Init(aValue); - PRBool success = smilType->ValueFromString(mPropID, mElement, aStr, aValue); + nsSMILCSSValueType::sSingleton.Init(aValue); + PRBool success = + nsSMILCSSValueType::sSingleton.ValueFromString(mPropID, mElement, + aStr, aValue); if (!success) { - smilType->Destroy(aValue); + nsSMILCSSValueType::sSingleton.Destroy(aValue); } return success ? NS_OK : NS_ERROR_FAILURE; } @@ -161,9 +146,8 @@ nsSMILCSSProperty::SetAnimValue(const nsSMILValue& aValue) nsresult rv = NS_OK; nsAutoString valStr; - nsISMILCSSValueType* smilType = GetSMILTypeForProperty(mPropID); - if (smilType->ValueToString(aValue, valStr)) { + if (nsSMILCSSValueType::sSingleton.ValueToString(aValue, valStr)) { // Apply the style to the target element nsCOMPtr overrideStyle; mElement->GetSMILOverrideStyle(getter_AddRefs(overrideStyle)); @@ -215,8 +199,7 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID) case eCSSProperty_font: case eCSSProperty_marker: case eCSSProperty_overflow: - // XXXdholbert Shorthand types not yet supported - return PR_FALSE; + return PR_TRUE; // PROPERTIES OF TYPE eCSSType_Rect case eCSSProperty_clip: diff --git a/content/smil/nsSMILCSSValueType.cpp b/content/smil/nsSMILCSSValueType.cpp index b7955c33fe2e..8962371e38e9 100644 --- a/content/smil/nsSMILCSSValueType.cpp +++ b/content/smil/nsSMILCSSValueType.cpp @@ -307,9 +307,6 @@ nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID, { NS_ABORT_IF_FALSE(aValue.mType == &nsSMILCSSValueType::sSingleton, "Passed-in value is wrong type"); - NS_ABORT_IF_FALSE(aPropID < eCSSProperty_COUNT_no_shorthands, - "nsSMILCSSValueType shouldn't be used with " - "shorthand properties"); NS_ABORT_IF_FALSE(!aValue.mU.mPtr, "expecting barely-initialized outparam"); nsPresContext* presContext = GetPresContextForElement(aTargetElement); diff --git a/content/smil/nsSMILCSSValueType.h b/content/smil/nsSMILCSSValueType.h index 9a79b27bfc5e..e97d226ed73d 100644 --- a/content/smil/nsSMILCSSValueType.h +++ b/content/smil/nsSMILCSSValueType.h @@ -40,16 +40,18 @@ #ifndef NS_SMILCSSVALUETYPE_H_ #define NS_SMILCSSVALUETYPE_H_ -#include "nsISMILCSSValueType.h" +#include "nsISMILType.h" +#include "nsCSSProperty.h" #include "nscore.h" // For NS_OVERRIDE +class nsPresContext; class nsIContent; +class nsAString; /* - * nsSMILCSSValueType: Represents a SMIL-animated simple (non-shorthand) CSS - * value. + * nsSMILCSSValueType: Represents a SMIL-animated CSS value. */ -class nsSMILCSSValueType : public nsISMILCSSValueType +class nsSMILCSSValueType : public nsISMILType { public: // nsISMILValueType Methods @@ -69,15 +71,38 @@ public: double aUnitDistance, nsSMILValue& aResult) const; - // nsISMILCSSValueType Methods - // --------------------------- - NS_OVERRIDE virtual PRBool ValueFromString(nsCSSProperty aPropID, - nsIContent* aTargetElement, - const nsAString& aString, - nsSMILValue& aValue) const; + /** + * Sets up the given nsSMILValue to represent the given string value. The + * string is interpreted as a value for the given property on the given + * element. + * + * Note: aValue is expected to be freshly initialized (i.e. it should already + * have been passed into nsSMILCSSValueType::Init(), and it should not have + * been set up further via e.g. Assign() or another ValueFromString() call.) + * + * @param aPropID The property for which we're parsing a value. + * @param aTargetElement The target element to whom the property/value + * setting applies. + * @param aString The string to be parsed as a CSS value. + * @param [out] aValue The nsSMILValue to be populated. + * @return PR_TRUE on success, PR_FALSE on failure. + */ + PRBool ValueFromString(nsCSSProperty aPropID, nsIContent* aTargetElement, + const nsAString& aString, nsSMILValue& aValue) const; - NS_OVERRIDE virtual PRBool ValueToString(const nsSMILValue& aValue, - nsAString& aString) const; + /** + * Creates a string representation of the given nsSMILValue. + * + * Note: aValue is expected to be of this type (that is, it's expected to + * have been initialized by nsSMILCSSValueType::sSingleton). If aValue is a + * freshly-initialized value, this method will succeed, though the resulting + * string will be empty. + * + * @param aValue The nsSMILValue to be converted into a string. + * @param [out] aString The string to be populated with the given value. + * @return PR_TRUE on success, PR_FALSE on failure. + */ + PRBool ValueToString(const nsSMILValue& aValue, nsAString& aString) const; // Singleton for nsSMILValue objects to hold onto. static nsSMILCSSValueType sSingleton; diff --git a/content/smil/test/db_smilCSSFromBy.js b/content/smil/test/db_smilCSSFromBy.js index 8fb0bceb14ef..43aacdb11dcf 100644 --- a/content/smil/test/db_smilCSSFromBy.js +++ b/content/smil/test/db_smilCSSFromBy.js @@ -91,6 +91,10 @@ var gFromByBundles = _fromByTestLists.paint)), // Check that 'by' animations involving URIs have no effect new TestcaseBundle(gPropList.filter, _fromByTestLists.URIsAndNone), + new TestcaseBundle(gPropList.font, [ + new AnimTestcaseFromBy("10px serif", + "normal normal 400 100px / 10px monospace"), + ]), new TestcaseBundle(gPropList.font_size, _fromByTestLists.lengthPx), new TestcaseBundle(gPropList.font_size_adjust, [ // These testcases implicitly have no effect, because font-size-adjust is @@ -100,6 +104,14 @@ var gFromByBundles = new AnimTestcaseFromBy("0.1", "none") ]), new TestcaseBundle(gPropList.lighting_color, _fromByTestLists.color), + new TestcaseBundle(gPropList.marker, _fromByTestLists.URIsAndNone), + new TestcaseBundle(gPropList.marker_end, _fromByTestLists.URIsAndNone), + new TestcaseBundle(gPropList.marker_mid, _fromByTestLists.URIsAndNone), + new TestcaseBundle(gPropList.marker_start, _fromByTestLists.URIsAndNone), + new TestcaseBundle(gPropList.overflow, [ + new AnimTestcaseFromBy("inherit", "auto"), + new AnimTestcaseFromBy("scroll", "hidden") + ]), new TestcaseBundle(gPropList.opacity, _fromByTestLists.opacity), new TestcaseBundle(gPropList.stroke_miterlimit, [ new AnimTestcaseFromBy("1", "1", { midComp: "1.5", toComp: "2" }), diff --git a/content/smil/test/db_smilCSSFromTo.js b/content/smil/test/db_smilCSSFromTo.js index 7900e986531d..5b74049e7674 100644 --- a/content/smil/test/db_smilCSSFromTo.js +++ b/content/smil/test/db_smilCSSFromTo.js @@ -248,7 +248,7 @@ var gFromToBundles = [ toComp: "normal normal 400 100px / 10px monospace"}), new AnimTestcaseFromTo("oblique normal 200 30px / 10px cursive", "normal small-caps 800 40px / 10px serif"), - ], "need support for 'font' shorthand"), + ]), new TestcaseBundle(gPropList.font_family, [ new AnimTestcaseFromTo("serif", "sans-serif"), new AnimTestcaseFromTo("cursive", "monospace"), @@ -328,8 +328,7 @@ var gFromToBundles = [ new TestcaseBundle(gPropList.lighting_color, [].concat(_fromToTestLists.color, _fromToTestLists.colorFromInheritWhite)), - new TestcaseBundle(gPropList.marker, _fromToTestLists.URIsAndNone, - "need support for 'marker' shorthand property"), + new TestcaseBundle(gPropList.marker, _fromToTestLists.URIsAndNone), new TestcaseBundle(gPropList.marker_end, _fromToTestLists.URIsAndNone), new TestcaseBundle(gPropList.marker_mid, _fromToTestLists.URIsAndNone), new TestcaseBundle(gPropList.marker_start, _fromToTestLists.URIsAndNone), @@ -337,8 +336,9 @@ var gFromToBundles = [ new TestcaseBundle(gPropList.opacity, _fromToTestLists.opacity), new TestcaseBundle(gPropList.overflow, [ new AnimTestcaseFromTo("auto", "visible"), + new AnimTestcaseFromTo("inherit", "visible", { fromComp: "hidden" }), new AnimTestcaseFromTo("scroll", "auto"), - ], "need support for 'overflow' shorthand"), + ]), new TestcaseBundle(gPropList.pointer_events, [ new AnimTestcaseFromTo("visibleFill", "stroke", { fromComp: "visiblefill" }), diff --git a/content/smil/test/test_smilCSSFromBy.xhtml b/content/smil/test/test_smilCSSFromBy.xhtml index 90ad54632c08..859867a7831e 100644 --- a/content/smil/test/test_smilCSSFromBy.xhtml +++ b/content/smil/test/test_smilCSSFromBy.xhtml @@ -18,6 +18,7 @@ more predictable. (otherwise, line-height varies depending on platform) --> testing 123 + diff --git a/layout/reftests/svg/smil/style/reftest.list b/layout/reftests/svg/smil/style/reftest.list index a385cfc71138..7ef343d6ed8e 100644 --- a/layout/reftests/svg/smil/style/reftest.list +++ b/layout/reftests/svg/smil/style/reftest.list @@ -66,8 +66,7 @@ fails == anim-css-fillopacity-3-clamp-big.svg anim-css-fillopacity-3-ref.svg == anim-css-fillopacity-3-clamp-small.svg anim-css-fillopacity-3-ref.svg # 'font' shorthand property -# XXXdholbert We don't yet support animating shorthand properties (bug 520239) -fails == anim-css-font-1.svg anim-css-font-1-ref.svg +== anim-css-font-1.svg anim-css-font-1-ref.svg # 'font-size' property, from/by/to with pixel values only == anim-css-fontsize-1-from-by-px-px.svg anim-css-fontsize-1-ref.svg From a4f10a3bdf410e86813385af64807fd950e651f0 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 10 Dec 2009 09:26:28 -0800 Subject: [PATCH 066/179] Bug 530675: Support "cursor" property in SVG/SMIL. r=roc --- content/smil/nsSMILCSSProperty.cpp | 6 +----- content/smil/test/db_smilCSSFromBy.js | 4 ++++ content/smil/test/db_smilCSSFromTo.js | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/content/smil/nsSMILCSSProperty.cpp b/content/smil/nsSMILCSSProperty.cpp index 1415e8c2b0f0..195394a8b50f 100644 --- a/content/smil/nsSMILCSSProperty.cpp +++ b/content/smil/nsSMILCSSProperty.cpp @@ -206,16 +206,12 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID) // XXXdholbert Rect type not yet supported by nsStyleAnimation return PR_FALSE; - // XXXdholbert: Some properties' types aren't yet supported by - // nsStyleAnimation (due to using URI values or string values). I'm - // commenting those properties out here for the time being, so that we - // don't try to animate them yet. case eCSSProperty_clip_rule: case eCSSProperty_clip_path: case eCSSProperty_color: case eCSSProperty_color_interpolation: case eCSSProperty_color_interpolation_filters: - // case eCSSProperty_cursor: + case eCSSProperty_cursor: case eCSSProperty_display: case eCSSProperty_dominant_baseline: case eCSSProperty_fill: diff --git a/content/smil/test/db_smilCSSFromBy.js b/content/smil/test/db_smilCSSFromBy.js index 43aacdb11dcf..c5b86e7a075f 100644 --- a/content/smil/test/db_smilCSSFromBy.js +++ b/content/smil/test/db_smilCSSFromBy.js @@ -87,6 +87,10 @@ var _fromByTestLists = // List of attribute/testcase-list bundles to be tested var gFromByBundles = [ + // Check that 'by' animations for 'cursor' has no effect + new TestcaseBundle(gPropList.cursor, [ + new AnimTestcaseFromBy("crosshair", "move"), + ]), new TestcaseBundle(gPropList.fill, [].concat(_fromByTestLists.color, _fromByTestLists.paint)), // Check that 'by' animations involving URIs have no effect diff --git a/content/smil/test/db_smilCSSFromTo.js b/content/smil/test/db_smilCSSFromTo.js index 5b74049e7674..78b79138fb29 100644 --- a/content/smil/test/db_smilCSSFromTo.js +++ b/content/smil/test/db_smilCSSFromTo.js @@ -183,8 +183,8 @@ var gFromToBundles = [ new AnimTestcaseFromTo("url('a.cur'), url('b.cur'), nw-resize", "sw-resize", { fromComp: "url(\"" + _testPath + "/a.cur\"), " + "url(\"" + _testPath + "/b.cur\"), " + - "nw-resize"}) - ], "need support for CSS value-lists and URI values"), + "nw-resize"}), + ]), new TestcaseBundle(gPropList.direction, [ new AnimTestcaseFromTo("ltr", "rtl"), new AnimTestcaseFromTo("rtl", "inherit"), From 41892fd0c4f4d84a038e64d49e4852a75cd374ec Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Thu, 10 Dec 2009 10:58:33 -0800 Subject: [PATCH 067/179] Bug 528829 - If mouse button is held down during page transition, Firefox stops responding to mouse clicks, r=roc --- layout/base/nsPresShell.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 7100da93718a..171d0536317f 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1028,6 +1028,18 @@ protected: // Utility method to restore the root scrollframe state void RestoreRootScrollPosition(); + void MaybeReleaseCapturingContent() + { + nsCOMPtr frameSelection = FrameSelection(); + if (frameSelection) { + frameSelection->SetMouseDownState(PR_FALSE); + } + if (gCaptureInfo.mContent && + gCaptureInfo.mContent->GetOwnerDoc() == mDocument) { + SetCapturingContent(nsnull, 0); + } + } + nsCOMPtr mPrefStyleSheet; // mStyleSet owns it but we // maintain a ref, may be null #ifdef DEBUG @@ -1832,6 +1844,8 @@ PresShell::Destroy() if (mHaveShutDown) return NS_OK; + MaybeReleaseCapturingContent(); + mContentToScrollTo = nsnull; if (mPresContext) { @@ -7075,6 +7089,8 @@ FreezeSubDocument(nsIDocument *aDocument, void *aData) void PresShell::Freeze() { + MaybeReleaseCapturingContent(); + mDocument->EnumerateFreezableElements(FreezeElement, this); if (mCaret) From b7d64d42bc408367f2716e55eb223b4dca16565d Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Thu, 10 Dec 2009 11:12:19 -0800 Subject: [PATCH 068/179] Bug 342045 - Fix O(n^2) access to all the children of a container, r=marcoz, davidb --- .../src/atk/nsApplicationAccessibleWrap.cpp | 22 +- accessible/src/base/nsAccessible.cpp | 608 ++++++++++-------- accessible/src/base/nsAccessible.h | 134 ++-- .../src/base/nsApplicationAccessible.cpp | 256 +++----- accessible/src/base/nsApplicationAccessible.h | 28 +- .../src/base/nsBaseWidgetAccessible.cpp | 9 +- accessible/src/base/nsCoreUtils.cpp | 2 +- accessible/src/base/nsCoreUtils.h | 2 +- accessible/src/base/nsDocAccessible.cpp | 131 ++-- accessible/src/base/nsDocAccessible.h | 3 +- accessible/src/base/nsOuterDocAccessible.cpp | 31 +- accessible/src/base/nsOuterDocAccessible.h | 12 +- accessible/src/base/nsRootAccessible.cpp | 58 +- accessible/src/base/nsRootAccessible.h | 2 +- accessible/src/base/nsTextAccessible.cpp | 1 - accessible/src/html/nsHTMLAreaAccessible.cpp | 1 - accessible/src/html/nsHTMLImageAccessible.cpp | 40 +- accessible/src/html/nsHTMLImageAccessible.h | 1 + .../src/html/nsHTMLSelectAccessible.cpp | 255 +++----- accessible/src/html/nsHTMLSelectAccessible.h | 29 +- accessible/src/html/nsHTMLTableAccessible.cpp | 54 +- accessible/src/html/nsHTMLTextAccessible.cpp | 34 +- accessible/src/html/nsHTMLTextAccessible.h | 7 +- accessible/src/html/nsHyperTextAccessible.cpp | 78 ++- accessible/src/html/nsHyperTextAccessible.h | 7 +- accessible/src/msaa/nsAccessibleWrap.cpp | 29 +- .../src/msaa/nsHTMLWin32ObjectAccessible.cpp | 62 +- .../src/msaa/nsHTMLWin32ObjectAccessible.h | 9 +- accessible/src/xforms/nsXFormsAccessible.cpp | 29 +- .../xforms/nsXFormsFormControlsAccessible.h | 10 +- .../src/xforms/nsXFormsWidgetsAccessible.h | 3 +- .../src/xul/nsXULColorPickerAccessible.cpp | 32 +- .../src/xul/nsXULFormControlAccessible.cpp | 115 ++-- .../src/xul/nsXULFormControlAccessible.h | 2 +- accessible/src/xul/nsXULTabAccessible.cpp | 9 - accessible/src/xul/nsXULTreeAccessible.cpp | 298 ++++----- accessible/src/xul/nsXULTreeAccessible.h | 38 +- .../src/xul/nsXULTreeGridAccessible.cpp | 233 +++---- accessible/src/xul/nsXULTreeGridAccessible.h | 23 +- accessible/tests/mochitest/Makefile.in | 3 +- accessible/tests/mochitest/common.js | 113 ++++ accessible/tests/mochitest/role.js | 4 + .../tests/mochitest/test_events_doc.html | 7 +- .../mochitest/test_invalidate_elmli.html | 168 ----- ...t_nsIAccessible_applicationAccessible.html | 63 -- accessible/tests/mochitest/tree/Makefile.in | 8 + .../tests/mochitest/tree/test_txtctrl.html | 65 +- 47 files changed, 1419 insertions(+), 1709 deletions(-) delete mode 100644 accessible/tests/mochitest/test_invalidate_elmli.html delete mode 100644 accessible/tests/mochitest/test_nsIAccessible_applicationAccessible.html diff --git a/accessible/src/atk/nsApplicationAccessibleWrap.cpp b/accessible/src/atk/nsApplicationAccessibleWrap.cpp index 4d059cb70fd7..592776054a18 100644 --- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp +++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp @@ -647,8 +647,7 @@ nsApplicationAccessibleWrap::AddRootAccessible(nsIAccessible *aRootAccWrap) AtkObject *atkAccessible = nsAccessibleWrap::GetAtkObject(aRootAccWrap); atk_object_set_parent(atkAccessible, mAtkObject); - PRUint32 count = 0; - mChildren->GetLength(&count); + PRUint32 count = mChildren.Count(); g_signal_emit_by_name(mAtkObject, "children_changed::add", count - 1, atkAccessible, NULL); @@ -670,36 +669,27 @@ nsApplicationAccessibleWrap::RemoveRootAccessible(nsIAccessible *aRootAccWrap) { NS_ENSURE_ARG_POINTER(aRootAccWrap); - PRUint32 index = 0; - nsresult rv = NS_ERROR_FAILURE; - - // we must use weak ref to get the index - nsCOMPtr weakPtr = do_GetWeakReference(aRootAccWrap); - rv = mChildren->IndexOf(0, weakPtr, &index); + PRInt32 index = mChildren.IndexOf(aRootAccWrap); AtkObject *atkAccessible = nsAccessibleWrap::GetAtkObject(aRootAccWrap); atk_object_set_parent(atkAccessible, NULL); g_signal_emit_by_name(mAtkObject, "children_changed::remove", index, atkAccessible, NULL); + nsresult rv = nsApplicationAccessible::RemoveRootAccessible(aRootAccWrap); + #ifdef MAI_LOGGING - PRUint32 count = 0; - mChildren->GetLength(&count); + PRUint32 count = mChildren.Count(); if (NS_SUCCEEDED(rv)) { - rv = mChildren->RemoveElementAt(index); MAI_LOG_DEBUG(("\nRemove RootAcc=%p, count=%d\n", (void*)aRootAccWrap, (count-1))); } else MAI_LOG_DEBUG(("\nFail to Remove RootAcc=%p, count=%d\n", (void*)aRootAccWrap, count)); -#else - NS_ENSURE_SUCCESS(rv, rv); - rv = mChildren->RemoveElementAt(index); - #endif - InvalidateChildren(); + return rv; } diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index 6280ef672ab2..efe0f1e6f08b 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -149,14 +149,12 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsAccessible) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsAccessible, nsAccessNode) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstChild) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNextSibling) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mChildren) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsAccessible, nsAccessNode) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent) - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstChild) - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNextSibling) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mChildren) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_ADDREF_INHERITED(nsAccessible, nsAccessNode) @@ -229,8 +227,8 @@ nsresult nsAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) } nsAccessible::nsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell): nsAccessNodeWrap(aNode, aShell), - mParent(nsnull), mFirstChild(nsnull), mNextSibling(nsnull), mRoleMapEntry(nsnull), - mAccChildCount(eChildCountUninitialized) + mParent(nsnull), mRoleMapEntry(nsnull), + mAreChildrenInitialized(PR_FALSE) { #ifdef NS_DEBUG_X { @@ -482,39 +480,9 @@ nsAccessible::GetKeyboardShortcut(nsAString& aAccessKey) return NS_OK; } -void -nsAccessible::SetParent(nsIAccessible *aParent) -{ - if (mParent != aParent) { - // Adopt a child -- we allow this now. the new parent - // may be a dom node which wasn't previously accessible but now is. - // The old parent's children now need to be invalidated, since - // it no longer owns the child, the new parent does - nsRefPtr oldParent = nsAccUtils::QueryAccessible(mParent); - if (oldParent) - oldParent->InvalidateChildren(); - } - - mParent = aParent; -} - -void -nsAccessible::SetFirstChild(nsIAccessible *aFirstChild) -{ - mFirstChild = aFirstChild; -} - -void -nsAccessible::SetNextSibling(nsIAccessible *aNextSibling) -{ - mNextSibling = aNextSibling; -} - nsresult nsAccessible::Shutdown() { - mNextSibling = nsnull; - // Invalidate the child count and pointers to other accessibles, also make // sure none of its children point to this parent InvalidateChildren(); @@ -527,198 +495,112 @@ nsAccessible::Shutdown() return nsAccessNodeWrap::Shutdown(); } -void -nsAccessible::InvalidateChildren() -{ - // Document has transformed, reset our invalid children and child count - - // Reset the sibling pointers, they will be set up again the next time - // CacheChildren() is called. - // Note: we don't want to start creating accessibles at this point, - // so don't use GetNextSibling() here. (bug 387252) - nsRefPtr child = nsAccUtils::QueryAccessible(mFirstChild); - while (child) { - child->mParent = nsnull; - - nsCOMPtr next = child->mNextSibling; - child->mNextSibling = nsnull; - child = nsAccUtils::QueryAccessible(next); - } - - mAccChildCount = eChildCountUninitialized; - mFirstChild = nsnull; -} - NS_IMETHODIMP nsAccessible::GetParent(nsIAccessible **aParent) { - if (IsDefunct()) - return NS_ERROR_FAILURE; + NS_ENSURE_ARG_POINTER(aParent); - nsCOMPtr cachedParent = GetCachedParent(); - if (cachedParent) { - cachedParent.swap(*aParent); - return NS_OK; - } - - nsCOMPtr docAccessible(GetDocAccessible()); - NS_ENSURE_TRUE(docAccessible, NS_ERROR_FAILURE); - - return docAccessible->GetAccessibleInParentChain(mDOMNode, PR_TRUE, aParent); -} - -already_AddRefed -nsAccessible::GetCachedParent() -{ - if (IsDefunct()) - return nsnull; - - nsCOMPtr cachedParent = mParent; - return cachedParent.forget(); -} - -already_AddRefed -nsAccessible::GetCachedFirstChild() -{ - if (IsDefunct()) - return nsnull; - - nsCOMPtr cachedFirstChild = mFirstChild; - return cachedFirstChild.forget(); + NS_IF_ADDREF(*aParent = GetParent()); + return *aParent ? NS_OK : NS_ERROR_FAILURE; } /* readonly attribute nsIAccessible nextSibling; */ -NS_IMETHODIMP nsAccessible::GetNextSibling(nsIAccessible * *aNextSibling) -{ - *aNextSibling = nsnull; - if (!mWeakShell) { - // This node has been shut down - return NS_ERROR_FAILURE; - } - if (!mParent) { - nsCOMPtr parent(GetParent()); - if (parent) { - PRInt32 numChildren; - parent->GetChildCount(&numChildren); // Make sure we cache all of the children - } - } +NS_IMETHODIMP +nsAccessible::GetNextSibling(nsIAccessible **aNextSibling) +{ + NS_ENSURE_ARG_POINTER(aNextSibling); - if (mNextSibling || !mParent) { - // If no parent, don't try to calculate a new sibling - // It either means we're at the root or shutting down the parent - NS_IF_ADDREF(*aNextSibling = mNextSibling); - - return NS_OK; - } - - return NS_ERROR_FAILURE; + nsresult rv = NS_OK; + NS_IF_ADDREF(*aNextSibling = GetSiblingAtOffset(1, &rv)); + return rv; } /* readonly attribute nsIAccessible previousSibling; */ -NS_IMETHODIMP nsAccessible::GetPreviousSibling(nsIAccessible * *aPreviousSibling) +NS_IMETHODIMP +nsAccessible::GetPreviousSibling(nsIAccessible * *aPreviousSibling) { - *aPreviousSibling = nsnull; + NS_ENSURE_ARG_POINTER(aPreviousSibling); - if (!mWeakShell) { - // This node has been shut down - return NS_ERROR_FAILURE; - } - - nsCOMPtr parent; - if (NS_FAILED(GetParent(getter_AddRefs(parent))) || !parent) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr testAccessible, prevSibling; - parent->GetFirstChild(getter_AddRefs(testAccessible)); - while (testAccessible && this != testAccessible) { - prevSibling = testAccessible; - prevSibling->GetNextSibling(getter_AddRefs(testAccessible)); - } - - if (!prevSibling) { - return NS_ERROR_FAILURE; - } - - NS_ADDREF(*aPreviousSibling = prevSibling); - return NS_OK; + nsresult rv = NS_OK; + NS_IF_ADDREF(*aPreviousSibling = GetSiblingAtOffset(-1, &rv)); + return rv; } /* readonly attribute nsIAccessible firstChild; */ -NS_IMETHODIMP nsAccessible::GetFirstChild(nsIAccessible * *aFirstChild) -{ - if (gIsCacheDisabled) { +NS_IMETHODIMP +nsAccessible::GetFirstChild(nsIAccessible **aFirstChild) +{ + NS_ENSURE_ARG_POINTER(aFirstChild); + *aFirstChild = nsnull; + + if (gIsCacheDisabled) InvalidateChildren(); - } - PRInt32 numChildren; - GetChildCount(&numChildren); // Make sure we cache all of the children -#ifdef DEBUG - nsRefPtr firstChild(nsAccUtils::QueryAccessible(mFirstChild)); - if (firstChild) { - nsCOMPtr realParent = firstChild->GetCachedParent(); - NS_ASSERTION(!realParent || realParent == this, - "Two accessibles have the same first child accessible."); - } -#endif + PRInt32 childCount = GetChildCount(); + NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE); - NS_IF_ADDREF(*aFirstChild = mFirstChild); + if (childCount > 0) + NS_ADDREF(*aFirstChild = GetChildAt(0)); - return NS_OK; -} - - /* readonly attribute nsIAccessible lastChild; */ -NS_IMETHODIMP nsAccessible::GetLastChild(nsIAccessible * *aLastChild) -{ - GetChildAt(-1, aLastChild); return NS_OK; } -NS_IMETHODIMP nsAccessible::GetChildAt(PRInt32 aChildNum, nsIAccessible **aChild) + /* readonly attribute nsIAccessible lastChild; */ +NS_IMETHODIMP +nsAccessible::GetLastChild(nsIAccessible **aLastChild) { - // aChildNum is a zero-based index + NS_ENSURE_ARG_POINTER(aLastChild); + *aLastChild = nsnull; - PRInt32 numChildren; - GetChildCount(&numChildren); + PRInt32 childCount = GetChildCount(); + NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE); - // If no children or aChildNum is larger than numChildren, return null - if (aChildNum >= numChildren || numChildren == 0 || !mWeakShell) { - *aChild = nsnull; - return NS_ERROR_FAILURE; - // If aChildNum is less than zero, set aChild to last index - } else if (aChildNum < 0) { - aChildNum = numChildren - 1; - } + NS_IF_ADDREF(*aLastChild = GetChildAt(childCount - 1)); + return NS_OK; +} - nsCOMPtr current(mFirstChild), nextSibling; - PRInt32 index = 0; +NS_IMETHODIMP +nsAccessible::GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild) +{ + NS_ENSURE_ARG_POINTER(aChild); + *aChild = nsnull; - while (current) { - nextSibling = current; - if (++index > aChildNum) { - break; - } - nextSibling->GetNextSibling(getter_AddRefs(current)); - } + PRInt32 childCount = GetChildCount(); + NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE); - NS_IF_ADDREF(*aChild = nextSibling); + // If child index is negative, then return last child. + // XXX: do we really need this? + if (aChildIndex < 0) + aChildIndex = childCount - 1; + nsIAccessible* child = GetChildAt(aChildIndex); + if (!child) + return NS_ERROR_INVALID_ARG; + + NS_ADDREF(*aChild = child); return NS_OK; } // readonly attribute nsIArray children; -NS_IMETHODIMP nsAccessible::GetChildren(nsIArray **aOutChildren) +NS_IMETHODIMP +nsAccessible::GetChildren(nsIArray **aOutChildren) { + NS_ENSURE_ARG_POINTER(aOutChildren); *aOutChildren = nsnull; - nsCOMPtr children = do_CreateInstance(NS_ARRAY_CONTRACTID); - if (!children) - return NS_ERROR_FAILURE; - nsCOMPtr curChild; - while (NextChild(curChild)) { - children->AppendElement(curChild, PR_FALSE); + PRInt32 childCount = GetChildCount(); + NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE); + + nsresult rv = NS_OK; + nsCOMPtr children = + do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) { + nsIAccessible* child = GetChildAt(childIdx); + children->AppendElement(child, PR_FALSE); } - + NS_ADDREF(*aOutChildren = children); return NS_OK; } @@ -735,39 +617,6 @@ nsIAccessible *nsAccessible::NextChild(nsCOMPtr& aAccessible) return (aAccessible = nextChild); } -void nsAccessible::CacheChildren() -{ - if (!mWeakShell) { - // This node has been shut down - mAccChildCount = eChildCountUninitialized; - return; - } - - if (mAccChildCount == eChildCountUninitialized) { - mAccChildCount = 0;// Prevent reentry - PRBool allowsAnonChildren = GetAllowsAnonChildAccessibles(); - nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren); - // Seed the frame hint early while we're still on a container node. - // This is better than doing the GetPrimaryFrameFor() later on - // a text node, because text nodes aren't in the frame map. - walker.mState.frame = GetFrame(); - - nsRefPtr prevAcc; - PRInt32 childCount = 0; - walker.GetFirstChild(); - SetFirstChild(walker.mState.accessible); - - while (walker.mState.accessible) { - ++ childCount; - prevAcc = nsAccUtils::QueryAccessible(walker.mState.accessible); - prevAcc->SetParent(this); - walker.GetNextSibling(); - prevAcc->SetNextSibling(walker.mState.accessible); - } - mAccChildCount = childCount; - } -} - PRBool nsAccessible::GetAllowsAnonChildAccessibles() { @@ -775,73 +624,23 @@ nsAccessible::GetAllowsAnonChildAccessibles() } /* readonly attribute long childCount; */ -NS_IMETHODIMP nsAccessible::GetChildCount(PRInt32 *aAccChildCount) +NS_IMETHODIMP +nsAccessible::GetChildCount(PRInt32 *aChildCount) { - CacheChildren(); - *aAccChildCount = mAccChildCount; - return NS_OK; + NS_ENSURE_ARG_POINTER(aChildCount); + + *aChildCount = GetChildCount(); + return *aChildCount != -1 ? NS_OK : NS_ERROR_FAILURE; } /* readonly attribute long indexInParent; */ -NS_IMETHODIMP nsAccessible::GetIndexInParent(PRInt32 *aIndexInParent) +NS_IMETHODIMP +nsAccessible::GetIndexInParent(PRInt32 *aIndexInParent) { - *aIndexInParent = -1; - if (!mWeakShell) { - return NS_ERROR_FAILURE; - } + NS_ENSURE_ARG_POINTER(aIndexInParent); - nsCOMPtr parent; - GetParent(getter_AddRefs(parent)); - if (!parent) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr sibling; - parent->GetFirstChild(getter_AddRefs(sibling)); - if (!sibling) { - return NS_ERROR_FAILURE; - } - - *aIndexInParent = 0; - while (sibling != this) { - NS_ASSERTION(sibling, "Never ran into the same child that we started from"); - - if (!sibling) - return NS_ERROR_FAILURE; - - ++*aIndexInParent; - nsCOMPtr tempAccessible; - sibling->GetNextSibling(getter_AddRefs(tempAccessible)); - sibling = tempAccessible; - } - - return NS_OK; -} - -void -nsAccessible::TestChildCache(nsIAccessible *aCachedChild) -{ -#ifdef DEBUG_A11Y - // All cached accessible nodes should be in the parent - // It will assert if not all the children were created - // when they were first cached, and no invalidation - // ever corrected parent accessible's child cache. - if (mAccChildCount <= 0) - return; - - nsCOMPtr sibling = mFirstChild; - - while (sibling != aCachedChild) { - NS_ASSERTION(sibling, "[TestChildCache] Never ran into the same child that we started from"); - if (!sibling) - return; - - nsCOMPtr tempAccessible; - sibling->GetNextSibling(getter_AddRefs(tempAccessible)); - sibling = tempAccessible; - } - -#endif + *aIndexInParent = GetIndexInParent(); + return *aIndexInParent != -1 ? NS_OK : NS_ERROR_FAILURE; } nsresult nsAccessible::GetTranslatedString(const nsAString& aKey, nsAString& aStringOut) @@ -3113,8 +2912,247 @@ nsAccessible::GetNameInternal(nsAString& aName) return NS_OK; } +void +nsAccessible::SetParent(nsIAccessible *aParent) +{ + NS_PRECONDITION(aParent, "This method isn't used to set null parent!"); + + if (mParent && mParent != aParent) { + // Adopt a child -- we allow this now. the new parent + // may be a dom node which wasn't previously accessible but now is. + // The old parent's children now need to be invalidated, since + // it no longer owns the child, the new parent does + NS_ASSERTION(PR_FALSE, "Adopting child!"); + nsRefPtr oldParent = nsAccUtils::QueryAccessible(mParent); + if (oldParent) + oldParent->InvalidateChildren(); + } + + mParent = aParent; +} + +void +nsAccessible::InvalidateChildren() +{ + PRInt32 childCount = mChildren.Count(); + for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) { + nsRefPtr child = + nsAccUtils::QueryObject(mChildren.ObjectAt(childIdx)); + child->mParent = nsnull; + } + + mChildren.Clear(); + mAreChildrenInitialized = PR_FALSE; +} + +nsIAccessible* +nsAccessible::GetParent() +{ + if (IsDefunct()) + return nsnull; + + if (mParent) + return mParent; + + nsCOMPtr docAccessible(GetDocAccessible()); + NS_ASSERTION(docAccessible, "No document accessible for valid accessible!"); + + if (!docAccessible) + return nsnull; + + nsCOMPtr parent; + docAccessible->GetAccessibleInParentChain(mDOMNode, PR_TRUE, + getter_AddRefs(parent)); + +#ifdef DEBUG + nsRefPtr parentAcc = nsAccUtils::QueryAccessible(parent); + NS_ASSERTION(!parentAcc->IsDefunct(), "Defunct parent!"); + + parentAcc->EnsureChildren(); + if (parent != mParent) + NS_WARNING("Bad accessible tree!"); +#endif + + return parent; +} + +nsIAccessible* +nsAccessible::GetChildAt(PRUint32 aIndex) +{ + if (EnsureChildren()) + return nsnull; + + nsIAccessible *child = mChildren.SafeObjectAt(aIndex); + if (!child) + return nsnull; + +#ifdef DEBUG + nsRefPtr childAcc = nsAccUtils::QueryAccessible(child); + nsCOMPtr realParent = childAcc->mParent; + NS_ASSERTION(!realParent || realParent == this, + "Two accessibles have the same first child accessible!"); +#endif + + return child; +} + +PRInt32 +nsAccessible::GetChildCount() +{ + return EnsureChildren() ? -1 : mChildren.Count(); +} + +PRInt32 +nsAccessible::GetIndexOf(nsIAccessible *aChild) +{ + return EnsureChildren() ? -1 : mChildren.IndexOf(aChild); +} + +PRInt32 +nsAccessible::GetIndexInParent() +{ + nsIAccessible *parent = GetParent(); + if (!parent) + return -1; + + nsRefPtr parentAcc = + nsAccUtils::QueryObject(parent); + return parentAcc->GetIndexOf(this); +} + +already_AddRefed +nsAccessible::GetCachedParent() +{ + if (IsDefunct()) + return nsnull; + + nsCOMPtr cachedParent = mParent; + return cachedParent.forget(); +} + +already_AddRefed +nsAccessible::GetCachedFirstChild() +{ + if (IsDefunct()) + return nsnull; + + nsCOMPtr cachedFirstChild = GetChildAt(0); + return cachedFirstChild.forget(); +} + + //////////////////////////////////////////////////////////////////////////////// -// nsAccessible private methods +// nsAccessible protected methods + +void +nsAccessible::CacheChildren() +{ + PRBool allowsAnonChildren = GetAllowsAnonChildAccessibles(); + nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren); + + // Seed the frame hint early while we're still on a container node. + // This is better than doing the GetPrimaryFrameFor() later on + // a text node, because text nodes aren't in the frame map. + walker.mState.frame = GetFrame(); + + walker.GetFirstChild(); + while (walker.mState.accessible) { + mChildren.AppendObject(walker.mState.accessible); + + nsRefPtr acc = + nsAccUtils::QueryObject(walker.mState.accessible); + acc->SetParent(this); + + walker.GetNextSibling(); + } +} + +void +nsAccessible::TestChildCache(nsIAccessible *aCachedChild) +{ +#ifdef DEBUG_A11Y + // All cached accessible nodes should be in the parent + // It will assert if not all the children were created + // when they were first cached, and no invalidation + // ever corrected parent accessible's child cache. + PRUint32 childCount = mChildren.Count(); + if (childCount == 0) { + NS_ASSERTION(mAreChildrenInitialized, + "Children are stored but not initailzied!"); + return; + } + + for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) { + nsIAccessible *child = GetChildAt(childIdx); + if (child == aCachedChild) + break; + } + + NS_ASSERTION(child == aCachedChild, + "[TestChildCache] cached accessible wasn't found. Wrong accessible tree!"); +#endif +} + +PRBool +nsAccessible::EnsureChildren() +{ + if (IsDefunct()) { + mAreChildrenInitialized = PR_FALSE; + return PR_TRUE; + } + + if (mAreChildrenInitialized) + return PR_FALSE; + + mAreChildrenInitialized = PR_TRUE; // Prevent reentry + CacheChildren(); + + return PR_FALSE; +} + +nsIAccessible* +nsAccessible::GetSiblingAtOffset(PRInt32 aOffset, nsresult* aError) +{ + if (IsDefunct()) { + if (aError) + *aError = NS_ERROR_FAILURE; + + return nsnull; + } + + nsIAccessible *parent = GetParent(); + if (!parent) { + if (aError) + *aError = NS_ERROR_UNEXPECTED; + + return nsnull; + } + + nsRefPtr parentAcc = + nsAccUtils::QueryObject(parent); + + PRInt32 indexInParent = parentAcc->GetIndexOf(this); + if (indexInParent == -1) { + if (aError) + *aError = NS_ERROR_UNEXPECTED; + + return nsnull; + } + + if (aError) { + PRInt32 childCount = parentAcc->GetChildCount(); + if (indexInParent + aOffset >= childCount) { + *aError = NS_OK; // fail peacefully + return nsnull; + } + } + + nsIAccessible *child = parentAcc->GetChildAt(indexInParent + aOffset); + if (aError && !child) + *aError = NS_ERROR_UNEXPECTED; + + return child; +} already_AddRefed nsAccessible::GetFirstAvailableAccessible(nsIDOMNode *aStartNode) diff --git a/accessible/src/base/nsAccessible.h b/accessible/src/base/nsAccessible.h index ee5a49859179..f68c6c3beac7 100644 --- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -103,11 +103,11 @@ private: #define NS_ACCESSIBLE_IMPL_CID \ -{ /* 53cfa871-be42-47fc-b416-0033653b3151 */ \ - 0x53cfa871, \ - 0xbe42, \ - 0x47fc, \ - { 0xb4, 0x16, 0x00, 0x33, 0x65, 0x3b, 0x31, 0x51 } \ +{ /* 07c5a6d6-4e87-4b57-8613-4c39e1b5150a */ \ + 0x07c5a6d6, \ + 0x4e87, \ + 0x4b57, \ + { 0x86, 0x13, 0x4c, 0x39, 0xe1, 0xb5, 0x15, 0x0a } \ } class nsAccessible : public nsAccessNodeWrap, @@ -199,22 +199,7 @@ public: nsIAccessible **aChild); ////////////////////////////////////////////////////////////////////////////// - // Initializing and cache methods - - /** - * Set accessible parent. - */ - void SetParent(nsIAccessible *aParent); - - /** - * Set first accessible child. - */ - void SetFirstChild(nsIAccessible *aFirstChild); - - /** - * Set next sibling accessible. - */ - void SetNextSibling(nsIAccessible *aNextSibling); + // Initializing methods /** * Set the ARIA role map entry for a new accessible. @@ -226,10 +211,45 @@ public: virtual void SetRoleMapEntry(nsRoleMapEntry *aRoleMapEntry); /** - * Set the child count to -1 (unknown) and null out cached child pointers + * Set accessible parent. + */ + void SetParent(nsIAccessible *aParent); + + /** + * Set the child count to -1 (unknown) and null out cached child pointers. + * Should be called when accessible tree is changed because document has + * transformed. */ virtual void InvalidateChildren(); + ////////////////////////////////////////////////////////////////////////////// + // Accessible tree traverse methods + + /** + * Return parent accessible. + */ + virtual nsIAccessible* GetParent(); + + /** + * Return child accessible at the given index. + */ + virtual nsIAccessible* GetChildAt(PRUint32 aIndex); + + /** + * Return child accessible count. + */ + virtual PRInt32 GetChildCount(); + + /** + * Return index of the given child accessible. + */ + virtual PRInt32 GetIndexOf(nsIAccessible *aChild); + + /** + * Return index in parent accessible. + */ + PRInt32 GetIndexInParent(); + /** * Return parent accessible only if cached. */ @@ -240,13 +260,8 @@ public: */ already_AddRefed GetCachedFirstChild(); - /** - * Assert if child not in parent's cache. - */ - void TestChildCache(nsIAccessible *aCachedChild); - ////////////////////////////////////////////////////////////////////////////// - // Miscellaneous methods. + // Miscellaneous methods /** * Fire accessible event. @@ -269,22 +284,41 @@ public: virtual nsresult AppendTextTo(nsAString& aText, PRUint32 aStartOffset, PRUint32 aLength); - ////////////////////////////////////////////////////////////////////////////// - // Helper methods - - already_AddRefed GetParent() { - nsIAccessible *parent = nsnull; - GetParent(&parent); - return parent; - } - protected: + + ////////////////////////////////////////////////////////////////////////////// + // Initializing, cache and tree traverse methods + + /** + * Cache accessible children. + */ + virtual void CacheChildren(); + + /** + * Assert if child not in parent's cache. + */ + void TestChildCache(nsIAccessible *aCachedChild); + + /** + * Cache children if necessary. Return true if the accessible is defunct. + */ + PRBool EnsureChildren(); + + /** + * Return sibling accessible at the given offset. + */ + virtual nsIAccessible* GetSiblingAtOffset(PRInt32 aOffset, + nsresult* aError = nsnull); + + ////////////////////////////////////////////////////////////////////////////// + // Miscellaneous helpers + virtual nsIFrame* GetBoundsFrame(); virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame); PRBool IsVisible(PRBool *aIsOffscreen); ////////////////////////////////////////////////////////////////////////////// - // Name helpers. + // Name helpers /** * Compute the name of HTML node. @@ -300,25 +334,6 @@ protected: static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut); static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut); - /** - * Walk into subtree and calculate the string which is used as the accessible - * name or description. - * - * @param aContent [in] traversed content - * @param aFlatString [in, out] result string - * @param aIsRootHidden [in] specifies whether root content (we started to - * traverse from) is hidden, in this case the result - * string is calculated from hidden children - * (this is used when hidden root content is explicitly - * specified as label or description by author) - */ - nsresult AppendFlatStringFromSubtreeRecurse(nsIContent *aContent, - nsAString *aFlatString, - PRBool aIsRootHidden); - - // Helpers for dealing with children - virtual void CacheChildren(); - // nsCOMPtr<>& is useful here, because getter_AddRefs() nulls the comptr's value, and NextChild // depends on the passed-in comptr being null or already set to a child (finding the next sibling). nsIAccessible *NextChild(nsCOMPtr& aAccessible); @@ -436,11 +451,10 @@ protected: // Data Members nsCOMPtr mParent; - nsCOMPtr mFirstChild; - nsCOMPtr mNextSibling; + nsCOMArray mChildren; + PRBool mAreChildrenInitialized; nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well - PRInt32 mAccChildCount; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessible, diff --git a/accessible/src/base/nsApplicationAccessible.cpp b/accessible/src/base/nsApplicationAccessible.cpp index 2af2b4e99678..e2ec604f5fff 100644 --- a/accessible/src/base/nsApplicationAccessible.cpp +++ b/accessible/src/base/nsApplicationAccessible.cpp @@ -42,64 +42,22 @@ #include "nsApplicationAccessible.h" +#include "nsAccessibilityService.h" + #include "nsIComponentManager.h" #include "nsServiceManagerUtils.h" -nsApplicationAccessible::nsApplicationAccessible(): - nsAccessibleWrap(nsnull, nsnull), mChildren(nsnull) +nsApplicationAccessible::nsApplicationAccessible() : + nsAccessibleWrap(nsnull, nsnull) { } //////////////////////////////////////////////////////////////////////////////// // nsISupports -NS_IMPL_CYCLE_COLLECTION_CLASS(nsApplicationAccessible) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsApplicationAccessible, - nsAccessible) - - nsCOMPtr enumerator; - tmp->mChildren->Enumerate(getter_AddRefs(enumerator)); - - nsCOMPtr childWeakRef; - nsCOMPtr accessible; - - PRBool hasMoreElements; - while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) - && hasMoreElements) { - - enumerator->GetNext(getter_AddRefs(childWeakRef)); - accessible = do_QueryReferent(childWeakRef); - if (accessible) { - NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "nsApplicationAccessible child"); - cb.NoteXPCOMChild(accessible); - } - } - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsApplicationAccessible, - nsAccessible) - tmp->mChildren->Clear(); -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsApplicationAccessible) -NS_INTERFACE_MAP_END_INHERITING(nsAccessible) - -NS_IMPL_ADDREF_INHERITED(nsApplicationAccessible, nsAccessible) -NS_IMPL_RELEASE_INHERITED(nsApplicationAccessible, nsAccessible) +NS_IMPL_ISUPPORTS_INHERITED0(nsApplicationAccessible, nsAccessible) //////////////////////////////////////////////////////////////////////////////// -// nsIAccessNode - -nsresult -nsApplicationAccessible::Init() -{ - nsresult rv; - mChildren = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); - return rv; -} - // nsIAccessible NS_IMETHODIMP @@ -130,19 +88,67 @@ nsApplicationAccessible::GetName(nsAString& aName) return NS_OK; } -nsresult -nsApplicationAccessible::GetRoleInternal(PRUint32 *aRole) +NS_IMETHODIMP +nsApplicationAccessible::GetDescription(nsAString& aValue) { - *aRole = nsIAccessibleRole::ROLE_APP_ROOT; + aValue.Truncate(); return NS_OK; } NS_IMETHODIMP nsApplicationAccessible::GetRole(PRUint32 *aRole) { + NS_ENSURE_ARG_POINTER(aRole); + return GetRoleInternal(aRole); } +NS_IMETHODIMP +nsApplicationAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState) +{ + NS_ENSURE_ARG_POINTER(aState); + *aState = 0; + + if (aExtraState) + *aExtraState = 0; + + return NS_OK; +} + +NS_IMETHODIMP +nsApplicationAccessible::GetParent(nsIAccessible **aAccessible) +{ + NS_ENSURE_ARG_POINTER(aAccessible); + *aAccessible = nsnull; + + return IsDefunct() ? NS_ERROR_FAILURE : NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// +// nsAccessNode public methods + +PRBool +nsApplicationAccessible::IsDefunct() +{ + return nsAccessibilityService::gIsShutdown; +} + +nsresult +nsApplicationAccessible::Init() +{ + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// +// nsAccessible public methods + +nsresult +nsApplicationAccessible::GetRoleInternal(PRUint32 *aRole) +{ + *aRole = nsIAccessibleRole::ROLE_APP_ROOT; + return NS_OK; +} + nsresult nsApplicationAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState) @@ -154,124 +160,59 @@ nsApplicationAccessible::GetStateInternal(PRUint32 *aState, return NS_OK; } -NS_IMETHODIMP -nsApplicationAccessible::GetParent(nsIAccessible **aParent) +nsIAccessible* +nsApplicationAccessible::GetParent() { - *aParent = nsnull; - return NS_OK; + return nsnull; } -NS_IMETHODIMP -nsApplicationAccessible::GetChildAt(PRInt32 aChildNum, nsIAccessible **aChild) +void +nsApplicationAccessible::InvalidateChildren() { - NS_ENSURE_ARG_POINTER(aChild); - *aChild = nsnull; - - PRUint32 count = 0; - nsresult rv = NS_OK; - - if (mChildren) { - rv = mChildren->GetLength(&count); - NS_ENSURE_SUCCESS(rv, rv); - } - - if (aChildNum >= static_cast(count) || count == 0) - return NS_ERROR_INVALID_ARG; - - if (aChildNum < 0) - aChildNum = count - 1; - - nsCOMPtr childWeakRef; - rv = mChildren->QueryElementAt(aChildNum, NS_GET_IID(nsIWeakReference), - getter_AddRefs(childWeakRef)); - NS_ENSURE_SUCCESS(rv, rv); - - if (childWeakRef) { - nsCOMPtr childAcc(do_QueryReferent(childWeakRef)); - NS_IF_ADDREF(*aChild = childAcc); - } - - return NS_OK; + // Do nothing because application children are kept updated by + // AddRootAccessible() and RemoveRootAccessible() method calls. } -NS_IMETHODIMP -nsApplicationAccessible::GetNextSibling(nsIAccessible **aNextSibling) -{ - NS_ENSURE_ARG_POINTER(aNextSibling); - - *aNextSibling = nsnull; - return NS_OK; -} - -NS_IMETHODIMP -nsApplicationAccessible::GetPreviousSibling(nsIAccessible **aPreviousSibling) -{ - NS_ENSURE_ARG_POINTER(aPreviousSibling); - - *aPreviousSibling = nsnull; - return NS_OK; -} - -NS_IMETHODIMP -nsApplicationAccessible::GetIndexInParent(PRInt32 *aIndexInParent) -{ - NS_ENSURE_ARG_POINTER(aIndexInParent); - - *aIndexInParent = -1; - return NS_OK; -} +//////////////////////////////////////////////////////////////////////////////// +// nsAccessible protected methods void nsApplicationAccessible::CacheChildren() { - if (!mChildren) { - mAccChildCount = eChildCountUninitialized; - return; - } - - if (mAccChildCount == eChildCountUninitialized) { - mAccChildCount = 0;// Prevent reentry - nsCOMPtr enumerator; - mChildren->Enumerate(getter_AddRefs(enumerator)); - - nsCOMPtr childWeakRef; - nsCOMPtr accessible; - nsRefPtr prevAcc; - PRBool hasMoreElements; - - while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) && - hasMoreElements) { - enumerator->GetNext(getter_AddRefs(childWeakRef)); - accessible = do_QueryReferent(childWeakRef); - if (accessible) { - if (prevAcc) - prevAcc->SetNextSibling(accessible); - else - SetFirstChild(accessible); - - prevAcc = nsAccUtils::QueryAccessible(accessible); - prevAcc->SetParent(this); - } - } - - PRUint32 count = 0; - mChildren->GetLength(&count); - mAccChildCount = static_cast(count); - } + // Nothing to do. Children are keeped up to dated by Add/RemoveRootAccessible + // method calls. } -// nsApplicationAccessible +nsIAccessible* +nsApplicationAccessible::GetSiblingAtOffset(PRInt32 aOffset, nsresult* aError) +{ + if (IsDefunct()) { + if (aError) + *aError = NS_ERROR_FAILURE; + + return nsnull; + } + + if (aError) + *aError = NS_OK; // fail peacefully + + return nsnull; +} + +//////////////////////////////////////////////////////////////////////////////// +// Public methods nsresult nsApplicationAccessible::AddRootAccessible(nsIAccessible *aRootAccessible) { NS_ENSURE_ARG_POINTER(aRootAccessible); - // add by weak reference - nsresult rv = mChildren->AppendElement(aRootAccessible, PR_TRUE); - NS_ENSURE_SUCCESS(rv, rv); + if (!mChildren.AppendObject(aRootAccessible)) + return NS_ERROR_FAILURE; + + nsRefPtr rootAcc = nsAccUtils::QueryAccessible(aRootAccessible); + rootAcc->SetParent(this); - InvalidateChildren(); return NS_OK; } @@ -280,17 +221,8 @@ nsApplicationAccessible::RemoveRootAccessible(nsIAccessible *aRootAccessible) { NS_ENSURE_ARG_POINTER(aRootAccessible); - PRUint32 index = 0; - - // we must use weak ref to get the index - nsCOMPtr weakPtr = do_GetWeakReference(aRootAccessible); - nsresult rv = mChildren->IndexOf(0, weakPtr, &index); - NS_ENSURE_SUCCESS(rv, rv); - - rv = mChildren->RemoveElementAt(index); - NS_ENSURE_SUCCESS(rv, rv); - - InvalidateChildren(); - return NS_OK; + // It's not needed to void root accessible parent because this method is + // called on root accessible shutdown and its parent will be cleared + // properly. + return mChildren.RemoveObject(aRootAccessible) ? NS_OK : NS_ERROR_FAILURE; } - diff --git a/accessible/src/base/nsApplicationAccessible.h b/accessible/src/base/nsApplicationAccessible.h index e45898e8e558..6668df5708bc 100644 --- a/accessible/src/base/nsApplicationAccessible.h +++ b/accessible/src/base/nsApplicationAccessible.h @@ -63,34 +63,36 @@ public: // nsISupports NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsApplicationAccessible, - nsAccessible) - - // nsAccessNode - virtual nsresult Init(); // nsIAccessible - NS_IMETHOD GetName(nsAString & aName); + NS_IMETHOD GetName(nsAString& aName); + NS_IMETHOD GetDescription(nsAString& aValue); NS_IMETHOD GetRole(PRUint32 *aRole); - NS_IMETHOD GetParent(nsIAccessible * *aParent); - NS_IMETHOD GetNextSibling(nsIAccessible * *aNextSibling); - NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling); - NS_IMETHOD GetIndexInParent(PRInt32 *aIndexInParent); - NS_IMETHOD GetChildAt(PRInt32 aChildNum, nsIAccessible **aChild); + NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState); + + NS_IMETHOD GetParent(nsIAccessible **aAccessible); + + // nsAccessNode + virtual PRBool IsDefunct(); + virtual nsresult Init(); // nsAccessible virtual nsresult GetRoleInternal(PRUint32 *aRole); virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState); + virtual nsIAccessible* GetParent(); + + virtual void InvalidateChildren(); // nsApplicationAccessible virtual nsresult AddRootAccessible(nsIAccessible *aRootAccWrap); virtual nsresult RemoveRootAccessible(nsIAccessible *aRootAccWrap); protected: + // nsAccessible virtual void CacheChildren(); - - nsCOMPtr mChildren; + virtual nsIAccessible* GetSiblingAtOffset(PRInt32 aOffset, + nsresult *aError = nsnull); }; #endif diff --git a/accessible/src/base/nsBaseWidgetAccessible.cpp b/accessible/src/base/nsBaseWidgetAccessible.cpp index 5bd4d105ca3d..eea11a3e0b29 100644 --- a/accessible/src/base/nsBaseWidgetAccessible.cpp +++ b/accessible/src/base/nsBaseWidgetAccessible.cpp @@ -65,7 +65,9 @@ nsAccessibleWrap(aNode, aShell) NS_IMPL_ISUPPORTS_INHERITED0(nsLeafAccessible, nsAccessible) -// nsAccessible::GetChildAtPoint() +//////////////////////////////////////////////////////////////////////////////// +// nsLeafAccessible: nsAccessible public + nsresult nsLeafAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, PRBool aDeepestChild, @@ -76,12 +78,13 @@ nsLeafAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, return NS_OK; } -// nsAccessible::CacheChildren() +//////////////////////////////////////////////////////////////////////////////// +// nsLeafAccessible: nsAccessible private + void nsLeafAccessible::CacheChildren() { // No children for leaf accessible. - mAccChildCount = IsDefunct() ? eChildCountUninitialized : 0; } diff --git a/accessible/src/base/nsCoreUtils.cpp b/accessible/src/base/nsCoreUtils.cpp index 3d5a88d2e222..0b32085ad579 100644 --- a/accessible/src/base/nsCoreUtils.cpp +++ b/accessible/src/base/nsCoreUtils.cpp @@ -1027,7 +1027,7 @@ nsCoreUtils::GetLastSensibleColumn(nsITreeBoxObject *aTree) } PRUint32 -nsCoreUtils::GetSensiblecolumnCount(nsITreeBoxObject *aTree) +nsCoreUtils::GetSensibleColumnCount(nsITreeBoxObject *aTree) { PRUint32 count = 0; diff --git a/accessible/src/base/nsCoreUtils.h b/accessible/src/base/nsCoreUtils.h index 4fa693ad2a9a..1eb7a2ee693b 100644 --- a/accessible/src/base/nsCoreUtils.h +++ b/accessible/src/base/nsCoreUtils.h @@ -413,7 +413,7 @@ public: /** * Return sensible columns count for the given tree box object. */ - static PRUint32 GetSensiblecolumnCount(nsITreeBoxObject *aTree); + static PRUint32 GetSensibleColumnCount(nsITreeBoxObject *aTree); /** * Return sensible column at the given index for the given tree box object. diff --git a/accessible/src/base/nsDocAccessible.cpp b/accessible/src/base/nsDocAccessible.cpp index 15f30508ad3d..276a8d745f93 100644 --- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -73,16 +73,16 @@ #include "nsIXULDocument.h" #endif -//=============================// -// nsDocAccessible // -//=============================// +//////////////////////////////////////////////////////////////////////////////// +// Static member initialization PRUint32 nsDocAccessible::gLastFocusedAccessiblesState = 0; nsIAtom *nsDocAccessible::gLastFocusedFrameType = nsnull; -//----------------------------------------------------- -// construction -//----------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +// Constructor/desctructor + nsDocAccessible::nsDocAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell): nsHyperTextAccessibleWrap(aDOMNode, aShell), mWnd(nsnull), mScrollPositionChangedTicks(0), mIsContentLoaded(PR_FALSE), @@ -129,15 +129,13 @@ nsDocAccessible::nsDocAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell) } } -//----------------------------------------------------- -// destruction -//----------------------------------------------------- nsDocAccessible::~nsDocAccessible() { } + //////////////////////////////////////////////////////////////////////////////// -// nsDocAccessible. nsISupports +// nsISupports static PLDHashOperator ElementTraverser(const void *aKey, nsIAccessNode *aAccessNode, @@ -182,6 +180,10 @@ NS_INTERFACE_MAP_END_INHERITING(nsHyperTextAccessible) NS_IMPL_ADDREF_INHERITED(nsDocAccessible, nsHyperTextAccessible) NS_IMPL_RELEASE_INHERITED(nsDocAccessible, nsHyperTextAccessible) + +//////////////////////////////////////////////////////////////////////////////// +// nsIAccessible + NS_IMETHODIMP nsDocAccessible::GetName(nsAString& aName) { @@ -204,6 +206,7 @@ nsDocAccessible::GetName(nsAString& aName) return rv; } +// nsAccessible public method nsresult nsDocAccessible::GetRoleInternal(PRUint32 *aRole) { @@ -242,6 +245,7 @@ nsDocAccessible::GetRoleInternal(PRUint32 *aRole) return NS_OK; } +// nsAccessible public method void nsDocAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry) { @@ -282,6 +286,7 @@ nsDocAccessible::GetDescription(nsAString& aDescription) return NS_OK; } +// nsAccessible public method nsresult nsDocAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState) { @@ -332,6 +337,7 @@ nsDocAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState) return NS_OK; } +// nsAccessible public method nsresult nsDocAccessible::GetARIAState(PRUint32 *aState, PRUint32 *aExtraState) { @@ -396,7 +402,9 @@ NS_IMETHODIMP nsDocAccessible::TakeFocus() return NS_ERROR_FAILURE; } -// ------- nsIAccessibleDocument Methods (5) --------------- + +//////////////////////////////////////////////////////////////////////////////// +// nsIAccessibleDocument NS_IMETHODIMP nsDocAccessible::GetURL(nsAString& aURL) { @@ -499,6 +507,7 @@ NS_IMETHODIMP nsDocAccessible::GetDocument(nsIDOMDocument **aDOMDoc) return NS_ERROR_FAILURE; } +// nsIAccessibleHyperText method NS_IMETHODIMP nsDocAccessible::GetAssociatedEditor(nsIEditor **aEditor) { NS_ENSURE_ARG_POINTER(aEditor); @@ -557,6 +566,7 @@ NS_IMETHODIMP nsDocAccessible::GetCachedAccessNode(void *aUniqueID, nsIAccessNod return NS_OK; } +// nsDocAccessible public method void nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode) { @@ -574,6 +584,7 @@ nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode) PutCacheEntry(mAccessNodeCache, aUniqueID, aAccessNode); } +// nsDocAccessible public method void nsDocAccessible::RemoveAccessNodeFromCache(nsIAccessNode *aAccessNode) { @@ -585,31 +596,8 @@ nsDocAccessible::RemoveAccessNodeFromCache(nsIAccessNode *aAccessNode) mAccessNodeCache.Remove(uniqueID); } -NS_IMETHODIMP nsDocAccessible::GetParent(nsIAccessible **aParent) -{ - // Hook up our new accessible with our parent - *aParent = nsnull; - NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE); - if (!mParent) { - nsIDocument *parentDoc = mDocument->GetParentDocument(); - NS_ENSURE_TRUE(parentDoc, NS_ERROR_FAILURE); - nsIContent *ownerContent = parentDoc->FindContentForSubDocument(mDocument); - nsCOMPtr ownerNode(do_QueryInterface(ownerContent)); - if (ownerNode) { - nsCOMPtr accService = - do_GetService("@mozilla.org/accessibilityService;1"); - if (accService) { - // XXX aaronl: ideally we would traverse the presshell chain - // Since there's no easy way to do that, we cheat and use - // the document hierarchy. GetAccessibleFor() is bad because - // it doesn't support our concept of multiple presshells per doc. - // It should be changed to use GetAccessibleInWeakShell() - accService->GetAccessibleFor(ownerNode, getter_AddRefs(mParent)); - } - } - } - return mParent ? nsAccessible::GetParent(aParent) : NS_ERROR_FAILURE; -} +//////////////////////////////////////////////////////////////////////////////// +// nsAccessNode nsresult nsDocAccessible::Init() @@ -618,8 +606,7 @@ nsDocAccessible::Init() AddEventListeners(); - nsCOMPtr parentAccessible; // Ensure outer doc mParent accessible - GetParent(getter_AddRefs(parentAccessible)); + GetParent(); // Ensure outer doc mParent accessible. nsresult rv = nsHyperTextAccessibleWrap::Init(); NS_ENSURE_SUCCESS(rv, rv); @@ -680,6 +667,7 @@ nsDocAccessible::Shutdown() return NS_OK; } +// nsDocAccessible protected member void nsDocAccessible::ShutdownChildDocuments(nsIDocShellTreeItem *aStart) { nsCOMPtr treeNode(do_QueryInterface(aStart)); @@ -725,6 +713,7 @@ nsDocAccessible::IsDefunct() return !mDocument; } +// nsDocAccessible protected member void nsDocAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aRelativeFrame) { *aRelativeFrame = GetFrame(); @@ -768,7 +757,7 @@ void nsDocAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aRelativeFrame) } } - +// nsDocAccessible protected member nsresult nsDocAccessible::AddEventListeners() { // 1) Set up scroll position listener @@ -814,6 +803,7 @@ nsresult nsDocAccessible::AddEventListeners() return NS_OK; } +// nsDocAccessible protected member nsresult nsDocAccessible::RemoveEventListeners() { // Remove listeners associated with content documents @@ -860,6 +850,7 @@ nsresult nsDocAccessible::RemoveEventListeners() return NS_OK; } +// nsDocAccessible public member void nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType) { @@ -889,8 +880,7 @@ nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType) if (isFinished) { // Need to wait until scrollable view is available AddScrollListener(); - nsCOMPtr parent(nsAccessible::GetParent()); - nsRefPtr acc(nsAccUtils::QueryAccessible(parent)); + nsRefPtr acc(nsAccUtils::QueryAccessible(GetParent())); if (acc) { // Make the parent forget about the old document as a child acc->InvalidateChildren(); @@ -954,6 +944,7 @@ void nsDocAccessible::ScrollTimerCallback(nsITimer *aTimer, void *aClosure) } } +// nsDocAccessible protected member void nsDocAccessible::AddScrollListener() { nsCOMPtr presShell(do_QueryReferent(mWeakShell)); @@ -970,6 +961,7 @@ void nsDocAccessible::AddScrollListener() scrollableView->AddScrollPositionListener(this); } +// nsDocAccessible protected member void nsDocAccessible::RemoveScrollListener() { nsCOMPtr presShell(do_QueryReferent(mWeakShell)); @@ -986,6 +978,9 @@ void nsDocAccessible::RemoveScrollListener() scrollableView->RemoveScrollPositionListener(this); } +//////////////////////////////////////////////////////////////////////////////// +// nsIScrollPositionListener + NS_IMETHODIMP nsDocAccessible::ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY) { return NS_OK; @@ -1012,6 +1007,9 @@ NS_IMETHODIMP nsDocAccessible::ScrollPositionDidChange(nsIScrollableView *aScrol return NS_OK; } +//////////////////////////////////////////////////////////////////////////////// +// nsIObserver + NS_IMETHODIMP nsDocAccessible::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { @@ -1026,7 +1024,7 @@ NS_IMETHODIMP nsDocAccessible::Observe(nsISupports *aSubject, const char *aTopic return NS_OK; } - /////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // nsIDocumentObserver NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(nsDocAccessible) @@ -1062,7 +1060,7 @@ nsDocAccessible::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent, } } - +// nsDocAccessible protected member void nsDocAccessible::AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID, nsIAtom* aAttribute) { @@ -1213,6 +1211,7 @@ nsDocAccessible::AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID } } +// nsDocAccessible protected member void nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) { @@ -1362,6 +1361,7 @@ void nsDocAccessible::ContentAppended(nsIDocument *aDocument, } } + void nsDocAccessible::ContentStatesChanged(nsIDocument* aDocument, nsIContent* aContent1, nsIContent* aContent2, @@ -1417,6 +1417,45 @@ nsDocAccessible::ParentChainChanged(nsIContent *aContent) { } + +//////////////////////////////////////////////////////////////////////////////// +// nsAccessible + +nsIAccessible* +nsDocAccessible::GetParent() +{ + if (IsDefunct()) + return nsnull; + + if (mParent) + return mParent; + + nsIDocument* parentDoc = mDocument->GetParentDocument(); + if (!parentDoc) + return nsnull; + + nsIContent* ownerContent = parentDoc->FindContentForSubDocument(mDocument); + nsCOMPtr ownerNode(do_QueryInterface(ownerContent)); + if (ownerNode) { + nsCOMPtr accService = GetAccService(); + if (accService) { + // XXX aaronl: ideally we would traverse the presshell chain. Since + // there's no easy way to do that, we cheat and use the document + // hierarchy. GetAccessibleFor() is bad because it doesn't support our + // concept of multiple presshells per doc. + // It should be changed to use GetAccessibleInWeakShell() + accService->GetAccessibleFor(ownerNode, getter_AddRefs(mParent)); + } + } + + NS_ASSERTION(mParent, "No parent for not root document accessible!"); + return mParent; +} + + +//////////////////////////////////////////////////////////////////////////////// +// Protected members + void nsDocAccessible::FireValueChangeForTextFields(nsIAccessible *aPossibleTextFieldAccessible) { @@ -1571,7 +1610,8 @@ nsDocAccessible::CreateTextChangeEventForNode(nsIAccessible *aContainerAccessibl return event; } - + +// nsDocAccessible public member nsresult nsDocAccessible::FireDelayedAccessibleEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode, @@ -1585,6 +1625,7 @@ nsDocAccessible::FireDelayedAccessibleEvent(PRUint32 aEventType, return FireDelayedAccessibleEvent(event); } +// nsDocAccessible public member nsresult nsDocAccessible::FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent) { @@ -1953,6 +1994,7 @@ void nsDocAccessible::RefreshNodes(nsIDOMNode *aStartNode) mAccessNodeCache.Remove(uniqueID); } +// nsDocAccessible public member void nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild, PRUint32 aChangeType) @@ -2180,6 +2222,7 @@ nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild, FireDelayedAccessibleEvent(reorderEvent); } +// nsIAccessibleDocument method NS_IMETHODIMP nsDocAccessible::GetAccessibleInParentChain(nsIDOMNode *aNode, PRBool aCanCreate, diff --git a/accessible/src/base/nsDocAccessible.h b/accessible/src/base/nsDocAccessible.h index 7926dccd90f7..d351be665a16 100644 --- a/accessible/src/base/nsDocAccessible.h +++ b/accessible/src/base/nsDocAccessible.h @@ -87,7 +87,6 @@ public: NS_IMETHOD GetDescription(nsAString& aDescription); NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes); NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild); - NS_IMETHOD GetParent(nsIAccessible **aParent); NS_IMETHOD TakeFocus(void); // nsIScrollPositionListener @@ -111,7 +110,9 @@ public: virtual nsresult GetRoleInternal(PRUint32 *aRole); virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState); virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState); + virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry); + virtual nsIAccessible* GetParent(); // nsIAccessibleText NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor); diff --git a/accessible/src/base/nsOuterDocAccessible.cpp b/accessible/src/base/nsOuterDocAccessible.cpp index b42b062c03f0..df962beffa7b 100644 --- a/accessible/src/base/nsOuterDocAccessible.cpp +++ b/accessible/src/base/nsOuterDocAccessible.cpp @@ -99,25 +99,11 @@ nsOuterDocAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, return NS_OK; } -void nsOuterDocAccessible::CacheChildren() -{ - // An outer doc accessible usually has 1 nsDocAccessible child, - // but could have none if we can't get to the inner documnet - if (!mWeakShell) { - mAccChildCount = eChildCountUninitialized; - return; // This outer doc node has been shut down - } - if (mAccChildCount != eChildCountUninitialized) { - return; - } - - InvalidateChildren(); - mAccChildCount = 0; - - // In these variable names, "outer" relates to the nsOuterDocAccessible - // as opposed to the nsDocAccessibleWrap which is "inner". - // The outer node is a something like a , ,

+ + + diff --git a/layout/reftests/font-face/underline-offset-change-2-ref.html b/layout/reftests/font-face/underline-offset-change-2-ref.html new file mode 100644 index 000000000000..17bf99d2c766 --- /dev/null +++ b/layout/reftests/font-face/underline-offset-change-2-ref.html @@ -0,0 +1,25 @@ + + + + Switching first font to one with lower underline (reference) + + + + + +

A

+ + + diff --git a/layout/reftests/font-face/underline-offset-change-2.html b/layout/reftests/font-face/underline-offset-change-2.html new file mode 100644 index 000000000000..57896d5932ea --- /dev/null +++ b/layout/reftests/font-face/underline-offset-change-2.html @@ -0,0 +1,45 @@ + + + + Switching first font to one with lower underline + + + + + + + +

A

+ + + diff --git a/layout/reftests/fonts/mark-generate.py b/layout/reftests/fonts/mark-generate.py index 9538e7058460..a7334faf0931 100755 --- a/layout/reftests/fonts/mark-generate.py +++ b/layout/reftests/fonts/mark-generate.py @@ -68,3 +68,25 @@ for codepoint in range(ord("A"), ord("D") + 1): f.generate("mark" + mark + charname + ".ttf") f.generate("mark" + mark + charname + ".otf") + +for codepoint in range(ord("A"), ord("A") + 1): + for (mark, width) in [("", 1500), ("2", 1800)]: + for (uposname, upos) in [("low", -350), ("high", -50)]: + charname = chr(codepoint) + f = fontforge.font() + n = "Mark" + mark + charname + f.fontname = n + f.familyname = n + f.fullname = n + f.descent = 400 + f.upos = upos + f.uwidth = 100 + f.copyright = "Copyright (c) 2008 Mozilla Corporation" + + g = f.createChar(codepoint, charname) + g.importOutlines("mark" + mark + "-glyph.svg") + g.width = width + + f.generate("mark" + mark + charname + "-" + uposname + + "underline.ttf") + diff --git a/layout/reftests/fonts/mark2A-highunderline.ttf b/layout/reftests/fonts/mark2A-highunderline.ttf new file mode 100644 index 0000000000000000000000000000000000000000..eb483093e1a5d364ed8348760fd90e197a17702a GIT binary patch literal 1524 zcmdT^&ubGw6#iy+vx!=Nl&XkU7_~|iS~n|{szDp8!GqC)MFl}wl5G-9x?vl|iU&bY zBH~FrC|-(q65ERx58^?^lQ%th@FFNh^iWYj8^4)sLKOc2XL$R*_ha6B^JZot04&8N zm>A7w$8uvIuipV;Z>a4(a&)_U{I&lM5GN=f%U8V`mYbg`KOybQpQ}qGjqiYI(QXyJ z$y%eqNQk|noG4bN#!p_kIYRqN$`?z%SD2qzcbE7rX|P1a;#7PoV<~%Isaik3Y7MSY zen@#mCCGayVT|h&lowaM^EDjAPTGek%L%XQ&&;j0X}Btrvpq(~4-_zr3^Jx%sG*`OY5TAuRt%`h zNCiUnTT^coCrwF3?1cqMZgDC(!?V%f#?w|t!QQo!3$+JDoug&!)cuWB{{MUEJIwo{ z<{oavP(2nUcHTrB12Y2K)3b34pWGQc_BK6h8ibfJl{%)>vvFJeOwY1~pWGeY8@e~| z=-!kR!wVn2d@<$EcS++F+sw1Fr;W#qh#uucD!i~BzWDLPc)ZXh=6~&Pc5xXVv=3zq z4o6tP#^ng}^59m4O>D&b2wSkl>IlcMLhOyOP5mi#D=c;A4w0HzpbKXsY!F|Ku!;S+ z8(|AwA`#&jq*xzeoBC0VAV3XM2vO#{E1}LCmqZ?0$z3>{Lqs`xU7$yW)1$0bghGZ_dP_9%wITD1mAoS|xfPOhH3UP)BG8DY%k%4qVqfWPv`DyL_My`7Tmtq^4#N{YcTLKPsO;n`|&q&jw-9m+pWg zcgbc(g2Dcj+s`uT(;28;(lO=>F&S-7>UN}bcGVckKdK*2a!1l}QUi|TQ1j0?tykH& ht>3%g`TaR8ih^E!S}pj_)jQUH&-_O(mA3Pr_ZtiH$T9!` literal 0 HcmV?d00001 diff --git a/layout/reftests/fonts/mark2A-lowunderline.ttf b/layout/reftests/fonts/mark2A-lowunderline.ttf new file mode 100644 index 0000000000000000000000000000000000000000..819d95ae093910020b1f5af789609354b10d5586 GIT binary patch literal 1524 zcmdT^&ubGw6#iy+vx!=5i$4&pFlv=lNV{2~)Ecz08a!AnSgIf>OR^@RNjGexSn(j} zNklw}AmXKpC$YVF>7jT~@#IYpJ$MlmDSD`2p|*ar*@P(m1J3aFeecJ-_vY=)Kmb^e z>(DWr$&3t*e7W-wh7k4L6fnZ|G0JPp&Xo#|;{fe_l;yZncBj8?GikpIXd5fuM0Mo>^2|R)`#z|> zk(M4mDPL$!{lGdy#l`FN*J6Xm0dq>1lw;78mV;{oO)0AK(jG)ous)1HV>H&Nl_Jm$ zpgV99(U@37gppeGvE-nQcy|5hZV76 zKvhP{5whO_b%b$JlvKnH7?9)!r;^kBH^F!HWj&){@9N2g+JmCzQ8za0{>Cc*|2={; z%=4n=A#O!eJr)IaUPlz&(*ixInW%vUd)kc5r)G4G5YxI+N0fRdYKrC53|qKh?{DAP zzGr{??zk9O`TYI6E|)*XwRdbY|CKqV%`zf3DkoCzjq&`=(wsKC(jpdr9j$e71D-X0 z%3hodv4DviA?D%1{SfQeg-;>cxYFMBJmqM%&-wLsg zqj(fz11%yJ;s~VJ5n_}2VGP1U1(Wbm5~Y{=VO!c#;Y06&%4s@ zwq(DoWhCfLB<%#tq)&68MoFX0=VKz=o($TN46>`nNWQ49KfxVI%Sv`zmPO4!?KM&FOD8ePYe{E0&0T%c)sS=vEBSe{srM={#u}sG=2f5MZHyWr|XRd zJ;8oYzO_`Ho%}L!cQ^IB$loa!-NKLK_(WR#_m(Nxl(4VUm+1GDYr#zWJ=`Jxg#3=G zmv>Re827i5Z>za8b)3U7>ifv+DYsUf+u6}i{R6;gse98w<26b={~`4UAa^5-WK)kW zZ_oV1W=s6y^@&R-R&la1Z_k*Td@Br*a&V8S8}q1!d4N3=dWv+>YK0ODTjaJJvQve! zL3D=_WiP2^*z~l;JWI*L2pfYKP`$Dtu_?5ZMdDl?Ba^2K7{m~UOubS^m9Z75jBOZE zQcNW>f@mZHfzH?_Lr$zaVL=mHoWc+BZNjzjvgu7FRvkmh9R${o_|)~H4Rn-&4dVYu z5Y{m3MP`<98_q;n(z` z_OAB5huU{1)!@qK@83=R=R?wXM^6Q*G~;>bb2I%P>FQX8WwreGlzHp-Q+tE59v;|vji)kA>Sa;ETCMX}3DzT&n&l4hA zp$%7K+F)(pj%gDoF(1#-iBu9Ms$MmGZ==)j-7>%3j45(fEAcT9{Y*Ya5(!& zmZt8+r{w>@&I|PfoL29pZk%nwy9}j1+okk%}Wf zN*CT#koEjhQK!2d-LJ#rh!3ZF(kTW=lQl2RV8(fpkLmbUI?O^(c&_9_^J6Xg)4Ygw uoStsSaVXj7q}iGLmDc?Re7WY3A6U_9Pbg6Ab?Id#+^gcVw}RLId;b7}jL|0m literal 0 HcmV?d00001 diff --git a/layout/reftests/fonts/markA-lowunderline.ttf b/layout/reftests/fonts/markA-lowunderline.ttf new file mode 100644 index 0000000000000000000000000000000000000000..020ceb2af8db06e5f7be9bdc7574051296e59d1f GIT binary patch literal 1528 zcmdT^&1(}u6#vbBq_uul>aB+mby0)EZ#$j=Rc%=7vye)bN5q^ zE^W;G#9B-I;`Nb>N0xB1F=J1fntUq^k#ca4sT(t>hIxQJ8G4Fz(Q1Vf3+v>z9I{h| zvVL@j5@pY;1=#eo&OAxU!w4JwIH>l^hQylCP8NxCX$*}XFQ6X-7%=r>9aY9wpfa{$ zL`gA~$Oxj52n0G~n+!Rz?t}$RY;g)dz_$t4#>=KRl~{5NC3g^5IpR}SidNB423Cpx zBSBchtQVPC#%)NBRhgML(Sq(-h25FC77Jg~vk7}XGiMqkF>8w07V%t5LjB3iF@;~# zd)m9&x9@4+npFLZpTB=M^`8$(;~hN}q|%J%q0hDSzprb{5-g~NzsJlQzn|J2YT?bB z#rF|}IoyE9&G*6%oQY}0+PWUoEGFEIX%k)e5YrZHwIQZ$Y+~I-@0pel%K#LJa+69d{o$nWdy9iB=XovoQA{M zODadJX81D(w8)M>}*)j4mvQmwjr(DUn_?*rdqgk?7ozZWU=&>|H_ zet<5#@gVE@rJ_!EJGxJY#}V&M^`uh_kS5Dsn!#M)Nj@gxTj?+hJ>j{M56zFY=uhw> v+Hrci9mk<$wUcIN@<&+l8}Q|tLw;aIt8Jk`vDc-Sm2j_$&)y1N`S1M$R`by( literal 0 HcmV?d00001 From 423522c88bf52465f5e65858194588942d661f44 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Thu, 10 Dec 2009 20:02:13 -0800 Subject: [PATCH 126/179] Bug 487667 - Clone documents for printing, r=roc+jst+joe+dbaron --HG-- extra : rebase_source : dbab242066ba97c0d7f34a2fb701a1c465f26ec4 --- content/base/public/nsContentUtils.h | 5 + content/base/public/nsIDocument.h | 29 ++ .../base/public/nsIObjectLoadingContent.idl | 11 +- content/base/src/nsContentUtils.cpp | 10 + content/base/src/nsDocument.cpp | 84 ++++++ content/base/src/nsFrameLoader.cpp | 44 ++- content/base/src/nsFrameLoader.h | 4 + content/base/src/nsGkAtomList.h | 1 - content/base/src/nsImageLoadingContent.cpp | 16 + content/base/src/nsImageLoadingContent.h | 3 +- content/base/src/nsObjectLoadingContent.cpp | 46 ++- content/base/src/nsObjectLoadingContent.h | 4 + content/base/src/nsStyledElement.cpp | 4 +- .../html/content/public/nsHTMLMediaElement.h | 5 +- content/html/content/src/Makefile.in | 2 + .../html/content/src/nsGenericHTMLElement.cpp | 19 ++ .../html/content/src/nsGenericHTMLElement.h | 2 + .../html/content/src/nsHTMLCanvasElement.cpp | 22 +- .../html/content/src/nsHTMLImageElement.cpp | 11 +- .../html/content/src/nsHTMLInputElement.cpp | 5 + .../html/content/src/nsHTMLMediaElement.cpp | 54 +++- .../html/content/src/nsHTMLObjectElement.cpp | 15 + .../html/content/src/nsHTMLOptionElement.cpp | 17 ++ .../content/src/nsHTMLSharedObjectElement.cpp | 15 + .../content/src/nsHTMLTextAreaElement.cpp | 17 ++ content/svg/content/src/nsSVGImageElement.cpp | 9 + content/svg/content/src/nsSVGImageElement.h | 2 + content/svg/document/src/nsSVGDocument.cpp | 14 + content/svg/document/src/nsSVGDocument.h | 2 +- docshell/base/Makefile.in | 4 +- docshell/base/nsDocShell.cpp | 31 ++ docshell/base/nsIDocShell.idl | 10 +- .../browser/webBrowser/nsIWebBrowserPrint.idl | 2 +- layout/base/nsCSSFrameConstructor.cpp | 3 +- layout/base/nsDocumentViewer.cpp | 130 ++++---- layout/base/nsIDocumentViewerPrint.h | 34 ++- layout/base/nsLayoutUtils.cpp | 43 --- layout/base/nsLayoutUtils.h | 7 - layout/base/nsPresContext.cpp | 2 +- layout/base/nsPresContext.h | 2 +- layout/base/nsPresShell.cpp | 140 +-------- layout/base/tests/chrome/bug396024_helper.xul | 17 +- layout/base/tests/chrome/bug482976_helper.xul | 7 +- .../base/tests/chrome/printpreview_helper.xul | 22 +- layout/generic/nsBlockFrame.cpp | 5 +- layout/generic/nsBulletFrame.cpp | 6 +- layout/generic/nsFrame.cpp | 2 +- layout/generic/nsObjectFrame.cpp | 18 +- layout/generic/nsTextFrame.h | 12 - layout/generic/nsTextFrameThebes.cpp | 78 ++--- layout/generic/nsVideoFrame.h | 10 +- layout/printing/nsPrintEngine.cpp | 181 +++++++++-- layout/printing/nsPrintEngine.h | 6 +- layout/printing/nsPrintObject.cpp | 62 +++- layout/printing/nsPrintObject.h | 7 +- layout/style/nsComputedDOMStyle.cpp | 6 +- layout/style/nsRuleNode.cpp | 42 ++- layout/style/nsStyleStruct.h | 19 +- layout/svg/base/src/nsSVGGlyphFrame.cpp | 11 +- layout/svg/base/src/nsSVGGlyphFrame.h | 5 - layout/svg/base/src/nsSVGUtils.h | 3 - layout/xul/base/src/nsImageBoxFrame.cpp | 6 +- .../xul/base/src/tree/src/nsTreeBodyFrame.cpp | 2 +- modules/libpr0n/public/imgIRequest.idl | 8 +- modules/libpr0n/src/Makefile.in | 4 +- modules/libpr0n/src/imgContainerRequest.cpp | 280 ++++++++++++++++++ modules/libpr0n/src/imgContainerRequest.h | 71 +++++ modules/libpr0n/src/imgRequest.cpp | 15 +- modules/libpr0n/src/imgRequest.h | 13 +- modules/libpr0n/src/imgRequestProxy.cpp | 46 ++- .../printing/content/printPreviewBindings.xml | 6 +- .../components/printing/content/printUtils.js | 54 +++- widget/src/windows/nsDeviceContextSpecWin.cpp | 13 +- 73 files changed, 1422 insertions(+), 495 deletions(-) create mode 100644 modules/libpr0n/src/imgContainerRequest.cpp create mode 100644 modules/libpr0n/src/imgContainerRequest.h diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index e1a6cf4cfde2..2ff7e3bf43f5 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -670,6 +670,11 @@ public: */ static already_AddRefed GetImageFromContent(nsIImageLoadingContent* aContent, imgIRequest **aRequest = nsnull); + /** + * Helper method to call imgIRequest::GetStaticRequest. + */ + static already_AddRefed GetStaticRequest(imgIRequest* aRequest); + /** * Method that decides whether a content node is draggable * diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 45c92b904bbf..2890f19f6b61 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -1159,6 +1159,25 @@ public: PRBool IsDNSPrefetchAllowed() const { return mAllowDNSPrefetch; } + /** + * PR_TRUE when this document is a static clone of a normal document. + * For example print preview and printing use static documents. + */ + PRBool IsStaticDocument() { return mIsStaticDocument; } + + /** + * Clones the document and subdocuments and stylesheet etc. + * @param aCloneContainer The container for the clone document. + */ + virtual already_AddRefed + CreateStaticClone(nsISupports* aCloneContainer); + + /** + * If this document is a static clone, this returns the original + * document. + */ + nsIDocument* GetOriginalDocument() { return mOriginalDocument; } + /** * Called by nsParser to preload images. Can be removed and code moved * to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the @@ -1308,6 +1327,16 @@ protected: // document has no window, DNS prefetch won't be performed no matter what. PRPackedBool mAllowDNSPrefetch; + // True when this document is a static clone of a normal document + PRPackedBool mIsStaticDocument; + + // True while this document is being cloned to a static document. + PRPackedBool mCreatingStaticClone; + + // If mIsStaticDocument is true, mOriginalDocument points to the original + // document. + nsCOMPtr mOriginalDocument; + // The bidi options for this document. What this bitfield means is // defined in nsBidiUtils.h PRUint32 mBidiOptions; diff --git a/content/base/public/nsIObjectLoadingContent.idl b/content/base/public/nsIObjectLoadingContent.idl index 0e1ef863ee3b..e335a1ce78b5 100644 --- a/content/base/public/nsIObjectLoadingContent.idl +++ b/content/base/public/nsIObjectLoadingContent.idl @@ -37,6 +37,7 @@ #include "nsISupports.idl" +interface nsIFrame; interface nsIObjectFrame; interface nsIPluginInstance; interface nsIDOMElement; @@ -45,7 +46,7 @@ interface nsIDOMClientRect; /** * This interface represents a content node that loads objects. */ -[scriptable, uuid(8afe3b08-293c-48bd-a997-321745478611)] +[scriptable, uuid(7749d965-92f3-473e-b12d-de1e342acf1c)] interface nsIObjectLoadingContent : nsISupports { const unsigned long TYPE_LOADING = 0; @@ -115,4 +116,12 @@ interface nsIObjectLoadingContent : nsISupports void setAbsoluteScreenPosition(in nsIDOMElement element, in nsIDOMClientRect position, in nsIDOMClientRect clip); + + /** + * If this object is in going to be printed, this method + * returns the nsIObjectFrame object which should be used when + * printing the plugin. The returned nsIFrame is in the original document, + * not in the static clone. + */ + [noscript] nsIFrame getPrintFrame(); }; diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 861bb991c4a5..8cdc95803d9e 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -2504,6 +2504,16 @@ nsContentUtils::GetImageFromContent(nsIImageLoadingContent* aContent, return imgContainer.forget(); } +//static +already_AddRefed +nsContentUtils::GetStaticRequest(imgIRequest* aRequest) +{ + NS_ENSURE_TRUE(aRequest, nsnull); + nsCOMPtr retval; + aRequest->GetStaticRequest(getter_AddRefs(retval)); + return retval.forget(); +} + // static PRBool nsContentUtils::ContentIsDraggable(nsIContent* aContent) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 229c8d5e2421..e42d18a6dfb4 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -3060,6 +3060,9 @@ nsDocument::doCreateShell(nsPresContext* aContext, // Note: we don't hold a ref to the shell (it holds a ref to us) NS_ENSURE_TRUE(mPresShells.AppendElementUnlessExists(shell), NS_ERROR_OUT_OF_MEMORY); + + NS_WARN_IF_FALSE(mPresShells.Length() == 1, "More than one presshell!"); + shell.swap(*aInstancePtrResult); return NS_OK; @@ -7587,6 +7590,8 @@ nsDocument::QuerySelectorAll(const nsAString& aSelector, nsresult nsDocument::CloneDocHelper(nsDocument* clone) const { + clone->mIsStaticDocument = mCreatingStaticClone; + // Init document nsresult rv = clone->Init(); NS_ENSURE_SUCCESS(rv, rv); @@ -7597,6 +7602,21 @@ nsDocument::CloneDocHelper(nsDocument* clone) const clone->SetPrincipal(NodePrincipal()); clone->mDocumentBaseURI = mDocumentBaseURI; + if (mCreatingStaticClone) { + nsCOMPtr channel = GetChannel(); + nsCOMPtr loadGroup = GetDocumentLoadGroup(); + if (channel && loadGroup) { + clone->Reset(channel, loadGroup); + } else { + nsIURI* uri = static_cast(this)->GetDocumentURI(); + if (uri) { + clone->ResetToURI(uri, loadGroup, NodePrincipal()); + } + } + nsCOMPtr container = GetContainer(); + clone->SetContainer(container); + } + // Set scripting object PRBool hasHadScriptObject = PR_TRUE; nsIScriptGlobalObject* scriptObject = @@ -7821,3 +7841,67 @@ nsIDocument::EnumerateFreezableElements(FreezableElementEnumerator aEnumerator, EnumerateFreezablesData data = { aEnumerator, aData }; mFreezableElements->EnumerateEntries(EnumerateFreezables, &data); } + +already_AddRefed +nsIDocument::CreateStaticClone(nsISupports* aCloneContainer) +{ + nsCOMPtr domDoc = do_QueryInterface(this); + NS_ENSURE_TRUE(domDoc, nsnull); + mCreatingStaticClone = PR_TRUE; + + // Make document use different container during cloning. + nsCOMPtr originalContainer = GetContainer(); + SetContainer(aCloneContainer); + nsCOMPtr clonedNode; + nsresult rv = domDoc->CloneNode(PR_TRUE, getter_AddRefs(clonedNode)); + SetContainer(originalContainer); + + nsCOMPtr clonedDoc; + if (NS_SUCCEEDED(rv)) { + clonedDoc = do_QueryInterface(clonedNode); + nsCOMPtr clonedDOMDoc = do_QueryInterface(clonedDoc); + if (clonedDOMDoc) { + clonedDoc->mOriginalDocument = this; + PRInt32 sheetsCount = GetNumberOfStyleSheets(); + for (PRInt32 i = 0; i < sheetsCount; ++i) { + nsCOMPtr sheet = + do_QueryInterface(GetStyleSheetAt(i)); + if (sheet) { + PRBool applicable = PR_TRUE; + sheet->GetApplicable(applicable); + if (applicable) { + nsCOMPtr clonedSheet; + sheet->Clone(nsnull, nsnull, clonedDoc, nsnull, + getter_AddRefs(clonedSheet)); + NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!"); + if (clonedSheet) { + clonedDoc->AddStyleSheet(clonedSheet); + } + } + } + } + + sheetsCount = GetNumberOfCatalogStyleSheets(); + for (PRInt32 i = 0; i < sheetsCount; ++i) { + nsCOMPtr sheet = + do_QueryInterface(GetCatalogStyleSheetAt(i)); + if (sheet) { + PRBool applicable = PR_TRUE; + sheet->GetApplicable(applicable); + if (applicable) { + nsCOMPtr clonedSheet; + sheet->Clone(nsnull, nsnull, clonedDoc, nsnull, + getter_AddRefs(clonedSheet)); + NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!"); + if (clonedSheet) { + clonedDoc->AddCatalogStyleSheet(clonedSheet); + } + } + } + } + } + } + mCreatingStaticClone = PR_FALSE; + return clonedDoc.forget(); +} + diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index d81ec4e831ac..653d96c8abeb 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -87,6 +87,8 @@ #include "nsINameSpaceManager.h" #include "nsThreadUtils.h" +#include "nsICSSStyleSheet.h" +#include "nsIContentViewer.h" class nsAsyncDocShellDestroyer : public nsRunnable { @@ -138,9 +140,11 @@ nsFrameLoader* nsFrameLoader::Create(nsIContent* aOwner) { NS_ENSURE_TRUE(aOwner, nsnull); - nsIDocument* doc = aOwner->GetCurrentDoc(); + nsIDocument* doc = aOwner->GetOwnerDoc(); NS_ENSURE_TRUE(doc && !doc->GetDisplayDocument() && - !doc->IsLoadedAsData(), nsnull); + ((!doc->IsLoadedAsData() && aOwner->GetCurrentDoc()) || + doc->IsStaticDocument()), + nsnull); return new nsFrameLoader(aOwner); } @@ -160,7 +164,7 @@ nsFrameLoader::LoadFrame() } nsIDocument* doc = mOwnerContent->GetOwnerDoc(); - if (!doc) { + if (!doc || doc->IsStaticDocument()) { return NS_OK; } @@ -910,8 +914,8 @@ nsFrameLoader::EnsureDocShell() // Get our parent docshell off the document of mOwnerContent // XXXbz this is such a total hack.... We really need to have a // better setup for doing this. - nsIDocument* doc = mOwnerContent->GetDocument(); - if (!doc) { + nsIDocument* doc = mOwnerContent->GetOwnerDoc(); + if (!doc || !(doc->IsStaticDocument() || mOwnerContent->IsInDoc())) { return NS_ERROR_UNEXPECTED; } @@ -920,8 +924,9 @@ nsFrameLoader::EnsureDocShell() return NS_ERROR_NOT_AVAILABLE; } - nsCOMPtr parentAsWebNav = - do_GetInterface(doc->GetScriptGlobalObject()); + nsCOMPtr container = + doc->GetContainer(); + nsCOMPtr parentAsWebNav = do_QueryInterface(container); // Create the docshell... mDocShell = do_CreateInstance("@mozilla.org/docshell;1"); @@ -1123,3 +1128,28 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI) return NS_OK; } + +nsresult +nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest) +{ + nsFrameLoader* dest = static_cast(aDest); + dest->EnsureDocShell(); + NS_ENSURE_STATE(dest->mDocShell); + + nsCOMPtr dummy = do_GetInterface(dest->mDocShell); + nsCOMPtr viewer; + dest->mDocShell->GetContentViewer(getter_AddRefs(viewer)); + NS_ENSURE_STATE(viewer); + + nsCOMPtr origDocShell; + GetDocShell(getter_AddRefs(origDocShell)); + nsCOMPtr domDoc = do_GetInterface(origDocShell); + + nsCOMPtr doc = do_QueryInterface(domDoc); + NS_ENSURE_STATE(doc); + nsCOMPtr clonedDoc = doc->CreateStaticClone(dest->mDocShell); + nsCOMPtr clonedDOMDoc = do_QueryInterface(clonedDoc); + + viewer->SetDOMDocument(clonedDOMDoc); + return NS_OK; +} diff --git a/content/base/src/nsFrameLoader.h b/content/base/src/nsFrameLoader.h index a4c2740464ba..ae594570a1a9 100644 --- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -81,6 +81,8 @@ public: void Finalize(); nsIDocShell* GetExistingDocShell() { return mDocShell; } + nsresult CreateStaticClone(nsIFrameLoader* aDest); + /** * Called from the layout frame associated with this frame loader; * this notifies us to hook up with the widget and view. @@ -96,6 +98,8 @@ public: */ void Hide(); + nsresult CloneForStatic(nsIFrameLoader* aOriginal); + // The guts of an nsIFrameLoaderOwner::SwapFrameLoader implementation. A // frame loader owner needs to call this, and pass in the two references to // nsRefPtrs for frame loaders that need to be swapped. diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 1b89b56c6e93..a56787921c27 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -201,7 +201,6 @@ GK_ATOM(click, "click") GK_ATOM(clickcount, "clickcount") GK_ATOM(movetoclick, "movetoclick") GK_ATOM(clip, "clip") -GK_ATOM(clonedTextForPrint, "clonedTextForPrint") GK_ATOM(close, "close") GK_ATOM(closed, "closed") GK_ATOM(closemenu, "closemenu") diff --git a/content/base/src/nsImageLoadingContent.cpp b/content/base/src/nsImageLoadingContent.cpp index 54f24bc5188d..dd1bb12abc98 100644 --- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -987,3 +987,19 @@ nsImageLoadingContent::SetBlockingOnload(PRBool aBlocking) mBlockingOnload = aBlocking; } } + +void +nsImageLoadingContent::CreateStaticImageClone(nsImageLoadingContent* aDest) const +{ + aDest->mCurrentRequest = nsContentUtils::GetStaticRequest(mCurrentRequest); + aDest->mForcedImageState = mForcedImageState; + aDest->mImageBlockingStatus = mImageBlockingStatus; + aDest->mLoadingEnabled = mLoadingEnabled; + aDest->mStartingLoad = mStartingLoad; + aDest->mIsImageStateForced = mIsImageStateForced; + aDest->mLoading = mLoading; + aDest->mBroken = mBroken; + aDest->mUserDisabled = mUserDisabled; + aDest->mSuppressed = mSuppressed; +} + diff --git a/content/base/src/nsImageLoadingContent.h b/content/base/src/nsImageLoadingContent.h index ac479547b54a..b44c7afb581e 100644 --- a/content/base/src/nsImageLoadingContent.h +++ b/content/base/src/nsImageLoadingContent.h @@ -247,9 +247,10 @@ private: nsresult FireEvent(const nsAString& aEventType); class Event; friend class Event; +protected: + void CreateStaticImageClone(nsImageLoadingContent* aDest) const; /* MEMBERS */ -protected: nsCOMPtr mCurrentRequest; nsCOMPtr mPendingRequest; nsCOMPtr mCurrentURI; diff --git a/content/base/src/nsObjectLoadingContent.cpp b/content/base/src/nsObjectLoadingContent.cpp index da9f98e981fd..32078b9ba96f 100644 --- a/content/base/src/nsObjectLoadingContent.cpp +++ b/content/base/src/nsObjectLoadingContent.cpp @@ -812,6 +812,14 @@ nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame) LOG(("OBJLC [%p]: Got frame %p (mInstantiating=%i)\n", this, aFrame, mInstantiating)); + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); + NS_ASSERTION(thisContent, "must be a content"); + nsIDocument* doc = thisContent->GetOwnerDoc(); + if (!doc || doc->IsStaticDocument()) { + return NS_OK; + } + // "revoke" any existing instantiate event as it likely has out of // date data (frame pointer etc). mPendingInstantiateEvent = nsnull; @@ -1098,7 +1106,9 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI, // Security checks if (doc->IsLoadedAsData()) { - Fallback(PR_FALSE); + if (!doc->IsStaticDocument()) { + Fallback(PR_FALSE); + } return NS_OK; } @@ -1876,6 +1886,40 @@ nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType) return ePluginUnsupported; } +void +nsObjectLoadingContent::CreateStaticClone(nsObjectLoadingContent* aDest) const +{ + nsImageLoadingContent::CreateStaticImageClone(aDest); + + aDest->mType = mType; + nsObjectLoadingContent* thisObj = const_cast(this); + if (thisObj->mPrintFrame.IsAlive()) { + aDest->mPrintFrame = thisObj->mPrintFrame; + } else { + nsIObjectFrame* frame = + const_cast(this)->GetExistingFrame(eDontFlush); + nsIFrame* f = do_QueryFrame(frame); + aDest->mPrintFrame = f; + } + + if (mFrameLoader) { + nsCOMPtr content = + do_QueryInterface(static_cast((aDest))); + nsFrameLoader* fl = nsFrameLoader::Create(content); + if (fl) { + aDest->mFrameLoader = fl; + mFrameLoader->CreateStaticClone(fl); + } + } +} + +NS_IMETHODIMP +nsObjectLoadingContent::GetPrintFrame(nsIFrame** aFrame) +{ + *aFrame = mPrintFrame.GetFrame(); + return NS_OK; +} + NS_IMETHODIMP nsObjectLoadingContent::SetAbsoluteScreenPosition(nsIDOMElement* element, nsIDOMClientRect* position, diff --git a/content/base/src/nsObjectLoadingContent.h b/content/base/src/nsObjectLoadingContent.h index 7ef57c545fdf..9e86d32a8c41 100644 --- a/content/base/src/nsObjectLoadingContent.h +++ b/content/base/src/nsObjectLoadingContent.h @@ -53,6 +53,7 @@ #include "nsIObjectLoadingContent.h" #include "nsIRunnable.h" #include "nsIChannelClassifier.h" +#include "nsIFrame.h" class nsAsyncInstantiateEvent; class AutoNotifier; @@ -223,6 +224,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent void Traverse(nsCycleCollectionTraversalCallback &cb); + void CreateStaticClone(nsObjectLoadingContent* aDest) const; private: /** * Check whether the given request represents a successful load. @@ -422,6 +424,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent // A specific state that caused us to fallback PluginSupportState mPluginState; + nsWeakFrame mPrintFrame; + friend class nsAsyncInstantiateEvent; }; diff --git a/content/base/src/nsStyledElement.cpp b/content/base/src/nsStyledElement.cpp index 921a2a66b026..69c709db1a32 100644 --- a/content/base/src/nsStyledElement.cpp +++ b/content/base/src/nsStyledElement.cpp @@ -222,7 +222,9 @@ nsStyledElement::ParseStyleAttribute(nsIContent* aContent, nsresult result = NS_OK; nsIDocument* doc = aContent->GetOwnerDoc(); - if (doc && (aForceInDataDoc || !doc->IsLoadedAsData())) { + if (doc && (aForceInDataDoc || + !doc->IsLoadedAsData() || + doc->IsStaticDocument())) { PRBool isCSS = PR_TRUE; // assume CSS until proven otherwise if (!aContent->IsInNativeAnonymousSubtree()) { // native anonymous content diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index e00e63210a8d..36888748cd13 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -267,8 +267,9 @@ public: * Returns PR_TRUE if the media has played or completed a seek. * Used by video frame to determine whether to paint the poster. */ - PRBool GetPlayedOrSeeked() { return mHasPlayedOrSeeked; } + PRBool GetPlayedOrSeeked() const { return mHasPlayedOrSeeked; } + nsresult CopyInnerTo(nsGenericElement* aDest) const; protected: class MediaLoadListener; class LoadNextSourceEvent; @@ -519,4 +520,6 @@ protected: // alive while no-one is referencing it but the element may still fire // events of its own accord. PRPackedBool mHasSelfReference; + + nsRefPtr mPrintSurface; }; diff --git a/content/html/content/src/Makefile.in b/content/html/content/src/Makefile.in index 0a7eb0715daa..337cd88ce87c 100644 --- a/content/html/content/src/Makefile.in +++ b/content/html/content/src/Makefile.in @@ -127,6 +127,8 @@ INCLUDES += \ -I$(srcdir)/../../../xbl/src \ -I$(srcdir)/../../../../layout/style \ -I$(srcdir)/../../../../layout/tables \ + -I$(srcdir)/../../../../layout/xul/base/src \ + -I$(srcdir)/../../../../layout/generic \ -I$(srcdir)/../../../../dom/base \ -I$(srcdir) \ $(NULL) diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 5ebcee1958f4..1408a0870d6b 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -2869,6 +2869,25 @@ nsGenericHTMLFrameElement::DestroyContent() nsGenericHTMLElement::DestroyContent(); } +nsresult +nsGenericHTMLFrameElement::CopyInnerTo(nsGenericElement* aDest) const +{ + nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest); + NS_ENSURE_SUCCESS(rv, rv); + + nsIDocument* doc = aDest->GetOwnerDoc(); + if (doc->IsStaticDocument() && mFrameLoader) { + nsGenericHTMLFrameElement* dest = + static_cast(aDest); + nsFrameLoader* fl = nsFrameLoader::Create(dest); + NS_ENSURE_STATE(fl); + dest->mFrameLoader = fl; + static_cast(mFrameLoader.get())->CreateStaticClone(fl); + } + + return rv; +} + //---------------------------------------------------------------------- nsresult diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index e200415a372c..588367e03e1f 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -917,6 +917,8 @@ public: PRBool aNotify); virtual void DestroyContent(); + nsresult CopyInnerTo(nsGenericElement* aDest) const; + // nsIDOMNSHTMLElement NS_IMETHOD GetTabIndex(PRInt32 *aTabIndex); NS_IMETHOD SetTabIndex(PRInt32 aTabIndex); diff --git a/content/html/content/src/nsHTMLCanvasElement.cpp b/content/html/content/src/nsHTMLCanvasElement.cpp index f1fe78ddf1a9..d9a6e8e564cb 100644 --- a/content/html/content/src/nsHTMLCanvasElement.cpp +++ b/content/html/content/src/nsHTMLCanvasElement.cpp @@ -58,7 +58,7 @@ #include "nsIRenderingContext.h" #include "nsICanvasRenderingContextInternal.h" - +#include "nsIDOMCanvasRenderingContext2D.h" #include "nsLayoutUtils.h" #define DEFAULT_CANVAS_WIDTH 300 @@ -118,7 +118,7 @@ public: nsIAtom* aPrefix, const nsAString& aValue, PRBool aNotify); virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - + nsresult CopyInnerTo(nsGenericElement* aDest) const; protected: nsIntSize GetWidthHeight(); @@ -218,6 +218,24 @@ nsHTMLCanvasElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, return rv; } +nsresult +nsHTMLCanvasElement::CopyInnerTo(nsGenericElement* aDest) const +{ + nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest); + NS_ENSURE_SUCCESS(rv, rv); + if (aDest->GetOwnerDoc()->IsStaticDocument()) { + nsHTMLCanvasElement* dest = static_cast(aDest); + nsCOMPtr cxt; + dest->GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(cxt)); + nsCOMPtr context2d = do_QueryInterface(cxt); + if (context2d) { + context2d->DrawImage(const_cast(this), + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); + } + } + return rv; +} + nsChangeHint nsHTMLCanvasElement::GetAttributeChangeHint(const nsIAtom* aAttribute, PRInt32 aModType) const diff --git a/content/html/content/src/nsHTMLImageElement.cpp b/content/html/content/src/nsHTMLImageElement.cpp index 53833cd3af72..f3ab6c7f3b21 100644 --- a/content/html/content/src/nsHTMLImageElement.cpp +++ b/content/html/content/src/nsHTMLImageElement.cpp @@ -148,6 +148,8 @@ public: virtual PRInt32 IntrinsicState() const; virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + nsresult CopyInnerTo(nsGenericElement* aDest) const; + void MaybeLoadImage(); protected: nsPoint GetXY(); @@ -658,4 +660,11 @@ nsHTMLImageElement::GetNaturalWidth(PRInt32* aNaturalWidth) return NS_OK; } - +nsresult +nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const +{ + if (aDest->GetOwnerDoc()->IsStaticDocument()) { + CreateStaticImageClone(static_cast(aDest)); + } + return nsGenericHTMLElement::CopyInnerTo(aDest); +} diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 56a952f10ede..affee9e83588 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -557,6 +557,11 @@ nsHTMLInputElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const it->DoSetChecked(checked, PR_FALSE); } break; + case NS_FORM_INPUT_IMAGE: + if (it->GetOwnerDoc()->IsStaticDocument()) { + CreateStaticImageClone(it); + } + break; default: break; } diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index af94a31c3570..7e8ba773f485 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -78,6 +78,8 @@ #include "nsContentErrors.h" #include "nsCrossSiteListenerProxy.h" #include "nsCycleCollectionParticipant.h" +#include "nsLayoutUtils.h" +#include "nsVideoFrame.h" #ifdef MOZ_OGG #include "nsOggDecoder.h" @@ -1084,7 +1086,8 @@ nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aPar PRBool aCompileEventHandlers) { mIsBindingToTree = PR_TRUE; - mAutoplayEnabled = IsAutoplayEnabled(); + mAutoplayEnabled = + IsAutoplayEnabled() && (!aDocument || !aDocument->IsStaticDocument()); nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, aBindingParent, @@ -1711,8 +1714,22 @@ void nsHTMLMediaElement::Paint(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, const gfxRect& aRect) { - if (mDecoder) + if (mPrintSurface) { + nsRefPtr pat = new gfxPattern(mPrintSurface); + if (!pat) + return; + // Make the source image fill the rectangle completely + pat->SetMatrix(gfxMatrix().Scale(mMediaSize.width/aRect.Width(), + mMediaSize.height/aRect.Height())); + + pat->SetFilter(aFilter); + + aContext->NewPath(); + aContext->PixelSnappedRectangleAndSetPattern(aRect, pat); + aContext->Fill(); + } else if (mDecoder) { mDecoder->Paint(aContext, aFilter, aRect); + } } nsresult nsHTMLMediaElement::DispatchSimpleEvent(const nsAString& aName) @@ -1995,3 +2012,36 @@ already_AddRefed nsHTMLMediaElement::GetDocumentLoadGroup() nsIDocument* doc = GetOwnerDoc(); return doc ? doc->GetDocumentLoadGroup() : nsnull; } + +nsresult +nsHTMLMediaElement::CopyInnerTo(nsGenericElement* aDest) const +{ + nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest); + NS_ENSURE_SUCCESS(rv, rv); + if (aDest->GetOwnerDoc()->IsStaticDocument()) { + nsHTMLMediaElement* dest = static_cast(aDest); + if (mPrintSurface) { + dest->mPrintSurface = mPrintSurface; + dest->mMediaSize = mMediaSize; + } else { + nsIFrame* frame = + GetPrimaryFrameFor(const_cast(this), + GetOwnerDoc()); + nsCOMPtr elem; + if (frame && frame->GetType() == nsGkAtoms::HTMLVideoFrame && + static_cast(frame)->ShouldDisplayPoster()) { + elem = do_QueryInterface(static_cast(frame)-> + GetPosterImage()); + } else { + elem = do_QueryInterface(const_cast(this)); + } + + nsLayoutUtils::SurfaceFromElementResult res = + nsLayoutUtils::SurfaceFromElement(elem, + nsLayoutUtils::SFE_WANT_NEW_SURFACE); + dest->mPrintSurface = res.mSurface; + dest->mMediaSize = nsIntSize(res.mSize.width, res.mSize.height); + } + } + return rv; +} diff --git a/content/html/content/src/nsHTMLObjectElement.cpp b/content/html/content/src/nsHTMLObjectElement.cpp index b4123f40e992..910b7cef8b89 100644 --- a/content/html/content/src/nsHTMLObjectElement.cpp +++ b/content/html/content/src/nsHTMLObjectElement.cpp @@ -123,6 +123,8 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + nsresult CopyInnerTo(nsGenericElement* aDest) const; + void StartObjectLoad() { StartObjectLoad(PR_TRUE); } NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLObjectElement, @@ -478,3 +480,16 @@ nsHTMLObjectElement::DestroyContent() RemovedFromDocument(); nsGenericHTMLFormElement::DestroyContent(); } + +nsresult +nsHTMLObjectElement::CopyInnerTo(nsGenericElement* aDest) const +{ + nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest); + NS_ENSURE_SUCCESS(rv, rv); + + if (aDest->GetOwnerDoc()->IsStaticDocument()) { + CreateStaticClone(static_cast(aDest)); + } + + return rv; +} diff --git a/content/html/content/src/nsHTMLOptionElement.cpp b/content/html/content/src/nsHTMLOptionElement.cpp index af4fcf952282..8a4164993037 100644 --- a/content/html/content/src/nsHTMLOptionElement.cpp +++ b/content/html/content/src/nsHTMLOptionElement.cpp @@ -120,6 +120,8 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + nsresult CopyInnerTo(nsGenericElement* aDest) const; + protected: /** * Get the select content element that contains this option, this @@ -528,3 +530,18 @@ nsHTMLOptionElement::Initialize(nsISupports* aOwner, return result; } + +nsresult +nsHTMLOptionElement::CopyInnerTo(nsGenericElement* aDest) const +{ + nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest); + NS_ENSURE_SUCCESS(rv, rv); + + if (aDest->GetOwnerDoc()->IsStaticDocument()) { + PRBool selected = PR_FALSE; + const_cast(this)->GetSelected(&selected); + static_cast(aDest)->SetSelected(selected); + } + return NS_OK; +} + diff --git a/content/html/content/src/nsHTMLSharedObjectElement.cpp b/content/html/content/src/nsHTMLSharedObjectElement.cpp index 3ecc832df15c..686af5d9085e 100644 --- a/content/html/content/src/nsHTMLSharedObjectElement.cpp +++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp @@ -130,6 +130,8 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + nsresult CopyInnerTo(nsGenericElement* aDest) const; + void StartObjectLoad() { StartObjectLoad(PR_TRUE); } NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLSharedObjectElement, @@ -460,3 +462,16 @@ nsHTMLSharedObjectElement::DestroyContent() RemovedFromDocument(); nsGenericHTMLElement::DestroyContent(); } + +nsresult +nsHTMLSharedObjectElement::CopyInnerTo(nsGenericElement* aDest) const +{ + nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest); + NS_ENSURE_SUCCESS(rv, rv); + + if (aDest->GetOwnerDoc()->IsStaticDocument()) { + CreateStaticClone(static_cast(aDest)); + } + + return rv; +} diff --git a/content/html/content/src/nsHTMLTextAreaElement.cpp b/content/html/content/src/nsHTMLTextAreaElement.cpp index 1b52d4e86872..7b5a4e9b9c15 100644 --- a/content/html/content/src/nsHTMLTextAreaElement.cpp +++ b/content/html/content/src/nsHTMLTextAreaElement.cpp @@ -150,6 +150,8 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + nsresult CopyInnerTo(nsGenericElement* aDest) const; + /** * Called when an attribute is about to be changed */ @@ -975,3 +977,18 @@ nsHTMLTextAreaElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify); } + +nsresult +nsHTMLTextAreaElement::CopyInnerTo(nsGenericElement* aDest) const +{ + nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest); + NS_ENSURE_SUCCESS(rv, rv); + + if (aDest->GetOwnerDoc()->IsStaticDocument()) { + nsAutoString value; + const_cast(this)->GetValue(value); + static_cast(aDest)->SetValue(value); + } + return NS_OK; +} + diff --git a/content/svg/content/src/nsSVGImageElement.cpp b/content/svg/content/src/nsSVGImageElement.cpp index 7990ab8e5c1c..aca2959a6753 100644 --- a/content/svg/content/src/nsSVGImageElement.cpp +++ b/content/svg/content/src/nsSVGImageElement.cpp @@ -269,3 +269,12 @@ nsSVGImageElement::GetStringInfo() return StringAttributesInfo(mStringAttributes, sStringInfo, NS_ARRAY_LENGTH(sStringInfo)); } + +nsresult +nsSVGImageElement::CopyInnerTo(nsGenericElement* aDest) const +{ + if (aDest->GetOwnerDoc()->IsStaticDocument()) { + CreateStaticImageClone(static_cast(aDest)); + } + return nsSVGImageElementBase::CopyInnerTo(aDest); +} diff --git a/content/svg/content/src/nsSVGImageElement.h b/content/svg/content/src/nsSVGImageElement.h index 6b527d477483..2ee68fedd6e5 100644 --- a/content/svg/content/src/nsSVGImageElement.h +++ b/content/svg/content/src/nsSVGImageElement.h @@ -90,6 +90,8 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + nsresult CopyInnerTo(nsGenericElement* aDest) const; + void MaybeLoadSVGImage(); protected: nsresult LoadSVGImage(PRBool aForce, PRBool aNotify); diff --git a/content/svg/document/src/nsSVGDocument.cpp b/content/svg/document/src/nsSVGDocument.cpp index fee0c7aad175..efada1260e78 100644 --- a/content/svg/document/src/nsSVGDocument.cpp +++ b/content/svg/document/src/nsSVGDocument.cpp @@ -129,6 +129,20 @@ nsSVGDocument::GetRootElement(nsIDOMSVGSVGElement** aRootElement) return root ? CallQueryInterface(root, aRootElement) : NS_OK; } +nsresult +nsSVGDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const +{ + NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager, + "Can't import this document into another document!"); + + nsRefPtr clone = new nsSVGDocument(); + NS_ENSURE_TRUE(clone, NS_ERROR_OUT_OF_MEMORY); + nsresult rv = CloneDocHelper(clone.get()); + NS_ENSURE_SUCCESS(rv, rv); + + return CallQueryInterface(clone.get(), aResult); +} + //////////////////////////////////////////////////////////////////////// // Exported creation functions diff --git a/content/svg/document/src/nsSVGDocument.h b/content/svg/document/src/nsSVGDocument.h index 03724a5958ea..f72aa8f555d1 100644 --- a/content/svg/document/src/nsSVGDocument.h +++ b/content/svg/document/src/nsSVGDocument.h @@ -54,7 +54,7 @@ class nsSVGDocument : public nsXMLDocument, NS_FORWARD_NSIDOMNODE(nsXMLDocument::) NS_FORWARD_NSIDOMDOCUMENTEVENT(nsXMLDocument::) NS_DECL_ISUPPORTS_INHERITED - + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; }; #endif diff --git a/docshell/base/Makefile.in b/docshell/base/Makefile.in index 4c0e53ab6aa9..be152a5bcc08 100644 --- a/docshell/base/Makefile.in +++ b/docshell/base/Makefile.in @@ -103,4 +103,6 @@ FORCE_STATIC_LIB = 1 include $(topsrcdir)/config/rules.mk -LOCAL_INCLUDES += -I$(srcdir)/../shistory/src +LOCAL_INCLUDES += -I$(srcdir)/../shistory/src \ + -I$(srcdir)/../../layout/base \ + $(NULL) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index a357433c784b..67ea2b6f9daa 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -202,6 +202,11 @@ // for embedding #include "nsIWebBrowserChromeFocus.h" +#if NS_PRINT_PREVIEW +#include "nsIDocumentViewerPrint.h" +#include "nsIWebBrowserPrint.h" +#endif + #include "nsPluginError.h" static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, @@ -11072,6 +11077,32 @@ nsDocShell::SetRendering(PRBool aRender) return NS_ERROR_DOCSHELL_REQUEST_REJECTED; } +NS_IMETHODIMP +nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview) +{ + *aPrintPreview = nsnull; +#if NS_PRINT_PREVIEW + nsCOMPtr print = do_QueryInterface(mContentViewer); + if (!print || !print->IsInitializedForPrintPreview()) { + Stop(nsIWebNavigation::STOP_ALL); + nsCOMPtr principal = + do_CreateInstance("@mozilla.org/nullprincipal;1"); + NS_ENSURE_STATE(principal); + nsresult rv = CreateAboutBlankContentViewer(principal, nsnull); + NS_ENSURE_SUCCESS(rv, rv); + print = do_QueryInterface(mContentViewer); + NS_ENSURE_STATE(print); + print->InitializeForPrintPreview(); + } + nsCOMPtr result = do_QueryInterface(print); + result.forget(aPrintPreview); + return NS_OK; +#else + return NS_ERROR_NOT_IMPLEMENTED; +#endif +} + + #ifdef DEBUG unsigned long nsDocShell::gNumberOfDocShells = 0; #endif diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index 73499b01005b..26634a9d603b 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -68,8 +68,9 @@ interface nsILayoutHistoryState; interface nsISecureBrowserUI; interface nsIDOMStorage; interface nsIPrincipal; +interface nsIWebBrowserPrint; -[scriptable, uuid(8ADFB831-1053-4A19-884D-BCDAD7277B4B)] +[scriptable, uuid(1067ee1a-08e8-455d-9b12-19eeeee56b8e)] interface nsIDocShell : nsISupports { /** @@ -488,4 +489,11 @@ interface nsIDocShell : nsISupports * and should be treated accordingly. **/ attribute boolean isOffScreenBrowser; + + /** + * If the current content viewer isn't initialized for print preview, + * it is replaced with one which is and to which an about:blank document + * is loaded. + */ + readonly attribute nsIWebBrowserPrint printPreview; }; diff --git a/embedding/browser/webBrowser/nsIWebBrowserPrint.idl b/embedding/browser/webBrowser/nsIWebBrowserPrint.idl index 587a6db062ff..c85b39b15643 100644 --- a/embedding/browser/webBrowser/nsIWebBrowserPrint.idl +++ b/embedding/browser/webBrowser/nsIWebBrowserPrint.idl @@ -144,7 +144,7 @@ interface nsIWebBrowserPrint : nsISupports * * @param aThePrintSettings - Printer Settings for the print preview, if aThePrintSettings is null * then the global PS will be used. - * @param aChildDOMWin - DOM Window of the child document to be PP (FrameSet frames) + * @param aChildDOMWin - DOM Window to be print previewed. * @param aWPListener - is updated during the printpreview * @return void */ diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 906abcac3f6c..a888e029d474 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -11614,8 +11614,7 @@ nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint) NS_UpdateHint(aExtraHint, mRebuildAllExtraHint); mRebuildAllExtraHint = nsChangeHint(0); - if (!mPresShell || !mPresShell->GetRootFrame() || - !mPresShell->GetPresContext()->IsDynamic()) + if (!mPresShell || !mPresShell->GetRootFrame()) return; nsAutoScriptBlocker scriptBlocker; diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 24e2512f0fe6..079b70fe6f2f 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -498,7 +498,7 @@ protected: PRPackedBool mIsPageMode; PRPackedBool mCallerIsClosingWindow; - + PRPackedBool mInitializedForPrintPreview; }; //------------------------------------------------------------------ @@ -540,11 +540,10 @@ void DocumentViewerImpl::PrepareToStartLoad() if (mPrintEngine) { mPrintEngine->Destroy(); mPrintEngine = nsnull; - } - #ifdef NS_PRINT_PREVIEW - SetIsPrintPreview(PR_FALSE); + SetIsPrintPreview(PR_FALSE); #endif + } #ifdef NS_DEBUG mDebugFile = nsnull; @@ -560,7 +559,8 @@ DocumentViewerImpl::DocumentViewerImpl() #ifdef NS_PRINT_PREVIEW mPrintPreviewZoom(1.0), #endif - mHintCharsetSource(kCharsetUninitialized) + mHintCharsetSource(kCharsetUninitialized), + mInitializedForPrintPreview(PR_FALSE) { PrepareToStartLoad(); } @@ -700,6 +700,9 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, nsresult DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow, PRBool aReenableRefresh) { + if (GetIsPrintPreview()) + return NS_OK; + NS_ASSERTION(!mPresShell, "Someone should have destroyed the presshell!"); @@ -1700,14 +1703,16 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument) // Clear the list of old child docshells. CChild docshells for the new // document will be constructed as frames are created. - nsCOMPtr node = do_QueryInterface(container); - if (node) { - PRInt32 count; - node->GetChildCount(&count); - for (PRInt32 i = 0; i < count; ++i) { - nsCOMPtr child; - node->GetChildAt(0, getter_AddRefs(child)); - node->RemoveChild(child); + if (!newDoc->IsStaticDocument()) { + nsCOMPtr node = do_QueryInterface(container); + if (node) { + PRInt32 count; + node->GetChildCount(&count); + for (PRInt32 i = 0; i < count; ++i) { + nsCOMPtr child; + node->GetChildAt(0, getter_AddRefs(child)); + node->RemoveChild(child); + } } } } @@ -1767,37 +1772,19 @@ DocumentViewerImpl::GetDocument(nsIDocument** aResult) nsIPresShell* DocumentViewerImpl::GetPresShell() { - if (!GetIsPrintPreview()) { - return mPresShell; - } - NS_ENSURE_TRUE(mDocument, nsnull); - nsCOMPtr shell; - nsCOMPtr currentShell; - nsPresShellIterator iter(mDocument); - while ((shell = iter.GetNextShell())) { - currentShell.swap(shell); - } - return currentShell.get(); + return mPresShell; } nsPresContext* DocumentViewerImpl::GetPresContext() { - if (!GetIsPrintPreview()) { - return mPresContext; - } - nsIPresShell* shell = GetPresShell(); - return shell ? shell->GetPresContext() : nsnull; + return mPresContext; } nsIViewManager* DocumentViewerImpl::GetViewManager() { - if (!GetIsPrintPreview()) { - return mViewManager; - } - nsIPresShell* shell = GetPresShell(); - return shell ? shell->GetViewManager() : nsnull; + return mViewManager; } NS_IMETHODIMP @@ -2011,8 +1998,10 @@ DocumentViewerImpl::Show(void) // window is shown because some JS on the page caused it to be // shown... - nsCOMPtr shellDeathGrip(mPresShell); // bug 378682 - mPresShell->UnsuppressPainting(); + if (mPresShell) { + nsCOMPtr shellDeathGrip(mPresShell); // bug 378682 + mPresShell->UnsuppressPainting(); + } } return NS_OK; @@ -2285,8 +2274,10 @@ DocumentViewerImpl::ClearHistoryEntry() nsresult DocumentViewerImpl::MakeWindow(const nsSize& aSize, nsIView* aContainerView) { - nsresult rv; + if (GetIsPrintPreview()) + return NS_OK; + nsresult rv; mViewManager = do_CreateInstance(kViewManagerCID, &rv); if (NS_FAILED(rv)) return rv; @@ -3774,6 +3765,10 @@ DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, nsIWebProgressListener* aWebProgressListener) { #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + NS_WARN_IF_FALSE(IsInitializedForPrintPreview(), + "Using docshell.printPreview is the preferred way for print previewing!"); + + NS_ENSURE_ARG_POINTER(aChildDOMWin); nsresult rv = NS_OK; if (GetIsPrinting()) { @@ -3791,25 +3786,23 @@ DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, } #endif - if (!mContainer) { - PR_PL(("Container was destroyed yet we are still trying to use it!")); - return NS_ERROR_FAILURE; - } - nsCOMPtr docShell(do_QueryReferent(mContainer)); NS_ASSERTION(docShell, "This has to be a docshell"); - nsCOMPtr presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - if (!presShell || !mDocument || !mDeviceContext || !mParentWidget) { - PR_PL(("Can't Print Preview without pres shell, document etc")); + if (!docShell ||! mDeviceContext || !mParentWidget) { + PR_PL(("Can't Print Preview without device context, docshell etc")); return NS_ERROR_FAILURE; } if (!mPrintEngine) { + nsCOMPtr domDoc; + aChildDOMWin->GetDocument(getter_AddRefs(domDoc)); + nsCOMPtr doc = do_QueryInterface(domDoc); + NS_ENSURE_STATE(doc); + mPrintEngine = new nsPrintEngine(); NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY); - rv = mPrintEngine->Initialize(this, docShell, mDocument, + rv = mPrintEngine->Initialize(this, docShell, doc, float(mDeviceContext->AppUnitsPerInch()) / float(mDeviceContext->AppUnitsPerDevPixel()) / mPageZoom, @@ -4224,6 +4217,12 @@ DocumentViewerImpl::SetIsPrintPreview(PRBool aIsPrintPreview) SetIsPrintingInDocShellTree(docShellTreeNode, aIsPrintPreview, PR_TRUE); } #endif + if (!aIsPrintPreview) { + mWindow = nsnull; + mViewManager = nsnull; + mPresContext = nsnull; + mPresShell = nsnull; + } } //---------------------------------------------------------------------------------- @@ -4256,14 +4255,13 @@ DocumentViewerImpl::ReturnToGalleyPresentation() mPrintEngine->Destroy(); mPrintEngine = nsnull; - mViewManager->EnableRefresh(NS_VMREFRESH_DEFERRED); + if (mViewManager) { + mViewManager->EnableRefresh(NS_VMREFRESH_DEFERRED); + } nsCOMPtr docShell(do_QueryReferent(mContainer)); ResetFocusState(docShell); - if (mPresContext) - mPresContext->RestoreImageAnimationMode(); - SetTextZoom(mTextZoom); SetFullZoom(mPageZoom); Show(); @@ -4335,8 +4333,6 @@ DocumentViewerImpl::OnDonePrinting() } mClosingWhilePrinting = PR_FALSE; } - if (mPresContext) - mPresContext->RestoreImageAnimationMode(); } #endif // NS_PRINTING && NS_PRINT_PREVIEW } @@ -4402,3 +4398,31 @@ DocumentViewerImpl::DestroyPresShell() mPresShell->Destroy(); mPresShell = nsnull; } + +PRBool +DocumentViewerImpl::IsInitializedForPrintPreview() +{ + return mInitializedForPrintPreview; +} + +void +DocumentViewerImpl::InitializeForPrintPreview() +{ + mInitializedForPrintPreview = PR_TRUE; +} + +void +DocumentViewerImpl::SetPrintPreviewPresentation(nsIWidget* aWidget, + nsIViewManager* aViewManager, + nsPresContext* aPresContext, + nsIPresShell* aPresShell) +{ + if (mPresShell) { + DestroyPresShell(); + } + + mWindow = aWidget; + mViewManager = aViewManager; + mPresContext = aPresContext; + mPresShell = aPresShell; +} diff --git a/layout/base/nsIDocumentViewerPrint.h b/layout/base/nsIDocumentViewerPrint.h index 57bebe8ce2c6..0f5ddb35cba7 100644 --- a/layout/base/nsIDocumentViewerPrint.h +++ b/layout/base/nsIDocumentViewerPrint.h @@ -41,10 +41,15 @@ class nsIDocument; class nsStyleSet; +class nsIPresShell; +class nsPresContext; +class nsIWidget; +class nsIViewManager; -// {D0B7F354-D575-43fd-903D-5AA35A193EDA} +// {c6f255cf-cadd-4382-b57f-cd2a9874169b} #define NS_IDOCUMENT_VIEWER_PRINT_IID \ - { 0xd0b7f354, 0xd575, 0x43fd, { 0x90, 0x3d, 0x5a, 0xa3, 0x5a, 0x19, 0x3e, 0xda } } +{ 0xc6f255cf, 0xcadd, 0x4382, \ + { 0xb5, 0x7f, 0xcd, 0x2a, 0x98, 0x74, 0x16, 0x9b } } /** * A DocumentViewerPrint is an INTERNAL Interface used for interaction @@ -72,6 +77,23 @@ public: virtual void OnDonePrinting() = 0; + /** + * Returns PR_TRUE is InitializeForPrintPreview() has been called. + */ + virtual PRBool IsInitializedForPrintPreview() = 0; + + /** + * Marks this viewer to be used for print preview. + */ + virtual void InitializeForPrintPreview() = 0; + + /** + * Replaces the current presentation with print preview presentation. + */ + virtual void SetPrintPreviewPresentation(nsIWidget* aWidget, + nsIViewManager* aViewManager, + nsPresContext* aPresContext, + nsIPresShell* aPresShell) = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewerPrint, @@ -86,6 +108,12 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewerPrint, virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsStyleSet** aStyleSet); \ virtual void IncrementDestroyRefCount(); \ virtual void ReturnToGalleyPresentation(); \ - virtual void OnDonePrinting(); + virtual void OnDonePrinting(); \ + virtual PRBool IsInitializedForPrintPreview(); \ + virtual void InitializeForPrintPreview(); \ + virtual void SetPrintPreviewPresentation(nsIWidget* aWidget, \ + nsIViewManager* aViewManager, \ + nsPresContext* aPresContext, \ + nsIPresShell* aPresShell); #endif /* nsIDocumentViewerPrint_h___ */ diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index c820fbaf6df0..cb943ab312a4 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -78,7 +78,6 @@ #include "gfxTypes.h" #include "gfxUserFontSet.h" #include "nsTArray.h" -#include "nsTextFragment.h" #include "nsICanvasElement.h" #include "nsICanvasRenderingContextInternal.h" #include "gfxPlatform.h" @@ -3275,48 +3274,6 @@ nsLayoutUtils::IsReallyFixedPos(nsIFrame* aFrame) parentType == nsGkAtoms::pageContentFrame; } -static void DeleteTextFragment(void* aObject, nsIAtom* aPropertyName, - void* aPropertyValue, void* aData) -{ - delete static_cast(aPropertyValue); -} - -/* static */ nsTextFragment* -nsLayoutUtils::GetTextFragmentForPrinting(const nsIFrame* aFrame) -{ - nsPresContext* presContext = aFrame->PresContext(); - NS_PRECONDITION(!presContext->IsDynamic(), - "Shouldn't call this with dynamic PresContext"); -#ifdef MOZ_SVG - NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::textFrame || - aFrame->GetType() == nsGkAtoms::svgGlyphFrame, - "Wrong frame type!"); -#else - NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::textFrame, - "Wrong frame type!"); -#endif // MOZ_SVG - - nsIContent* content = aFrame->GetContent(); - nsTextFragment* frag = - static_cast(presContext->PropertyTable()-> - GetProperty(content, nsGkAtoms::clonedTextForPrint)); - - if (!frag) { - frag = new nsTextFragment(); - NS_ENSURE_TRUE(frag, nsnull); - *frag = *content->GetText(); - nsresult rv = presContext->PropertyTable()-> - SetProperty(content, nsGkAtoms::clonedTextForPrint, frag, - DeleteTextFragment, nsnull); - if (NS_FAILED(rv)) { - delete frag; - return nsnull; - } - } - - return frag; -} - nsLayoutUtils::SurfaceFromElementResult nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement, PRUint32 aSurfaceFlags) diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 3efb0ada1e33..805442bc9c0b 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -67,7 +67,6 @@ class nsClientRectList; #include "nsCSSPseudoElements.h" class nsBlockFrame; -class nsTextFragment; /** * nsLayoutUtils is a namespace class used for various helper @@ -1063,12 +1062,6 @@ public: */ static PRBool sDisableGetUsedXAssertions; - /** - * Returns the text fragment, which aFrame should use for printing. - * @param aFrame The nsIFrame object, which uses text fragment data. - */ - static nsTextFragment* GetTextFragmentForPrinting(const nsIFrame* aFrame); - /** * Return true if aFrame is in an {ib} split and is NOT one of the * continuations of the first inline in it. diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index b39777413b86..1393f85847cd 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -1229,7 +1229,7 @@ nsPresContext::GetDefaultFont(PRUint8 aFontID) const void nsPresContext::SetFullZoom(float aZoom) { - if (!mShell || mFullZoom == aZoom || !IsDynamic()) { + if (!mShell || mFullZoom == aZoom) { return; } // Re-fetch the view manager's window dimensions in case there's a deferred diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index b3da1075f056..1c4b03702195 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -103,6 +103,7 @@ class nsUserFontSet; struct nsFontFaceRuleContainer; class nsObjectFrame; class nsTransitionManager; +class imgIContainer; #ifdef MOZ_REFLOW_PERF class nsIRenderingContext; @@ -278,7 +279,6 @@ public: * Access the image animation mode for this context */ PRUint16 ImageAnimationMode() const { return mImageAnimationMode; } - void RestoreImageAnimationMode() { SetImageAnimationMode(mImageAnimationModePref); } virtual NS_HIDDEN_(void) SetImageAnimationModeExternal(PRUint16 aMode); NS_HIDDEN_(void) SetImageAnimationModeInternal(PRUint16 aMode); #ifdef _IMPL_NS_LAYOUT diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index b0de26a2a21e..516b585b5545 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1223,9 +1223,6 @@ protected: static PRBool sDisableNonTestMouseEvents; - - nsCOMPtr mDocumentObserverForNonDynamicContext; - // false if a check should be done for key/ime events that should be // retargeted to the currently focused presshell static PRBool sDontRetargetEvents; @@ -1340,122 +1337,6 @@ public: nsRefPtr mPresShell; }; -class nsDocumentObserverForNonDynamicPresContext : public nsStubDocumentObserver -{ -public: - nsDocumentObserverForNonDynamicPresContext(PresShell* aBaseObserver) - : mBaseObserver(aBaseObserver) - { - NS_ASSERTION(aBaseObserver, "Null document observer!"); - } - - NS_DECL_ISUPPORTS - - virtual void BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) - { - mBaseObserver->BeginUpdate(aDocument, aUpdateType); - } - virtual void EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) - { - mBaseObserver->EndUpdate(aDocument, aUpdateType); - } - virtual void BeginLoad(nsIDocument* aDocument) - { - mBaseObserver->BeginLoad(aDocument); - } - virtual void EndLoad(nsIDocument* aDocument) - { - mBaseObserver->EndLoad(aDocument); - } - virtual void ContentStatesChanged(nsIDocument* aDocument, - nsIContent* aContent1, - nsIContent* aContent2, - PRInt32 aStateMask) - { - if ((!aContent1 || AllowMutation(aContent1)) && - (!aContent2 || AllowMutation(aContent2))) { - mBaseObserver->ContentStatesChanged(aDocument, aContent1, aContent2, - aStateMask); - } - } - - // nsIMutationObserver - virtual void CharacterDataChanged(nsIDocument* aDocument, - nsIContent* aContent, - CharacterDataChangeInfo* aInfo) - { - if (AllowMutation(aContent)) { - mBaseObserver->CharacterDataChanged(aDocument, aContent, aInfo); - } - } - virtual void AttributeChanged(nsIDocument* aDocument, - nsIContent* aContent, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute, - PRInt32 aModType) - { - if (AllowMutation(aContent)) { - mBaseObserver->AttributeChanged(aDocument, aContent, aNameSpaceID, - aAttribute, aModType); - } - } - virtual void ContentAppended(nsIDocument* aDocument, - nsIContent* aContainer, - PRInt32 aNewIndexInContainer) - { - if (AllowMutation(aContainer)) { - mBaseObserver->ContentAppended(aDocument, aContainer, - aNewIndexInContainer); - } - } - virtual void ContentInserted(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild, - PRInt32 aIndexInContainer) - { - if (AllowMutation(aContainer)) { - mBaseObserver->ContentInserted(aDocument, aContainer, aChild, - aIndexInContainer); - } - } - virtual void ContentRemoved(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild, - PRInt32 aIndexInContainer) - { - if (AllowMutation(aContainer)) { - mBaseObserver->ContentRemoved(aDocument, aContainer, aChild, - aIndexInContainer); - } - } - - PRBool AllowMutation(nsIContent* aContent) { - if(aContent && aContent->IsInDoc()) { - if (mBaseObserver->ObservesNativeAnonMutationsForPrint() && - aContent->IsInNativeAnonymousSubtree()) { - return PR_TRUE; - } - // Changes to scrollbar are always ok. - nsIContent* root = aContent->GetCurrentDoc()->GetRootContent(); - while (aContent && aContent->IsInNativeAnonymousSubtree()) { - nsIContent* parent = aContent->GetParent(); - if (parent == root && aContent->IsXUL()) { - nsIAtom* tag = aContent->Tag(); - return tag == nsGkAtoms::scrollbar || tag == nsGkAtoms::scrollcorner; - } - aContent = parent; - } - } - return PR_FALSE; - } -protected: - nsRefPtr mBaseObserver; -}; - -NS_IMPL_ISUPPORTS2(nsDocumentObserverForNonDynamicPresContext, - nsIDocumentObserver, - nsIMutationObserver) - PRBool PresShell::sDisableNonTestMouseEvents = PR_FALSE; PRBool PresShell::sDontRetargetEvents = PR_FALSE; @@ -2532,14 +2413,7 @@ NS_IMETHODIMP PresShell::BeginObservingDocument() { if (mDocument && !mIsDestroying) { - if (mPresContext->IsDynamic()) { - mDocument->AddObserver(this); - } else { - mDocumentObserverForNonDynamicContext = - new nsDocumentObserverForNonDynamicPresContext(this); - NS_ENSURE_TRUE(mDocumentObserverForNonDynamicContext, NS_ERROR_OUT_OF_MEMORY); - mDocument->AddObserver(mDocumentObserverForNonDynamicContext); - } + mDocument->AddObserver(this); if (mIsDocumentGone) { NS_WARNING("Adding a presshell that was disconnected from the document " "as a document observer? Sounds wrong..."); @@ -2557,10 +2431,7 @@ PresShell::EndObservingDocument() // is gone, perhaps? Except for printing it's NOT gone, sometimes. mIsDocumentGone = PR_TRUE; if (mDocument) { - mDocument->RemoveObserver(mDocumentObserverForNonDynamicContext ? - mDocumentObserverForNonDynamicContext.get() : - this); - mDocumentObserverForNonDynamicContext = nsnull; + mDocument->RemoveObserver(this); } return NS_OK; } @@ -3624,10 +3495,6 @@ PresShell::RecreateFramesFor(nsIContent* aContent) return NS_OK; } - if (!mPresContext->IsDynamic()) { - return NS_OK; - } - // Don't call RecreateFramesForContent since that is not exported and we want // to keep the number of entrypoints down. @@ -5159,9 +5026,6 @@ PresShell::ContentRemoved(nsIDocument *aDocument, nsresult PresShell::ReconstructFrames(void) { - if (!mPresContext || !mPresContext->IsDynamic()) { - return NS_OK; - } nsAutoCauseReflowNotifier crNotifier(this); mFrameConstructor->BeginUpdate(); nsresult rv = mFrameConstructor->ReconstructDocElementHierarchy(); diff --git a/layout/base/tests/chrome/bug396024_helper.xul b/layout/base/tests/chrome/bug396024_helper.xul index 9ee34c72ddbc..8d246aa51167 100644 --- a/layout/base/tests/chrome/bug396024_helper.xul +++ b/layout/base/tests/chrome/bug396024_helper.xul @@ -8,6 +8,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=396024 + + + + + + + + + + + + + + Mozilla Bug 529621 + +

+ +
+  
+ + + + + + + + + + + + + + + + + + + + + + +
col1col2
caption
cell1cell2
cell3cell4
caption2
cell5cell6
+ + + + + + + + + + + + +
colheader
bla
+ + + + + + +
rowheadercell
+ + From c91de797cc159ea70d4118c71f3545f76d88d5cf Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Sat, 12 Dec 2009 03:38:33 +0800 Subject: [PATCH 128/179] Bug 527466 - (nsAccessibleTreeWalker) Less frame walking, more node walking, r=marcoz, davidb --- accessible/public/nsIAccessibilityService.idl | 17 ++- .../src/base/nsAccessibilityService.cpp | 48 ++------ .../src/base/nsAccessibleTreeWalker.cpp | 114 ++++++++++-------- accessible/src/base/nsAccessibleTreeWalker.h | 7 +- 4 files changed, 91 insertions(+), 95 deletions(-) diff --git a/accessible/public/nsIAccessibilityService.idl b/accessible/public/nsIAccessibilityService.idl index 5dafbaa1eb69..49d4bf2ad98d 100644 --- a/accessible/public/nsIAccessibilityService.idl +++ b/accessible/public/nsIAccessibilityService.idl @@ -46,7 +46,7 @@ interface nsObjectFrame; interface nsIContent; interface nsITimer; -[uuid(29384ba1-f9ce-425d-afb5-54e2ee949d87)] +[uuid(61098f48-4fcc-4b05-9cf3-c11b8efbe682)] interface nsIAccessibilityService : nsIAccessibleRetrieval { nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode); @@ -76,9 +76,18 @@ interface nsIAccessibilityService : nsIAccessibleRetrieval nsIAccessible createHTMLTextFieldAccessible(in nsIFrame aFrame); nsIAccessible createHTMLCaptionAccessible(in nsIFrame aFrame); - nsIAccessible getAccessible(in nsIDOMNode aNode, in nsIPresShell aPresShell, - in nsIWeakReference aWeakShell, - inout nsIFrame frameHint, out boolean aIsHidden); + /** + * Return an accessible for the given DOM node. + * + * @param aNode [in] the given node + * @param aPresShell [in] the pres shell of the node + * @param aWeakShell [in] the weak shell for the pres shell + * @param aFrameHint [in] the frame of the given node + * @param aIsHidden [out] indicates whether the node's frame is hidden + */ + nsIAccessible getAccessible(in nsIDOMNode aNode, in nsIPresShell aPresShell, + in nsIWeakReference aWeakShell, + in nsIFrame aFrameHint, out boolean aIsHidden); // For gtk+ native window accessible nsIAccessible addNativeRootAccessible(in voidPtr aAtkAccessible); diff --git a/accessible/src/base/nsAccessibilityService.cpp b/accessible/src/base/nsAccessibilityService.cpp index df05ef6b63ec..48770a5798ac 100644 --- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -1242,10 +1242,9 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleInShell(nsIDOMNode *aNode, NS_ENSURE_ARG(aPresShell); nsCOMPtr weakShell(do_GetWeakReference(aPresShell)); - nsIFrame *outFrameUnused = NULL; PRBool isHiddenUnused = false; return GetAccessible(aNode, aPresShell, weakShell, - &outFrameUnused, &isHiddenUnused, aAccessible); + nsnull, &isHiddenUnused, aAccessible); } NS_IMETHODIMP nsAccessibilityService::GetAccessibleInWeakShell(nsIDOMNode *aNode, @@ -1259,10 +1258,9 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleInWeakShell(nsIDOMNode *aNode NS_ENSURE_ARG(aWeakShell); nsCOMPtr presShell(do_QueryReferent(aWeakShell)); - nsIFrame *outFrameUnused = NULL; PRBool isHiddenUnused = false; return GetAccessible(aNode, presShell, aWeakShell, - &outFrameUnused, &isHiddenUnused, aAccessible); + nsnull, &isHiddenUnused, aAccessible); } nsresult nsAccessibilityService::InitAccessible(nsIAccessible *aAccessibleIn, @@ -1315,13 +1313,13 @@ static PRBool HasRelatedContent(nsIContent *aContent) NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, nsIPresShell *aPresShell, nsIWeakReference *aWeakShell, - nsIFrame **aFrameHint, + nsIFrame *aFrameHint, PRBool *aIsHidden, nsIAccessible **aAccessible) { NS_ENSURE_ARG_POINTER(aAccessible); - NS_ENSURE_ARG_POINTER(aFrameHint); *aAccessible = nsnull; + if (!aPresShell || !aWeakShell || gIsShutdown) { return NS_ERROR_FAILURE; } @@ -1334,7 +1332,7 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, // that can flush layout, either directly, or via DOM manipulation, or some // CSS styles like :hover. We use the weak frame checks to avoid calling // methods on a dead frame pointer. - nsWeakFrame weakFrame(*aFrameHint); + nsWeakFrame weakFrame(aFrameHint); #ifdef DEBUG_A11Y // Please leave this in for now, it's a convenient debugging method @@ -1391,7 +1389,6 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, CreateRootAccessible(aPresShell, nodeIsDoc, getter_AddRefs(newAcc)); // Does Init() for us } - *aFrameHint = aPresShell->GetRootFrame(); NS_IF_ADDREF(*aAccessible = newAcc); return NS_OK; } @@ -1421,7 +1418,7 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, if (content->IsNodeOfType(nsINode::eTEXT)) { ++frameHintFailedForText; } - frameHintNonexistant += !*aFrameHint; + frameHintNonexistant += !aFrameHint; printf("Frame hint failures: %d / %d . Text fails = %d. No hint fails = %d \n", frameHintFailed, frameHintTried, frameHintFailedForText, frameHintNonexistant); if (frameHintTried >= 354) { printf("* "); // Aaron's break point @@ -1450,7 +1447,6 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, return NS_OK; } - *aFrameHint = weakFrame.GetFrame(); } } @@ -1460,10 +1456,8 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, *aIsHidden = PR_TRUE; } - if (*aIsHidden) { - *aFrameHint = weakFrame.GetFrame(); + if (*aIsHidden) return NS_OK; - } /** * Attempt to create an accessible based on what we know @@ -1477,7 +1471,6 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, if (renderedWhitespace.IsEmpty()) { // Really empty -- nothing is rendered *aIsHidden = PR_TRUE; - *aFrameHint = weakFrame.GetFrame(); return NS_OK; } } @@ -1485,9 +1478,7 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, weakFrame.GetFrame()->GetAccessible(getter_AddRefs(newAcc)); } - nsresult rv = InitAccessible(newAcc, aAccessible, nsnull); - *aFrameHint = weakFrame.GetFrame(); - return rv; + return InitAccessible(newAcc, aAccessible, nsnull); } PRBool isHTML = content->IsHTML(); @@ -1504,16 +1495,12 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::name, name); if (!name.IsEmpty()) { *aIsHidden = PR_TRUE; - *aFrameHint = weakFrame.GetFrame(); return NS_OK; } nsresult rv = CreateHyperTextAccessible(weakFrame.GetFrame(), getter_AddRefs(newAcc)); - if (NS_FAILED(rv)) { - *aFrameHint = weakFrame.GetFrame(); - return rv; - } + NS_ENSURE_SUCCESS(rv, rv); } nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode); @@ -1522,7 +1509,6 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, // Only create accessible for role of "presentation" if it is focusable -- // in that case we need an accessible in case it gets focused, we // don't want focus ever to be 'lost' - *aFrameHint = weakFrame.GetFrame(); return NS_OK; } @@ -1580,7 +1566,6 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, // presentation if they aren't focusable and have not explicit ARIA // role (don't create accessibles for them unless they need to fire // focus events). - *aFrameHint = weakFrame.GetFrame(); return NS_OK; } @@ -1628,10 +1613,7 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, nsresult rv = CreateHTMLAccessibleByMarkup(weakFrame.GetFrame(), aWeakShell, aNode, getter_AddRefs(newAcc)); - if (NS_FAILED(rv)) { - *aFrameHint = weakFrame.GetFrame(); - return rv; - } + NS_ENSURE_SUCCESS(rv, rv); if (!newAcc) { // Do not create accessible object subtrees for non-rendered table @@ -1649,7 +1631,6 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, // XXX This is not the ideal place for this code, but right now there // is no better place: *aIsHidden = PR_TRUE; - *aFrameHint = weakFrame.GetFrame(); return NS_OK; } f->GetAccessible(getter_AddRefs(newAcc)); // Try using frame to do it @@ -1661,10 +1642,7 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, // Elements may implement nsIAccessibleProvider via XBL. This allows them to // say what kind of accessible to create. nsresult rv = GetAccessibleByType(aNode, getter_AddRefs(newAcc)); - if (NS_FAILED(rv)) { - *aFrameHint = weakFrame.GetFrame(); - return rv; - } + NS_ENSURE_SUCCESS(rv, rv); } if (!newAcc) { @@ -1707,9 +1685,7 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, } } - nsresult rv = InitAccessible(newAcc, aAccessible, roleMapEntry); - *aFrameHint = weakFrame.GetFrame(); - return rv; + return InitAccessible(newAcc, aAccessible, roleMapEntry); } PRBool diff --git a/accessible/src/base/nsAccessibleTreeWalker.cpp b/accessible/src/base/nsAccessibleTreeWalker.cpp index dece7a3cbfff..b6df6491a100 100644 --- a/accessible/src/base/nsAccessibleTreeWalker.cpp +++ b/accessible/src/base/nsAccessibleTreeWalker.cpp @@ -77,7 +77,7 @@ void nsAccessibleTreeWalker::GetKids(nsIDOMNode *aParentNode) mState.frame = nsnull; // Don't walk frames in non-HTML content, just walk the DOM. } - UpdateFrame(PR_TRUE); + WalkFrames(); // Walk frames? UpdateFrame() sets this when it sees anonymous frames if (mState.siblingIndex == eSiblingsWalkFrames) { @@ -160,20 +160,40 @@ NS_IMETHODIMP nsAccessibleTreeWalker::PushState() void nsAccessibleTreeWalker::GetNextDOMNode() { - // Get next DOM node + // Get next DOM node and its frame. if (mState.parentContent) { - mState.domNode = do_QueryInterface(mState.parentContent->GetChildAt(++mState.siblingIndex)); - } - else if (mState.siblingIndex == eSiblingsWalkFrames) { - if (mState.frame.GetFrame()) { - mState.domNode = do_QueryInterface(mState.frame.GetFrame()->GetContent()); - } else { - mState.domNode = nsnull; + mState.domNode = + do_QueryInterface(mState.parentContent->GetChildAt(++mState.siblingIndex)); + + } else if (mState.siblingIndex == eSiblingsWalkFrames) { + if (mState.frame.IsAlive()) { + mState.frame = mState.frame.GetFrame()->GetNextSibling(); + + if (mState.frame.IsAlive()) { + mState.domNode = do_QueryInterface(mState.frame.GetFrame()->GetContent()); + return; + } } + + mState.domNode = nsnull; + return; + + } else { + mState.siblingList->Item(++mState.siblingIndex, + getter_AddRefs(mState.domNode)); } - else { - mState.siblingList->Item(++mState.siblingIndex, getter_AddRefs(mState.domNode)); - } + + // Update the frame. + nsCOMPtr presShell(do_QueryReferent(mWeakShell)); + NS_ASSERTION(presShell, "Huh? No presshell?"); + if (!presShell) + return; + + nsCOMPtr content = do_QueryInterface(mState.domNode); + if (content) + mState.frame = presShell->GetRealPrimaryFrameFor(content); + else + mState.frame = presShell->GetRootFrame(); } NS_IMETHODIMP nsAccessibleTreeWalker::GetNextSibling() @@ -185,7 +205,6 @@ NS_IMETHODIMP nsAccessibleTreeWalker::GetNextSibling() while (PR_TRUE) { // Get next frame - UpdateFrame(PR_FALSE); GetNextDOMNode(); if (!mState.domNode) { // Done with current siblings @@ -219,7 +238,7 @@ NS_IMETHODIMP nsAccessibleTreeWalker::GetFirstChild() while (mState.domNode) { if ((mState.domNode != parent && GetAccessible()) || NS_SUCCEEDED(GetFirstChild())) return NS_OK; - UpdateFrame(PR_FALSE); + GetNextDOMNode(); } @@ -227,50 +246,46 @@ NS_IMETHODIMP nsAccessibleTreeWalker::GetFirstChild() return NS_ERROR_FAILURE; } -void nsAccessibleTreeWalker::UpdateFrame(PRBool aTryFirstChild) +void +nsAccessibleTreeWalker::WalkFrames() { nsIFrame *curFrame = mState.frame.GetFrame(); if (!curFrame) { return; } - if (aTryFirstChild) { - // If the frame implements nsIAnonymousContentCreator interface then go down - // through the frames and obtain anonymous nodes for them. - nsIAnonymousContentCreator* creator = do_QueryFrame(curFrame); - nsIFrame *child = curFrame->GetFirstChild(nsnull); - mState.frame = child; + // If the frame implements nsIAnonymousContentCreator interface then go down + // through the frames and obtain anonymous nodes for them. + nsIAnonymousContentCreator* creator = do_QueryFrame(curFrame); + nsIFrame *child = curFrame->GetFirstChild(nsnull); - if (creator && child && mState.siblingIndex < 0) { - mState.domNode = do_QueryInterface(child->GetContent()); - mState.siblingIndex = eSiblingsWalkFrames; - } + if (creator && child && mState.siblingIndex < 0) { + mState.frame = child; + mState.domNode = do_QueryInterface(child->GetContent()); + mState.siblingIndex = eSiblingsWalkFrames; + } // temporary workaround for Bug 359210. We never want to walk frames. // Aaron Leventhal will refix :before and :after content later without walking frames. #if 0 - if (mState.frame && mState.siblingIndex < 0) { - // Container frames can contain generated content frames from - // :before and :after style rules, so we walk their frame trees - // instead of content trees - // XXX Walking the frame tree doesn't get us Aural CSS nodes, e.g. - // @media screen { display: none; } - // Asking the style system might be better (with ProbePseudoStyleFor(), - // except that we need to ask only for those display types that support - // :before and :after (which roughly means non-replaced elements) - // Here's some code to see if there is an :after rule for an element - // nsRefPtr pseudoContext; - // nsStyleContext *styleContext = primaryFrame->GetStyleContext(); - // if (aContent) { - // pseudoContext = presContext->StyleSet()-> - // ProbePseudoStyleFor(content, nsAccessibilityAtoms::after, aStyleContext); - mState.domNode = do_QueryInterface(mState.frame->GetContent()); - mState.siblingIndex = eSiblingsWalkFrames; - } + if (mState.frame && mState.siblingIndex < 0) { + // Container frames can contain generated content frames from + // :before and :after style rules, so we walk their frame trees + // instead of content trees + // XXX Walking the frame tree doesn't get us Aural CSS nodes, e.g. + // @media screen { display: none; } + // Asking the style system might be better (with ProbePseudoStyleFor(), + // except that we need to ask only for those display types that support + // :before and :after (which roughly means non-replaced elements) + // Here's some code to see if there is an :after rule for an element + // nsRefPtr pseudoContext; + // nsStyleContext *styleContext = primaryFrame->GetStyleContext(); + // if (aContent) { + // pseudoContext = presContext->StyleSet()-> + // ProbePseudoStyleFor(content, nsAccessibilityAtoms::after, aStyleContext); + mState.domNode = do_QueryInterface(mState.frame->GetContent()); + mState.siblingIndex = eSiblingsWalkFrames; + } #endif - } - else { - mState.frame = curFrame->GetNextSibling(); - } } /** @@ -286,11 +301,10 @@ PRBool nsAccessibleTreeWalker::GetAccessible() mState.accessible = nsnull; nsCOMPtr presShell(do_QueryReferent(mWeakShell)); - nsIFrame *frame = mState.frame.GetFrame(); mAccService->GetAccessible(mState.domNode, presShell, mWeakShell, - &frame, &mState.isHidden, + mState.frame.GetFrame(), &mState.isHidden, getter_AddRefs(mState.accessible)); - mState.frame = frame; + return mState.accessible ? PR_TRUE : PR_FALSE; } diff --git a/accessible/src/base/nsAccessibleTreeWalker.h b/accessible/src/base/nsAccessibleTreeWalker.h index 58a2028df77b..b74b09a743c5 100644 --- a/accessible/src/base/nsAccessibleTreeWalker.h +++ b/accessible/src/base/nsAccessibleTreeWalker.h @@ -121,12 +121,9 @@ protected: NS_IMETHOD PopState(); /** - * Change current state so that its frame is changed to next frame. - * - * @param aTryFirstChild [in] points whether we should move to child or - * sibling frame + * Make treewalker traverse by frame tree if necessary. */ - void UpdateFrame(PRBool aTryFirstChild); + void WalkFrames(); /** * Change current state so that its node is changed to next node. From 91d414a663bbd2d0c9f8ee0daec90b40c6d2ce6e Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Sat, 12 Dec 2009 03:38:55 +0800 Subject: [PATCH 129/179] Bug 530014 - ARIA single selectable widget should implement nsIAccessibleSelectable, r=marcoz, davidb --HG-- rename : accessible/tests/mochitest/test_selectable_tree.xul => accessible/tests/mochitest/selectable/test_tree.xul --- accessible/src/base/nsAccUtils.cpp | 71 ++++++----- accessible/src/base/nsAccUtils.h | 20 ++- accessible/src/base/nsAccessible.cpp | 30 ++--- accessible/src/base/nsDocAccessible.cpp | 2 +- .../src/html/nsHTMLSelectAccessible.cpp | 2 +- accessible/tests/mochitest/Makefile.in | 3 +- .../tests/mochitest/selectable/Makefile.in | 55 ++++++++ .../tests/mochitest/selectable/test_aria.html | 120 ++++++++++++++++++ .../mochitest/selectable/test_select.html | 66 ++++++++++ .../test_tree.xul} | 0 10 files changed, 312 insertions(+), 57 deletions(-) create mode 100644 accessible/tests/mochitest/selectable/Makefile.in create mode 100644 accessible/tests/mochitest/selectable/test_aria.html create mode 100644 accessible/tests/mochitest/selectable/test_select.html rename accessible/tests/mochitest/{test_selectable_tree.xul => selectable/test_tree.xul} (100%) diff --git a/accessible/src/base/nsAccUtils.cpp b/accessible/src/base/nsAccUtils.cpp index faf287e008dd..65be3a3d5d1d 100644 --- a/accessible/src/base/nsAccUtils.cpp +++ b/accessible/src/base/nsAccUtils.cpp @@ -502,6 +502,46 @@ nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem, } } +already_AddRefed +nsAccUtils::GetSelectableContainer(nsIAccessible *aAccessible, PRUint32 aState) +{ + if (!aAccessible) + return nsnull; + + if (!(aState & nsIAccessibleStates::STATE_SELECTABLE)) + return nsnull; + + nsCOMPtr container; + nsCOMPtr parent, accessible(aAccessible); + while (!container) { + accessible->GetParent(getter_AddRefs(parent)); + + if (!parent || Role(parent) == nsIAccessibleRole::ROLE_PANE) + return nsnull; + + container = do_QueryInterface(parent); + parent.swap(accessible); + } + + return accessible.forget(); +} + +already_AddRefed +nsAccUtils::GetMultiSelectableContainer(nsIDOMNode *aNode) +{ + nsCOMPtr accessible; + nsAccessNode::GetAccService()->GetAccessibleFor(aNode, + getter_AddRefs(accessible)); + + nsCOMPtr container = + GetSelectableContainer(accessible, State(accessible)); + + if (State(container) & nsIAccessibleStates::STATE_MULTISELECTABLE) + return container.forget(); + + return nsnull; +} + PRBool nsAccUtils::IsARIASelected(nsIAccessible *aAccessible) { @@ -927,37 +967,6 @@ nsAccUtils::IsNodeRelevant(nsIDOMNode *aNode) return aNode == relevantNode; } -already_AddRefed -nsAccUtils::GetMultiSelectFor(nsIDOMNode *aNode) -{ - if (!aNode) - return nsnull; - - nsCOMPtr accessible; - nsAccessNode::GetAccService()->GetAccessibleFor(aNode, - getter_AddRefs(accessible)); - if (!accessible) - return nsnull; - - PRUint32 state = State(accessible); - if (0 == (state & nsIAccessibleStates::STATE_SELECTABLE)) - return nsnull; - - while (0 == (state & nsIAccessibleStates::STATE_MULTISELECTABLE)) { - nsIAccessible *current = accessible; - current->GetParent(getter_AddRefs(accessible)); - if (!accessible || - nsAccUtils::Role(accessible) == nsIAccessibleRole::ROLE_PANE) { - return nsnull; - } - state = State(accessible); - } - - nsIAccessible *returnAccessible = nsnull; - accessible.swap(returnAccessible); - return returnAccessible; -} - nsresult nsAccUtils::GetHeaderCellsFor(nsIAccessibleTable *aTable, nsIAccessibleTableCell *aCell, diff --git a/accessible/src/base/nsAccUtils.h b/accessible/src/base/nsAccUtils.h index 282b14a951c7..675c7397bb4e 100644 --- a/accessible/src/base/nsAccUtils.h +++ b/accessible/src/base/nsAccUtils.h @@ -179,6 +179,21 @@ public: nsIContent *aStartTreeItemContent, nsIAccessible **aTreeItemParent); + /** + * Return single or multi selectable container for the given item. + * + * @param aAccessible [in] the item accessible + * @param aState [in] the state of the item accessible + */ + static already_AddRefed + GetSelectableContainer(nsIAccessible *aAccessible, PRUint32 aState); + + /** + * Return multi selectable container for the given item. + */ + static already_AddRefed + GetMultiSelectableContainer(nsIDOMNode *aNode); + /** * Return true if the DOM node of given accessible has aria-selected="true" * attribute. @@ -467,11 +482,6 @@ public: */ static PRBool IsNodeRelevant(nsIDOMNode *aNode); - /** - * Return multiselectable parent for the given selectable accessible if any. - */ - static already_AddRefed GetMultiSelectFor(nsIDOMNode *aNode); - /** * Search hint enum constants. Used by GetHeaderCellsFor() method. */ diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index efe0f1e6f08b..e657556e329b 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -184,23 +184,19 @@ nsresult nsAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) } if (aIID.Equals(NS_GET_IID(nsIAccessibleSelectable))) { - nsCOMPtr content(do_QueryInterface(mDOMNode)); - if (!content) { - return NS_ERROR_FAILURE; // This accessible has been shut down - } - if (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) { - // If we have an XHTML role attribute present and the - // aria-multiselectable attribute is true, then we need - // to support nsIAccessibleSelectable + if (mRoleMapEntry && + (mRoleMapEntry->attributeMap1 == eARIAMultiSelectable || + mRoleMapEntry->attributeMap2 == eARIAMultiSelectable || + mRoleMapEntry->attributeMap3 == eARIAMultiSelectable)) { + + // If we have an ARIA role attribute present and the role allows multi + // selectable state, then we need to support nsIAccessibleSelectable. // If either attribute (role or multiselectable) change, then we'll // destroy this accessible so that we can follow COM identity rules. - nsAutoString multiselectable; - if (content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::aria_multiselectable, - nsAccessibilityAtoms::_true, eCaseMatters)) { - *aInstancePtr = static_cast(this); - NS_ADDREF_THIS(); - return NS_OK; - } + + *aInstancePtr = static_cast(this); + NS_ADDREF_THIS(); + return NS_OK; } } @@ -1183,7 +1179,7 @@ NS_IMETHODIMP nsAccessible::SetSelected(PRBool aSelect) PRUint32 state = nsAccUtils::State(this); if (state & nsIAccessibleStates::STATE_SELECTABLE) { nsCOMPtr multiSelect = - nsAccUtils::GetMultiSelectFor(mDOMNode); + nsAccUtils::GetMultiSelectableContainer(mDOMNode); if (!multiSelect) { return aSelect ? TakeFocus() : NS_ERROR_FAILURE; } @@ -1213,7 +1209,7 @@ NS_IMETHODIMP nsAccessible::TakeSelection() PRUint32 state = nsAccUtils::State(this); if (state & nsIAccessibleStates::STATE_SELECTABLE) { nsCOMPtr multiSelect = - nsAccUtils::GetMultiSelectFor(mDOMNode); + nsAccUtils::GetMultiSelectableContainer(mDOMNode); if (multiSelect) { nsCOMPtr selectable = do_QueryInterface(multiSelect); selectable->ClearSelection(); diff --git a/accessible/src/base/nsDocAccessible.cpp b/accessible/src/base/nsDocAccessible.cpp index 89ef2540dcb9..7bf74c9251f1 100644 --- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -1169,7 +1169,7 @@ nsDocAccessible::AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID aAttribute == nsAccessibilityAtoms::aria_selected) { // ARIA or XUL selection nsCOMPtr multiSelect = - nsAccUtils::GetMultiSelectFor(targetNode); + nsAccUtils::GetMultiSelectableContainer(targetNode); // Multi selects use selection_add and selection_remove // Single select widgets just mirror event_selection for // whatever gets event_focus, which is done in diff --git a/accessible/src/html/nsHTMLSelectAccessible.cpp b/accessible/src/html/nsHTMLSelectAccessible.cpp index 5a4dbd4497b5..91f24949cc7f 100644 --- a/accessible/src/html/nsHTMLSelectAccessible.cpp +++ b/accessible/src/html/nsHTMLSelectAccessible.cpp @@ -795,7 +795,7 @@ void nsHTMLSelectOptionAccessible::SelectionChangedIfOption(nsIContent *aPossibl NS_ASSERTION(optionNode, "No option node for nsIContent with option tag!"); nsCOMPtr multiSelect = - nsAccUtils::GetMultiSelectFor(optionNode); + nsAccUtils::GetMultiSelectableContainer(optionNode); if (!multiSelect) return; diff --git a/accessible/tests/mochitest/Makefile.in b/accessible/tests/mochitest/Makefile.in index 0ce639c81016..14ca34664e9c 100644 --- a/accessible/tests/mochitest/Makefile.in +++ b/accessible/tests/mochitest/Makefile.in @@ -42,7 +42,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ relativesrcdir = accessible -DIRS = tree +DIRS = tree selectable include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk @@ -132,7 +132,6 @@ _TEST_FILES =\ test_relations_tree.xul \ test_role_nsHyperTextAcc.html \ test_role_table_cells.html \ - test_selectable_tree.xul \ test_states.html \ test_states_doc.html \ test_states_docarticle.html \ diff --git a/accessible/tests/mochitest/selectable/Makefile.in b/accessible/tests/mochitest/selectable/Makefile.in new file mode 100644 index 000000000000..48cc8406231f --- /dev/null +++ b/accessible/tests/mochitest/selectable/Makefile.in @@ -0,0 +1,55 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Mozilla Corporation. +# Portions created by the Initial Developer are Copyright (C) 2009 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Alexander Surkov (original author) +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ +relativesrcdir = accessible/selectable + +include $(DEPTH)/config/autoconf.mk +include $(topsrcdir)/config/rules.mk + +_TEST_FILES =\ + test_aria.html \ + test_select.html \ + test_tree.xul \ + $(NULL) + +libs:: $(_TEST_FILES) + $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir) diff --git a/accessible/tests/mochitest/selectable/test_aria.html b/accessible/tests/mochitest/selectable/test_aria.html new file mode 100644 index 000000000000..d78c83836762 --- /dev/null +++ b/accessible/tests/mochitest/selectable/test_aria.html @@ -0,0 +1,120 @@ + + + + nsIAccessibleSelectable ARIA widgets testing + + + + + + + + + + + + + + + + + + + Mozilla Bug 530014 +
+

+ +
+  
+ +
+
item1
+
item2
+
+ +
+
item1
+
item2
+
+ +
+
item1
+
item2
+
+ +
+
+ cell + cell +
+
+ cell + cell +
+
+ +
+
+ item1 +
+
item1.1
+
+
+
item2
+
+ +
+
+ cell + cell +
+
+ cell + cell +
+
+ cell + cell +
+
+ + diff --git a/accessible/tests/mochitest/selectable/test_select.html b/accessible/tests/mochitest/selectable/test_select.html new file mode 100644 index 000000000000..8971c26400e9 --- /dev/null +++ b/accessible/tests/mochitest/selectable/test_select.html @@ -0,0 +1,66 @@ + + + + nsIAccessibleSelectable HTML select testing + + + + + + + + + + + + + + + + + + + Mozilla Bug 530014 +
+

+ +
+  
+ + + + + + + diff --git a/accessible/tests/mochitest/test_selectable_tree.xul b/accessible/tests/mochitest/selectable/test_tree.xul similarity index 100% rename from accessible/tests/mochitest/test_selectable_tree.xul rename to accessible/tests/mochitest/selectable/test_tree.xul From 7b2ab07e57519685db92439d91ec4a3a06ffdf6d Mon Sep 17 00:00:00 2001 From: Ginn Chen Date: Sat, 12 Dec 2009 03:39:08 +0800 Subject: [PATCH 130/179] Bug 342045 - solaris bustage fix, r=surkov --- accessible/src/xul/nsXULTreeAccessible.cpp | 2 +- accessible/src/xul/nsXULTreeGridAccessible.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/accessible/src/xul/nsXULTreeAccessible.cpp b/accessible/src/xul/nsXULTreeAccessible.cpp index 048f4642cc9c..0cbd29a702fd 100644 --- a/accessible/src/xul/nsXULTreeAccessible.cpp +++ b/accessible/src/xul/nsXULTreeAccessible.cpp @@ -1073,7 +1073,7 @@ nsXULTreeItemAccessibleBase::GetStateInternal(PRUint32 *aState, nsIAccessible* nsXULTreeItemAccessibleBase::GetParent() { - return IsDefunct() ? nsnull : mParent; + return IsDefunct() ? nsnull : mParent.get(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/src/xul/nsXULTreeGridAccessible.cpp b/accessible/src/xul/nsXULTreeGridAccessible.cpp index d369670916e0..647c13bfc312 100644 --- a/accessible/src/xul/nsXULTreeGridAccessible.cpp +++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp @@ -1225,7 +1225,7 @@ nsXULTreeGridCellAccessible::GetStateInternal(PRUint32 *aStates, nsIAccessible* nsXULTreeGridCellAccessible::GetParent() { - return IsDefunct() ? nsnull : mParent; + return IsDefunct() ? nsnull : mParent.get(); } //////////////////////////////////////////////////////////////////////////////// From 3a94be32e4d82ebb83de9934f7a0a10cb54f9cdf Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Fri, 11 Dec 2009 12:50:54 -0800 Subject: [PATCH 131/179] Bug 534051, r=jorendorff+jst, sr=jst. --- dom/src/threads/nsDOMWorker.cpp | 2 ++ js/src/jsapi.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/dom/src/threads/nsDOMWorker.cpp b/dom/src/threads/nsDOMWorker.cpp index bbb21407a0ba..7cfe52a148a3 100644 --- a/dom/src/threads/nsDOMWorker.cpp +++ b/dom/src/threads/nsDOMWorker.cpp @@ -1489,6 +1489,8 @@ nsDOMWorker::SetGlobalForContext(JSContext* aCx) return PR_FALSE; } + JSAutoRequest ar(aCx); + JS_SetGlobalObject(aCx, mGlobal); return PR_TRUE; } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 00de732cc37d..4f86761630ab 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1216,6 +1216,7 @@ JS_GetGlobalObject(JSContext *cx) JS_PUBLIC_API(void) JS_SetGlobalObject(JSContext *cx, JSObject *obj) { + CHECK_REQUEST(cx); cx->globalObject = obj; #if JS_HAS_XML_SUPPORT From ec313f69b932e554243c16ff03f7f9f4930a8faa Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Fri, 11 Dec 2009 14:30:27 -0800 Subject: [PATCH 132/179] Bustage fix, r=mrbkap --- js/src/xpconnect/src/xpccomponents.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp index 3c2b5b1a405a..a459ae77292d 100644 --- a/js/src/xpconnect/src/xpccomponents.cpp +++ b/js/src/xpconnect/src/xpccomponents.cpp @@ -3416,6 +3416,7 @@ ContextHolder::ContextHolder(JSContext *aOuterCx, JSObject *aSandbox) { if(mJSContext) { + JSAutoRequest ar(mJSContext); JS_SetOptions(mJSContext, JSOPTION_DONT_REPORT_UNCAUGHT | JSOPTION_PRIVATE_IS_NSISUPPORTS); From 461f05b3f0b0a8bc87253b14ebba11ecf9351806 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Tue, 24 Nov 2009 14:28:18 +0200 Subject: [PATCH 133/179] Bug 529544 - Shut down the HTML5 parser thread from an observer (random crash [@ mozilla::storage::Connection::Close()]). r=sdwilsh. --HG-- extra : rebase_source : b63735cb935261066b0836d451967a87a5c22929 --- parser/html/nsHtml5Module.cpp | 33 +++++++++++++++++-- parser/htmlparser/tests/mochitest/Makefile.in | 4 +-- .../tests/mochitest/test_compatmode.html | 10 +++--- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/parser/html/nsHtml5Module.cpp b/parser/html/nsHtml5Module.cpp index daad73913b9e..33f8e8a66dd2 100644 --- a/parser/html/nsHtml5Module.cpp +++ b/parser/html/nsHtml5Module.cpp @@ -46,6 +46,8 @@ #include "nsHtml5TreeBuilder.h" #include "nsHtml5UTF16Buffer.h" #include "nsHtml5Module.h" +#include "nsIObserverService.h" +#include "nsIServiceManager.h" // static PRBool nsHtml5Module::sEnabled = PR_FALSE; @@ -90,9 +92,6 @@ nsHtml5Module::ReleaseStatics() nsHtml5Tokenizer::releaseStatics(); nsHtml5TreeBuilder::releaseStatics(); nsHtml5UTF16Buffer::releaseStatics(); - if (sStreamParserThread) { - sStreamParserThread->Shutdown(); - } NS_IF_RELEASE(sStreamParserThread); NS_IF_RELEASE(sMainThread); } @@ -116,6 +115,29 @@ nsHtml5Module::Initialize(nsIParser* aParser, nsIDocument* aDoc, nsIURI* aURI, n return parser->Initialize(aDoc, aURI, aContainer, aChannel); } +class nsHtml5ParserThreadTerminator : public nsIObserver +{ + public: + NS_DECL_ISUPPORTS + nsHtml5ParserThreadTerminator(nsIThread* aThread) + : mThread(aThread) + {} + NS_IMETHODIMP Observe(nsISupports *, const char *topic, const PRUnichar *) + { + NS_ASSERTION(!strcmp(topic, "xpcom-shutdown-threads"), + "Unexpected topic"); + if (mThread) { + mThread->Shutdown(); + mThread = nsnull; + } + return NS_OK; + } + private: + nsCOMPtr mThread; +}; + +NS_IMPL_ISUPPORTS1(nsHtml5ParserThreadTerminator, nsIObserver) + // static nsIThread* nsHtml5Module::GetStreamParserThread() @@ -124,6 +146,11 @@ nsHtml5Module::GetStreamParserThread() if (!sStreamParserThread) { NS_NewThread(&sStreamParserThread); NS_ASSERTION(sStreamParserThread, "Thread creation failed!"); + nsCOMPtr os = do_GetService("@mozilla.org/observer-service;1"); + NS_ASSERTION(os, "do_GetService failed"); + os->AddObserver(new nsHtml5ParserThreadTerminator(sStreamParserThread), + "xpcom-shutdown-threads", + PR_FALSE); } return sStreamParserThread; } diff --git a/parser/htmlparser/tests/mochitest/Makefile.in b/parser/htmlparser/tests/mochitest/Makefile.in index ac787859ed5e..dcddf627295e 100644 --- a/parser/htmlparser/tests/mochitest/Makefile.in +++ b/parser/htmlparser/tests/mochitest/Makefile.in @@ -57,6 +57,7 @@ _TEST_FILES = parser_datreader.js \ test_bug396568.html \ test_bug418464.html \ test_bug460437.xhtml \ + test_bug502091.html \ bug_502091_iframe.html \ test_compatmode.html \ regressions.txt \ @@ -65,6 +66,3 @@ _TEST_FILES = parser_datreader.js \ libs:: $(_TEST_FILES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) - -# Disabled due to bug 529544 -# test_bug502091.html \ diff --git a/parser/htmlparser/tests/mochitest/test_compatmode.html b/parser/htmlparser/tests/mochitest/test_compatmode.html index 17090f87ea16..2c7b618aeacf 100644 --- a/parser/htmlparser/tests/mochitest/test_compatmode.html +++ b/parser/htmlparser/tests/mochitest/test_compatmode.html @@ -77,12 +77,12 @@ function finishTest() { function test(mode,i){ is(mode,doctypes[i],doctypes[i+1]); if (i == doctypes.length - 2) { -// if (typeof(gOriginalHtml5Pref) == "undefined") { -// doTestHtml5(); Disabled due to bug 529544 -// } -// else { + if (typeof(gOriginalHtml5Pref) == "undefined") { + doTestHtml5(); + } + else { finishTest(); -// } + } } } From 5fa10d54ccc28e92fc0bb97d5a4d0f601145b3f0 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Wed, 11 Nov 2009 10:37:34 +0200 Subject: [PATCH 134/179] Crashtest for bug 525229 - Crash [@ nsHtml5PendingNotification::nsHtml5PendingNotification] when document.writing an external script followed by start tag. r=bnewman. --HG-- extra : rebase_source : 706b0fd3c4eadfc39d984eee4d71288d7b8c46e2 --- parser/htmlparser/tests/crashtests/525229-1.html | 7 +++++++ parser/htmlparser/tests/crashtests/crashtests.list | 1 + 2 files changed, 8 insertions(+) create mode 100644 parser/htmlparser/tests/crashtests/525229-1.html diff --git a/parser/htmlparser/tests/crashtests/525229-1.html b/parser/htmlparser/tests/crashtests/525229-1.html new file mode 100644 index 000000000000..8bffa7d6012b --- /dev/null +++ b/parser/htmlparser/tests/crashtests/525229-1.html @@ -0,0 +1,7 @@ + +Test for bug 525229 + + +text diff --git a/parser/htmlparser/tests/crashtests/crashtests.list b/parser/htmlparser/tests/crashtests/crashtests.list index 8623e7069162..066536bae1fc 100644 --- a/parser/htmlparser/tests/crashtests/crashtests.list +++ b/parser/htmlparser/tests/crashtests/crashtests.list @@ -38,4 +38,5 @@ load 468538-1.xhtml load 515278-1.html load 515533-1.html load 515816-1.html +load 525229-1.html load 522326-1.html From 7023e1003899b478060cce46058f2d7af4d9e1b1 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Fri, 6 Nov 2009 15:06:48 +0200 Subject: [PATCH 135/179] Bug 497861 - Wrong form state preservation on reparse in HTML5 parser. r=bnewman. --HG-- extra : rebase_source : 841506bea91507339e89eefa95cde68ca2d9a5dd --- content/base/src/nsContentUtils.cpp | 3 + parser/html/nsHtml5Parser.cpp | 10 +- parser/html/nsHtml5TreeBuilderCppSupplement.h | 8 ++ parser/html/nsHtml5TreeOpExecutor.cpp | 124 +++++++++--------- parser/html/nsHtml5TreeOpExecutor.h | 83 ++++++------ parser/html/nsHtml5TreeOperation.cpp | 13 +- parser/html/nsHtml5TreeOperation.h | 3 +- 7 files changed, 129 insertions(+), 115 deletions(-) diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 8cdc95803d9e..c7193f112493 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -1957,6 +1957,9 @@ nsContentUtils::GenerateStateKey(nsIContent* aContent, if (htmlDocument) { // Flush our content model so it'll be up to date + // If this becomes unnecessary and the following line is removed, + // please also remove the corresponding flush operation from + // nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.) aContent->GetCurrentDoc()->FlushPendingNotifications(Flush_Content); nsContentList *htmlForms = htmlDocument->GetForms(); diff --git a/parser/html/nsHtml5Parser.cpp b/parser/html/nsHtml5Parser.cpp index 2257c77332d3..77547d2ad0f0 100644 --- a/parser/html/nsHtml5Parser.cpp +++ b/parser/html/nsHtml5Parser.cpp @@ -251,7 +251,7 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer, PRBool aLastCall, nsDTDMode aMode) // ignored { - NS_PRECONDITION(!mFragmentMode, "Document.write called in fragment mode!"); + NS_PRECONDITION(!mExecutor->IsFragmentMode(), "Document.write called in fragment mode!"); // Maintain a reference to ourselves so we don't go away // till we're completely done. The old parser grips itself in this method. @@ -458,7 +458,7 @@ nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer, nsIContent* weakTarget = target; mTreeBuilder->setFragmentContext(aContextLocalName, aContextNamespace, &weakTarget, aQuirks); - mFragmentMode = PR_TRUE; + mExecutor->EnableFragmentMode(); NS_PRECONDITION(!mExecutor->HasStarted(), "Tried to start parse without initializing the parser properly."); mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled()); @@ -474,7 +474,6 @@ nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer, lastWasCR = PR_FALSE; if (buffer.hasMore()) { lastWasCR = mTokenizer->tokenizeBuffer(&buffer); - mExecutor->MaybePreventExecution(); } } } @@ -507,7 +506,6 @@ nsHtml5Parser::Reset() { mExecutor->Reset(); mLastWasCR = PR_FALSE; - mFragmentMode = PR_FALSE; UnblockParser(); mDocumentClosed = PR_FALSE; mStreamParser = nsnull; @@ -524,7 +522,7 @@ nsHtml5Parser::Reset() PRBool nsHtml5Parser::CanInterrupt() { - return !mFragmentMode; + return !mExecutor->IsFragmentMode(); } PRBool @@ -565,7 +563,7 @@ nsHtml5Parser::IsScriptCreated() void nsHtml5Parser::ParseUntilBlocked() { - NS_PRECONDITION(!mFragmentMode, "ParseUntilBlocked called in fragment mode."); + NS_PRECONDITION(!mExecutor->IsFragmentMode(), "ParseUntilBlocked called in fragment mode."); if (mBlocked) { return; diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index 43cadf8bb371..b0c0f3b064e1 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -541,6 +541,14 @@ nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent } if (aName == nsHtml5Atoms::input || aName == nsHtml5Atoms::button) { + if (!formPointer) { + // If form inputs don't belong to a form, their state preservation + // won't work right without an append notification flush at this + // point. See bug 497861. + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + treeOp->Init(eTreeOpFlushPendingAppendNotifications); + } nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); treeOp->Init(eTreeOpDoneCreatingElement, aElement); diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp index dbc9ce245d97..13606390bdbb 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -75,7 +75,6 @@ NS_IMPL_RELEASE_INHERITED(nsHtml5TreeOpExecutor, nsContentSink) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHtml5TreeOpExecutor, nsContentSink) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFlushTimer) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptElement) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mOwnedElements) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mOwnedNonElements) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END @@ -85,7 +84,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHtml5TreeOpExecutor, nsContent tmp->mFlushTimer->Cancel(); } NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFlushTimer) - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mScriptElement) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mOwnedElements) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mOwnedNonElements) NS_IMPL_CYCLE_COLLECTION_UNLINK_END @@ -123,8 +121,17 @@ nsHtml5TreeOpExecutor::WillParse() NS_IMETHODIMP nsHtml5TreeOpExecutor::DidBuildModel(PRBool aTerminated) { - NS_PRECONDITION(mStarted && mParser, - "Bad life cycle."); + NS_PRECONDITION(mStarted, "Bad life cycle."); + + // Break out of update batch if we are in one + EndDocUpdate(); + + // If the above caused a call to nsIParser::Terminate(), let that call + // win. + if (!mParser) { + return NS_OK; + } + // This is comes from nsXMLContentSink DidBuildModelImpl(aTerminated); mDocument->ScriptLoader()->RemoveObserver(this); @@ -279,11 +286,11 @@ nsHtml5TreeOpExecutor::Flush() mFlushTimer->Cancel(); return; } - if (mFlushing) { + if (mFlushState != eNotFlushing) { return; } - mFlushing = PR_TRUE; + mFlushState = eInFlush; nsRefPtr kungFuDeathGrip(this); // avoid crashing near EOF nsCOMPtr parserKungFuDeathGrip(mParser); @@ -292,6 +299,8 @@ nsHtml5TreeOpExecutor::Flush() mStage.RetrieveOperations(mOpQueue); } + nsIContent* scriptElement = nsnull; + BeginDocUpdate(); PRIntervalTime flushStart = 0; @@ -308,13 +317,8 @@ nsHtml5TreeOpExecutor::Flush() // The previous tree op caused a call to nsIParser::Terminate(); break; } - iter->Perform(this); - } - - if (NS_LIKELY(mParser)) { - FlushPendingAppendNotifications(); - } else { - mPendingNotifications.Clear(); + NS_ASSERTION(mFlushState == eInDocUpdate, "Tried to perform tree op outside update batch."); + iter->Perform(this, &scriptElement); } #ifdef DEBUG_hsivonen @@ -338,36 +342,16 @@ nsHtml5TreeOpExecutor::Flush() EndDocUpdate(); - mFlushing = PR_FALSE; + mFlushState = eNotFlushing; if (!mParser) { return; } ScheduleTimer(); - - if (!mCharsetSwitch.IsEmpty()) { - NS_ASSERTION(!mScriptElement, "Had a charset switch and a script"); - NS_ASSERTION(!mCallDidBuildModel, "Had a charset switch and DidBuildModel call"); - PerformCharsetSwitch(); - mCharsetSwitch.Truncate(); - if (mParser) { - // The charset switch was unsuccessful. - return (static_cast (mParser.get()))->ContinueAfterFailedCharsetSwitch(); - } - } else if (mCallDidBuildModel) { - mCallDidBuildModel = PR_FALSE; - // If we have a script element here, it must be malformed - #ifdef DEBUG - nsCOMPtr sele = do_QueryInterface(mScriptElement); - if (sele) { - NS_ASSERTION(sele->IsMalformed(), "Script wasn't marked as malformed."); - } - #endif - mScriptElement = nsnull; - DidBuildModel(PR_FALSE); - } else if (mScriptElement) { - RunScript(); + + if (scriptElement) { + RunScript(scriptElement); // must be tail call when mFlushState is eNotFlushing } } @@ -458,32 +442,46 @@ nsHtml5TreeOpExecutor::DocumentMode(nsHtml5DocumentMode m) * main-thread case is to allow the control to return from the tokenizer * before scripts run. This way, the tokenizer is not invoked re-entrantly * although the parser is. + * + * The reason why this is called as a tail call when mFlushState is set to + * eNotFlushing is to allow re-entry to Flush() but only after the current + * Flush() has cleared the op queue and is otherwise done cleaning up after + * itself. */ void -nsHtml5TreeOpExecutor::RunScript() +nsHtml5TreeOpExecutor::RunScript(nsIContent* aScriptElement) { mReadingFromStage = PR_FALSE; - NS_ASSERTION(mScriptElement, "No script to run"); + NS_ASSERTION(aScriptElement, "No script to run"); + NS_ASSERTION(mFlushState == eNotFlushing, "Tried to run script when flushing."); + + nsCOMPtr sele = do_QueryInterface(aScriptElement); - nsCOMPtr sele = do_QueryInterface(mScriptElement); if (!mParser) { NS_ASSERTION(sele->IsMalformed(), "Script wasn't marked as malformed."); // We got here not because of an end tag but because the tree builder // popped an incomplete script element on EOF. Returning here to avoid - // calling back into mParser anymore. mParser has been nulled out by now. + // calling back into mParser anymore. return; } + + if (mFragmentMode) { + // ending the doc update called nsIParser::Terminate or we are in the + // fragment mode + sele->PreventExecution(); + return; + } + sele->SetCreatorParser(mParser); // Notify our document that we're loading this script. nsCOMPtr htmlDocument = do_QueryInterface(mDocument); NS_ASSERTION(htmlDocument, "Document didn't QI into HTML document."); htmlDocument->ScriptLoading(sele); - // Copied from nsXMLContentSink + // Copied from nsXMLContentSink // Now tell the script that it's ready to go. This may execute the script // or return NS_ERROR_HTMLPARSER_BLOCK. Or neither if the script doesn't // need executing. - nsresult rv = mScriptElement->DoneAddingChildren(PR_TRUE); - mScriptElement = nsnull; + nsresult rv = aScriptElement->DoneAddingChildren(PR_TRUE); // If the act of insertion evaluated the script, we're fine. // Else, block the parser till the script has loaded. if (rv == NS_ERROR_HTMLPARSER_BLOCK) { @@ -516,19 +514,19 @@ nsHtml5TreeOpExecutor::Start() { NS_PRECONDITION(!mStarted, "Tried to start when already started."); mStarted = PR_TRUE; - mScriptElement = nsnull; ScheduleTimer(); } void nsHtml5TreeOpExecutor::NeedsCharsetSwitchTo(const char* aEncoding) { - mCharsetSwitch.Assign(aEncoding); -} + EndDocUpdate(); -void -nsHtml5TreeOpExecutor::PerformCharsetSwitch() -{ + if(NS_UNLIKELY(!mParser)) { + // got terminate + return; + } + nsresult rv = NS_OK; nsCOMPtr wss = do_QueryInterface(mDocShell); if (!wss) { @@ -540,12 +538,21 @@ nsHtml5TreeOpExecutor::PerformCharsetSwitch() // do nothing and fall thru } else if (NS_FAILED(rv = wss->StopDocumentLoad())) { rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something. - } else if (NS_FAILED(rv = wss->ReloadDocument(mCharsetSwitch.get(), kCharsetFromMetaTag))) { + } else if (NS_FAILED(rv = wss->ReloadDocument(aEncoding, kCharsetFromMetaTag))) { rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something. } // if the charset switch was accepted, wss has called Terminate() on the // parser by now #endif + + if (!mParser) { + // success + return; + } + + (static_cast (mParser.get()))->ContinueAfterFailedCharsetSwitch(); + + BeginDocUpdate(); } nsHtml5Tokenizer* @@ -560,11 +567,8 @@ nsHtml5TreeOpExecutor::Reset() { mReadingFromStage = PR_FALSE; mOpQueue.Clear(); mStarted = PR_FALSE; - mScriptElement = nsnull; - mCallDidBuildModel = PR_FALSE; - mCharsetSwitch.Truncate(); - mInDocumentUpdate = PR_FALSE; - mFlushing = PR_FALSE; + mFlushState = eNotFlushing; + mFragmentMode = PR_FALSE; } void @@ -576,7 +580,7 @@ nsHtml5TreeOpExecutor::MaybeFlush(nsTArray& aOpQueue) void nsHtml5TreeOpExecutor::ForcedFlush(nsTArray& aOpQueue) { - NS_PRECONDITION(!mFlushing, "mOpQueue modified during tree op execution."); + NS_PRECONDITION(mFlushState == eNotFlushing, "mOpQueue modified during tree op execution."); if (mOpQueue.IsEmpty()) { mOpQueue.SwapElements(aOpQueue); return; @@ -590,12 +594,6 @@ nsHtml5TreeOpExecutor::InitializeDocWriteParserState(nsAHtml5TreeBuilderState* a static_cast (mParser.get())->InitializeDocWriteParserState(aState, aLine); } -void -nsHtml5TreeOpExecutor::StreamEnded() -{ - mCallDidBuildModel = PR_TRUE; -} - PRUint32 nsHtml5TreeOpExecutor::sTreeOpQueueMaxLength = NS_HTML5_TREE_OP_EXECUTOR_DEFAULT_QUEUE_LENGTH; #ifdef DEBUG_hsivonen PRUint32 nsHtml5TreeOpExecutor::sInsertionBatchMaxLength = 0; diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h index 26749e9797c4..452f6d7aeb78 100644 --- a/parser/html/nsHtml5TreeOpExecutor.h +++ b/parser/html/nsHtml5TreeOpExecutor.h @@ -63,6 +63,13 @@ class nsHtml5StreamParser; typedef nsIContent* nsIContentPtr; +enum eHtml5FlushState { + eNotFlushing = 0, // not flushing + eInFlush = 1, // the Flush() method is on the call stack + eInDocUpdate = 2, // inside an update batch on the document + eNotifying = 3 // flushing pending append notifications +}; + class nsHtml5TreeOpExecutor : public nsContentSink, public nsIContentSink, public nsAHtml5TreeOpSink @@ -105,23 +112,11 @@ class nsHtml5TreeOpExecutor : public nsContentSink, */ PRBool mStarted; - /** - * Script to run ASAP - */ - nsCOMPtr mScriptElement; - nsHtml5TreeOpStage mStage; - PRBool mFlushing; - - PRBool mInDocumentUpdate; + eHtml5FlushState mFlushState; - /** - * Used for deferring DidBuildModel call out of notification batch - */ - PRBool mCallDidBuildModel; - - nsCString mCharsetSwitch; + PRBool mFragmentMode; public: @@ -220,25 +215,33 @@ class nsHtml5TreeOpExecutor : public nsContentSink, mStreamParser = aStreamParser; } - inline void SetScriptElement(nsIContent* aScript) { - mScriptElement = aScript; - } - void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, PRInt32 aLine); PRBool IsScriptEnabled(); + void EnableFragmentMode() { + mFragmentMode = PR_TRUE; + } + + PRBool IsFragmentMode() { + return mFragmentMode; + } + inline void BeginDocUpdate() { - NS_PRECONDITION(!mInDocumentUpdate, "Tried to double-open update."); + NS_PRECONDITION(mFlushState == eInFlush, "Tried to double-open update."); NS_PRECONDITION(mParser, "Started update without parser."); - mInDocumentUpdate = PR_TRUE; + mFlushState = eInDocUpdate; mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); } inline void EndDocUpdate() { - if (mInDocumentUpdate) { - mInDocumentUpdate = PR_FALSE; + if (mFlushState >= eInDocUpdate) { + FlushPendingAppendNotifications(); + if (NS_UNLIKELY(!mParser)) { + return; + } mDocument->EndUpdate(UPDATE_CONTENT_MODEL); + mFlushState = eInFlush; } } @@ -268,9 +271,23 @@ class nsHtml5TreeOpExecutor : public nsContentSink, } void FlushPendingAppendNotifications() { + if (NS_UNLIKELY(mFlushState == eNotifying)) { + // nsIParser::Terminate() was called in response to iter->Fire below + // earlier in the call stack. + return; + } + NS_PRECONDITION(mFlushState == eInDocUpdate, "Notifications flushed outside update"); + mFlushState = eNotifying; const nsHtml5PendingNotification* start = mPendingNotifications.Elements(); const nsHtml5PendingNotification* end = start + mPendingNotifications.Length(); for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) { + if (NS_UNLIKELY(!mParser)) { + // nsIParser::Terminate() was called in response to a notification + // this most likely means that the page is being navigated away from + // so just dropping the rest of the notifications on the floor + // instead of doing something fancy. + break; + } iter->Fire(); } mPendingNotifications.Clear(); @@ -280,6 +297,7 @@ class nsHtml5TreeOpExecutor : public nsContentSink, } #endif mElementsSeenInThisAppendBatch.Clear(); + mFlushState = eInDocUpdate; } inline PRBool HaveNotified(nsIContent* aElement) { @@ -321,14 +339,6 @@ class nsHtml5TreeOpExecutor : public nsContentSink, void NeedsCharsetSwitchTo(const char* aEncoding); - void PerformCharsetSwitch(); - -#ifdef DEBUG - PRBool HasScriptElement() { - return !!mScriptElement; - } -#endif - PRBool IsComplete() { return !mParser; } @@ -338,19 +348,10 @@ class nsHtml5TreeOpExecutor : public nsContentSink, } PRBool IsFlushing() { - return mFlushing; + return mFlushState >= eInFlush; } - void RunScript(); - - void MaybePreventExecution() { - if (mScriptElement) { - nsCOMPtr script = do_QueryInterface(mScriptElement); - NS_ASSERTION(script, "mScriptElement didn't QI to nsIScriptElement!"); - script->PreventExecution(); - mScriptElement = nsnull; - } - } + void RunScript(nsIContent* aScriptElement); void Reset(); diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp index 4985069445d6..6c9fcc1cec70 100644 --- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -94,7 +94,8 @@ nsHtml5TreeOperation::~nsHtml5TreeOperation() } nsresult -nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder) +nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, + nsIContent** aScriptElement) { nsresult rv = NS_OK; switch(mOpCode) { @@ -325,7 +326,7 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder) if (snapshot) { aBuilder->InitializeDocWriteParserState(snapshot, mInt); } - aBuilder->SetScriptElement(node); + *aScriptElement = node; return rv; } case eTreeOpDoneAddingChildren: { @@ -338,6 +339,10 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder) node->DoneCreatingElement(); return rv; } + case eTreeOpFlushPendingAppendNotifications: { + aBuilder->FlushPendingAppendNotifications(); + return rv; + } case eTreeOpSetDocumentCharset: { char* str = mOne.charPtr; nsDependentCString dependentString(str); @@ -380,11 +385,11 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder) return rv; } case eTreeOpStreamEnded: { - aBuilder->StreamEnded(); + aBuilder->DidBuildModel(PR_FALSE); // this causes a notifications flush anyway return rv; } case eTreeOpStartLayout: { - aBuilder->StartLayout(); // this causes a flush anyway + aBuilder->StartLayout(); // this causes a notification flush anyway return rv; } case eTreeOpDocumentMode: { diff --git a/parser/html/nsHtml5TreeOperation.h b/parser/html/nsHtml5TreeOperation.h index 75be187debe2..2ee7b5da7edd 100644 --- a/parser/html/nsHtml5TreeOperation.h +++ b/parser/html/nsHtml5TreeOperation.h @@ -66,6 +66,7 @@ enum eHtml5TreeOperation { eTreeOpRunScript, eTreeOpDoneAddingChildren, eTreeOpDoneCreatingElement, + eTreeOpFlushPendingAppendNotifications, eTreeOpSetDocumentCharset, eTreeOpNeedsCharsetSwitchTo, eTreeOpUpdateStyleSheet, @@ -257,7 +258,7 @@ class nsHtml5TreeOperation { mInt = aLine; } - nsresult Perform(nsHtml5TreeOpExecutor* aBuilder); + nsresult Perform(nsHtml5TreeOpExecutor* aBuilder, nsIContent** aScriptElement); inline already_AddRefed Reget(nsIAtom* aAtom) { if (!aAtom || aAtom->IsStaticAtom()) { From 5127042e1d9ad91fc03428b00aded95c8869551e Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Wed, 11 Nov 2009 10:37:35 +0200 Subject: [PATCH 136/179] Bug 509666 - Notify the right document in the HTML5 parser when nodes have been moved between documents during the parse. r=bnewman. --HG-- extra : rebase_source : ecf04f12b213b6be84887b83c98e15817074d374 --- parser/html/nsHtml5TreeOperation.cpp | 84 +++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp index 6c9fcc1cec70..921e36e207aa 100644 --- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -58,6 +58,34 @@ #include "nsIStyleSheetLinkingElement.h" #include "nsIDOMDocumentType.h" +/** + * Helper class that opens a notification batch if the current doc + * is different from the executor doc. + */ +class NS_STACK_CLASS nsHtml5OtherDocUpdate { + public: + nsHtml5OtherDocUpdate(nsIDocument* aCurrentDoc, nsIDocument* aExecutorDoc) + { + NS_PRECONDITION(aCurrentDoc, "Node has no doc?"); + NS_PRECONDITION(aExecutorDoc, "Executor has no doc?"); + if (NS_LIKELY(aCurrentDoc == aExecutorDoc)) { + mDocument = nsnull; + } else { + mDocument = aCurrentDoc; + aCurrentDoc->BeginUpdate(UPDATE_CONTENT_MODEL); + } + } + + ~nsHtml5OtherDocUpdate() + { + if (NS_UNLIKELY(mDocument)) { + mDocument->EndUpdate(UPDATE_CONTENT_MODEL); + } + } + private: + nsIDocument* mDocument; +}; + nsHtml5TreeOperation::nsHtml5TreeOperation() #ifdef DEBUG : mOpCode(eTreeOpUninitialized) @@ -102,8 +130,27 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, case eTreeOpAppend: { nsIContent* node = *(mOne.node); nsIContent* parent = *(mTwo.node); - aBuilder->PostPendingAppendNotification(parent, node); + + nsIDocument* executorDoc = aBuilder->GetDocument(); + NS_ASSERTION(executorDoc, "Null doc on executor"); + nsIDocument* parentDoc = parent->GetOwnerDoc(); + NS_ASSERTION(parentDoc, "Null owner doc on old node."); + + if (NS_LIKELY(executorDoc == parentDoc)) { + // the usual case. the parent is in the parser's doc + aBuilder->PostPendingAppendNotification(parent, node); + rv = parent->AppendChildTo(node, PR_FALSE); + return rv; + } + + // The parent has been moved to another doc + parentDoc->BeginUpdate(UPDATE_CONTENT_MODEL); + + PRUint32 childCount = parent->GetChildCount(); rv = parent->AppendChildTo(node, PR_FALSE); + nsNodeUtils::ContentAppended(parent, childCount); + + parentDoc->EndUpdate(UPDATE_CONTENT_MODEL); return rv; } case eTreeOpDetach: { @@ -111,6 +158,8 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, aBuilder->FlushPendingAppendNotifications(); nsIContent* parent = node->GetParent(); if (parent) { + nsHtml5OtherDocUpdate update(parent->GetOwnerDoc(), + aBuilder->GetDocument()); PRUint32 pos = parent->IndexOf(node); NS_ASSERTION((pos >= 0), "Element not found as child of its parent"); rv = parent->RemoveChildAt(pos, PR_TRUE, PR_FALSE); @@ -122,6 +171,10 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, nsIContent* node = *(mOne.node); nsIContent* parent = *(mTwo.node); aBuilder->FlushPendingAppendNotifications(); + + nsHtml5OtherDocUpdate update(parent->GetOwnerDoc(), + aBuilder->GetDocument()); + PRUint32 childCount = parent->GetChildCount(); PRBool didAppend = PR_FALSE; while (node->GetChildCount()) { @@ -142,16 +195,40 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, nsIContent* parent = *(mTwo.node); nsIContent* table = *(mThree.node); nsIContent* foster = table->GetParent(); + if (foster && foster->IsNodeOfType(nsINode::eELEMENT)) { aBuilder->FlushPendingAppendNotifications(); + + nsHtml5OtherDocUpdate update(foster->GetOwnerDoc(), + aBuilder->GetDocument()); + PRUint32 pos = foster->IndexOf(table); rv = foster->InsertChildAt(node, pos, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); nsNodeUtils::ContentInserted(foster, node, pos); - } else { + return rv; + } + + nsIDocument* executorDoc = aBuilder->GetDocument(); + NS_ASSERTION(executorDoc, "Null doc on executor"); + nsIDocument* parentDoc = parent->GetOwnerDoc(); + NS_ASSERTION(parentDoc, "Null owner doc on old node."); + + if (NS_LIKELY(executorDoc == parentDoc)) { + // the usual case. the parent is in the parser's doc aBuilder->PostPendingAppendNotification(parent, node); rv = parent->AppendChildTo(node, PR_FALSE); + return rv; } + + // The parent has been moved to another doc + parentDoc->BeginUpdate(UPDATE_CONTENT_MODEL); + + PRUint32 childCount = parent->GetChildCount(); + rv = parent->AppendChildTo(node, PR_FALSE); + nsNodeUtils::ContentAppended(parent, childCount); + + parentDoc->EndUpdate(UPDATE_CONTENT_MODEL); return rv; } case eTreeOpAppendToDocument: { @@ -168,6 +245,9 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, nsIContent* node = *(mOne.node); nsHtml5HtmlAttributes* attributes = mTwo.attributes; + nsHtml5OtherDocUpdate update(node->GetOwnerDoc(), + aBuilder->GetDocument()); + nsIDocument* document = node->GetCurrentDoc(); PRInt32 len = attributes->getLength(); From f002552428396ed0822c7f535be4c6c660fe86ff Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Tue, 17 Nov 2009 10:52:30 +0200 Subject: [PATCH 137/179] Bug 528442 - Call WillCallDoneAddingChildren for SVG scripts in the HTML5 parser. r=bnewman. --HG-- extra : rebase_source : 7fef8d4a9ac5fcc442229ea7c3349944c5d4ecef --- parser/html/nsHtml5TreeOperation.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp index 921e36e207aa..378470c91102 100644 --- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -316,6 +316,9 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, ssle->InitStyleLinkElement(PR_FALSE); ssle->SetEnableUpdates(PR_FALSE); } + } else if (NS_UNLIKELY(name == nsHtml5Atoms::script && ns == kNameSpaceID_SVG)) { + nsCOMPtr sele = do_QueryInterface(newContent); + sele->WillCallDoneAddingChildren(); } if (!attributes) { From 279a50ebf4edbe69882c04111ad94bbc8dc14e27 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Tue, 24 Nov 2009 09:34:49 +0200 Subject: [PATCH 138/179] Bug 530535 - Add AddIntPrefVarCache (like AddBoolPrefVarCache). r&sr=sicking. --HG-- extra : rebase_source : 5ce2fcc6348707cc868ca0c2f7c7fb713dcb7b34 --- content/base/public/nsContentUtils.h | 1 + content/base/src/nsContentUtils.cpp | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 2ff7e3bf43f5..740facda054f 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -573,6 +573,7 @@ public: PrefChangedFunc aCallback, void * aClosure); static void AddBoolPrefVarCache(const char* aPref, PRBool* aVariable); + static void AddIntPrefVarCache(const char* aPref, PRInt32* aVariable); static nsIPrefBranch *GetPrefBranch() { return sPrefBranch; diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index c7193f112493..69832c6d345f 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -2678,6 +2678,23 @@ nsContentUtils::AddBoolPrefVarCache(const char *aPref, RegisterPrefCallback(aPref, BoolVarChanged, aCache); } +static int +IntVarChanged(const char *aPref, void *aClosure) +{ + PRInt32* cache = static_cast(aClosure); + *cache = nsContentUtils::GetIntPref(aPref, 0); + + return 0; +} + +void +nsContentUtils::AddIntPrefVarCache(const char *aPref, + PRInt32* aCache) +{ + *aCache = GetIntPref(aPref, PR_FALSE); + RegisterPrefCallback(aPref, IntVarChanged, aCache); +} + static const char *gEventNames[] = {"event"}; static const char *gSVGEventNames[] = {"evt"}; // for b/w compat, the first name to onerror is still 'event', even though it From 8447be28509d81baf5e51d19822218fba72e240b Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Mon, 30 Nov 2009 17:34:51 +0200 Subject: [PATCH 139/179] Bug 502804, bug 510063 - Update the HTML5 tree builder to spec as of 2009-11-24. rs=sicking. --HG-- extra : rebase_source : 3707836f9ad9d61921bf7455d74ee0844f6a4d02 --- parser/html/nsHtml5AtomList.h | 9 +- parser/html/nsHtml5ElementName.cpp | 139 +++++++++++---------- parser/html/nsHtml5ElementName.h | 6 +- parser/html/nsHtml5TreeBuilder.cpp | 186 ++++++++++++++++++++--------- parser/html/nsHtml5TreeBuilder.h | 9 +- 5 files changed, 209 insertions(+), 140 deletions(-) diff --git a/parser/html/nsHtml5AtomList.h b/parser/html/nsHtml5AtomList.h index b6b5a7042dbe..1a4080672772 100644 --- a/parser/html/nsHtml5AtomList.h +++ b/parser/html/nsHtml5AtomList.h @@ -20,9 +20,11 @@ HTML5_ATOM(button, "button") HTML5_ATOM(input, "input") HTML5_ATOM(option, "option") HTML5_ATOM(ruby, "ruby") +HTML5_ATOM(select, "select") HTML5_ATOM(optgroup, "optgroup") HTML5_ATOM(frameset, "frameset") -HTML5_ATOM(select, "select") +HTML5_ATOM(ul, "ul") +HTML5_ATOM(ol, "ol") HTML5_ATOM(html, "html") HTML5_ATOM(td, "td") HTML5_ATOM(th, "th") @@ -711,12 +713,10 @@ HTML5_ATOM(mi, "mi") HTML5_ATOM(mn, "mn") HTML5_ATOM(mo, "mo") HTML5_ATOM(ms, "ms") -HTML5_ATOM(ol, "ol") HTML5_ATOM(or_, "or") HTML5_ATOM(pi, "pi") HTML5_ATOM(rp, "rp") HTML5_ATOM(tt, "tt") -HTML5_ATOM(ul, "ul") HTML5_ATOM(and_, "and") HTML5_ATOM(arg, "arg") HTML5_ATOM(abs, "abs") @@ -841,7 +841,6 @@ HTML5_ATOM(center, "center") HTML5_ATOM(canvas, "canvas") HTML5_ATOM(divide, "divide") HTML5_ATOM(degree, "degree") -HTML5_ATOM(dialog, "dialog") HTML5_ATOM(domain, "domain") HTML5_ATOM(exists, "exists") HTML5_ATOM(fetile, "fetile") @@ -849,6 +848,7 @@ HTML5_ATOM(feTile, "feTile") HTML5_ATOM(figure, "figure") HTML5_ATOM(forall, "forall") HTML5_ATOM(footer, "footer") +HTML5_ATOM(hgroup, "hgroup") HTML5_ATOM(header, "header") HTML5_ATOM(keygen, "keygen") HTML5_ATOM(lambda, "lambda") @@ -983,7 +983,6 @@ HTML5_ATOM(solidcolor, "solidcolor") HTML5_ATOM(altglyphdef, "altglyphdef") HTML5_ATOM(altGlyphDef, "altGlyphDef") HTML5_ATOM(determinant, "determinant") -HTML5_ATOM(eventsource, "eventsource") HTML5_ATOM(femergenode, "femergenode") HTML5_ATOM(feMergeNode, "feMergeNode") HTML5_ATOM(fecomposite, "fecomposite") diff --git a/parser/html/nsHtml5ElementName.cpp b/parser/html/nsHtml5ElementName.cpp index 04a20a34ade7..eed9a77e833b 100644 --- a/parser/html/nsHtml5ElementName.cpp +++ b/parser/html/nsHtml5ElementName.cpp @@ -131,7 +131,7 @@ nsHtml5ElementName::cloneElementName(nsHtml5AtomTable* interner) return this; } -static PRInt32 const ELEMENT_HASHES_DATA[] = { 1057, 1090, 1255, 1321, 1552, 1585, 1651, 1717, 68162, 68899, 69059, 69764, 70020, 70276, 71077, 71205, 72134, 72232, 72264, 72296, 72328, 72360, 72392, 73351, 74312, 75209, 78124, 78284, 78476, 79149, 79309, 79341, 79469, 81295, 81487, 82224, 84498, 84626, 86164, 86292, 86612, 86676, 87445, 3183041, 3186241, 3198017, 3218722, 3226754, 3247715, 3256803, 3263971, 3264995, 3289252, 3291332, 3295524, 3299620, 3326725, 3379303, 3392679, 3448233, 3460553, 3461577, 3510347, 3546604, 3552364, 3556524, 3576461, 3586349, 3588141, 3590797, 3596333, 3622062, 3625454, 3627054, 3675728, 3749042, 3771059, 3771571, 3776211, 3782323, 3782963, 3784883, 3785395, 3788979, 3815476, 3839605, 3885110, 3917911, 3948984, 3951096, 135304769, 135858241, 136498210, 136906434, 137138658, 137512995, 137531875, 137548067, 137629283, 137645539, 137646563, 137775779, 138529956, 138615076, 139040932, 140954086, 141179366, 141690439, 142738600, 143013512, 146979116, 147175724, 147475756, 147902637, 147936877, 148017645, 148131885, 148228141, 148229165, 148309165, 148395629, 148551853, 148618829, 149076462, 149490158, 149572782, 151277616, 151639440, 153268914, 153486514, 153563314, 153750706, 153763314, 153914034, 154406067, 154417459, 154600979, 154678323, 154680979, 154866835, 155366708, 155375188, 155391572, 155465780, 155869364, 158045494, 168988979, 169321621, 169652752, 173151309, 174240818, 174247297, 174669292, 175391532, 176638123, 177380397, 177879204, 177886734, 180753473, 181020073, 181503558, 181686320, 181999237, 181999311, 182048201, 182074866, 182078003, 182083764, 182920847, 184716457, 184976961, 185145071, 187281445, 187872052, 188100653, 188875944, 188919873, 188920457, 189203987, 189371817, 189414886, 189567458, 190266670, 191318187, 191337609, 202479203, 202493027, 202835587, 202843747, 203013219, 203036048, 203045987, 203177552, 203898516, 204648562, 205067918, 205078130, 205096654, 205689142, 205690439, 205766017, 205988909, 207213161, 207794484, 207800999, 208023602, 208213644, 208213647, 210310273, 210940978, 213325049, 213946445, 214055079, 215125040, 215134273, 215135028, 215237420, 215418148, 215553166, 215553394, 215563858, 215627949, 215754324, 217529652, 217713834, 217732628, 218731945, 221417045, 221424946, 221493746, 221515401, 221658189, 221844577, 221908140, 221910626, 221921586, 222659762, 225001091, 236105833, 236113965, 236194995, 236195427, 236206132, 236206387, 236211683, 236212707, 236381647, 236571826, 237124271, 238172205, 238210544, 238270764, 238435405, 238501172, 239224867, 239257644, 239710497, 240307721, 241208789, 241241557, 241318060, 241319404, 241343533, 241344069, 241405397, 241765845, 243864964, 244502085, 244946220, 245109902, 247647266, 247707956, 248648814, 248648836, 248682161, 248986932, 249058914, 249697357, 252132601, 252135604, 252317348, 255007012, 255278388, 256365156, 257566121, 269763372, 271202790, 271863856, 272049197, 272127474, 272770631, 274339449, 274939471, 275388004, 275388005, 275388006, 275977800, 278267602, 278513831, 278712622, 281613765, 281683369, 282120228, 282250732, 282508942, 283743649, 283787570, 284710386, 285391148, 285478533, 285854898, 285873762, 286931113, 288964227, 289445441, 289689648, 291671489, 303512884, 305319975, 305610036, 305764101, 308448294, 308675890, 312085683, 312264750, 315032867, 316391000, 317331042, 317902135, 318950711, 319447220, 321499182, 322538804, 323145200, 337067316, 337826293, 339905989, 340833697, 341457068, 345302593, 349554733, 349771471, 349786245, 350819405, 356072847, 370349192, 373962798, 374509141, 375558638, 375574835, 376053993, 383276530, 383373833, 383407586, 384439906, 386079012, 404133513, 404307343, 407031852, 408072233, 409112005, 409608425, 409771500, 419040932, 437730612, 439529766, 442616365, 442813037, 443157674, 443295316, 450118444, 450482697, 456789668, 459935396, 471217869, 474073645, 476230702, 476665218, 476717289, 483014825, 485083298, 489306281, 538364390, 540675748, 543819186, 543958612, 576960820, 577242548, 610515252, 642202932, 644420819 }; +static PRInt32 const ELEMENT_HASHES_DATA[] = { 1057, 1090, 1255, 1321, 1552, 1585, 1651, 1717, 68162, 68899, 69059, 69764, 70020, 70276, 71077, 71205, 72134, 72232, 72264, 72296, 72328, 72360, 72392, 73351, 74312, 75209, 78124, 78284, 78476, 79149, 79309, 79341, 79469, 81295, 81487, 82224, 84498, 84626, 86164, 86292, 86612, 86676, 87445, 3183041, 3186241, 3198017, 3218722, 3226754, 3247715, 3256803, 3263971, 3264995, 3289252, 3291332, 3295524, 3299620, 3326725, 3379303, 3392679, 3448233, 3460553, 3461577, 3510347, 3546604, 3552364, 3556524, 3576461, 3586349, 3588141, 3590797, 3596333, 3622062, 3625454, 3627054, 3675728, 3749042, 3771059, 3771571, 3776211, 3782323, 3782963, 3784883, 3785395, 3788979, 3815476, 3839605, 3885110, 3917911, 3948984, 3951096, 135304769, 135858241, 136498210, 136906434, 137138658, 137512995, 137531875, 137548067, 137629283, 137645539, 137646563, 137775779, 138529956, 138615076, 139040932, 140954086, 141179366, 141690439, 142738600, 143013512, 146979116, 147175724, 147475756, 147902637, 147936877, 148017645, 148131885, 148228141, 148229165, 148309165, 148395629, 148551853, 148618829, 149076462, 149490158, 149572782, 151277616, 151639440, 153268914, 153486514, 153563314, 153750706, 153763314, 153914034, 154406067, 154417459, 154600979, 154678323, 154680979, 154866835, 155366708, 155375188, 155391572, 155465780, 155869364, 158045494, 168988979, 169321621, 169652752, 173151309, 174240818, 174247297, 174669292, 175391532, 176638123, 177380397, 177879204, 177886734, 180753473, 181020073, 181503558, 181686320, 181999237, 181999311, 182048201, 182074866, 182078003, 182083764, 182920847, 184716457, 184976961, 185145071, 187281445, 187872052, 188100653, 188875944, 188919873, 188920457, 189203987, 189371817, 189414886, 189567458, 190266670, 191318187, 191337609, 202479203, 202493027, 202835587, 202843747, 203013219, 203036048, 203045987, 203177552, 203898516, 204648562, 205067918, 205078130, 205096654, 205689142, 205690439, 205988909, 207213161, 207794484, 207800999, 208023602, 208213644, 208213647, 210261490, 210310273, 210940978, 213325049, 213946445, 214055079, 215125040, 215134273, 215135028, 215237420, 215418148, 215553166, 215553394, 215563858, 215627949, 215754324, 217529652, 217713834, 217732628, 218731945, 221417045, 221424946, 221493746, 221515401, 221658189, 221844577, 221908140, 221910626, 221921586, 222659762, 225001091, 236105833, 236113965, 236194995, 236195427, 236206132, 236206387, 236211683, 236212707, 236381647, 236571826, 237124271, 238172205, 238210544, 238270764, 238435405, 238501172, 239224867, 239257644, 239710497, 240307721, 241208789, 241241557, 241318060, 241319404, 241343533, 241344069, 241405397, 241765845, 243864964, 244502085, 244946220, 245109902, 247647266, 247707956, 248648814, 248648836, 248682161, 248986932, 249058914, 249697357, 252132601, 252135604, 252317348, 255007012, 255278388, 256365156, 257566121, 269763372, 271202790, 271863856, 272049197, 272127474, 272770631, 274339449, 274939471, 275388004, 275388005, 275388006, 275977800, 278267602, 278513831, 278712622, 281613765, 281683369, 282120228, 282250732, 282508942, 283743649, 283787570, 284710386, 285391148, 285478533, 285854898, 285873762, 286931113, 288964227, 289445441, 289689648, 291671489, 303512884, 305319975, 305610036, 305764101, 308448294, 308675890, 312085683, 312264750, 315032867, 316391000, 317331042, 317902135, 318950711, 319447220, 321499182, 322538804, 323145200, 337067316, 337826293, 339905989, 340833697, 341457068, 345302593, 349554733, 349771471, 349786245, 350819405, 356072847, 370349192, 373962798, 375558638, 375574835, 376053993, 383276530, 383373833, 383407586, 384439906, 386079012, 404133513, 404307343, 407031852, 408072233, 409112005, 409608425, 409771500, 419040932, 437730612, 439529766, 442616365, 442813037, 443157674, 443295316, 450118444, 450482697, 456789668, 459935396, 471217869, 474073645, 476230702, 476665218, 476717289, 483014825, 485083298, 489306281, 538364390, 540675748, 543819186, 543958612, 576960820, 577242548, 610515252, 642202932, 644420819 }; void nsHtml5ElementName::initializeStatics() { @@ -190,7 +190,7 @@ nsHtml5ElementName::initializeStatics() ELT_COT = new nsHtml5ElementName(nsHtml5Atoms::cot, nsHtml5Atoms::cot, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_DEL = new nsHtml5ElementName(nsHtml5Atoms::del, nsHtml5Atoms::del, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_DFN = new nsHtml5ElementName(nsHtml5Atoms::dfn, nsHtml5Atoms::dfn, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_DIR = new nsHtml5ElementName(nsHtml5Atoms::dir, nsHtml5Atoms::dir, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_DIR = new nsHtml5ElementName(nsHtml5Atoms::dir, nsHtml5Atoms::dir, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_DIV = new nsHtml5ElementName(nsHtml5Atoms::div, nsHtml5Atoms::div, NS_HTML5TREE_BUILDER_DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU, PR_TRUE, PR_FALSE, PR_FALSE); ELT_EXP = new nsHtml5ElementName(nsHtml5Atoms::exp, nsHtml5Atoms::exp, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_GCD = new nsHtml5ElementName(nsHtml5Atoms::gcd, nsHtml5Atoms::gcd, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); @@ -209,7 +209,7 @@ nsHtml5ElementName::initializeStatics() ELT_MAX = new nsHtml5ElementName(nsHtml5Atoms::max, nsHtml5Atoms::max, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_NEQ = new nsHtml5ElementName(nsHtml5Atoms::neq, nsHtml5Atoms::neq, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_NOT = new nsHtml5ElementName(nsHtml5Atoms::not_, nsHtml5Atoms::not_, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_NAV = new nsHtml5ElementName(nsHtml5Atoms::nav, nsHtml5Atoms::nav, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_NAV = new nsHtml5ElementName(nsHtml5Atoms::nav, nsHtml5Atoms::nav, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_PRE = new nsHtml5ElementName(nsHtml5Atoms::pre, nsHtml5Atoms::pre, NS_HTML5TREE_BUILDER_PRE_OR_LISTING, PR_TRUE, PR_FALSE, PR_FALSE); ELT_REM = new nsHtml5ElementName(nsHtml5Atoms::rem, nsHtml5Atoms::rem, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_SUB = new nsHtml5ElementName(nsHtml5Atoms::sub, nsHtml5Atoms::sub, NS_HTML5TREE_BUILDER_RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR, PR_FALSE, PR_FALSE, PR_FALSE); @@ -282,7 +282,7 @@ nsHtml5ElementName::initializeStatics() ELT_TANH = new nsHtml5ElementName(nsHtml5Atoms::tanh, nsHtml5Atoms::tanh, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_TEXT = new nsHtml5ElementName(nsHtml5Atoms::text, nsHtml5Atoms::text, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_VIEW = new nsHtml5ElementName(nsHtml5Atoms::view, nsHtml5Atoms::view, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_ASIDE = new nsHtml5ElementName(nsHtml5Atoms::aside, nsHtml5Atoms::aside, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_ASIDE = new nsHtml5ElementName(nsHtml5Atoms::aside, nsHtml5Atoms::aside, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_AUDIO = new nsHtml5ElementName(nsHtml5Atoms::audio, nsHtml5Atoms::audio, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_APPLY = new nsHtml5ElementName(nsHtml5Atoms::apply, nsHtml5Atoms::apply, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_EMBED = new nsHtml5ElementName(nsHtml5Atoms::embed, nsHtml5Atoms::embed, NS_HTML5TREE_BUILDER_EMBED_OR_IMG, PR_TRUE, PR_FALSE, PR_FALSE); @@ -336,15 +336,15 @@ nsHtml5ElementName::initializeStatics() ELT_CANVAS = new nsHtml5ElementName(nsHtml5Atoms::canvas, nsHtml5Atoms::canvas, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_DIVIDE = new nsHtml5ElementName(nsHtml5Atoms::divide, nsHtml5Atoms::divide, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_DEGREE = new nsHtml5ElementName(nsHtml5Atoms::degree, nsHtml5Atoms::degree, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_DIALOG = new nsHtml5ElementName(nsHtml5Atoms::dialog, nsHtml5Atoms::dialog, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_DOMAIN = new nsHtml5ElementName(nsHtml5Atoms::domain, nsHtml5Atoms::domain, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_EXISTS = new nsHtml5ElementName(nsHtml5Atoms::exists, nsHtml5Atoms::exists, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_FETILE = new nsHtml5ElementName(nsHtml5Atoms::fetile, nsHtml5Atoms::feTile, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_FIGURE = new nsHtml5ElementName(nsHtml5Atoms::figure, nsHtml5Atoms::figure, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_FIGURE = new nsHtml5ElementName(nsHtml5Atoms::figure, nsHtml5Atoms::figure, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_FORALL = new nsHtml5ElementName(nsHtml5Atoms::forall, nsHtml5Atoms::forall, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_FILTER = new nsHtml5ElementName(nsHtml5Atoms::filter, nsHtml5Atoms::filter, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_FOOTER = new nsHtml5ElementName(nsHtml5Atoms::footer, nsHtml5Atoms::footer, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); - ELT_HEADER = new nsHtml5ElementName(nsHtml5Atoms::header, nsHtml5Atoms::header, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_FOOTER = new nsHtml5ElementName(nsHtml5Atoms::footer, nsHtml5Atoms::footer, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_HGROUP = new nsHtml5ElementName(nsHtml5Atoms::hgroup, nsHtml5Atoms::hgroup, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_HEADER = new nsHtml5ElementName(nsHtml5Atoms::header, nsHtml5Atoms::header, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_IFRAME = new nsHtml5ElementName(nsHtml5Atoms::iframe, nsHtml5Atoms::iframe, NS_HTML5TREE_BUILDER_IFRAME, PR_TRUE, PR_FALSE, PR_FALSE); ELT_KEYGEN = new nsHtml5ElementName(nsHtml5Atoms::keygen, nsHtml5Atoms::keygen, NS_HTML5TREE_BUILDER_KEYGEN, PR_TRUE, PR_FALSE, PR_FALSE); ELT_LAMBDA = new nsHtml5ElementName(nsHtml5Atoms::lambda, nsHtml5Atoms::lambda, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); @@ -374,7 +374,7 @@ nsHtml5ElementName::initializeStatics() ELT_SCRIPT = new nsHtml5ElementName(nsHtml5Atoms::script, nsHtml5Atoms::script, NS_HTML5TREE_BUILDER_SCRIPT, PR_TRUE, PR_FALSE, PR_FALSE); ELT_TBREAK = new nsHtml5ElementName(nsHtml5Atoms::tbreak, nsHtml5Atoms::tbreak, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_VECTOR = new nsHtml5ElementName(nsHtml5Atoms::vector, nsHtml5Atoms::vector, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_ARTICLE = new nsHtml5ElementName(nsHtml5Atoms::article, nsHtml5Atoms::article, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_ARTICLE = new nsHtml5ElementName(nsHtml5Atoms::article, nsHtml5Atoms::article, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_ANIMATE = new nsHtml5ElementName(nsHtml5Atoms::animate, nsHtml5Atoms::animate, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_ARCSECH = new nsHtml5ElementName(nsHtml5Atoms::arcsech, nsHtml5Atoms::arcsech, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_ARCCSCH = new nsHtml5ElementName(nsHtml5Atoms::arccsch, nsHtml5Atoms::arccsch, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); @@ -383,16 +383,16 @@ nsHtml5ElementName::initializeStatics() ELT_ARCCOSH = new nsHtml5ElementName(nsHtml5Atoms::arccosh, nsHtml5Atoms::arccosh, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_ARCCOTH = new nsHtml5ElementName(nsHtml5Atoms::arccoth, nsHtml5Atoms::arccoth, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_ACRONYM = new nsHtml5ElementName(nsHtml5Atoms::acronym, nsHtml5Atoms::acronym, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_ADDRESS = new nsHtml5ElementName(nsHtml5Atoms::address, nsHtml5Atoms::address, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_ADDRESS = new nsHtml5ElementName(nsHtml5Atoms::address, nsHtml5Atoms::address, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_BGSOUND = new nsHtml5ElementName(nsHtml5Atoms::bgsound, nsHtml5Atoms::bgsound, NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, PR_TRUE, PR_FALSE, PR_FALSE); - ELT_COMMAND = new nsHtml5ElementName(nsHtml5Atoms::command, nsHtml5Atoms::command, NS_HTML5TREE_BUILDER_COMMAND_OR_EVENT_SOURCE, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_COMMAND = new nsHtml5ElementName(nsHtml5Atoms::command, nsHtml5Atoms::command, NS_HTML5TREE_BUILDER_COMMAND, PR_TRUE, PR_FALSE, PR_FALSE); ELT_COMPOSE = new nsHtml5ElementName(nsHtml5Atoms::compose, nsHtml5Atoms::compose, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_CEILING = new nsHtml5ElementName(nsHtml5Atoms::ceiling, nsHtml5Atoms::ceiling, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_CSYMBOL = new nsHtml5ElementName(nsHtml5Atoms::csymbol, nsHtml5Atoms::csymbol, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_CAPTION = new nsHtml5ElementName(nsHtml5Atoms::caption, nsHtml5Atoms::caption, NS_HTML5TREE_BUILDER_CAPTION, PR_FALSE, PR_TRUE, PR_FALSE); ELT_DISCARD = new nsHtml5ElementName(nsHtml5Atoms::discard, nsHtml5Atoms::discard, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_DECLARE = new nsHtml5ElementName(nsHtml5Atoms::declare, nsHtml5Atoms::declare, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_DETAILS = new nsHtml5ElementName(nsHtml5Atoms::details, nsHtml5Atoms::details, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_DETAILS = new nsHtml5ElementName(nsHtml5Atoms::details, nsHtml5Atoms::details, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_ELLIPSE = new nsHtml5ElementName(nsHtml5Atoms::ellipse, nsHtml5Atoms::ellipse, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_FEFUNCA = new nsHtml5ElementName(nsHtml5Atoms::fefunca, nsHtml5Atoms::feFuncA, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_FEFUNCB = new nsHtml5ElementName(nsHtml5Atoms::fefuncb, nsHtml5Atoms::feFuncB, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); @@ -418,7 +418,7 @@ nsHtml5ElementName::initializeStatics() ELT_PATTERN = new nsHtml5ElementName(nsHtml5Atoms::pattern, nsHtml5Atoms::pattern, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_PRODUCT = new nsHtml5ElementName(nsHtml5Atoms::product, nsHtml5Atoms::product, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_SETDIFF = new nsHtml5ElementName(nsHtml5Atoms::setdiff, nsHtml5Atoms::setdiff, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_SECTION = new nsHtml5ElementName(nsHtml5Atoms::section, nsHtml5Atoms::section, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_SECTION = new nsHtml5ElementName(nsHtml5Atoms::section, nsHtml5Atoms::section, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_TENDSTO = new nsHtml5ElementName(nsHtml5Atoms::tendsto, nsHtml5Atoms::tendsto, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_UPLIMIT = new nsHtml5ElementName(nsHtml5Atoms::uplimit, nsHtml5Atoms::uplimit, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_ALTGLYPH = new nsHtml5ElementName(nsHtml5Atoms::altglyph, nsHtml5Atoms::altGlyph, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); @@ -426,7 +426,7 @@ nsHtml5ElementName::initializeStatics() ELT_CLIPPATH = new nsHtml5ElementName(nsHtml5Atoms::clippath, nsHtml5Atoms::clipPath, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_CODOMAIN = new nsHtml5ElementName(nsHtml5Atoms::codomain, nsHtml5Atoms::codomain, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_COLGROUP = new nsHtml5ElementName(nsHtml5Atoms::colgroup, nsHtml5Atoms::colgroup, NS_HTML5TREE_BUILDER_COLGROUP, PR_TRUE, PR_FALSE, PR_FALSE); - ELT_DATAGRID = new nsHtml5ElementName(nsHtml5Atoms::datagrid, nsHtml5Atoms::datagrid, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); + ELT_DATAGRID = new nsHtml5ElementName(nsHtml5Atoms::datagrid, nsHtml5Atoms::datagrid, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE); ELT_EMPTYSET = new nsHtml5ElementName(nsHtml5Atoms::emptyset, nsHtml5Atoms::emptyset, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_FACTOROF = new nsHtml5ElementName(nsHtml5Atoms::factorof, nsHtml5Atoms::factorof, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_FIELDSET = new nsHtml5ElementName(nsHtml5Atoms::fieldset, nsHtml5Atoms::fieldset, NS_HTML5TREE_BUILDER_FIELDSET, PR_TRUE, PR_FALSE, PR_FALSE); @@ -483,7 +483,6 @@ nsHtml5ElementName::initializeStatics() ELT_SOLIDCOLOR = new nsHtml5ElementName(nsHtml5Atoms::solidcolor, nsHtml5Atoms::solidcolor, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_ALTGLYPHDEF = new nsHtml5ElementName(nsHtml5Atoms::altglyphdef, nsHtml5Atoms::altGlyphDef, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_DETERMINANT = new nsHtml5ElementName(nsHtml5Atoms::determinant, nsHtml5Atoms::determinant, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELT_EVENTSOURCE = new nsHtml5ElementName(nsHtml5Atoms::eventsource, nsHtml5Atoms::eventsource, NS_HTML5TREE_BUILDER_COMMAND_OR_EVENT_SOURCE, PR_TRUE, PR_FALSE, PR_FALSE); ELT_FEMERGENODE = new nsHtml5ElementName(nsHtml5Atoms::femergenode, nsHtml5Atoms::feMergeNode, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_FECOMPOSITE = new nsHtml5ElementName(nsHtml5Atoms::fecomposite, nsHtml5Atoms::feComposite, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_FESPOTLIGHT = new nsHtml5ElementName(nsHtml5Atoms::fespotlight, nsHtml5Atoms::feSpotLight, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); @@ -527,7 +526,7 @@ nsHtml5ElementName::initializeStatics() ELT_FESPECULARLIGHTING = new nsHtml5ElementName(nsHtml5Atoms::fespecularlighting, nsHtml5Atoms::feSpecularLighting, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_DOMAINOFAPPLICATION = new nsHtml5ElementName(nsHtml5Atoms::domainofapplication, nsHtml5Atoms::domainofapplication, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); ELT_FECOMPONENTTRANSFER = new nsHtml5ElementName(nsHtml5Atoms::fecomponenttransfer, nsHtml5Atoms::feComponentTransfer, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE); - ELEMENT_NAMES = new nsHtml5ElementName*[391]; + ELEMENT_NAMES = new nsHtml5ElementName*[390]; ELEMENT_NAMES[0] = ELT_A; ELEMENT_NAMES[1] = ELT_B; ELEMENT_NAMES[2] = ELT_G; @@ -728,14 +727,14 @@ nsHtml5ElementName::initializeStatics() ELEMENT_NAMES[197] = ELT_CANVAS; ELEMENT_NAMES[198] = ELT_DIVIDE; ELEMENT_NAMES[199] = ELT_DEGREE; - ELEMENT_NAMES[200] = ELT_DIALOG; - ELEMENT_NAMES[201] = ELT_DOMAIN; - ELEMENT_NAMES[202] = ELT_EXISTS; - ELEMENT_NAMES[203] = ELT_FETILE; - ELEMENT_NAMES[204] = ELT_FIGURE; - ELEMENT_NAMES[205] = ELT_FORALL; - ELEMENT_NAMES[206] = ELT_FILTER; - ELEMENT_NAMES[207] = ELT_FOOTER; + ELEMENT_NAMES[200] = ELT_DOMAIN; + ELEMENT_NAMES[201] = ELT_EXISTS; + ELEMENT_NAMES[202] = ELT_FETILE; + ELEMENT_NAMES[203] = ELT_FIGURE; + ELEMENT_NAMES[204] = ELT_FORALL; + ELEMENT_NAMES[205] = ELT_FILTER; + ELEMENT_NAMES[206] = ELT_FOOTER; + ELEMENT_NAMES[207] = ELT_HGROUP; ELEMENT_NAMES[208] = ELT_HEADER; ELEMENT_NAMES[209] = ELT_IFRAME; ELEMENT_NAMES[210] = ELT_KEYGEN; @@ -875,51 +874,50 @@ nsHtml5ElementName::initializeStatics() ELEMENT_NAMES[344] = ELT_SOLIDCOLOR; ELEMENT_NAMES[345] = ELT_ALTGLYPHDEF; ELEMENT_NAMES[346] = ELT_DETERMINANT; - ELEMENT_NAMES[347] = ELT_EVENTSOURCE; - ELEMENT_NAMES[348] = ELT_FEMERGENODE; - ELEMENT_NAMES[349] = ELT_FECOMPOSITE; - ELEMENT_NAMES[350] = ELT_FESPOTLIGHT; - ELEMENT_NAMES[351] = ELT_MALIGNGROUP; - ELEMENT_NAMES[352] = ELT_MPRESCRIPTS; - ELEMENT_NAMES[353] = ELT_MOMENTABOUT; - ELEMENT_NAMES[354] = ELT_NOTPRSUBSET; - ELEMENT_NAMES[355] = ELT_PARTIALDIFF; - ELEMENT_NAMES[356] = ELT_ALTGLYPHITEM; - ELEMENT_NAMES[357] = ELT_ANIMATECOLOR; - ELEMENT_NAMES[358] = ELT_DATATEMPLATE; - ELEMENT_NAMES[359] = ELT_EXPONENTIALE; - ELEMENT_NAMES[360] = ELT_FETURBULENCE; - ELEMENT_NAMES[361] = ELT_FEPOINTLIGHT; - ELEMENT_NAMES[362] = ELT_FEMORPHOLOGY; - ELEMENT_NAMES[363] = ELT_OUTERPRODUCT; - ELEMENT_NAMES[364] = ELT_ANIMATEMOTION; - ELEMENT_NAMES[365] = ELT_COLOR_PROFILE; - ELEMENT_NAMES[366] = ELT_FONT_FACE_SRC; - ELEMENT_NAMES[367] = ELT_FONT_FACE_URI; - ELEMENT_NAMES[368] = ELT_FOREIGNOBJECT; - ELEMENT_NAMES[369] = ELT_FECOLORMATRIX; - ELEMENT_NAMES[370] = ELT_MISSING_GLYPH; - ELEMENT_NAMES[371] = ELT_MMULTISCRIPTS; - ELEMENT_NAMES[372] = ELT_SCALARPRODUCT; - ELEMENT_NAMES[373] = ELT_VECTORPRODUCT; - ELEMENT_NAMES[374] = ELT_ANNOTATION_XML; - ELEMENT_NAMES[375] = ELT_DEFINITION_SRC; - ELEMENT_NAMES[376] = ELT_FONT_FACE_NAME; - ELEMENT_NAMES[377] = ELT_FEGAUSSIANBLUR; - ELEMENT_NAMES[378] = ELT_FEDISTANTLIGHT; - ELEMENT_NAMES[379] = ELT_LINEARGRADIENT; - ELEMENT_NAMES[380] = ELT_NATURALNUMBERS; - ELEMENT_NAMES[381] = ELT_RADIALGRADIENT; - ELEMENT_NAMES[382] = ELT_ANIMATETRANSFORM; - ELEMENT_NAMES[383] = ELT_CARTESIANPRODUCT; - ELEMENT_NAMES[384] = ELT_FONT_FACE_FORMAT; - ELEMENT_NAMES[385] = ELT_FECONVOLVEMATRIX; - ELEMENT_NAMES[386] = ELT_FEDIFFUSELIGHTING; - ELEMENT_NAMES[387] = ELT_FEDISPLACEMENTMAP; - ELEMENT_NAMES[388] = ELT_FESPECULARLIGHTING; - ELEMENT_NAMES[389] = ELT_DOMAINOFAPPLICATION; - ELEMENT_NAMES[390] = ELT_FECOMPONENTTRANSFER; - ELEMENT_HASHES = jArray((PRInt32*)ELEMENT_HASHES_DATA, 391); + ELEMENT_NAMES[347] = ELT_FEMERGENODE; + ELEMENT_NAMES[348] = ELT_FECOMPOSITE; + ELEMENT_NAMES[349] = ELT_FESPOTLIGHT; + ELEMENT_NAMES[350] = ELT_MALIGNGROUP; + ELEMENT_NAMES[351] = ELT_MPRESCRIPTS; + ELEMENT_NAMES[352] = ELT_MOMENTABOUT; + ELEMENT_NAMES[353] = ELT_NOTPRSUBSET; + ELEMENT_NAMES[354] = ELT_PARTIALDIFF; + ELEMENT_NAMES[355] = ELT_ALTGLYPHITEM; + ELEMENT_NAMES[356] = ELT_ANIMATECOLOR; + ELEMENT_NAMES[357] = ELT_DATATEMPLATE; + ELEMENT_NAMES[358] = ELT_EXPONENTIALE; + ELEMENT_NAMES[359] = ELT_FETURBULENCE; + ELEMENT_NAMES[360] = ELT_FEPOINTLIGHT; + ELEMENT_NAMES[361] = ELT_FEMORPHOLOGY; + ELEMENT_NAMES[362] = ELT_OUTERPRODUCT; + ELEMENT_NAMES[363] = ELT_ANIMATEMOTION; + ELEMENT_NAMES[364] = ELT_COLOR_PROFILE; + ELEMENT_NAMES[365] = ELT_FONT_FACE_SRC; + ELEMENT_NAMES[366] = ELT_FONT_FACE_URI; + ELEMENT_NAMES[367] = ELT_FOREIGNOBJECT; + ELEMENT_NAMES[368] = ELT_FECOLORMATRIX; + ELEMENT_NAMES[369] = ELT_MISSING_GLYPH; + ELEMENT_NAMES[370] = ELT_MMULTISCRIPTS; + ELEMENT_NAMES[371] = ELT_SCALARPRODUCT; + ELEMENT_NAMES[372] = ELT_VECTORPRODUCT; + ELEMENT_NAMES[373] = ELT_ANNOTATION_XML; + ELEMENT_NAMES[374] = ELT_DEFINITION_SRC; + ELEMENT_NAMES[375] = ELT_FONT_FACE_NAME; + ELEMENT_NAMES[376] = ELT_FEGAUSSIANBLUR; + ELEMENT_NAMES[377] = ELT_FEDISTANTLIGHT; + ELEMENT_NAMES[378] = ELT_LINEARGRADIENT; + ELEMENT_NAMES[379] = ELT_NATURALNUMBERS; + ELEMENT_NAMES[380] = ELT_RADIALGRADIENT; + ELEMENT_NAMES[381] = ELT_ANIMATETRANSFORM; + ELEMENT_NAMES[382] = ELT_CARTESIANPRODUCT; + ELEMENT_NAMES[383] = ELT_FONT_FACE_FORMAT; + ELEMENT_NAMES[384] = ELT_FECONVOLVEMATRIX; + ELEMENT_NAMES[385] = ELT_FEDIFFUSELIGHTING; + ELEMENT_NAMES[386] = ELT_FEDISPLACEMENTMAP; + ELEMENT_NAMES[387] = ELT_FESPECULARLIGHTING; + ELEMENT_NAMES[388] = ELT_DOMAINOFAPPLICATION; + ELEMENT_NAMES[389] = ELT_FECOMPONENTTRANSFER; + ELEMENT_HASHES = jArray((PRInt32*)ELEMENT_HASHES_DATA, 390); } void @@ -1126,7 +1124,6 @@ nsHtml5ElementName::releaseStatics() delete ELT_CANVAS; delete ELT_DIVIDE; delete ELT_DEGREE; - delete ELT_DIALOG; delete ELT_DOMAIN; delete ELT_EXISTS; delete ELT_FETILE; @@ -1134,6 +1131,7 @@ nsHtml5ElementName::releaseStatics() delete ELT_FORALL; delete ELT_FILTER; delete ELT_FOOTER; + delete ELT_HGROUP; delete ELT_HEADER; delete ELT_IFRAME; delete ELT_KEYGEN; @@ -1273,7 +1271,6 @@ nsHtml5ElementName::releaseStatics() delete ELT_SOLIDCOLOR; delete ELT_ALTGLYPHDEF; delete ELT_DETERMINANT; - delete ELT_EVENTSOURCE; delete ELT_FEMERGENODE; delete ELT_FECOMPOSITE; delete ELT_FESPOTLIGHT; diff --git a/parser/html/nsHtml5ElementName.h b/parser/html/nsHtml5ElementName.h index 08865a877175..bff02370f585 100644 --- a/parser/html/nsHtml5ElementName.h +++ b/parser/html/nsHtml5ElementName.h @@ -278,7 +278,6 @@ class nsHtml5ElementName static nsHtml5ElementName* ELT_CANVAS; static nsHtml5ElementName* ELT_DIVIDE; static nsHtml5ElementName* ELT_DEGREE; - static nsHtml5ElementName* ELT_DIALOG; static nsHtml5ElementName* ELT_DOMAIN; static nsHtml5ElementName* ELT_EXISTS; static nsHtml5ElementName* ELT_FETILE; @@ -286,6 +285,7 @@ class nsHtml5ElementName static nsHtml5ElementName* ELT_FORALL; static nsHtml5ElementName* ELT_FILTER; static nsHtml5ElementName* ELT_FOOTER; + static nsHtml5ElementName* ELT_HGROUP; static nsHtml5ElementName* ELT_HEADER; static nsHtml5ElementName* ELT_IFRAME; static nsHtml5ElementName* ELT_KEYGEN; @@ -425,7 +425,6 @@ class nsHtml5ElementName static nsHtml5ElementName* ELT_SOLIDCOLOR; static nsHtml5ElementName* ELT_ALTGLYPHDEF; static nsHtml5ElementName* ELT_DETERMINANT; - static nsHtml5ElementName* ELT_EVENTSOURCE; static nsHtml5ElementName* ELT_FEMERGENODE; static nsHtml5ElementName* ELT_FECOMPOSITE; static nsHtml5ElementName* ELT_FESPOTLIGHT; @@ -679,7 +678,6 @@ nsHtml5ElementName* nsHtml5ElementName::ELT_CURSOR = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_CANVAS = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_DIVIDE = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_DEGREE = nsnull; -nsHtml5ElementName* nsHtml5ElementName::ELT_DIALOG = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_DOMAIN = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_EXISTS = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_FETILE = nsnull; @@ -687,6 +685,7 @@ nsHtml5ElementName* nsHtml5ElementName::ELT_FIGURE = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_FORALL = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_FILTER = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_FOOTER = nsnull; +nsHtml5ElementName* nsHtml5ElementName::ELT_HGROUP = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_HEADER = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_IFRAME = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_KEYGEN = nsnull; @@ -826,7 +825,6 @@ nsHtml5ElementName* nsHtml5ElementName::ELT_NOTANUMBER = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_SOLIDCOLOR = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_ALTGLYPHDEF = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_DETERMINANT = nsnull; -nsHtml5ElementName* nsHtml5ElementName::ELT_EVENTSOURCE = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_FEMERGENODE = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_FECOMPOSITE = nsnull; nsHtml5ElementName* nsHtml5ElementName::ELT_FESPOTLIGHT = nsnull; diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp index d681da78588a..fb941bb674b1 100644 --- a/parser/html/nsHtml5TreeBuilder.cpp +++ b/parser/html/nsHtml5TreeBuilder.cpp @@ -209,7 +209,7 @@ nsHtml5TreeBuilder::characters(PRUnichar* buf, PRInt32 start, PRInt32 length) case NS_HTML5TREE_BUILDER_IN_CAPTION: { reconstructTheActiveFormattingElements(); } - case NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA: { + case NS_HTML5TREE_BUILDER_TEXT: { accumulateCharacters(buf, start, length); return; } @@ -495,7 +495,7 @@ nsHtml5TreeBuilder::eof() case NS_HTML5TREE_BUILDER_IN_BODY: { goto eofloop_end; } - case NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA: { + case NS_HTML5TREE_BUILDER_TEXT: { if (originalMode == NS_HTML5TREE_BUILDER_AFTER_HEAD) { popOnEof(); @@ -769,7 +769,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_STYLE: { appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -783,6 +783,12 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu attributes = nsnull; goto starttagloop_end; } + case NS_HTML5TREE_BUILDER_FORM: { + + appendVoidElementToCurrent(kNameSpaceID_XHTML, name, attributes); + attributes = nsnull; + goto starttagloop_end; + } default: { goto intableloop_end; @@ -904,7 +910,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_STYLE: case NS_HTML5TREE_BUILDER_SCRIPT: case NS_HTML5TREE_BUILDER_TITLE: - case NS_HTML5TREE_BUILDER_COMMAND_OR_EVENT_SOURCE: { + case NS_HTML5TREE_BUILDER_COMMAND: { goto inbodyloop_end; } case NS_HTML5TREE_BUILDER_BODY: { @@ -916,7 +922,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_P: case NS_HTML5TREE_BUILDER_DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: case NS_HTML5TREE_BUILDER_UL_OR_OL_OR_DL: - case NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION: { + case NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION: { implicitlyCloseP(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); attributes = nsnull; @@ -1058,15 +1064,6 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu attributes = nsnull; goto starttagloop_end; } - case NS_HTML5TREE_BUILDER_XMP: { - reconstructTheActiveFormattingElements(); - appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); - originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); - attributes = nsnull; - goto starttagloop_end; - } case NS_HTML5TREE_BUILDER_TABLE: { if (!quirks) { implicitlyCloseP(); @@ -1120,7 +1117,6 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } appendToCurrentNodeAndPushFormElementMayFoster(formAttrs); appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, nsHtml5ElementName::ELT_HR, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); - appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, nsHtml5ElementName::ELT_P, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, nsHtml5ElementName::ELT_LABEL, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); PRInt32 promptIndex = attributes->getIndex(nsHtml5AttributeName::ATTR_PROMPT); if (promptIndex > -1) { @@ -1143,7 +1139,6 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu attributes->clearWithoutReleasingContents(); appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, nsHtml5Atoms::input, inputAttributes, formPointer); pop(); - pop(); appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, nsHtml5ElementName::ELT_HR, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES); pop(); selfClosing = PR_FALSE; @@ -1156,11 +1151,21 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes, formPointer); tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RCDATA, elementName); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; needToDropLF = PR_TRUE; attributes = nsnull; goto starttagloop_end; } + case NS_HTML5TREE_BUILDER_XMP: { + implicitlyCloseP(); + reconstructTheActiveFormattingElements(); + appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + originalMode = mode; + mode = NS_HTML5TREE_BUILDER_TEXT; + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; + goto starttagloop_end; + } case NS_HTML5TREE_BUILDER_NOSCRIPT: { if (!scriptingEnabled) { reconstructTheActiveFormattingElements(); @@ -1175,7 +1180,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_NOEMBED: { appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -1310,7 +1315,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu goto starttagloop_end; } case NS_HTML5TREE_BUILDER_BASE: - case NS_HTML5TREE_BUILDER_COMMAND_OR_EVENT_SOURCE: { + case NS_HTML5TREE_BUILDER_COMMAND: { appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; attributes = nsnull; @@ -1323,7 +1328,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_TITLE: { appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RCDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -1332,7 +1337,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu if (scriptingEnabled) { appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); } else { appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); @@ -1346,7 +1351,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_NOFRAMES: { appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -1389,7 +1394,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_NOFRAMES: { appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -1444,7 +1449,15 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_TD_OR_TH: case NS_HTML5TREE_BUILDER_TABLE: { - endSelect(); + eltPos = findLastInTableScope(nsHtml5Atoms::select); + if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) { + + goto starttagloop_end; + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); continue; } default: @@ -1494,15 +1507,24 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } } case NS_HTML5TREE_BUILDER_INPUT: - case NS_HTML5TREE_BUILDER_TEXTAREA: { + case NS_HTML5TREE_BUILDER_TEXTAREA: + case NS_HTML5TREE_BUILDER_KEYGEN: { - endSelect(); + eltPos = findLastInTableScope(nsHtml5Atoms::select); + if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) { + + goto starttagloop_end; + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); continue; } case NS_HTML5TREE_BUILDER_SCRIPT: { appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -1556,7 +1578,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_NOFRAMES: { appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -1626,7 +1648,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } else { appendToCurrentNodeAndPushBodyElement(attributes); } - mode = NS_HTML5TREE_BUILDER_FRAMESET_OK; + mode = NS_HTML5TREE_BUILDER_IN_BODY; attributes = nsnull; goto starttagloop_end; } @@ -1669,7 +1691,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu pushHeadPointerOntoStack(); appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -1680,7 +1702,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu pushHeadPointerOntoStack(); appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -1690,7 +1712,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu pushHeadPointerOntoStack(); appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RCDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -1727,7 +1749,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_NOFRAMES: { appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; - mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; + mode = NS_HTML5TREE_BUILDER_TEXT; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); attributes = nsnull; goto starttagloop_end; @@ -2222,7 +2244,7 @@ nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) case NS_HTML5TREE_BUILDER_UL_OR_OL_OR_DL: case NS_HTML5TREE_BUILDER_PRE_OR_LISTING: case NS_HTML5TREE_BUILDER_FIELDSET: - case NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION: { + case NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION: { eltPos = findLastInScope(name); if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) { @@ -2280,8 +2302,22 @@ nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) } goto endtagloop_end; } - case NS_HTML5TREE_BUILDER_DD_OR_DT: case NS_HTML5TREE_BUILDER_LI: { + eltPos = findLastInListScope(name); + if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) { + + } else { + generateImpliedEndTagsExceptFor(name); + if (eltPos != currentPtr) { + + } + while (currentPtr >= eltPos) { + pop(); + } + } + goto endtagloop_end; + } + case NS_HTML5TREE_BUILDER_DD_OR_DT: { eltPos = findLastInScope(name); if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) { @@ -2436,7 +2472,15 @@ nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) case NS_HTML5TREE_BUILDER_TD_OR_TH: { if (findLastInTableScope(name) != NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) { - endSelect(); + eltPos = findLastInTableScope(nsHtml5Atoms::select); + if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) { + + goto endtagloop_end; + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); continue; } else { goto endtagloop_end; @@ -2469,7 +2513,16 @@ nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) goto endtagloop_end; } case NS_HTML5TREE_BUILDER_SELECT: { - endSelect(); + eltPos = findLastInTableScope(nsHtml5Atoms::select); + if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) { + + + goto endtagloop_end; + } + while (currentPtr >= eltPos) { + pop(); + } + resetTheInsertionMode(); goto endtagloop_end; } default: { @@ -2534,9 +2587,20 @@ nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) continue; } case NS_HTML5TREE_BUILDER_BEFORE_HTML: { - appendHtmlElementToDocumentAndPush(); - mode = NS_HTML5TREE_BUILDER_BEFORE_HEAD; - continue; + switch(group) { + case NS_HTML5TREE_BUILDER_HEAD: + case NS_HTML5TREE_BUILDER_BR: + case NS_HTML5TREE_BUILDER_HTML: + case NS_HTML5TREE_BUILDER_BODY: { + appendHtmlElementToDocumentAndPush(); + mode = NS_HTML5TREE_BUILDER_BEFORE_HEAD; + continue; + } + default: { + + goto endtagloop_end; + } + } } case NS_HTML5TREE_BUILDER_BEFORE_HEAD: { switch(group) { @@ -2618,7 +2682,7 @@ nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) mode = NS_HTML5TREE_BUILDER_IN_FRAMESET; continue; } - case NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA: { + case NS_HTML5TREE_BUILDER_TEXT: { if (originalMode == NS_HTML5TREE_BUILDER_AFTER_HEAD) { pop(); } @@ -2634,21 +2698,6 @@ nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) } } -void -nsHtml5TreeBuilder::endSelect() -{ - PRInt32 eltPos = findLastInTableScope(nsHtml5Atoms::select); - if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) { - - - return; - } - while (currentPtr >= eltPos) { - pop(); - } - resetTheInsertionMode(); -} - PRInt32 nsHtml5TreeBuilder::findLastInTableScopeOrRootTbodyTheadTfoot() { @@ -2697,6 +2746,19 @@ nsHtml5TreeBuilder::findLastInScope(nsIAtom* name) return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK; } +PRInt32 +nsHtml5TreeBuilder::findLastInListScope(nsIAtom* name) +{ + for (PRInt32 i = currentPtr; i > 0; i--) { + if (stack[i]->name == name) { + return i; + } else if (stack[i]->scoping || stack[i]->name == nsHtml5Atoms::ul || stack[i]->name == nsHtml5Atoms::ol) { + return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK; + } + } + return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK; +} + PRInt32 nsHtml5TreeBuilder::findLastInScopeHn() { @@ -3601,6 +3663,18 @@ nsHtml5TreeBuilder::appendVoidElementToCurrent(PRInt32 ns, nsIAtom* name, nsHtml ; } +void +nsHtml5TreeBuilder::appendVoidElementToCurrent(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes) +{ + flushCharacters(); + nsIContent** elt = createElement(ns, name, attributes); + nsHtml5StackNode* current = stack[currentPtr]; + appendElement(elt, current->node); + elementPushed(ns, name, elt); + elementPopped(ns, name, elt); + ; +} + void nsHtml5TreeBuilder::accumulateCharacter(PRUnichar c) { diff --git a/parser/html/nsHtml5TreeBuilder.h b/parser/html/nsHtml5TreeBuilder.h index 4799d346b20a..67c3a8f9fde8 100644 --- a/parser/html/nsHtml5TreeBuilder.h +++ b/parser/html/nsHtml5TreeBuilder.h @@ -110,11 +110,11 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState public: void endTag(nsHtml5ElementName* elementName); private: - void endSelect(); PRInt32 findLastInTableScopeOrRootTbodyTheadTfoot(); PRInt32 findLast(nsIAtom* name); PRInt32 findLastInTableScope(nsIAtom* name); PRInt32 findLastInScope(nsIAtom* name); + PRInt32 findLastInListScope(nsIAtom* name); PRInt32 findLastInScopeHn(); PRBool hasForeignInScope(); void generateImpliedEndTagsExceptFor(nsIAtom* name); @@ -177,6 +177,7 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState void appendVoidElementToCurrentMayFoster(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); void appendVoidElementToCurrentMayFosterCamelCase(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); void appendVoidElementToCurrent(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form); + void appendVoidElementToCurrent(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes); protected: void accumulateCharacters(PRUnichar* buf, PRInt32 start, PRInt32 length); void accumulateCharacter(PRUnichar c); @@ -289,10 +290,10 @@ jArray nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = nsnull; #define NS_HTML5TREE_BUILDER_EMBED_OR_IMG 48 #define NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR 49 #define NS_HTML5TREE_BUILDER_DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU 50 -#define NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION 51 +#define NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION 51 #define NS_HTML5TREE_BUILDER_RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR 52 #define NS_HTML5TREE_BUILDER_RT_OR_RP 53 -#define NS_HTML5TREE_BUILDER_COMMAND_OR_EVENT_SOURCE 54 +#define NS_HTML5TREE_BUILDER_COMMAND 54 #define NS_HTML5TREE_BUILDER_PARAM_OR_SOURCE 55 #define NS_HTML5TREE_BUILDER_MGLYPH_OR_MALIGNMARK 56 #define NS_HTML5TREE_BUILDER_MI_MO_MN_MS_MTEXT 57 @@ -324,7 +325,7 @@ jArray nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = nsnull; #define NS_HTML5TREE_BUILDER_AFTER_FRAMESET 17 #define NS_HTML5TREE_BUILDER_AFTER_AFTER_BODY 18 #define NS_HTML5TREE_BUILDER_AFTER_AFTER_FRAMESET 19 -#define NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA 20 +#define NS_HTML5TREE_BUILDER_TEXT 20 #define NS_HTML5TREE_BUILDER_FRAMESET_OK 21 #define NS_HTML5TREE_BUILDER_CHARSET_INITIAL 0 #define NS_HTML5TREE_BUILDER_CHARSET_C 1 From 888d6846dccc1dca17b446dd8088591c3b5f958a Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Mon, 30 Nov 2009 17:34:51 +0200 Subject: [PATCH 140/179] Bug 509009, bug 497848 - Update the HTML5 tokenizer to spec (excluding script changes) as of 2009-11-24. rs=sicking. --HG-- extra : rebase_source : 1ea9013dcd1a4a4b4d0000f810916d3569cd0172 --- .../html/java/named-character-references.html | 171 +- parser/html/nsHtml5AtomList.h | 2 +- parser/html/nsHtml5NamedCharacters.cpp | 14 +- parser/html/nsHtml5NamedCharactersInclude.h | 2241 +++++++++-------- parser/html/nsHtml5Tokenizer.cpp | 426 +++- parser/html/nsHtml5Tokenizer.h | 13 +- parser/html/nsHtml5TreeBuilder.cpp | 46 +- 7 files changed, 1488 insertions(+), 1425 deletions(-) diff --git a/parser/html/java/named-character-references.html b/parser/html/java/named-character-references.html index ea4ade1d9220..c8d1e08daf0b 100644 --- a/parser/html/java/named-character-references.html +++ b/parser/html/java/named-character-references.html @@ -1,168 +1,7 @@ - -HTML 5 - - -
-

W3C

-

HTML 5

-

A vocabulary and associated APIs for HTML and XHTML

-
- -

8.6 Named character references

This table lists the character reference names that are supported - by HTML, and the code points to which they refer. It is referenced - by the previous sections.

-
Name Character
AElig; U+000C6
AElig U+000C6
AMP; U+00026
AMP U+00026
Aacute; U+000C1
Aacute U+000C1
Abreve; U+00102
Acirc; U+000C2
Acirc U+000C2
Acy; U+00410
Afr; U+1D504
Agrave; U+000C0
Agrave U+000C0
Alpha; U+00391
Amacr; U+00100
And; U+02A53
Aogon; U+00104
Aopf; U+1D538
ApplyFunction; U+02061
Aring; U+000C5
Aring U+000C5
Ascr; U+1D49C
Assign; U+02254
Atilde; U+000C3
Atilde U+000C3
Auml; U+000C4
Auml U+000C4
Backslash; U+02216
Barv; U+02AE7
Barwed; U+02306
Bcy; U+00411
Because; U+02235
Bernoullis; U+0212C
Beta; U+00392
Bfr; U+1D505
Bopf; U+1D539
Breve; U+002D8
Bscr; U+0212C
Bumpeq; U+0224E
CHcy; U+00427
COPY; U+000A9
COPY U+000A9
Cacute; U+00106
Cap; U+022D2
CapitalDifferentialD; U+02145
Cayleys; U+0212D
Ccaron; U+0010C
Ccedil; U+000C7
Ccedil U+000C7
Ccirc; U+00108
Cconint; U+02230
Cdot; U+0010A
Cedilla; U+000B8
CenterDot; U+000B7
Cfr; U+0212D
Chi; U+003A7
CircleDot; U+02299
CircleMinus; U+02296
CirclePlus; U+02295
CircleTimes; U+02297
ClockwiseContourIntegral; U+02232
CloseCurlyDoubleQuote; U+0201D
CloseCurlyQuote; U+02019
Colon; U+02237
Colone; U+02A74
Congruent; U+02261
Conint; U+0222F
ContourIntegral; U+0222E
Copf; U+02102
Coproduct; U+02210
CounterClockwiseContourIntegral; U+02233
Cross; U+02A2F
Cscr; U+1D49E
Cup; U+022D3
CupCap; U+0224D
DD; U+02145
DDotrahd; U+02911
DJcy; U+00402
DScy; U+00405
DZcy; U+0040F
Dagger; U+02021
Darr; U+021A1
Dashv; U+02AE4
Dcaron; U+0010E
Dcy; U+00414
Del; U+02207
Delta; U+00394
Dfr; U+1D507
DiacriticalAcute; U+000B4
DiacriticalDot; U+002D9
DiacriticalDoubleAcute; U+002DD
DiacriticalGrave; U+00060
DiacriticalTilde; U+002DC
Diamond; U+022C4
DifferentialD; U+02146
Dopf; U+1D53B
Dot; U+000A8
DotDot; U+020DC
DotEqual; U+02250
DoubleContourIntegral; U+0222F
DoubleDot; U+000A8
DoubleDownArrow; U+021D3
DoubleLeftArrow; U+021D0
DoubleLeftRightArrow; U+021D4
DoubleLeftTee; U+02AE4
DoubleLongLeftArrow; U+027F8
DoubleLongLeftRightArrow; U+027FA
DoubleLongRightArrow; U+027F9
DoubleRightArrow; U+021D2
DoubleRightTee; U+022A8
DoubleUpArrow; U+021D1
DoubleUpDownArrow; U+021D5
DoubleVerticalBar; U+02225
DownArrow; U+02193
DownArrowBar; U+02913
DownArrowUpArrow; U+021F5
DownBreve; U+00311
DownLeftRightVector; U+02950
DownLeftTeeVector; U+0295E
DownLeftVector; U+021BD
DownLeftVectorBar; U+02956
DownRightTeeVector; U+0295F
DownRightVector; U+021C1
DownRightVectorBar; U+02957
DownTee; U+022A4
DownTeeArrow; U+021A7
Downarrow; U+021D3
Dscr; U+1D49F
Dstrok; U+00110
ENG; U+0014A
ETH; U+000D0
ETH U+000D0
Eacute; U+000C9
Eacute U+000C9
Ecaron; U+0011A
Ecirc; U+000CA
Ecirc U+000CA
Ecy; U+0042D
Edot; U+00116
Efr; U+1D508
Egrave; U+000C8
Egrave U+000C8
Element; U+02208
Emacr; U+00112
EmptySmallSquare; U+025FB
EmptyVerySmallSquare; U+025AB
Eogon; U+00118
Eopf; U+1D53C
Epsilon; U+00395
Equal; U+02A75
EqualTilde; U+02242
Equilibrium; U+021CC
Escr; U+02130
Esim; U+02A73
Eta; U+00397
Euml; U+000CB
Euml U+000CB
Exists; U+02203
ExponentialE; U+02147
Fcy; U+00424
Ffr; U+1D509
FilledSmallSquare; U+025FC
FilledVerySmallSquare; U+025AA
Fopf; U+1D53D
ForAll; U+02200
Fouriertrf; U+02131
Fscr; U+02131
GJcy; U+00403
GT; U+0003E
GT U+0003E
Gamma; U+00393
Gammad; U+003DC
Gbreve; U+0011E
Gcedil; U+00122
Gcirc; U+0011C
Gcy; U+00413
Gdot; U+00120
Gfr; U+1D50A
Gg; U+022D9
Gopf; U+1D53E
GreaterEqual; U+02265
GreaterEqualLess; U+022DB
GreaterFullEqual; U+02267
GreaterGreater; U+02AA2
GreaterLess; U+02277
GreaterSlantEqual; U+02A7E
GreaterTilde; U+02273
Gscr; U+1D4A2
Gt; U+0226B
HARDcy; U+0042A
Hacek; U+002C7
Hat; U+0005E
Hcirc; U+00124
Hfr; U+0210C
HilbertSpace; U+0210B
Hopf; U+0210D
HorizontalLine; U+02500
Hscr; U+0210B
Hstrok; U+00126
HumpDownHump; U+0224E
HumpEqual; U+0224F
IEcy; U+00415
IJlig; U+00132
IOcy; U+00401
Iacute; U+000CD
Iacute U+000CD
Icirc; U+000CE
Icirc U+000CE
Icy; U+00418
Idot; U+00130
Ifr; U+02111
Igrave; U+000CC
Igrave U+000CC
Im; U+02111
Imacr; U+0012A
ImaginaryI; U+02148
Implies; U+021D2
Int; U+0222C
Integral; U+0222B
Intersection; U+022C2
InvisibleComma; U+02063
InvisibleTimes; U+02062
Iogon; U+0012E
Iopf; U+1D540
Iota; U+00399
Iscr; U+02110
Itilde; U+00128
Iukcy; U+00406
Iuml; U+000CF
Iuml U+000CF
Jcirc; U+00134
Jcy; U+00419
Jfr; U+1D50D
Jopf; U+1D541
Jscr; U+1D4A5
Jsercy; U+00408
Jukcy; U+00404
KHcy; U+00425
KJcy; U+0040C
Kappa; U+0039A
Kcedil; U+00136
Kcy; U+0041A
Kfr; U+1D50E
Kopf; U+1D542
Kscr; U+1D4A6
LJcy; U+00409
LT; U+0003C
LT U+0003C
Lacute; U+00139
Lambda; U+0039B
Lang; U+027EA
Laplacetrf; U+02112
Larr; U+0219E
Lcaron; U+0013D
Lcedil; U+0013B
Lcy; U+0041B
LeftAngleBracket; U+027E8
LeftArrow; U+02190
LeftArrowBar; U+021E4
LeftArrowRightArrow; U+021C6
LeftCeiling; U+02308
LeftDoubleBracket; U+027E6
LeftDownTeeVector; U+02961
LeftDownVector; U+021C3
LeftDownVectorBar; U+02959
LeftFloor; U+0230A
LeftRightArrow; U+02194
LeftRightVector; U+0294E
LeftTee; U+022A3
LeftTeeArrow; U+021A4
LeftTeeVector; U+0295A
LeftTriangle; U+022B2
LeftTriangleBar; U+029CF
LeftTriangleEqual; U+022B4
LeftUpDownVector; U+02951
LeftUpTeeVector; U+02960
LeftUpVector; U+021BF
LeftUpVectorBar; U+02958
LeftVector; U+021BC
LeftVectorBar; U+02952
Leftarrow; U+021D0
Leftrightarrow; U+021D4
LessEqualGreater; U+022DA
LessFullEqual; U+02266
LessGreater; U+02276
LessLess; U+02AA1
LessSlantEqual; U+02A7D
LessTilde; U+02272
Lfr; U+1D50F
Ll; U+022D8
Lleftarrow; U+021DA
Lmidot; U+0013F
LongLeftArrow; U+027F5
LongLeftRightArrow; U+027F7
LongRightArrow; U+027F6
Longleftarrow; U+027F8
Longleftrightarrow; U+027FA
Longrightarrow; U+027F9
Lopf; U+1D543
LowerLeftArrow; U+02199
LowerRightArrow; U+02198
Lscr; U+02112
Lsh; U+021B0
Lstrok; U+00141
Lt; U+0226A
Map; U+02905
Mcy; U+0041C
MediumSpace; U+0205F
Mellintrf; U+02133
Mfr; U+1D510
MinusPlus; U+02213
Mopf; U+1D544
Mscr; U+02133
Mu; U+0039C
NJcy; U+0040A
Nacute; U+00143
Ncaron; U+00147
Ncedil; U+00145
Ncy; U+0041D
NegativeMediumSpace; U+0200B
NegativeThickSpace; U+0200B
NegativeThinSpace; U+0200B
NegativeVeryThinSpace; U+0200B
NestedGreaterGreater; U+0226B
NestedLessLess; U+0226A
NewLine; U+0000A
Nfr; U+1D511
NoBreak; U+02060
NonBreakingSpace; U+000A0
Nopf; U+02115
Not; U+02AEC
NotCongruent; U+02262
NotCupCap; U+0226D
NotDoubleVerticalBar; U+02226
NotElement; U+02209
NotEqual; U+02260
NotExists; U+02204
NotGreater; U+0226F
NotGreaterEqual; U+02271
NotGreaterLess; U+02279
NotGreaterTilde; U+02275
NotLeftTriangle; U+022EA
NotLeftTriangleEqual; U+022EC
NotLess; U+0226E
NotLessEqual; U+02270
NotLessGreater; U+02278
NotLessTilde; U+02274
NotPrecedes; U+02280
NotPrecedesSlantEqual; U+022E0
NotReverseElement; U+0220C
NotRightTriangle; U+022EB
NotRightTriangleEqual; U+022ED
NotSquareSubsetEqual; U+022E2
NotSquareSupersetEqual; U+022E3
NotSubsetEqual; U+02288
NotSucceeds; U+02281
NotSucceedsSlantEqual; U+022E1
NotSupersetEqual; U+02289
NotTilde; U+02241
NotTildeEqual; U+02244
NotTildeFullEqual; U+02247
NotTildeTilde; U+02249
NotVerticalBar; U+02224
Nscr; U+1D4A9
Ntilde; U+000D1
Ntilde U+000D1
Nu; U+0039D
OElig; U+00152
Oacute; U+000D3
Oacute U+000D3
Ocirc; U+000D4
Ocirc U+000D4
Ocy; U+0041E
Odblac; U+00150
Ofr; U+1D512
Ograve; U+000D2
Ograve U+000D2
Omacr; U+0014C
Omega; U+003A9
Omicron; U+0039F
Oopf; U+1D546
OpenCurlyDoubleQuote; U+0201C
OpenCurlyQuote; U+02018
Or; U+02A54
Oscr; U+1D4AA
Oslash; U+000D8
Oslash U+000D8
Otilde; U+000D5
Otilde U+000D5
Otimes; U+02A37
Ouml; U+000D6
Ouml U+000D6
OverBar; U+000AF
OverBrace; U+023DE
OverBracket; U+023B4
OverParenthesis; U+023DC
PartialD; U+02202
Pcy; U+0041F
Pfr; U+1D513
Phi; U+003A6
Pi; U+003A0
PlusMinus; U+000B1
Poincareplane; U+0210C
Popf; U+02119
Pr; U+02ABB
Precedes; U+0227A
PrecedesEqual; U+02AAF
PrecedesSlantEqual; U+0227C
PrecedesTilde; U+0227E
Prime; U+02033
Product; U+0220F
Proportion; U+02237
Proportional; U+0221D
Pscr; U+1D4AB
Psi; U+003A8
QUOT; U+00022
QUOT U+00022
Qfr; U+1D514
Qopf; U+0211A
Qscr; U+1D4AC
RBarr; U+02910
REG; U+000AE
REG U+000AE
Racute; U+00154
Rang; U+027EB
Rarr; U+021A0
Rarrtl; U+02916
Rcaron; U+00158
Rcedil; U+00156
Rcy; U+00420
Re; U+0211C
ReverseElement; U+0220B
ReverseEquilibrium; U+021CB
ReverseUpEquilibrium; U+0296F
Rfr; U+0211C
Rho; U+003A1
RightAngleBracket; U+027E9
RightArrow; U+02192
RightArrowBar; U+021E5
RightArrowLeftArrow; U+021C4
RightCeiling; U+02309
RightDoubleBracket; U+027E7
RightDownTeeVector; U+0295D
RightDownVector; U+021C2
RightDownVectorBar; U+02955
RightFloor; U+0230B
RightTee; U+022A2
RightTeeArrow; U+021A6
RightTeeVector; U+0295B
RightTriangle; U+022B3
RightTriangleBar; U+029D0
RightTriangleEqual; U+022B5
RightUpDownVector; U+0294F
RightUpTeeVector; U+0295C
RightUpVector; U+021BE
RightUpVectorBar; U+02954
RightVector; U+021C0
RightVectorBar; U+02953
Rightarrow; U+021D2
Ropf; U+0211D
RoundImplies; U+02970
Rrightarrow; U+021DB
Rscr; U+0211B
Rsh; U+021B1
RuleDelayed; U+029F4
SHCHcy; U+00429
SHcy; U+00428
SOFTcy; U+0042C
Sacute; U+0015A
Sc; U+02ABC
Scaron; U+00160
Scedil; U+0015E
Scirc; U+0015C
Scy; U+00421
Sfr; U+1D516
ShortDownArrow; U+02193
ShortLeftArrow; U+02190
ShortRightArrow; U+02192
ShortUpArrow; U+02191
Sigma; U+003A3
SmallCircle; U+02218
Sopf; U+1D54A
Sqrt; U+0221A
Square; U+025A1
SquareIntersection; U+02293
SquareSubset; U+0228F
SquareSubsetEqual; U+02291
SquareSuperset; U+02290
SquareSupersetEqual; U+02292
SquareUnion; U+02294
Sscr; U+1D4AE
Star; U+022C6
Sub; U+022D0
Subset; U+022D0
SubsetEqual; U+02286
Succeeds; U+0227B
SucceedsEqual; U+02AB0
SucceedsSlantEqual; U+0227D
SucceedsTilde; U+0227F
SuchThat; U+0220B
Sum; U+02211
Sup; U+022D1
Superset; U+02283
SupersetEqual; U+02287
Supset; U+022D1
THORN; U+000DE
THORN U+000DE
TRADE; U+02122
TSHcy; U+0040B
TScy; U+00426
Tab; U+00009
Tau; U+003A4
Tcaron; U+00164
Tcedil; U+00162
Tcy; U+00422
Tfr; U+1D517
Therefore; U+02234
Theta; U+00398
ThinSpace; U+02009
Tilde; U+0223C
TildeEqual; U+02243
TildeFullEqual; U+02245
TildeTilde; U+02248
Topf; U+1D54B
TripleDot; U+020DB
Tscr; U+1D4AF
Tstrok; U+00166
Uacute; U+000DA
Uacute U+000DA
Uarr; U+0219F
Uarrocir; U+02949
Ubrcy; U+0040E
Ubreve; U+0016C
Ucirc; U+000DB
Ucirc U+000DB
Ucy; U+00423
Udblac; U+00170
Ufr; U+1D518
Ugrave; U+000D9
Ugrave U+000D9
Umacr; U+0016A
UnderBar; U+00332
UnderBrace; U+023DF
UnderBracket; U+023B5
UnderParenthesis; U+023DD
Union; U+022C3
UnionPlus; U+0228E
Uogon; U+00172
Uopf; U+1D54C
UpArrow; U+02191
UpArrowBar; U+02912
UpArrowDownArrow; U+021C5
UpDownArrow; U+02195
UpEquilibrium; U+0296E
UpTee; U+022A5
UpTeeArrow; U+021A5
Uparrow; U+021D1
Updownarrow; U+021D5
UpperLeftArrow; U+02196
UpperRightArrow; U+02197
Upsi; U+003D2
Upsilon; U+003A5
Uring; U+0016E
Uscr; U+1D4B0
Utilde; U+00168
Uuml; U+000DC
Uuml U+000DC
VDash; U+022AB
Vbar; U+02AEB
Vcy; U+00412
Vdash; U+022A9
Vdashl; U+02AE6
Vee; U+022C1
Verbar; U+02016
Vert; U+02016
VerticalBar; U+02223
VerticalLine; U+0007C
VerticalSeparator; U+02758
VerticalTilde; U+02240
VeryThinSpace; U+0200A
Vfr; U+1D519
Vopf; U+1D54D
Vscr; U+1D4B1
Vvdash; U+022AA
Wcirc; U+00174
Wedge; U+022C0
Wfr; U+1D51A
Wopf; U+1D54E
Wscr; U+1D4B2
Xfr; U+1D51B
Xi; U+0039E
Xopf; U+1D54F
Xscr; U+1D4B3
YAcy; U+0042F
YIcy; U+00407
YUcy; U+0042E
Yacute; U+000DD
Yacute U+000DD
Ycirc; U+00176
Ycy; U+0042B
Yfr; U+1D51C
Yopf; U+1D550
Yscr; U+1D4B4
Yuml; U+00178
ZHcy; U+00416
Zacute; U+00179
Zcaron; U+0017D
Zcy; U+00417
Zdot; U+0017B
ZeroWidthSpace; U+0200B
Zeta; U+00396
Zfr; U+02128
Zopf; U+02124
Zscr; U+1D4B5
aacute; U+000E1
aacute U+000E1
abreve; U+00103
ac; U+0223E
acd; U+0223F
acirc; U+000E2
acirc U+000E2
acute; U+000B4
acute U+000B4
acy; U+00430
aelig; U+000E6
aelig U+000E6
af; U+02061
afr; U+1D51E
agrave; U+000E0
agrave U+000E0
alefsym; U+02135
aleph; U+02135
alpha; U+003B1
amacr; U+00101
amalg; U+02A3F
amp; U+00026
amp U+00026
and; U+02227
andand; U+02A55
andd; U+02A5C
andslope; U+02A58
andv; U+02A5A
ang; U+02220
ange; U+029A4
angle; U+02220
angmsd; U+02221
angmsdaa; U+029A8
angmsdab; U+029A9
angmsdac; U+029AA
angmsdad; U+029AB
angmsdae; U+029AC
angmsdaf; U+029AD
angmsdag; U+029AE
angmsdah; U+029AF
angrt; U+0221F
angrtvb; U+022BE
angrtvbd; U+0299D
angsph; U+02222
angst; U+0212B
angzarr; U+0237C
aogon; U+00105
aopf; U+1D552
ap; U+02248
apE; U+02A70
apacir; U+02A6F
ape; U+0224A
apid; U+0224B
apos; U+00027
approx; U+02248
approxeq; U+0224A
aring; U+000E5
aring U+000E5
ascr; U+1D4B6
ast; U+0002A
asymp; U+02248
asympeq; U+0224D
atilde; U+000E3
atilde U+000E3
auml; U+000E4
auml U+000E4
awconint; U+02233
awint; U+02A11
bNot; U+02AED
backcong; U+0224C
backepsilon; U+003F6
backprime; U+02035
backsim; U+0223D
backsimeq; U+022CD
barvee; U+022BD
barwed; U+02305
barwedge; U+02305
bbrk; U+023B5
bbrktbrk; U+023B6
bcong; U+0224C
bcy; U+00431
bdquo; U+0201E
becaus; U+02235
because; U+02235
bemptyv; U+029B0
bepsi; U+003F6
bernou; U+0212C
beta; U+003B2
beth; U+02136
between; U+0226C
bfr; U+1D51F
bigcap; U+022C2
bigcirc; U+025EF
bigcup; U+022C3
bigodot; U+02A00
bigoplus; U+02A01
bigotimes; U+02A02
bigsqcup; U+02A06
bigstar; U+02605
bigtriangledown; U+025BD
bigtriangleup; U+025B3
biguplus; U+02A04
bigvee; U+022C1
bigwedge; U+022C0
bkarow; U+0290D
blacklozenge; U+029EB
blacksquare; U+025AA
blacktriangle; U+025B4
blacktriangledown; U+025BE
blacktriangleleft; U+025C2
blacktriangleright; U+025B8
blank; U+02423
blk12; U+02592
blk14; U+02591
blk34; U+02593
block; U+02588
bnot; U+02310
bopf; U+1D553
bot; U+022A5
bottom; U+022A5
bowtie; U+022C8
boxDL; U+02557
boxDR; U+02554
boxDl; U+02556
boxDr; U+02553
boxH; U+02550
boxHD; U+02566
boxHU; U+02569
boxHd; U+02564
boxHu; U+02567
boxUL; U+0255D
boxUR; U+0255A
boxUl; U+0255C
boxUr; U+02559
boxV; U+02551
boxVH; U+0256C
boxVL; U+02563
boxVR; U+02560
boxVh; U+0256B
boxVl; U+02562
boxVr; U+0255F
boxbox; U+029C9
boxdL; U+02555
boxdR; U+02552
boxdl; U+02510
boxdr; U+0250C
boxh; U+02500
boxhD; U+02565
boxhU; U+02568
boxhd; U+0252C
boxhu; U+02534
boxminus; U+0229F
boxplus; U+0229E
boxtimes; U+022A0
boxuL; U+0255B
boxuR; U+02558
boxul; U+02518
boxur; U+02514
boxv; U+02502
boxvH; U+0256A
boxvL; U+02561
boxvR; U+0255E
boxvh; U+0253C
boxvl; U+02524
boxvr; U+0251C
bprime; U+02035
breve; U+002D8
brvbar; U+000A6
brvbar U+000A6
bscr; U+1D4B7
bsemi; U+0204F
bsim; U+0223D
bsime; U+022CD
bsol; U+0005C
bsolb; U+029C5
bull; U+02022
bullet; U+02022
bump; U+0224E
bumpE; U+02AAE
bumpe; U+0224F
bumpeq; U+0224F
cacute; U+00107
cap; U+02229
capand; U+02A44
capbrcup; U+02A49
capcap; U+02A4B
capcup; U+02A47
capdot; U+02A40
caret; U+02041
caron; U+002C7
ccaps; U+02A4D
ccaron; U+0010D
ccedil; U+000E7
ccedil U+000E7
ccirc; U+00109
ccups; U+02A4C
ccupssm; U+02A50
cdot; U+0010B
cedil; U+000B8
cedil U+000B8
cemptyv; U+029B2
cent; U+000A2
cent U+000A2
centerdot; U+000B7
cfr; U+1D520
chcy; U+00447
check; U+02713
checkmark; U+02713
chi; U+003C7
cir; U+025CB
cirE; U+029C3
circ; U+002C6
circeq; U+02257
circlearrowleft; U+021BA
circlearrowright; U+021BB
circledR; U+000AE
circledS; U+024C8
circledast; U+0229B
circledcirc; U+0229A
circleddash; U+0229D
cire; U+02257
cirfnint; U+02A10
cirmid; U+02AEF
cirscir; U+029C2
clubs; U+02663
clubsuit; U+02663
colon; U+0003A
colone; U+02254
coloneq; U+02254
comma; U+0002C
commat; U+00040
comp; U+02201
compfn; U+02218
complement; U+02201
complexes; U+02102
cong; U+02245
congdot; U+02A6D
conint; U+0222E
copf; U+1D554
coprod; U+02210
copy; U+000A9
copy U+000A9
copysr; U+02117
crarr; U+021B5
cross; U+02717
cscr; U+1D4B8
csub; U+02ACF
csube; U+02AD1
csup; U+02AD0
csupe; U+02AD2
ctdot; U+022EF
cudarrl; U+02938
cudarrr; U+02935
cuepr; U+022DE
cuesc; U+022DF
cularr; U+021B6
cularrp; U+0293D
cup; U+0222A
cupbrcap; U+02A48
cupcap; U+02A46
cupcup; U+02A4A
cupdot; U+0228D
cupor; U+02A45
curarr; U+021B7
curarrm; U+0293C
curlyeqprec; U+022DE
curlyeqsucc; U+022DF
curlyvee; U+022CE
curlywedge; U+022CF
curren; U+000A4
curren U+000A4
curvearrowleft; U+021B6
curvearrowright; U+021B7
cuvee; U+022CE
cuwed; U+022CF
cwconint; U+02232
cwint; U+02231
cylcty; U+0232D
dArr; U+021D3
dHar; U+02965
dagger; U+02020
daleth; U+02138
darr; U+02193
dash; U+02010
dashv; U+022A3
dbkarow; U+0290F
dblac; U+002DD
dcaron; U+0010F
dcy; U+00434
dd; U+02146
ddagger; U+02021
ddarr; U+021CA
ddotseq; U+02A77
deg; U+000B0
deg U+000B0
delta; U+003B4
demptyv; U+029B1
dfisht; U+0297F
dfr; U+1D521
dharl; U+021C3
dharr; U+021C2
diam; U+022C4
diamond; U+022C4
diamondsuit; U+02666
diams; U+02666
die; U+000A8
digamma; U+003DD
disin; U+022F2
div; U+000F7
divide; U+000F7
divide U+000F7
divideontimes; U+022C7
divonx; U+022C7
djcy; U+00452
dlcorn; U+0231E
dlcrop; U+0230D
dollar; U+00024
dopf; U+1D555
dot; U+002D9
doteq; U+02250
doteqdot; U+02251
dotminus; U+02238
dotplus; U+02214
dotsquare; U+022A1
doublebarwedge; U+02306
downarrow; U+02193
downdownarrows; U+021CA
downharpoonleft; U+021C3
downharpoonright; U+021C2
drbkarow; U+02910
drcorn; U+0231F
drcrop; U+0230C
dscr; U+1D4B9
dscy; U+00455
dsol; U+029F6
dstrok; U+00111
dtdot; U+022F1
dtri; U+025BF
dtrif; U+025BE
duarr; U+021F5
duhar; U+0296F
dwangle; U+029A6
dzcy; U+0045F
dzigrarr; U+027FF
eDDot; U+02A77
eDot; U+02251
eacute; U+000E9
eacute U+000E9
easter; U+02A6E
ecaron; U+0011B
ecir; U+02256
ecirc; U+000EA
ecirc U+000EA
ecolon; U+02255
ecy; U+0044D
edot; U+00117
ee; U+02147
efDot; U+02252
efr; U+1D522
eg; U+02A9A
egrave; U+000E8
egrave U+000E8
egs; U+02A96
egsdot; U+02A98
el; U+02A99
elinters; U+023E7
ell; U+02113
els; U+02A95
elsdot; U+02A97
emacr; U+00113
empty; U+02205
emptyset; U+02205
emptyv; U+02205
emsp13; U+02004
emsp14; U+02005
emsp; U+02003
eng; U+0014B
ensp; U+02002
eogon; U+00119
eopf; U+1D556
epar; U+022D5
eparsl; U+029E3
eplus; U+02A71
epsi; U+003F5
epsilon; U+003B5
epsiv; U+003B5
eqcirc; U+02256
eqcolon; U+02255
eqsim; U+02242
eqslantgtr; U+02A96
eqslantless; U+02A95
equals; U+0003D
equest; U+0225F
equiv; U+02261
equivDD; U+02A78
eqvparsl; U+029E5
erDot; U+02253
erarr; U+02971
escr; U+0212F
esdot; U+02250
esim; U+02242
eta; U+003B7
eth; U+000F0
eth U+000F0
euml; U+000EB
euml U+000EB
euro; U+020AC
excl; U+00021
exist; U+02203
expectation; U+02130
exponentiale; U+02147
fallingdotseq; U+02252
fcy; U+00444
female; U+02640
ffilig; U+0FB03
fflig; U+0FB00
ffllig; U+0FB04
ffr; U+1D523
filig; U+0FB01
flat; U+0266D
fllig; U+0FB02
fltns; U+025B1
fnof; U+00192
fopf; U+1D557
forall; U+02200
fork; U+022D4
forkv; U+02AD9
fpartint; U+02A0D
frac12; U+000BD
frac12 U+000BD
frac13; U+02153
frac14; U+000BC
frac14 U+000BC
frac15; U+02155
frac16; U+02159
frac18; U+0215B
frac23; U+02154
frac25; U+02156
frac34; U+000BE
frac34 U+000BE
frac35; U+02157
frac38; U+0215C
frac45; U+02158
frac56; U+0215A
frac58; U+0215D
frac78; U+0215E
frasl; U+02044
frown; U+02322
fscr; U+1D4BB
gE; U+02267
gEl; U+02A8C
gacute; U+001F5
gamma; U+003B3
gammad; U+003DD
gap; U+02A86
gbreve; U+0011F
gcirc; U+0011D
gcy; U+00433
gdot; U+00121
ge; U+02265
gel; U+022DB
geq; U+02265
geqq; U+02267
geqslant; U+02A7E
ges; U+02A7E
gescc; U+02AA9
gesdot; U+02A80
gesdoto; U+02A82
gesdotol; U+02A84
gesles; U+02A94
gfr; U+1D524
gg; U+0226B
ggg; U+022D9
gimel; U+02137
gjcy; U+00453
gl; U+02277
glE; U+02A92
gla; U+02AA5
glj; U+02AA4
gnE; U+02269
gnap; U+02A8A
gnapprox; U+02A8A
gne; U+02A88
gneq; U+02A88
gneqq; U+02269
gnsim; U+022E7
gopf; U+1D558
grave; U+00060
gscr; U+0210A
gsim; U+02273
gsime; U+02A8E
gsiml; U+02A90
gt; U+0003E
gt U+0003E
gtcc; U+02AA7
gtcir; U+02A7A
gtdot; U+022D7
gtlPar; U+02995
gtquest; U+02A7C
gtrapprox; U+02A86
gtrarr; U+02978
gtrdot; U+022D7
gtreqless; U+022DB
gtreqqless; U+02A8C
gtrless; U+02277
gtrsim; U+02273
hArr; U+021D4
hairsp; U+0200A
half; U+000BD
hamilt; U+0210B
hardcy; U+0044A
harr; U+02194
harrcir; U+02948
harrw; U+021AD
hbar; U+0210F
hcirc; U+00125
hearts; U+02665
heartsuit; U+02665
hellip; U+02026
hercon; U+022B9
hfr; U+1D525
hksearow; U+02925
hkswarow; U+02926
hoarr; U+021FF
homtht; U+0223B
hookleftarrow; U+021A9
hookrightarrow; U+021AA
hopf; U+1D559
horbar; U+02015
hscr; U+1D4BD
hslash; U+0210F
hstrok; U+00127
hybull; U+02043
hyphen; U+02010
iacute; U+000ED
iacute U+000ED
ic; U+02063
icirc; U+000EE
icirc U+000EE
icy; U+00438
iecy; U+00435
iexcl; U+000A1
iexcl U+000A1
iff; U+021D4
ifr; U+1D526
igrave; U+000EC
igrave U+000EC
ii; U+02148
iiiint; U+02A0C
iiint; U+0222D
iinfin; U+029DC
iiota; U+02129
ijlig; U+00133
imacr; U+0012B
image; U+02111
imagline; U+02110
imagpart; U+02111
imath; U+00131
imof; U+022B7
imped; U+001B5
in; U+02208
incare; U+02105
infin; U+0221E
infintie; U+029DD
inodot; U+00131
int; U+0222B
intcal; U+022BA
integers; U+02124
intercal; U+022BA
intlarhk; U+02A17
intprod; U+02A3C
iocy; U+00451
iogon; U+0012F
iopf; U+1D55A
iota; U+003B9
iprod; U+02A3C
iquest; U+000BF
iquest U+000BF
iscr; U+1D4BE
isin; U+02208
isinE; U+022F9
isindot; U+022F5
isins; U+022F4
isinsv; U+022F3
isinv; U+02208
it; U+02062
itilde; U+00129
iukcy; U+00456
iuml; U+000EF
iuml U+000EF
jcirc; U+00135
jcy; U+00439
jfr; U+1D527
jmath; U+00237
jopf; U+1D55B
jscr; U+1D4BF
jsercy; U+00458
jukcy; U+00454
kappa; U+003BA
kappav; U+003F0
kcedil; U+00137
kcy; U+0043A
kfr; U+1D528
kgreen; U+00138
khcy; U+00445
kjcy; U+0045C
kopf; U+1D55C
kscr; U+1D4C0
lAarr; U+021DA
lArr; U+021D0
lAtail; U+0291B
lBarr; U+0290E
lE; U+02266
lEg; U+02A8B
lHar; U+02962
lacute; U+0013A
laemptyv; U+029B4
lagran; U+02112
lambda; U+003BB
lang; U+027E8
langd; U+02991
langle; U+027E8
lap; U+02A85
laquo; U+000AB
laquo U+000AB
larr; U+02190
larrb; U+021E4
larrbfs; U+0291F
larrfs; U+0291D
larrhk; U+021A9
larrlp; U+021AB
larrpl; U+02939
larrsim; U+02973
larrtl; U+021A2
lat; U+02AAB
latail; U+02919
late; U+02AAD
lbarr; U+0290C
lbbrk; U+02772
lbrace; U+0007B
lbrack; U+0005B
lbrke; U+0298B
lbrksld; U+0298F
lbrkslu; U+0298D
lcaron; U+0013E
lcedil; U+0013C
lceil; U+02308
lcub; U+0007B
lcy; U+0043B
ldca; U+02936
ldquo; U+0201C
ldquor; U+0201E
ldrdhar; U+02967
ldrushar; U+0294B
ldsh; U+021B2
le; U+02264
leftarrow; U+02190
leftarrowtail; U+021A2
leftharpoondown; U+021BD
leftharpoonup; U+021BC
leftleftarrows; U+021C7
leftrightarrow; U+02194
leftrightarrows; U+021C6
leftrightharpoons; U+021CB
leftrightsquigarrow; U+021AD
leftthreetimes; U+022CB
leg; U+022DA
leq; U+02264
leqq; U+02266
leqslant; U+02A7D
les; U+02A7D
lescc; U+02AA8
lesdot; U+02A7F
lesdoto; U+02A81
lesdotor; U+02A83
lesges; U+02A93
lessapprox; U+02A85
lessdot; U+022D6
lesseqgtr; U+022DA
lesseqqgtr; U+02A8B
lessgtr; U+02276
lesssim; U+02272
lfisht; U+0297C
lfloor; U+0230A
lfr; U+1D529
lg; U+02276
lgE; U+02A91
lhard; U+021BD
lharu; U+021BC
lharul; U+0296A
lhblk; U+02584
ljcy; U+00459
ll; U+0226A
llarr; U+021C7
llcorner; U+0231E
llhard; U+0296B
lltri; U+025FA
lmidot; U+00140
lmoust; U+023B0
lmoustache; U+023B0
lnE; U+02268
lnap; U+02A89
lnapprox; U+02A89
lne; U+02A87
lneq; U+02A87
lneqq; U+02268
lnsim; U+022E6
loang; U+027EC
loarr; U+021FD
lobrk; U+027E6
longleftarrow; U+027F5
longleftrightarrow; U+027F7
longmapsto; U+027FC
longrightarrow; U+027F6
looparrowleft; U+021AB
looparrowright; U+021AC
lopar; U+02985
lopf; U+1D55D
loplus; U+02A2D
lotimes; U+02A34
lowast; U+02217
lowbar; U+0005F
loz; U+025CA
lozenge; U+025CA
lozf; U+029EB
lpar; U+00028
lparlt; U+02993
lrarr; U+021C6
lrcorner; U+0231F
lrhar; U+021CB
lrhard; U+0296D
lrm; U+0200E
lrtri; U+022BF
lsaquo; U+02039
lscr; U+1D4C1
lsh; U+021B0
lsim; U+02272
lsime; U+02A8D
lsimg; U+02A8F
lsqb; U+0005B
lsquo; U+02018
lsquor; U+0201A
lstrok; U+00142
lt; U+0003C
lt U+0003C
ltcc; U+02AA6
ltcir; U+02A79
ltdot; U+022D6
lthree; U+022CB
ltimes; U+022C9
ltlarr; U+02976
ltquest; U+02A7B
ltrPar; U+02996
ltri; U+025C3
ltrie; U+022B4
ltrif; U+025C2
lurdshar; U+0294A
luruhar; U+02966
mDDot; U+0223A
macr; U+000AF
macr U+000AF
male; U+02642
malt; U+02720
maltese; U+02720
map; U+021A6
mapsto; U+021A6
mapstodown; U+021A7
mapstoleft; U+021A4
mapstoup; U+021A5
marker; U+025AE
mcomma; U+02A29
mcy; U+0043C
mdash; U+02014
measuredangle; U+02221
mfr; U+1D52A
mho; U+02127
micro; U+000B5
micro U+000B5
mid; U+02223
midast; U+0002A
midcir; U+02AF0
middot; U+000B7
middot U+000B7
minus; U+02212
minusb; U+0229F
minusd; U+02238
minusdu; U+02A2A
mlcp; U+02ADB
mldr; U+02026
mnplus; U+02213
models; U+022A7
mopf; U+1D55E
mp; U+02213
mscr; U+1D4C2
mstpos; U+0223E
mu; U+003BC
multimap; U+022B8
mumap; U+022B8
nLeftarrow; U+021CD
nLeftrightarrow; U+021CE
nRightarrow; U+021CF
nVDash; U+022AF
nVdash; U+022AE
nabla; U+02207
nacute; U+00144
nap; U+02249
napos; U+00149
napprox; U+02249
natur; U+0266E
natural; U+0266E
naturals; U+02115
nbsp; U+000A0
nbsp U+000A0
ncap; U+02A43
ncaron; U+00148
ncedil; U+00146
ncong; U+02247
ncup; U+02A42
ncy; U+0043D
ndash; U+02013
ne; U+02260
neArr; U+021D7
nearhk; U+02924
nearr; U+02197
nearrow; U+02197
nequiv; U+02262
nesear; U+02928
nexist; U+02204
nexists; U+02204
nfr; U+1D52B
nge; U+02271
ngeq; U+02271
ngsim; U+02275
ngt; U+0226F
ngtr; U+0226F
nhArr; U+021CE
nharr; U+021AE
nhpar; U+02AF2
ni; U+0220B
nis; U+022FC
nisd; U+022FA
niv; U+0220B
njcy; U+0045A
nlArr; U+021CD
nlarr; U+0219A
nldr; U+02025
nle; U+02270
nleftarrow; U+0219A
nleftrightarrow; U+021AE
nleq; U+02270
nless; U+0226E
nlsim; U+02274
nlt; U+0226E
nltri; U+022EA
nltrie; U+022EC
nmid; U+02224
nopf; U+1D55F
not; U+000AC
not U+000AC
notin; U+02209
notinva; U+02209
notinvb; U+022F7
notinvc; U+022F6
notni; U+0220C
notniva; U+0220C
notnivb; U+022FE
notnivc; U+022FD
npar; U+02226
nparallel; U+02226
npolint; U+02A14
npr; U+02280
nprcue; U+022E0
nprec; U+02280
nrArr; U+021CF
nrarr; U+0219B
nrightarrow; U+0219B
nrtri; U+022EB
nrtrie; U+022ED
nsc; U+02281
nsccue; U+022E1
nscr; U+1D4C3
nshortmid; U+02224
nshortparallel; U+02226
nsim; U+02241
nsime; U+02244
nsimeq; U+02244
nsmid; U+02224
nspar; U+02226
nsqsube; U+022E2
nsqsupe; U+022E3
nsub; U+02284
nsube; U+02288
nsubseteq; U+02288
nsucc; U+02281
nsup; U+02285
nsupe; U+02289
nsupseteq; U+02289
ntgl; U+02279
ntilde; U+000F1
ntilde U+000F1
ntlg; U+02278
ntriangleleft; U+022EA
ntrianglelefteq; U+022EC
ntriangleright; U+022EB
ntrianglerighteq; U+022ED
nu; U+003BD
num; U+00023
numero; U+02116
numsp; U+02007
nvDash; U+022AD
nvHarr; U+02904
nvdash; U+022AC
nvinfin; U+029DE
nvlArr; U+02902
nvrArr; U+02903
nwArr; U+021D6
nwarhk; U+02923
nwarr; U+02196
nwarrow; U+02196
nwnear; U+02927
oS; U+024C8
oacute; U+000F3
oacute U+000F3
oast; U+0229B
ocir; U+0229A
ocirc; U+000F4
ocirc U+000F4
ocy; U+0043E
odash; U+0229D
odblac; U+00151
odiv; U+02A38
odot; U+02299
odsold; U+029BC
oelig; U+00153
ofcir; U+029BF
ofr; U+1D52C
ogon; U+002DB
ograve; U+000F2
ograve U+000F2
ogt; U+029C1
ohbar; U+029B5
ohm; U+02126
oint; U+0222E
olarr; U+021BA
olcir; U+029BE
olcross; U+029BB
oline; U+0203E
olt; U+029C0
omacr; U+0014D
omega; U+003C9
omicron; U+003BF
omid; U+029B6
ominus; U+02296
oopf; U+1D560
opar; U+029B7
operp; U+029B9
oplus; U+02295
or; U+02228
orarr; U+021BB
ord; U+02A5D
order; U+02134
orderof; U+02134
ordf; U+000AA
ordf U+000AA
ordm; U+000BA
ordm U+000BA
origof; U+022B6
oror; U+02A56
orslope; U+02A57
orv; U+02A5B
oscr; U+02134
oslash; U+000F8
oslash U+000F8
osol; U+02298
otilde; U+000F5
otilde U+000F5
otimes; U+02297
otimesas; U+02A36
ouml; U+000F6
ouml U+000F6
ovbar; U+0233D
par; U+02225
para; U+000B6
para U+000B6
parallel; U+02225
parsim; U+02AF3
parsl; U+02AFD
part; U+02202
pcy; U+0043F
percnt; U+00025
period; U+0002E
permil; U+02030
perp; U+022A5
pertenk; U+02031
pfr; U+1D52D
phi; U+003C6
phiv; U+003C6
phmmat; U+02133
phone; U+0260E
pi; U+003C0
pitchfork; U+022D4
piv; U+003D6
planck; U+0210F
planckh; U+0210E
plankv; U+0210F
plus; U+0002B
plusacir; U+02A23
plusb; U+0229E
pluscir; U+02A22
plusdo; U+02214
plusdu; U+02A25
pluse; U+02A72
plusmn; U+000B1
plusmn U+000B1
plussim; U+02A26
plustwo; U+02A27
pm; U+000B1
pointint; U+02A15
popf; U+1D561
pound; U+000A3
pound U+000A3
pr; U+0227A
prE; U+02AB3
prap; U+02AB7
prcue; U+0227C
pre; U+02AAF
prec; U+0227A
precapprox; U+02AB7
preccurlyeq; U+0227C
preceq; U+02AAF
precnapprox; U+02AB9
precneqq; U+02AB5
precnsim; U+022E8
precsim; U+0227E
prime; U+02032
primes; U+02119
prnE; U+02AB5
prnap; U+02AB9
prnsim; U+022E8
prod; U+0220F
profalar; U+0232E
profline; U+02312
profsurf; U+02313
prop; U+0221D
propto; U+0221D
prsim; U+0227E
prurel; U+022B0
pscr; U+1D4C5
psi; U+003C8
puncsp; U+02008
qfr; U+1D52E
qint; U+02A0C
qopf; U+1D562
qprime; U+02057
qscr; U+1D4C6
quaternions; U+0210D
quatint; U+02A16
quest; U+0003F
questeq; U+0225F
quot; U+00022
quot U+00022
rAarr; U+021DB
rArr; U+021D2
rAtail; U+0291C
rBarr; U+0290F
rHar; U+02964
race; U+029DA
racute; U+00155
radic; U+0221A
raemptyv; U+029B3
rang; U+027E9
rangd; U+02992
range; U+029A5
rangle; U+027E9
raquo; U+000BB
raquo U+000BB
rarr; U+02192
rarrap; U+02975
rarrb; U+021E5
rarrbfs; U+02920
rarrc; U+02933
rarrfs; U+0291E
rarrhk; U+021AA
rarrlp; U+021AC
rarrpl; U+02945
rarrsim; U+02974
rarrtl; U+021A3
rarrw; U+0219D
ratail; U+0291A
ratio; U+02236
rationals; U+0211A
rbarr; U+0290D
rbbrk; U+02773
rbrace; U+0007D
rbrack; U+0005D
rbrke; U+0298C
rbrksld; U+0298E
rbrkslu; U+02990
rcaron; U+00159
rcedil; U+00157
rceil; U+02309
rcub; U+0007D
rcy; U+00440
rdca; U+02937
rdldhar; U+02969
rdquo; U+0201D
rdquor; U+0201D
rdsh; U+021B3
real; U+0211C
realine; U+0211B
realpart; U+0211C
reals; U+0211D
rect; U+025AD
reg; U+000AE
reg U+000AE
rfisht; U+0297D
rfloor; U+0230B
rfr; U+1D52F
rhard; U+021C1
rharu; U+021C0
rharul; U+0296C
rho; U+003C1
rhov; U+003F1
rightarrow; U+02192
rightarrowtail; U+021A3
rightharpoondown; U+021C1
rightharpoonup; U+021C0
rightleftarrows; U+021C4
rightleftharpoons; U+021CC
rightrightarrows; U+021C9
rightsquigarrow; U+0219D
rightthreetimes; U+022CC
ring; U+002DA
risingdotseq; U+02253
rlarr; U+021C4
rlhar; U+021CC
rlm; U+0200F
rmoust; U+023B1
rmoustache; U+023B1
rnmid; U+02AEE
roang; U+027ED
roarr; U+021FE
robrk; U+027E7
ropar; U+02986
ropf; U+1D563
roplus; U+02A2E
rotimes; U+02A35
rpar; U+00029
rpargt; U+02994
rppolint; U+02A12
rrarr; U+021C9
rsaquo; U+0203A
rscr; U+1D4C7
rsh; U+021B1
rsqb; U+0005D
rsquo; U+02019
rsquor; U+02019
rthree; U+022CC
rtimes; U+022CA
rtri; U+025B9
rtrie; U+022B5
rtrif; U+025B8
rtriltri; U+029CE
ruluhar; U+02968
rx; U+0211E
sacute; U+0015B
sbquo; U+0201A
sc; U+0227B
scE; U+02AB4
scap; U+02AB8
scaron; U+00161
sccue; U+0227D
sce; U+02AB0
scedil; U+0015F
scirc; U+0015D
scnE; U+02AB6
scnap; U+02ABA
scnsim; U+022E9
scpolint; U+02A13
scsim; U+0227F
scy; U+00441
sdot; U+022C5
sdotb; U+022A1
sdote; U+02A66
seArr; U+021D8
searhk; U+02925
searr; U+02198
searrow; U+02198
sect; U+000A7
sect U+000A7
semi; U+0003B
seswar; U+02929
setminus; U+02216
setmn; U+02216
sext; U+02736
sfr; U+1D530
sfrown; U+02322
sharp; U+0266F
shchcy; U+00449
shcy; U+00448
shortmid; U+02223
shortparallel; U+02225
shy; U+000AD
shy U+000AD
sigma; U+003C3
sigmaf; U+003C2
sigmav; U+003C2
sim; U+0223C
simdot; U+02A6A
sime; U+02243
simeq; U+02243
simg; U+02A9E
simgE; U+02AA0
siml; U+02A9D
simlE; U+02A9F
simne; U+02246
simplus; U+02A24
simrarr; U+02972
slarr; U+02190
smallsetminus; U+02216
smashp; U+02A33
smeparsl; U+029E4
smid; U+02223
smile; U+02323
smt; U+02AAA
smte; U+02AAC
softcy; U+0044C
sol; U+0002F
solb; U+029C4
solbar; U+0233F
sopf; U+1D564
spades; U+02660
spadesuit; U+02660
spar; U+02225
sqcap; U+02293
sqcup; U+02294
sqsub; U+0228F
sqsube; U+02291
sqsubset; U+0228F
sqsubseteq; U+02291
sqsup; U+02290
sqsupe; U+02292
sqsupset; U+02290
sqsupseteq; U+02292
squ; U+025A1
square; U+025A1
squarf; U+025AA
squf; U+025AA
srarr; U+02192
sscr; U+1D4C8
ssetmn; U+02216
ssmile; U+02323
sstarf; U+022C6
star; U+02606
starf; U+02605
straightepsilon; U+003F5
straightphi; U+003D5
strns; U+000AF
sub; U+02282
subE; U+02AC5
subdot; U+02ABD
sube; U+02286
subedot; U+02AC3
submult; U+02AC1
subnE; U+02ACB
subne; U+0228A
subplus; U+02ABF
subrarr; U+02979
subset; U+02282
subseteq; U+02286
subseteqq; U+02AC5
subsetneq; U+0228A
subsetneqq; U+02ACB
subsim; U+02AC7
subsub; U+02AD5
subsup; U+02AD3
succ; U+0227B
succapprox; U+02AB8
succcurlyeq; U+0227D
succeq; U+02AB0
succnapprox; U+02ABA
succneqq; U+02AB6
succnsim; U+022E9
succsim; U+0227F
sum; U+02211
sung; U+0266A
sup1; U+000B9
sup1 U+000B9
sup2; U+000B2
sup2 U+000B2
sup3; U+000B3
sup3 U+000B3
sup; U+02283
supE; U+02AC6
supdot; U+02ABE
supdsub; U+02AD8
supe; U+02287
supedot; U+02AC4
suphsub; U+02AD7
suplarr; U+0297B
supmult; U+02AC2
supnE; U+02ACC
supne; U+0228B
supplus; U+02AC0
supset; U+02283
supseteq; U+02287
supseteqq; U+02AC6
supsetneq; U+0228B
supsetneqq; U+02ACC
supsim; U+02AC8
supsub; U+02AD4
supsup; U+02AD6
swArr; U+021D9
swarhk; U+02926
swarr; U+02199
swarrow; U+02199
swnwar; U+0292A
szlig; U+000DF
szlig U+000DF
target; U+02316
tau; U+003C4
tbrk; U+023B4
tcaron; U+00165
tcedil; U+00163
tcy; U+00442
tdot; U+020DB
telrec; U+02315
tfr; U+1D531
there4; U+02234
therefore; U+02234
theta; U+003B8
thetasym; U+003D1
thetav; U+003D1
thickapprox; U+02248
thicksim; U+0223C
thinsp; U+02009
thkap; U+02248
thksim; U+0223C
thorn; U+000FE
thorn U+000FE
tilde; U+002DC
times; U+000D7
times U+000D7
timesb; U+022A0
timesbar; U+02A31
timesd; U+02A30
tint; U+0222D
toea; U+02928
top; U+022A4
topbot; U+02336
topcir; U+02AF1
topf; U+1D565
topfork; U+02ADA
tosa; U+02929
tprime; U+02034
trade; U+02122
triangle; U+025B5
triangledown; U+025BF
triangleleft; U+025C3
trianglelefteq; U+022B4
triangleq; U+0225C
triangleright; U+025B9
trianglerighteq; U+022B5
tridot; U+025EC
trie; U+0225C
triminus; U+02A3A
triplus; U+02A39
trisb; U+029CD
tritime; U+02A3B
trpezium; U+023E2
tscr; U+1D4C9
tscy; U+00446
tshcy; U+0045B
tstrok; U+00167
twixt; U+0226C
twoheadleftarrow; U+0219E
twoheadrightarrow; U+021A0
uArr; U+021D1
uHar; U+02963
uacute; U+000FA
uacute U+000FA
uarr; U+02191
ubrcy; U+0045E
ubreve; U+0016D
ucirc; U+000FB
ucirc U+000FB
ucy; U+00443
udarr; U+021C5
udblac; U+00171
udhar; U+0296E
ufisht; U+0297E
ufr; U+1D532
ugrave; U+000F9
ugrave U+000F9
uharl; U+021BF
uharr; U+021BE
uhblk; U+02580
ulcorn; U+0231C
ulcorner; U+0231C
ulcrop; U+0230F
ultri; U+025F8
umacr; U+0016B
uml; U+000A8
uml U+000A8
uogon; U+00173
uopf; U+1D566
uparrow; U+02191
updownarrow; U+02195
upharpoonleft; U+021BF
upharpoonright; U+021BE
uplus; U+0228E
upsi; U+003C5
upsih; U+003D2
upsilon; U+003C5
upuparrows; U+021C8
urcorn; U+0231D
urcorner; U+0231D
urcrop; U+0230E
uring; U+0016F
urtri; U+025F9
uscr; U+1D4CA
utdot; U+022F0
utilde; U+00169
utri; U+025B5
utrif; U+025B4
uuarr; U+021C8
uuml; U+000FC
uuml U+000FC
uwangle; U+029A7
vArr; U+021D5
vBar; U+02AE8
vBarv; U+02AE9
vDash; U+022A8
vangrt; U+0299C
varepsilon; U+003B5
varkappa; U+003F0
varnothing; U+02205
varphi; U+003C6
varpi; U+003D6
varpropto; U+0221D
varr; U+02195
varrho; U+003F1
varsigma; U+003C2
vartheta; U+003D1
vartriangleleft; U+022B2
vartriangleright; U+022B3
vcy; U+00432
vdash; U+022A2
vee; U+02228
veebar; U+022BB
veeeq; U+0225A
vellip; U+022EE
verbar; U+0007C
vert; U+0007C
vfr; U+1D533
vltri; U+022B2
vopf; U+1D567
vprop; U+0221D
vrtri; U+022B3
vscr; U+1D4CB
vzigzag; U+0299A
wcirc; U+00175
wedbar; U+02A5F
wedge; U+02227
wedgeq; U+02259
weierp; U+02118
wfr; U+1D534
wopf; U+1D568
wp; U+02118
wr; U+02240
wreath; U+02240
wscr; U+1D4CC
xcap; U+022C2
xcirc; U+025EF
xcup; U+022C3
xdtri; U+025BD
xfr; U+1D535
xhArr; U+027FA
xharr; U+027F7
xi; U+003BE
xlArr; U+027F8
xlarr; U+027F5
xmap; U+027FC
xnis; U+022FB
xodot; U+02A00
xopf; U+1D569
xoplus; U+02A01
xotime; U+02A02
xrArr; U+027F9
xrarr; U+027F6
xscr; U+1D4CD
xsqcup; U+02A06
xuplus; U+02A04
xutri; U+025B3
xvee; U+022C1
xwedge; U+022C0
yacute; U+000FD
yacute U+000FD
yacy; U+0044F
ycirc; U+00177
ycy; U+0044B
yen; U+000A5
yen U+000A5
yfr; U+1D536
yicy; U+00457
yopf; U+1D56A
yscr; U+1D4CE
yucy; U+0044E
yuml; U+000FF
yuml U+000FF
zacute; U+0017A
zcaron; U+0017E
zcy; U+00437
zdot; U+0017C
zeetrf; U+02128
zeta; U+003B6
zfr; U+1D537
zhcy; U+00436
zigrarr; U+021DD
zopf; U+1D56B
zscr; U+1D4CF
zwj; U+0200D
zwnj; U+0200C
\ No newline at end of file + \ No newline at end of file diff --git a/parser/html/nsHtml5AtomList.h b/parser/html/nsHtml5AtomList.h index 1a4080672772..ca090f614dc0 100644 --- a/parser/html/nsHtml5AtomList.h +++ b/parser/html/nsHtml5AtomList.h @@ -2,13 +2,13 @@ HTML5_ATOM(emptystring, "") HTML5_ATOM(title, "title") HTML5_ATOM(textarea, "textarea") HTML5_ATOM(style, "style") -HTML5_ATOM(script, "script") HTML5_ATOM(xmp, "xmp") HTML5_ATOM(iframe, "iframe") HTML5_ATOM(noembed, "noembed") HTML5_ATOM(noframes, "noframes") HTML5_ATOM(noscript, "noscript") HTML5_ATOM(plaintext, "plaintext") +HTML5_ATOM(script, "script") HTML5_ATOM(table, "table") HTML5_ATOM(caption, "caption") HTML5_ATOM(p, "p") diff --git a/parser/html/nsHtml5NamedCharacters.cpp b/parser/html/nsHtml5NamedCharacters.cpp index 8e1a009e02aa..3ac9ef693001 100644 --- a/parser/html/nsHtml5NamedCharacters.cpp +++ b/parser/html/nsHtml5NamedCharacters.cpp @@ -10,7 +10,7 @@ jArray* nsHtml5NamedCharacters::VALUES; PRUnichar** nsHtml5NamedCharacters::WINDOWS_1252; static PRUnichar const WINDOWS_1252_DATA[] = { 0x20AC, - 0xFFFD, + 0x0081, 0x201A, 0x0192, 0x201E, @@ -22,10 +22,10 @@ static PRUnichar const WINDOWS_1252_DATA[] = { 0x0160, 0x2039, 0x0152, - 0xFFFD, + 0x008D, 0x017D, - 0xFFFD, - 0xFFFD, + 0x008F, + 0x0090, 0x2018, 0x2019, 0x201C, @@ -38,7 +38,7 @@ static PRUnichar const WINDOWS_1252_DATA[] = { 0x0161, 0x203A, 0x0153, - 0xFFFD, + 0x009D, 0x017E, 0x0178 }; @@ -61,14 +61,14 @@ static PRUnichar const VALUE_##N[] = { VALUE }; void nsHtml5NamedCharacters::initializeStatics() { - NAMES = jArray,PRInt32>(2137); + NAMES = jArray,PRInt32>(2138); #define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, VALUE, SIZE) \ NAMES[N] = jArray((PRUnichar*)NAME_##N, LEN); #include "nsHtml5NamedCharactersInclude.h" #undef NAMED_CHARACTER_REFERENCE - VALUES = new jArray[2137]; + VALUES = new jArray[2138]; #define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, VALUE, SIZE) \ VALUES[N] = jArray((PRUnichar*)VALUE_##N, SIZE); diff --git a/parser/html/nsHtml5NamedCharactersInclude.h b/parser/html/nsHtml5NamedCharactersInclude.h index 2e8548aaa2a7..13155d15e569 100644 --- a/parser/html/nsHtml5NamedCharactersInclude.h +++ b/parser/html/nsHtml5NamedCharactersInclude.h @@ -413,7 +413,7 @@ NAMED_CHARACTER_REFERENCE(388, 'O' _ 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x00d NAMED_CHARACTER_REFERENCE(389, 'O' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0x2a37, 1) NAMED_CHARACTER_REFERENCE(390, 'O' _ 'u' _ 'm' _ 'l', 4, 0x00d6, 1) NAMED_CHARACTER_REFERENCE(391, 'O' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00d6, 1) -NAMED_CHARACTER_REFERENCE(392, 'O' _ 'v' _ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 8, 0x00af, 1) +NAMED_CHARACTER_REFERENCE(392, 'O' _ 'v' _ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 8, 0x203e, 1) NAMED_CHARACTER_REFERENCE(393, 'O' _ 'v' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 10, 0x23de, 1) NAMED_CHARACTER_REFERENCE(394, 'O' _ 'v' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 12, 0x23b4, 1) NAMED_CHARACTER_REFERENCE(395, 'O' _ 'v' _ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', 16, 0x23dc, 1) @@ -562,7 +562,7 @@ NAMED_CHARACTER_REFERENCE(537, 'U' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd18, 2) NAMED_CHARACTER_REFERENCE(538, 'U' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e', 6, 0x00d9, 1) NAMED_CHARACTER_REFERENCE(539, 'U' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 7, 0x00d9, 1) NAMED_CHARACTER_REFERENCE(540, 'U' _ 'm' _ 'a' _ 'c' _ 'r' _ ';', 6, 0x016a, 1) -NAMED_CHARACTER_REFERENCE(541, 'U' _ 'n' _ 'd' _ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 9, 0x0332, 1) +NAMED_CHARACTER_REFERENCE(541, 'U' _ 'n' _ 'd' _ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 9, 0x005f, 1) NAMED_CHARACTER_REFERENCE(542, 'U' _ 'n' _ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 11, 0x23df, 1) NAMED_CHARACTER_REFERENCE(543, 'U' _ 'n' _ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 13, 0x23b5, 1) NAMED_CHARACTER_REFERENCE(544, 'U' _ 'n' _ 'd' _ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', 17, 0x23dd, 1) @@ -679,7 +679,7 @@ NAMED_CHARACTER_REFERENCE(654, 'a' _ 'n' _ 'g' _ 'r' _ 't' _ ';', 6, 0x221f, 1) NAMED_CHARACTER_REFERENCE(655, 'a' _ 'n' _ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ ';', 8, 0x22be, 1) NAMED_CHARACTER_REFERENCE(656, 'a' _ 'n' _ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ 'd' _ ';', 9, 0x299d, 1) NAMED_CHARACTER_REFERENCE(657, 'a' _ 'n' _ 'g' _ 's' _ 'p' _ 'h' _ ';', 7, 0x2222, 1) -NAMED_CHARACTER_REFERENCE(658, 'a' _ 'n' _ 'g' _ 's' _ 't' _ ';', 6, 0x212b, 1) +NAMED_CHARACTER_REFERENCE(658, 'a' _ 'n' _ 'g' _ 's' _ 't' _ ';', 6, 0x00c5, 1) NAMED_CHARACTER_REFERENCE(659, 'a' _ 'n' _ 'g' _ 'z' _ 'a' _ 'r' _ 'r' _ ';', 8, 0x237c, 1) NAMED_CHARACTER_REFERENCE(660, 'a' _ 'o' _ 'g' _ 'o' _ 'n' _ ';', 6, 0x0105, 1) NAMED_CHARACTER_REFERENCE(661, 'a' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd52, 2) @@ -810,898 +810,898 @@ NAMED_CHARACTER_REFERENCE(785, 'b' _ 's' _ 'i' _ 'm' _ ';', 5, 0x223d, 1) NAMED_CHARACTER_REFERENCE(786, 'b' _ 's' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x22cd, 1) NAMED_CHARACTER_REFERENCE(787, 'b' _ 's' _ 'o' _ 'l' _ ';', 5, 0x005c, 1) NAMED_CHARACTER_REFERENCE(788, 'b' _ 's' _ 'o' _ 'l' _ 'b' _ ';', 6, 0x29c5, 1) -NAMED_CHARACTER_REFERENCE(789, 'b' _ 'u' _ 'l' _ 'l' _ ';', 5, 0x2022, 1) -NAMED_CHARACTER_REFERENCE(790, 'b' _ 'u' _ 'l' _ 'l' _ 'e' _ 't' _ ';', 7, 0x2022, 1) -NAMED_CHARACTER_REFERENCE(791, 'b' _ 'u' _ 'm' _ 'p' _ ';', 5, 0x224e, 1) -NAMED_CHARACTER_REFERENCE(792, 'b' _ 'u' _ 'm' _ 'p' _ 'E' _ ';', 6, 0x2aae, 1) -NAMED_CHARACTER_REFERENCE(793, 'b' _ 'u' _ 'm' _ 'p' _ 'e' _ ';', 6, 0x224f, 1) -NAMED_CHARACTER_REFERENCE(794, 'b' _ 'u' _ 'm' _ 'p' _ 'e' _ 'q' _ ';', 7, 0x224f, 1) -NAMED_CHARACTER_REFERENCE(795, 'c' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x0107, 1) -NAMED_CHARACTER_REFERENCE(796, 'c' _ 'a' _ 'p' _ ';', 4, 0x2229, 1) -NAMED_CHARACTER_REFERENCE(797, 'c' _ 'a' _ 'p' _ 'a' _ 'n' _ 'd' _ ';', 7, 0x2a44, 1) -NAMED_CHARACTER_REFERENCE(798, 'c' _ 'a' _ 'p' _ 'b' _ 'r' _ 'c' _ 'u' _ 'p' _ ';', 9, 0x2a49, 1) -NAMED_CHARACTER_REFERENCE(799, 'c' _ 'a' _ 'p' _ 'c' _ 'a' _ 'p' _ ';', 7, 0x2a4b, 1) -NAMED_CHARACTER_REFERENCE(800, 'c' _ 'a' _ 'p' _ 'c' _ 'u' _ 'p' _ ';', 7, 0x2a47, 1) -NAMED_CHARACTER_REFERENCE(801, 'c' _ 'a' _ 'p' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a40, 1) -NAMED_CHARACTER_REFERENCE(802, 'c' _ 'a' _ 'r' _ 'e' _ 't' _ ';', 6, 0x2041, 1) -NAMED_CHARACTER_REFERENCE(803, 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 6, 0x02c7, 1) -NAMED_CHARACTER_REFERENCE(804, 'c' _ 'c' _ 'a' _ 'p' _ 's' _ ';', 6, 0x2a4d, 1) -NAMED_CHARACTER_REFERENCE(805, 'c' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x010d, 1) -NAMED_CHARACTER_REFERENCE(806, 'c' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l', 6, 0x00e7, 1) -NAMED_CHARACTER_REFERENCE(807, 'c' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 7, 0x00e7, 1) -NAMED_CHARACTER_REFERENCE(808, 'c' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x0109, 1) -NAMED_CHARACTER_REFERENCE(809, 'c' _ 'c' _ 'u' _ 'p' _ 's' _ ';', 6, 0x2a4c, 1) -NAMED_CHARACTER_REFERENCE(810, 'c' _ 'c' _ 'u' _ 'p' _ 's' _ 's' _ 'm' _ ';', 8, 0x2a50, 1) -NAMED_CHARACTER_REFERENCE(811, 'c' _ 'd' _ 'o' _ 't' _ ';', 5, 0x010b, 1) -NAMED_CHARACTER_REFERENCE(812, 'c' _ 'e' _ 'd' _ 'i' _ 'l', 5, 0x00b8, 1) -NAMED_CHARACTER_REFERENCE(813, 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 6, 0x00b8, 1) -NAMED_CHARACTER_REFERENCE(814, 'c' _ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 8, 0x29b2, 1) -NAMED_CHARACTER_REFERENCE(815, 'c' _ 'e' _ 'n' _ 't', 4, 0x00a2, 1) -NAMED_CHARACTER_REFERENCE(816, 'c' _ 'e' _ 'n' _ 't' _ ';', 5, 0x00a2, 1) -NAMED_CHARACTER_REFERENCE(817, 'c' _ 'e' _ 'n' _ 't' _ 'e' _ 'r' _ 'd' _ 'o' _ 't' _ ';', 10, 0x00b7, 1) -NAMED_CHARACTER_REFERENCE(818, 'c' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd20, 2) -NAMED_CHARACTER_REFERENCE(819, 'c' _ 'h' _ 'c' _ 'y' _ ';', 5, 0x0447, 1) -NAMED_CHARACTER_REFERENCE(820, 'c' _ 'h' _ 'e' _ 'c' _ 'k' _ ';', 6, 0x2713, 1) -NAMED_CHARACTER_REFERENCE(821, 'c' _ 'h' _ 'e' _ 'c' _ 'k' _ 'm' _ 'a' _ 'r' _ 'k' _ ';', 10, 0x2713, 1) -NAMED_CHARACTER_REFERENCE(822, 'c' _ 'h' _ 'i' _ ';', 4, 0x03c7, 1) -NAMED_CHARACTER_REFERENCE(823, 'c' _ 'i' _ 'r' _ ';', 4, 0x25cb, 1) -NAMED_CHARACTER_REFERENCE(824, 'c' _ 'i' _ 'r' _ 'E' _ ';', 5, 0x29c3, 1) -NAMED_CHARACTER_REFERENCE(825, 'c' _ 'i' _ 'r' _ 'c' _ ';', 5, 0x02c6, 1) -NAMED_CHARACTER_REFERENCE(826, 'c' _ 'i' _ 'r' _ 'c' _ 'e' _ 'q' _ ';', 7, 0x2257, 1) -NAMED_CHARACTER_REFERENCE(827, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 16, 0x21ba, 1) -NAMED_CHARACTER_REFERENCE(828, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 17, 0x21bb, 1) -NAMED_CHARACTER_REFERENCE(829, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'R' _ ';', 9, 0x00ae, 1) -NAMED_CHARACTER_REFERENCE(830, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'S' _ ';', 9, 0x24c8, 1) -NAMED_CHARACTER_REFERENCE(831, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'a' _ 's' _ 't' _ ';', 11, 0x229b, 1) -NAMED_CHARACTER_REFERENCE(832, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 12, 0x229a, 1) -NAMED_CHARACTER_REFERENCE(833, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 12, 0x229d, 1) -NAMED_CHARACTER_REFERENCE(834, 'c' _ 'i' _ 'r' _ 'e' _ ';', 5, 0x2257, 1) -NAMED_CHARACTER_REFERENCE(835, 'c' _ 'i' _ 'r' _ 'f' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 9, 0x2a10, 1) -NAMED_CHARACTER_REFERENCE(836, 'c' _ 'i' _ 'r' _ 'm' _ 'i' _ 'd' _ ';', 7, 0x2aef, 1) -NAMED_CHARACTER_REFERENCE(837, 'c' _ 'i' _ 'r' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 8, 0x29c2, 1) -NAMED_CHARACTER_REFERENCE(838, 'c' _ 'l' _ 'u' _ 'b' _ 's' _ ';', 6, 0x2663, 1) -NAMED_CHARACTER_REFERENCE(839, 'c' _ 'l' _ 'u' _ 'b' _ 's' _ 'u' _ 'i' _ 't' _ ';', 9, 0x2663, 1) -NAMED_CHARACTER_REFERENCE(840, 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x003a, 1) -NAMED_CHARACTER_REFERENCE(841, 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ 'e' _ ';', 7, 0x2254, 1) -NAMED_CHARACTER_REFERENCE(842, 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ 'e' _ 'q' _ ';', 8, 0x2254, 1) -NAMED_CHARACTER_REFERENCE(843, 'c' _ 'o' _ 'm' _ 'm' _ 'a' _ ';', 6, 0x002c, 1) -NAMED_CHARACTER_REFERENCE(844, 'c' _ 'o' _ 'm' _ 'm' _ 'a' _ 't' _ ';', 7, 0x0040, 1) -NAMED_CHARACTER_REFERENCE(845, 'c' _ 'o' _ 'm' _ 'p' _ ';', 5, 0x2201, 1) -NAMED_CHARACTER_REFERENCE(846, 'c' _ 'o' _ 'm' _ 'p' _ 'f' _ 'n' _ ';', 7, 0x2218, 1) -NAMED_CHARACTER_REFERENCE(847, 'c' _ 'o' _ 'm' _ 'p' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 11, 0x2201, 1) -NAMED_CHARACTER_REFERENCE(848, 'c' _ 'o' _ 'm' _ 'p' _ 'l' _ 'e' _ 'x' _ 'e' _ 's' _ ';', 10, 0x2102, 1) -NAMED_CHARACTER_REFERENCE(849, 'c' _ 'o' _ 'n' _ 'g' _ ';', 5, 0x2245, 1) -NAMED_CHARACTER_REFERENCE(850, 'c' _ 'o' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ ';', 8, 0x2a6d, 1) -NAMED_CHARACTER_REFERENCE(851, 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0x222e, 1) -NAMED_CHARACTER_REFERENCE(852, 'c' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd54, 2) -NAMED_CHARACTER_REFERENCE(853, 'c' _ 'o' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 7, 0x2210, 1) -NAMED_CHARACTER_REFERENCE(854, 'c' _ 'o' _ 'p' _ 'y', 4, 0x00a9, 1) -NAMED_CHARACTER_REFERENCE(855, 'c' _ 'o' _ 'p' _ 'y' _ ';', 5, 0x00a9, 1) -NAMED_CHARACTER_REFERENCE(856, 'c' _ 'o' _ 'p' _ 'y' _ 's' _ 'r' _ ';', 7, 0x2117, 1) -NAMED_CHARACTER_REFERENCE(857, 'c' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21b5, 1) -NAMED_CHARACTER_REFERENCE(858, 'c' _ 'r' _ 'o' _ 's' _ 's' _ ';', 6, 0x2717, 1) -NAMED_CHARACTER_REFERENCE(859, 'c' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcb8, 2) -NAMED_CHARACTER_REFERENCE(860, 'c' _ 's' _ 'u' _ 'b' _ ';', 5, 0x2acf, 1) -NAMED_CHARACTER_REFERENCE(861, 'c' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 6, 0x2ad1, 1) -NAMED_CHARACTER_REFERENCE(862, 'c' _ 's' _ 'u' _ 'p' _ ';', 5, 0x2ad0, 1) -NAMED_CHARACTER_REFERENCE(863, 'c' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 6, 0x2ad2, 1) -NAMED_CHARACTER_REFERENCE(864, 'c' _ 't' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22ef, 1) -NAMED_CHARACTER_REFERENCE(865, 'c' _ 'u' _ 'd' _ 'a' _ 'r' _ 'r' _ 'l' _ ';', 8, 0x2938, 1) -NAMED_CHARACTER_REFERENCE(866, 'c' _ 'u' _ 'd' _ 'a' _ 'r' _ 'r' _ 'r' _ ';', 8, 0x2935, 1) -NAMED_CHARACTER_REFERENCE(867, 'c' _ 'u' _ 'e' _ 'p' _ 'r' _ ';', 6, 0x22de, 1) -NAMED_CHARACTER_REFERENCE(868, 'c' _ 'u' _ 'e' _ 's' _ 'c' _ ';', 6, 0x22df, 1) -NAMED_CHARACTER_REFERENCE(869, 'c' _ 'u' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x21b6, 1) -NAMED_CHARACTER_REFERENCE(870, 'c' _ 'u' _ 'l' _ 'a' _ 'r' _ 'r' _ 'p' _ ';', 8, 0x293d, 1) -NAMED_CHARACTER_REFERENCE(871, 'c' _ 'u' _ 'p' _ ';', 4, 0x222a, 1) -NAMED_CHARACTER_REFERENCE(872, 'c' _ 'u' _ 'p' _ 'b' _ 'r' _ 'c' _ 'a' _ 'p' _ ';', 9, 0x2a48, 1) -NAMED_CHARACTER_REFERENCE(873, 'c' _ 'u' _ 'p' _ 'c' _ 'a' _ 'p' _ ';', 7, 0x2a46, 1) -NAMED_CHARACTER_REFERENCE(874, 'c' _ 'u' _ 'p' _ 'c' _ 'u' _ 'p' _ ';', 7, 0x2a4a, 1) -NAMED_CHARACTER_REFERENCE(875, 'c' _ 'u' _ 'p' _ 'd' _ 'o' _ 't' _ ';', 7, 0x228d, 1) -NAMED_CHARACTER_REFERENCE(876, 'c' _ 'u' _ 'p' _ 'o' _ 'r' _ ';', 6, 0x2a45, 1) -NAMED_CHARACTER_REFERENCE(877, 'c' _ 'u' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x21b7, 1) -NAMED_CHARACTER_REFERENCE(878, 'c' _ 'u' _ 'r' _ 'a' _ 'r' _ 'r' _ 'm' _ ';', 8, 0x293c, 1) -NAMED_CHARACTER_REFERENCE(879, 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 'p' _ 'r' _ 'e' _ 'c' _ ';', 12, 0x22de, 1) -NAMED_CHARACTER_REFERENCE(880, 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 's' _ 'u' _ 'c' _ 'c' _ ';', 12, 0x22df, 1) -NAMED_CHARACTER_REFERENCE(881, 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'v' _ 'e' _ 'e' _ ';', 9, 0x22ce, 1) -NAMED_CHARACTER_REFERENCE(882, 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 11, 0x22cf, 1) -NAMED_CHARACTER_REFERENCE(883, 'c' _ 'u' _ 'r' _ 'r' _ 'e' _ 'n', 6, 0x00a4, 1) -NAMED_CHARACTER_REFERENCE(884, 'c' _ 'u' _ 'r' _ 'r' _ 'e' _ 'n' _ ';', 7, 0x00a4, 1) -NAMED_CHARACTER_REFERENCE(885, 'c' _ 'u' _ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 15, 0x21b6, 1) -NAMED_CHARACTER_REFERENCE(886, 'c' _ 'u' _ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 16, 0x21b7, 1) -NAMED_CHARACTER_REFERENCE(887, 'c' _ 'u' _ 'v' _ 'e' _ 'e' _ ';', 6, 0x22ce, 1) -NAMED_CHARACTER_REFERENCE(888, 'c' _ 'u' _ 'w' _ 'e' _ 'd' _ ';', 6, 0x22cf, 1) -NAMED_CHARACTER_REFERENCE(889, 'c' _ 'w' _ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 9, 0x2232, 1) -NAMED_CHARACTER_REFERENCE(890, 'c' _ 'w' _ 'i' _ 'n' _ 't' _ ';', 6, 0x2231, 1) -NAMED_CHARACTER_REFERENCE(891, 'c' _ 'y' _ 'l' _ 'c' _ 't' _ 'y' _ ';', 7, 0x232d, 1) -NAMED_CHARACTER_REFERENCE(892, 'd' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d3, 1) -NAMED_CHARACTER_REFERENCE(893, 'd' _ 'H' _ 'a' _ 'r' _ ';', 5, 0x2965, 1) -NAMED_CHARACTER_REFERENCE(894, 'd' _ 'a' _ 'g' _ 'g' _ 'e' _ 'r' _ ';', 7, 0x2020, 1) -NAMED_CHARACTER_REFERENCE(895, 'd' _ 'a' _ 'l' _ 'e' _ 't' _ 'h' _ ';', 7, 0x2138, 1) -NAMED_CHARACTER_REFERENCE(896, 'd' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2193, 1) -NAMED_CHARACTER_REFERENCE(897, 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0x2010, 1) -NAMED_CHARACTER_REFERENCE(898, 'd' _ 'a' _ 's' _ 'h' _ 'v' _ ';', 6, 0x22a3, 1) -NAMED_CHARACTER_REFERENCE(899, 'd' _ 'b' _ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x290f, 1) -NAMED_CHARACTER_REFERENCE(900, 'd' _ 'b' _ 'l' _ 'a' _ 'c' _ ';', 6, 0x02dd, 1) -NAMED_CHARACTER_REFERENCE(901, 'd' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x010f, 1) -NAMED_CHARACTER_REFERENCE(902, 'd' _ 'c' _ 'y' _ ';', 4, 0x0434, 1) -NAMED_CHARACTER_REFERENCE(903, 'd' _ 'd' _ ';', 3, 0x2146, 1) -NAMED_CHARACTER_REFERENCE(904, 'd' _ 'd' _ 'a' _ 'g' _ 'g' _ 'e' _ 'r' _ ';', 8, 0x2021, 1) -NAMED_CHARACTER_REFERENCE(905, 'd' _ 'd' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21ca, 1) -NAMED_CHARACTER_REFERENCE(906, 'd' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 8, 0x2a77, 1) -NAMED_CHARACTER_REFERENCE(907, 'd' _ 'e' _ 'g', 3, 0x00b0, 1) -NAMED_CHARACTER_REFERENCE(908, 'd' _ 'e' _ 'g' _ ';', 4, 0x00b0, 1) -NAMED_CHARACTER_REFERENCE(909, 'd' _ 'e' _ 'l' _ 't' _ 'a' _ ';', 6, 0x03b4, 1) -NAMED_CHARACTER_REFERENCE(910, 'd' _ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 8, 0x29b1, 1) -NAMED_CHARACTER_REFERENCE(911, 'd' _ 'f' _ 'i' _ 's' _ 'h' _ 't' _ ';', 7, 0x297f, 1) -NAMED_CHARACTER_REFERENCE(912, 'd' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd21, 2) -NAMED_CHARACTER_REFERENCE(913, 'd' _ 'h' _ 'a' _ 'r' _ 'l' _ ';', 6, 0x21c3, 1) -NAMED_CHARACTER_REFERENCE(914, 'd' _ 'h' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21c2, 1) -NAMED_CHARACTER_REFERENCE(915, 'd' _ 'i' _ 'a' _ 'm' _ ';', 5, 0x22c4, 1) -NAMED_CHARACTER_REFERENCE(916, 'd' _ 'i' _ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 8, 0x22c4, 1) -NAMED_CHARACTER_REFERENCE(917, 'd' _ 'i' _ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ 's' _ 'u' _ 'i' _ 't' _ ';', 12, 0x2666, 1) -NAMED_CHARACTER_REFERENCE(918, 'd' _ 'i' _ 'a' _ 'm' _ 's' _ ';', 6, 0x2666, 1) -NAMED_CHARACTER_REFERENCE(919, 'd' _ 'i' _ 'e' _ ';', 4, 0x00a8, 1) -NAMED_CHARACTER_REFERENCE(920, 'd' _ 'i' _ 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ ';', 8, 0x03dd, 1) -NAMED_CHARACTER_REFERENCE(921, 'd' _ 'i' _ 's' _ 'i' _ 'n' _ ';', 6, 0x22f2, 1) -NAMED_CHARACTER_REFERENCE(922, 'd' _ 'i' _ 'v' _ ';', 4, 0x00f7, 1) -NAMED_CHARACTER_REFERENCE(923, 'd' _ 'i' _ 'v' _ 'i' _ 'd' _ 'e', 6, 0x00f7, 1) -NAMED_CHARACTER_REFERENCE(924, 'd' _ 'i' _ 'v' _ 'i' _ 'd' _ 'e' _ ';', 7, 0x00f7, 1) -NAMED_CHARACTER_REFERENCE(925, 'd' _ 'i' _ 'v' _ 'i' _ 'd' _ 'e' _ 'o' _ 'n' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 14, 0x22c7, 1) -NAMED_CHARACTER_REFERENCE(926, 'd' _ 'i' _ 'v' _ 'o' _ 'n' _ 'x' _ ';', 7, 0x22c7, 1) -NAMED_CHARACTER_REFERENCE(927, 'd' _ 'j' _ 'c' _ 'y' _ ';', 5, 0x0452, 1) -NAMED_CHARACTER_REFERENCE(928, 'd' _ 'l' _ 'c' _ 'o' _ 'r' _ 'n' _ ';', 7, 0x231e, 1) -NAMED_CHARACTER_REFERENCE(929, 'd' _ 'l' _ 'c' _ 'r' _ 'o' _ 'p' _ ';', 7, 0x230d, 1) -NAMED_CHARACTER_REFERENCE(930, 'd' _ 'o' _ 'l' _ 'l' _ 'a' _ 'r' _ ';', 7, 0x0024, 1) -NAMED_CHARACTER_REFERENCE(931, 'd' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd55, 2) -NAMED_CHARACTER_REFERENCE(932, 'd' _ 'o' _ 't' _ ';', 4, 0x02d9, 1) -NAMED_CHARACTER_REFERENCE(933, 'd' _ 'o' _ 't' _ 'e' _ 'q' _ ';', 6, 0x2250, 1) -NAMED_CHARACTER_REFERENCE(934, 'd' _ 'o' _ 't' _ 'e' _ 'q' _ 'd' _ 'o' _ 't' _ ';', 9, 0x2251, 1) -NAMED_CHARACTER_REFERENCE(935, 'd' _ 'o' _ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 9, 0x2238, 1) -NAMED_CHARACTER_REFERENCE(936, 'd' _ 'o' _ 't' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 8, 0x2214, 1) -NAMED_CHARACTER_REFERENCE(937, 'd' _ 'o' _ 't' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 10, 0x22a1, 1) -NAMED_CHARACTER_REFERENCE(938, 'd' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'b' _ 'a' _ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 15, 0x2306, 1) -NAMED_CHARACTER_REFERENCE(939, 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x2193, 1) -NAMED_CHARACTER_REFERENCE(940, 'd' _ 'o' _ 'w' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 15, 0x21ca, 1) -NAMED_CHARACTER_REFERENCE(941, 'd' _ 'o' _ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 16, 0x21c3, 1) -NAMED_CHARACTER_REFERENCE(942, 'd' _ 'o' _ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 17, 0x21c2, 1) -NAMED_CHARACTER_REFERENCE(943, 'd' _ 'r' _ 'b' _ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x2910, 1) -NAMED_CHARACTER_REFERENCE(944, 'd' _ 'r' _ 'c' _ 'o' _ 'r' _ 'n' _ ';', 7, 0x231f, 1) -NAMED_CHARACTER_REFERENCE(945, 'd' _ 'r' _ 'c' _ 'r' _ 'o' _ 'p' _ ';', 7, 0x230c, 1) -NAMED_CHARACTER_REFERENCE(946, 'd' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcb9, 2) -NAMED_CHARACTER_REFERENCE(947, 'd' _ 's' _ 'c' _ 'y' _ ';', 5, 0x0455, 1) -NAMED_CHARACTER_REFERENCE(948, 'd' _ 's' _ 'o' _ 'l' _ ';', 5, 0x29f6, 1) -NAMED_CHARACTER_REFERENCE(949, 'd' _ 's' _ 't' _ 'r' _ 'o' _ 'k' _ ';', 7, 0x0111, 1) -NAMED_CHARACTER_REFERENCE(950, 'd' _ 't' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22f1, 1) -NAMED_CHARACTER_REFERENCE(951, 'd' _ 't' _ 'r' _ 'i' _ ';', 5, 0x25bf, 1) -NAMED_CHARACTER_REFERENCE(952, 'd' _ 't' _ 'r' _ 'i' _ 'f' _ ';', 6, 0x25be, 1) -NAMED_CHARACTER_REFERENCE(953, 'd' _ 'u' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21f5, 1) -NAMED_CHARACTER_REFERENCE(954, 'd' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x296f, 1) -NAMED_CHARACTER_REFERENCE(955, 'd' _ 'w' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 8, 0x29a6, 1) -NAMED_CHARACTER_REFERENCE(956, 'd' _ 'z' _ 'c' _ 'y' _ ';', 5, 0x045f, 1) -NAMED_CHARACTER_REFERENCE(957, 'd' _ 'z' _ 'i' _ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 9, 0x27ff, 1) -NAMED_CHARACTER_REFERENCE(958, 'e' _ 'D' _ 'D' _ 'o' _ 't' _ ';', 6, 0x2a77, 1) -NAMED_CHARACTER_REFERENCE(959, 'e' _ 'D' _ 'o' _ 't' _ ';', 5, 0x2251, 1) -NAMED_CHARACTER_REFERENCE(960, 'e' _ 'a' _ 'c' _ 'u' _ 't' _ 'e', 6, 0x00e9, 1) -NAMED_CHARACTER_REFERENCE(961, 'e' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x00e9, 1) -NAMED_CHARACTER_REFERENCE(962, 'e' _ 'a' _ 's' _ 't' _ 'e' _ 'r' _ ';', 7, 0x2a6e, 1) -NAMED_CHARACTER_REFERENCE(963, 'e' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x011b, 1) -NAMED_CHARACTER_REFERENCE(964, 'e' _ 'c' _ 'i' _ 'r' _ ';', 5, 0x2256, 1) -NAMED_CHARACTER_REFERENCE(965, 'e' _ 'c' _ 'i' _ 'r' _ 'c', 5, 0x00ea, 1) -NAMED_CHARACTER_REFERENCE(966, 'e' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x00ea, 1) -NAMED_CHARACTER_REFERENCE(967, 'e' _ 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 7, 0x2255, 1) -NAMED_CHARACTER_REFERENCE(968, 'e' _ 'c' _ 'y' _ ';', 4, 0x044d, 1) -NAMED_CHARACTER_REFERENCE(969, 'e' _ 'd' _ 'o' _ 't' _ ';', 5, 0x0117, 1) -NAMED_CHARACTER_REFERENCE(970, 'e' _ 'e' _ ';', 3, 0x2147, 1) -NAMED_CHARACTER_REFERENCE(971, 'e' _ 'f' _ 'D' _ 'o' _ 't' _ ';', 6, 0x2252, 1) -NAMED_CHARACTER_REFERENCE(972, 'e' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd22, 2) -NAMED_CHARACTER_REFERENCE(973, 'e' _ 'g' _ ';', 3, 0x2a9a, 1) -NAMED_CHARACTER_REFERENCE(974, 'e' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e', 6, 0x00e8, 1) -NAMED_CHARACTER_REFERENCE(975, 'e' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 7, 0x00e8, 1) -NAMED_CHARACTER_REFERENCE(976, 'e' _ 'g' _ 's' _ ';', 4, 0x2a96, 1) -NAMED_CHARACTER_REFERENCE(977, 'e' _ 'g' _ 's' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a98, 1) -NAMED_CHARACTER_REFERENCE(978, 'e' _ 'l' _ ';', 3, 0x2a99, 1) -NAMED_CHARACTER_REFERENCE(979, 'e' _ 'l' _ 'i' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ ';', 9, 0x23e7, 1) -NAMED_CHARACTER_REFERENCE(980, 'e' _ 'l' _ 'l' _ ';', 4, 0x2113, 1) -NAMED_CHARACTER_REFERENCE(981, 'e' _ 'l' _ 's' _ ';', 4, 0x2a95, 1) -NAMED_CHARACTER_REFERENCE(982, 'e' _ 'l' _ 's' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a97, 1) -NAMED_CHARACTER_REFERENCE(983, 'e' _ 'm' _ 'a' _ 'c' _ 'r' _ ';', 6, 0x0113, 1) -NAMED_CHARACTER_REFERENCE(984, 'e' _ 'm' _ 'p' _ 't' _ 'y' _ ';', 6, 0x2205, 1) -NAMED_CHARACTER_REFERENCE(985, 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 's' _ 'e' _ 't' _ ';', 9, 0x2205, 1) -NAMED_CHARACTER_REFERENCE(986, 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, 0x2205, 1) -NAMED_CHARACTER_REFERENCE(987, 'e' _ 'm' _ 's' _ 'p' _ '1' _ '3' _ ';', 7, 0x2004, 1) -NAMED_CHARACTER_REFERENCE(988, 'e' _ 'm' _ 's' _ 'p' _ '1' _ '4' _ ';', 7, 0x2005, 1) -NAMED_CHARACTER_REFERENCE(989, 'e' _ 'm' _ 's' _ 'p' _ ';', 5, 0x2003, 1) -NAMED_CHARACTER_REFERENCE(990, 'e' _ 'n' _ 'g' _ ';', 4, 0x014b, 1) -NAMED_CHARACTER_REFERENCE(991, 'e' _ 'n' _ 's' _ 'p' _ ';', 5, 0x2002, 1) -NAMED_CHARACTER_REFERENCE(992, 'e' _ 'o' _ 'g' _ 'o' _ 'n' _ ';', 6, 0x0119, 1) -NAMED_CHARACTER_REFERENCE(993, 'e' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd56, 2) -NAMED_CHARACTER_REFERENCE(994, 'e' _ 'p' _ 'a' _ 'r' _ ';', 5, 0x22d5, 1) -NAMED_CHARACTER_REFERENCE(995, 'e' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, 0x29e3, 1) -NAMED_CHARACTER_REFERENCE(996, 'e' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2a71, 1) -NAMED_CHARACTER_REFERENCE(997, 'e' _ 'p' _ 's' _ 'i' _ ';', 5, 0x03f5, 1) -NAMED_CHARACTER_REFERENCE(998, 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 8, 0x03b5, 1) -NAMED_CHARACTER_REFERENCE(999, 'e' _ 'p' _ 's' _ 'i' _ 'v' _ ';', 6, 0x03b5, 1) -NAMED_CHARACTER_REFERENCE(1000, 'e' _ 'q' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 7, 0x2256, 1) -NAMED_CHARACTER_REFERENCE(1001, 'e' _ 'q' _ 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 8, 0x2255, 1) -NAMED_CHARACTER_REFERENCE(1002, 'e' _ 'q' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2242, 1) -NAMED_CHARACTER_REFERENCE(1003, 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'g' _ 't' _ 'r' _ ';', 11, 0x2a96, 1) -NAMED_CHARACTER_REFERENCE(1004, 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'l' _ 'e' _ 's' _ 's' _ ';', 12, 0x2a95, 1) -NAMED_CHARACTER_REFERENCE(1005, 'e' _ 'q' _ 'u' _ 'a' _ 'l' _ 's' _ ';', 7, 0x003d, 1) -NAMED_CHARACTER_REFERENCE(1006, 'e' _ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 7, 0x225f, 1) -NAMED_CHARACTER_REFERENCE(1007, 'e' _ 'q' _ 'u' _ 'i' _ 'v' _ ';', 6, 0x2261, 1) -NAMED_CHARACTER_REFERENCE(1008, 'e' _ 'q' _ 'u' _ 'i' _ 'v' _ 'D' _ 'D' _ ';', 8, 0x2a78, 1) -NAMED_CHARACTER_REFERENCE(1009, 'e' _ 'q' _ 'v' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 9, 0x29e5, 1) -NAMED_CHARACTER_REFERENCE(1010, 'e' _ 'r' _ 'D' _ 'o' _ 't' _ ';', 6, 0x2253, 1) -NAMED_CHARACTER_REFERENCE(1011, 'e' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2971, 1) -NAMED_CHARACTER_REFERENCE(1012, 'e' _ 's' _ 'c' _ 'r' _ ';', 5, 0x212f, 1) -NAMED_CHARACTER_REFERENCE(1013, 'e' _ 's' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2250, 1) -NAMED_CHARACTER_REFERENCE(1014, 'e' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2242, 1) -NAMED_CHARACTER_REFERENCE(1015, 'e' _ 't' _ 'a' _ ';', 4, 0x03b7, 1) -NAMED_CHARACTER_REFERENCE(1016, 'e' _ 't' _ 'h', 3, 0x00f0, 1) -NAMED_CHARACTER_REFERENCE(1017, 'e' _ 't' _ 'h' _ ';', 4, 0x00f0, 1) -NAMED_CHARACTER_REFERENCE(1018, 'e' _ 'u' _ 'm' _ 'l', 4, 0x00eb, 1) -NAMED_CHARACTER_REFERENCE(1019, 'e' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00eb, 1) -NAMED_CHARACTER_REFERENCE(1020, 'e' _ 'u' _ 'r' _ 'o' _ ';', 5, 0x20ac, 1) -NAMED_CHARACTER_REFERENCE(1021, 'e' _ 'x' _ 'c' _ 'l' _ ';', 5, 0x0021, 1) -NAMED_CHARACTER_REFERENCE(1022, 'e' _ 'x' _ 'i' _ 's' _ 't' _ ';', 6, 0x2203, 1) -NAMED_CHARACTER_REFERENCE(1023, 'e' _ 'x' _ 'p' _ 'e' _ 'c' _ 't' _ 'a' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 12, 0x2130, 1) -NAMED_CHARACTER_REFERENCE(1024, 'e' _ 'x' _ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'e' _ ';', 13, 0x2147, 1) -NAMED_CHARACTER_REFERENCE(1025, 'f' _ 'a' _ 'l' _ 'l' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 14, 0x2252, 1) -NAMED_CHARACTER_REFERENCE(1026, 'f' _ 'c' _ 'y' _ ';', 4, 0x0444, 1) -NAMED_CHARACTER_REFERENCE(1027, 'f' _ 'e' _ 'm' _ 'a' _ 'l' _ 'e' _ ';', 7, 0x2640, 1) -NAMED_CHARACTER_REFERENCE(1028, 'f' _ 'f' _ 'i' _ 'l' _ 'i' _ 'g' _ ';', 7, 0xfb03, 1) -NAMED_CHARACTER_REFERENCE(1029, 'f' _ 'f' _ 'l' _ 'i' _ 'g' _ ';', 6, 0xfb00, 1) -NAMED_CHARACTER_REFERENCE(1030, 'f' _ 'f' _ 'l' _ 'l' _ 'i' _ 'g' _ ';', 7, 0xfb04, 1) -NAMED_CHARACTER_REFERENCE(1031, 'f' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd23, 2) -NAMED_CHARACTER_REFERENCE(1032, 'f' _ 'i' _ 'l' _ 'i' _ 'g' _ ';', 6, 0xfb01, 1) -NAMED_CHARACTER_REFERENCE(1033, 'f' _ 'l' _ 'a' _ 't' _ ';', 5, 0x266d, 1) -NAMED_CHARACTER_REFERENCE(1034, 'f' _ 'l' _ 'l' _ 'i' _ 'g' _ ';', 6, 0xfb02, 1) -NAMED_CHARACTER_REFERENCE(1035, 'f' _ 'l' _ 't' _ 'n' _ 's' _ ';', 6, 0x25b1, 1) -NAMED_CHARACTER_REFERENCE(1036, 'f' _ 'n' _ 'o' _ 'f' _ ';', 5, 0x0192, 1) -NAMED_CHARACTER_REFERENCE(1037, 'f' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd57, 2) -NAMED_CHARACTER_REFERENCE(1038, 'f' _ 'o' _ 'r' _ 'a' _ 'l' _ 'l' _ ';', 7, 0x2200, 1) -NAMED_CHARACTER_REFERENCE(1039, 'f' _ 'o' _ 'r' _ 'k' _ ';', 5, 0x22d4, 1) -NAMED_CHARACTER_REFERENCE(1040, 'f' _ 'o' _ 'r' _ 'k' _ 'v' _ ';', 6, 0x2ad9, 1) -NAMED_CHARACTER_REFERENCE(1041, 'f' _ 'p' _ 'a' _ 'r' _ 't' _ 'i' _ 'n' _ 't' _ ';', 9, 0x2a0d, 1) -NAMED_CHARACTER_REFERENCE(1042, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '2', 6, 0x00bd, 1) -NAMED_CHARACTER_REFERENCE(1043, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '2' _ ';', 7, 0x00bd, 1) -NAMED_CHARACTER_REFERENCE(1044, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '3' _ ';', 7, 0x2153, 1) -NAMED_CHARACTER_REFERENCE(1045, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '4', 6, 0x00bc, 1) -NAMED_CHARACTER_REFERENCE(1046, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '4' _ ';', 7, 0x00bc, 1) -NAMED_CHARACTER_REFERENCE(1047, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '5' _ ';', 7, 0x2155, 1) -NAMED_CHARACTER_REFERENCE(1048, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '6' _ ';', 7, 0x2159, 1) -NAMED_CHARACTER_REFERENCE(1049, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '8' _ ';', 7, 0x215b, 1) -NAMED_CHARACTER_REFERENCE(1050, 'f' _ 'r' _ 'a' _ 'c' _ '2' _ '3' _ ';', 7, 0x2154, 1) -NAMED_CHARACTER_REFERENCE(1051, 'f' _ 'r' _ 'a' _ 'c' _ '2' _ '5' _ ';', 7, 0x2156, 1) -NAMED_CHARACTER_REFERENCE(1052, 'f' _ 'r' _ 'a' _ 'c' _ '3' _ '4', 6, 0x00be, 1) -NAMED_CHARACTER_REFERENCE(1053, 'f' _ 'r' _ 'a' _ 'c' _ '3' _ '4' _ ';', 7, 0x00be, 1) -NAMED_CHARACTER_REFERENCE(1054, 'f' _ 'r' _ 'a' _ 'c' _ '3' _ '5' _ ';', 7, 0x2157, 1) -NAMED_CHARACTER_REFERENCE(1055, 'f' _ 'r' _ 'a' _ 'c' _ '3' _ '8' _ ';', 7, 0x215c, 1) -NAMED_CHARACTER_REFERENCE(1056, 'f' _ 'r' _ 'a' _ 'c' _ '4' _ '5' _ ';', 7, 0x2158, 1) -NAMED_CHARACTER_REFERENCE(1057, 'f' _ 'r' _ 'a' _ 'c' _ '5' _ '6' _ ';', 7, 0x215a, 1) -NAMED_CHARACTER_REFERENCE(1058, 'f' _ 'r' _ 'a' _ 'c' _ '5' _ '8' _ ';', 7, 0x215d, 1) -NAMED_CHARACTER_REFERENCE(1059, 'f' _ 'r' _ 'a' _ 'c' _ '7' _ '8' _ ';', 7, 0x215e, 1) -NAMED_CHARACTER_REFERENCE(1060, 'f' _ 'r' _ 'a' _ 's' _ 'l' _ ';', 6, 0x2044, 1) -NAMED_CHARACTER_REFERENCE(1061, 'f' _ 'r' _ 'o' _ 'w' _ 'n' _ ';', 6, 0x2322, 1) -NAMED_CHARACTER_REFERENCE(1062, 'f' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcbb, 2) -NAMED_CHARACTER_REFERENCE(1063, 'g' _ 'E' _ ';', 3, 0x2267, 1) -NAMED_CHARACTER_REFERENCE(1064, 'g' _ 'E' _ 'l' _ ';', 4, 0x2a8c, 1) -NAMED_CHARACTER_REFERENCE(1065, 'g' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x01f5, 1) -NAMED_CHARACTER_REFERENCE(1066, 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ ';', 6, 0x03b3, 1) -NAMED_CHARACTER_REFERENCE(1067, 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ 'd' _ ';', 7, 0x03dd, 1) -NAMED_CHARACTER_REFERENCE(1068, 'g' _ 'a' _ 'p' _ ';', 4, 0x2a86, 1) -NAMED_CHARACTER_REFERENCE(1069, 'g' _ 'b' _ 'r' _ 'e' _ 'v' _ 'e' _ ';', 7, 0x011f, 1) -NAMED_CHARACTER_REFERENCE(1070, 'g' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x011d, 1) -NAMED_CHARACTER_REFERENCE(1071, 'g' _ 'c' _ 'y' _ ';', 4, 0x0433, 1) -NAMED_CHARACTER_REFERENCE(1072, 'g' _ 'd' _ 'o' _ 't' _ ';', 5, 0x0121, 1) -NAMED_CHARACTER_REFERENCE(1073, 'g' _ 'e' _ ';', 3, 0x2265, 1) -NAMED_CHARACTER_REFERENCE(1074, 'g' _ 'e' _ 'l' _ ';', 4, 0x22db, 1) -NAMED_CHARACTER_REFERENCE(1075, 'g' _ 'e' _ 'q' _ ';', 4, 0x2265, 1) -NAMED_CHARACTER_REFERENCE(1076, 'g' _ 'e' _ 'q' _ 'q' _ ';', 5, 0x2267, 1) -NAMED_CHARACTER_REFERENCE(1077, 'g' _ 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 9, 0x2a7e, 1) -NAMED_CHARACTER_REFERENCE(1078, 'g' _ 'e' _ 's' _ ';', 4, 0x2a7e, 1) -NAMED_CHARACTER_REFERENCE(1079, 'g' _ 'e' _ 's' _ 'c' _ 'c' _ ';', 6, 0x2aa9, 1) -NAMED_CHARACTER_REFERENCE(1080, 'g' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a80, 1) -NAMED_CHARACTER_REFERENCE(1081, 'g' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 8, 0x2a82, 1) -NAMED_CHARACTER_REFERENCE(1082, 'g' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'l' _ ';', 9, 0x2a84, 1) -NAMED_CHARACTER_REFERENCE(1083, 'g' _ 'e' _ 's' _ 'l' _ 'e' _ 's' _ ';', 7, 0x2a94, 1) -NAMED_CHARACTER_REFERENCE(1084, 'g' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd24, 2) -NAMED_CHARACTER_REFERENCE(1085, 'g' _ 'g' _ ';', 3, 0x226b, 1) -NAMED_CHARACTER_REFERENCE(1086, 'g' _ 'g' _ 'g' _ ';', 4, 0x22d9, 1) -NAMED_CHARACTER_REFERENCE(1087, 'g' _ 'i' _ 'm' _ 'e' _ 'l' _ ';', 6, 0x2137, 1) -NAMED_CHARACTER_REFERENCE(1088, 'g' _ 'j' _ 'c' _ 'y' _ ';', 5, 0x0453, 1) -NAMED_CHARACTER_REFERENCE(1089, 'g' _ 'l' _ ';', 3, 0x2277, 1) -NAMED_CHARACTER_REFERENCE(1090, 'g' _ 'l' _ 'E' _ ';', 4, 0x2a92, 1) -NAMED_CHARACTER_REFERENCE(1091, 'g' _ 'l' _ 'a' _ ';', 4, 0x2aa5, 1) -NAMED_CHARACTER_REFERENCE(1092, 'g' _ 'l' _ 'j' _ ';', 4, 0x2aa4, 1) -NAMED_CHARACTER_REFERENCE(1093, 'g' _ 'n' _ 'E' _ ';', 4, 0x2269, 1) -NAMED_CHARACTER_REFERENCE(1094, 'g' _ 'n' _ 'a' _ 'p' _ ';', 5, 0x2a8a, 1) -NAMED_CHARACTER_REFERENCE(1095, 'g' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0x2a8a, 1) -NAMED_CHARACTER_REFERENCE(1096, 'g' _ 'n' _ 'e' _ ';', 4, 0x2a88, 1) -NAMED_CHARACTER_REFERENCE(1097, 'g' _ 'n' _ 'e' _ 'q' _ ';', 5, 0x2a88, 1) -NAMED_CHARACTER_REFERENCE(1098, 'g' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 6, 0x2269, 1) -NAMED_CHARACTER_REFERENCE(1099, 'g' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 6, 0x22e7, 1) -NAMED_CHARACTER_REFERENCE(1100, 'g' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd58, 2) -NAMED_CHARACTER_REFERENCE(1101, 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 6, 0x0060, 1) -NAMED_CHARACTER_REFERENCE(1102, 'g' _ 's' _ 'c' _ 'r' _ ';', 5, 0x210a, 1) -NAMED_CHARACTER_REFERENCE(1103, 'g' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2273, 1) -NAMED_CHARACTER_REFERENCE(1104, 'g' _ 's' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x2a8e, 1) -NAMED_CHARACTER_REFERENCE(1105, 'g' _ 's' _ 'i' _ 'm' _ 'l' _ ';', 6, 0x2a90, 1) -NAMED_CHARACTER_REFERENCE(1106, 'g' _ 't', 2, 0x003e, 1) -NAMED_CHARACTER_REFERENCE(1107, 'g' _ 't' _ ';', 3, 0x003e, 1) -NAMED_CHARACTER_REFERENCE(1108, 'g' _ 't' _ 'c' _ 'c' _ ';', 5, 0x2aa7, 1) -NAMED_CHARACTER_REFERENCE(1109, 'g' _ 't' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x2a7a, 1) -NAMED_CHARACTER_REFERENCE(1110, 'g' _ 't' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22d7, 1) -NAMED_CHARACTER_REFERENCE(1111, 'g' _ 't' _ 'l' _ 'P' _ 'a' _ 'r' _ ';', 7, 0x2995, 1) -NAMED_CHARACTER_REFERENCE(1112, 'g' _ 't' _ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 8, 0x2a7c, 1) -NAMED_CHARACTER_REFERENCE(1113, 'g' _ 't' _ 'r' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0x2a86, 1) -NAMED_CHARACTER_REFERENCE(1114, 'g' _ 't' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x2978, 1) -NAMED_CHARACTER_REFERENCE(1115, 'g' _ 't' _ 'r' _ 'd' _ 'o' _ 't' _ ';', 7, 0x22d7, 1) -NAMED_CHARACTER_REFERENCE(1116, 'g' _ 't' _ 'r' _ 'e' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 10, 0x22db, 1) -NAMED_CHARACTER_REFERENCE(1117, 'g' _ 't' _ 'r' _ 'e' _ 'q' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 11, 0x2a8c, 1) -NAMED_CHARACTER_REFERENCE(1118, 'g' _ 't' _ 'r' _ 'l' _ 'e' _ 's' _ 's' _ ';', 8, 0x2277, 1) -NAMED_CHARACTER_REFERENCE(1119, 'g' _ 't' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 7, 0x2273, 1) -NAMED_CHARACTER_REFERENCE(1120, 'h' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d4, 1) -NAMED_CHARACTER_REFERENCE(1121, 'h' _ 'a' _ 'i' _ 'r' _ 's' _ 'p' _ ';', 7, 0x200a, 1) -NAMED_CHARACTER_REFERENCE(1122, 'h' _ 'a' _ 'l' _ 'f' _ ';', 5, 0x00bd, 1) -NAMED_CHARACTER_REFERENCE(1123, 'h' _ 'a' _ 'm' _ 'i' _ 'l' _ 't' _ ';', 7, 0x210b, 1) -NAMED_CHARACTER_REFERENCE(1124, 'h' _ 'a' _ 'r' _ 'd' _ 'c' _ 'y' _ ';', 7, 0x044a, 1) -NAMED_CHARACTER_REFERENCE(1125, 'h' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2194, 1) -NAMED_CHARACTER_REFERENCE(1126, 'h' _ 'a' _ 'r' _ 'r' _ 'c' _ 'i' _ 'r' _ ';', 8, 0x2948, 1) -NAMED_CHARACTER_REFERENCE(1127, 'h' _ 'a' _ 'r' _ 'r' _ 'w' _ ';', 6, 0x21ad, 1) -NAMED_CHARACTER_REFERENCE(1128, 'h' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x210f, 1) -NAMED_CHARACTER_REFERENCE(1129, 'h' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x0125, 1) -NAMED_CHARACTER_REFERENCE(1130, 'h' _ 'e' _ 'a' _ 'r' _ 't' _ 's' _ ';', 7, 0x2665, 1) -NAMED_CHARACTER_REFERENCE(1131, 'h' _ 'e' _ 'a' _ 'r' _ 't' _ 's' _ 'u' _ 'i' _ 't' _ ';', 10, 0x2665, 1) -NAMED_CHARACTER_REFERENCE(1132, 'h' _ 'e' _ 'l' _ 'l' _ 'i' _ 'p' _ ';', 7, 0x2026, 1) -NAMED_CHARACTER_REFERENCE(1133, 'h' _ 'e' _ 'r' _ 'c' _ 'o' _ 'n' _ ';', 7, 0x22b9, 1) -NAMED_CHARACTER_REFERENCE(1134, 'h' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd25, 2) -NAMED_CHARACTER_REFERENCE(1135, 'h' _ 'k' _ 's' _ 'e' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x2925, 1) -NAMED_CHARACTER_REFERENCE(1136, 'h' _ 'k' _ 's' _ 'w' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x2926, 1) -NAMED_CHARACTER_REFERENCE(1137, 'h' _ 'o' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21ff, 1) -NAMED_CHARACTER_REFERENCE(1138, 'h' _ 'o' _ 'm' _ 't' _ 'h' _ 't' _ ';', 7, 0x223b, 1) -NAMED_CHARACTER_REFERENCE(1139, 'h' _ 'o' _ 'o' _ 'k' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x21a9, 1) -NAMED_CHARACTER_REFERENCE(1140, 'h' _ 'o' _ 'o' _ 'k' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x21aa, 1) -NAMED_CHARACTER_REFERENCE(1141, 'h' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd59, 2) -NAMED_CHARACTER_REFERENCE(1142, 'h' _ 'o' _ 'r' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x2015, 1) -NAMED_CHARACTER_REFERENCE(1143, 'h' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcbd, 2) -NAMED_CHARACTER_REFERENCE(1144, 'h' _ 's' _ 'l' _ 'a' _ 's' _ 'h' _ ';', 7, 0x210f, 1) -NAMED_CHARACTER_REFERENCE(1145, 'h' _ 's' _ 't' _ 'r' _ 'o' _ 'k' _ ';', 7, 0x0127, 1) -NAMED_CHARACTER_REFERENCE(1146, 'h' _ 'y' _ 'b' _ 'u' _ 'l' _ 'l' _ ';', 7, 0x2043, 1) -NAMED_CHARACTER_REFERENCE(1147, 'h' _ 'y' _ 'p' _ 'h' _ 'e' _ 'n' _ ';', 7, 0x2010, 1) -NAMED_CHARACTER_REFERENCE(1148, 'i' _ 'a' _ 'c' _ 'u' _ 't' _ 'e', 6, 0x00ed, 1) -NAMED_CHARACTER_REFERENCE(1149, 'i' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x00ed, 1) -NAMED_CHARACTER_REFERENCE(1150, 'i' _ 'c' _ ';', 3, 0x2063, 1) -NAMED_CHARACTER_REFERENCE(1151, 'i' _ 'c' _ 'i' _ 'r' _ 'c', 5, 0x00ee, 1) -NAMED_CHARACTER_REFERENCE(1152, 'i' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x00ee, 1) -NAMED_CHARACTER_REFERENCE(1153, 'i' _ 'c' _ 'y' _ ';', 4, 0x0438, 1) -NAMED_CHARACTER_REFERENCE(1154, 'i' _ 'e' _ 'c' _ 'y' _ ';', 5, 0x0435, 1) -NAMED_CHARACTER_REFERENCE(1155, 'i' _ 'e' _ 'x' _ 'c' _ 'l', 5, 0x00a1, 1) -NAMED_CHARACTER_REFERENCE(1156, 'i' _ 'e' _ 'x' _ 'c' _ 'l' _ ';', 6, 0x00a1, 1) -NAMED_CHARACTER_REFERENCE(1157, 'i' _ 'f' _ 'f' _ ';', 4, 0x21d4, 1) -NAMED_CHARACTER_REFERENCE(1158, 'i' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd26, 2) -NAMED_CHARACTER_REFERENCE(1159, 'i' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e', 6, 0x00ec, 1) -NAMED_CHARACTER_REFERENCE(1160, 'i' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 7, 0x00ec, 1) -NAMED_CHARACTER_REFERENCE(1161, 'i' _ 'i' _ ';', 3, 0x2148, 1) -NAMED_CHARACTER_REFERENCE(1162, 'i' _ 'i' _ 'i' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a0c, 1) -NAMED_CHARACTER_REFERENCE(1163, 'i' _ 'i' _ 'i' _ 'n' _ 't' _ ';', 6, 0x222d, 1) -NAMED_CHARACTER_REFERENCE(1164, 'i' _ 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 7, 0x29dc, 1) -NAMED_CHARACTER_REFERENCE(1165, 'i' _ 'i' _ 'o' _ 't' _ 'a' _ ';', 6, 0x2129, 1) -NAMED_CHARACTER_REFERENCE(1166, 'i' _ 'j' _ 'l' _ 'i' _ 'g' _ ';', 6, 0x0133, 1) -NAMED_CHARACTER_REFERENCE(1167, 'i' _ 'm' _ 'a' _ 'c' _ 'r' _ ';', 6, 0x012b, 1) -NAMED_CHARACTER_REFERENCE(1168, 'i' _ 'm' _ 'a' _ 'g' _ 'e' _ ';', 6, 0x2111, 1) -NAMED_CHARACTER_REFERENCE(1169, 'i' _ 'm' _ 'a' _ 'g' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 9, 0x2110, 1) -NAMED_CHARACTER_REFERENCE(1170, 'i' _ 'm' _ 'a' _ 'g' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 9, 0x2111, 1) -NAMED_CHARACTER_REFERENCE(1171, 'i' _ 'm' _ 'a' _ 't' _ 'h' _ ';', 6, 0x0131, 1) -NAMED_CHARACTER_REFERENCE(1172, 'i' _ 'm' _ 'o' _ 'f' _ ';', 5, 0x22b7, 1) -NAMED_CHARACTER_REFERENCE(1173, 'i' _ 'm' _ 'p' _ 'e' _ 'd' _ ';', 6, 0x01b5, 1) -NAMED_CHARACTER_REFERENCE(1174, 'i' _ 'n' _ ';', 3, 0x2208, 1) -NAMED_CHARACTER_REFERENCE(1175, 'i' _ 'n' _ 'c' _ 'a' _ 'r' _ 'e' _ ';', 7, 0x2105, 1) -NAMED_CHARACTER_REFERENCE(1176, 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 6, 0x221e, 1) -NAMED_CHARACTER_REFERENCE(1177, 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ 't' _ 'i' _ 'e' _ ';', 9, 0x29dd, 1) -NAMED_CHARACTER_REFERENCE(1178, 'i' _ 'n' _ 'o' _ 'd' _ 'o' _ 't' _ ';', 7, 0x0131, 1) -NAMED_CHARACTER_REFERENCE(1179, 'i' _ 'n' _ 't' _ ';', 4, 0x222b, 1) -NAMED_CHARACTER_REFERENCE(1180, 'i' _ 'n' _ 't' _ 'c' _ 'a' _ 'l' _ ';', 7, 0x22ba, 1) -NAMED_CHARACTER_REFERENCE(1181, 'i' _ 'n' _ 't' _ 'e' _ 'g' _ 'e' _ 'r' _ 's' _ ';', 9, 0x2124, 1) -NAMED_CHARACTER_REFERENCE(1182, 'i' _ 'n' _ 't' _ 'e' _ 'r' _ 'c' _ 'a' _ 'l' _ ';', 9, 0x22ba, 1) -NAMED_CHARACTER_REFERENCE(1183, 'i' _ 'n' _ 't' _ 'l' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 9, 0x2a17, 1) -NAMED_CHARACTER_REFERENCE(1184, 'i' _ 'n' _ 't' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 8, 0x2a3c, 1) -NAMED_CHARACTER_REFERENCE(1185, 'i' _ 'o' _ 'c' _ 'y' _ ';', 5, 0x0451, 1) -NAMED_CHARACTER_REFERENCE(1186, 'i' _ 'o' _ 'g' _ 'o' _ 'n' _ ';', 6, 0x012f, 1) -NAMED_CHARACTER_REFERENCE(1187, 'i' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5a, 2) -NAMED_CHARACTER_REFERENCE(1188, 'i' _ 'o' _ 't' _ 'a' _ ';', 5, 0x03b9, 1) -NAMED_CHARACTER_REFERENCE(1189, 'i' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 6, 0x2a3c, 1) -NAMED_CHARACTER_REFERENCE(1190, 'i' _ 'q' _ 'u' _ 'e' _ 's' _ 't', 6, 0x00bf, 1) -NAMED_CHARACTER_REFERENCE(1191, 'i' _ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 7, 0x00bf, 1) -NAMED_CHARACTER_REFERENCE(1192, 'i' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcbe, 2) -NAMED_CHARACTER_REFERENCE(1193, 'i' _ 's' _ 'i' _ 'n' _ ';', 5, 0x2208, 1) -NAMED_CHARACTER_REFERENCE(1194, 'i' _ 's' _ 'i' _ 'n' _ 'E' _ ';', 6, 0x22f9, 1) -NAMED_CHARACTER_REFERENCE(1195, 'i' _ 's' _ 'i' _ 'n' _ 'd' _ 'o' _ 't' _ ';', 8, 0x22f5, 1) -NAMED_CHARACTER_REFERENCE(1196, 'i' _ 's' _ 'i' _ 'n' _ 's' _ ';', 6, 0x22f4, 1) -NAMED_CHARACTER_REFERENCE(1197, 'i' _ 's' _ 'i' _ 'n' _ 's' _ 'v' _ ';', 7, 0x22f3, 1) -NAMED_CHARACTER_REFERENCE(1198, 'i' _ 's' _ 'i' _ 'n' _ 'v' _ ';', 6, 0x2208, 1) -NAMED_CHARACTER_REFERENCE(1199, 'i' _ 't' _ ';', 3, 0x2062, 1) -NAMED_CHARACTER_REFERENCE(1200, 'i' _ 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x0129, 1) -NAMED_CHARACTER_REFERENCE(1201, 'i' _ 'u' _ 'k' _ 'c' _ 'y' _ ';', 6, 0x0456, 1) -NAMED_CHARACTER_REFERENCE(1202, 'i' _ 'u' _ 'm' _ 'l', 4, 0x00ef, 1) -NAMED_CHARACTER_REFERENCE(1203, 'i' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00ef, 1) -NAMED_CHARACTER_REFERENCE(1204, 'j' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x0135, 1) -NAMED_CHARACTER_REFERENCE(1205, 'j' _ 'c' _ 'y' _ ';', 4, 0x0439, 1) -NAMED_CHARACTER_REFERENCE(1206, 'j' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd27, 2) -NAMED_CHARACTER_REFERENCE(1207, 'j' _ 'm' _ 'a' _ 't' _ 'h' _ ';', 6, 0x0237, 1) -NAMED_CHARACTER_REFERENCE(1208, 'j' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5b, 2) -NAMED_CHARACTER_REFERENCE(1209, 'j' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcbf, 2) -NAMED_CHARACTER_REFERENCE(1210, 'j' _ 's' _ 'e' _ 'r' _ 'c' _ 'y' _ ';', 7, 0x0458, 1) -NAMED_CHARACTER_REFERENCE(1211, 'j' _ 'u' _ 'k' _ 'c' _ 'y' _ ';', 6, 0x0454, 1) -NAMED_CHARACTER_REFERENCE(1212, 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ ';', 6, 0x03ba, 1) -NAMED_CHARACTER_REFERENCE(1213, 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ 'v' _ ';', 7, 0x03f0, 1) -NAMED_CHARACTER_REFERENCE(1214, 'k' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 7, 0x0137, 1) -NAMED_CHARACTER_REFERENCE(1215, 'k' _ 'c' _ 'y' _ ';', 4, 0x043a, 1) -NAMED_CHARACTER_REFERENCE(1216, 'k' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd28, 2) -NAMED_CHARACTER_REFERENCE(1217, 'k' _ 'g' _ 'r' _ 'e' _ 'e' _ 'n' _ ';', 7, 0x0138, 1) -NAMED_CHARACTER_REFERENCE(1218, 'k' _ 'h' _ 'c' _ 'y' _ ';', 5, 0x0445, 1) -NAMED_CHARACTER_REFERENCE(1219, 'k' _ 'j' _ 'c' _ 'y' _ ';', 5, 0x045c, 1) -NAMED_CHARACTER_REFERENCE(1220, 'k' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5c, 2) -NAMED_CHARACTER_REFERENCE(1221, 'k' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc0, 2) -NAMED_CHARACTER_REFERENCE(1222, 'l' _ 'A' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21da, 1) -NAMED_CHARACTER_REFERENCE(1223, 'l' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d0, 1) -NAMED_CHARACTER_REFERENCE(1224, 'l' _ 'A' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 7, 0x291b, 1) -NAMED_CHARACTER_REFERENCE(1225, 'l' _ 'B' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x290e, 1) -NAMED_CHARACTER_REFERENCE(1226, 'l' _ 'E' _ ';', 3, 0x2266, 1) -NAMED_CHARACTER_REFERENCE(1227, 'l' _ 'E' _ 'g' _ ';', 4, 0x2a8b, 1) -NAMED_CHARACTER_REFERENCE(1228, 'l' _ 'H' _ 'a' _ 'r' _ ';', 5, 0x2962, 1) -NAMED_CHARACTER_REFERENCE(1229, 'l' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x013a, 1) -NAMED_CHARACTER_REFERENCE(1230, 'l' _ 'a' _ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 9, 0x29b4, 1) -NAMED_CHARACTER_REFERENCE(1231, 'l' _ 'a' _ 'g' _ 'r' _ 'a' _ 'n' _ ';', 7, 0x2112, 1) -NAMED_CHARACTER_REFERENCE(1232, 'l' _ 'a' _ 'm' _ 'b' _ 'd' _ 'a' _ ';', 7, 0x03bb, 1) -NAMED_CHARACTER_REFERENCE(1233, 'l' _ 'a' _ 'n' _ 'g' _ ';', 5, 0x27e8, 1) -NAMED_CHARACTER_REFERENCE(1234, 'l' _ 'a' _ 'n' _ 'g' _ 'd' _ ';', 6, 0x2991, 1) -NAMED_CHARACTER_REFERENCE(1235, 'l' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 7, 0x27e8, 1) -NAMED_CHARACTER_REFERENCE(1236, 'l' _ 'a' _ 'p' _ ';', 4, 0x2a85, 1) -NAMED_CHARACTER_REFERENCE(1237, 'l' _ 'a' _ 'q' _ 'u' _ 'o', 5, 0x00ab, 1) -NAMED_CHARACTER_REFERENCE(1238, 'l' _ 'a' _ 'q' _ 'u' _ 'o' _ ';', 6, 0x00ab, 1) -NAMED_CHARACTER_REFERENCE(1239, 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2190, 1) -NAMED_CHARACTER_REFERENCE(1240, 'l' _ 'a' _ 'r' _ 'r' _ 'b' _ ';', 6, 0x21e4, 1) -NAMED_CHARACTER_REFERENCE(1241, 'l' _ 'a' _ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 8, 0x291f, 1) -NAMED_CHARACTER_REFERENCE(1242, 'l' _ 'a' _ 'r' _ 'r' _ 'f' _ 's' _ ';', 7, 0x291d, 1) -NAMED_CHARACTER_REFERENCE(1243, 'l' _ 'a' _ 'r' _ 'r' _ 'h' _ 'k' _ ';', 7, 0x21a9, 1) -NAMED_CHARACTER_REFERENCE(1244, 'l' _ 'a' _ 'r' _ 'r' _ 'l' _ 'p' _ ';', 7, 0x21ab, 1) -NAMED_CHARACTER_REFERENCE(1245, 'l' _ 'a' _ 'r' _ 'r' _ 'p' _ 'l' _ ';', 7, 0x2939, 1) -NAMED_CHARACTER_REFERENCE(1246, 'l' _ 'a' _ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 8, 0x2973, 1) -NAMED_CHARACTER_REFERENCE(1247, 'l' _ 'a' _ 'r' _ 'r' _ 't' _ 'l' _ ';', 7, 0x21a2, 1) -NAMED_CHARACTER_REFERENCE(1248, 'l' _ 'a' _ 't' _ ';', 4, 0x2aab, 1) -NAMED_CHARACTER_REFERENCE(1249, 'l' _ 'a' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 7, 0x2919, 1) -NAMED_CHARACTER_REFERENCE(1250, 'l' _ 'a' _ 't' _ 'e' _ ';', 5, 0x2aad, 1) -NAMED_CHARACTER_REFERENCE(1251, 'l' _ 'b' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x290c, 1) -NAMED_CHARACTER_REFERENCE(1252, 'l' _ 'b' _ 'b' _ 'r' _ 'k' _ ';', 6, 0x2772, 1) -NAMED_CHARACTER_REFERENCE(1253, 'l' _ 'b' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 7, 0x007b, 1) -NAMED_CHARACTER_REFERENCE(1254, 'l' _ 'b' _ 'r' _ 'a' _ 'c' _ 'k' _ ';', 7, 0x005b, 1) -NAMED_CHARACTER_REFERENCE(1255, 'l' _ 'b' _ 'r' _ 'k' _ 'e' _ ';', 6, 0x298b, 1) -NAMED_CHARACTER_REFERENCE(1256, 'l' _ 'b' _ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 8, 0x298f, 1) -NAMED_CHARACTER_REFERENCE(1257, 'l' _ 'b' _ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 8, 0x298d, 1) -NAMED_CHARACTER_REFERENCE(1258, 'l' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x013e, 1) -NAMED_CHARACTER_REFERENCE(1259, 'l' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 7, 0x013c, 1) -NAMED_CHARACTER_REFERENCE(1260, 'l' _ 'c' _ 'e' _ 'i' _ 'l' _ ';', 6, 0x2308, 1) -NAMED_CHARACTER_REFERENCE(1261, 'l' _ 'c' _ 'u' _ 'b' _ ';', 5, 0x007b, 1) -NAMED_CHARACTER_REFERENCE(1262, 'l' _ 'c' _ 'y' _ ';', 4, 0x043b, 1) -NAMED_CHARACTER_REFERENCE(1263, 'l' _ 'd' _ 'c' _ 'a' _ ';', 5, 0x2936, 1) -NAMED_CHARACTER_REFERENCE(1264, 'l' _ 'd' _ 'q' _ 'u' _ 'o' _ ';', 6, 0x201c, 1) -NAMED_CHARACTER_REFERENCE(1265, 'l' _ 'd' _ 'q' _ 'u' _ 'o' _ 'r' _ ';', 7, 0x201e, 1) -NAMED_CHARACTER_REFERENCE(1266, 'l' _ 'd' _ 'r' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 8, 0x2967, 1) -NAMED_CHARACTER_REFERENCE(1267, 'l' _ 'd' _ 'r' _ 'u' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 9, 0x294b, 1) -NAMED_CHARACTER_REFERENCE(1268, 'l' _ 'd' _ 's' _ 'h' _ ';', 5, 0x21b2, 1) -NAMED_CHARACTER_REFERENCE(1269, 'l' _ 'e' _ ';', 3, 0x2264, 1) -NAMED_CHARACTER_REFERENCE(1270, 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x2190, 1) -NAMED_CHARACTER_REFERENCE(1271, 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 14, 0x21a2, 1) -NAMED_CHARACTER_REFERENCE(1272, 'l' _ 'e' _ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 16, 0x21bd, 1) -NAMED_CHARACTER_REFERENCE(1273, 'l' _ 'e' _ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 14, 0x21bc, 1) -NAMED_CHARACTER_REFERENCE(1274, 'l' _ 'e' _ 'f' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 15, 0x21c7, 1) -NAMED_CHARACTER_REFERENCE(1275, 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x2194, 1) -NAMED_CHARACTER_REFERENCE(1276, 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 16, 0x21c6, 1) -NAMED_CHARACTER_REFERENCE(1277, 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', 18, 0x21cb, 1) -NAMED_CHARACTER_REFERENCE(1278, 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 20, 0x21ad, 1) -NAMED_CHARACTER_REFERENCE(1279, 'l' _ 'e' _ 'f' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 15, 0x22cb, 1) -NAMED_CHARACTER_REFERENCE(1280, 'l' _ 'e' _ 'g' _ ';', 4, 0x22da, 1) -NAMED_CHARACTER_REFERENCE(1281, 'l' _ 'e' _ 'q' _ ';', 4, 0x2264, 1) -NAMED_CHARACTER_REFERENCE(1282, 'l' _ 'e' _ 'q' _ 'q' _ ';', 5, 0x2266, 1) -NAMED_CHARACTER_REFERENCE(1283, 'l' _ 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 9, 0x2a7d, 1) -NAMED_CHARACTER_REFERENCE(1284, 'l' _ 'e' _ 's' _ ';', 4, 0x2a7d, 1) -NAMED_CHARACTER_REFERENCE(1285, 'l' _ 'e' _ 's' _ 'c' _ 'c' _ ';', 6, 0x2aa8, 1) -NAMED_CHARACTER_REFERENCE(1286, 'l' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a7f, 1) -NAMED_CHARACTER_REFERENCE(1287, 'l' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 8, 0x2a81, 1) -NAMED_CHARACTER_REFERENCE(1288, 'l' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'r' _ ';', 9, 0x2a83, 1) -NAMED_CHARACTER_REFERENCE(1289, 'l' _ 'e' _ 's' _ 'g' _ 'e' _ 's' _ ';', 7, 0x2a93, 1) -NAMED_CHARACTER_REFERENCE(1290, 'l' _ 'e' _ 's' _ 's' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 11, 0x2a85, 1) -NAMED_CHARACTER_REFERENCE(1291, 'l' _ 'e' _ 's' _ 's' _ 'd' _ 'o' _ 't' _ ';', 8, 0x22d6, 1) -NAMED_CHARACTER_REFERENCE(1292, 'l' _ 'e' _ 's' _ 's' _ 'e' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 10, 0x22da, 1) -NAMED_CHARACTER_REFERENCE(1293, 'l' _ 'e' _ 's' _ 's' _ 'e' _ 'q' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 11, 0x2a8b, 1) -NAMED_CHARACTER_REFERENCE(1294, 'l' _ 'e' _ 's' _ 's' _ 'g' _ 't' _ 'r' _ ';', 8, 0x2276, 1) -NAMED_CHARACTER_REFERENCE(1295, 'l' _ 'e' _ 's' _ 's' _ 's' _ 'i' _ 'm' _ ';', 8, 0x2272, 1) -NAMED_CHARACTER_REFERENCE(1296, 'l' _ 'f' _ 'i' _ 's' _ 'h' _ 't' _ ';', 7, 0x297c, 1) -NAMED_CHARACTER_REFERENCE(1297, 'l' _ 'f' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 7, 0x230a, 1) -NAMED_CHARACTER_REFERENCE(1298, 'l' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd29, 2) -NAMED_CHARACTER_REFERENCE(1299, 'l' _ 'g' _ ';', 3, 0x2276, 1) -NAMED_CHARACTER_REFERENCE(1300, 'l' _ 'g' _ 'E' _ ';', 4, 0x2a91, 1) -NAMED_CHARACTER_REFERENCE(1301, 'l' _ 'h' _ 'a' _ 'r' _ 'd' _ ';', 6, 0x21bd, 1) -NAMED_CHARACTER_REFERENCE(1302, 'l' _ 'h' _ 'a' _ 'r' _ 'u' _ ';', 6, 0x21bc, 1) -NAMED_CHARACTER_REFERENCE(1303, 'l' _ 'h' _ 'a' _ 'r' _ 'u' _ 'l' _ ';', 7, 0x296a, 1) -NAMED_CHARACTER_REFERENCE(1304, 'l' _ 'h' _ 'b' _ 'l' _ 'k' _ ';', 6, 0x2584, 1) -NAMED_CHARACTER_REFERENCE(1305, 'l' _ 'j' _ 'c' _ 'y' _ ';', 5, 0x0459, 1) -NAMED_CHARACTER_REFERENCE(1306, 'l' _ 'l' _ ';', 3, 0x226a, 1) -NAMED_CHARACTER_REFERENCE(1307, 'l' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21c7, 1) -NAMED_CHARACTER_REFERENCE(1308, 'l' _ 'l' _ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 9, 0x231e, 1) -NAMED_CHARACTER_REFERENCE(1309, 'l' _ 'l' _ 'h' _ 'a' _ 'r' _ 'd' _ ';', 7, 0x296b, 1) -NAMED_CHARACTER_REFERENCE(1310, 'l' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 6, 0x25fa, 1) -NAMED_CHARACTER_REFERENCE(1311, 'l' _ 'm' _ 'i' _ 'd' _ 'o' _ 't' _ ';', 7, 0x0140, 1) -NAMED_CHARACTER_REFERENCE(1312, 'l' _ 'm' _ 'o' _ 'u' _ 's' _ 't' _ ';', 7, 0x23b0, 1) -NAMED_CHARACTER_REFERENCE(1313, 'l' _ 'm' _ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 11, 0x23b0, 1) -NAMED_CHARACTER_REFERENCE(1314, 'l' _ 'n' _ 'E' _ ';', 4, 0x2268, 1) -NAMED_CHARACTER_REFERENCE(1315, 'l' _ 'n' _ 'a' _ 'p' _ ';', 5, 0x2a89, 1) -NAMED_CHARACTER_REFERENCE(1316, 'l' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0x2a89, 1) -NAMED_CHARACTER_REFERENCE(1317, 'l' _ 'n' _ 'e' _ ';', 4, 0x2a87, 1) -NAMED_CHARACTER_REFERENCE(1318, 'l' _ 'n' _ 'e' _ 'q' _ ';', 5, 0x2a87, 1) -NAMED_CHARACTER_REFERENCE(1319, 'l' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 6, 0x2268, 1) -NAMED_CHARACTER_REFERENCE(1320, 'l' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 6, 0x22e6, 1) -NAMED_CHARACTER_REFERENCE(1321, 'l' _ 'o' _ 'a' _ 'n' _ 'g' _ ';', 6, 0x27ec, 1) -NAMED_CHARACTER_REFERENCE(1322, 'l' _ 'o' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21fd, 1) -NAMED_CHARACTER_REFERENCE(1323, 'l' _ 'o' _ 'b' _ 'r' _ 'k' _ ';', 6, 0x27e6, 1) -NAMED_CHARACTER_REFERENCE(1324, 'l' _ 'o' _ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x27f5, 1) -NAMED_CHARACTER_REFERENCE(1325, 'l' _ 'o' _ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 19, 0x27f7, 1) -NAMED_CHARACTER_REFERENCE(1326, 'l' _ 'o' _ 'n' _ 'g' _ 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ ';', 11, 0x27fc, 1) -NAMED_CHARACTER_REFERENCE(1327, 'l' _ 'o' _ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x27f6, 1) -NAMED_CHARACTER_REFERENCE(1328, 'l' _ 'o' _ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x21ab, 1) -NAMED_CHARACTER_REFERENCE(1329, 'l' _ 'o' _ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x21ac, 1) -NAMED_CHARACTER_REFERENCE(1330, 'l' _ 'o' _ 'p' _ 'a' _ 'r' _ ';', 6, 0x2985, 1) -NAMED_CHARACTER_REFERENCE(1331, 'l' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5d, 2) -NAMED_CHARACTER_REFERENCE(1332, 'l' _ 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2a2d, 1) -NAMED_CHARACTER_REFERENCE(1333, 'l' _ 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 8, 0x2a34, 1) -NAMED_CHARACTER_REFERENCE(1334, 'l' _ 'o' _ 'w' _ 'a' _ 's' _ 't' _ ';', 7, 0x2217, 1) -NAMED_CHARACTER_REFERENCE(1335, 'l' _ 'o' _ 'w' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x005f, 1) -NAMED_CHARACTER_REFERENCE(1336, 'l' _ 'o' _ 'z' _ ';', 4, 0x25ca, 1) -NAMED_CHARACTER_REFERENCE(1337, 'l' _ 'o' _ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 8, 0x25ca, 1) -NAMED_CHARACTER_REFERENCE(1338, 'l' _ 'o' _ 'z' _ 'f' _ ';', 5, 0x29eb, 1) -NAMED_CHARACTER_REFERENCE(1339, 'l' _ 'p' _ 'a' _ 'r' _ ';', 5, 0x0028, 1) -NAMED_CHARACTER_REFERENCE(1340, 'l' _ 'p' _ 'a' _ 'r' _ 'l' _ 't' _ ';', 7, 0x2993, 1) -NAMED_CHARACTER_REFERENCE(1341, 'l' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21c6, 1) -NAMED_CHARACTER_REFERENCE(1342, 'l' _ 'r' _ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 9, 0x231f, 1) -NAMED_CHARACTER_REFERENCE(1343, 'l' _ 'r' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x21cb, 1) -NAMED_CHARACTER_REFERENCE(1344, 'l' _ 'r' _ 'h' _ 'a' _ 'r' _ 'd' _ ';', 7, 0x296d, 1) -NAMED_CHARACTER_REFERENCE(1345, 'l' _ 'r' _ 'm' _ ';', 4, 0x200e, 1) -NAMED_CHARACTER_REFERENCE(1346, 'l' _ 'r' _ 't' _ 'r' _ 'i' _ ';', 6, 0x22bf, 1) -NAMED_CHARACTER_REFERENCE(1347, 'l' _ 's' _ 'a' _ 'q' _ 'u' _ 'o' _ ';', 7, 0x2039, 1) -NAMED_CHARACTER_REFERENCE(1348, 'l' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc1, 2) -NAMED_CHARACTER_REFERENCE(1349, 'l' _ 's' _ 'h' _ ';', 4, 0x21b0, 1) -NAMED_CHARACTER_REFERENCE(1350, 'l' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2272, 1) -NAMED_CHARACTER_REFERENCE(1351, 'l' _ 's' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x2a8d, 1) -NAMED_CHARACTER_REFERENCE(1352, 'l' _ 's' _ 'i' _ 'm' _ 'g' _ ';', 6, 0x2a8f, 1) -NAMED_CHARACTER_REFERENCE(1353, 'l' _ 's' _ 'q' _ 'b' _ ';', 5, 0x005b, 1) -NAMED_CHARACTER_REFERENCE(1354, 'l' _ 's' _ 'q' _ 'u' _ 'o' _ ';', 6, 0x2018, 1) -NAMED_CHARACTER_REFERENCE(1355, 'l' _ 's' _ 'q' _ 'u' _ 'o' _ 'r' _ ';', 7, 0x201a, 1) -NAMED_CHARACTER_REFERENCE(1356, 'l' _ 's' _ 't' _ 'r' _ 'o' _ 'k' _ ';', 7, 0x0142, 1) -NAMED_CHARACTER_REFERENCE(1357, 'l' _ 't', 2, 0x003c, 1) -NAMED_CHARACTER_REFERENCE(1358, 'l' _ 't' _ ';', 3, 0x003c, 1) -NAMED_CHARACTER_REFERENCE(1359, 'l' _ 't' _ 'c' _ 'c' _ ';', 5, 0x2aa6, 1) -NAMED_CHARACTER_REFERENCE(1360, 'l' _ 't' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x2a79, 1) -NAMED_CHARACTER_REFERENCE(1361, 'l' _ 't' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22d6, 1) -NAMED_CHARACTER_REFERENCE(1362, 'l' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ ';', 7, 0x22cb, 1) -NAMED_CHARACTER_REFERENCE(1363, 'l' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0x22c9, 1) -NAMED_CHARACTER_REFERENCE(1364, 'l' _ 't' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x2976, 1) -NAMED_CHARACTER_REFERENCE(1365, 'l' _ 't' _ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 8, 0x2a7b, 1) -NAMED_CHARACTER_REFERENCE(1366, 'l' _ 't' _ 'r' _ 'P' _ 'a' _ 'r' _ ';', 7, 0x2996, 1) -NAMED_CHARACTER_REFERENCE(1367, 'l' _ 't' _ 'r' _ 'i' _ ';', 5, 0x25c3, 1) -NAMED_CHARACTER_REFERENCE(1368, 'l' _ 't' _ 'r' _ 'i' _ 'e' _ ';', 6, 0x22b4, 1) -NAMED_CHARACTER_REFERENCE(1369, 'l' _ 't' _ 'r' _ 'i' _ 'f' _ ';', 6, 0x25c2, 1) -NAMED_CHARACTER_REFERENCE(1370, 'l' _ 'u' _ 'r' _ 'd' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 9, 0x294a, 1) -NAMED_CHARACTER_REFERENCE(1371, 'l' _ 'u' _ 'r' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 8, 0x2966, 1) -NAMED_CHARACTER_REFERENCE(1372, 'm' _ 'D' _ 'D' _ 'o' _ 't' _ ';', 6, 0x223a, 1) -NAMED_CHARACTER_REFERENCE(1373, 'm' _ 'a' _ 'c' _ 'r', 4, 0x00af, 1) -NAMED_CHARACTER_REFERENCE(1374, 'm' _ 'a' _ 'c' _ 'r' _ ';', 5, 0x00af, 1) -NAMED_CHARACTER_REFERENCE(1375, 'm' _ 'a' _ 'l' _ 'e' _ ';', 5, 0x2642, 1) -NAMED_CHARACTER_REFERENCE(1376, 'm' _ 'a' _ 'l' _ 't' _ ';', 5, 0x2720, 1) -NAMED_CHARACTER_REFERENCE(1377, 'm' _ 'a' _ 'l' _ 't' _ 'e' _ 's' _ 'e' _ ';', 8, 0x2720, 1) -NAMED_CHARACTER_REFERENCE(1378, 'm' _ 'a' _ 'p' _ ';', 4, 0x21a6, 1) -NAMED_CHARACTER_REFERENCE(1379, 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ ';', 7, 0x21a6, 1) -NAMED_CHARACTER_REFERENCE(1380, 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 11, 0x21a7, 1) -NAMED_CHARACTER_REFERENCE(1381, 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 11, 0x21a4, 1) -NAMED_CHARACTER_REFERENCE(1382, 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ 'u' _ 'p' _ ';', 9, 0x21a5, 1) -NAMED_CHARACTER_REFERENCE(1383, 'm' _ 'a' _ 'r' _ 'k' _ 'e' _ 'r' _ ';', 7, 0x25ae, 1) -NAMED_CHARACTER_REFERENCE(1384, 'm' _ 'c' _ 'o' _ 'm' _ 'm' _ 'a' _ ';', 7, 0x2a29, 1) -NAMED_CHARACTER_REFERENCE(1385, 'm' _ 'c' _ 'y' _ ';', 4, 0x043c, 1) -NAMED_CHARACTER_REFERENCE(1386, 'm' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 6, 0x2014, 1) -NAMED_CHARACTER_REFERENCE(1387, 'm' _ 'e' _ 'a' _ 's' _ 'u' _ 'r' _ 'e' _ 'd' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 14, 0x2221, 1) -NAMED_CHARACTER_REFERENCE(1388, 'm' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd2a, 2) -NAMED_CHARACTER_REFERENCE(1389, 'm' _ 'h' _ 'o' _ ';', 4, 0x2127, 1) -NAMED_CHARACTER_REFERENCE(1390, 'm' _ 'i' _ 'c' _ 'r' _ 'o', 5, 0x00b5, 1) -NAMED_CHARACTER_REFERENCE(1391, 'm' _ 'i' _ 'c' _ 'r' _ 'o' _ ';', 6, 0x00b5, 1) -NAMED_CHARACTER_REFERENCE(1392, 'm' _ 'i' _ 'd' _ ';', 4, 0x2223, 1) -NAMED_CHARACTER_REFERENCE(1393, 'm' _ 'i' _ 'd' _ 'a' _ 's' _ 't' _ ';', 7, 0x002a, 1) -NAMED_CHARACTER_REFERENCE(1394, 'm' _ 'i' _ 'd' _ 'c' _ 'i' _ 'r' _ ';', 7, 0x2af0, 1) -NAMED_CHARACTER_REFERENCE(1395, 'm' _ 'i' _ 'd' _ 'd' _ 'o' _ 't', 6, 0x00b7, 1) -NAMED_CHARACTER_REFERENCE(1396, 'm' _ 'i' _ 'd' _ 'd' _ 'o' _ 't' _ ';', 7, 0x00b7, 1) -NAMED_CHARACTER_REFERENCE(1397, 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 6, 0x2212, 1) -NAMED_CHARACTER_REFERENCE(1398, 'm' _ 'i' _ 'n' _ 'u' _ 's' _ 'b' _ ';', 7, 0x229f, 1) -NAMED_CHARACTER_REFERENCE(1399, 'm' _ 'i' _ 'n' _ 'u' _ 's' _ 'd' _ ';', 7, 0x2238, 1) -NAMED_CHARACTER_REFERENCE(1400, 'm' _ 'i' _ 'n' _ 'u' _ 's' _ 'd' _ 'u' _ ';', 8, 0x2a2a, 1) -NAMED_CHARACTER_REFERENCE(1401, 'm' _ 'l' _ 'c' _ 'p' _ ';', 5, 0x2adb, 1) -NAMED_CHARACTER_REFERENCE(1402, 'm' _ 'l' _ 'd' _ 'r' _ ';', 5, 0x2026, 1) -NAMED_CHARACTER_REFERENCE(1403, 'm' _ 'n' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2213, 1) -NAMED_CHARACTER_REFERENCE(1404, 'm' _ 'o' _ 'd' _ 'e' _ 'l' _ 's' _ ';', 7, 0x22a7, 1) -NAMED_CHARACTER_REFERENCE(1405, 'm' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5e, 2) -NAMED_CHARACTER_REFERENCE(1406, 'm' _ 'p' _ ';', 3, 0x2213, 1) -NAMED_CHARACTER_REFERENCE(1407, 'm' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc2, 2) -NAMED_CHARACTER_REFERENCE(1408, 'm' _ 's' _ 't' _ 'p' _ 'o' _ 's' _ ';', 7, 0x223e, 1) -NAMED_CHARACTER_REFERENCE(1409, 'm' _ 'u' _ ';', 3, 0x03bc, 1) -NAMED_CHARACTER_REFERENCE(1410, 'm' _ 'u' _ 'l' _ 't' _ 'i' _ 'm' _ 'a' _ 'p' _ ';', 9, 0x22b8, 1) -NAMED_CHARACTER_REFERENCE(1411, 'm' _ 'u' _ 'm' _ 'a' _ 'p' _ ';', 6, 0x22b8, 1) -NAMED_CHARACTER_REFERENCE(1412, 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0x21cd, 1) -NAMED_CHARACTER_REFERENCE(1413, 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0x21ce, 1) -NAMED_CHARACTER_REFERENCE(1414, 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x21cf, 1) -NAMED_CHARACTER_REFERENCE(1415, 'n' _ 'V' _ 'D' _ 'a' _ 's' _ 'h' _ ';', 7, 0x22af, 1) -NAMED_CHARACTER_REFERENCE(1416, 'n' _ 'V' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 7, 0x22ae, 1) -NAMED_CHARACTER_REFERENCE(1417, 'n' _ 'a' _ 'b' _ 'l' _ 'a' _ ';', 6, 0x2207, 1) -NAMED_CHARACTER_REFERENCE(1418, 'n' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x0144, 1) -NAMED_CHARACTER_REFERENCE(1419, 'n' _ 'a' _ 'p' _ ';', 4, 0x2249, 1) -NAMED_CHARACTER_REFERENCE(1420, 'n' _ 'a' _ 'p' _ 'o' _ 's' _ ';', 6, 0x0149, 1) -NAMED_CHARACTER_REFERENCE(1421, 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 8, 0x2249, 1) -NAMED_CHARACTER_REFERENCE(1422, 'n' _ 'a' _ 't' _ 'u' _ 'r' _ ';', 6, 0x266e, 1) -NAMED_CHARACTER_REFERENCE(1423, 'n' _ 'a' _ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ ';', 8, 0x266e, 1) -NAMED_CHARACTER_REFERENCE(1424, 'n' _ 'a' _ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ 's' _ ';', 9, 0x2115, 1) -NAMED_CHARACTER_REFERENCE(1425, 'n' _ 'b' _ 's' _ 'p', 4, 0x00a0, 1) -NAMED_CHARACTER_REFERENCE(1426, 'n' _ 'b' _ 's' _ 'p' _ ';', 5, 0x00a0, 1) -NAMED_CHARACTER_REFERENCE(1427, 'n' _ 'c' _ 'a' _ 'p' _ ';', 5, 0x2a43, 1) -NAMED_CHARACTER_REFERENCE(1428, 'n' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x0148, 1) -NAMED_CHARACTER_REFERENCE(1429, 'n' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 7, 0x0146, 1) -NAMED_CHARACTER_REFERENCE(1430, 'n' _ 'c' _ 'o' _ 'n' _ 'g' _ ';', 6, 0x2247, 1) -NAMED_CHARACTER_REFERENCE(1431, 'n' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x2a42, 1) -NAMED_CHARACTER_REFERENCE(1432, 'n' _ 'c' _ 'y' _ ';', 4, 0x043d, 1) -NAMED_CHARACTER_REFERENCE(1433, 'n' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 6, 0x2013, 1) -NAMED_CHARACTER_REFERENCE(1434, 'n' _ 'e' _ ';', 3, 0x2260, 1) -NAMED_CHARACTER_REFERENCE(1435, 'n' _ 'e' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21d7, 1) -NAMED_CHARACTER_REFERENCE(1436, 'n' _ 'e' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, 0x2924, 1) -NAMED_CHARACTER_REFERENCE(1437, 'n' _ 'e' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2197, 1) -NAMED_CHARACTER_REFERENCE(1438, 'n' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2197, 1) -NAMED_CHARACTER_REFERENCE(1439, 'n' _ 'e' _ 'q' _ 'u' _ 'i' _ 'v' _ ';', 7, 0x2262, 1) -NAMED_CHARACTER_REFERENCE(1440, 'n' _ 'e' _ 's' _ 'e' _ 'a' _ 'r' _ ';', 7, 0x2928, 1) -NAMED_CHARACTER_REFERENCE(1441, 'n' _ 'e' _ 'x' _ 'i' _ 's' _ 't' _ ';', 7, 0x2204, 1) -NAMED_CHARACTER_REFERENCE(1442, 'n' _ 'e' _ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 8, 0x2204, 1) -NAMED_CHARACTER_REFERENCE(1443, 'n' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd2b, 2) -NAMED_CHARACTER_REFERENCE(1444, 'n' _ 'g' _ 'e' _ ';', 4, 0x2271, 1) -NAMED_CHARACTER_REFERENCE(1445, 'n' _ 'g' _ 'e' _ 'q' _ ';', 5, 0x2271, 1) -NAMED_CHARACTER_REFERENCE(1446, 'n' _ 'g' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2275, 1) -NAMED_CHARACTER_REFERENCE(1447, 'n' _ 'g' _ 't' _ ';', 4, 0x226f, 1) -NAMED_CHARACTER_REFERENCE(1448, 'n' _ 'g' _ 't' _ 'r' _ ';', 5, 0x226f, 1) -NAMED_CHARACTER_REFERENCE(1449, 'n' _ 'h' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21ce, 1) -NAMED_CHARACTER_REFERENCE(1450, 'n' _ 'h' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21ae, 1) -NAMED_CHARACTER_REFERENCE(1451, 'n' _ 'h' _ 'p' _ 'a' _ 'r' _ ';', 6, 0x2af2, 1) -NAMED_CHARACTER_REFERENCE(1452, 'n' _ 'i' _ ';', 3, 0x220b, 1) -NAMED_CHARACTER_REFERENCE(1453, 'n' _ 'i' _ 's' _ ';', 4, 0x22fc, 1) -NAMED_CHARACTER_REFERENCE(1454, 'n' _ 'i' _ 's' _ 'd' _ ';', 5, 0x22fa, 1) -NAMED_CHARACTER_REFERENCE(1455, 'n' _ 'i' _ 'v' _ ';', 4, 0x220b, 1) -NAMED_CHARACTER_REFERENCE(1456, 'n' _ 'j' _ 'c' _ 'y' _ ';', 5, 0x045a, 1) -NAMED_CHARACTER_REFERENCE(1457, 'n' _ 'l' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21cd, 1) -NAMED_CHARACTER_REFERENCE(1458, 'n' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x219a, 1) -NAMED_CHARACTER_REFERENCE(1459, 'n' _ 'l' _ 'd' _ 'r' _ ';', 5, 0x2025, 1) -NAMED_CHARACTER_REFERENCE(1460, 'n' _ 'l' _ 'e' _ ';', 4, 0x2270, 1) -NAMED_CHARACTER_REFERENCE(1461, 'n' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0x219a, 1) -NAMED_CHARACTER_REFERENCE(1462, 'n' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0x21ae, 1) -NAMED_CHARACTER_REFERENCE(1463, 'n' _ 'l' _ 'e' _ 'q' _ ';', 5, 0x2270, 1) -NAMED_CHARACTER_REFERENCE(1464, 'n' _ 'l' _ 'e' _ 's' _ 's' _ ';', 6, 0x226e, 1) -NAMED_CHARACTER_REFERENCE(1465, 'n' _ 'l' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2274, 1) -NAMED_CHARACTER_REFERENCE(1466, 'n' _ 'l' _ 't' _ ';', 4, 0x226e, 1) -NAMED_CHARACTER_REFERENCE(1467, 'n' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 6, 0x22ea, 1) -NAMED_CHARACTER_REFERENCE(1468, 'n' _ 'l' _ 't' _ 'r' _ 'i' _ 'e' _ ';', 7, 0x22ec, 1) -NAMED_CHARACTER_REFERENCE(1469, 'n' _ 'm' _ 'i' _ 'd' _ ';', 5, 0x2224, 1) -NAMED_CHARACTER_REFERENCE(1470, 'n' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5f, 2) -NAMED_CHARACTER_REFERENCE(1471, 'n' _ 'o' _ 't', 3, 0x00ac, 1) -NAMED_CHARACTER_REFERENCE(1472, 'n' _ 'o' _ 't' _ ';', 4, 0x00ac, 1) -NAMED_CHARACTER_REFERENCE(1473, 'n' _ 'o' _ 't' _ 'i' _ 'n' _ ';', 6, 0x2209, 1) -NAMED_CHARACTER_REFERENCE(1474, 'n' _ 'o' _ 't' _ 'i' _ 'n' _ 'v' _ 'a' _ ';', 8, 0x2209, 1) -NAMED_CHARACTER_REFERENCE(1475, 'n' _ 'o' _ 't' _ 'i' _ 'n' _ 'v' _ 'b' _ ';', 8, 0x22f7, 1) -NAMED_CHARACTER_REFERENCE(1476, 'n' _ 'o' _ 't' _ 'i' _ 'n' _ 'v' _ 'c' _ ';', 8, 0x22f6, 1) -NAMED_CHARACTER_REFERENCE(1477, 'n' _ 'o' _ 't' _ 'n' _ 'i' _ ';', 6, 0x220c, 1) -NAMED_CHARACTER_REFERENCE(1478, 'n' _ 'o' _ 't' _ 'n' _ 'i' _ 'v' _ 'a' _ ';', 8, 0x220c, 1) -NAMED_CHARACTER_REFERENCE(1479, 'n' _ 'o' _ 't' _ 'n' _ 'i' _ 'v' _ 'b' _ ';', 8, 0x22fe, 1) -NAMED_CHARACTER_REFERENCE(1480, 'n' _ 'o' _ 't' _ 'n' _ 'i' _ 'v' _ 'c' _ ';', 8, 0x22fd, 1) -NAMED_CHARACTER_REFERENCE(1481, 'n' _ 'p' _ 'a' _ 'r' _ ';', 5, 0x2226, 1) -NAMED_CHARACTER_REFERENCE(1482, 'n' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 10, 0x2226, 1) -NAMED_CHARACTER_REFERENCE(1483, 'n' _ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 8, 0x2a14, 1) -NAMED_CHARACTER_REFERENCE(1484, 'n' _ 'p' _ 'r' _ ';', 4, 0x2280, 1) -NAMED_CHARACTER_REFERENCE(1485, 'n' _ 'p' _ 'r' _ 'c' _ 'u' _ 'e' _ ';', 7, 0x22e0, 1) -NAMED_CHARACTER_REFERENCE(1486, 'n' _ 'p' _ 'r' _ 'e' _ 'c' _ ';', 6, 0x2280, 1) -NAMED_CHARACTER_REFERENCE(1487, 'n' _ 'r' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21cf, 1) -NAMED_CHARACTER_REFERENCE(1488, 'n' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x219b, 1) -NAMED_CHARACTER_REFERENCE(1489, 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x219b, 1) -NAMED_CHARACTER_REFERENCE(1490, 'n' _ 'r' _ 't' _ 'r' _ 'i' _ ';', 6, 0x22eb, 1) -NAMED_CHARACTER_REFERENCE(1491, 'n' _ 'r' _ 't' _ 'r' _ 'i' _ 'e' _ ';', 7, 0x22ed, 1) -NAMED_CHARACTER_REFERENCE(1492, 'n' _ 's' _ 'c' _ ';', 4, 0x2281, 1) -NAMED_CHARACTER_REFERENCE(1493, 'n' _ 's' _ 'c' _ 'c' _ 'u' _ 'e' _ ';', 7, 0x22e1, 1) -NAMED_CHARACTER_REFERENCE(1494, 'n' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc3, 2) -NAMED_CHARACTER_REFERENCE(1495, 'n' _ 's' _ 'h' _ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 10, 0x2224, 1) -NAMED_CHARACTER_REFERENCE(1496, 'n' _ 's' _ 'h' _ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 15, 0x2226, 1) -NAMED_CHARACTER_REFERENCE(1497, 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2241, 1) -NAMED_CHARACTER_REFERENCE(1498, 'n' _ 's' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x2244, 1) -NAMED_CHARACTER_REFERENCE(1499, 'n' _ 's' _ 'i' _ 'm' _ 'e' _ 'q' _ ';', 7, 0x2244, 1) -NAMED_CHARACTER_REFERENCE(1500, 'n' _ 's' _ 'm' _ 'i' _ 'd' _ ';', 6, 0x2224, 1) -NAMED_CHARACTER_REFERENCE(1501, 'n' _ 's' _ 'p' _ 'a' _ 'r' _ ';', 6, 0x2226, 1) -NAMED_CHARACTER_REFERENCE(1502, 'n' _ 's' _ 'q' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 8, 0x22e2, 1) -NAMED_CHARACTER_REFERENCE(1503, 'n' _ 's' _ 'q' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 8, 0x22e3, 1) -NAMED_CHARACTER_REFERENCE(1504, 'n' _ 's' _ 'u' _ 'b' _ ';', 5, 0x2284, 1) -NAMED_CHARACTER_REFERENCE(1505, 'n' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 6, 0x2288, 1) -NAMED_CHARACTER_REFERENCE(1506, 'n' _ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 10, 0x2288, 1) -NAMED_CHARACTER_REFERENCE(1507, 'n' _ 's' _ 'u' _ 'c' _ 'c' _ ';', 6, 0x2281, 1) -NAMED_CHARACTER_REFERENCE(1508, 'n' _ 's' _ 'u' _ 'p' _ ';', 5, 0x2285, 1) -NAMED_CHARACTER_REFERENCE(1509, 'n' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 6, 0x2289, 1) -NAMED_CHARACTER_REFERENCE(1510, 'n' _ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 10, 0x2289, 1) -NAMED_CHARACTER_REFERENCE(1511, 'n' _ 't' _ 'g' _ 'l' _ ';', 5, 0x2279, 1) -NAMED_CHARACTER_REFERENCE(1512, 'n' _ 't' _ 'i' _ 'l' _ 'd' _ 'e', 6, 0x00f1, 1) -NAMED_CHARACTER_REFERENCE(1513, 'n' _ 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x00f1, 1) -NAMED_CHARACTER_REFERENCE(1514, 'n' _ 't' _ 'l' _ 'g' _ ';', 5, 0x2278, 1) -NAMED_CHARACTER_REFERENCE(1515, 'n' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x22ea, 1) -NAMED_CHARACTER_REFERENCE(1516, 'n' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 16, 0x22ec, 1) -NAMED_CHARACTER_REFERENCE(1517, 'n' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x22eb, 1) -NAMED_CHARACTER_REFERENCE(1518, 'n' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 17, 0x22ed, 1) -NAMED_CHARACTER_REFERENCE(1519, 'n' _ 'u' _ ';', 3, 0x03bd, 1) -NAMED_CHARACTER_REFERENCE(1520, 'n' _ 'u' _ 'm' _ ';', 4, 0x0023, 1) -NAMED_CHARACTER_REFERENCE(1521, 'n' _ 'u' _ 'm' _ 'e' _ 'r' _ 'o' _ ';', 7, 0x2116, 1) -NAMED_CHARACTER_REFERENCE(1522, 'n' _ 'u' _ 'm' _ 's' _ 'p' _ ';', 6, 0x2007, 1) -NAMED_CHARACTER_REFERENCE(1523, 'n' _ 'v' _ 'D' _ 'a' _ 's' _ 'h' _ ';', 7, 0x22ad, 1) -NAMED_CHARACTER_REFERENCE(1524, 'n' _ 'v' _ 'H' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x2904, 1) -NAMED_CHARACTER_REFERENCE(1525, 'n' _ 'v' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 7, 0x22ac, 1) -NAMED_CHARACTER_REFERENCE(1526, 'n' _ 'v' _ 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 8, 0x29de, 1) -NAMED_CHARACTER_REFERENCE(1527, 'n' _ 'v' _ 'l' _ 'A' _ 'r' _ 'r' _ ';', 7, 0x2902, 1) -NAMED_CHARACTER_REFERENCE(1528, 'n' _ 'v' _ 'r' _ 'A' _ 'r' _ 'r' _ ';', 7, 0x2903, 1) -NAMED_CHARACTER_REFERENCE(1529, 'n' _ 'w' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21d6, 1) -NAMED_CHARACTER_REFERENCE(1530, 'n' _ 'w' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, 0x2923, 1) -NAMED_CHARACTER_REFERENCE(1531, 'n' _ 'w' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2196, 1) -NAMED_CHARACTER_REFERENCE(1532, 'n' _ 'w' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2196, 1) -NAMED_CHARACTER_REFERENCE(1533, 'n' _ 'w' _ 'n' _ 'e' _ 'a' _ 'r' _ ';', 7, 0x2927, 1) -NAMED_CHARACTER_REFERENCE(1534, 'o' _ 'S' _ ';', 3, 0x24c8, 1) -NAMED_CHARACTER_REFERENCE(1535, 'o' _ 'a' _ 'c' _ 'u' _ 't' _ 'e', 6, 0x00f3, 1) -NAMED_CHARACTER_REFERENCE(1536, 'o' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x00f3, 1) -NAMED_CHARACTER_REFERENCE(1537, 'o' _ 'a' _ 's' _ 't' _ ';', 5, 0x229b, 1) -NAMED_CHARACTER_REFERENCE(1538, 'o' _ 'c' _ 'i' _ 'r' _ ';', 5, 0x229a, 1) -NAMED_CHARACTER_REFERENCE(1539, 'o' _ 'c' _ 'i' _ 'r' _ 'c', 5, 0x00f4, 1) -NAMED_CHARACTER_REFERENCE(1540, 'o' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x00f4, 1) -NAMED_CHARACTER_REFERENCE(1541, 'o' _ 'c' _ 'y' _ ';', 4, 0x043e, 1) -NAMED_CHARACTER_REFERENCE(1542, 'o' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 6, 0x229d, 1) -NAMED_CHARACTER_REFERENCE(1543, 'o' _ 'd' _ 'b' _ 'l' _ 'a' _ 'c' _ ';', 7, 0x0151, 1) -NAMED_CHARACTER_REFERENCE(1544, 'o' _ 'd' _ 'i' _ 'v' _ ';', 5, 0x2a38, 1) -NAMED_CHARACTER_REFERENCE(1545, 'o' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2299, 1) -NAMED_CHARACTER_REFERENCE(1546, 'o' _ 'd' _ 's' _ 'o' _ 'l' _ 'd' _ ';', 7, 0x29bc, 1) -NAMED_CHARACTER_REFERENCE(1547, 'o' _ 'e' _ 'l' _ 'i' _ 'g' _ ';', 6, 0x0153, 1) -NAMED_CHARACTER_REFERENCE(1548, 'o' _ 'f' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x29bf, 1) -NAMED_CHARACTER_REFERENCE(1549, 'o' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd2c, 2) -NAMED_CHARACTER_REFERENCE(1550, 'o' _ 'g' _ 'o' _ 'n' _ ';', 5, 0x02db, 1) -NAMED_CHARACTER_REFERENCE(1551, 'o' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e', 6, 0x00f2, 1) -NAMED_CHARACTER_REFERENCE(1552, 'o' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 7, 0x00f2, 1) -NAMED_CHARACTER_REFERENCE(1553, 'o' _ 'g' _ 't' _ ';', 4, 0x29c1, 1) -NAMED_CHARACTER_REFERENCE(1554, 'o' _ 'h' _ 'b' _ 'a' _ 'r' _ ';', 6, 0x29b5, 1) -NAMED_CHARACTER_REFERENCE(1555, 'o' _ 'h' _ 'm' _ ';', 4, 0x2126, 1) -NAMED_CHARACTER_REFERENCE(1556, 'o' _ 'i' _ 'n' _ 't' _ ';', 5, 0x222e, 1) -NAMED_CHARACTER_REFERENCE(1557, 'o' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21ba, 1) -NAMED_CHARACTER_REFERENCE(1558, 'o' _ 'l' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x29be, 1) -NAMED_CHARACTER_REFERENCE(1559, 'o' _ 'l' _ 'c' _ 'r' _ 'o' _ 's' _ 's' _ ';', 8, 0x29bb, 1) -NAMED_CHARACTER_REFERENCE(1560, 'o' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 6, 0x203e, 1) -NAMED_CHARACTER_REFERENCE(1561, 'o' _ 'l' _ 't' _ ';', 4, 0x29c0, 1) -NAMED_CHARACTER_REFERENCE(1562, 'o' _ 'm' _ 'a' _ 'c' _ 'r' _ ';', 6, 0x014d, 1) -NAMED_CHARACTER_REFERENCE(1563, 'o' _ 'm' _ 'e' _ 'g' _ 'a' _ ';', 6, 0x03c9, 1) -NAMED_CHARACTER_REFERENCE(1564, 'o' _ 'm' _ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 8, 0x03bf, 1) -NAMED_CHARACTER_REFERENCE(1565, 'o' _ 'm' _ 'i' _ 'd' _ ';', 5, 0x29b6, 1) -NAMED_CHARACTER_REFERENCE(1566, 'o' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0x2296, 1) -NAMED_CHARACTER_REFERENCE(1567, 'o' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd60, 2) -NAMED_CHARACTER_REFERENCE(1568, 'o' _ 'p' _ 'a' _ 'r' _ ';', 5, 0x29b7, 1) -NAMED_CHARACTER_REFERENCE(1569, 'o' _ 'p' _ 'e' _ 'r' _ 'p' _ ';', 6, 0x29b9, 1) -NAMED_CHARACTER_REFERENCE(1570, 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2295, 1) -NAMED_CHARACTER_REFERENCE(1571, 'o' _ 'r' _ ';', 3, 0x2228, 1) -NAMED_CHARACTER_REFERENCE(1572, 'o' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21bb, 1) -NAMED_CHARACTER_REFERENCE(1573, 'o' _ 'r' _ 'd' _ ';', 4, 0x2a5d, 1) -NAMED_CHARACTER_REFERENCE(1574, 'o' _ 'r' _ 'd' _ 'e' _ 'r' _ ';', 6, 0x2134, 1) -NAMED_CHARACTER_REFERENCE(1575, 'o' _ 'r' _ 'd' _ 'e' _ 'r' _ 'o' _ 'f' _ ';', 8, 0x2134, 1) -NAMED_CHARACTER_REFERENCE(1576, 'o' _ 'r' _ 'd' _ 'f', 4, 0x00aa, 1) -NAMED_CHARACTER_REFERENCE(1577, 'o' _ 'r' _ 'd' _ 'f' _ ';', 5, 0x00aa, 1) -NAMED_CHARACTER_REFERENCE(1578, 'o' _ 'r' _ 'd' _ 'm', 4, 0x00ba, 1) -NAMED_CHARACTER_REFERENCE(1579, 'o' _ 'r' _ 'd' _ 'm' _ ';', 5, 0x00ba, 1) -NAMED_CHARACTER_REFERENCE(1580, 'o' _ 'r' _ 'i' _ 'g' _ 'o' _ 'f' _ ';', 7, 0x22b6, 1) -NAMED_CHARACTER_REFERENCE(1581, 'o' _ 'r' _ 'o' _ 'r' _ ';', 5, 0x2a56, 1) -NAMED_CHARACTER_REFERENCE(1582, 'o' _ 'r' _ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 8, 0x2a57, 1) -NAMED_CHARACTER_REFERENCE(1583, 'o' _ 'r' _ 'v' _ ';', 4, 0x2a5b, 1) -NAMED_CHARACTER_REFERENCE(1584, 'o' _ 's' _ 'c' _ 'r' _ ';', 5, 0x2134, 1) -NAMED_CHARACTER_REFERENCE(1585, 'o' _ 's' _ 'l' _ 'a' _ 's' _ 'h', 6, 0x00f8, 1) -NAMED_CHARACTER_REFERENCE(1586, 'o' _ 's' _ 'l' _ 'a' _ 's' _ 'h' _ ';', 7, 0x00f8, 1) -NAMED_CHARACTER_REFERENCE(1587, 'o' _ 's' _ 'o' _ 'l' _ ';', 5, 0x2298, 1) -NAMED_CHARACTER_REFERENCE(1588, 'o' _ 't' _ 'i' _ 'l' _ 'd' _ 'e', 6, 0x00f5, 1) -NAMED_CHARACTER_REFERENCE(1589, 'o' _ 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x00f5, 1) -NAMED_CHARACTER_REFERENCE(1590, 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0x2297, 1) -NAMED_CHARACTER_REFERENCE(1591, 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ 'a' _ 's' _ ';', 9, 0x2a36, 1) -NAMED_CHARACTER_REFERENCE(1592, 'o' _ 'u' _ 'm' _ 'l', 4, 0x00f6, 1) -NAMED_CHARACTER_REFERENCE(1593, 'o' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00f6, 1) -NAMED_CHARACTER_REFERENCE(1594, 'o' _ 'v' _ 'b' _ 'a' _ 'r' _ ';', 6, 0x233d, 1) -NAMED_CHARACTER_REFERENCE(1595, 'p' _ 'a' _ 'r' _ ';', 4, 0x2225, 1) -NAMED_CHARACTER_REFERENCE(1596, 'p' _ 'a' _ 'r' _ 'a', 4, 0x00b6, 1) -NAMED_CHARACTER_REFERENCE(1597, 'p' _ 'a' _ 'r' _ 'a' _ ';', 5, 0x00b6, 1) -NAMED_CHARACTER_REFERENCE(1598, 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 9, 0x2225, 1) -NAMED_CHARACTER_REFERENCE(1599, 'p' _ 'a' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 7, 0x2af3, 1) -NAMED_CHARACTER_REFERENCE(1600, 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 6, 0x2afd, 1) -NAMED_CHARACTER_REFERENCE(1601, 'p' _ 'a' _ 'r' _ 't' _ ';', 5, 0x2202, 1) -NAMED_CHARACTER_REFERENCE(1602, 'p' _ 'c' _ 'y' _ ';', 4, 0x043f, 1) -NAMED_CHARACTER_REFERENCE(1603, 'p' _ 'e' _ 'r' _ 'c' _ 'n' _ 't' _ ';', 7, 0x0025, 1) -NAMED_CHARACTER_REFERENCE(1604, 'p' _ 'e' _ 'r' _ 'i' _ 'o' _ 'd' _ ';', 7, 0x002e, 1) -NAMED_CHARACTER_REFERENCE(1605, 'p' _ 'e' _ 'r' _ 'm' _ 'i' _ 'l' _ ';', 7, 0x2030, 1) -NAMED_CHARACTER_REFERENCE(1606, 'p' _ 'e' _ 'r' _ 'p' _ ';', 5, 0x22a5, 1) -NAMED_CHARACTER_REFERENCE(1607, 'p' _ 'e' _ 'r' _ 't' _ 'e' _ 'n' _ 'k' _ ';', 8, 0x2031, 1) -NAMED_CHARACTER_REFERENCE(1608, 'p' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd2d, 2) -NAMED_CHARACTER_REFERENCE(1609, 'p' _ 'h' _ 'i' _ ';', 4, 0x03c6, 1) -NAMED_CHARACTER_REFERENCE(1610, 'p' _ 'h' _ 'i' _ 'v' _ ';', 5, 0x03c6, 1) -NAMED_CHARACTER_REFERENCE(1611, 'p' _ 'h' _ 'm' _ 'm' _ 'a' _ 't' _ ';', 7, 0x2133, 1) -NAMED_CHARACTER_REFERENCE(1612, 'p' _ 'h' _ 'o' _ 'n' _ 'e' _ ';', 6, 0x260e, 1) -NAMED_CHARACTER_REFERENCE(1613, 'p' _ 'i' _ ';', 3, 0x03c0, 1) -NAMED_CHARACTER_REFERENCE(1614, 'p' _ 'i' _ 't' _ 'c' _ 'h' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 10, 0x22d4, 1) -NAMED_CHARACTER_REFERENCE(1615, 'p' _ 'i' _ 'v' _ ';', 4, 0x03d6, 1) -NAMED_CHARACTER_REFERENCE(1616, 'p' _ 'l' _ 'a' _ 'n' _ 'c' _ 'k' _ ';', 7, 0x210f, 1) -NAMED_CHARACTER_REFERENCE(1617, 'p' _ 'l' _ 'a' _ 'n' _ 'c' _ 'k' _ 'h' _ ';', 8, 0x210e, 1) -NAMED_CHARACTER_REFERENCE(1618, 'p' _ 'l' _ 'a' _ 'n' _ 'k' _ 'v' _ ';', 7, 0x210f, 1) -NAMED_CHARACTER_REFERENCE(1619, 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x002b, 1) -NAMED_CHARACTER_REFERENCE(1620, 'p' _ 'l' _ 'u' _ 's' _ 'a' _ 'c' _ 'i' _ 'r' _ ';', 9, 0x2a23, 1) -NAMED_CHARACTER_REFERENCE(1621, 'p' _ 'l' _ 'u' _ 's' _ 'b' _ ';', 6, 0x229e, 1) -NAMED_CHARACTER_REFERENCE(1622, 'p' _ 'l' _ 'u' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 8, 0x2a22, 1) -NAMED_CHARACTER_REFERENCE(1623, 'p' _ 'l' _ 'u' _ 's' _ 'd' _ 'o' _ ';', 7, 0x2214, 1) -NAMED_CHARACTER_REFERENCE(1624, 'p' _ 'l' _ 'u' _ 's' _ 'd' _ 'u' _ ';', 7, 0x2a25, 1) -NAMED_CHARACTER_REFERENCE(1625, 'p' _ 'l' _ 'u' _ 's' _ 'e' _ ';', 6, 0x2a72, 1) -NAMED_CHARACTER_REFERENCE(1626, 'p' _ 'l' _ 'u' _ 's' _ 'm' _ 'n', 6, 0x00b1, 1) -NAMED_CHARACTER_REFERENCE(1627, 'p' _ 'l' _ 'u' _ 's' _ 'm' _ 'n' _ ';', 7, 0x00b1, 1) -NAMED_CHARACTER_REFERENCE(1628, 'p' _ 'l' _ 'u' _ 's' _ 's' _ 'i' _ 'm' _ ';', 8, 0x2a26, 1) -NAMED_CHARACTER_REFERENCE(1629, 'p' _ 'l' _ 'u' _ 's' _ 't' _ 'w' _ 'o' _ ';', 8, 0x2a27, 1) -NAMED_CHARACTER_REFERENCE(1630, 'p' _ 'm' _ ';', 3, 0x00b1, 1) -NAMED_CHARACTER_REFERENCE(1631, 'p' _ 'o' _ 'i' _ 'n' _ 't' _ 'i' _ 'n' _ 't' _ ';', 9, 0x2a15, 1) -NAMED_CHARACTER_REFERENCE(1632, 'p' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd61, 2) -NAMED_CHARACTER_REFERENCE(1633, 'p' _ 'o' _ 'u' _ 'n' _ 'd', 5, 0x00a3, 1) -NAMED_CHARACTER_REFERENCE(1634, 'p' _ 'o' _ 'u' _ 'n' _ 'd' _ ';', 6, 0x00a3, 1) -NAMED_CHARACTER_REFERENCE(1635, 'p' _ 'r' _ ';', 3, 0x227a, 1) -NAMED_CHARACTER_REFERENCE(1636, 'p' _ 'r' _ 'E' _ ';', 4, 0x2ab3, 1) -NAMED_CHARACTER_REFERENCE(1637, 'p' _ 'r' _ 'a' _ 'p' _ ';', 5, 0x2ab7, 1) -NAMED_CHARACTER_REFERENCE(1638, 'p' _ 'r' _ 'c' _ 'u' _ 'e' _ ';', 6, 0x227c, 1) -NAMED_CHARACTER_REFERENCE(1639, 'p' _ 'r' _ 'e' _ ';', 4, 0x2aaf, 1) -NAMED_CHARACTER_REFERENCE(1640, 'p' _ 'r' _ 'e' _ 'c' _ ';', 5, 0x227a, 1) -NAMED_CHARACTER_REFERENCE(1641, 'p' _ 'r' _ 'e' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 11, 0x2ab7, 1) -NAMED_CHARACTER_REFERENCE(1642, 'p' _ 'r' _ 'e' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 12, 0x227c, 1) -NAMED_CHARACTER_REFERENCE(1643, 'p' _ 'r' _ 'e' _ 'c' _ 'e' _ 'q' _ ';', 7, 0x2aaf, 1) -NAMED_CHARACTER_REFERENCE(1644, 'p' _ 'r' _ 'e' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 12, 0x2ab9, 1) -NAMED_CHARACTER_REFERENCE(1645, 'p' _ 'r' _ 'e' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0x2ab5, 1) -NAMED_CHARACTER_REFERENCE(1646, 'p' _ 'r' _ 'e' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 9, 0x22e8, 1) -NAMED_CHARACTER_REFERENCE(1647, 'p' _ 'r' _ 'e' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 8, 0x227e, 1) -NAMED_CHARACTER_REFERENCE(1648, 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x2032, 1) -NAMED_CHARACTER_REFERENCE(1649, 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0x2119, 1) -NAMED_CHARACTER_REFERENCE(1650, 'p' _ 'r' _ 'n' _ 'E' _ ';', 5, 0x2ab5, 1) -NAMED_CHARACTER_REFERENCE(1651, 'p' _ 'r' _ 'n' _ 'a' _ 'p' _ ';', 6, 0x2ab9, 1) -NAMED_CHARACTER_REFERENCE(1652, 'p' _ 'r' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, 0x22e8, 1) -NAMED_CHARACTER_REFERENCE(1653, 'p' _ 'r' _ 'o' _ 'd' _ ';', 5, 0x220f, 1) -NAMED_CHARACTER_REFERENCE(1654, 'p' _ 'r' _ 'o' _ 'f' _ 'a' _ 'l' _ 'a' _ 'r' _ ';', 9, 0x232e, 1) -NAMED_CHARACTER_REFERENCE(1655, 'p' _ 'r' _ 'o' _ 'f' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 9, 0x2312, 1) -NAMED_CHARACTER_REFERENCE(1656, 'p' _ 'r' _ 'o' _ 'f' _ 's' _ 'u' _ 'r' _ 'f' _ ';', 9, 0x2313, 1) -NAMED_CHARACTER_REFERENCE(1657, 'p' _ 'r' _ 'o' _ 'p' _ ';', 5, 0x221d, 1) -NAMED_CHARACTER_REFERENCE(1658, 'p' _ 'r' _ 'o' _ 'p' _ 't' _ 'o' _ ';', 7, 0x221d, 1) -NAMED_CHARACTER_REFERENCE(1659, 'p' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0x227e, 1) -NAMED_CHARACTER_REFERENCE(1660, 'p' _ 'r' _ 'u' _ 'r' _ 'e' _ 'l' _ ';', 7, 0x22b0, 1) -NAMED_CHARACTER_REFERENCE(1661, 'p' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc5, 2) -NAMED_CHARACTER_REFERENCE(1662, 'p' _ 's' _ 'i' _ ';', 4, 0x03c8, 1) -NAMED_CHARACTER_REFERENCE(1663, 'p' _ 'u' _ 'n' _ 'c' _ 's' _ 'p' _ ';', 7, 0x2008, 1) -NAMED_CHARACTER_REFERENCE(1664, 'q' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd2e, 2) -NAMED_CHARACTER_REFERENCE(1665, 'q' _ 'i' _ 'n' _ 't' _ ';', 5, 0x2a0c, 1) -NAMED_CHARACTER_REFERENCE(1666, 'q' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd62, 2) -NAMED_CHARACTER_REFERENCE(1667, 'q' _ 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 7, 0x2057, 1) -NAMED_CHARACTER_REFERENCE(1668, 'q' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc6, 2) -NAMED_CHARACTER_REFERENCE(1669, 'q' _ 'u' _ 'a' _ 't' _ 'e' _ 'r' _ 'n' _ 'i' _ 'o' _ 'n' _ 's' _ ';', 12, 0x210d, 1) -NAMED_CHARACTER_REFERENCE(1670, 'q' _ 'u' _ 'a' _ 't' _ 'i' _ 'n' _ 't' _ ';', 8, 0x2a16, 1) -NAMED_CHARACTER_REFERENCE(1671, 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0x003f, 1) -NAMED_CHARACTER_REFERENCE(1672, 'q' _ 'u' _ 'e' _ 's' _ 't' _ 'e' _ 'q' _ ';', 8, 0x225f, 1) -NAMED_CHARACTER_REFERENCE(1673, 'q' _ 'u' _ 'o' _ 't', 4, 0x0022, 1) -NAMED_CHARACTER_REFERENCE(1674, 'q' _ 'u' _ 'o' _ 't' _ ';', 5, 0x0022, 1) -NAMED_CHARACTER_REFERENCE(1675, 'r' _ 'A' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21db, 1) -NAMED_CHARACTER_REFERENCE(1676, 'r' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d2, 1) -NAMED_CHARACTER_REFERENCE(1677, 'r' _ 'A' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 7, 0x291c, 1) -NAMED_CHARACTER_REFERENCE(1678, 'r' _ 'B' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x290f, 1) -NAMED_CHARACTER_REFERENCE(1679, 'r' _ 'H' _ 'a' _ 'r' _ ';', 5, 0x2964, 1) -NAMED_CHARACTER_REFERENCE(1680, 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0x29da, 1) +NAMED_CHARACTER_REFERENCE(789, 'b' _ 's' _ 'o' _ 'l' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 9, 0x27c8, 1) +NAMED_CHARACTER_REFERENCE(790, 'b' _ 'u' _ 'l' _ 'l' _ ';', 5, 0x2022, 1) +NAMED_CHARACTER_REFERENCE(791, 'b' _ 'u' _ 'l' _ 'l' _ 'e' _ 't' _ ';', 7, 0x2022, 1) +NAMED_CHARACTER_REFERENCE(792, 'b' _ 'u' _ 'm' _ 'p' _ ';', 5, 0x224e, 1) +NAMED_CHARACTER_REFERENCE(793, 'b' _ 'u' _ 'm' _ 'p' _ 'E' _ ';', 6, 0x2aae, 1) +NAMED_CHARACTER_REFERENCE(794, 'b' _ 'u' _ 'm' _ 'p' _ 'e' _ ';', 6, 0x224f, 1) +NAMED_CHARACTER_REFERENCE(795, 'b' _ 'u' _ 'm' _ 'p' _ 'e' _ 'q' _ ';', 7, 0x224f, 1) +NAMED_CHARACTER_REFERENCE(796, 'c' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x0107, 1) +NAMED_CHARACTER_REFERENCE(797, 'c' _ 'a' _ 'p' _ ';', 4, 0x2229, 1) +NAMED_CHARACTER_REFERENCE(798, 'c' _ 'a' _ 'p' _ 'a' _ 'n' _ 'd' _ ';', 7, 0x2a44, 1) +NAMED_CHARACTER_REFERENCE(799, 'c' _ 'a' _ 'p' _ 'b' _ 'r' _ 'c' _ 'u' _ 'p' _ ';', 9, 0x2a49, 1) +NAMED_CHARACTER_REFERENCE(800, 'c' _ 'a' _ 'p' _ 'c' _ 'a' _ 'p' _ ';', 7, 0x2a4b, 1) +NAMED_CHARACTER_REFERENCE(801, 'c' _ 'a' _ 'p' _ 'c' _ 'u' _ 'p' _ ';', 7, 0x2a47, 1) +NAMED_CHARACTER_REFERENCE(802, 'c' _ 'a' _ 'p' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a40, 1) +NAMED_CHARACTER_REFERENCE(803, 'c' _ 'a' _ 'r' _ 'e' _ 't' _ ';', 6, 0x2041, 1) +NAMED_CHARACTER_REFERENCE(804, 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 6, 0x02c7, 1) +NAMED_CHARACTER_REFERENCE(805, 'c' _ 'c' _ 'a' _ 'p' _ 's' _ ';', 6, 0x2a4d, 1) +NAMED_CHARACTER_REFERENCE(806, 'c' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x010d, 1) +NAMED_CHARACTER_REFERENCE(807, 'c' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l', 6, 0x00e7, 1) +NAMED_CHARACTER_REFERENCE(808, 'c' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 7, 0x00e7, 1) +NAMED_CHARACTER_REFERENCE(809, 'c' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x0109, 1) +NAMED_CHARACTER_REFERENCE(810, 'c' _ 'c' _ 'u' _ 'p' _ 's' _ ';', 6, 0x2a4c, 1) +NAMED_CHARACTER_REFERENCE(811, 'c' _ 'c' _ 'u' _ 'p' _ 's' _ 's' _ 'm' _ ';', 8, 0x2a50, 1) +NAMED_CHARACTER_REFERENCE(812, 'c' _ 'd' _ 'o' _ 't' _ ';', 5, 0x010b, 1) +NAMED_CHARACTER_REFERENCE(813, 'c' _ 'e' _ 'd' _ 'i' _ 'l', 5, 0x00b8, 1) +NAMED_CHARACTER_REFERENCE(814, 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 6, 0x00b8, 1) +NAMED_CHARACTER_REFERENCE(815, 'c' _ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 8, 0x29b2, 1) +NAMED_CHARACTER_REFERENCE(816, 'c' _ 'e' _ 'n' _ 't', 4, 0x00a2, 1) +NAMED_CHARACTER_REFERENCE(817, 'c' _ 'e' _ 'n' _ 't' _ ';', 5, 0x00a2, 1) +NAMED_CHARACTER_REFERENCE(818, 'c' _ 'e' _ 'n' _ 't' _ 'e' _ 'r' _ 'd' _ 'o' _ 't' _ ';', 10, 0x00b7, 1) +NAMED_CHARACTER_REFERENCE(819, 'c' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd20, 2) +NAMED_CHARACTER_REFERENCE(820, 'c' _ 'h' _ 'c' _ 'y' _ ';', 5, 0x0447, 1) +NAMED_CHARACTER_REFERENCE(821, 'c' _ 'h' _ 'e' _ 'c' _ 'k' _ ';', 6, 0x2713, 1) +NAMED_CHARACTER_REFERENCE(822, 'c' _ 'h' _ 'e' _ 'c' _ 'k' _ 'm' _ 'a' _ 'r' _ 'k' _ ';', 10, 0x2713, 1) +NAMED_CHARACTER_REFERENCE(823, 'c' _ 'h' _ 'i' _ ';', 4, 0x03c7, 1) +NAMED_CHARACTER_REFERENCE(824, 'c' _ 'i' _ 'r' _ ';', 4, 0x25cb, 1) +NAMED_CHARACTER_REFERENCE(825, 'c' _ 'i' _ 'r' _ 'E' _ ';', 5, 0x29c3, 1) +NAMED_CHARACTER_REFERENCE(826, 'c' _ 'i' _ 'r' _ 'c' _ ';', 5, 0x02c6, 1) +NAMED_CHARACTER_REFERENCE(827, 'c' _ 'i' _ 'r' _ 'c' _ 'e' _ 'q' _ ';', 7, 0x2257, 1) +NAMED_CHARACTER_REFERENCE(828, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 16, 0x21ba, 1) +NAMED_CHARACTER_REFERENCE(829, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 17, 0x21bb, 1) +NAMED_CHARACTER_REFERENCE(830, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'R' _ ';', 9, 0x00ae, 1) +NAMED_CHARACTER_REFERENCE(831, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'S' _ ';', 9, 0x24c8, 1) +NAMED_CHARACTER_REFERENCE(832, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'a' _ 's' _ 't' _ ';', 11, 0x229b, 1) +NAMED_CHARACTER_REFERENCE(833, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 12, 0x229a, 1) +NAMED_CHARACTER_REFERENCE(834, 'c' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 12, 0x229d, 1) +NAMED_CHARACTER_REFERENCE(835, 'c' _ 'i' _ 'r' _ 'e' _ ';', 5, 0x2257, 1) +NAMED_CHARACTER_REFERENCE(836, 'c' _ 'i' _ 'r' _ 'f' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 9, 0x2a10, 1) +NAMED_CHARACTER_REFERENCE(837, 'c' _ 'i' _ 'r' _ 'm' _ 'i' _ 'd' _ ';', 7, 0x2aef, 1) +NAMED_CHARACTER_REFERENCE(838, 'c' _ 'i' _ 'r' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 8, 0x29c2, 1) +NAMED_CHARACTER_REFERENCE(839, 'c' _ 'l' _ 'u' _ 'b' _ 's' _ ';', 6, 0x2663, 1) +NAMED_CHARACTER_REFERENCE(840, 'c' _ 'l' _ 'u' _ 'b' _ 's' _ 'u' _ 'i' _ 't' _ ';', 9, 0x2663, 1) +NAMED_CHARACTER_REFERENCE(841, 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x003a, 1) +NAMED_CHARACTER_REFERENCE(842, 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ 'e' _ ';', 7, 0x2254, 1) +NAMED_CHARACTER_REFERENCE(843, 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ 'e' _ 'q' _ ';', 8, 0x2254, 1) +NAMED_CHARACTER_REFERENCE(844, 'c' _ 'o' _ 'm' _ 'm' _ 'a' _ ';', 6, 0x002c, 1) +NAMED_CHARACTER_REFERENCE(845, 'c' _ 'o' _ 'm' _ 'm' _ 'a' _ 't' _ ';', 7, 0x0040, 1) +NAMED_CHARACTER_REFERENCE(846, 'c' _ 'o' _ 'm' _ 'p' _ ';', 5, 0x2201, 1) +NAMED_CHARACTER_REFERENCE(847, 'c' _ 'o' _ 'm' _ 'p' _ 'f' _ 'n' _ ';', 7, 0x2218, 1) +NAMED_CHARACTER_REFERENCE(848, 'c' _ 'o' _ 'm' _ 'p' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 11, 0x2201, 1) +NAMED_CHARACTER_REFERENCE(849, 'c' _ 'o' _ 'm' _ 'p' _ 'l' _ 'e' _ 'x' _ 'e' _ 's' _ ';', 10, 0x2102, 1) +NAMED_CHARACTER_REFERENCE(850, 'c' _ 'o' _ 'n' _ 'g' _ ';', 5, 0x2245, 1) +NAMED_CHARACTER_REFERENCE(851, 'c' _ 'o' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ ';', 8, 0x2a6d, 1) +NAMED_CHARACTER_REFERENCE(852, 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0x222e, 1) +NAMED_CHARACTER_REFERENCE(853, 'c' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd54, 2) +NAMED_CHARACTER_REFERENCE(854, 'c' _ 'o' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 7, 0x2210, 1) +NAMED_CHARACTER_REFERENCE(855, 'c' _ 'o' _ 'p' _ 'y', 4, 0x00a9, 1) +NAMED_CHARACTER_REFERENCE(856, 'c' _ 'o' _ 'p' _ 'y' _ ';', 5, 0x00a9, 1) +NAMED_CHARACTER_REFERENCE(857, 'c' _ 'o' _ 'p' _ 'y' _ 's' _ 'r' _ ';', 7, 0x2117, 1) +NAMED_CHARACTER_REFERENCE(858, 'c' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21b5, 1) +NAMED_CHARACTER_REFERENCE(859, 'c' _ 'r' _ 'o' _ 's' _ 's' _ ';', 6, 0x2717, 1) +NAMED_CHARACTER_REFERENCE(860, 'c' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcb8, 2) +NAMED_CHARACTER_REFERENCE(861, 'c' _ 's' _ 'u' _ 'b' _ ';', 5, 0x2acf, 1) +NAMED_CHARACTER_REFERENCE(862, 'c' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 6, 0x2ad1, 1) +NAMED_CHARACTER_REFERENCE(863, 'c' _ 's' _ 'u' _ 'p' _ ';', 5, 0x2ad0, 1) +NAMED_CHARACTER_REFERENCE(864, 'c' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 6, 0x2ad2, 1) +NAMED_CHARACTER_REFERENCE(865, 'c' _ 't' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22ef, 1) +NAMED_CHARACTER_REFERENCE(866, 'c' _ 'u' _ 'd' _ 'a' _ 'r' _ 'r' _ 'l' _ ';', 8, 0x2938, 1) +NAMED_CHARACTER_REFERENCE(867, 'c' _ 'u' _ 'd' _ 'a' _ 'r' _ 'r' _ 'r' _ ';', 8, 0x2935, 1) +NAMED_CHARACTER_REFERENCE(868, 'c' _ 'u' _ 'e' _ 'p' _ 'r' _ ';', 6, 0x22de, 1) +NAMED_CHARACTER_REFERENCE(869, 'c' _ 'u' _ 'e' _ 's' _ 'c' _ ';', 6, 0x22df, 1) +NAMED_CHARACTER_REFERENCE(870, 'c' _ 'u' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x21b6, 1) +NAMED_CHARACTER_REFERENCE(871, 'c' _ 'u' _ 'l' _ 'a' _ 'r' _ 'r' _ 'p' _ ';', 8, 0x293d, 1) +NAMED_CHARACTER_REFERENCE(872, 'c' _ 'u' _ 'p' _ ';', 4, 0x222a, 1) +NAMED_CHARACTER_REFERENCE(873, 'c' _ 'u' _ 'p' _ 'b' _ 'r' _ 'c' _ 'a' _ 'p' _ ';', 9, 0x2a48, 1) +NAMED_CHARACTER_REFERENCE(874, 'c' _ 'u' _ 'p' _ 'c' _ 'a' _ 'p' _ ';', 7, 0x2a46, 1) +NAMED_CHARACTER_REFERENCE(875, 'c' _ 'u' _ 'p' _ 'c' _ 'u' _ 'p' _ ';', 7, 0x2a4a, 1) +NAMED_CHARACTER_REFERENCE(876, 'c' _ 'u' _ 'p' _ 'd' _ 'o' _ 't' _ ';', 7, 0x228d, 1) +NAMED_CHARACTER_REFERENCE(877, 'c' _ 'u' _ 'p' _ 'o' _ 'r' _ ';', 6, 0x2a45, 1) +NAMED_CHARACTER_REFERENCE(878, 'c' _ 'u' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x21b7, 1) +NAMED_CHARACTER_REFERENCE(879, 'c' _ 'u' _ 'r' _ 'a' _ 'r' _ 'r' _ 'm' _ ';', 8, 0x293c, 1) +NAMED_CHARACTER_REFERENCE(880, 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 'p' _ 'r' _ 'e' _ 'c' _ ';', 12, 0x22de, 1) +NAMED_CHARACTER_REFERENCE(881, 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 's' _ 'u' _ 'c' _ 'c' _ ';', 12, 0x22df, 1) +NAMED_CHARACTER_REFERENCE(882, 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'v' _ 'e' _ 'e' _ ';', 9, 0x22ce, 1) +NAMED_CHARACTER_REFERENCE(883, 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 11, 0x22cf, 1) +NAMED_CHARACTER_REFERENCE(884, 'c' _ 'u' _ 'r' _ 'r' _ 'e' _ 'n', 6, 0x00a4, 1) +NAMED_CHARACTER_REFERENCE(885, 'c' _ 'u' _ 'r' _ 'r' _ 'e' _ 'n' _ ';', 7, 0x00a4, 1) +NAMED_CHARACTER_REFERENCE(886, 'c' _ 'u' _ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 15, 0x21b6, 1) +NAMED_CHARACTER_REFERENCE(887, 'c' _ 'u' _ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 16, 0x21b7, 1) +NAMED_CHARACTER_REFERENCE(888, 'c' _ 'u' _ 'v' _ 'e' _ 'e' _ ';', 6, 0x22ce, 1) +NAMED_CHARACTER_REFERENCE(889, 'c' _ 'u' _ 'w' _ 'e' _ 'd' _ ';', 6, 0x22cf, 1) +NAMED_CHARACTER_REFERENCE(890, 'c' _ 'w' _ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 9, 0x2232, 1) +NAMED_CHARACTER_REFERENCE(891, 'c' _ 'w' _ 'i' _ 'n' _ 't' _ ';', 6, 0x2231, 1) +NAMED_CHARACTER_REFERENCE(892, 'c' _ 'y' _ 'l' _ 'c' _ 't' _ 'y' _ ';', 7, 0x232d, 1) +NAMED_CHARACTER_REFERENCE(893, 'd' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d3, 1) +NAMED_CHARACTER_REFERENCE(894, 'd' _ 'H' _ 'a' _ 'r' _ ';', 5, 0x2965, 1) +NAMED_CHARACTER_REFERENCE(895, 'd' _ 'a' _ 'g' _ 'g' _ 'e' _ 'r' _ ';', 7, 0x2020, 1) +NAMED_CHARACTER_REFERENCE(896, 'd' _ 'a' _ 'l' _ 'e' _ 't' _ 'h' _ ';', 7, 0x2138, 1) +NAMED_CHARACTER_REFERENCE(897, 'd' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2193, 1) +NAMED_CHARACTER_REFERENCE(898, 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0x2010, 1) +NAMED_CHARACTER_REFERENCE(899, 'd' _ 'a' _ 's' _ 'h' _ 'v' _ ';', 6, 0x22a3, 1) +NAMED_CHARACTER_REFERENCE(900, 'd' _ 'b' _ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x290f, 1) +NAMED_CHARACTER_REFERENCE(901, 'd' _ 'b' _ 'l' _ 'a' _ 'c' _ ';', 6, 0x02dd, 1) +NAMED_CHARACTER_REFERENCE(902, 'd' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x010f, 1) +NAMED_CHARACTER_REFERENCE(903, 'd' _ 'c' _ 'y' _ ';', 4, 0x0434, 1) +NAMED_CHARACTER_REFERENCE(904, 'd' _ 'd' _ ';', 3, 0x2146, 1) +NAMED_CHARACTER_REFERENCE(905, 'd' _ 'd' _ 'a' _ 'g' _ 'g' _ 'e' _ 'r' _ ';', 8, 0x2021, 1) +NAMED_CHARACTER_REFERENCE(906, 'd' _ 'd' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21ca, 1) +NAMED_CHARACTER_REFERENCE(907, 'd' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 8, 0x2a77, 1) +NAMED_CHARACTER_REFERENCE(908, 'd' _ 'e' _ 'g', 3, 0x00b0, 1) +NAMED_CHARACTER_REFERENCE(909, 'd' _ 'e' _ 'g' _ ';', 4, 0x00b0, 1) +NAMED_CHARACTER_REFERENCE(910, 'd' _ 'e' _ 'l' _ 't' _ 'a' _ ';', 6, 0x03b4, 1) +NAMED_CHARACTER_REFERENCE(911, 'd' _ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 8, 0x29b1, 1) +NAMED_CHARACTER_REFERENCE(912, 'd' _ 'f' _ 'i' _ 's' _ 'h' _ 't' _ ';', 7, 0x297f, 1) +NAMED_CHARACTER_REFERENCE(913, 'd' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd21, 2) +NAMED_CHARACTER_REFERENCE(914, 'd' _ 'h' _ 'a' _ 'r' _ 'l' _ ';', 6, 0x21c3, 1) +NAMED_CHARACTER_REFERENCE(915, 'd' _ 'h' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21c2, 1) +NAMED_CHARACTER_REFERENCE(916, 'd' _ 'i' _ 'a' _ 'm' _ ';', 5, 0x22c4, 1) +NAMED_CHARACTER_REFERENCE(917, 'd' _ 'i' _ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 8, 0x22c4, 1) +NAMED_CHARACTER_REFERENCE(918, 'd' _ 'i' _ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ 's' _ 'u' _ 'i' _ 't' _ ';', 12, 0x2666, 1) +NAMED_CHARACTER_REFERENCE(919, 'd' _ 'i' _ 'a' _ 'm' _ 's' _ ';', 6, 0x2666, 1) +NAMED_CHARACTER_REFERENCE(920, 'd' _ 'i' _ 'e' _ ';', 4, 0x00a8, 1) +NAMED_CHARACTER_REFERENCE(921, 'd' _ 'i' _ 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ ';', 8, 0x03dd, 1) +NAMED_CHARACTER_REFERENCE(922, 'd' _ 'i' _ 's' _ 'i' _ 'n' _ ';', 6, 0x22f2, 1) +NAMED_CHARACTER_REFERENCE(923, 'd' _ 'i' _ 'v' _ ';', 4, 0x00f7, 1) +NAMED_CHARACTER_REFERENCE(924, 'd' _ 'i' _ 'v' _ 'i' _ 'd' _ 'e', 6, 0x00f7, 1) +NAMED_CHARACTER_REFERENCE(925, 'd' _ 'i' _ 'v' _ 'i' _ 'd' _ 'e' _ ';', 7, 0x00f7, 1) +NAMED_CHARACTER_REFERENCE(926, 'd' _ 'i' _ 'v' _ 'i' _ 'd' _ 'e' _ 'o' _ 'n' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 14, 0x22c7, 1) +NAMED_CHARACTER_REFERENCE(927, 'd' _ 'i' _ 'v' _ 'o' _ 'n' _ 'x' _ ';', 7, 0x22c7, 1) +NAMED_CHARACTER_REFERENCE(928, 'd' _ 'j' _ 'c' _ 'y' _ ';', 5, 0x0452, 1) +NAMED_CHARACTER_REFERENCE(929, 'd' _ 'l' _ 'c' _ 'o' _ 'r' _ 'n' _ ';', 7, 0x231e, 1) +NAMED_CHARACTER_REFERENCE(930, 'd' _ 'l' _ 'c' _ 'r' _ 'o' _ 'p' _ ';', 7, 0x230d, 1) +NAMED_CHARACTER_REFERENCE(931, 'd' _ 'o' _ 'l' _ 'l' _ 'a' _ 'r' _ ';', 7, 0x0024, 1) +NAMED_CHARACTER_REFERENCE(932, 'd' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd55, 2) +NAMED_CHARACTER_REFERENCE(933, 'd' _ 'o' _ 't' _ ';', 4, 0x02d9, 1) +NAMED_CHARACTER_REFERENCE(934, 'd' _ 'o' _ 't' _ 'e' _ 'q' _ ';', 6, 0x2250, 1) +NAMED_CHARACTER_REFERENCE(935, 'd' _ 'o' _ 't' _ 'e' _ 'q' _ 'd' _ 'o' _ 't' _ ';', 9, 0x2251, 1) +NAMED_CHARACTER_REFERENCE(936, 'd' _ 'o' _ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 9, 0x2238, 1) +NAMED_CHARACTER_REFERENCE(937, 'd' _ 'o' _ 't' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 8, 0x2214, 1) +NAMED_CHARACTER_REFERENCE(938, 'd' _ 'o' _ 't' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 10, 0x22a1, 1) +NAMED_CHARACTER_REFERENCE(939, 'd' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'b' _ 'a' _ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 15, 0x2306, 1) +NAMED_CHARACTER_REFERENCE(940, 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x2193, 1) +NAMED_CHARACTER_REFERENCE(941, 'd' _ 'o' _ 'w' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 15, 0x21ca, 1) +NAMED_CHARACTER_REFERENCE(942, 'd' _ 'o' _ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 16, 0x21c3, 1) +NAMED_CHARACTER_REFERENCE(943, 'd' _ 'o' _ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 17, 0x21c2, 1) +NAMED_CHARACTER_REFERENCE(944, 'd' _ 'r' _ 'b' _ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x2910, 1) +NAMED_CHARACTER_REFERENCE(945, 'd' _ 'r' _ 'c' _ 'o' _ 'r' _ 'n' _ ';', 7, 0x231f, 1) +NAMED_CHARACTER_REFERENCE(946, 'd' _ 'r' _ 'c' _ 'r' _ 'o' _ 'p' _ ';', 7, 0x230c, 1) +NAMED_CHARACTER_REFERENCE(947, 'd' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcb9, 2) +NAMED_CHARACTER_REFERENCE(948, 'd' _ 's' _ 'c' _ 'y' _ ';', 5, 0x0455, 1) +NAMED_CHARACTER_REFERENCE(949, 'd' _ 's' _ 'o' _ 'l' _ ';', 5, 0x29f6, 1) +NAMED_CHARACTER_REFERENCE(950, 'd' _ 's' _ 't' _ 'r' _ 'o' _ 'k' _ ';', 7, 0x0111, 1) +NAMED_CHARACTER_REFERENCE(951, 'd' _ 't' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22f1, 1) +NAMED_CHARACTER_REFERENCE(952, 'd' _ 't' _ 'r' _ 'i' _ ';', 5, 0x25bf, 1) +NAMED_CHARACTER_REFERENCE(953, 'd' _ 't' _ 'r' _ 'i' _ 'f' _ ';', 6, 0x25be, 1) +NAMED_CHARACTER_REFERENCE(954, 'd' _ 'u' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21f5, 1) +NAMED_CHARACTER_REFERENCE(955, 'd' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x296f, 1) +NAMED_CHARACTER_REFERENCE(956, 'd' _ 'w' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 8, 0x29a6, 1) +NAMED_CHARACTER_REFERENCE(957, 'd' _ 'z' _ 'c' _ 'y' _ ';', 5, 0x045f, 1) +NAMED_CHARACTER_REFERENCE(958, 'd' _ 'z' _ 'i' _ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 9, 0x27ff, 1) +NAMED_CHARACTER_REFERENCE(959, 'e' _ 'D' _ 'D' _ 'o' _ 't' _ ';', 6, 0x2a77, 1) +NAMED_CHARACTER_REFERENCE(960, 'e' _ 'D' _ 'o' _ 't' _ ';', 5, 0x2251, 1) +NAMED_CHARACTER_REFERENCE(961, 'e' _ 'a' _ 'c' _ 'u' _ 't' _ 'e', 6, 0x00e9, 1) +NAMED_CHARACTER_REFERENCE(962, 'e' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x00e9, 1) +NAMED_CHARACTER_REFERENCE(963, 'e' _ 'a' _ 's' _ 't' _ 'e' _ 'r' _ ';', 7, 0x2a6e, 1) +NAMED_CHARACTER_REFERENCE(964, 'e' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x011b, 1) +NAMED_CHARACTER_REFERENCE(965, 'e' _ 'c' _ 'i' _ 'r' _ ';', 5, 0x2256, 1) +NAMED_CHARACTER_REFERENCE(966, 'e' _ 'c' _ 'i' _ 'r' _ 'c', 5, 0x00ea, 1) +NAMED_CHARACTER_REFERENCE(967, 'e' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x00ea, 1) +NAMED_CHARACTER_REFERENCE(968, 'e' _ 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 7, 0x2255, 1) +NAMED_CHARACTER_REFERENCE(969, 'e' _ 'c' _ 'y' _ ';', 4, 0x044d, 1) +NAMED_CHARACTER_REFERENCE(970, 'e' _ 'd' _ 'o' _ 't' _ ';', 5, 0x0117, 1) +NAMED_CHARACTER_REFERENCE(971, 'e' _ 'e' _ ';', 3, 0x2147, 1) +NAMED_CHARACTER_REFERENCE(972, 'e' _ 'f' _ 'D' _ 'o' _ 't' _ ';', 6, 0x2252, 1) +NAMED_CHARACTER_REFERENCE(973, 'e' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd22, 2) +NAMED_CHARACTER_REFERENCE(974, 'e' _ 'g' _ ';', 3, 0x2a9a, 1) +NAMED_CHARACTER_REFERENCE(975, 'e' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e', 6, 0x00e8, 1) +NAMED_CHARACTER_REFERENCE(976, 'e' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 7, 0x00e8, 1) +NAMED_CHARACTER_REFERENCE(977, 'e' _ 'g' _ 's' _ ';', 4, 0x2a96, 1) +NAMED_CHARACTER_REFERENCE(978, 'e' _ 'g' _ 's' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a98, 1) +NAMED_CHARACTER_REFERENCE(979, 'e' _ 'l' _ ';', 3, 0x2a99, 1) +NAMED_CHARACTER_REFERENCE(980, 'e' _ 'l' _ 'i' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ ';', 9, 0x23e7, 1) +NAMED_CHARACTER_REFERENCE(981, 'e' _ 'l' _ 'l' _ ';', 4, 0x2113, 1) +NAMED_CHARACTER_REFERENCE(982, 'e' _ 'l' _ 's' _ ';', 4, 0x2a95, 1) +NAMED_CHARACTER_REFERENCE(983, 'e' _ 'l' _ 's' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a97, 1) +NAMED_CHARACTER_REFERENCE(984, 'e' _ 'm' _ 'a' _ 'c' _ 'r' _ ';', 6, 0x0113, 1) +NAMED_CHARACTER_REFERENCE(985, 'e' _ 'm' _ 'p' _ 't' _ 'y' _ ';', 6, 0x2205, 1) +NAMED_CHARACTER_REFERENCE(986, 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 's' _ 'e' _ 't' _ ';', 9, 0x2205, 1) +NAMED_CHARACTER_REFERENCE(987, 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, 0x2205, 1) +NAMED_CHARACTER_REFERENCE(988, 'e' _ 'm' _ 's' _ 'p' _ '1' _ '3' _ ';', 7, 0x2004, 1) +NAMED_CHARACTER_REFERENCE(989, 'e' _ 'm' _ 's' _ 'p' _ '1' _ '4' _ ';', 7, 0x2005, 1) +NAMED_CHARACTER_REFERENCE(990, 'e' _ 'm' _ 's' _ 'p' _ ';', 5, 0x2003, 1) +NAMED_CHARACTER_REFERENCE(991, 'e' _ 'n' _ 'g' _ ';', 4, 0x014b, 1) +NAMED_CHARACTER_REFERENCE(992, 'e' _ 'n' _ 's' _ 'p' _ ';', 5, 0x2002, 1) +NAMED_CHARACTER_REFERENCE(993, 'e' _ 'o' _ 'g' _ 'o' _ 'n' _ ';', 6, 0x0119, 1) +NAMED_CHARACTER_REFERENCE(994, 'e' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd56, 2) +NAMED_CHARACTER_REFERENCE(995, 'e' _ 'p' _ 'a' _ 'r' _ ';', 5, 0x22d5, 1) +NAMED_CHARACTER_REFERENCE(996, 'e' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, 0x29e3, 1) +NAMED_CHARACTER_REFERENCE(997, 'e' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2a71, 1) +NAMED_CHARACTER_REFERENCE(998, 'e' _ 'p' _ 's' _ 'i' _ ';', 5, 0x03b5, 1) +NAMED_CHARACTER_REFERENCE(999, 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 8, 0x03b5, 1) +NAMED_CHARACTER_REFERENCE(1000, 'e' _ 'p' _ 's' _ 'i' _ 'v' _ ';', 6, 0x03f5, 1) +NAMED_CHARACTER_REFERENCE(1001, 'e' _ 'q' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 7, 0x2256, 1) +NAMED_CHARACTER_REFERENCE(1002, 'e' _ 'q' _ 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 8, 0x2255, 1) +NAMED_CHARACTER_REFERENCE(1003, 'e' _ 'q' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2242, 1) +NAMED_CHARACTER_REFERENCE(1004, 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'g' _ 't' _ 'r' _ ';', 11, 0x2a96, 1) +NAMED_CHARACTER_REFERENCE(1005, 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'l' _ 'e' _ 's' _ 's' _ ';', 12, 0x2a95, 1) +NAMED_CHARACTER_REFERENCE(1006, 'e' _ 'q' _ 'u' _ 'a' _ 'l' _ 's' _ ';', 7, 0x003d, 1) +NAMED_CHARACTER_REFERENCE(1007, 'e' _ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 7, 0x225f, 1) +NAMED_CHARACTER_REFERENCE(1008, 'e' _ 'q' _ 'u' _ 'i' _ 'v' _ ';', 6, 0x2261, 1) +NAMED_CHARACTER_REFERENCE(1009, 'e' _ 'q' _ 'u' _ 'i' _ 'v' _ 'D' _ 'D' _ ';', 8, 0x2a78, 1) +NAMED_CHARACTER_REFERENCE(1010, 'e' _ 'q' _ 'v' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 9, 0x29e5, 1) +NAMED_CHARACTER_REFERENCE(1011, 'e' _ 'r' _ 'D' _ 'o' _ 't' _ ';', 6, 0x2253, 1) +NAMED_CHARACTER_REFERENCE(1012, 'e' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2971, 1) +NAMED_CHARACTER_REFERENCE(1013, 'e' _ 's' _ 'c' _ 'r' _ ';', 5, 0x212f, 1) +NAMED_CHARACTER_REFERENCE(1014, 'e' _ 's' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2250, 1) +NAMED_CHARACTER_REFERENCE(1015, 'e' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2242, 1) +NAMED_CHARACTER_REFERENCE(1016, 'e' _ 't' _ 'a' _ ';', 4, 0x03b7, 1) +NAMED_CHARACTER_REFERENCE(1017, 'e' _ 't' _ 'h', 3, 0x00f0, 1) +NAMED_CHARACTER_REFERENCE(1018, 'e' _ 't' _ 'h' _ ';', 4, 0x00f0, 1) +NAMED_CHARACTER_REFERENCE(1019, 'e' _ 'u' _ 'm' _ 'l', 4, 0x00eb, 1) +NAMED_CHARACTER_REFERENCE(1020, 'e' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00eb, 1) +NAMED_CHARACTER_REFERENCE(1021, 'e' _ 'u' _ 'r' _ 'o' _ ';', 5, 0x20ac, 1) +NAMED_CHARACTER_REFERENCE(1022, 'e' _ 'x' _ 'c' _ 'l' _ ';', 5, 0x0021, 1) +NAMED_CHARACTER_REFERENCE(1023, 'e' _ 'x' _ 'i' _ 's' _ 't' _ ';', 6, 0x2203, 1) +NAMED_CHARACTER_REFERENCE(1024, 'e' _ 'x' _ 'p' _ 'e' _ 'c' _ 't' _ 'a' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 12, 0x2130, 1) +NAMED_CHARACTER_REFERENCE(1025, 'e' _ 'x' _ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'e' _ ';', 13, 0x2147, 1) +NAMED_CHARACTER_REFERENCE(1026, 'f' _ 'a' _ 'l' _ 'l' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 14, 0x2252, 1) +NAMED_CHARACTER_REFERENCE(1027, 'f' _ 'c' _ 'y' _ ';', 4, 0x0444, 1) +NAMED_CHARACTER_REFERENCE(1028, 'f' _ 'e' _ 'm' _ 'a' _ 'l' _ 'e' _ ';', 7, 0x2640, 1) +NAMED_CHARACTER_REFERENCE(1029, 'f' _ 'f' _ 'i' _ 'l' _ 'i' _ 'g' _ ';', 7, 0xfb03, 1) +NAMED_CHARACTER_REFERENCE(1030, 'f' _ 'f' _ 'l' _ 'i' _ 'g' _ ';', 6, 0xfb00, 1) +NAMED_CHARACTER_REFERENCE(1031, 'f' _ 'f' _ 'l' _ 'l' _ 'i' _ 'g' _ ';', 7, 0xfb04, 1) +NAMED_CHARACTER_REFERENCE(1032, 'f' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd23, 2) +NAMED_CHARACTER_REFERENCE(1033, 'f' _ 'i' _ 'l' _ 'i' _ 'g' _ ';', 6, 0xfb01, 1) +NAMED_CHARACTER_REFERENCE(1034, 'f' _ 'l' _ 'a' _ 't' _ ';', 5, 0x266d, 1) +NAMED_CHARACTER_REFERENCE(1035, 'f' _ 'l' _ 'l' _ 'i' _ 'g' _ ';', 6, 0xfb02, 1) +NAMED_CHARACTER_REFERENCE(1036, 'f' _ 'l' _ 't' _ 'n' _ 's' _ ';', 6, 0x25b1, 1) +NAMED_CHARACTER_REFERENCE(1037, 'f' _ 'n' _ 'o' _ 'f' _ ';', 5, 0x0192, 1) +NAMED_CHARACTER_REFERENCE(1038, 'f' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd57, 2) +NAMED_CHARACTER_REFERENCE(1039, 'f' _ 'o' _ 'r' _ 'a' _ 'l' _ 'l' _ ';', 7, 0x2200, 1) +NAMED_CHARACTER_REFERENCE(1040, 'f' _ 'o' _ 'r' _ 'k' _ ';', 5, 0x22d4, 1) +NAMED_CHARACTER_REFERENCE(1041, 'f' _ 'o' _ 'r' _ 'k' _ 'v' _ ';', 6, 0x2ad9, 1) +NAMED_CHARACTER_REFERENCE(1042, 'f' _ 'p' _ 'a' _ 'r' _ 't' _ 'i' _ 'n' _ 't' _ ';', 9, 0x2a0d, 1) +NAMED_CHARACTER_REFERENCE(1043, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '2', 6, 0x00bd, 1) +NAMED_CHARACTER_REFERENCE(1044, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '2' _ ';', 7, 0x00bd, 1) +NAMED_CHARACTER_REFERENCE(1045, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '3' _ ';', 7, 0x2153, 1) +NAMED_CHARACTER_REFERENCE(1046, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '4', 6, 0x00bc, 1) +NAMED_CHARACTER_REFERENCE(1047, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '4' _ ';', 7, 0x00bc, 1) +NAMED_CHARACTER_REFERENCE(1048, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '5' _ ';', 7, 0x2155, 1) +NAMED_CHARACTER_REFERENCE(1049, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '6' _ ';', 7, 0x2159, 1) +NAMED_CHARACTER_REFERENCE(1050, 'f' _ 'r' _ 'a' _ 'c' _ '1' _ '8' _ ';', 7, 0x215b, 1) +NAMED_CHARACTER_REFERENCE(1051, 'f' _ 'r' _ 'a' _ 'c' _ '2' _ '3' _ ';', 7, 0x2154, 1) +NAMED_CHARACTER_REFERENCE(1052, 'f' _ 'r' _ 'a' _ 'c' _ '2' _ '5' _ ';', 7, 0x2156, 1) +NAMED_CHARACTER_REFERENCE(1053, 'f' _ 'r' _ 'a' _ 'c' _ '3' _ '4', 6, 0x00be, 1) +NAMED_CHARACTER_REFERENCE(1054, 'f' _ 'r' _ 'a' _ 'c' _ '3' _ '4' _ ';', 7, 0x00be, 1) +NAMED_CHARACTER_REFERENCE(1055, 'f' _ 'r' _ 'a' _ 'c' _ '3' _ '5' _ ';', 7, 0x2157, 1) +NAMED_CHARACTER_REFERENCE(1056, 'f' _ 'r' _ 'a' _ 'c' _ '3' _ '8' _ ';', 7, 0x215c, 1) +NAMED_CHARACTER_REFERENCE(1057, 'f' _ 'r' _ 'a' _ 'c' _ '4' _ '5' _ ';', 7, 0x2158, 1) +NAMED_CHARACTER_REFERENCE(1058, 'f' _ 'r' _ 'a' _ 'c' _ '5' _ '6' _ ';', 7, 0x215a, 1) +NAMED_CHARACTER_REFERENCE(1059, 'f' _ 'r' _ 'a' _ 'c' _ '5' _ '8' _ ';', 7, 0x215d, 1) +NAMED_CHARACTER_REFERENCE(1060, 'f' _ 'r' _ 'a' _ 'c' _ '7' _ '8' _ ';', 7, 0x215e, 1) +NAMED_CHARACTER_REFERENCE(1061, 'f' _ 'r' _ 'a' _ 's' _ 'l' _ ';', 6, 0x2044, 1) +NAMED_CHARACTER_REFERENCE(1062, 'f' _ 'r' _ 'o' _ 'w' _ 'n' _ ';', 6, 0x2322, 1) +NAMED_CHARACTER_REFERENCE(1063, 'f' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcbb, 2) +NAMED_CHARACTER_REFERENCE(1064, 'g' _ 'E' _ ';', 3, 0x2267, 1) +NAMED_CHARACTER_REFERENCE(1065, 'g' _ 'E' _ 'l' _ ';', 4, 0x2a8c, 1) +NAMED_CHARACTER_REFERENCE(1066, 'g' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x01f5, 1) +NAMED_CHARACTER_REFERENCE(1067, 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ ';', 6, 0x03b3, 1) +NAMED_CHARACTER_REFERENCE(1068, 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ 'd' _ ';', 7, 0x03dd, 1) +NAMED_CHARACTER_REFERENCE(1069, 'g' _ 'a' _ 'p' _ ';', 4, 0x2a86, 1) +NAMED_CHARACTER_REFERENCE(1070, 'g' _ 'b' _ 'r' _ 'e' _ 'v' _ 'e' _ ';', 7, 0x011f, 1) +NAMED_CHARACTER_REFERENCE(1071, 'g' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x011d, 1) +NAMED_CHARACTER_REFERENCE(1072, 'g' _ 'c' _ 'y' _ ';', 4, 0x0433, 1) +NAMED_CHARACTER_REFERENCE(1073, 'g' _ 'd' _ 'o' _ 't' _ ';', 5, 0x0121, 1) +NAMED_CHARACTER_REFERENCE(1074, 'g' _ 'e' _ ';', 3, 0x2265, 1) +NAMED_CHARACTER_REFERENCE(1075, 'g' _ 'e' _ 'l' _ ';', 4, 0x22db, 1) +NAMED_CHARACTER_REFERENCE(1076, 'g' _ 'e' _ 'q' _ ';', 4, 0x2265, 1) +NAMED_CHARACTER_REFERENCE(1077, 'g' _ 'e' _ 'q' _ 'q' _ ';', 5, 0x2267, 1) +NAMED_CHARACTER_REFERENCE(1078, 'g' _ 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 9, 0x2a7e, 1) +NAMED_CHARACTER_REFERENCE(1079, 'g' _ 'e' _ 's' _ ';', 4, 0x2a7e, 1) +NAMED_CHARACTER_REFERENCE(1080, 'g' _ 'e' _ 's' _ 'c' _ 'c' _ ';', 6, 0x2aa9, 1) +NAMED_CHARACTER_REFERENCE(1081, 'g' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a80, 1) +NAMED_CHARACTER_REFERENCE(1082, 'g' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 8, 0x2a82, 1) +NAMED_CHARACTER_REFERENCE(1083, 'g' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'l' _ ';', 9, 0x2a84, 1) +NAMED_CHARACTER_REFERENCE(1084, 'g' _ 'e' _ 's' _ 'l' _ 'e' _ 's' _ ';', 7, 0x2a94, 1) +NAMED_CHARACTER_REFERENCE(1085, 'g' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd24, 2) +NAMED_CHARACTER_REFERENCE(1086, 'g' _ 'g' _ ';', 3, 0x226b, 1) +NAMED_CHARACTER_REFERENCE(1087, 'g' _ 'g' _ 'g' _ ';', 4, 0x22d9, 1) +NAMED_CHARACTER_REFERENCE(1088, 'g' _ 'i' _ 'm' _ 'e' _ 'l' _ ';', 6, 0x2137, 1) +NAMED_CHARACTER_REFERENCE(1089, 'g' _ 'j' _ 'c' _ 'y' _ ';', 5, 0x0453, 1) +NAMED_CHARACTER_REFERENCE(1090, 'g' _ 'l' _ ';', 3, 0x2277, 1) +NAMED_CHARACTER_REFERENCE(1091, 'g' _ 'l' _ 'E' _ ';', 4, 0x2a92, 1) +NAMED_CHARACTER_REFERENCE(1092, 'g' _ 'l' _ 'a' _ ';', 4, 0x2aa5, 1) +NAMED_CHARACTER_REFERENCE(1093, 'g' _ 'l' _ 'j' _ ';', 4, 0x2aa4, 1) +NAMED_CHARACTER_REFERENCE(1094, 'g' _ 'n' _ 'E' _ ';', 4, 0x2269, 1) +NAMED_CHARACTER_REFERENCE(1095, 'g' _ 'n' _ 'a' _ 'p' _ ';', 5, 0x2a8a, 1) +NAMED_CHARACTER_REFERENCE(1096, 'g' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0x2a8a, 1) +NAMED_CHARACTER_REFERENCE(1097, 'g' _ 'n' _ 'e' _ ';', 4, 0x2a88, 1) +NAMED_CHARACTER_REFERENCE(1098, 'g' _ 'n' _ 'e' _ 'q' _ ';', 5, 0x2a88, 1) +NAMED_CHARACTER_REFERENCE(1099, 'g' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 6, 0x2269, 1) +NAMED_CHARACTER_REFERENCE(1100, 'g' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 6, 0x22e7, 1) +NAMED_CHARACTER_REFERENCE(1101, 'g' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd58, 2) +NAMED_CHARACTER_REFERENCE(1102, 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 6, 0x0060, 1) +NAMED_CHARACTER_REFERENCE(1103, 'g' _ 's' _ 'c' _ 'r' _ ';', 5, 0x210a, 1) +NAMED_CHARACTER_REFERENCE(1104, 'g' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2273, 1) +NAMED_CHARACTER_REFERENCE(1105, 'g' _ 's' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x2a8e, 1) +NAMED_CHARACTER_REFERENCE(1106, 'g' _ 's' _ 'i' _ 'm' _ 'l' _ ';', 6, 0x2a90, 1) +NAMED_CHARACTER_REFERENCE(1107, 'g' _ 't', 2, 0x003e, 1) +NAMED_CHARACTER_REFERENCE(1108, 'g' _ 't' _ ';', 3, 0x003e, 1) +NAMED_CHARACTER_REFERENCE(1109, 'g' _ 't' _ 'c' _ 'c' _ ';', 5, 0x2aa7, 1) +NAMED_CHARACTER_REFERENCE(1110, 'g' _ 't' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x2a7a, 1) +NAMED_CHARACTER_REFERENCE(1111, 'g' _ 't' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22d7, 1) +NAMED_CHARACTER_REFERENCE(1112, 'g' _ 't' _ 'l' _ 'P' _ 'a' _ 'r' _ ';', 7, 0x2995, 1) +NAMED_CHARACTER_REFERENCE(1113, 'g' _ 't' _ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 8, 0x2a7c, 1) +NAMED_CHARACTER_REFERENCE(1114, 'g' _ 't' _ 'r' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0x2a86, 1) +NAMED_CHARACTER_REFERENCE(1115, 'g' _ 't' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x2978, 1) +NAMED_CHARACTER_REFERENCE(1116, 'g' _ 't' _ 'r' _ 'd' _ 'o' _ 't' _ ';', 7, 0x22d7, 1) +NAMED_CHARACTER_REFERENCE(1117, 'g' _ 't' _ 'r' _ 'e' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 10, 0x22db, 1) +NAMED_CHARACTER_REFERENCE(1118, 'g' _ 't' _ 'r' _ 'e' _ 'q' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 11, 0x2a8c, 1) +NAMED_CHARACTER_REFERENCE(1119, 'g' _ 't' _ 'r' _ 'l' _ 'e' _ 's' _ 's' _ ';', 8, 0x2277, 1) +NAMED_CHARACTER_REFERENCE(1120, 'g' _ 't' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 7, 0x2273, 1) +NAMED_CHARACTER_REFERENCE(1121, 'h' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d4, 1) +NAMED_CHARACTER_REFERENCE(1122, 'h' _ 'a' _ 'i' _ 'r' _ 's' _ 'p' _ ';', 7, 0x200a, 1) +NAMED_CHARACTER_REFERENCE(1123, 'h' _ 'a' _ 'l' _ 'f' _ ';', 5, 0x00bd, 1) +NAMED_CHARACTER_REFERENCE(1124, 'h' _ 'a' _ 'm' _ 'i' _ 'l' _ 't' _ ';', 7, 0x210b, 1) +NAMED_CHARACTER_REFERENCE(1125, 'h' _ 'a' _ 'r' _ 'd' _ 'c' _ 'y' _ ';', 7, 0x044a, 1) +NAMED_CHARACTER_REFERENCE(1126, 'h' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2194, 1) +NAMED_CHARACTER_REFERENCE(1127, 'h' _ 'a' _ 'r' _ 'r' _ 'c' _ 'i' _ 'r' _ ';', 8, 0x2948, 1) +NAMED_CHARACTER_REFERENCE(1128, 'h' _ 'a' _ 'r' _ 'r' _ 'w' _ ';', 6, 0x21ad, 1) +NAMED_CHARACTER_REFERENCE(1129, 'h' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x210f, 1) +NAMED_CHARACTER_REFERENCE(1130, 'h' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x0125, 1) +NAMED_CHARACTER_REFERENCE(1131, 'h' _ 'e' _ 'a' _ 'r' _ 't' _ 's' _ ';', 7, 0x2665, 1) +NAMED_CHARACTER_REFERENCE(1132, 'h' _ 'e' _ 'a' _ 'r' _ 't' _ 's' _ 'u' _ 'i' _ 't' _ ';', 10, 0x2665, 1) +NAMED_CHARACTER_REFERENCE(1133, 'h' _ 'e' _ 'l' _ 'l' _ 'i' _ 'p' _ ';', 7, 0x2026, 1) +NAMED_CHARACTER_REFERENCE(1134, 'h' _ 'e' _ 'r' _ 'c' _ 'o' _ 'n' _ ';', 7, 0x22b9, 1) +NAMED_CHARACTER_REFERENCE(1135, 'h' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd25, 2) +NAMED_CHARACTER_REFERENCE(1136, 'h' _ 'k' _ 's' _ 'e' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x2925, 1) +NAMED_CHARACTER_REFERENCE(1137, 'h' _ 'k' _ 's' _ 'w' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x2926, 1) +NAMED_CHARACTER_REFERENCE(1138, 'h' _ 'o' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21ff, 1) +NAMED_CHARACTER_REFERENCE(1139, 'h' _ 'o' _ 'm' _ 't' _ 'h' _ 't' _ ';', 7, 0x223b, 1) +NAMED_CHARACTER_REFERENCE(1140, 'h' _ 'o' _ 'o' _ 'k' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x21a9, 1) +NAMED_CHARACTER_REFERENCE(1141, 'h' _ 'o' _ 'o' _ 'k' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x21aa, 1) +NAMED_CHARACTER_REFERENCE(1142, 'h' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd59, 2) +NAMED_CHARACTER_REFERENCE(1143, 'h' _ 'o' _ 'r' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x2015, 1) +NAMED_CHARACTER_REFERENCE(1144, 'h' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcbd, 2) +NAMED_CHARACTER_REFERENCE(1145, 'h' _ 's' _ 'l' _ 'a' _ 's' _ 'h' _ ';', 7, 0x210f, 1) +NAMED_CHARACTER_REFERENCE(1146, 'h' _ 's' _ 't' _ 'r' _ 'o' _ 'k' _ ';', 7, 0x0127, 1) +NAMED_CHARACTER_REFERENCE(1147, 'h' _ 'y' _ 'b' _ 'u' _ 'l' _ 'l' _ ';', 7, 0x2043, 1) +NAMED_CHARACTER_REFERENCE(1148, 'h' _ 'y' _ 'p' _ 'h' _ 'e' _ 'n' _ ';', 7, 0x2010, 1) +NAMED_CHARACTER_REFERENCE(1149, 'i' _ 'a' _ 'c' _ 'u' _ 't' _ 'e', 6, 0x00ed, 1) +NAMED_CHARACTER_REFERENCE(1150, 'i' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x00ed, 1) +NAMED_CHARACTER_REFERENCE(1151, 'i' _ 'c' _ ';', 3, 0x2063, 1) +NAMED_CHARACTER_REFERENCE(1152, 'i' _ 'c' _ 'i' _ 'r' _ 'c', 5, 0x00ee, 1) +NAMED_CHARACTER_REFERENCE(1153, 'i' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x00ee, 1) +NAMED_CHARACTER_REFERENCE(1154, 'i' _ 'c' _ 'y' _ ';', 4, 0x0438, 1) +NAMED_CHARACTER_REFERENCE(1155, 'i' _ 'e' _ 'c' _ 'y' _ ';', 5, 0x0435, 1) +NAMED_CHARACTER_REFERENCE(1156, 'i' _ 'e' _ 'x' _ 'c' _ 'l', 5, 0x00a1, 1) +NAMED_CHARACTER_REFERENCE(1157, 'i' _ 'e' _ 'x' _ 'c' _ 'l' _ ';', 6, 0x00a1, 1) +NAMED_CHARACTER_REFERENCE(1158, 'i' _ 'f' _ 'f' _ ';', 4, 0x21d4, 1) +NAMED_CHARACTER_REFERENCE(1159, 'i' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd26, 2) +NAMED_CHARACTER_REFERENCE(1160, 'i' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e', 6, 0x00ec, 1) +NAMED_CHARACTER_REFERENCE(1161, 'i' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 7, 0x00ec, 1) +NAMED_CHARACTER_REFERENCE(1162, 'i' _ 'i' _ ';', 3, 0x2148, 1) +NAMED_CHARACTER_REFERENCE(1163, 'i' _ 'i' _ 'i' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a0c, 1) +NAMED_CHARACTER_REFERENCE(1164, 'i' _ 'i' _ 'i' _ 'n' _ 't' _ ';', 6, 0x222d, 1) +NAMED_CHARACTER_REFERENCE(1165, 'i' _ 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 7, 0x29dc, 1) +NAMED_CHARACTER_REFERENCE(1166, 'i' _ 'i' _ 'o' _ 't' _ 'a' _ ';', 6, 0x2129, 1) +NAMED_CHARACTER_REFERENCE(1167, 'i' _ 'j' _ 'l' _ 'i' _ 'g' _ ';', 6, 0x0133, 1) +NAMED_CHARACTER_REFERENCE(1168, 'i' _ 'm' _ 'a' _ 'c' _ 'r' _ ';', 6, 0x012b, 1) +NAMED_CHARACTER_REFERENCE(1169, 'i' _ 'm' _ 'a' _ 'g' _ 'e' _ ';', 6, 0x2111, 1) +NAMED_CHARACTER_REFERENCE(1170, 'i' _ 'm' _ 'a' _ 'g' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 9, 0x2110, 1) +NAMED_CHARACTER_REFERENCE(1171, 'i' _ 'm' _ 'a' _ 'g' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 9, 0x2111, 1) +NAMED_CHARACTER_REFERENCE(1172, 'i' _ 'm' _ 'a' _ 't' _ 'h' _ ';', 6, 0x0131, 1) +NAMED_CHARACTER_REFERENCE(1173, 'i' _ 'm' _ 'o' _ 'f' _ ';', 5, 0x22b7, 1) +NAMED_CHARACTER_REFERENCE(1174, 'i' _ 'm' _ 'p' _ 'e' _ 'd' _ ';', 6, 0x01b5, 1) +NAMED_CHARACTER_REFERENCE(1175, 'i' _ 'n' _ ';', 3, 0x2208, 1) +NAMED_CHARACTER_REFERENCE(1176, 'i' _ 'n' _ 'c' _ 'a' _ 'r' _ 'e' _ ';', 7, 0x2105, 1) +NAMED_CHARACTER_REFERENCE(1177, 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 6, 0x221e, 1) +NAMED_CHARACTER_REFERENCE(1178, 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ 't' _ 'i' _ 'e' _ ';', 9, 0x29dd, 1) +NAMED_CHARACTER_REFERENCE(1179, 'i' _ 'n' _ 'o' _ 'd' _ 'o' _ 't' _ ';', 7, 0x0131, 1) +NAMED_CHARACTER_REFERENCE(1180, 'i' _ 'n' _ 't' _ ';', 4, 0x222b, 1) +NAMED_CHARACTER_REFERENCE(1181, 'i' _ 'n' _ 't' _ 'c' _ 'a' _ 'l' _ ';', 7, 0x22ba, 1) +NAMED_CHARACTER_REFERENCE(1182, 'i' _ 'n' _ 't' _ 'e' _ 'g' _ 'e' _ 'r' _ 's' _ ';', 9, 0x2124, 1) +NAMED_CHARACTER_REFERENCE(1183, 'i' _ 'n' _ 't' _ 'e' _ 'r' _ 'c' _ 'a' _ 'l' _ ';', 9, 0x22ba, 1) +NAMED_CHARACTER_REFERENCE(1184, 'i' _ 'n' _ 't' _ 'l' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 9, 0x2a17, 1) +NAMED_CHARACTER_REFERENCE(1185, 'i' _ 'n' _ 't' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 8, 0x2a3c, 1) +NAMED_CHARACTER_REFERENCE(1186, 'i' _ 'o' _ 'c' _ 'y' _ ';', 5, 0x0451, 1) +NAMED_CHARACTER_REFERENCE(1187, 'i' _ 'o' _ 'g' _ 'o' _ 'n' _ ';', 6, 0x012f, 1) +NAMED_CHARACTER_REFERENCE(1188, 'i' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5a, 2) +NAMED_CHARACTER_REFERENCE(1189, 'i' _ 'o' _ 't' _ 'a' _ ';', 5, 0x03b9, 1) +NAMED_CHARACTER_REFERENCE(1190, 'i' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 6, 0x2a3c, 1) +NAMED_CHARACTER_REFERENCE(1191, 'i' _ 'q' _ 'u' _ 'e' _ 's' _ 't', 6, 0x00bf, 1) +NAMED_CHARACTER_REFERENCE(1192, 'i' _ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 7, 0x00bf, 1) +NAMED_CHARACTER_REFERENCE(1193, 'i' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcbe, 2) +NAMED_CHARACTER_REFERENCE(1194, 'i' _ 's' _ 'i' _ 'n' _ ';', 5, 0x2208, 1) +NAMED_CHARACTER_REFERENCE(1195, 'i' _ 's' _ 'i' _ 'n' _ 'E' _ ';', 6, 0x22f9, 1) +NAMED_CHARACTER_REFERENCE(1196, 'i' _ 's' _ 'i' _ 'n' _ 'd' _ 'o' _ 't' _ ';', 8, 0x22f5, 1) +NAMED_CHARACTER_REFERENCE(1197, 'i' _ 's' _ 'i' _ 'n' _ 's' _ ';', 6, 0x22f4, 1) +NAMED_CHARACTER_REFERENCE(1198, 'i' _ 's' _ 'i' _ 'n' _ 's' _ 'v' _ ';', 7, 0x22f3, 1) +NAMED_CHARACTER_REFERENCE(1199, 'i' _ 's' _ 'i' _ 'n' _ 'v' _ ';', 6, 0x2208, 1) +NAMED_CHARACTER_REFERENCE(1200, 'i' _ 't' _ ';', 3, 0x2062, 1) +NAMED_CHARACTER_REFERENCE(1201, 'i' _ 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x0129, 1) +NAMED_CHARACTER_REFERENCE(1202, 'i' _ 'u' _ 'k' _ 'c' _ 'y' _ ';', 6, 0x0456, 1) +NAMED_CHARACTER_REFERENCE(1203, 'i' _ 'u' _ 'm' _ 'l', 4, 0x00ef, 1) +NAMED_CHARACTER_REFERENCE(1204, 'i' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00ef, 1) +NAMED_CHARACTER_REFERENCE(1205, 'j' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x0135, 1) +NAMED_CHARACTER_REFERENCE(1206, 'j' _ 'c' _ 'y' _ ';', 4, 0x0439, 1) +NAMED_CHARACTER_REFERENCE(1207, 'j' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd27, 2) +NAMED_CHARACTER_REFERENCE(1208, 'j' _ 'm' _ 'a' _ 't' _ 'h' _ ';', 6, 0x0237, 1) +NAMED_CHARACTER_REFERENCE(1209, 'j' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5b, 2) +NAMED_CHARACTER_REFERENCE(1210, 'j' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcbf, 2) +NAMED_CHARACTER_REFERENCE(1211, 'j' _ 's' _ 'e' _ 'r' _ 'c' _ 'y' _ ';', 7, 0x0458, 1) +NAMED_CHARACTER_REFERENCE(1212, 'j' _ 'u' _ 'k' _ 'c' _ 'y' _ ';', 6, 0x0454, 1) +NAMED_CHARACTER_REFERENCE(1213, 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ ';', 6, 0x03ba, 1) +NAMED_CHARACTER_REFERENCE(1214, 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ 'v' _ ';', 7, 0x03f0, 1) +NAMED_CHARACTER_REFERENCE(1215, 'k' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 7, 0x0137, 1) +NAMED_CHARACTER_REFERENCE(1216, 'k' _ 'c' _ 'y' _ ';', 4, 0x043a, 1) +NAMED_CHARACTER_REFERENCE(1217, 'k' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd28, 2) +NAMED_CHARACTER_REFERENCE(1218, 'k' _ 'g' _ 'r' _ 'e' _ 'e' _ 'n' _ ';', 7, 0x0138, 1) +NAMED_CHARACTER_REFERENCE(1219, 'k' _ 'h' _ 'c' _ 'y' _ ';', 5, 0x0445, 1) +NAMED_CHARACTER_REFERENCE(1220, 'k' _ 'j' _ 'c' _ 'y' _ ';', 5, 0x045c, 1) +NAMED_CHARACTER_REFERENCE(1221, 'k' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5c, 2) +NAMED_CHARACTER_REFERENCE(1222, 'k' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc0, 2) +NAMED_CHARACTER_REFERENCE(1223, 'l' _ 'A' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21da, 1) +NAMED_CHARACTER_REFERENCE(1224, 'l' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d0, 1) +NAMED_CHARACTER_REFERENCE(1225, 'l' _ 'A' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 7, 0x291b, 1) +NAMED_CHARACTER_REFERENCE(1226, 'l' _ 'B' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x290e, 1) +NAMED_CHARACTER_REFERENCE(1227, 'l' _ 'E' _ ';', 3, 0x2266, 1) +NAMED_CHARACTER_REFERENCE(1228, 'l' _ 'E' _ 'g' _ ';', 4, 0x2a8b, 1) +NAMED_CHARACTER_REFERENCE(1229, 'l' _ 'H' _ 'a' _ 'r' _ ';', 5, 0x2962, 1) +NAMED_CHARACTER_REFERENCE(1230, 'l' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x013a, 1) +NAMED_CHARACTER_REFERENCE(1231, 'l' _ 'a' _ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 9, 0x29b4, 1) +NAMED_CHARACTER_REFERENCE(1232, 'l' _ 'a' _ 'g' _ 'r' _ 'a' _ 'n' _ ';', 7, 0x2112, 1) +NAMED_CHARACTER_REFERENCE(1233, 'l' _ 'a' _ 'm' _ 'b' _ 'd' _ 'a' _ ';', 7, 0x03bb, 1) +NAMED_CHARACTER_REFERENCE(1234, 'l' _ 'a' _ 'n' _ 'g' _ ';', 5, 0x27e8, 1) +NAMED_CHARACTER_REFERENCE(1235, 'l' _ 'a' _ 'n' _ 'g' _ 'd' _ ';', 6, 0x2991, 1) +NAMED_CHARACTER_REFERENCE(1236, 'l' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 7, 0x27e8, 1) +NAMED_CHARACTER_REFERENCE(1237, 'l' _ 'a' _ 'p' _ ';', 4, 0x2a85, 1) +NAMED_CHARACTER_REFERENCE(1238, 'l' _ 'a' _ 'q' _ 'u' _ 'o', 5, 0x00ab, 1) +NAMED_CHARACTER_REFERENCE(1239, 'l' _ 'a' _ 'q' _ 'u' _ 'o' _ ';', 6, 0x00ab, 1) +NAMED_CHARACTER_REFERENCE(1240, 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2190, 1) +NAMED_CHARACTER_REFERENCE(1241, 'l' _ 'a' _ 'r' _ 'r' _ 'b' _ ';', 6, 0x21e4, 1) +NAMED_CHARACTER_REFERENCE(1242, 'l' _ 'a' _ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 8, 0x291f, 1) +NAMED_CHARACTER_REFERENCE(1243, 'l' _ 'a' _ 'r' _ 'r' _ 'f' _ 's' _ ';', 7, 0x291d, 1) +NAMED_CHARACTER_REFERENCE(1244, 'l' _ 'a' _ 'r' _ 'r' _ 'h' _ 'k' _ ';', 7, 0x21a9, 1) +NAMED_CHARACTER_REFERENCE(1245, 'l' _ 'a' _ 'r' _ 'r' _ 'l' _ 'p' _ ';', 7, 0x21ab, 1) +NAMED_CHARACTER_REFERENCE(1246, 'l' _ 'a' _ 'r' _ 'r' _ 'p' _ 'l' _ ';', 7, 0x2939, 1) +NAMED_CHARACTER_REFERENCE(1247, 'l' _ 'a' _ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 8, 0x2973, 1) +NAMED_CHARACTER_REFERENCE(1248, 'l' _ 'a' _ 'r' _ 'r' _ 't' _ 'l' _ ';', 7, 0x21a2, 1) +NAMED_CHARACTER_REFERENCE(1249, 'l' _ 'a' _ 't' _ ';', 4, 0x2aab, 1) +NAMED_CHARACTER_REFERENCE(1250, 'l' _ 'a' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 7, 0x2919, 1) +NAMED_CHARACTER_REFERENCE(1251, 'l' _ 'a' _ 't' _ 'e' _ ';', 5, 0x2aad, 1) +NAMED_CHARACTER_REFERENCE(1252, 'l' _ 'b' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x290c, 1) +NAMED_CHARACTER_REFERENCE(1253, 'l' _ 'b' _ 'b' _ 'r' _ 'k' _ ';', 6, 0x2772, 1) +NAMED_CHARACTER_REFERENCE(1254, 'l' _ 'b' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 7, 0x007b, 1) +NAMED_CHARACTER_REFERENCE(1255, 'l' _ 'b' _ 'r' _ 'a' _ 'c' _ 'k' _ ';', 7, 0x005b, 1) +NAMED_CHARACTER_REFERENCE(1256, 'l' _ 'b' _ 'r' _ 'k' _ 'e' _ ';', 6, 0x298b, 1) +NAMED_CHARACTER_REFERENCE(1257, 'l' _ 'b' _ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 8, 0x298f, 1) +NAMED_CHARACTER_REFERENCE(1258, 'l' _ 'b' _ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 8, 0x298d, 1) +NAMED_CHARACTER_REFERENCE(1259, 'l' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x013e, 1) +NAMED_CHARACTER_REFERENCE(1260, 'l' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 7, 0x013c, 1) +NAMED_CHARACTER_REFERENCE(1261, 'l' _ 'c' _ 'e' _ 'i' _ 'l' _ ';', 6, 0x2308, 1) +NAMED_CHARACTER_REFERENCE(1262, 'l' _ 'c' _ 'u' _ 'b' _ ';', 5, 0x007b, 1) +NAMED_CHARACTER_REFERENCE(1263, 'l' _ 'c' _ 'y' _ ';', 4, 0x043b, 1) +NAMED_CHARACTER_REFERENCE(1264, 'l' _ 'd' _ 'c' _ 'a' _ ';', 5, 0x2936, 1) +NAMED_CHARACTER_REFERENCE(1265, 'l' _ 'd' _ 'q' _ 'u' _ 'o' _ ';', 6, 0x201c, 1) +NAMED_CHARACTER_REFERENCE(1266, 'l' _ 'd' _ 'q' _ 'u' _ 'o' _ 'r' _ ';', 7, 0x201e, 1) +NAMED_CHARACTER_REFERENCE(1267, 'l' _ 'd' _ 'r' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 8, 0x2967, 1) +NAMED_CHARACTER_REFERENCE(1268, 'l' _ 'd' _ 'r' _ 'u' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 9, 0x294b, 1) +NAMED_CHARACTER_REFERENCE(1269, 'l' _ 'd' _ 's' _ 'h' _ ';', 5, 0x21b2, 1) +NAMED_CHARACTER_REFERENCE(1270, 'l' _ 'e' _ ';', 3, 0x2264, 1) +NAMED_CHARACTER_REFERENCE(1271, 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x2190, 1) +NAMED_CHARACTER_REFERENCE(1272, 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 14, 0x21a2, 1) +NAMED_CHARACTER_REFERENCE(1273, 'l' _ 'e' _ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 16, 0x21bd, 1) +NAMED_CHARACTER_REFERENCE(1274, 'l' _ 'e' _ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 14, 0x21bc, 1) +NAMED_CHARACTER_REFERENCE(1275, 'l' _ 'e' _ 'f' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 15, 0x21c7, 1) +NAMED_CHARACTER_REFERENCE(1276, 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x2194, 1) +NAMED_CHARACTER_REFERENCE(1277, 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 16, 0x21c6, 1) +NAMED_CHARACTER_REFERENCE(1278, 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', 18, 0x21cb, 1) +NAMED_CHARACTER_REFERENCE(1279, 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 20, 0x21ad, 1) +NAMED_CHARACTER_REFERENCE(1280, 'l' _ 'e' _ 'f' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 15, 0x22cb, 1) +NAMED_CHARACTER_REFERENCE(1281, 'l' _ 'e' _ 'g' _ ';', 4, 0x22da, 1) +NAMED_CHARACTER_REFERENCE(1282, 'l' _ 'e' _ 'q' _ ';', 4, 0x2264, 1) +NAMED_CHARACTER_REFERENCE(1283, 'l' _ 'e' _ 'q' _ 'q' _ ';', 5, 0x2266, 1) +NAMED_CHARACTER_REFERENCE(1284, 'l' _ 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 9, 0x2a7d, 1) +NAMED_CHARACTER_REFERENCE(1285, 'l' _ 'e' _ 's' _ ';', 4, 0x2a7d, 1) +NAMED_CHARACTER_REFERENCE(1286, 'l' _ 'e' _ 's' _ 'c' _ 'c' _ ';', 6, 0x2aa8, 1) +NAMED_CHARACTER_REFERENCE(1287, 'l' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a7f, 1) +NAMED_CHARACTER_REFERENCE(1288, 'l' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 8, 0x2a81, 1) +NAMED_CHARACTER_REFERENCE(1289, 'l' _ 'e' _ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'r' _ ';', 9, 0x2a83, 1) +NAMED_CHARACTER_REFERENCE(1290, 'l' _ 'e' _ 's' _ 'g' _ 'e' _ 's' _ ';', 7, 0x2a93, 1) +NAMED_CHARACTER_REFERENCE(1291, 'l' _ 'e' _ 's' _ 's' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 11, 0x2a85, 1) +NAMED_CHARACTER_REFERENCE(1292, 'l' _ 'e' _ 's' _ 's' _ 'd' _ 'o' _ 't' _ ';', 8, 0x22d6, 1) +NAMED_CHARACTER_REFERENCE(1293, 'l' _ 'e' _ 's' _ 's' _ 'e' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 10, 0x22da, 1) +NAMED_CHARACTER_REFERENCE(1294, 'l' _ 'e' _ 's' _ 's' _ 'e' _ 'q' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 11, 0x2a8b, 1) +NAMED_CHARACTER_REFERENCE(1295, 'l' _ 'e' _ 's' _ 's' _ 'g' _ 't' _ 'r' _ ';', 8, 0x2276, 1) +NAMED_CHARACTER_REFERENCE(1296, 'l' _ 'e' _ 's' _ 's' _ 's' _ 'i' _ 'm' _ ';', 8, 0x2272, 1) +NAMED_CHARACTER_REFERENCE(1297, 'l' _ 'f' _ 'i' _ 's' _ 'h' _ 't' _ ';', 7, 0x297c, 1) +NAMED_CHARACTER_REFERENCE(1298, 'l' _ 'f' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 7, 0x230a, 1) +NAMED_CHARACTER_REFERENCE(1299, 'l' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd29, 2) +NAMED_CHARACTER_REFERENCE(1300, 'l' _ 'g' _ ';', 3, 0x2276, 1) +NAMED_CHARACTER_REFERENCE(1301, 'l' _ 'g' _ 'E' _ ';', 4, 0x2a91, 1) +NAMED_CHARACTER_REFERENCE(1302, 'l' _ 'h' _ 'a' _ 'r' _ 'd' _ ';', 6, 0x21bd, 1) +NAMED_CHARACTER_REFERENCE(1303, 'l' _ 'h' _ 'a' _ 'r' _ 'u' _ ';', 6, 0x21bc, 1) +NAMED_CHARACTER_REFERENCE(1304, 'l' _ 'h' _ 'a' _ 'r' _ 'u' _ 'l' _ ';', 7, 0x296a, 1) +NAMED_CHARACTER_REFERENCE(1305, 'l' _ 'h' _ 'b' _ 'l' _ 'k' _ ';', 6, 0x2584, 1) +NAMED_CHARACTER_REFERENCE(1306, 'l' _ 'j' _ 'c' _ 'y' _ ';', 5, 0x0459, 1) +NAMED_CHARACTER_REFERENCE(1307, 'l' _ 'l' _ ';', 3, 0x226a, 1) +NAMED_CHARACTER_REFERENCE(1308, 'l' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21c7, 1) +NAMED_CHARACTER_REFERENCE(1309, 'l' _ 'l' _ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 9, 0x231e, 1) +NAMED_CHARACTER_REFERENCE(1310, 'l' _ 'l' _ 'h' _ 'a' _ 'r' _ 'd' _ ';', 7, 0x296b, 1) +NAMED_CHARACTER_REFERENCE(1311, 'l' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 6, 0x25fa, 1) +NAMED_CHARACTER_REFERENCE(1312, 'l' _ 'm' _ 'i' _ 'd' _ 'o' _ 't' _ ';', 7, 0x0140, 1) +NAMED_CHARACTER_REFERENCE(1313, 'l' _ 'm' _ 'o' _ 'u' _ 's' _ 't' _ ';', 7, 0x23b0, 1) +NAMED_CHARACTER_REFERENCE(1314, 'l' _ 'm' _ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 11, 0x23b0, 1) +NAMED_CHARACTER_REFERENCE(1315, 'l' _ 'n' _ 'E' _ ';', 4, 0x2268, 1) +NAMED_CHARACTER_REFERENCE(1316, 'l' _ 'n' _ 'a' _ 'p' _ ';', 5, 0x2a89, 1) +NAMED_CHARACTER_REFERENCE(1317, 'l' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0x2a89, 1) +NAMED_CHARACTER_REFERENCE(1318, 'l' _ 'n' _ 'e' _ ';', 4, 0x2a87, 1) +NAMED_CHARACTER_REFERENCE(1319, 'l' _ 'n' _ 'e' _ 'q' _ ';', 5, 0x2a87, 1) +NAMED_CHARACTER_REFERENCE(1320, 'l' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 6, 0x2268, 1) +NAMED_CHARACTER_REFERENCE(1321, 'l' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 6, 0x22e6, 1) +NAMED_CHARACTER_REFERENCE(1322, 'l' _ 'o' _ 'a' _ 'n' _ 'g' _ ';', 6, 0x27ec, 1) +NAMED_CHARACTER_REFERENCE(1323, 'l' _ 'o' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21fd, 1) +NAMED_CHARACTER_REFERENCE(1324, 'l' _ 'o' _ 'b' _ 'r' _ 'k' _ ';', 6, 0x27e6, 1) +NAMED_CHARACTER_REFERENCE(1325, 'l' _ 'o' _ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x27f5, 1) +NAMED_CHARACTER_REFERENCE(1326, 'l' _ 'o' _ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 19, 0x27f7, 1) +NAMED_CHARACTER_REFERENCE(1327, 'l' _ 'o' _ 'n' _ 'g' _ 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ ';', 11, 0x27fc, 1) +NAMED_CHARACTER_REFERENCE(1328, 'l' _ 'o' _ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x27f6, 1) +NAMED_CHARACTER_REFERENCE(1329, 'l' _ 'o' _ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x21ab, 1) +NAMED_CHARACTER_REFERENCE(1330, 'l' _ 'o' _ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x21ac, 1) +NAMED_CHARACTER_REFERENCE(1331, 'l' _ 'o' _ 'p' _ 'a' _ 'r' _ ';', 6, 0x2985, 1) +NAMED_CHARACTER_REFERENCE(1332, 'l' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5d, 2) +NAMED_CHARACTER_REFERENCE(1333, 'l' _ 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2a2d, 1) +NAMED_CHARACTER_REFERENCE(1334, 'l' _ 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 8, 0x2a34, 1) +NAMED_CHARACTER_REFERENCE(1335, 'l' _ 'o' _ 'w' _ 'a' _ 's' _ 't' _ ';', 7, 0x2217, 1) +NAMED_CHARACTER_REFERENCE(1336, 'l' _ 'o' _ 'w' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x005f, 1) +NAMED_CHARACTER_REFERENCE(1337, 'l' _ 'o' _ 'z' _ ';', 4, 0x25ca, 1) +NAMED_CHARACTER_REFERENCE(1338, 'l' _ 'o' _ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 8, 0x25ca, 1) +NAMED_CHARACTER_REFERENCE(1339, 'l' _ 'o' _ 'z' _ 'f' _ ';', 5, 0x29eb, 1) +NAMED_CHARACTER_REFERENCE(1340, 'l' _ 'p' _ 'a' _ 'r' _ ';', 5, 0x0028, 1) +NAMED_CHARACTER_REFERENCE(1341, 'l' _ 'p' _ 'a' _ 'r' _ 'l' _ 't' _ ';', 7, 0x2993, 1) +NAMED_CHARACTER_REFERENCE(1342, 'l' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21c6, 1) +NAMED_CHARACTER_REFERENCE(1343, 'l' _ 'r' _ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 9, 0x231f, 1) +NAMED_CHARACTER_REFERENCE(1344, 'l' _ 'r' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x21cb, 1) +NAMED_CHARACTER_REFERENCE(1345, 'l' _ 'r' _ 'h' _ 'a' _ 'r' _ 'd' _ ';', 7, 0x296d, 1) +NAMED_CHARACTER_REFERENCE(1346, 'l' _ 'r' _ 'm' _ ';', 4, 0x200e, 1) +NAMED_CHARACTER_REFERENCE(1347, 'l' _ 'r' _ 't' _ 'r' _ 'i' _ ';', 6, 0x22bf, 1) +NAMED_CHARACTER_REFERENCE(1348, 'l' _ 's' _ 'a' _ 'q' _ 'u' _ 'o' _ ';', 7, 0x2039, 1) +NAMED_CHARACTER_REFERENCE(1349, 'l' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc1, 2) +NAMED_CHARACTER_REFERENCE(1350, 'l' _ 's' _ 'h' _ ';', 4, 0x21b0, 1) +NAMED_CHARACTER_REFERENCE(1351, 'l' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2272, 1) +NAMED_CHARACTER_REFERENCE(1352, 'l' _ 's' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x2a8d, 1) +NAMED_CHARACTER_REFERENCE(1353, 'l' _ 's' _ 'i' _ 'm' _ 'g' _ ';', 6, 0x2a8f, 1) +NAMED_CHARACTER_REFERENCE(1354, 'l' _ 's' _ 'q' _ 'b' _ ';', 5, 0x005b, 1) +NAMED_CHARACTER_REFERENCE(1355, 'l' _ 's' _ 'q' _ 'u' _ 'o' _ ';', 6, 0x2018, 1) +NAMED_CHARACTER_REFERENCE(1356, 'l' _ 's' _ 'q' _ 'u' _ 'o' _ 'r' _ ';', 7, 0x201a, 1) +NAMED_CHARACTER_REFERENCE(1357, 'l' _ 's' _ 't' _ 'r' _ 'o' _ 'k' _ ';', 7, 0x0142, 1) +NAMED_CHARACTER_REFERENCE(1358, 'l' _ 't', 2, 0x003c, 1) +NAMED_CHARACTER_REFERENCE(1359, 'l' _ 't' _ ';', 3, 0x003c, 1) +NAMED_CHARACTER_REFERENCE(1360, 'l' _ 't' _ 'c' _ 'c' _ ';', 5, 0x2aa6, 1) +NAMED_CHARACTER_REFERENCE(1361, 'l' _ 't' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x2a79, 1) +NAMED_CHARACTER_REFERENCE(1362, 'l' _ 't' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22d6, 1) +NAMED_CHARACTER_REFERENCE(1363, 'l' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ ';', 7, 0x22cb, 1) +NAMED_CHARACTER_REFERENCE(1364, 'l' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0x22c9, 1) +NAMED_CHARACTER_REFERENCE(1365, 'l' _ 't' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x2976, 1) +NAMED_CHARACTER_REFERENCE(1366, 'l' _ 't' _ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 8, 0x2a7b, 1) +NAMED_CHARACTER_REFERENCE(1367, 'l' _ 't' _ 'r' _ 'P' _ 'a' _ 'r' _ ';', 7, 0x2996, 1) +NAMED_CHARACTER_REFERENCE(1368, 'l' _ 't' _ 'r' _ 'i' _ ';', 5, 0x25c3, 1) +NAMED_CHARACTER_REFERENCE(1369, 'l' _ 't' _ 'r' _ 'i' _ 'e' _ ';', 6, 0x22b4, 1) +NAMED_CHARACTER_REFERENCE(1370, 'l' _ 't' _ 'r' _ 'i' _ 'f' _ ';', 6, 0x25c2, 1) +NAMED_CHARACTER_REFERENCE(1371, 'l' _ 'u' _ 'r' _ 'd' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 9, 0x294a, 1) +NAMED_CHARACTER_REFERENCE(1372, 'l' _ 'u' _ 'r' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 8, 0x2966, 1) +NAMED_CHARACTER_REFERENCE(1373, 'm' _ 'D' _ 'D' _ 'o' _ 't' _ ';', 6, 0x223a, 1) +NAMED_CHARACTER_REFERENCE(1374, 'm' _ 'a' _ 'c' _ 'r', 4, 0x00af, 1) +NAMED_CHARACTER_REFERENCE(1375, 'm' _ 'a' _ 'c' _ 'r' _ ';', 5, 0x00af, 1) +NAMED_CHARACTER_REFERENCE(1376, 'm' _ 'a' _ 'l' _ 'e' _ ';', 5, 0x2642, 1) +NAMED_CHARACTER_REFERENCE(1377, 'm' _ 'a' _ 'l' _ 't' _ ';', 5, 0x2720, 1) +NAMED_CHARACTER_REFERENCE(1378, 'm' _ 'a' _ 'l' _ 't' _ 'e' _ 's' _ 'e' _ ';', 8, 0x2720, 1) +NAMED_CHARACTER_REFERENCE(1379, 'm' _ 'a' _ 'p' _ ';', 4, 0x21a6, 1) +NAMED_CHARACTER_REFERENCE(1380, 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ ';', 7, 0x21a6, 1) +NAMED_CHARACTER_REFERENCE(1381, 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 11, 0x21a7, 1) +NAMED_CHARACTER_REFERENCE(1382, 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 11, 0x21a4, 1) +NAMED_CHARACTER_REFERENCE(1383, 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ 'u' _ 'p' _ ';', 9, 0x21a5, 1) +NAMED_CHARACTER_REFERENCE(1384, 'm' _ 'a' _ 'r' _ 'k' _ 'e' _ 'r' _ ';', 7, 0x25ae, 1) +NAMED_CHARACTER_REFERENCE(1385, 'm' _ 'c' _ 'o' _ 'm' _ 'm' _ 'a' _ ';', 7, 0x2a29, 1) +NAMED_CHARACTER_REFERENCE(1386, 'm' _ 'c' _ 'y' _ ';', 4, 0x043c, 1) +NAMED_CHARACTER_REFERENCE(1387, 'm' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 6, 0x2014, 1) +NAMED_CHARACTER_REFERENCE(1388, 'm' _ 'e' _ 'a' _ 's' _ 'u' _ 'r' _ 'e' _ 'd' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 14, 0x2221, 1) +NAMED_CHARACTER_REFERENCE(1389, 'm' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd2a, 2) +NAMED_CHARACTER_REFERENCE(1390, 'm' _ 'h' _ 'o' _ ';', 4, 0x2127, 1) +NAMED_CHARACTER_REFERENCE(1391, 'm' _ 'i' _ 'c' _ 'r' _ 'o', 5, 0x00b5, 1) +NAMED_CHARACTER_REFERENCE(1392, 'm' _ 'i' _ 'c' _ 'r' _ 'o' _ ';', 6, 0x00b5, 1) +NAMED_CHARACTER_REFERENCE(1393, 'm' _ 'i' _ 'd' _ ';', 4, 0x2223, 1) +NAMED_CHARACTER_REFERENCE(1394, 'm' _ 'i' _ 'd' _ 'a' _ 's' _ 't' _ ';', 7, 0x002a, 1) +NAMED_CHARACTER_REFERENCE(1395, 'm' _ 'i' _ 'd' _ 'c' _ 'i' _ 'r' _ ';', 7, 0x2af0, 1) +NAMED_CHARACTER_REFERENCE(1396, 'm' _ 'i' _ 'd' _ 'd' _ 'o' _ 't', 6, 0x00b7, 1) +NAMED_CHARACTER_REFERENCE(1397, 'm' _ 'i' _ 'd' _ 'd' _ 'o' _ 't' _ ';', 7, 0x00b7, 1) +NAMED_CHARACTER_REFERENCE(1398, 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 6, 0x2212, 1) +NAMED_CHARACTER_REFERENCE(1399, 'm' _ 'i' _ 'n' _ 'u' _ 's' _ 'b' _ ';', 7, 0x229f, 1) +NAMED_CHARACTER_REFERENCE(1400, 'm' _ 'i' _ 'n' _ 'u' _ 's' _ 'd' _ ';', 7, 0x2238, 1) +NAMED_CHARACTER_REFERENCE(1401, 'm' _ 'i' _ 'n' _ 'u' _ 's' _ 'd' _ 'u' _ ';', 8, 0x2a2a, 1) +NAMED_CHARACTER_REFERENCE(1402, 'm' _ 'l' _ 'c' _ 'p' _ ';', 5, 0x2adb, 1) +NAMED_CHARACTER_REFERENCE(1403, 'm' _ 'l' _ 'd' _ 'r' _ ';', 5, 0x2026, 1) +NAMED_CHARACTER_REFERENCE(1404, 'm' _ 'n' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2213, 1) +NAMED_CHARACTER_REFERENCE(1405, 'm' _ 'o' _ 'd' _ 'e' _ 'l' _ 's' _ ';', 7, 0x22a7, 1) +NAMED_CHARACTER_REFERENCE(1406, 'm' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5e, 2) +NAMED_CHARACTER_REFERENCE(1407, 'm' _ 'p' _ ';', 3, 0x2213, 1) +NAMED_CHARACTER_REFERENCE(1408, 'm' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc2, 2) +NAMED_CHARACTER_REFERENCE(1409, 'm' _ 's' _ 't' _ 'p' _ 'o' _ 's' _ ';', 7, 0x223e, 1) +NAMED_CHARACTER_REFERENCE(1410, 'm' _ 'u' _ ';', 3, 0x03bc, 1) +NAMED_CHARACTER_REFERENCE(1411, 'm' _ 'u' _ 'l' _ 't' _ 'i' _ 'm' _ 'a' _ 'p' _ ';', 9, 0x22b8, 1) +NAMED_CHARACTER_REFERENCE(1412, 'm' _ 'u' _ 'm' _ 'a' _ 'p' _ ';', 6, 0x22b8, 1) +NAMED_CHARACTER_REFERENCE(1413, 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0x21cd, 1) +NAMED_CHARACTER_REFERENCE(1414, 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0x21ce, 1) +NAMED_CHARACTER_REFERENCE(1415, 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x21cf, 1) +NAMED_CHARACTER_REFERENCE(1416, 'n' _ 'V' _ 'D' _ 'a' _ 's' _ 'h' _ ';', 7, 0x22af, 1) +NAMED_CHARACTER_REFERENCE(1417, 'n' _ 'V' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 7, 0x22ae, 1) +NAMED_CHARACTER_REFERENCE(1418, 'n' _ 'a' _ 'b' _ 'l' _ 'a' _ ';', 6, 0x2207, 1) +NAMED_CHARACTER_REFERENCE(1419, 'n' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x0144, 1) +NAMED_CHARACTER_REFERENCE(1420, 'n' _ 'a' _ 'p' _ ';', 4, 0x2249, 1) +NAMED_CHARACTER_REFERENCE(1421, 'n' _ 'a' _ 'p' _ 'o' _ 's' _ ';', 6, 0x0149, 1) +NAMED_CHARACTER_REFERENCE(1422, 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 8, 0x2249, 1) +NAMED_CHARACTER_REFERENCE(1423, 'n' _ 'a' _ 't' _ 'u' _ 'r' _ ';', 6, 0x266e, 1) +NAMED_CHARACTER_REFERENCE(1424, 'n' _ 'a' _ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ ';', 8, 0x266e, 1) +NAMED_CHARACTER_REFERENCE(1425, 'n' _ 'a' _ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ 's' _ ';', 9, 0x2115, 1) +NAMED_CHARACTER_REFERENCE(1426, 'n' _ 'b' _ 's' _ 'p', 4, 0x00a0, 1) +NAMED_CHARACTER_REFERENCE(1427, 'n' _ 'b' _ 's' _ 'p' _ ';', 5, 0x00a0, 1) +NAMED_CHARACTER_REFERENCE(1428, 'n' _ 'c' _ 'a' _ 'p' _ ';', 5, 0x2a43, 1) +NAMED_CHARACTER_REFERENCE(1429, 'n' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x0148, 1) +NAMED_CHARACTER_REFERENCE(1430, 'n' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 7, 0x0146, 1) +NAMED_CHARACTER_REFERENCE(1431, 'n' _ 'c' _ 'o' _ 'n' _ 'g' _ ';', 6, 0x2247, 1) +NAMED_CHARACTER_REFERENCE(1432, 'n' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x2a42, 1) +NAMED_CHARACTER_REFERENCE(1433, 'n' _ 'c' _ 'y' _ ';', 4, 0x043d, 1) +NAMED_CHARACTER_REFERENCE(1434, 'n' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 6, 0x2013, 1) +NAMED_CHARACTER_REFERENCE(1435, 'n' _ 'e' _ ';', 3, 0x2260, 1) +NAMED_CHARACTER_REFERENCE(1436, 'n' _ 'e' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21d7, 1) +NAMED_CHARACTER_REFERENCE(1437, 'n' _ 'e' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, 0x2924, 1) +NAMED_CHARACTER_REFERENCE(1438, 'n' _ 'e' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2197, 1) +NAMED_CHARACTER_REFERENCE(1439, 'n' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2197, 1) +NAMED_CHARACTER_REFERENCE(1440, 'n' _ 'e' _ 'q' _ 'u' _ 'i' _ 'v' _ ';', 7, 0x2262, 1) +NAMED_CHARACTER_REFERENCE(1441, 'n' _ 'e' _ 's' _ 'e' _ 'a' _ 'r' _ ';', 7, 0x2928, 1) +NAMED_CHARACTER_REFERENCE(1442, 'n' _ 'e' _ 'x' _ 'i' _ 's' _ 't' _ ';', 7, 0x2204, 1) +NAMED_CHARACTER_REFERENCE(1443, 'n' _ 'e' _ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 8, 0x2204, 1) +NAMED_CHARACTER_REFERENCE(1444, 'n' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd2b, 2) +NAMED_CHARACTER_REFERENCE(1445, 'n' _ 'g' _ 'e' _ ';', 4, 0x2271, 1) +NAMED_CHARACTER_REFERENCE(1446, 'n' _ 'g' _ 'e' _ 'q' _ ';', 5, 0x2271, 1) +NAMED_CHARACTER_REFERENCE(1447, 'n' _ 'g' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2275, 1) +NAMED_CHARACTER_REFERENCE(1448, 'n' _ 'g' _ 't' _ ';', 4, 0x226f, 1) +NAMED_CHARACTER_REFERENCE(1449, 'n' _ 'g' _ 't' _ 'r' _ ';', 5, 0x226f, 1) +NAMED_CHARACTER_REFERENCE(1450, 'n' _ 'h' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21ce, 1) +NAMED_CHARACTER_REFERENCE(1451, 'n' _ 'h' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21ae, 1) +NAMED_CHARACTER_REFERENCE(1452, 'n' _ 'h' _ 'p' _ 'a' _ 'r' _ ';', 6, 0x2af2, 1) +NAMED_CHARACTER_REFERENCE(1453, 'n' _ 'i' _ ';', 3, 0x220b, 1) +NAMED_CHARACTER_REFERENCE(1454, 'n' _ 'i' _ 's' _ ';', 4, 0x22fc, 1) +NAMED_CHARACTER_REFERENCE(1455, 'n' _ 'i' _ 's' _ 'd' _ ';', 5, 0x22fa, 1) +NAMED_CHARACTER_REFERENCE(1456, 'n' _ 'i' _ 'v' _ ';', 4, 0x220b, 1) +NAMED_CHARACTER_REFERENCE(1457, 'n' _ 'j' _ 'c' _ 'y' _ ';', 5, 0x045a, 1) +NAMED_CHARACTER_REFERENCE(1458, 'n' _ 'l' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21cd, 1) +NAMED_CHARACTER_REFERENCE(1459, 'n' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x219a, 1) +NAMED_CHARACTER_REFERENCE(1460, 'n' _ 'l' _ 'd' _ 'r' _ ';', 5, 0x2025, 1) +NAMED_CHARACTER_REFERENCE(1461, 'n' _ 'l' _ 'e' _ ';', 4, 0x2270, 1) +NAMED_CHARACTER_REFERENCE(1462, 'n' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0x219a, 1) +NAMED_CHARACTER_REFERENCE(1463, 'n' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0x21ae, 1) +NAMED_CHARACTER_REFERENCE(1464, 'n' _ 'l' _ 'e' _ 'q' _ ';', 5, 0x2270, 1) +NAMED_CHARACTER_REFERENCE(1465, 'n' _ 'l' _ 'e' _ 's' _ 's' _ ';', 6, 0x226e, 1) +NAMED_CHARACTER_REFERENCE(1466, 'n' _ 'l' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2274, 1) +NAMED_CHARACTER_REFERENCE(1467, 'n' _ 'l' _ 't' _ ';', 4, 0x226e, 1) +NAMED_CHARACTER_REFERENCE(1468, 'n' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 6, 0x22ea, 1) +NAMED_CHARACTER_REFERENCE(1469, 'n' _ 'l' _ 't' _ 'r' _ 'i' _ 'e' _ ';', 7, 0x22ec, 1) +NAMED_CHARACTER_REFERENCE(1470, 'n' _ 'm' _ 'i' _ 'd' _ ';', 5, 0x2224, 1) +NAMED_CHARACTER_REFERENCE(1471, 'n' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd5f, 2) +NAMED_CHARACTER_REFERENCE(1472, 'n' _ 'o' _ 't', 3, 0x00ac, 1) +NAMED_CHARACTER_REFERENCE(1473, 'n' _ 'o' _ 't' _ ';', 4, 0x00ac, 1) +NAMED_CHARACTER_REFERENCE(1474, 'n' _ 'o' _ 't' _ 'i' _ 'n' _ ';', 6, 0x2209, 1) +NAMED_CHARACTER_REFERENCE(1475, 'n' _ 'o' _ 't' _ 'i' _ 'n' _ 'v' _ 'a' _ ';', 8, 0x2209, 1) +NAMED_CHARACTER_REFERENCE(1476, 'n' _ 'o' _ 't' _ 'i' _ 'n' _ 'v' _ 'b' _ ';', 8, 0x22f7, 1) +NAMED_CHARACTER_REFERENCE(1477, 'n' _ 'o' _ 't' _ 'i' _ 'n' _ 'v' _ 'c' _ ';', 8, 0x22f6, 1) +NAMED_CHARACTER_REFERENCE(1478, 'n' _ 'o' _ 't' _ 'n' _ 'i' _ ';', 6, 0x220c, 1) +NAMED_CHARACTER_REFERENCE(1479, 'n' _ 'o' _ 't' _ 'n' _ 'i' _ 'v' _ 'a' _ ';', 8, 0x220c, 1) +NAMED_CHARACTER_REFERENCE(1480, 'n' _ 'o' _ 't' _ 'n' _ 'i' _ 'v' _ 'b' _ ';', 8, 0x22fe, 1) +NAMED_CHARACTER_REFERENCE(1481, 'n' _ 'o' _ 't' _ 'n' _ 'i' _ 'v' _ 'c' _ ';', 8, 0x22fd, 1) +NAMED_CHARACTER_REFERENCE(1482, 'n' _ 'p' _ 'a' _ 'r' _ ';', 5, 0x2226, 1) +NAMED_CHARACTER_REFERENCE(1483, 'n' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 10, 0x2226, 1) +NAMED_CHARACTER_REFERENCE(1484, 'n' _ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 8, 0x2a14, 1) +NAMED_CHARACTER_REFERENCE(1485, 'n' _ 'p' _ 'r' _ ';', 4, 0x2280, 1) +NAMED_CHARACTER_REFERENCE(1486, 'n' _ 'p' _ 'r' _ 'c' _ 'u' _ 'e' _ ';', 7, 0x22e0, 1) +NAMED_CHARACTER_REFERENCE(1487, 'n' _ 'p' _ 'r' _ 'e' _ 'c' _ ';', 6, 0x2280, 1) +NAMED_CHARACTER_REFERENCE(1488, 'n' _ 'r' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21cf, 1) +NAMED_CHARACTER_REFERENCE(1489, 'n' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x219b, 1) +NAMED_CHARACTER_REFERENCE(1490, 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x219b, 1) +NAMED_CHARACTER_REFERENCE(1491, 'n' _ 'r' _ 't' _ 'r' _ 'i' _ ';', 6, 0x22eb, 1) +NAMED_CHARACTER_REFERENCE(1492, 'n' _ 'r' _ 't' _ 'r' _ 'i' _ 'e' _ ';', 7, 0x22ed, 1) +NAMED_CHARACTER_REFERENCE(1493, 'n' _ 's' _ 'c' _ ';', 4, 0x2281, 1) +NAMED_CHARACTER_REFERENCE(1494, 'n' _ 's' _ 'c' _ 'c' _ 'u' _ 'e' _ ';', 7, 0x22e1, 1) +NAMED_CHARACTER_REFERENCE(1495, 'n' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc3, 2) +NAMED_CHARACTER_REFERENCE(1496, 'n' _ 's' _ 'h' _ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 10, 0x2224, 1) +NAMED_CHARACTER_REFERENCE(1497, 'n' _ 's' _ 'h' _ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 15, 0x2226, 1) +NAMED_CHARACTER_REFERENCE(1498, 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2241, 1) +NAMED_CHARACTER_REFERENCE(1499, 'n' _ 's' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x2244, 1) +NAMED_CHARACTER_REFERENCE(1500, 'n' _ 's' _ 'i' _ 'm' _ 'e' _ 'q' _ ';', 7, 0x2244, 1) +NAMED_CHARACTER_REFERENCE(1501, 'n' _ 's' _ 'm' _ 'i' _ 'd' _ ';', 6, 0x2224, 1) +NAMED_CHARACTER_REFERENCE(1502, 'n' _ 's' _ 'p' _ 'a' _ 'r' _ ';', 6, 0x2226, 1) +NAMED_CHARACTER_REFERENCE(1503, 'n' _ 's' _ 'q' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 8, 0x22e2, 1) +NAMED_CHARACTER_REFERENCE(1504, 'n' _ 's' _ 'q' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 8, 0x22e3, 1) +NAMED_CHARACTER_REFERENCE(1505, 'n' _ 's' _ 'u' _ 'b' _ ';', 5, 0x2284, 1) +NAMED_CHARACTER_REFERENCE(1506, 'n' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 6, 0x2288, 1) +NAMED_CHARACTER_REFERENCE(1507, 'n' _ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 10, 0x2288, 1) +NAMED_CHARACTER_REFERENCE(1508, 'n' _ 's' _ 'u' _ 'c' _ 'c' _ ';', 6, 0x2281, 1) +NAMED_CHARACTER_REFERENCE(1509, 'n' _ 's' _ 'u' _ 'p' _ ';', 5, 0x2285, 1) +NAMED_CHARACTER_REFERENCE(1510, 'n' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 6, 0x2289, 1) +NAMED_CHARACTER_REFERENCE(1511, 'n' _ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 10, 0x2289, 1) +NAMED_CHARACTER_REFERENCE(1512, 'n' _ 't' _ 'g' _ 'l' _ ';', 5, 0x2279, 1) +NAMED_CHARACTER_REFERENCE(1513, 'n' _ 't' _ 'i' _ 'l' _ 'd' _ 'e', 6, 0x00f1, 1) +NAMED_CHARACTER_REFERENCE(1514, 'n' _ 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x00f1, 1) +NAMED_CHARACTER_REFERENCE(1515, 'n' _ 't' _ 'l' _ 'g' _ ';', 5, 0x2278, 1) +NAMED_CHARACTER_REFERENCE(1516, 'n' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x22ea, 1) +NAMED_CHARACTER_REFERENCE(1517, 'n' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 16, 0x22ec, 1) +NAMED_CHARACTER_REFERENCE(1518, 'n' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x22eb, 1) +NAMED_CHARACTER_REFERENCE(1519, 'n' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 17, 0x22ed, 1) +NAMED_CHARACTER_REFERENCE(1520, 'n' _ 'u' _ ';', 3, 0x03bd, 1) +NAMED_CHARACTER_REFERENCE(1521, 'n' _ 'u' _ 'm' _ ';', 4, 0x0023, 1) +NAMED_CHARACTER_REFERENCE(1522, 'n' _ 'u' _ 'm' _ 'e' _ 'r' _ 'o' _ ';', 7, 0x2116, 1) +NAMED_CHARACTER_REFERENCE(1523, 'n' _ 'u' _ 'm' _ 's' _ 'p' _ ';', 6, 0x2007, 1) +NAMED_CHARACTER_REFERENCE(1524, 'n' _ 'v' _ 'D' _ 'a' _ 's' _ 'h' _ ';', 7, 0x22ad, 1) +NAMED_CHARACTER_REFERENCE(1525, 'n' _ 'v' _ 'H' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x2904, 1) +NAMED_CHARACTER_REFERENCE(1526, 'n' _ 'v' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 7, 0x22ac, 1) +NAMED_CHARACTER_REFERENCE(1527, 'n' _ 'v' _ 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 8, 0x29de, 1) +NAMED_CHARACTER_REFERENCE(1528, 'n' _ 'v' _ 'l' _ 'A' _ 'r' _ 'r' _ ';', 7, 0x2902, 1) +NAMED_CHARACTER_REFERENCE(1529, 'n' _ 'v' _ 'r' _ 'A' _ 'r' _ 'r' _ ';', 7, 0x2903, 1) +NAMED_CHARACTER_REFERENCE(1530, 'n' _ 'w' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21d6, 1) +NAMED_CHARACTER_REFERENCE(1531, 'n' _ 'w' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, 0x2923, 1) +NAMED_CHARACTER_REFERENCE(1532, 'n' _ 'w' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2196, 1) +NAMED_CHARACTER_REFERENCE(1533, 'n' _ 'w' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2196, 1) +NAMED_CHARACTER_REFERENCE(1534, 'n' _ 'w' _ 'n' _ 'e' _ 'a' _ 'r' _ ';', 7, 0x2927, 1) +NAMED_CHARACTER_REFERENCE(1535, 'o' _ 'S' _ ';', 3, 0x24c8, 1) +NAMED_CHARACTER_REFERENCE(1536, 'o' _ 'a' _ 'c' _ 'u' _ 't' _ 'e', 6, 0x00f3, 1) +NAMED_CHARACTER_REFERENCE(1537, 'o' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x00f3, 1) +NAMED_CHARACTER_REFERENCE(1538, 'o' _ 'a' _ 's' _ 't' _ ';', 5, 0x229b, 1) +NAMED_CHARACTER_REFERENCE(1539, 'o' _ 'c' _ 'i' _ 'r' _ ';', 5, 0x229a, 1) +NAMED_CHARACTER_REFERENCE(1540, 'o' _ 'c' _ 'i' _ 'r' _ 'c', 5, 0x00f4, 1) +NAMED_CHARACTER_REFERENCE(1541, 'o' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x00f4, 1) +NAMED_CHARACTER_REFERENCE(1542, 'o' _ 'c' _ 'y' _ ';', 4, 0x043e, 1) +NAMED_CHARACTER_REFERENCE(1543, 'o' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 6, 0x229d, 1) +NAMED_CHARACTER_REFERENCE(1544, 'o' _ 'd' _ 'b' _ 'l' _ 'a' _ 'c' _ ';', 7, 0x0151, 1) +NAMED_CHARACTER_REFERENCE(1545, 'o' _ 'd' _ 'i' _ 'v' _ ';', 5, 0x2a38, 1) +NAMED_CHARACTER_REFERENCE(1546, 'o' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2299, 1) +NAMED_CHARACTER_REFERENCE(1547, 'o' _ 'd' _ 's' _ 'o' _ 'l' _ 'd' _ ';', 7, 0x29bc, 1) +NAMED_CHARACTER_REFERENCE(1548, 'o' _ 'e' _ 'l' _ 'i' _ 'g' _ ';', 6, 0x0153, 1) +NAMED_CHARACTER_REFERENCE(1549, 'o' _ 'f' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x29bf, 1) +NAMED_CHARACTER_REFERENCE(1550, 'o' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd2c, 2) +NAMED_CHARACTER_REFERENCE(1551, 'o' _ 'g' _ 'o' _ 'n' _ ';', 5, 0x02db, 1) +NAMED_CHARACTER_REFERENCE(1552, 'o' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e', 6, 0x00f2, 1) +NAMED_CHARACTER_REFERENCE(1553, 'o' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 7, 0x00f2, 1) +NAMED_CHARACTER_REFERENCE(1554, 'o' _ 'g' _ 't' _ ';', 4, 0x29c1, 1) +NAMED_CHARACTER_REFERENCE(1555, 'o' _ 'h' _ 'b' _ 'a' _ 'r' _ ';', 6, 0x29b5, 1) +NAMED_CHARACTER_REFERENCE(1556, 'o' _ 'h' _ 'm' _ ';', 4, 0x03a9, 1) +NAMED_CHARACTER_REFERENCE(1557, 'o' _ 'i' _ 'n' _ 't' _ ';', 5, 0x222e, 1) +NAMED_CHARACTER_REFERENCE(1558, 'o' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21ba, 1) +NAMED_CHARACTER_REFERENCE(1559, 'o' _ 'l' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x29be, 1) +NAMED_CHARACTER_REFERENCE(1560, 'o' _ 'l' _ 'c' _ 'r' _ 'o' _ 's' _ 's' _ ';', 8, 0x29bb, 1) +NAMED_CHARACTER_REFERENCE(1561, 'o' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 6, 0x203e, 1) +NAMED_CHARACTER_REFERENCE(1562, 'o' _ 'l' _ 't' _ ';', 4, 0x29c0, 1) +NAMED_CHARACTER_REFERENCE(1563, 'o' _ 'm' _ 'a' _ 'c' _ 'r' _ ';', 6, 0x014d, 1) +NAMED_CHARACTER_REFERENCE(1564, 'o' _ 'm' _ 'e' _ 'g' _ 'a' _ ';', 6, 0x03c9, 1) +NAMED_CHARACTER_REFERENCE(1565, 'o' _ 'm' _ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 8, 0x03bf, 1) +NAMED_CHARACTER_REFERENCE(1566, 'o' _ 'm' _ 'i' _ 'd' _ ';', 5, 0x29b6, 1) +NAMED_CHARACTER_REFERENCE(1567, 'o' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0x2296, 1) +NAMED_CHARACTER_REFERENCE(1568, 'o' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd60, 2) +NAMED_CHARACTER_REFERENCE(1569, 'o' _ 'p' _ 'a' _ 'r' _ ';', 5, 0x29b7, 1) +NAMED_CHARACTER_REFERENCE(1570, 'o' _ 'p' _ 'e' _ 'r' _ 'p' _ ';', 6, 0x29b9, 1) +NAMED_CHARACTER_REFERENCE(1571, 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2295, 1) +NAMED_CHARACTER_REFERENCE(1572, 'o' _ 'r' _ ';', 3, 0x2228, 1) +NAMED_CHARACTER_REFERENCE(1573, 'o' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21bb, 1) +NAMED_CHARACTER_REFERENCE(1574, 'o' _ 'r' _ 'd' _ ';', 4, 0x2a5d, 1) +NAMED_CHARACTER_REFERENCE(1575, 'o' _ 'r' _ 'd' _ 'e' _ 'r' _ ';', 6, 0x2134, 1) +NAMED_CHARACTER_REFERENCE(1576, 'o' _ 'r' _ 'd' _ 'e' _ 'r' _ 'o' _ 'f' _ ';', 8, 0x2134, 1) +NAMED_CHARACTER_REFERENCE(1577, 'o' _ 'r' _ 'd' _ 'f', 4, 0x00aa, 1) +NAMED_CHARACTER_REFERENCE(1578, 'o' _ 'r' _ 'd' _ 'f' _ ';', 5, 0x00aa, 1) +NAMED_CHARACTER_REFERENCE(1579, 'o' _ 'r' _ 'd' _ 'm', 4, 0x00ba, 1) +NAMED_CHARACTER_REFERENCE(1580, 'o' _ 'r' _ 'd' _ 'm' _ ';', 5, 0x00ba, 1) +NAMED_CHARACTER_REFERENCE(1581, 'o' _ 'r' _ 'i' _ 'g' _ 'o' _ 'f' _ ';', 7, 0x22b6, 1) +NAMED_CHARACTER_REFERENCE(1582, 'o' _ 'r' _ 'o' _ 'r' _ ';', 5, 0x2a56, 1) +NAMED_CHARACTER_REFERENCE(1583, 'o' _ 'r' _ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 8, 0x2a57, 1) +NAMED_CHARACTER_REFERENCE(1584, 'o' _ 'r' _ 'v' _ ';', 4, 0x2a5b, 1) +NAMED_CHARACTER_REFERENCE(1585, 'o' _ 's' _ 'c' _ 'r' _ ';', 5, 0x2134, 1) +NAMED_CHARACTER_REFERENCE(1586, 'o' _ 's' _ 'l' _ 'a' _ 's' _ 'h', 6, 0x00f8, 1) +NAMED_CHARACTER_REFERENCE(1587, 'o' _ 's' _ 'l' _ 'a' _ 's' _ 'h' _ ';', 7, 0x00f8, 1) +NAMED_CHARACTER_REFERENCE(1588, 'o' _ 's' _ 'o' _ 'l' _ ';', 5, 0x2298, 1) +NAMED_CHARACTER_REFERENCE(1589, 'o' _ 't' _ 'i' _ 'l' _ 'd' _ 'e', 6, 0x00f5, 1) +NAMED_CHARACTER_REFERENCE(1590, 'o' _ 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x00f5, 1) +NAMED_CHARACTER_REFERENCE(1591, 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0x2297, 1) +NAMED_CHARACTER_REFERENCE(1592, 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ 'a' _ 's' _ ';', 9, 0x2a36, 1) +NAMED_CHARACTER_REFERENCE(1593, 'o' _ 'u' _ 'm' _ 'l', 4, 0x00f6, 1) +NAMED_CHARACTER_REFERENCE(1594, 'o' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00f6, 1) +NAMED_CHARACTER_REFERENCE(1595, 'o' _ 'v' _ 'b' _ 'a' _ 'r' _ ';', 6, 0x233d, 1) +NAMED_CHARACTER_REFERENCE(1596, 'p' _ 'a' _ 'r' _ ';', 4, 0x2225, 1) +NAMED_CHARACTER_REFERENCE(1597, 'p' _ 'a' _ 'r' _ 'a', 4, 0x00b6, 1) +NAMED_CHARACTER_REFERENCE(1598, 'p' _ 'a' _ 'r' _ 'a' _ ';', 5, 0x00b6, 1) +NAMED_CHARACTER_REFERENCE(1599, 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 9, 0x2225, 1) +NAMED_CHARACTER_REFERENCE(1600, 'p' _ 'a' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 7, 0x2af3, 1) +NAMED_CHARACTER_REFERENCE(1601, 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 6, 0x2afd, 1) +NAMED_CHARACTER_REFERENCE(1602, 'p' _ 'a' _ 'r' _ 't' _ ';', 5, 0x2202, 1) +NAMED_CHARACTER_REFERENCE(1603, 'p' _ 'c' _ 'y' _ ';', 4, 0x043f, 1) +NAMED_CHARACTER_REFERENCE(1604, 'p' _ 'e' _ 'r' _ 'c' _ 'n' _ 't' _ ';', 7, 0x0025, 1) +NAMED_CHARACTER_REFERENCE(1605, 'p' _ 'e' _ 'r' _ 'i' _ 'o' _ 'd' _ ';', 7, 0x002e, 1) +NAMED_CHARACTER_REFERENCE(1606, 'p' _ 'e' _ 'r' _ 'm' _ 'i' _ 'l' _ ';', 7, 0x2030, 1) +NAMED_CHARACTER_REFERENCE(1607, 'p' _ 'e' _ 'r' _ 'p' _ ';', 5, 0x22a5, 1) +NAMED_CHARACTER_REFERENCE(1608, 'p' _ 'e' _ 'r' _ 't' _ 'e' _ 'n' _ 'k' _ ';', 8, 0x2031, 1) +NAMED_CHARACTER_REFERENCE(1609, 'p' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd2d, 2) +NAMED_CHARACTER_REFERENCE(1610, 'p' _ 'h' _ 'i' _ ';', 4, 0x03c6, 1) +NAMED_CHARACTER_REFERENCE(1611, 'p' _ 'h' _ 'i' _ 'v' _ ';', 5, 0x03d5, 1) +NAMED_CHARACTER_REFERENCE(1612, 'p' _ 'h' _ 'm' _ 'm' _ 'a' _ 't' _ ';', 7, 0x2133, 1) +NAMED_CHARACTER_REFERENCE(1613, 'p' _ 'h' _ 'o' _ 'n' _ 'e' _ ';', 6, 0x260e, 1) +NAMED_CHARACTER_REFERENCE(1614, 'p' _ 'i' _ ';', 3, 0x03c0, 1) +NAMED_CHARACTER_REFERENCE(1615, 'p' _ 'i' _ 't' _ 'c' _ 'h' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 10, 0x22d4, 1) +NAMED_CHARACTER_REFERENCE(1616, 'p' _ 'i' _ 'v' _ ';', 4, 0x03d6, 1) +NAMED_CHARACTER_REFERENCE(1617, 'p' _ 'l' _ 'a' _ 'n' _ 'c' _ 'k' _ ';', 7, 0x210f, 1) +NAMED_CHARACTER_REFERENCE(1618, 'p' _ 'l' _ 'a' _ 'n' _ 'c' _ 'k' _ 'h' _ ';', 8, 0x210e, 1) +NAMED_CHARACTER_REFERENCE(1619, 'p' _ 'l' _ 'a' _ 'n' _ 'k' _ 'v' _ ';', 7, 0x210f, 1) +NAMED_CHARACTER_REFERENCE(1620, 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x002b, 1) +NAMED_CHARACTER_REFERENCE(1621, 'p' _ 'l' _ 'u' _ 's' _ 'a' _ 'c' _ 'i' _ 'r' _ ';', 9, 0x2a23, 1) +NAMED_CHARACTER_REFERENCE(1622, 'p' _ 'l' _ 'u' _ 's' _ 'b' _ ';', 6, 0x229e, 1) +NAMED_CHARACTER_REFERENCE(1623, 'p' _ 'l' _ 'u' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 8, 0x2a22, 1) +NAMED_CHARACTER_REFERENCE(1624, 'p' _ 'l' _ 'u' _ 's' _ 'd' _ 'o' _ ';', 7, 0x2214, 1) +NAMED_CHARACTER_REFERENCE(1625, 'p' _ 'l' _ 'u' _ 's' _ 'd' _ 'u' _ ';', 7, 0x2a25, 1) +NAMED_CHARACTER_REFERENCE(1626, 'p' _ 'l' _ 'u' _ 's' _ 'e' _ ';', 6, 0x2a72, 1) +NAMED_CHARACTER_REFERENCE(1627, 'p' _ 'l' _ 'u' _ 's' _ 'm' _ 'n', 6, 0x00b1, 1) +NAMED_CHARACTER_REFERENCE(1628, 'p' _ 'l' _ 'u' _ 's' _ 'm' _ 'n' _ ';', 7, 0x00b1, 1) +NAMED_CHARACTER_REFERENCE(1629, 'p' _ 'l' _ 'u' _ 's' _ 's' _ 'i' _ 'm' _ ';', 8, 0x2a26, 1) +NAMED_CHARACTER_REFERENCE(1630, 'p' _ 'l' _ 'u' _ 's' _ 't' _ 'w' _ 'o' _ ';', 8, 0x2a27, 1) +NAMED_CHARACTER_REFERENCE(1631, 'p' _ 'm' _ ';', 3, 0x00b1, 1) +NAMED_CHARACTER_REFERENCE(1632, 'p' _ 'o' _ 'i' _ 'n' _ 't' _ 'i' _ 'n' _ 't' _ ';', 9, 0x2a15, 1) +NAMED_CHARACTER_REFERENCE(1633, 'p' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd61, 2) +NAMED_CHARACTER_REFERENCE(1634, 'p' _ 'o' _ 'u' _ 'n' _ 'd', 5, 0x00a3, 1) +NAMED_CHARACTER_REFERENCE(1635, 'p' _ 'o' _ 'u' _ 'n' _ 'd' _ ';', 6, 0x00a3, 1) +NAMED_CHARACTER_REFERENCE(1636, 'p' _ 'r' _ ';', 3, 0x227a, 1) +NAMED_CHARACTER_REFERENCE(1637, 'p' _ 'r' _ 'E' _ ';', 4, 0x2ab3, 1) +NAMED_CHARACTER_REFERENCE(1638, 'p' _ 'r' _ 'a' _ 'p' _ ';', 5, 0x2ab7, 1) +NAMED_CHARACTER_REFERENCE(1639, 'p' _ 'r' _ 'c' _ 'u' _ 'e' _ ';', 6, 0x227c, 1) +NAMED_CHARACTER_REFERENCE(1640, 'p' _ 'r' _ 'e' _ ';', 4, 0x2aaf, 1) +NAMED_CHARACTER_REFERENCE(1641, 'p' _ 'r' _ 'e' _ 'c' _ ';', 5, 0x227a, 1) +NAMED_CHARACTER_REFERENCE(1642, 'p' _ 'r' _ 'e' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 11, 0x2ab7, 1) +NAMED_CHARACTER_REFERENCE(1643, 'p' _ 'r' _ 'e' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 12, 0x227c, 1) +NAMED_CHARACTER_REFERENCE(1644, 'p' _ 'r' _ 'e' _ 'c' _ 'e' _ 'q' _ ';', 7, 0x2aaf, 1) +NAMED_CHARACTER_REFERENCE(1645, 'p' _ 'r' _ 'e' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 12, 0x2ab9, 1) +NAMED_CHARACTER_REFERENCE(1646, 'p' _ 'r' _ 'e' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0x2ab5, 1) +NAMED_CHARACTER_REFERENCE(1647, 'p' _ 'r' _ 'e' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 9, 0x22e8, 1) +NAMED_CHARACTER_REFERENCE(1648, 'p' _ 'r' _ 'e' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 8, 0x227e, 1) +NAMED_CHARACTER_REFERENCE(1649, 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x2032, 1) +NAMED_CHARACTER_REFERENCE(1650, 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0x2119, 1) +NAMED_CHARACTER_REFERENCE(1651, 'p' _ 'r' _ 'n' _ 'E' _ ';', 5, 0x2ab5, 1) +NAMED_CHARACTER_REFERENCE(1652, 'p' _ 'r' _ 'n' _ 'a' _ 'p' _ ';', 6, 0x2ab9, 1) +NAMED_CHARACTER_REFERENCE(1653, 'p' _ 'r' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, 0x22e8, 1) +NAMED_CHARACTER_REFERENCE(1654, 'p' _ 'r' _ 'o' _ 'd' _ ';', 5, 0x220f, 1) +NAMED_CHARACTER_REFERENCE(1655, 'p' _ 'r' _ 'o' _ 'f' _ 'a' _ 'l' _ 'a' _ 'r' _ ';', 9, 0x232e, 1) +NAMED_CHARACTER_REFERENCE(1656, 'p' _ 'r' _ 'o' _ 'f' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 9, 0x2312, 1) +NAMED_CHARACTER_REFERENCE(1657, 'p' _ 'r' _ 'o' _ 'f' _ 's' _ 'u' _ 'r' _ 'f' _ ';', 9, 0x2313, 1) +NAMED_CHARACTER_REFERENCE(1658, 'p' _ 'r' _ 'o' _ 'p' _ ';', 5, 0x221d, 1) +NAMED_CHARACTER_REFERENCE(1659, 'p' _ 'r' _ 'o' _ 'p' _ 't' _ 'o' _ ';', 7, 0x221d, 1) +NAMED_CHARACTER_REFERENCE(1660, 'p' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0x227e, 1) +NAMED_CHARACTER_REFERENCE(1661, 'p' _ 'r' _ 'u' _ 'r' _ 'e' _ 'l' _ ';', 7, 0x22b0, 1) +NAMED_CHARACTER_REFERENCE(1662, 'p' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc5, 2) +NAMED_CHARACTER_REFERENCE(1663, 'p' _ 's' _ 'i' _ ';', 4, 0x03c8, 1) +NAMED_CHARACTER_REFERENCE(1664, 'p' _ 'u' _ 'n' _ 'c' _ 's' _ 'p' _ ';', 7, 0x2008, 1) +NAMED_CHARACTER_REFERENCE(1665, 'q' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd2e, 2) +NAMED_CHARACTER_REFERENCE(1666, 'q' _ 'i' _ 'n' _ 't' _ ';', 5, 0x2a0c, 1) +NAMED_CHARACTER_REFERENCE(1667, 'q' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd62, 2) +NAMED_CHARACTER_REFERENCE(1668, 'q' _ 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 7, 0x2057, 1) +NAMED_CHARACTER_REFERENCE(1669, 'q' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc6, 2) +NAMED_CHARACTER_REFERENCE(1670, 'q' _ 'u' _ 'a' _ 't' _ 'e' _ 'r' _ 'n' _ 'i' _ 'o' _ 'n' _ 's' _ ';', 12, 0x210d, 1) +NAMED_CHARACTER_REFERENCE(1671, 'q' _ 'u' _ 'a' _ 't' _ 'i' _ 'n' _ 't' _ ';', 8, 0x2a16, 1) +NAMED_CHARACTER_REFERENCE(1672, 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0x003f, 1) +NAMED_CHARACTER_REFERENCE(1673, 'q' _ 'u' _ 'e' _ 's' _ 't' _ 'e' _ 'q' _ ';', 8, 0x225f, 1) +NAMED_CHARACTER_REFERENCE(1674, 'q' _ 'u' _ 'o' _ 't', 4, 0x0022, 1) +NAMED_CHARACTER_REFERENCE(1675, 'q' _ 'u' _ 'o' _ 't' _ ';', 5, 0x0022, 1) +NAMED_CHARACTER_REFERENCE(1676, 'r' _ 'A' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21db, 1) +NAMED_CHARACTER_REFERENCE(1677, 'r' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d2, 1) +NAMED_CHARACTER_REFERENCE(1678, 'r' _ 'A' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 7, 0x291c, 1) +NAMED_CHARACTER_REFERENCE(1679, 'r' _ 'B' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x290f, 1) +NAMED_CHARACTER_REFERENCE(1680, 'r' _ 'H' _ 'a' _ 'r' _ ';', 5, 0x2964, 1) NAMED_CHARACTER_REFERENCE(1681, 'r' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x0155, 1) NAMED_CHARACTER_REFERENCE(1682, 'r' _ 'a' _ 'd' _ 'i' _ 'c' _ ';', 6, 0x221a, 1) NAMED_CHARACTER_REFERENCE(1683, 'r' _ 'a' _ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 9, 0x29b3, 1) @@ -1933,230 +1933,231 @@ NAMED_CHARACTER_REFERENCE(1908, 's' _ 'u' _ 'p' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2a NAMED_CHARACTER_REFERENCE(1909, 's' _ 'u' _ 'p' _ 'd' _ 's' _ 'u' _ 'b' _ ';', 8, 0x2ad8, 1) NAMED_CHARACTER_REFERENCE(1910, 's' _ 'u' _ 'p' _ 'e' _ ';', 5, 0x2287, 1) NAMED_CHARACTER_REFERENCE(1911, 's' _ 'u' _ 'p' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 8, 0x2ac4, 1) -NAMED_CHARACTER_REFERENCE(1912, 's' _ 'u' _ 'p' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 8, 0x2ad7, 1) -NAMED_CHARACTER_REFERENCE(1913, 's' _ 'u' _ 'p' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 8, 0x297b, 1) -NAMED_CHARACTER_REFERENCE(1914, 's' _ 'u' _ 'p' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 8, 0x2ac2, 1) -NAMED_CHARACTER_REFERENCE(1915, 's' _ 'u' _ 'p' _ 'n' _ 'E' _ ';', 6, 0x2acc, 1) -NAMED_CHARACTER_REFERENCE(1916, 's' _ 'u' _ 'p' _ 'n' _ 'e' _ ';', 6, 0x228b, 1) -NAMED_CHARACTER_REFERENCE(1917, 's' _ 'u' _ 'p' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 8, 0x2ac0, 1) -NAMED_CHARACTER_REFERENCE(1918, 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ ';', 7, 0x2283, 1) -NAMED_CHARACTER_REFERENCE(1919, 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0x2287, 1) -NAMED_CHARACTER_REFERENCE(1920, 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 10, 0x2ac6, 1) -NAMED_CHARACTER_REFERENCE(1921, 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 10, 0x228b, 1) -NAMED_CHARACTER_REFERENCE(1922, 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 11, 0x2acc, 1) -NAMED_CHARACTER_REFERENCE(1923, 's' _ 'u' _ 'p' _ 's' _ 'i' _ 'm' _ ';', 7, 0x2ac8, 1) -NAMED_CHARACTER_REFERENCE(1924, 's' _ 'u' _ 'p' _ 's' _ 'u' _ 'b' _ ';', 7, 0x2ad4, 1) -NAMED_CHARACTER_REFERENCE(1925, 's' _ 'u' _ 'p' _ 's' _ 'u' _ 'p' _ ';', 7, 0x2ad6, 1) -NAMED_CHARACTER_REFERENCE(1926, 's' _ 'w' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21d9, 1) -NAMED_CHARACTER_REFERENCE(1927, 's' _ 'w' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, 0x2926, 1) -NAMED_CHARACTER_REFERENCE(1928, 's' _ 'w' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2199, 1) -NAMED_CHARACTER_REFERENCE(1929, 's' _ 'w' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2199, 1) -NAMED_CHARACTER_REFERENCE(1930, 's' _ 'w' _ 'n' _ 'w' _ 'a' _ 'r' _ ';', 7, 0x292a, 1) -NAMED_CHARACTER_REFERENCE(1931, 's' _ 'z' _ 'l' _ 'i' _ 'g', 5, 0x00df, 1) -NAMED_CHARACTER_REFERENCE(1932, 's' _ 'z' _ 'l' _ 'i' _ 'g' _ ';', 6, 0x00df, 1) -NAMED_CHARACTER_REFERENCE(1933, 't' _ 'a' _ 'r' _ 'g' _ 'e' _ 't' _ ';', 7, 0x2316, 1) -NAMED_CHARACTER_REFERENCE(1934, 't' _ 'a' _ 'u' _ ';', 4, 0x03c4, 1) -NAMED_CHARACTER_REFERENCE(1935, 't' _ 'b' _ 'r' _ 'k' _ ';', 5, 0x23b4, 1) -NAMED_CHARACTER_REFERENCE(1936, 't' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x0165, 1) -NAMED_CHARACTER_REFERENCE(1937, 't' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 7, 0x0163, 1) -NAMED_CHARACTER_REFERENCE(1938, 't' _ 'c' _ 'y' _ ';', 4, 0x0442, 1) -NAMED_CHARACTER_REFERENCE(1939, 't' _ 'd' _ 'o' _ 't' _ ';', 5, 0x20db, 1) -NAMED_CHARACTER_REFERENCE(1940, 't' _ 'e' _ 'l' _ 'r' _ 'e' _ 'c' _ ';', 7, 0x2315, 1) -NAMED_CHARACTER_REFERENCE(1941, 't' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd31, 2) -NAMED_CHARACTER_REFERENCE(1942, 't' _ 'h' _ 'e' _ 'r' _ 'e' _ '4' _ ';', 7, 0x2234, 1) -NAMED_CHARACTER_REFERENCE(1943, 't' _ 'h' _ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 10, 0x2234, 1) -NAMED_CHARACTER_REFERENCE(1944, 't' _ 'h' _ 'e' _ 't' _ 'a' _ ';', 6, 0x03b8, 1) -NAMED_CHARACTER_REFERENCE(1945, 't' _ 'h' _ 'e' _ 't' _ 'a' _ 's' _ 'y' _ 'm' _ ';', 9, 0x03d1, 1) -NAMED_CHARACTER_REFERENCE(1946, 't' _ 'h' _ 'e' _ 't' _ 'a' _ 'v' _ ';', 7, 0x03d1, 1) -NAMED_CHARACTER_REFERENCE(1947, 't' _ 'h' _ 'i' _ 'c' _ 'k' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 12, 0x2248, 1) -NAMED_CHARACTER_REFERENCE(1948, 't' _ 'h' _ 'i' _ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 9, 0x223c, 1) -NAMED_CHARACTER_REFERENCE(1949, 't' _ 'h' _ 'i' _ 'n' _ 's' _ 'p' _ ';', 7, 0x2009, 1) -NAMED_CHARACTER_REFERENCE(1950, 't' _ 'h' _ 'k' _ 'a' _ 'p' _ ';', 6, 0x2248, 1) -NAMED_CHARACTER_REFERENCE(1951, 't' _ 'h' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 7, 0x223c, 1) -NAMED_CHARACTER_REFERENCE(1952, 't' _ 'h' _ 'o' _ 'r' _ 'n', 5, 0x00fe, 1) -NAMED_CHARACTER_REFERENCE(1953, 't' _ 'h' _ 'o' _ 'r' _ 'n' _ ';', 6, 0x00fe, 1) -NAMED_CHARACTER_REFERENCE(1954, 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 6, 0x02dc, 1) -NAMED_CHARACTER_REFERENCE(1955, 't' _ 'i' _ 'm' _ 'e' _ 's', 5, 0x00d7, 1) -NAMED_CHARACTER_REFERENCE(1956, 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0x00d7, 1) -NAMED_CHARACTER_REFERENCE(1957, 't' _ 'i' _ 'm' _ 'e' _ 's' _ 'b' _ ';', 7, 0x22a0, 1) -NAMED_CHARACTER_REFERENCE(1958, 't' _ 'i' _ 'm' _ 'e' _ 's' _ 'b' _ 'a' _ 'r' _ ';', 9, 0x2a31, 1) -NAMED_CHARACTER_REFERENCE(1959, 't' _ 'i' _ 'm' _ 'e' _ 's' _ 'd' _ ';', 7, 0x2a30, 1) -NAMED_CHARACTER_REFERENCE(1960, 't' _ 'i' _ 'n' _ 't' _ ';', 5, 0x222d, 1) -NAMED_CHARACTER_REFERENCE(1961, 't' _ 'o' _ 'e' _ 'a' _ ';', 5, 0x2928, 1) -NAMED_CHARACTER_REFERENCE(1962, 't' _ 'o' _ 'p' _ ';', 4, 0x22a4, 1) -NAMED_CHARACTER_REFERENCE(1963, 't' _ 'o' _ 'p' _ 'b' _ 'o' _ 't' _ ';', 7, 0x2336, 1) -NAMED_CHARACTER_REFERENCE(1964, 't' _ 'o' _ 'p' _ 'c' _ 'i' _ 'r' _ ';', 7, 0x2af1, 1) -NAMED_CHARACTER_REFERENCE(1965, 't' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd65, 2) -NAMED_CHARACTER_REFERENCE(1966, 't' _ 'o' _ 'p' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 8, 0x2ada, 1) -NAMED_CHARACTER_REFERENCE(1967, 't' _ 'o' _ 's' _ 'a' _ ';', 5, 0x2929, 1) -NAMED_CHARACTER_REFERENCE(1968, 't' _ 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 7, 0x2034, 1) -NAMED_CHARACTER_REFERENCE(1969, 't' _ 'r' _ 'a' _ 'd' _ 'e' _ ';', 6, 0x2122, 1) -NAMED_CHARACTER_REFERENCE(1970, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 9, 0x25b5, 1) -NAMED_CHARACTER_REFERENCE(1971, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 13, 0x25bf, 1) -NAMED_CHARACTER_REFERENCE(1972, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 13, 0x25c3, 1) -NAMED_CHARACTER_REFERENCE(1973, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 15, 0x22b4, 1) -NAMED_CHARACTER_REFERENCE(1974, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'q' _ ';', 10, 0x225c, 1) -NAMED_CHARACTER_REFERENCE(1975, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 14, 0x25b9, 1) -NAMED_CHARACTER_REFERENCE(1976, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 16, 0x22b5, 1) -NAMED_CHARACTER_REFERENCE(1977, 't' _ 'r' _ 'i' _ 'd' _ 'o' _ 't' _ ';', 7, 0x25ec, 1) -NAMED_CHARACTER_REFERENCE(1978, 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0x225c, 1) -NAMED_CHARACTER_REFERENCE(1979, 't' _ 'r' _ 'i' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 9, 0x2a3a, 1) -NAMED_CHARACTER_REFERENCE(1980, 't' _ 'r' _ 'i' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 8, 0x2a39, 1) -NAMED_CHARACTER_REFERENCE(1981, 't' _ 'r' _ 'i' _ 's' _ 'b' _ ';', 6, 0x29cd, 1) -NAMED_CHARACTER_REFERENCE(1982, 't' _ 'r' _ 'i' _ 't' _ 'i' _ 'm' _ 'e' _ ';', 8, 0x2a3b, 1) -NAMED_CHARACTER_REFERENCE(1983, 't' _ 'r' _ 'p' _ 'e' _ 'z' _ 'i' _ 'u' _ 'm' _ ';', 9, 0x23e2, 1) -NAMED_CHARACTER_REFERENCE(1984, 't' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc9, 2) -NAMED_CHARACTER_REFERENCE(1985, 't' _ 's' _ 'c' _ 'y' _ ';', 5, 0x0446, 1) -NAMED_CHARACTER_REFERENCE(1986, 't' _ 's' _ 'h' _ 'c' _ 'y' _ ';', 6, 0x045b, 1) -NAMED_CHARACTER_REFERENCE(1987, 't' _ 's' _ 't' _ 'r' _ 'o' _ 'k' _ ';', 7, 0x0167, 1) -NAMED_CHARACTER_REFERENCE(1988, 't' _ 'w' _ 'i' _ 'x' _ 't' _ ';', 6, 0x226c, 1) -NAMED_CHARACTER_REFERENCE(1989, 't' _ 'w' _ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0x219e, 1) -NAMED_CHARACTER_REFERENCE(1990, 't' _ 'w' _ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0x21a0, 1) -NAMED_CHARACTER_REFERENCE(1991, 'u' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d1, 1) -NAMED_CHARACTER_REFERENCE(1992, 'u' _ 'H' _ 'a' _ 'r' _ ';', 5, 0x2963, 1) -NAMED_CHARACTER_REFERENCE(1993, 'u' _ 'a' _ 'c' _ 'u' _ 't' _ 'e', 6, 0x00fa, 1) -NAMED_CHARACTER_REFERENCE(1994, 'u' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x00fa, 1) -NAMED_CHARACTER_REFERENCE(1995, 'u' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2191, 1) -NAMED_CHARACTER_REFERENCE(1996, 'u' _ 'b' _ 'r' _ 'c' _ 'y' _ ';', 6, 0x045e, 1) -NAMED_CHARACTER_REFERENCE(1997, 'u' _ 'b' _ 'r' _ 'e' _ 'v' _ 'e' _ ';', 7, 0x016d, 1) -NAMED_CHARACTER_REFERENCE(1998, 'u' _ 'c' _ 'i' _ 'r' _ 'c', 5, 0x00fb, 1) -NAMED_CHARACTER_REFERENCE(1999, 'u' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x00fb, 1) -NAMED_CHARACTER_REFERENCE(2000, 'u' _ 'c' _ 'y' _ ';', 4, 0x0443, 1) -NAMED_CHARACTER_REFERENCE(2001, 'u' _ 'd' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21c5, 1) -NAMED_CHARACTER_REFERENCE(2002, 'u' _ 'd' _ 'b' _ 'l' _ 'a' _ 'c' _ ';', 7, 0x0171, 1) -NAMED_CHARACTER_REFERENCE(2003, 'u' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x296e, 1) -NAMED_CHARACTER_REFERENCE(2004, 'u' _ 'f' _ 'i' _ 's' _ 'h' _ 't' _ ';', 7, 0x297e, 1) -NAMED_CHARACTER_REFERENCE(2005, 'u' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd32, 2) -NAMED_CHARACTER_REFERENCE(2006, 'u' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e', 6, 0x00f9, 1) -NAMED_CHARACTER_REFERENCE(2007, 'u' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 7, 0x00f9, 1) -NAMED_CHARACTER_REFERENCE(2008, 'u' _ 'h' _ 'a' _ 'r' _ 'l' _ ';', 6, 0x21bf, 1) -NAMED_CHARACTER_REFERENCE(2009, 'u' _ 'h' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21be, 1) -NAMED_CHARACTER_REFERENCE(2010, 'u' _ 'h' _ 'b' _ 'l' _ 'k' _ ';', 6, 0x2580, 1) -NAMED_CHARACTER_REFERENCE(2011, 'u' _ 'l' _ 'c' _ 'o' _ 'r' _ 'n' _ ';', 7, 0x231c, 1) -NAMED_CHARACTER_REFERENCE(2012, 'u' _ 'l' _ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 9, 0x231c, 1) -NAMED_CHARACTER_REFERENCE(2013, 'u' _ 'l' _ 'c' _ 'r' _ 'o' _ 'p' _ ';', 7, 0x230f, 1) -NAMED_CHARACTER_REFERENCE(2014, 'u' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 6, 0x25f8, 1) -NAMED_CHARACTER_REFERENCE(2015, 'u' _ 'm' _ 'a' _ 'c' _ 'r' _ ';', 6, 0x016b, 1) -NAMED_CHARACTER_REFERENCE(2016, 'u' _ 'm' _ 'l', 3, 0x00a8, 1) -NAMED_CHARACTER_REFERENCE(2017, 'u' _ 'm' _ 'l' _ ';', 4, 0x00a8, 1) -NAMED_CHARACTER_REFERENCE(2018, 'u' _ 'o' _ 'g' _ 'o' _ 'n' _ ';', 6, 0x0173, 1) -NAMED_CHARACTER_REFERENCE(2019, 'u' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd66, 2) -NAMED_CHARACTER_REFERENCE(2020, 'u' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2191, 1) -NAMED_CHARACTER_REFERENCE(2021, 'u' _ 'p' _ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x2195, 1) -NAMED_CHARACTER_REFERENCE(2022, 'u' _ 'p' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x21bf, 1) -NAMED_CHARACTER_REFERENCE(2023, 'u' _ 'p' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x21be, 1) -NAMED_CHARACTER_REFERENCE(2024, 'u' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x228e, 1) -NAMED_CHARACTER_REFERENCE(2025, 'u' _ 'p' _ 's' _ 'i' _ ';', 5, 0x03c5, 1) -NAMED_CHARACTER_REFERENCE(2026, 'u' _ 'p' _ 's' _ 'i' _ 'h' _ ';', 6, 0x03d2, 1) -NAMED_CHARACTER_REFERENCE(2027, 'u' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 8, 0x03c5, 1) -NAMED_CHARACTER_REFERENCE(2028, 'u' _ 'p' _ 'u' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 11, 0x21c8, 1) -NAMED_CHARACTER_REFERENCE(2029, 'u' _ 'r' _ 'c' _ 'o' _ 'r' _ 'n' _ ';', 7, 0x231d, 1) -NAMED_CHARACTER_REFERENCE(2030, 'u' _ 'r' _ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 9, 0x231d, 1) -NAMED_CHARACTER_REFERENCE(2031, 'u' _ 'r' _ 'c' _ 'r' _ 'o' _ 'p' _ ';', 7, 0x230e, 1) -NAMED_CHARACTER_REFERENCE(2032, 'u' _ 'r' _ 'i' _ 'n' _ 'g' _ ';', 6, 0x016f, 1) -NAMED_CHARACTER_REFERENCE(2033, 'u' _ 'r' _ 't' _ 'r' _ 'i' _ ';', 6, 0x25f9, 1) -NAMED_CHARACTER_REFERENCE(2034, 'u' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcca, 2) -NAMED_CHARACTER_REFERENCE(2035, 'u' _ 't' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22f0, 1) -NAMED_CHARACTER_REFERENCE(2036, 'u' _ 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x0169, 1) -NAMED_CHARACTER_REFERENCE(2037, 'u' _ 't' _ 'r' _ 'i' _ ';', 5, 0x25b5, 1) -NAMED_CHARACTER_REFERENCE(2038, 'u' _ 't' _ 'r' _ 'i' _ 'f' _ ';', 6, 0x25b4, 1) -NAMED_CHARACTER_REFERENCE(2039, 'u' _ 'u' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21c8, 1) -NAMED_CHARACTER_REFERENCE(2040, 'u' _ 'u' _ 'm' _ 'l', 4, 0x00fc, 1) -NAMED_CHARACTER_REFERENCE(2041, 'u' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00fc, 1) -NAMED_CHARACTER_REFERENCE(2042, 'u' _ 'w' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 8, 0x29a7, 1) -NAMED_CHARACTER_REFERENCE(2043, 'v' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d5, 1) -NAMED_CHARACTER_REFERENCE(2044, 'v' _ 'B' _ 'a' _ 'r' _ ';', 5, 0x2ae8, 1) -NAMED_CHARACTER_REFERENCE(2045, 'v' _ 'B' _ 'a' _ 'r' _ 'v' _ ';', 6, 0x2ae9, 1) -NAMED_CHARACTER_REFERENCE(2046, 'v' _ 'D' _ 'a' _ 's' _ 'h' _ ';', 6, 0x22a8, 1) -NAMED_CHARACTER_REFERENCE(2047, 'v' _ 'a' _ 'n' _ 'g' _ 'r' _ 't' _ ';', 7, 0x299c, 1) -NAMED_CHARACTER_REFERENCE(2048, 'v' _ 'a' _ 'r' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 11, 0x03b5, 1) -NAMED_CHARACTER_REFERENCE(2049, 'v' _ 'a' _ 'r' _ 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ ';', 9, 0x03f0, 1) -NAMED_CHARACTER_REFERENCE(2050, 'v' _ 'a' _ 'r' _ 'n' _ 'o' _ 't' _ 'h' _ 'i' _ 'n' _ 'g' _ ';', 11, 0x2205, 1) -NAMED_CHARACTER_REFERENCE(2051, 'v' _ 'a' _ 'r' _ 'p' _ 'h' _ 'i' _ ';', 7, 0x03c6, 1) -NAMED_CHARACTER_REFERENCE(2052, 'v' _ 'a' _ 'r' _ 'p' _ 'i' _ ';', 6, 0x03d6, 1) -NAMED_CHARACTER_REFERENCE(2053, 'v' _ 'a' _ 'r' _ 'p' _ 'r' _ 'o' _ 'p' _ 't' _ 'o' _ ';', 10, 0x221d, 1) -NAMED_CHARACTER_REFERENCE(2054, 'v' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2195, 1) -NAMED_CHARACTER_REFERENCE(2055, 'v' _ 'a' _ 'r' _ 'r' _ 'h' _ 'o' _ ';', 7, 0x03f1, 1) -NAMED_CHARACTER_REFERENCE(2056, 'v' _ 'a' _ 'r' _ 's' _ 'i' _ 'g' _ 'm' _ 'a' _ ';', 9, 0x03c2, 1) -NAMED_CHARACTER_REFERENCE(2057, 'v' _ 'a' _ 'r' _ 't' _ 'h' _ 'e' _ 't' _ 'a' _ ';', 9, 0x03d1, 1) -NAMED_CHARACTER_REFERENCE(2058, 'v' _ 'a' _ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 16, 0x22b2, 1) -NAMED_CHARACTER_REFERENCE(2059, 'v' _ 'a' _ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 17, 0x22b3, 1) -NAMED_CHARACTER_REFERENCE(2060, 'v' _ 'c' _ 'y' _ ';', 4, 0x0432, 1) -NAMED_CHARACTER_REFERENCE(2061, 'v' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 6, 0x22a2, 1) -NAMED_CHARACTER_REFERENCE(2062, 'v' _ 'e' _ 'e' _ ';', 4, 0x2228, 1) -NAMED_CHARACTER_REFERENCE(2063, 'v' _ 'e' _ 'e' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x22bb, 1) -NAMED_CHARACTER_REFERENCE(2064, 'v' _ 'e' _ 'e' _ 'e' _ 'q' _ ';', 6, 0x225a, 1) -NAMED_CHARACTER_REFERENCE(2065, 'v' _ 'e' _ 'l' _ 'l' _ 'i' _ 'p' _ ';', 7, 0x22ee, 1) -NAMED_CHARACTER_REFERENCE(2066, 'v' _ 'e' _ 'r' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x007c, 1) -NAMED_CHARACTER_REFERENCE(2067, 'v' _ 'e' _ 'r' _ 't' _ ';', 5, 0x007c, 1) -NAMED_CHARACTER_REFERENCE(2068, 'v' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd33, 2) -NAMED_CHARACTER_REFERENCE(2069, 'v' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 6, 0x22b2, 1) -NAMED_CHARACTER_REFERENCE(2070, 'v' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd67, 2) -NAMED_CHARACTER_REFERENCE(2071, 'v' _ 'p' _ 'r' _ 'o' _ 'p' _ ';', 6, 0x221d, 1) -NAMED_CHARACTER_REFERENCE(2072, 'v' _ 'r' _ 't' _ 'r' _ 'i' _ ';', 6, 0x22b3, 1) -NAMED_CHARACTER_REFERENCE(2073, 'v' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdccb, 2) -NAMED_CHARACTER_REFERENCE(2074, 'v' _ 'z' _ 'i' _ 'g' _ 'z' _ 'a' _ 'g' _ ';', 8, 0x299a, 1) -NAMED_CHARACTER_REFERENCE(2075, 'w' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x0175, 1) -NAMED_CHARACTER_REFERENCE(2076, 'w' _ 'e' _ 'd' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x2a5f, 1) -NAMED_CHARACTER_REFERENCE(2077, 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 6, 0x2227, 1) -NAMED_CHARACTER_REFERENCE(2078, 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ 'q' _ ';', 7, 0x2259, 1) -NAMED_CHARACTER_REFERENCE(2079, 'w' _ 'e' _ 'i' _ 'e' _ 'r' _ 'p' _ ';', 7, 0x2118, 1) -NAMED_CHARACTER_REFERENCE(2080, 'w' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd34, 2) -NAMED_CHARACTER_REFERENCE(2081, 'w' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd68, 2) -NAMED_CHARACTER_REFERENCE(2082, 'w' _ 'p' _ ';', 3, 0x2118, 1) -NAMED_CHARACTER_REFERENCE(2083, 'w' _ 'r' _ ';', 3, 0x2240, 1) -NAMED_CHARACTER_REFERENCE(2084, 'w' _ 'r' _ 'e' _ 'a' _ 't' _ 'h' _ ';', 7, 0x2240, 1) -NAMED_CHARACTER_REFERENCE(2085, 'w' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdccc, 2) -NAMED_CHARACTER_REFERENCE(2086, 'x' _ 'c' _ 'a' _ 'p' _ ';', 5, 0x22c2, 1) -NAMED_CHARACTER_REFERENCE(2087, 'x' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x25ef, 1) -NAMED_CHARACTER_REFERENCE(2088, 'x' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x22c3, 1) -NAMED_CHARACTER_REFERENCE(2089, 'x' _ 'd' _ 't' _ 'r' _ 'i' _ ';', 6, 0x25bd, 1) -NAMED_CHARACTER_REFERENCE(2090, 'x' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd35, 2) -NAMED_CHARACTER_REFERENCE(2091, 'x' _ 'h' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x27fa, 1) -NAMED_CHARACTER_REFERENCE(2092, 'x' _ 'h' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x27f7, 1) -NAMED_CHARACTER_REFERENCE(2093, 'x' _ 'i' _ ';', 3, 0x03be, 1) -NAMED_CHARACTER_REFERENCE(2094, 'x' _ 'l' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x27f8, 1) -NAMED_CHARACTER_REFERENCE(2095, 'x' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x27f5, 1) -NAMED_CHARACTER_REFERENCE(2096, 'x' _ 'm' _ 'a' _ 'p' _ ';', 5, 0x27fc, 1) -NAMED_CHARACTER_REFERENCE(2097, 'x' _ 'n' _ 'i' _ 's' _ ';', 5, 0x22fb, 1) -NAMED_CHARACTER_REFERENCE(2098, 'x' _ 'o' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2a00, 1) -NAMED_CHARACTER_REFERENCE(2099, 'x' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd69, 2) -NAMED_CHARACTER_REFERENCE(2100, 'x' _ 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2a01, 1) -NAMED_CHARACTER_REFERENCE(2101, 'x' _ 'o' _ 't' _ 'i' _ 'm' _ 'e' _ ';', 7, 0x2a02, 1) -NAMED_CHARACTER_REFERENCE(2102, 'x' _ 'r' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x27f9, 1) -NAMED_CHARACTER_REFERENCE(2103, 'x' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x27f6, 1) -NAMED_CHARACTER_REFERENCE(2104, 'x' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdccd, 2) -NAMED_CHARACTER_REFERENCE(2105, 'x' _ 's' _ 'q' _ 'c' _ 'u' _ 'p' _ ';', 7, 0x2a06, 1) -NAMED_CHARACTER_REFERENCE(2106, 'x' _ 'u' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2a04, 1) -NAMED_CHARACTER_REFERENCE(2107, 'x' _ 'u' _ 't' _ 'r' _ 'i' _ ';', 6, 0x25b3, 1) -NAMED_CHARACTER_REFERENCE(2108, 'x' _ 'v' _ 'e' _ 'e' _ ';', 5, 0x22c1, 1) -NAMED_CHARACTER_REFERENCE(2109, 'x' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, 0x22c0, 1) -NAMED_CHARACTER_REFERENCE(2110, 'y' _ 'a' _ 'c' _ 'u' _ 't' _ 'e', 6, 0x00fd, 1) -NAMED_CHARACTER_REFERENCE(2111, 'y' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x00fd, 1) -NAMED_CHARACTER_REFERENCE(2112, 'y' _ 'a' _ 'c' _ 'y' _ ';', 5, 0x044f, 1) -NAMED_CHARACTER_REFERENCE(2113, 'y' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x0177, 1) -NAMED_CHARACTER_REFERENCE(2114, 'y' _ 'c' _ 'y' _ ';', 4, 0x044b, 1) -NAMED_CHARACTER_REFERENCE(2115, 'y' _ 'e' _ 'n', 3, 0x00a5, 1) -NAMED_CHARACTER_REFERENCE(2116, 'y' _ 'e' _ 'n' _ ';', 4, 0x00a5, 1) -NAMED_CHARACTER_REFERENCE(2117, 'y' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd36, 2) -NAMED_CHARACTER_REFERENCE(2118, 'y' _ 'i' _ 'c' _ 'y' _ ';', 5, 0x0457, 1) -NAMED_CHARACTER_REFERENCE(2119, 'y' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd6a, 2) -NAMED_CHARACTER_REFERENCE(2120, 'y' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcce, 2) -NAMED_CHARACTER_REFERENCE(2121, 'y' _ 'u' _ 'c' _ 'y' _ ';', 5, 0x044e, 1) -NAMED_CHARACTER_REFERENCE(2122, 'y' _ 'u' _ 'm' _ 'l', 4, 0x00ff, 1) -NAMED_CHARACTER_REFERENCE(2123, 'y' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00ff, 1) -NAMED_CHARACTER_REFERENCE(2124, 'z' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x017a, 1) -NAMED_CHARACTER_REFERENCE(2125, 'z' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x017e, 1) -NAMED_CHARACTER_REFERENCE(2126, 'z' _ 'c' _ 'y' _ ';', 4, 0x0437, 1) -NAMED_CHARACTER_REFERENCE(2127, 'z' _ 'd' _ 'o' _ 't' _ ';', 5, 0x017c, 1) -NAMED_CHARACTER_REFERENCE(2128, 'z' _ 'e' _ 'e' _ 't' _ 'r' _ 'f' _ ';', 7, 0x2128, 1) -NAMED_CHARACTER_REFERENCE(2129, 'z' _ 'e' _ 't' _ 'a' _ ';', 5, 0x03b6, 1) -NAMED_CHARACTER_REFERENCE(2130, 'z' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd37, 2) -NAMED_CHARACTER_REFERENCE(2131, 'z' _ 'h' _ 'c' _ 'y' _ ';', 5, 0x0436, 1) -NAMED_CHARACTER_REFERENCE(2132, 'z' _ 'i' _ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 8, 0x21dd, 1) -NAMED_CHARACTER_REFERENCE(2133, 'z' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd6b, 2) -NAMED_CHARACTER_REFERENCE(2134, 'z' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdccf, 2) -NAMED_CHARACTER_REFERENCE(2135, 'z' _ 'w' _ 'j' _ ';', 4, 0x200d, 1) -NAMED_CHARACTER_REFERENCE(2136, 'z' _ 'w' _ 'n' _ 'j' _ ';', 5, 0x200c, 1) +NAMED_CHARACTER_REFERENCE(1912, 's' _ 'u' _ 'p' _ 'h' _ 's' _ 'o' _ 'l' _ ';', 8, 0x27c9, 1) +NAMED_CHARACTER_REFERENCE(1913, 's' _ 'u' _ 'p' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 8, 0x2ad7, 1) +NAMED_CHARACTER_REFERENCE(1914, 's' _ 'u' _ 'p' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 8, 0x297b, 1) +NAMED_CHARACTER_REFERENCE(1915, 's' _ 'u' _ 'p' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 8, 0x2ac2, 1) +NAMED_CHARACTER_REFERENCE(1916, 's' _ 'u' _ 'p' _ 'n' _ 'E' _ ';', 6, 0x2acc, 1) +NAMED_CHARACTER_REFERENCE(1917, 's' _ 'u' _ 'p' _ 'n' _ 'e' _ ';', 6, 0x228b, 1) +NAMED_CHARACTER_REFERENCE(1918, 's' _ 'u' _ 'p' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 8, 0x2ac0, 1) +NAMED_CHARACTER_REFERENCE(1919, 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ ';', 7, 0x2283, 1) +NAMED_CHARACTER_REFERENCE(1920, 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0x2287, 1) +NAMED_CHARACTER_REFERENCE(1921, 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 10, 0x2ac6, 1) +NAMED_CHARACTER_REFERENCE(1922, 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 10, 0x228b, 1) +NAMED_CHARACTER_REFERENCE(1923, 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 11, 0x2acc, 1) +NAMED_CHARACTER_REFERENCE(1924, 's' _ 'u' _ 'p' _ 's' _ 'i' _ 'm' _ ';', 7, 0x2ac8, 1) +NAMED_CHARACTER_REFERENCE(1925, 's' _ 'u' _ 'p' _ 's' _ 'u' _ 'b' _ ';', 7, 0x2ad4, 1) +NAMED_CHARACTER_REFERENCE(1926, 's' _ 'u' _ 'p' _ 's' _ 'u' _ 'p' _ ';', 7, 0x2ad6, 1) +NAMED_CHARACTER_REFERENCE(1927, 's' _ 'w' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x21d9, 1) +NAMED_CHARACTER_REFERENCE(1928, 's' _ 'w' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, 0x2926, 1) +NAMED_CHARACTER_REFERENCE(1929, 's' _ 'w' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2199, 1) +NAMED_CHARACTER_REFERENCE(1930, 's' _ 'w' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2199, 1) +NAMED_CHARACTER_REFERENCE(1931, 's' _ 'w' _ 'n' _ 'w' _ 'a' _ 'r' _ ';', 7, 0x292a, 1) +NAMED_CHARACTER_REFERENCE(1932, 's' _ 'z' _ 'l' _ 'i' _ 'g', 5, 0x00df, 1) +NAMED_CHARACTER_REFERENCE(1933, 's' _ 'z' _ 'l' _ 'i' _ 'g' _ ';', 6, 0x00df, 1) +NAMED_CHARACTER_REFERENCE(1934, 't' _ 'a' _ 'r' _ 'g' _ 'e' _ 't' _ ';', 7, 0x2316, 1) +NAMED_CHARACTER_REFERENCE(1935, 't' _ 'a' _ 'u' _ ';', 4, 0x03c4, 1) +NAMED_CHARACTER_REFERENCE(1936, 't' _ 'b' _ 'r' _ 'k' _ ';', 5, 0x23b4, 1) +NAMED_CHARACTER_REFERENCE(1937, 't' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x0165, 1) +NAMED_CHARACTER_REFERENCE(1938, 't' _ 'c' _ 'e' _ 'd' _ 'i' _ 'l' _ ';', 7, 0x0163, 1) +NAMED_CHARACTER_REFERENCE(1939, 't' _ 'c' _ 'y' _ ';', 4, 0x0442, 1) +NAMED_CHARACTER_REFERENCE(1940, 't' _ 'd' _ 'o' _ 't' _ ';', 5, 0x20db, 1) +NAMED_CHARACTER_REFERENCE(1941, 't' _ 'e' _ 'l' _ 'r' _ 'e' _ 'c' _ ';', 7, 0x2315, 1) +NAMED_CHARACTER_REFERENCE(1942, 't' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd31, 2) +NAMED_CHARACTER_REFERENCE(1943, 't' _ 'h' _ 'e' _ 'r' _ 'e' _ '4' _ ';', 7, 0x2234, 1) +NAMED_CHARACTER_REFERENCE(1944, 't' _ 'h' _ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 10, 0x2234, 1) +NAMED_CHARACTER_REFERENCE(1945, 't' _ 'h' _ 'e' _ 't' _ 'a' _ ';', 6, 0x03b8, 1) +NAMED_CHARACTER_REFERENCE(1946, 't' _ 'h' _ 'e' _ 't' _ 'a' _ 's' _ 'y' _ 'm' _ ';', 9, 0x03d1, 1) +NAMED_CHARACTER_REFERENCE(1947, 't' _ 'h' _ 'e' _ 't' _ 'a' _ 'v' _ ';', 7, 0x03d1, 1) +NAMED_CHARACTER_REFERENCE(1948, 't' _ 'h' _ 'i' _ 'c' _ 'k' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 12, 0x2248, 1) +NAMED_CHARACTER_REFERENCE(1949, 't' _ 'h' _ 'i' _ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 9, 0x223c, 1) +NAMED_CHARACTER_REFERENCE(1950, 't' _ 'h' _ 'i' _ 'n' _ 's' _ 'p' _ ';', 7, 0x2009, 1) +NAMED_CHARACTER_REFERENCE(1951, 't' _ 'h' _ 'k' _ 'a' _ 'p' _ ';', 6, 0x2248, 1) +NAMED_CHARACTER_REFERENCE(1952, 't' _ 'h' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 7, 0x223c, 1) +NAMED_CHARACTER_REFERENCE(1953, 't' _ 'h' _ 'o' _ 'r' _ 'n', 5, 0x00fe, 1) +NAMED_CHARACTER_REFERENCE(1954, 't' _ 'h' _ 'o' _ 'r' _ 'n' _ ';', 6, 0x00fe, 1) +NAMED_CHARACTER_REFERENCE(1955, 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 6, 0x02dc, 1) +NAMED_CHARACTER_REFERENCE(1956, 't' _ 'i' _ 'm' _ 'e' _ 's', 5, 0x00d7, 1) +NAMED_CHARACTER_REFERENCE(1957, 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0x00d7, 1) +NAMED_CHARACTER_REFERENCE(1958, 't' _ 'i' _ 'm' _ 'e' _ 's' _ 'b' _ ';', 7, 0x22a0, 1) +NAMED_CHARACTER_REFERENCE(1959, 't' _ 'i' _ 'm' _ 'e' _ 's' _ 'b' _ 'a' _ 'r' _ ';', 9, 0x2a31, 1) +NAMED_CHARACTER_REFERENCE(1960, 't' _ 'i' _ 'm' _ 'e' _ 's' _ 'd' _ ';', 7, 0x2a30, 1) +NAMED_CHARACTER_REFERENCE(1961, 't' _ 'i' _ 'n' _ 't' _ ';', 5, 0x222d, 1) +NAMED_CHARACTER_REFERENCE(1962, 't' _ 'o' _ 'e' _ 'a' _ ';', 5, 0x2928, 1) +NAMED_CHARACTER_REFERENCE(1963, 't' _ 'o' _ 'p' _ ';', 4, 0x22a4, 1) +NAMED_CHARACTER_REFERENCE(1964, 't' _ 'o' _ 'p' _ 'b' _ 'o' _ 't' _ ';', 7, 0x2336, 1) +NAMED_CHARACTER_REFERENCE(1965, 't' _ 'o' _ 'p' _ 'c' _ 'i' _ 'r' _ ';', 7, 0x2af1, 1) +NAMED_CHARACTER_REFERENCE(1966, 't' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd65, 2) +NAMED_CHARACTER_REFERENCE(1967, 't' _ 'o' _ 'p' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 8, 0x2ada, 1) +NAMED_CHARACTER_REFERENCE(1968, 't' _ 'o' _ 's' _ 'a' _ ';', 5, 0x2929, 1) +NAMED_CHARACTER_REFERENCE(1969, 't' _ 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 7, 0x2034, 1) +NAMED_CHARACTER_REFERENCE(1970, 't' _ 'r' _ 'a' _ 'd' _ 'e' _ ';', 6, 0x2122, 1) +NAMED_CHARACTER_REFERENCE(1971, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 9, 0x25b5, 1) +NAMED_CHARACTER_REFERENCE(1972, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 13, 0x25bf, 1) +NAMED_CHARACTER_REFERENCE(1973, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 13, 0x25c3, 1) +NAMED_CHARACTER_REFERENCE(1974, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 15, 0x22b4, 1) +NAMED_CHARACTER_REFERENCE(1975, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'q' _ ';', 10, 0x225c, 1) +NAMED_CHARACTER_REFERENCE(1976, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 14, 0x25b9, 1) +NAMED_CHARACTER_REFERENCE(1977, 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 16, 0x22b5, 1) +NAMED_CHARACTER_REFERENCE(1978, 't' _ 'r' _ 'i' _ 'd' _ 'o' _ 't' _ ';', 7, 0x25ec, 1) +NAMED_CHARACTER_REFERENCE(1979, 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0x225c, 1) +NAMED_CHARACTER_REFERENCE(1980, 't' _ 'r' _ 'i' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 9, 0x2a3a, 1) +NAMED_CHARACTER_REFERENCE(1981, 't' _ 'r' _ 'i' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 8, 0x2a39, 1) +NAMED_CHARACTER_REFERENCE(1982, 't' _ 'r' _ 'i' _ 's' _ 'b' _ ';', 6, 0x29cd, 1) +NAMED_CHARACTER_REFERENCE(1983, 't' _ 'r' _ 'i' _ 't' _ 'i' _ 'm' _ 'e' _ ';', 8, 0x2a3b, 1) +NAMED_CHARACTER_REFERENCE(1984, 't' _ 'r' _ 'p' _ 'e' _ 'z' _ 'i' _ 'u' _ 'm' _ ';', 9, 0x23e2, 1) +NAMED_CHARACTER_REFERENCE(1985, 't' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcc9, 2) +NAMED_CHARACTER_REFERENCE(1986, 't' _ 's' _ 'c' _ 'y' _ ';', 5, 0x0446, 1) +NAMED_CHARACTER_REFERENCE(1987, 't' _ 's' _ 'h' _ 'c' _ 'y' _ ';', 6, 0x045b, 1) +NAMED_CHARACTER_REFERENCE(1988, 't' _ 's' _ 't' _ 'r' _ 'o' _ 'k' _ ';', 7, 0x0167, 1) +NAMED_CHARACTER_REFERENCE(1989, 't' _ 'w' _ 'i' _ 'x' _ 't' _ ';', 6, 0x226c, 1) +NAMED_CHARACTER_REFERENCE(1990, 't' _ 'w' _ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0x219e, 1) +NAMED_CHARACTER_REFERENCE(1991, 't' _ 'w' _ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0x21a0, 1) +NAMED_CHARACTER_REFERENCE(1992, 'u' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d1, 1) +NAMED_CHARACTER_REFERENCE(1993, 'u' _ 'H' _ 'a' _ 'r' _ ';', 5, 0x2963, 1) +NAMED_CHARACTER_REFERENCE(1994, 'u' _ 'a' _ 'c' _ 'u' _ 't' _ 'e', 6, 0x00fa, 1) +NAMED_CHARACTER_REFERENCE(1995, 'u' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x00fa, 1) +NAMED_CHARACTER_REFERENCE(1996, 'u' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2191, 1) +NAMED_CHARACTER_REFERENCE(1997, 'u' _ 'b' _ 'r' _ 'c' _ 'y' _ ';', 6, 0x045e, 1) +NAMED_CHARACTER_REFERENCE(1998, 'u' _ 'b' _ 'r' _ 'e' _ 'v' _ 'e' _ ';', 7, 0x016d, 1) +NAMED_CHARACTER_REFERENCE(1999, 'u' _ 'c' _ 'i' _ 'r' _ 'c', 5, 0x00fb, 1) +NAMED_CHARACTER_REFERENCE(2000, 'u' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x00fb, 1) +NAMED_CHARACTER_REFERENCE(2001, 'u' _ 'c' _ 'y' _ ';', 4, 0x0443, 1) +NAMED_CHARACTER_REFERENCE(2002, 'u' _ 'd' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21c5, 1) +NAMED_CHARACTER_REFERENCE(2003, 'u' _ 'd' _ 'b' _ 'l' _ 'a' _ 'c' _ ';', 7, 0x0171, 1) +NAMED_CHARACTER_REFERENCE(2004, 'u' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x296e, 1) +NAMED_CHARACTER_REFERENCE(2005, 'u' _ 'f' _ 'i' _ 's' _ 'h' _ 't' _ ';', 7, 0x297e, 1) +NAMED_CHARACTER_REFERENCE(2006, 'u' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd32, 2) +NAMED_CHARACTER_REFERENCE(2007, 'u' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e', 6, 0x00f9, 1) +NAMED_CHARACTER_REFERENCE(2008, 'u' _ 'g' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 7, 0x00f9, 1) +NAMED_CHARACTER_REFERENCE(2009, 'u' _ 'h' _ 'a' _ 'r' _ 'l' _ ';', 6, 0x21bf, 1) +NAMED_CHARACTER_REFERENCE(2010, 'u' _ 'h' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21be, 1) +NAMED_CHARACTER_REFERENCE(2011, 'u' _ 'h' _ 'b' _ 'l' _ 'k' _ ';', 6, 0x2580, 1) +NAMED_CHARACTER_REFERENCE(2012, 'u' _ 'l' _ 'c' _ 'o' _ 'r' _ 'n' _ ';', 7, 0x231c, 1) +NAMED_CHARACTER_REFERENCE(2013, 'u' _ 'l' _ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 9, 0x231c, 1) +NAMED_CHARACTER_REFERENCE(2014, 'u' _ 'l' _ 'c' _ 'r' _ 'o' _ 'p' _ ';', 7, 0x230f, 1) +NAMED_CHARACTER_REFERENCE(2015, 'u' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 6, 0x25f8, 1) +NAMED_CHARACTER_REFERENCE(2016, 'u' _ 'm' _ 'a' _ 'c' _ 'r' _ ';', 6, 0x016b, 1) +NAMED_CHARACTER_REFERENCE(2017, 'u' _ 'm' _ 'l', 3, 0x00a8, 1) +NAMED_CHARACTER_REFERENCE(2018, 'u' _ 'm' _ 'l' _ ';', 4, 0x00a8, 1) +NAMED_CHARACTER_REFERENCE(2019, 'u' _ 'o' _ 'g' _ 'o' _ 'n' _ ';', 6, 0x0173, 1) +NAMED_CHARACTER_REFERENCE(2020, 'u' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd66, 2) +NAMED_CHARACTER_REFERENCE(2021, 'u' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2191, 1) +NAMED_CHARACTER_REFERENCE(2022, 'u' _ 'p' _ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x2195, 1) +NAMED_CHARACTER_REFERENCE(2023, 'u' _ 'p' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x21bf, 1) +NAMED_CHARACTER_REFERENCE(2024, 'u' _ 'p' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x21be, 1) +NAMED_CHARACTER_REFERENCE(2025, 'u' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x228e, 1) +NAMED_CHARACTER_REFERENCE(2026, 'u' _ 'p' _ 's' _ 'i' _ ';', 5, 0x03c5, 1) +NAMED_CHARACTER_REFERENCE(2027, 'u' _ 'p' _ 's' _ 'i' _ 'h' _ ';', 6, 0x03d2, 1) +NAMED_CHARACTER_REFERENCE(2028, 'u' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 8, 0x03c5, 1) +NAMED_CHARACTER_REFERENCE(2029, 'u' _ 'p' _ 'u' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 11, 0x21c8, 1) +NAMED_CHARACTER_REFERENCE(2030, 'u' _ 'r' _ 'c' _ 'o' _ 'r' _ 'n' _ ';', 7, 0x231d, 1) +NAMED_CHARACTER_REFERENCE(2031, 'u' _ 'r' _ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 9, 0x231d, 1) +NAMED_CHARACTER_REFERENCE(2032, 'u' _ 'r' _ 'c' _ 'r' _ 'o' _ 'p' _ ';', 7, 0x230e, 1) +NAMED_CHARACTER_REFERENCE(2033, 'u' _ 'r' _ 'i' _ 'n' _ 'g' _ ';', 6, 0x016f, 1) +NAMED_CHARACTER_REFERENCE(2034, 'u' _ 'r' _ 't' _ 'r' _ 'i' _ ';', 6, 0x25f9, 1) +NAMED_CHARACTER_REFERENCE(2035, 'u' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcca, 2) +NAMED_CHARACTER_REFERENCE(2036, 'u' _ 't' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22f0, 1) +NAMED_CHARACTER_REFERENCE(2037, 'u' _ 't' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x0169, 1) +NAMED_CHARACTER_REFERENCE(2038, 'u' _ 't' _ 'r' _ 'i' _ ';', 5, 0x25b5, 1) +NAMED_CHARACTER_REFERENCE(2039, 'u' _ 't' _ 'r' _ 'i' _ 'f' _ ';', 6, 0x25b4, 1) +NAMED_CHARACTER_REFERENCE(2040, 'u' _ 'u' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21c8, 1) +NAMED_CHARACTER_REFERENCE(2041, 'u' _ 'u' _ 'm' _ 'l', 4, 0x00fc, 1) +NAMED_CHARACTER_REFERENCE(2042, 'u' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00fc, 1) +NAMED_CHARACTER_REFERENCE(2043, 'u' _ 'w' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 8, 0x29a7, 1) +NAMED_CHARACTER_REFERENCE(2044, 'v' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x21d5, 1) +NAMED_CHARACTER_REFERENCE(2045, 'v' _ 'B' _ 'a' _ 'r' _ ';', 5, 0x2ae8, 1) +NAMED_CHARACTER_REFERENCE(2046, 'v' _ 'B' _ 'a' _ 'r' _ 'v' _ ';', 6, 0x2ae9, 1) +NAMED_CHARACTER_REFERENCE(2047, 'v' _ 'D' _ 'a' _ 's' _ 'h' _ ';', 6, 0x22a8, 1) +NAMED_CHARACTER_REFERENCE(2048, 'v' _ 'a' _ 'n' _ 'g' _ 'r' _ 't' _ ';', 7, 0x299c, 1) +NAMED_CHARACTER_REFERENCE(2049, 'v' _ 'a' _ 'r' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 11, 0x03f5, 1) +NAMED_CHARACTER_REFERENCE(2050, 'v' _ 'a' _ 'r' _ 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ ';', 9, 0x03f0, 1) +NAMED_CHARACTER_REFERENCE(2051, 'v' _ 'a' _ 'r' _ 'n' _ 'o' _ 't' _ 'h' _ 'i' _ 'n' _ 'g' _ ';', 11, 0x2205, 1) +NAMED_CHARACTER_REFERENCE(2052, 'v' _ 'a' _ 'r' _ 'p' _ 'h' _ 'i' _ ';', 7, 0x03d5, 1) +NAMED_CHARACTER_REFERENCE(2053, 'v' _ 'a' _ 'r' _ 'p' _ 'i' _ ';', 6, 0x03d6, 1) +NAMED_CHARACTER_REFERENCE(2054, 'v' _ 'a' _ 'r' _ 'p' _ 'r' _ 'o' _ 'p' _ 't' _ 'o' _ ';', 10, 0x221d, 1) +NAMED_CHARACTER_REFERENCE(2055, 'v' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2195, 1) +NAMED_CHARACTER_REFERENCE(2056, 'v' _ 'a' _ 'r' _ 'r' _ 'h' _ 'o' _ ';', 7, 0x03f1, 1) +NAMED_CHARACTER_REFERENCE(2057, 'v' _ 'a' _ 'r' _ 's' _ 'i' _ 'g' _ 'm' _ 'a' _ ';', 9, 0x03c2, 1) +NAMED_CHARACTER_REFERENCE(2058, 'v' _ 'a' _ 'r' _ 't' _ 'h' _ 'e' _ 't' _ 'a' _ ';', 9, 0x03d1, 1) +NAMED_CHARACTER_REFERENCE(2059, 'v' _ 'a' _ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 16, 0x22b2, 1) +NAMED_CHARACTER_REFERENCE(2060, 'v' _ 'a' _ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 17, 0x22b3, 1) +NAMED_CHARACTER_REFERENCE(2061, 'v' _ 'c' _ 'y' _ ';', 4, 0x0432, 1) +NAMED_CHARACTER_REFERENCE(2062, 'v' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 6, 0x22a2, 1) +NAMED_CHARACTER_REFERENCE(2063, 'v' _ 'e' _ 'e' _ ';', 4, 0x2228, 1) +NAMED_CHARACTER_REFERENCE(2064, 'v' _ 'e' _ 'e' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x22bb, 1) +NAMED_CHARACTER_REFERENCE(2065, 'v' _ 'e' _ 'e' _ 'e' _ 'q' _ ';', 6, 0x225a, 1) +NAMED_CHARACTER_REFERENCE(2066, 'v' _ 'e' _ 'l' _ 'l' _ 'i' _ 'p' _ ';', 7, 0x22ee, 1) +NAMED_CHARACTER_REFERENCE(2067, 'v' _ 'e' _ 'r' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x007c, 1) +NAMED_CHARACTER_REFERENCE(2068, 'v' _ 'e' _ 'r' _ 't' _ ';', 5, 0x007c, 1) +NAMED_CHARACTER_REFERENCE(2069, 'v' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd33, 2) +NAMED_CHARACTER_REFERENCE(2070, 'v' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 6, 0x22b2, 1) +NAMED_CHARACTER_REFERENCE(2071, 'v' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd67, 2) +NAMED_CHARACTER_REFERENCE(2072, 'v' _ 'p' _ 'r' _ 'o' _ 'p' _ ';', 6, 0x221d, 1) +NAMED_CHARACTER_REFERENCE(2073, 'v' _ 'r' _ 't' _ 'r' _ 'i' _ ';', 6, 0x22b3, 1) +NAMED_CHARACTER_REFERENCE(2074, 'v' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdccb, 2) +NAMED_CHARACTER_REFERENCE(2075, 'v' _ 'z' _ 'i' _ 'g' _ 'z' _ 'a' _ 'g' _ ';', 8, 0x299a, 1) +NAMED_CHARACTER_REFERENCE(2076, 'w' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x0175, 1) +NAMED_CHARACTER_REFERENCE(2077, 'w' _ 'e' _ 'd' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x2a5f, 1) +NAMED_CHARACTER_REFERENCE(2078, 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 6, 0x2227, 1) +NAMED_CHARACTER_REFERENCE(2079, 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ 'q' _ ';', 7, 0x2259, 1) +NAMED_CHARACTER_REFERENCE(2080, 'w' _ 'e' _ 'i' _ 'e' _ 'r' _ 'p' _ ';', 7, 0x2118, 1) +NAMED_CHARACTER_REFERENCE(2081, 'w' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd34, 2) +NAMED_CHARACTER_REFERENCE(2082, 'w' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd68, 2) +NAMED_CHARACTER_REFERENCE(2083, 'w' _ 'p' _ ';', 3, 0x2118, 1) +NAMED_CHARACTER_REFERENCE(2084, 'w' _ 'r' _ ';', 3, 0x2240, 1) +NAMED_CHARACTER_REFERENCE(2085, 'w' _ 'r' _ 'e' _ 'a' _ 't' _ 'h' _ ';', 7, 0x2240, 1) +NAMED_CHARACTER_REFERENCE(2086, 'w' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdccc, 2) +NAMED_CHARACTER_REFERENCE(2087, 'x' _ 'c' _ 'a' _ 'p' _ ';', 5, 0x22c2, 1) +NAMED_CHARACTER_REFERENCE(2088, 'x' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x25ef, 1) +NAMED_CHARACTER_REFERENCE(2089, 'x' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x22c3, 1) +NAMED_CHARACTER_REFERENCE(2090, 'x' _ 'd' _ 't' _ 'r' _ 'i' _ ';', 6, 0x25bd, 1) +NAMED_CHARACTER_REFERENCE(2091, 'x' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd35, 2) +NAMED_CHARACTER_REFERENCE(2092, 'x' _ 'h' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x27fa, 1) +NAMED_CHARACTER_REFERENCE(2093, 'x' _ 'h' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x27f7, 1) +NAMED_CHARACTER_REFERENCE(2094, 'x' _ 'i' _ ';', 3, 0x03be, 1) +NAMED_CHARACTER_REFERENCE(2095, 'x' _ 'l' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x27f8, 1) +NAMED_CHARACTER_REFERENCE(2096, 'x' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x27f5, 1) +NAMED_CHARACTER_REFERENCE(2097, 'x' _ 'm' _ 'a' _ 'p' _ ';', 5, 0x27fc, 1) +NAMED_CHARACTER_REFERENCE(2098, 'x' _ 'n' _ 'i' _ 's' _ ';', 5, 0x22fb, 1) +NAMED_CHARACTER_REFERENCE(2099, 'x' _ 'o' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2a00, 1) +NAMED_CHARACTER_REFERENCE(2100, 'x' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd69, 2) +NAMED_CHARACTER_REFERENCE(2101, 'x' _ 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2a01, 1) +NAMED_CHARACTER_REFERENCE(2102, 'x' _ 'o' _ 't' _ 'i' _ 'm' _ 'e' _ ';', 7, 0x2a02, 1) +NAMED_CHARACTER_REFERENCE(2103, 'x' _ 'r' _ 'A' _ 'r' _ 'r' _ ';', 6, 0x27f9, 1) +NAMED_CHARACTER_REFERENCE(2104, 'x' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x27f6, 1) +NAMED_CHARACTER_REFERENCE(2105, 'x' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdccd, 2) +NAMED_CHARACTER_REFERENCE(2106, 'x' _ 's' _ 'q' _ 'c' _ 'u' _ 'p' _ ';', 7, 0x2a06, 1) +NAMED_CHARACTER_REFERENCE(2107, 'x' _ 'u' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2a04, 1) +NAMED_CHARACTER_REFERENCE(2108, 'x' _ 'u' _ 't' _ 'r' _ 'i' _ ';', 6, 0x25b3, 1) +NAMED_CHARACTER_REFERENCE(2109, 'x' _ 'v' _ 'e' _ 'e' _ ';', 5, 0x22c1, 1) +NAMED_CHARACTER_REFERENCE(2110, 'x' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, 0x22c0, 1) +NAMED_CHARACTER_REFERENCE(2111, 'y' _ 'a' _ 'c' _ 'u' _ 't' _ 'e', 6, 0x00fd, 1) +NAMED_CHARACTER_REFERENCE(2112, 'y' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x00fd, 1) +NAMED_CHARACTER_REFERENCE(2113, 'y' _ 'a' _ 'c' _ 'y' _ ';', 5, 0x044f, 1) +NAMED_CHARACTER_REFERENCE(2114, 'y' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x0177, 1) +NAMED_CHARACTER_REFERENCE(2115, 'y' _ 'c' _ 'y' _ ';', 4, 0x044b, 1) +NAMED_CHARACTER_REFERENCE(2116, 'y' _ 'e' _ 'n', 3, 0x00a5, 1) +NAMED_CHARACTER_REFERENCE(2117, 'y' _ 'e' _ 'n' _ ';', 4, 0x00a5, 1) +NAMED_CHARACTER_REFERENCE(2118, 'y' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd36, 2) +NAMED_CHARACTER_REFERENCE(2119, 'y' _ 'i' _ 'c' _ 'y' _ ';', 5, 0x0457, 1) +NAMED_CHARACTER_REFERENCE(2120, 'y' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd6a, 2) +NAMED_CHARACTER_REFERENCE(2121, 'y' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdcce, 2) +NAMED_CHARACTER_REFERENCE(2122, 'y' _ 'u' _ 'c' _ 'y' _ ';', 5, 0x044e, 1) +NAMED_CHARACTER_REFERENCE(2123, 'y' _ 'u' _ 'm' _ 'l', 4, 0x00ff, 1) +NAMED_CHARACTER_REFERENCE(2124, 'y' _ 'u' _ 'm' _ 'l' _ ';', 5, 0x00ff, 1) +NAMED_CHARACTER_REFERENCE(2125, 'z' _ 'a' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 7, 0x017a, 1) +NAMED_CHARACTER_REFERENCE(2126, 'z' _ 'c' _ 'a' _ 'r' _ 'o' _ 'n' _ ';', 7, 0x017e, 1) +NAMED_CHARACTER_REFERENCE(2127, 'z' _ 'c' _ 'y' _ ';', 4, 0x0437, 1) +NAMED_CHARACTER_REFERENCE(2128, 'z' _ 'd' _ 'o' _ 't' _ ';', 5, 0x017c, 1) +NAMED_CHARACTER_REFERENCE(2129, 'z' _ 'e' _ 'e' _ 't' _ 'r' _ 'f' _ ';', 7, 0x2128, 1) +NAMED_CHARACTER_REFERENCE(2130, 'z' _ 'e' _ 't' _ 'a' _ ';', 5, 0x03b6, 1) +NAMED_CHARACTER_REFERENCE(2131, 'z' _ 'f' _ 'r' _ ';', 4, 0xd835 _ 0xdd37, 2) +NAMED_CHARACTER_REFERENCE(2132, 'z' _ 'h' _ 'c' _ 'y' _ ';', 5, 0x0436, 1) +NAMED_CHARACTER_REFERENCE(2133, 'z' _ 'i' _ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 8, 0x21dd, 1) +NAMED_CHARACTER_REFERENCE(2134, 'z' _ 'o' _ 'p' _ 'f' _ ';', 5, 0xd835 _ 0xdd6b, 2) +NAMED_CHARACTER_REFERENCE(2135, 'z' _ 's' _ 'c' _ 'r' _ ';', 5, 0xd835 _ 0xdccf, 2) +NAMED_CHARACTER_REFERENCE(2136, 'z' _ 'w' _ 'j' _ ';', 4, 0x200d, 1) +NAMED_CHARACTER_REFERENCE(2137, 'z' _ 'w' _ 'n' _ 'j' _ ';', 5, 0x200c, 1) #undef _ diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp index 29ecfde859bf..c59374b2a20b 100644 --- a/parser/html/nsHtml5Tokenizer.cpp +++ b/parser/html/nsHtml5Tokenizer.cpp @@ -443,8 +443,9 @@ nsHtml5Tokenizer::tokenizeBuffer(nsHtml5UTF16Buffer* buffer) switch(state) { case NS_HTML5TOKENIZER_DATA: case NS_HTML5TOKENIZER_RCDATA: - case NS_HTML5TOKENIZER_CDATA: + case NS_HTML5TOKENIZER_SCRIPT_DATA: case NS_HTML5TOKENIZER_PLAINTEXT: + case NS_HTML5TOKENIZER_RAWTEXT: case NS_HTML5TOKENIZER_CDATA_SECTION: case NS_HTML5TOKENIZER_ESCAPE: case NS_HTML5TOKENIZER_ESCAPE_EXCLAMATION: @@ -538,7 +539,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* goto stateloop; } case '/': { - state = NS_HTML5TOKENIZER_CLOSE_TAG_OPEN_PCDATA; + state = NS_HTML5TOKENIZER_CLOSE_TAG_OPEN; goto stateloop; } case '\?': { @@ -779,6 +780,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } case '<': case '=': + case '`': default: { clearLongStrBufAndAppendCurrentC(c); state = NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_UNQUOTED; @@ -943,6 +945,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* case '\"': case '\'': case '=': + case '`': default: { appendLongStrBuf(c); @@ -1636,14 +1639,14 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* index++; continue; } else { - state = NS_HTML5TOKENIZER_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER; + state = NS_HTML5TOKENIZER_AFTER_DOCTYPE_PUBLIC_KEYWORD; reconsume = PR_TRUE; goto doctypeublicloop_end; } } doctypeublicloop_end: ; } - case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: { + case NS_HTML5TOKENIZER_AFTER_DOCTYPE_PUBLIC_KEYWORD: { for (; ; ) { if (reconsume) { reconsume = PR_FALSE; @@ -1653,6 +1656,55 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } c = checkChar(buf, pos); } + switch(c) { + case '\r': { + silentCarriageReturn(); + state = NS_HTML5TOKENIZER_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER; + goto stateloop_end; + } + case '\n': { + silentLineFeed(); + } + case ' ': + case '\t': + case '\f': { + state = NS_HTML5TOKENIZER_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER; + goto afterdoctypepublickeywordloop_end; + } + case '\"': { + + clearLongStrBufForNextState(); + state = NS_HTML5TOKENIZER_DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED; + goto stateloop; + } + case '\'': { + + clearLongStrBufForNextState(); + state = NS_HTML5TOKENIZER_DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED; + goto stateloop; + } + case '>': { + + forceQuirks = PR_TRUE; + emitDoctypeToken(pos); + state = NS_HTML5TOKENIZER_DATA; + goto stateloop; + } + default: { + bogusDoctype(); + state = NS_HTML5TOKENIZER_BOGUS_DOCTYPE; + goto stateloop; + } + } + } + afterdoctypepublickeywordloop_end: ; + } + case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: { + for (; ; ) { + if (++pos == endPos) { + goto stateloop_end; + } + c = checkChar(buf, pos); switch(c) { case '\r': { silentCarriageReturn(); @@ -1740,6 +1792,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* switch(c) { case '\r': { silentCarriageReturn(); + state = NS_HTML5TOKENIZER_BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS; goto stateloop_end; } case '\n': { @@ -1748,23 +1801,26 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* case ' ': case '\t': case '\f': { - continue; - } - case '\"': { - clearLongStrBufForNextState(); - state = NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED; + state = NS_HTML5TOKENIZER_BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS; goto afterdoctypepublicidentifierloop_end; } - case '\'': { - clearLongStrBufForNextState(); - state = NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED; - goto stateloop; - } case '>': { emitDoctypeToken(pos); state = NS_HTML5TOKENIZER_DATA; goto stateloop; } + case '\"': { + + clearLongStrBufForNextState(); + state = NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED; + goto stateloop; + } + case '\'': { + + clearLongStrBufForNextState(); + state = NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED; + goto stateloop; + } default: { bogusDoctype(); state = NS_HTML5TOKENIZER_BOGUS_DOCTYPE; @@ -1774,6 +1830,49 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } afterdoctypepublicidentifierloop_end: ; } + case NS_HTML5TOKENIZER_BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: { + for (; ; ) { + if (++pos == endPos) { + goto stateloop_end; + } + c = checkChar(buf, pos); + switch(c) { + case '\r': { + silentCarriageReturn(); + goto stateloop_end; + } + case '\n': { + silentLineFeed(); + } + case ' ': + case '\t': + case '\f': { + continue; + } + case '>': { + emitDoctypeToken(pos); + state = NS_HTML5TOKENIZER_DATA; + goto stateloop; + } + case '\"': { + clearLongStrBufForNextState(); + state = NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED; + goto betweendoctypepublicandsystemidentifiersloop_end; + } + case '\'': { + clearLongStrBufForNextState(); + state = NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED; + goto stateloop; + } + default: { + bogusDoctype(); + state = NS_HTML5TOKENIZER_BOGUS_DOCTYPE; + goto stateloop; + } + } + } + betweendoctypepublicandsystemidentifiersloop_end: ; + } case NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: { for (; ; ) { if (++pos == endPos) { @@ -1895,14 +1994,14 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* index++; goto stateloop; } else { - state = NS_HTML5TOKENIZER_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER; + state = NS_HTML5TOKENIZER_AFTER_DOCTYPE_SYSTEM_KEYWORD; reconsume = PR_TRUE; goto doctypeystemloop_end; } } doctypeystemloop_end: ; } - case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: { + case NS_HTML5TOKENIZER_AFTER_DOCTYPE_SYSTEM_KEYWORD: { for (; ; ) { if (reconsume) { reconsume = PR_FALSE; @@ -1912,6 +2011,55 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } c = checkChar(buf, pos); } + switch(c) { + case '\r': { + silentCarriageReturn(); + state = NS_HTML5TOKENIZER_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER; + goto stateloop_end; + } + case '\n': { + silentLineFeed(); + } + case ' ': + case '\t': + case '\f': { + state = NS_HTML5TOKENIZER_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER; + goto afterdoctypesystemkeywordloop_end; + } + case '\"': { + + clearLongStrBufForNextState(); + state = NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED; + goto stateloop; + } + case '\'': { + + clearLongStrBufForNextState(); + state = NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED; + goto stateloop; + } + case '>': { + + forceQuirks = PR_TRUE; + emitDoctypeToken(pos); + state = NS_HTML5TOKENIZER_DATA; + goto stateloop; + } + default: { + bogusDoctype(); + state = NS_HTML5TOKENIZER_BOGUS_DOCTYPE; + goto stateloop; + } + } + } + afterdoctypesystemkeywordloop_end: ; + } + case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: { + for (; ; ) { + if (++pos == endPos) { + goto stateloop_end; + } + c = checkChar(buf, pos); switch(c) { case '\r': { silentCarriageReturn(); @@ -2500,7 +2648,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } } - case NS_HTML5TOKENIZER_CDATA: { + case NS_HTML5TOKENIZER_SCRIPT_DATA: { for (; ; ) { if (reconsume) { reconsume = PR_FALSE; @@ -2514,8 +2662,8 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* case '<': { flushChars(buf, pos); returnState = state; - state = NS_HTML5TOKENIZER_TAG_OPEN_NON_PCDATA; - goto cdataloop_end; + state = NS_HTML5TOKENIZER_SCRIPT_DATA_LESS_THAN_SIGN_STATE; + goto scriptdataloop_end; } case '\0': { emitReplacementCharacter(buf, pos); @@ -2533,39 +2681,37 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } } } - cdataloop_end: ; + scriptdataloop_end: ; } - case NS_HTML5TOKENIZER_TAG_OPEN_NON_PCDATA: { + case NS_HTML5TOKENIZER_SCRIPT_DATA_LESS_THAN_SIGN_STATE: { for (; ; ) { if (++pos == endPos) { goto stateloop_end; } c = checkChar(buf, pos); switch(c) { + case '/': { + index = 0; + clearStrBufForNextState(); + state = NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME; + goto stateloop; + } case '!': { tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); cstart = pos; state = NS_HTML5TOKENIZER_ESCAPE_EXCLAMATION; - goto tagopennonpcdataloop_end; - } - case '/': { - if (!!contentModelElement) { - index = 0; - clearStrBufForNextState(); - state = NS_HTML5TOKENIZER_CLOSE_TAG_OPEN_NOT_PCDATA; - goto stateloop; - } + goto scriptdatalessthansignloop_end; } default: { tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); cstart = pos; - state = returnState; + state = NS_HTML5TOKENIZER_SCRIPT_DATA; reconsume = PR_TRUE; goto stateloop; } } } - tagopennonpcdataloop_end: ; + scriptdatalessthansignloop_end: ; } case NS_HTML5TOKENIZER_ESCAPE_EXCLAMATION: { for (; ; ) { @@ -2703,74 +2849,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } } - case NS_HTML5TOKENIZER_CLOSE_TAG_OPEN_NOT_PCDATA: { - for (; ; ) { - if (++pos == endPos) { - goto stateloop_end; - } - c = checkChar(buf, pos); - if (index < contentModelElementNameAsArray.length) { - PRUnichar e = contentModelElementNameAsArray[index]; - PRUnichar folded = c; - if (c >= 'A' && c <= 'Z') { - folded += 0x20; - } - if (folded != e) { - tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); - emitStrBuf(); - cstart = pos; - state = returnState; - reconsume = PR_TRUE; - goto stateloop; - } - appendStrBuf(c); - index++; - continue; - } else { - endTag = PR_TRUE; - tagName = contentModelElement; - switch(c) { - case '\r': { - silentCarriageReturn(); - state = NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME; - goto stateloop_end; - } - case '\n': { - silentLineFeed(); - } - case ' ': - case '\t': - case '\f': { - state = NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME; - goto stateloop; - } - case '>': { - state = emitCurrentTagToken(PR_FALSE, pos); - if (shouldSuspend) { - goto stateloop_end; - } - goto stateloop; - } - case '/': { - state = NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG; - goto stateloop; - } - default: { - tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); - emitStrBuf(); - if (c == '\0') { - emitReplacementCharacter(buf, pos); - } else { - cstart = pos; - } - state = returnState; - goto stateloop; - } - } - } - } - } - case NS_HTML5TOKENIZER_CLOSE_TAG_OPEN_PCDATA: { + case NS_HTML5TOKENIZER_CLOSE_TAG_OPEN: { if (++pos == endPos) { goto stateloop_end; } @@ -2839,7 +2918,7 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* case '<': { flushChars(buf, pos); returnState = state; - state = NS_HTML5TOKENIZER_TAG_OPEN_NON_PCDATA; + state = NS_HTML5TOKENIZER_RAWTEXT_RCDATA_LESS_THAN_SIGN_STATE; goto stateloop; } case '\0': { @@ -2860,6 +2939,132 @@ nsHtml5Tokenizer::stateLoop(PRInt32 state, PRUnichar c, PRInt32 pos, PRUnichar* } } + case NS_HTML5TOKENIZER_RAWTEXT: { + for (; ; ) { + if (reconsume) { + reconsume = PR_FALSE; + } else { + if (++pos == endPos) { + goto stateloop_end; + } + c = checkChar(buf, pos); + } + switch(c) { + case '<': { + flushChars(buf, pos); + returnState = state; + state = NS_HTML5TOKENIZER_RAWTEXT_RCDATA_LESS_THAN_SIGN_STATE; + goto rawtextloop_end; + } + case '\0': { + emitReplacementCharacter(buf, pos); + continue; + } + case '\r': { + emitCarriageReturn(buf, pos); + goto stateloop_end; + } + case '\n': { + silentLineFeed(); + } + default: { + continue; + } + } + } + rawtextloop_end: ; + } + case NS_HTML5TOKENIZER_RAWTEXT_RCDATA_LESS_THAN_SIGN_STATE: { + for (; ; ) { + if (++pos == endPos) { + goto stateloop_end; + } + c = checkChar(buf, pos); + switch(c) { + case '/': { + index = 0; + clearStrBufForNextState(); + state = NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME; + goto rawtextrcdatalessthansignloop_end; + } + default: { + tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); + cstart = pos; + state = returnState; + reconsume = PR_TRUE; + goto stateloop; + } + } + } + rawtextrcdatalessthansignloop_end: ; + } + case NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME: { + for (; ; ) { + if (++pos == endPos) { + goto stateloop_end; + } + c = checkChar(buf, pos); + if (index < contentModelElementNameAsArray.length) { + PRUnichar e = contentModelElementNameAsArray[index]; + PRUnichar folded = c; + if (c >= 'A' && c <= 'Z') { + folded += 0x20; + } + if (folded != e) { + tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); + emitStrBuf(); + cstart = pos; + state = returnState; + reconsume = PR_TRUE; + goto stateloop; + } + appendStrBuf(c); + index++; + continue; + } else { + endTag = PR_TRUE; + tagName = contentModelElement; + switch(c) { + case '\r': { + silentCarriageReturn(); + state = NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME; + goto stateloop_end; + } + case '\n': { + silentLineFeed(); + } + case ' ': + case '\t': + case '\f': { + state = NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME; + goto stateloop; + } + case '/': { + state = NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG; + goto stateloop; + } + case '>': { + state = emitCurrentTagToken(PR_FALSE, pos); + if (shouldSuspend) { + goto stateloop_end; + } + goto stateloop; + } + default: { + tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); + emitStrBuf(); + if (c == '\0') { + emitReplacementCharacter(buf, pos); + } else { + cstart = pos; + } + state = returnState; + goto stateloop; + } + } + } + } + } } } stateloop_end: ; @@ -2943,17 +3148,11 @@ nsHtml5Tokenizer::handleNcrValue(PRInt32 returnState) } else if (value == 0x0D) { emitOrAppendOne(nsHtml5Tokenizer::LF, returnState); - } else if ((value >= 0x0000 && value <= 0x0008) || (value == 0x000B) || (value >= 0x000E && value <= 0x001F) || value == 0x007F) { + } else if (value == 0x0) { emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState); } else if ((value & 0xF800) == 0xD800) { - emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState); - } else if ((value & 0xFFFE) == 0xFFFE) { - - emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState); - } else if (value >= 0xFDD0 && value <= 0xFDEF) { - emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState); } else if (value <= 0xFFFF) { PRUnichar ch = (PRUnichar) value; @@ -2976,7 +3175,7 @@ nsHtml5Tokenizer::eof() PRInt32 returnState = returnStateSave; eofloop: for (; ; ) { switch(state) { - case NS_HTML5TOKENIZER_TAG_OPEN_NON_PCDATA: { + case NS_HTML5TOKENIZER_SCRIPT_DATA_LESS_THAN_SIGN_STATE: { tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); goto eofloop_end; } @@ -2985,7 +3184,7 @@ nsHtml5Tokenizer::eof() tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1); goto eofloop_end; } - case NS_HTML5TOKENIZER_CLOSE_TAG_OPEN_NOT_PCDATA: { + case NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME: { if (index < contentModelElementNameAsArray.length) { goto eofloop_end; } else { @@ -2993,7 +3192,7 @@ nsHtml5Tokenizer::eof() goto eofloop_end; } } - case NS_HTML5TOKENIZER_CLOSE_TAG_OPEN_PCDATA: { + case NS_HTML5TOKENIZER_CLOSE_TAG_OPEN: { tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2); goto eofloop_end; @@ -3104,6 +3303,8 @@ nsHtml5Tokenizer::eof() case NS_HTML5TOKENIZER_DOCTYPE_UBLIC: case NS_HTML5TOKENIZER_DOCTYPE_YSTEM: case NS_HTML5TOKENIZER_AFTER_DOCTYPE_NAME: + case NS_HTML5TOKENIZER_AFTER_DOCTYPE_PUBLIC_KEYWORD: + case NS_HTML5TOKENIZER_AFTER_DOCTYPE_SYSTEM_KEYWORD: case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: { forceQuirks = PR_TRUE; @@ -3119,7 +3320,8 @@ nsHtml5Tokenizer::eof() goto eofloop_end; } case NS_HTML5TOKENIZER_AFTER_DOCTYPE_PUBLIC_IDENTIFIER: - case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: { + case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: + case NS_HTML5TOKENIZER_BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: { forceQuirks = PR_TRUE; emitDoctypeToken(0); diff --git a/parser/html/nsHtml5Tokenizer.h b/parser/html/nsHtml5Tokenizer.h index d046a1908a2e..6d6b1b9b079a 100644 --- a/parser/html/nsHtml5Tokenizer.h +++ b/parser/html/nsHtml5Tokenizer.h @@ -295,10 +295,10 @@ jArray nsHtml5Tokenizer::NOFRAMES_ARR = 0; #define NS_HTML5TOKENIZER_DATA 0 #define NS_HTML5TOKENIZER_RCDATA 1 -#define NS_HTML5TOKENIZER_CDATA 2 +#define NS_HTML5TOKENIZER_SCRIPT_DATA 2 #define NS_HTML5TOKENIZER_PLAINTEXT 3 #define NS_HTML5TOKENIZER_TAG_OPEN 4 -#define NS_HTML5TOKENIZER_CLOSE_TAG_OPEN_PCDATA 5 +#define NS_HTML5TOKENIZER_CLOSE_TAG_OPEN 5 #define NS_HTML5TOKENIZER_TAG_NAME 6 #define NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME 7 #define NS_HTML5TOKENIZER_ATTRIBUTE_NAME 8 @@ -330,7 +330,7 @@ jArray nsHtml5Tokenizer::NOFRAMES_ARR = 0; #define NS_HTML5TOKENIZER_COMMENT_END 34 #define NS_HTML5TOKENIZER_COMMENT_END_SPACE 35 #define NS_HTML5TOKENIZER_COMMENT_END_BANG 36 -#define NS_HTML5TOKENIZER_CLOSE_TAG_OPEN_NOT_PCDATA 37 +#define NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME 37 #define NS_HTML5TOKENIZER_MARKUP_DECLARATION_HYPHEN 38 #define NS_HTML5TOKENIZER_MARKUP_DECLARATION_OCTYPE 39 #define NS_HTML5TOKENIZER_DOCTYPE_UBLIC 40 @@ -346,13 +346,18 @@ jArray nsHtml5Tokenizer::NOFRAMES_ARR = 0; #define NS_HTML5TOKENIZER_CDATA_SECTION 50 #define NS_HTML5TOKENIZER_CDATA_RSQB 51 #define NS_HTML5TOKENIZER_CDATA_RSQB_RSQB 52 -#define NS_HTML5TOKENIZER_TAG_OPEN_NON_PCDATA 53 +#define NS_HTML5TOKENIZER_SCRIPT_DATA_LESS_THAN_SIGN_STATE 53 #define NS_HTML5TOKENIZER_ESCAPE_EXCLAMATION 54 #define NS_HTML5TOKENIZER_ESCAPE_EXCLAMATION_HYPHEN 55 #define NS_HTML5TOKENIZER_ESCAPE 56 #define NS_HTML5TOKENIZER_ESCAPE_HYPHEN 57 #define NS_HTML5TOKENIZER_ESCAPE_HYPHEN_HYPHEN 58 #define NS_HTML5TOKENIZER_BOGUS_COMMENT_HYPHEN 59 +#define NS_HTML5TOKENIZER_RAWTEXT 60 +#define NS_HTML5TOKENIZER_RAWTEXT_RCDATA_LESS_THAN_SIGN_STATE 61 +#define NS_HTML5TOKENIZER_AFTER_DOCTYPE_PUBLIC_KEYWORD 62 +#define NS_HTML5TOKENIZER_BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS 63 +#define NS_HTML5TOKENIZER_AFTER_DOCTYPE_SYSTEM_KEYWORD 64 #define NS_HTML5TOKENIZER_LEAD_OFFSET (0xD800 - (0x10000 >> 10)) #define NS_HTML5TOKENIZER_BUFFER_GROW_BY 1024 diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp index fb941bb674b1..0d89aaba7ee4 100644 --- a/parser/html/nsHtml5TreeBuilder.cpp +++ b/parser/html/nsHtml5TreeBuilder.cpp @@ -97,10 +97,12 @@ nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) resetTheInsertionMode(); if (nsHtml5Atoms::title == contextName || nsHtml5Atoms::textarea == contextName) { tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RCDATA, contextName); - } else if (nsHtml5Atoms::style == contextName || nsHtml5Atoms::script == contextName || nsHtml5Atoms::xmp == contextName || nsHtml5Atoms::iframe == contextName || nsHtml5Atoms::noembed == contextName || nsHtml5Atoms::noframes == contextName || (scriptingEnabled && nsHtml5Atoms::noscript == contextName)) { - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, contextName); + } else if (nsHtml5Atoms::style == contextName || nsHtml5Atoms::xmp == contextName || nsHtml5Atoms::iframe == contextName || nsHtml5Atoms::noembed == contextName || nsHtml5Atoms::noframes == contextName || (scriptingEnabled && nsHtml5Atoms::noscript == contextName)) { + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RAWTEXT, contextName); } else if (nsHtml5Atoms::plaintext == contextName) { tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_PLAINTEXT, contextName); + } else if (nsHtml5Atoms::script == contextName) { + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_SCRIPT_DATA, contextName); } else { tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_DATA, contextName); } @@ -765,12 +767,19 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu resetTheInsertionMode(); goto starttagloop; } - case NS_HTML5TREE_BUILDER_SCRIPT: + case NS_HTML5TREE_BUILDER_SCRIPT: { + appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); + originalMode = mode; + mode = NS_HTML5TREE_BUILDER_TEXT; + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_SCRIPT_DATA, elementName); + attributes = nsnull; + goto starttagloop_end; + } case NS_HTML5TREE_BUILDER_STYLE: { appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RAWTEXT, elementName); attributes = nsnull; goto starttagloop_end; } @@ -1162,7 +1171,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RAWTEXT, elementName); attributes = nsnull; goto starttagloop_end; } @@ -1181,7 +1190,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RAWTEXT, elementName); attributes = nsnull; goto starttagloop_end; } @@ -1338,7 +1347,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RAWTEXT, elementName); } else { appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); mode = NS_HTML5TREE_BUILDER_IN_HEAD_NOSCRIPT; @@ -1346,13 +1355,20 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu attributes = nsnull; goto starttagloop_end; } - case NS_HTML5TREE_BUILDER_SCRIPT: + case NS_HTML5TREE_BUILDER_SCRIPT: { + appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + originalMode = mode; + mode = NS_HTML5TREE_BUILDER_TEXT; + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_SCRIPT_DATA, elementName); + attributes = nsnull; + goto starttagloop_end; + } case NS_HTML5TREE_BUILDER_STYLE: case NS_HTML5TREE_BUILDER_NOFRAMES: { appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RAWTEXT, elementName); attributes = nsnull; goto starttagloop_end; } @@ -1395,7 +1411,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RAWTEXT, elementName); attributes = nsnull; goto starttagloop_end; } @@ -1525,7 +1541,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_SCRIPT_DATA, elementName); attributes = nsnull; goto starttagloop_end; } @@ -1579,7 +1595,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RAWTEXT, elementName); attributes = nsnull; goto starttagloop_end; } @@ -1692,7 +1708,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_SCRIPT_DATA, elementName); attributes = nsnull; goto starttagloop_end; } @@ -1703,7 +1719,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RAWTEXT, elementName); attributes = nsnull; goto starttagloop_end; } @@ -1750,7 +1766,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); originalMode = mode; mode = NS_HTML5TREE_BUILDER_TEXT; - tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_SCRIPT_DATA, elementName); attributes = nsnull; goto starttagloop_end; } From 5d28b83605aa705a883ada1302964e6f8691dd5e Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Mon, 30 Nov 2009 17:34:51 +0200 Subject: [PATCH 141/179] Bug 503632 - Script containing + + Test for Bug 527896 + + + + + +Mozilla Bug 527896 +

+ +
+
+
+ + diff --git a/content/html/content/src/nsHTMLScriptElement.cpp b/content/html/content/src/nsHTMLScriptElement.cpp index d4d381ce6f16..4436c5e7ce08 100644 --- a/content/html/content/src/nsHTMLScriptElement.cpp +++ b/content/html/content/src/nsHTMLScriptElement.cpp @@ -329,11 +329,9 @@ public: // nsIScriptElement virtual void GetScriptType(nsAString& type); - virtual already_AddRefed GetScriptURI(); virtual void GetScriptText(nsAString& text); virtual void GetScriptCharset(nsAString& charset); - virtual PRBool GetScriptDeferred(); - virtual PRBool GetScriptAsync(); + virtual void FreezeUriAsyncDefer(); // nsIContent virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, @@ -477,7 +475,14 @@ nsresult nsHTMLScriptElement::DoneAddingChildren(PRBool aHaveNotified) { mDoneAddingChildren = PR_TRUE; - return MaybeProcessScript(); + nsresult rv = MaybeProcessScript(); + if (!mIsEvaluated) { + // Need to thaw the script uri here to allow another script to cause + // execution later. + mFrozen = PR_FALSE; + mUri = nsnull; + } + return rv; } PRBool @@ -495,20 +500,6 @@ nsHTMLScriptElement::GetScriptType(nsAString& type) GetType(type); } -// variation of this code in nsSVGScriptElement - check if changes -// need to be transfered when modifying - -already_AddRefed -nsHTMLScriptElement::GetScriptURI() -{ - nsIURI *uri = nsnull; - nsAutoString src; - GetSrc(src); - if (!src.IsEmpty()) - NS_NewURI(&uri, src); - return uri; -} - void nsHTMLScriptElement::GetScriptText(nsAString& text) { @@ -521,31 +512,35 @@ nsHTMLScriptElement::GetScriptCharset(nsAString& charset) GetCharset(charset); } -PRBool -nsHTMLScriptElement::GetScriptDeferred() +void +nsHTMLScriptElement::FreezeUriAsyncDefer() { - PRBool defer, async; - GetAsync(&async); - GetDefer(&defer); - nsCOMPtr uri = GetScriptURI(); + if (mFrozen) { + return; + } + + // variation of this code in nsSVGScriptElement - check if changes + // need to be transfered when modifying + if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) { + nsAutoString src; + GetSrc(src); + NS_NewURI(getter_AddRefs(mUri), src); - return !async && defer && uri; -} + PRBool defer, async; + GetAsync(&async); + GetDefer(&defer); -PRBool -nsHTMLScriptElement::GetScriptAsync() -{ - PRBool async; - GetAsync(&async); - nsCOMPtr uri = GetScriptURI(); - - return async && uri; + mDefer = !async && defer; + mAsync = async; + } + + mFrozen = PR_TRUE; } PRBool nsHTMLScriptElement::HasScriptContent() { - return HasAttr(kNameSpaceID_None, nsGkAtoms::src) || + return (mFrozen ? !!mUri : HasAttr(kNameSpaceID_None, nsGkAtoms::src)) || nsContentUtils::HasNonEmptyTextContent(this); } diff --git a/content/svg/content/src/nsSVGScriptElement.cpp b/content/svg/content/src/nsSVGScriptElement.cpp index f6a51bcf996c..0e8df93ee363 100644 --- a/content/svg/content/src/nsSVGScriptElement.cpp +++ b/content/svg/content/src/nsSVGScriptElement.cpp @@ -76,12 +76,10 @@ public: // nsIScriptElement virtual void GetScriptType(nsAString& type); - virtual already_AddRefed GetScriptURI(); virtual void GetScriptText(nsAString& text); virtual void GetScriptCharset(nsAString& charset); - virtual PRBool GetScriptDeferred(); - virtual PRBool GetScriptAsync(); - + virtual void FreezeUriAsyncDefer(); + // nsScriptElement virtual PRBool HasScriptContent(); @@ -199,22 +197,6 @@ nsSVGScriptElement::GetScriptType(nsAString& type) GetType(type); } -// variation of this code in nsHTMLScriptElement - check if changes -// need to be transfered when modifying - -already_AddRefed -nsSVGScriptElement::GetScriptURI() -{ - nsIURI *uri = nsnull; - nsAutoString src; - mStringAttributes[HREF].GetAnimValue(src, this); - if (!src.IsEmpty()) { - nsCOMPtr baseURI = GetBaseURI(); - NS_NewURI(&uri, src, nsnull, baseURI); - } - return uri; -} - void nsSVGScriptElement::GetScriptText(nsAString& text) { @@ -227,16 +209,24 @@ nsSVGScriptElement::GetScriptCharset(nsAString& charset) charset.Truncate(); } -PRBool -nsSVGScriptElement::GetScriptDeferred() +void +nsSVGScriptElement::FreezeUriAsyncDefer() { - return PR_FALSE; -} + if (mFrozen) { + return; + } -PRBool -nsSVGScriptElement::GetScriptAsync() -{ - return PR_FALSE; + // variation of this code in nsHTMLScriptElement - check if changes + // need to be transfered when modifying + nsAutoString src; + mStringAttributes[HREF].GetAnimValue(src, this); + // preserving bug 528444 here due to being unsure how to fix correctly + if (!src.IsEmpty()) { + nsCOMPtr baseURI = GetBaseURI(); + NS_NewURI(getter_AddRefs(mUri), src, nsnull, baseURI); + } + + mFrozen = PR_TRUE; } //---------------------------------------------------------------------- @@ -245,9 +235,10 @@ nsSVGScriptElement::GetScriptAsync() PRBool nsSVGScriptElement::HasScriptContent() { - nsAutoString str; - mStringAttributes[HREF].GetAnimValue(str, this); - return !str.IsEmpty() || + nsAutoString src; + mStringAttributes[HREF].GetAnimValue(src, this); + // preserving bug 528444 here due to being unsure how to fix correctly + return (mFrozen ? !!mUri : !src.IsEmpty()) || nsContentUtils::HasNonEmptyTextContent(this); } @@ -278,7 +269,14 @@ nsresult nsSVGScriptElement::DoneAddingChildren(PRBool aHaveNotified) { mDoneAddingChildren = PR_TRUE; - return MaybeProcessScript(); + nsresult rv = MaybeProcessScript(); + if (!mIsEvaluated) { + // Need to thaw the script uri here to allow another script to cause + // execution later. + mFrozen = PR_FALSE; + mUri = nsnull; + } + return rv; } nsresult diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index 600ca4ec9687..af940e763f5a 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -164,7 +164,7 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm } else if (nsHtml5Atoms::script == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); - treeOp->Init(eTreeOpSetScriptLineNumber, content, tokenizer->getLineNumber()); + treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber()); nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC); if (url) { @@ -208,7 +208,7 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm } else if (nsHtml5Atoms::script == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); - treeOp->Init(eTreeOpSetScriptLineNumber, content, tokenizer->getLineNumber()); + treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber()); nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); if (url) { @@ -241,7 +241,7 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm } else if (nsHtml5Atoms::script == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); - treeOp->Init(eTreeOpSetScriptLineNumber, content, tokenizer->getLineNumber()); + treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber()); } } diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp index 154e238e0b67..5352f913ee0d 100644 --- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -582,11 +582,12 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, ssle->SetLineNumber(mInt); return rv; } - case eTreeOpSetScriptLineNumber: { + case eTreeOpSetScriptLineNumberAndFreeze: { nsIContent* node = *(mOne.node); nsCOMPtr sele = do_QueryInterface(node); NS_ASSERTION(sele, "Node didn't QI to script."); sele->SetScriptLineNumber(mInt); + sele->FreezeUriAsyncDefer(); return rv; } default: { diff --git a/parser/html/nsHtml5TreeOperation.h b/parser/html/nsHtml5TreeOperation.h index 013825f5c01b..755bb942f609 100644 --- a/parser/html/nsHtml5TreeOperation.h +++ b/parser/html/nsHtml5TreeOperation.h @@ -78,7 +78,7 @@ enum eHtml5TreeOperation { eTreeOpMarkMalformedIfScript, eTreeOpStreamEnded, eTreeOpSetStyleLineNumber, - eTreeOpSetScriptLineNumber, + eTreeOpSetScriptLineNumberAndFreeze, eTreeOpStartLayout }; From 9126f32030104551d68c252d16ea0679695bd3db Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Tue, 17 Nov 2009 10:52:30 +0200 Subject: [PATCH 152/179] Bug 515610 - Make defer and async work with the speculating HTML5 parser. r=bnewman. --HG-- extra : rebase_source : 19dc4eaddf51c50cb416d62081fcef4ecd8d11c4 --- content/base/src/nsContentSink.cpp | 6 +++++ parser/html/nsHtml5TreeBuilderCppSupplement.h | 22 ++++++++++++++++++- parser/html/nsHtml5TreeBuilderHSupplement.h | 1 + parser/html/nsHtml5TreeOpExecutor.cpp | 22 +++++++++++++++---- parser/html/nsHtml5TreeOperation.h | 1 + 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index c1cd4fd37e2e..3a43f34e5bae 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -360,6 +360,9 @@ nsContentSink::ScriptAvailable(nsresult aResult, return NS_OK; } + NS_ASSERTION(!aElement->GetScriptDeferred(), "defer script was in mScriptElements"); + NS_ASSERTION(!aElement->GetScriptAsync(), "async script was in mScriptElements"); + if (mParser && !mParser->IsParserEnabled()) { // make sure to unblock the parser before evaluating the script, // we must unblock the parser even if loading the script failed or @@ -402,6 +405,9 @@ nsContentSink::ScriptEvaluated(nsresult aResult, return NS_OK; } + NS_ASSERTION(!aElement->GetScriptDeferred(), "defer script was in mScriptElements"); + NS_ASSERTION(!aElement->GetScriptAsync(), "async script was in mScriptElements"); + // Pop the script element stack mScriptElements.RemoveObjectAt(count - 1); diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index af940e763f5a..4e43e6ad8f73 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -59,6 +59,7 @@ nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink) , mOpSink(aOpSink) , mHandles(new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH]) , mHandlesUsed(0) + , mCurrentHtmlScriptIsAsyncOrDefer(PR_FALSE) #ifdef DEBUG , mActive(PR_FALSE) #endif @@ -174,6 +175,9 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm *url, (charset) ? *charset : EmptyString(), (type) ? *type : EmptyString())); + mCurrentHtmlScriptIsAsyncOrDefer = + aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) || + aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER); } } else if (nsHtml5Atoms::link == aName) { nsString* rel = aAttributes->getValue(nsHtml5AttributeName::ATTR_REL); @@ -233,7 +237,7 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm break; } } else if (aNamespace != kNameSpaceID_MathML) { - // No speculative loader--just line numbers + // No speculative loader--just line numbers and defer/async check if (nsHtml5Atoms::style == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); @@ -242,6 +246,12 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber()); + if (aNamespace == kNameSpaceID_XHTML) { + mCurrentHtmlScriptIsAsyncOrDefer = + aAttributes->contains(nsHtml5AttributeName::ATTR_SRC) && + (aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) || + aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER)); + } } } @@ -399,6 +409,7 @@ nsHtml5TreeBuilder::markMalformedIfScript(nsIContent** aElement) void nsHtml5TreeBuilder::start(PRBool fragment) { + mCurrentHtmlScriptIsAsyncOrDefer = PR_FALSE; #ifdef DEBUG mActive = PR_TRUE; #endif @@ -453,6 +464,15 @@ nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent } // we now have only SVG and HTML if (aName == nsHtml5Atoms::script) { + if (mCurrentHtmlScriptIsAsyncOrDefer) { + NS_ASSERTION(aNamespace == kNameSpaceID_XHTML, + "Only HTML scripts may be async/defer."); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + treeOp->Init(eTreeOpRunScriptAsyncDefer, aElement); + mCurrentHtmlScriptIsAsyncOrDefer = PR_FALSE; + return; + } requestSuspension(); nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); diff --git a/parser/html/nsHtml5TreeBuilderHSupplement.h b/parser/html/nsHtml5TreeBuilderHSupplement.h index d3061df1ebe0..bff38d1354db 100644 --- a/parser/html/nsHtml5TreeBuilderHSupplement.h +++ b/parser/html/nsHtml5TreeBuilderHSupplement.h @@ -45,6 +45,7 @@ PRInt32 mHandlesUsed; nsTArray > mOldHandles; nsRefPtr mSpeculativeLoader; + PRBool mCurrentHtmlScriptIsAsyncOrDefer; #ifdef DEBUG PRBool mActive; #endif diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp index ba896e52893f..594c9d6bf4c8 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -419,12 +419,9 @@ nsHtml5TreeOpExecutor::DocumentMode(nsHtml5DocumentMode m) void nsHtml5TreeOpExecutor::RunScript(nsIContent* aScriptElement) { - mReadingFromStage = PR_FALSE; NS_ASSERTION(aScriptElement, "No script to run"); - NS_ASSERTION(mFlushState == eNotFlushing, "Tried to run script when flushing."); - nsCOMPtr sele = do_QueryInterface(aScriptElement); - + if (!mParser) { NS_ASSERTION(sele->IsMalformed(), "Script wasn't marked as malformed."); // We got here not because of an end tag but because the tree builder @@ -440,16 +437,33 @@ nsHtml5TreeOpExecutor::RunScript(nsIContent* aScriptElement) return; } + if (sele->GetScriptDeferred() || sele->GetScriptAsync()) { + #ifdef DEBUG + nsresult rv = + #endif + aScriptElement->DoneAddingChildren(PR_TRUE); // scripts ignore the argument + NS_ASSERTION(rv != NS_ERROR_HTMLPARSER_BLOCK, + "Defer or async script tried to block."); + return; + } + + NS_ASSERTION(mFlushState == eNotFlushing, "Tried to run script when flushing."); + + mReadingFromStage = PR_FALSE; + sele->SetCreatorParser(mParser); + // Notify our document that we're loading this script. nsCOMPtr htmlDocument = do_QueryInterface(mDocument); NS_ASSERTION(htmlDocument, "Document didn't QI into HTML document."); htmlDocument->ScriptLoading(sele); + // Copied from nsXMLContentSink // Now tell the script that it's ready to go. This may execute the script // or return NS_ERROR_HTMLPARSER_BLOCK. Or neither if the script doesn't // need executing. nsresult rv = aScriptElement->DoneAddingChildren(PR_TRUE); + // If the act of insertion evaluated the script, we're fine. // Else, block the parser till the script has loaded. if (rv == NS_ERROR_HTMLPARSER_BLOCK) { diff --git a/parser/html/nsHtml5TreeOperation.h b/parser/html/nsHtml5TreeOperation.h index 755bb942f609..51c31fbfc463 100644 --- a/parser/html/nsHtml5TreeOperation.h +++ b/parser/html/nsHtml5TreeOperation.h @@ -66,6 +66,7 @@ enum eHtml5TreeOperation { eTreeOpAppendDoctypeToDocument, // Gecko-specific on-pop ops eTreeOpRunScript, + eTreeOpRunScriptAsyncDefer, eTreeOpDoneAddingChildren, eTreeOpDoneCreatingElement, eTreeOpFlushPendingAppendNotifications, From 4bf31544543992ad13dacefdbe2c708fa5459777 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Sat, 12 Dec 2009 13:25:21 +0900 Subject: [PATCH 153/179] Bug 42676 Can't drag to extend selection out of blocks with overflow:hidden/auto/scroll r=Olli --- content/base/public/nsINode.h | 3 +- content/base/src/nsGenericElement.cpp | 46 +- layout/generic/nsFrameSelection.h | 1 - layout/generic/nsSelection.cpp | 105 ++--- layout/generic/test/Makefile.in | 2 + .../generic/test/selection_expanding_xbl.xml | 11 + .../test/test_selection_expanding.html | 413 ++++++++++++++++++ 7 files changed, 504 insertions(+), 77 deletions(-) create mode 100644 layout/generic/test/selection_expanding_xbl.xml create mode 100644 layout/generic/test/test_selection_expanding.html diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index d087cd1e4aa5..a0936a510bb9 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -803,7 +803,8 @@ public: * user does "Select All" while the focus is in this node. Note that if this * node is not in an editor, the result comes from the nsFrameSelection that * is related to aPresShell, so the result might not be the ancestor of this - * node. + * node. Be aware that if this node and the computed selection limiter are + * not in same subtree, this returns the root content of the closeset subtree. */ nsIContent* GetSelectionRootContent(nsIPresShell* aPresShell); diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index cfce03ad98ee..ffc652b1ac5a 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -372,6 +372,20 @@ static nsIEditor* GetHTMLEditor(nsPresContext* aPresContext) return editor; } +static nsIContent* GetRootForContentSubtree(nsIContent* aContent) +{ + NS_ENSURE_TRUE(aContent, nsnull); + nsIContent* stop = aContent->GetBindingParent(); + while (aContent) { + nsIContent* parent = aContent->GetParent(); + if (parent == stop) { + break; + } + aContent = parent; + } + return aContent; +} + nsIContent* nsINode::GetSelectionRootContent(nsIPresShell* aPresShell) { @@ -397,8 +411,13 @@ nsINode::GetSelectionRootContent(nsIPresShell* aPresShell) if (editor) { // This node is in HTML editor. nsIDocument* doc = GetCurrentDoc(); - if (!doc || doc->HasFlag(NODE_IS_EDITABLE) || !HasFlag(NODE_IS_EDITABLE)) - return GetEditorRootContent(editor); + if (!doc || doc->HasFlag(NODE_IS_EDITABLE) || + !HasFlag(NODE_IS_EDITABLE)) { + nsIContent* editorRoot = GetEditorRootContent(editor); + return nsContentUtils::IsInSameAnonymousTree(this, editorRoot) ? + editorRoot : + GetRootForContentSubtree(static_cast(this)); + } // If the current document is not editable, but current content is // editable, we should assume that the child of the nearest non-editable // ancestor is selection root. @@ -413,14 +432,21 @@ nsINode::GetSelectionRootContent(nsIPresShell* aPresShell) nsCOMPtr fs = aPresShell->FrameSelection(); nsIContent* content = fs->GetLimiter(); - if (content) - return content; - content = fs->GetAncestorLimiter(); - if (content) - return content; - nsIDocument* doc = aPresShell->GetDocument(); - NS_ENSURE_TRUE(doc, nsnull); - return doc->GetRootContent(); + if (!content) { + content = fs->GetAncestorLimiter(); + if (!content) { + nsIDocument* doc = aPresShell->GetDocument(); + NS_ENSURE_TRUE(doc, nsnull); + content = doc->GetRootContent(); + if (!content) + return nsnull; + } + } + + // This node might be in another subtree, if so, we should find this subtree's + // root. Otherwise, we can return the content simply. + return nsContentUtils::IsInSameAnonymousTree(this, content) ? + content : GetRootForContentSubtree(static_cast(this)); } nsINodeList* diff --git a/layout/generic/nsFrameSelection.h b/layout/generic/nsFrameSelection.h index 8f6d0fd9fee2..db0f3d3b8dde 100644 --- a/layout/generic/nsFrameSelection.h +++ b/layout/generic/nsFrameSelection.h @@ -658,7 +658,6 @@ private: void InvalidateDesiredX(); //do not listen to mDesiredX you must get another. void SetDesiredX(nscoord aX); //set the mDesiredX - nsresult GetRootForContentSubtree(nsIContent *aContent, nsIContent **aParent); nsresult ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame, nsPoint& aPoint, nsIFrame **aRetFrame, nsPoint& aRetPoint); PRUint32 GetBatching() const {return mBatching; } diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index d6f4c2496f5c..4e1e5c66f3e0 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -851,52 +851,6 @@ nsFrameSelection::SetDesiredX(nscoord aX) //set the mDesiredX mDesiredXSet = PR_TRUE; } -nsresult -nsFrameSelection::GetRootForContentSubtree(nsIContent *aContent, - nsIContent **aParent) -{ - // This method returns the root of the sub-tree containing aContent. - // We do this by searching up through the parent hierarchy, and stopping - // when there are no more parents, or we hit a situation where the - // parent/child relationship becomes invalid. - // - // An example of an invalid parent/child relationship is anonymous content. - // Anonymous content has a pointer to its parent, but it is not listed - // as a child of its parent. In this case, the anonymous content would - // be considered the root of the subtree. - - if (!aContent || !aParent) - return NS_ERROR_NULL_POINTER; - - *aParent = 0; - - nsIContent* child = aContent; - - while (child) - { - nsIContent* parent = child->GetParent(); - - if (!parent) - break; - - PRUint32 childCount = parent->GetChildCount(); - - if (childCount < 1) - break; - - PRInt32 childIndex = parent->IndexOf(child); - - if (childIndex < 0 || ((PRUint32)childIndex) >= childCount) - break; - - child = parent; - } - - NS_IF_ADDREF(*aParent = child); - - return NS_OK; -} - nsresult nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame, nsPoint& aPoint, @@ -956,11 +910,8 @@ nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame, // Now find the root of the subtree containing the anchor's content. // - nsCOMPtr anchorRoot; - result = GetRootForContentSubtree(anchorContent, getter_AddRefs(anchorRoot)); - - if (NS_FAILED(result)) - return result; + NS_ENSURE_STATE(mShell); + nsIContent* anchorRoot = anchorContent->GetSelectionRootContent(mShell); // // Now find the root of the subtree containing aFrame's content. @@ -970,29 +921,53 @@ nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame, if (content) { - nsCOMPtr contentRoot; - - result = GetRootForContentSubtree(content, getter_AddRefs(contentRoot)); + nsIContent* contentRoot = content->GetSelectionRootContent(mShell); if (anchorRoot == contentRoot) { - // - // The anchor and AFrame's root are the same. There - // is no need to constrain, simply return aFrame. - // - *aRetFrame = aFrame; - return NS_OK; + // If the aFrame's content isn't the capturing content, it should be + // a descendant. At this time, we can return simply. + nsIContent* capturedContent = nsIPresShell::GetCapturingContent(); + if (capturedContent != content) + { + return NS_OK; + } + + // Find the frame under the mouse cursor with the root frame. + // At this time, don't use the anchor's frame because it may not have + // fixed positioned frames. + nsIFrame* rootFrame = mShell->FrameManager()->GetRootFrame(); + nsPoint ptInRoot = aPoint + aFrame->GetOffsetTo(rootFrame); + nsIFrame* cursorFrame = + nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot); + + // If the mouse cursor in on a frame which is descendant of same + // selection root, we can expand the selection to the frame. + if (cursorFrame && cursorFrame->PresContext()->PresShell() == mShell) + { + nsIContent* cursorContent = cursorFrame->GetContent(); + NS_ENSURE_TRUE(cursorContent, NS_ERROR_FAILURE); + nsIContent* cursorContentRoot = + cursorContent->GetSelectionRootContent(mShell); + if (cursorContentRoot == anchorRoot) + { + *aRetFrame = cursorFrame; + aRetPoint = aPoint + aFrame->GetOffsetTo(cursorFrame); + return NS_OK; + } + } + // Otherwise, e.g., the cursor isn't on any frames (e.g., the mouse + // cursor is out of the window), we should use the frame of the anchor + // root. } } // - // aFrame's root does not match the anchor's root, or there is no - // content associated with aFrame. Just return the primary frame - // for the anchor's root. We'll let GetContentAndOffsetsFromPoint() - // find the closest frame aPoint. + // When we can't find a frame which is under the mouse cursor and has a same + // selection root as the anchor node's, we should return the selection root + // frame. // - NS_ENSURE_STATE(mShell); *aRetFrame = mShell->GetPrimaryFrameFor(anchorRoot); if (!*aRetFrame) diff --git a/layout/generic/test/Makefile.in b/layout/generic/test/Makefile.in index 994e1d813d38..59c8397da161 100644 --- a/layout/generic/test/Makefile.in +++ b/layout/generic/test/Makefile.in @@ -101,6 +101,8 @@ _TEST_FILES = \ test_plugin_focus.html \ test_plugin_mouse_coords.html \ test_plugin_position.xhtml \ + test_selection_expanding.html \ + selection_expanding_xbl.xml \ test_selection_underline.html \ file_BrokenImageReference.png \ file_Dolske.png \ diff --git a/layout/generic/test/selection_expanding_xbl.xml b/layout/generic/test/selection_expanding_xbl.xml new file mode 100644 index 000000000000..aade8f8bb6c3 --- /dev/null +++ b/layout/generic/test/selection_expanding_xbl.xml @@ -0,0 +1,11 @@ + + + + + +

xxxxxxx xxxxxxx xxxxxxx

+ +
+
+
+
diff --git a/layout/generic/test/test_selection_expanding.html b/layout/generic/test/test_selection_expanding.html new file mode 100644 index 000000000000..832030235c05 --- /dev/null +++ b/layout/generic/test/test_selection_expanding.html @@ -0,0 +1,413 @@ + + + +selection expanding test + + + + + + + + + +
+ aaaaaaa + + aaaaaaa aaaaaaa
aaaaaaa aaaaaaa aaaaaaa aaaaaaa
aaaaaaa +
+
+ bbbbbbb + + bbbbbbb bbbbbbb
bbbbbbb bbbbbbb bbbbbbb
bbbbbbb +
+
+ ccccccc + + ccccccc ccccccc
ccccccc ccccccc ccccccc ccccccc
ccccccc +
+ dddddd dddddd dddddd +
+
+
+

yyyyyyy yyyyyyy yyyyyyy

+
+
+ eeeeee eeeeee eeeeee +
+
+
+
+ + \ No newline at end of file From 73f9a129d82ae8f46aa11be3bd7ee3618b8c6a05 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Sat, 12 Dec 2009 14:17:40 +0900 Subject: [PATCH 154/179] Bug 125282 Webpage-JS can steal focus from URLbar / chrome r=enndeakin --- browser/base/content/test/browser_drag.js | 3 + .../content/test/browser_overflowScroll.js | 7 + dom/base/nsFocusManager.cpp | 36 +++- dom/base/nsFocusManager.h | 2 +- dom/tests/Makefile.in | 4 +- dom/tests/browser/Makefile.in | 51 ++++++ .../browser_focus_steal_from_chrome.js | 169 ++++++++++++++++++ 7 files changed, 264 insertions(+), 8 deletions(-) create mode 100644 dom/tests/browser/Makefile.in create mode 100644 dom/tests/browser/browser_focus_steal_from_chrome.js diff --git a/browser/base/content/test/browser_drag.js b/browser/base/content/test/browser_drag.js index ccc10c79ab15..f41d87807b0f 100644 --- a/browser/base/content/test/browser_drag.js +++ b/browser/base/content/test/browser_drag.js @@ -20,4 +20,7 @@ function test() var dt = EventUtils.synthesizeDragStart(proxyicon, expected); is(dt, null, "drag on proxy icon"); proxyicon.setAttribute("pageproxystate", oldstate); + // Now, the identity information panel is opened by the proxy icon click. + // We need to close it for next tests. + EventUtils.synthesizeKey("VK_ESCAPE", {}, window); } diff --git a/browser/base/content/test/browser_overflowScroll.js b/browser/base/content/test/browser_overflowScroll.js index f00f8ae7eac3..f4b26a6d88c8 100644 --- a/browser/base/content/test/browser_overflowScroll.js +++ b/browser/base/content/test/browser_overflowScroll.js @@ -16,6 +16,13 @@ function nextRightElement() elementFromPoint(right(scrollbox) + 1); function test() { waitForExplicitFinish(); + // If the previous (or more) test finished with cleaning up the tabs, + // there may be some pending animations. That can cause a failure of + // this tests, so, we should test this in another stack. + setTimeout(doTest, 0); +} + +function doTest() { tabstrip.smoothScroll = false; var tabMinWidth = gPrefService.getIntPref("browser.tabs.tabMinWidth"); diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index b3cd2f41d4ae..37fdd564549c 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -1075,7 +1075,24 @@ nsFocusManager::SetFocusInner(nsIContent* aNewContent, PRInt32 aFlags, // if the element is in the active window, frame switching is allowed and // the content is in a visible window, fire blur and focus events. - if (isElementInActiveWindow && allowFrameSwitch && IsWindowVisible(newWindow)) { + PRBool sendFocusEvent = + isElementInActiveWindow && allowFrameSwitch && IsWindowVisible(newWindow); + + // When the following conditions are true: + // * an element has focus + // * isn't called by trusted event (i.e., called by untrusted event or by js) + // * the focus is moved to another document's element + // we need to check the permission. + if (sendFocusEvent && mFocusedContent && + mFocusedContent->GetOwnerDoc() != aNewContent->GetOwnerDoc()) { + // If the caller cannot access the current focused node, the caller should + // not be able to steal focus from it. E.g., When the current focused node + // is in chrome, any web contents should not be able to steal the focus. + nsCOMPtr domNode(do_QueryInterface(mFocusedContent)); + sendFocusEvent = nsContentUtils::CanCallerAccess(domNode); + } + + if (sendFocusEvent) { // return if blurring fails or the focus changes during the blur if (mFocusedWindow) { // if the focus is being moved to another element in the same document, @@ -1109,10 +1126,10 @@ nsFocusManager::SetFocusInner(nsIContent* aNewContent, PRInt32 aFlags, aFocusChanged, PR_FALSE); } else { - // otherwise, for inactive windows, update the node in the window, and - // raise the window if desired. + // otherwise, for inactive windows and when the caller cannot steal the + // focus, update the node in the window, and raise the window if desired. if (allowFrameSwitch) - AdjustWindowFocus(newWindow); + AdjustWindowFocus(newWindow, PR_TRUE); // set the focus node and method as needed PRUint32 focusMethod = aFocusChanged ? aFlags & FOCUSMETHOD_MASK : @@ -1201,7 +1218,8 @@ nsFocusManager::GetCommonAncestor(nsPIDOMWindow* aWindow1, } void -nsFocusManager::AdjustWindowFocus(nsPIDOMWindow* aWindow) +nsFocusManager::AdjustWindowFocus(nsPIDOMWindow* aWindow, + PRBool aCheckPermission) { PRBool isVisible = IsWindowVisible(aWindow); @@ -1227,6 +1245,12 @@ nsFocusManager::AdjustWindowFocus(nsPIDOMWindow* aWindow) if (IsWindowVisible(window) != isVisible) break; + // When aCheckPermission is true, we should check whether the caller can + // access the window or not. If it cannot access, we should stop the + // adjusting. + if (aCheckPermission && !nsContentUtils::CanCallerAccess(window)) + break; + window->SetFocusedNode(frameContent); } } @@ -1528,7 +1552,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow, // focus can be traversed from the top level down to the newly focused // window. if (aIsNewDocument) - AdjustWindowFocus(aWindow); + AdjustWindowFocus(aWindow, PR_FALSE); // indicate that the window has taken focus. if (aWindow->TakeFocus(PR_TRUE, focusMethod)) diff --git a/dom/base/nsFocusManager.h b/dom/base/nsFocusManager.h index 019b3f6d4ec8..4aed027819c7 100644 --- a/dom/base/nsFocusManager.h +++ b/dom/base/nsFocusManager.h @@ -150,7 +150,7 @@ protected: * the active top-level window and navigate down the currently focused * elements for each frame in the tree to get to aNewWindow. */ - void AdjustWindowFocus(nsPIDOMWindow* aNewWindow); + void AdjustWindowFocus(nsPIDOMWindow* aNewWindow, PRBool aCheckPermission); /** * Returns true if aWindow is visible. diff --git a/dom/tests/Makefile.in b/dom/tests/Makefile.in index eb734a074165..8750807ccb33 100644 --- a/dom/tests/Makefile.in +++ b/dom/tests/Makefile.in @@ -44,7 +44,9 @@ include $(DEPTH)/config/autoconf.mk MODULE = test_dom -DIRS += mochitest +DIRS += mochitest \ + browser \ + $(NULL) XPCSHELL_TESTS = unit include $(topsrcdir)/config/rules.mk diff --git a/dom/tests/browser/Makefile.in b/dom/tests/browser/Makefile.in new file mode 100644 index 000000000000..7f49129d12cf --- /dev/null +++ b/dom/tests/browser/Makefile.in @@ -0,0 +1,51 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2007 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ +relativesrcdir = dom/tests/browser + +include $(DEPTH)/config/autoconf.mk +include $(topsrcdir)/config/rules.mk + +_BROWSER_FILES = \ + browser_focus_steal_from_chrome.js \ + +libs:: $(_BROWSER_FILES) + $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir) diff --git a/dom/tests/browser/browser_focus_steal_from_chrome.js b/dom/tests/browser/browser_focus_steal_from_chrome.js new file mode 100644 index 000000000000..4f4e20e8e4b0 --- /dev/null +++ b/dom/tests/browser/browser_focus_steal_from_chrome.js @@ -0,0 +1,169 @@ +function test() { + waitForExplicitFinish(); + + let fm = Components.classes["@mozilla.org/focus-manager;1"] + .getService(Components.interfaces.nsIFocusManager); + + let tabs = [ gBrowser.mCurrentTab, gBrowser.addTab() ]; + gBrowser.selectedTab = tabs[0]; + + let testingList = [ + { uri: "data:text/html,", + tagName: "INPUT", methodName: "focus" }, + { uri: "data:text/html,", + tagName: "INPUT", methodName: "select" }, + { uri: "data:text/html,anchor", + tagName: "A", methodName: "focus" }, + { uri: "data:text/html,", + tagName: "BUTTON", methodName: "focus" }, + { uri: "data:text/html,", + tagName: "SELECT", methodName: "focus" }, + { uri: "data:text/html,", + tagName: "TEXTAREA", methodName: "focus" }, + { uri: "data:text/html,", + tagName: "TEXTAREA", methodName: "select" }, + { uri: "data:text/html,", + tagName: "INPUT", methodName: "focus of label element" }, + { uri: "data:text/html,
legend
", + tagName: "INPUT", methodName: "focus of legend element" }, + { uri: "data:text/html," + + "", + tagName: "BUTTON", methodName: "mousedown event on the button element" }, + { uri: "data:text/html," + + "", + tagName: "INPUT", methodName: "click event on the label element" }, + ]; + + let testingIndex = -1; + let canRetry; + let callback; + let loadedCount; + + function runNextTest() { + if (++testingIndex >= testingList.length) { + // cleaning-up... + let cleanTab = gBrowser.addTab(); + gBrowser.selectedTab = cleanTab; + for (let i = 0; i < tabs.length; i++) { + gBrowser.removeTab(tabs[i]); + } + finish(); + return; + } + callback = doTest1; + loadTestPage(); + } + + function loadTestPage() { + loadedCount = 0; + canRetry = 10; + // Set the focus to the contents. + tabs[0].linkedBrowser.focus(); + for (let i = 0; i < tabs.length; i++) { + tabs[i].linkedBrowser.addEventListener("load", onLoad, true); + tabs[i].linkedBrowser.loadURI(testingList[testingIndex].uri); + } + } + + function onLoad() { + if (++loadedCount == tabs.length) { + for (let i = 0; i < tabs.length; i++) { + tabs[i].linkedBrowser.removeEventListener("load", onLoad, true); + } + setTimeout(callback, 20); + } + } + + function isPrepared() { + for (let i = 0; i < tabs.length; i++) { + if (tabs[i].linkedBrowser.contentDocument.activeElement.tagName != + testingList[testingIndex].tagName) { + return false; + } + } + return true; + } + + function doTest1() { + if (canRetry-- > 0 && !isPrepared()) { + setTimeout(callback, 10); // retry + return; + } + + // The contents should be able to steal the focus from content. + + // in foreground tab + let e = tabs[0].linkedBrowser.contentDocument.activeElement; + is(e.tagName, testingList[testingIndex].tagName, + "the foreground tab's " + testingList[testingIndex].tagName + + " element is not active by the " + testingList[testingIndex].methodName + + " (Test1: content can steal focus)"); + is(fm.focusedElement, e, + "the " + testingList[testingIndex].tagName + + " element isn't focused by the " + testingList[testingIndex].methodName + + " (Test1: content can steal focus)"); + + // in background tab + e = tabs[1].linkedBrowser.contentDocument.activeElement; + is(e.tagName, testingList[testingIndex].tagName, + "the background tab's " + testingList[testingIndex].tagName + + " element is not active by the " + testingList[testingIndex].methodName + + " (Test1: content can steal focus)"); + isnot(fm.focusedElement, e, + "the " + testingList[testingIndex].tagName + + " element is focused by the " + testingList[testingIndex].methodName + + " (Test1: content can steal focus)"); + + callback = doTest2; + loadTestPage(); + + // Set focus to chrome element before onload events of the loading contents. + BrowserSearch.searchBar.focus(); + } + + + function doTest2() { + if (canRetry-- > 0 && !isPrepared()) { + setTimeout(callback, 10); // retry + return; + } + + // The contents shouldn't be able to steal the focus from chrome. + + // in foreground tab + let e = tabs[0].linkedBrowser.contentDocument.activeElement; + is(e.tagName, testingList[testingIndex].tagName, + "the foreground tab's " + testingList[testingIndex].tagName + + " element is not active by the " + testingList[testingIndex].methodName + + " (Test2: content can NOT steal focus)"); + isnot(fm.focusedElement, e, + "the " + testingList[testingIndex].tagName + + " element is focused by the " + testingList[testingIndex].methodName + + " (Test2: content can NOT steal focus)"); + + // in background tab + e = tabs[1].linkedBrowser.contentDocument.activeElement; + is(e.tagName, testingList[testingIndex].tagName, + "the background tab's " + testingList[testingIndex].tagName + + " element is not active by the " + testingList[testingIndex].methodName + + " (Test2: content can NOT steal focus)"); + isnot(fm.focusedElement, e, + "the " + testingList[testingIndex].tagName + + " element is focused by the " + testingList[testingIndex].methodName + + " (Test2: content can NOT steal focus)"); + + runNextTest(); + } + + runNextTest(); +} \ No newline at end of file From e0f8a871948e22153d7e9c94a34093e5b759bf12 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Fri, 11 Dec 2009 22:36:33 -0800 Subject: [PATCH 155/179] Bug 340017. Make document.formName work in XHTML. r=bzbarsky --- content/html/document/src/nsHTMLDocument.cpp | 5 ---- content/html/document/test/Makefile.in | 1 + .../html/document/test/test_bug340017.xhtml | 28 +++++++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 content/html/document/test/test_bug340017.xhtml diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index adad4e302515..0e0b0a7b609c 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -2635,11 +2635,6 @@ nsHTMLDocument::ResolveName(const nsAString& aName, { *aResult = nsnull; - if (!mIsRegularHTML) { - // We don't dynamically resolve names on non-HTML documents. - return NS_OK; - } - nsCOMPtr name(do_GetAtom(aName)); // We have built a table and cache the named items. The table will diff --git a/content/html/document/test/Makefile.in b/content/html/document/test/Makefile.in index 5d56ef8d8561..aa0932e250ff 100644 --- a/content/html/document/test/Makefile.in +++ b/content/html/document/test/Makefile.in @@ -97,6 +97,7 @@ _TEST_FILES = test_bug1682.html \ test_bug486741.html \ test_bug497242.xhtml \ test_bug512367.html \ + test_bug340017.xhtml \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/document/test/test_bug340017.xhtml b/content/html/document/test/test_bug340017.xhtml new file mode 100644 index 000000000000..1768640d3c7d --- /dev/null +++ b/content/html/document/test/test_bug340017.xhtml @@ -0,0 +1,28 @@ + + + + Test for Bug 340017 + + + + + +Mozilla Bug 340017 +

+ +
+
+
+ + From 95aa939837fffa89364659b44eeaba68ce833c19 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 11 Dec 2009 22:36:33 -0800 Subject: [PATCH 156/179] Bug 526596. Make sure appends to an {ib} split coalesce blocks correctly if the appended frames start with a block and the trailing inline of the split is empty. r=roc --- layout/base/nsCSSFrameConstructor.cpp | 44 +++++++++++++++---- ...append-to-empty-trailing-inline-1-ref.html | 19 ++++++++ .../append-to-empty-trailing-inline-1.html | 27 ++++++++++++ layout/reftests/ib-split/reftest.list | 1 + 4 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 layout/reftests/ib-split/append-to-empty-trailing-inline-1-ref.html create mode 100644 layout/reftests/ib-split/append-to-empty-trailing-inline-1.html diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index a888e029d474..fd97033b06ee 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1379,9 +1379,10 @@ PRBool IsBorderCollapse(nsIFrame* aFrame) * Moves aFrameList from aOldParent to aNewParent. This updates the parent * pointer of the frames in the list, reparents their views as needed, and sets * the NS_FRAME_HAS_VIEW bit on aNewParent and its ancestors as needed. Then - * it sets the list as the initial child list on aNewParent. Note that this - * method differs from ReparentFrames in that it doesn't change the kids' style - * contexts. + * it sets the list as the initial child list on aNewParent, unless aNewParent + * either already has kids or has been reflowed; in that case it appends the + * new frames. Note that this method differs from ReparentFrames in that it + * doesn't change the kids' style contexts. */ // XXXbz Since this is only used for {ib} splits, could we just copy the view // bits from aOldParent to aNewParent and then use the @@ -1397,10 +1398,6 @@ MoveChildrenTo(nsPresContext* aPresContext, { NS_PRECONDITION(aOldParent->GetParent() == aNewParent->GetParent(), "Unexpected old and new parents"); - NS_PRECONDITION(aNewParent->GetChildList(nsnull).IsEmpty(), - "New parent should have no kids"); - NS_PRECONDITION(aNewParent->GetStateBits() & NS_FRAME_FIRST_REFLOW, - "New parent shouldn't have been reflowed yet"); if (aNewParent->HasView() || aOldParent->HasView()) { // Move the frames into the new view @@ -1424,7 +1421,12 @@ MoveChildrenTo(nsPresContext* aPresContext, aNewParent->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW); } - aNewParent->SetInitialChildList(nsnull, aFrameList); + if (aNewParent->GetChildList(nsnull).IsEmpty() && + (aNewParent->GetStateBits() & NS_FRAME_FIRST_REFLOW)) { + aNewParent->SetInitialChildList(nsnull, aFrameList); + } else { + aNewParent->AppendFrames(nsnull, aFrameList); + } } // ----------------------------------------------------------- @@ -5799,6 +5801,32 @@ nsCSSFrameConstructor::AppendFrames(nsFrameConstructorState& aState, // of an {ib} split, we may need to create additional {ib} siblings to parent // them. if (!nextSibling && IsFrameSpecial(aParentFrame)) { + // When we get here, our frame list might start with a block. If it does + // so, and aParentFrame is an inline, and it and all its previous + // continuations have no siblings, then put the initial blocks from the + // frame list into the previous block of the {ib} split. Note that we + // didn't want to stop at the block part of the split when figuring out + // initial parent, because that could screw up float parenting; it's easier + // to do this little fixup here instead. + if (aFrameList.NotEmpty() && !IsInlineOutside(aFrameList.FirstChild())) { + // See whether out trailing inline is empty + nsIFrame* firstContinuation = aParentFrame->GetFirstContinuation(); + if (firstContinuation->GetChildList(nsnull).IsEmpty()) { + // Our trailing inline is empty. Collect our starting blocks from + // aFrameList, get the right parent frame for them, and put them in. + nsFrameList::FrameLinkEnumerator firstNonBlockEnumerator = + FindFirstNonBlock(aFrameList); + nsFrameList blockKids = aFrameList.ExtractHead(firstNonBlockEnumerator); + NS_ASSERTION(blockKids.NotEmpty(), "No blocks?"); + + nsIFrame* prevBlock = + GetSpecialPrevSibling(firstContinuation)->GetLastContinuation(); + NS_ASSERTION(prevBlock, "Should have previous block here"); + + MoveChildrenTo(aState.mPresContext, aParentFrame, prevBlock, blockKids); + } + } + // We want to put some of the frames into this inline frame. nsFrameList::FrameLinkEnumerator firstBlockEnumerator(aFrameList); FindFirstBlock(firstBlockEnumerator); diff --git a/layout/reftests/ib-split/append-to-empty-trailing-inline-1-ref.html b/layout/reftests/ib-split/append-to-empty-trailing-inline-1-ref.html new file mode 100644 index 000000000000..91dbb4659fc7 --- /dev/null +++ b/layout/reftests/ib-split/append-to-empty-trailing-inline-1-ref.html @@ -0,0 +1,19 @@ + + + + + + + + + + +AA + + + diff --git a/layout/reftests/ib-split/append-to-empty-trailing-inline-1.html b/layout/reftests/ib-split/append-to-empty-trailing-inline-1.html new file mode 100644 index 000000000000..8f080454f868 --- /dev/null +++ b/layout/reftests/ib-split/append-to-empty-trailing-inline-1.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + +A + + + diff --git a/layout/reftests/ib-split/reftest.list b/layout/reftests/ib-split/reftest.list index ecaa4139616a..e6b9664a3a48 100644 --- a/layout/reftests/ib-split/reftest.list +++ b/layout/reftests/ib-split/reftest.list @@ -80,3 +80,4 @@ == ignored-margins-2a.html ignored-margins-2-ref.html == ignored-margins-2b.html ignored-margins-2-ref.html == trailing-inline-with-continuations-1.html trailing-inline-with-continuations-1-ref.html +== append-to-empty-trailing-inline-1.html append-to-empty-trailing-inline-1-ref.html From bab8cbeae816cf3f787827f83d61e0e2561f275f Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 11 Dec 2009 22:36:34 -0800 Subject: [PATCH 157/179] Bug 531148. Fix appends of a block to the trailing inline of an {ib} split which has an inline parent. r=roc --- layout/base/nsCSSFrameConstructor.cpp | 35 +++++++++++++++---- ...end-to-nested-split-inline-1-noib-ref.html | 34 ++++++++++++++++++ .../append-to-nested-split-inline-1-ref.html | 22 ++++++++++++ .../append-to-nested-split-inline-1.html | 32 +++++++++++++++++ .../ib-split/insert-into-split-inline-14.html | 1 - layout/reftests/ib-split/reftest.list | 2 ++ 6 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 layout/reftests/ib-split/append-to-nested-split-inline-1-noib-ref.html create mode 100644 layout/reftests/ib-split/append-to-nested-split-inline-1-ref.html create mode 100644 layout/reftests/ib-split/append-to-nested-split-inline-1.html diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index fd97033b06ee..82d135528418 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -5852,8 +5852,9 @@ nsCSSFrameConstructor::AppendFrames(nsFrameConstructorState& aState, nsIPresShell::eTreeChange, NS_FRAME_HAS_DIRTY_CHILDREN); - return aState.mFrameManager->InsertFrames(aParentFrame->GetParent(), - nsnull, aParentFrame, ibSiblings); + // Recurse so we create new ib siblings as needed for aParentFrame's parent + return AppendFrames(aState, aParentFrame->GetParent(), ibSiblings, + aParentFrame); } return NS_OK; @@ -11030,6 +11031,26 @@ nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState, aParentItem.mIsAllInline = aParentItem.mChildItems.AreAllItemsInline(); } +// return whether it's ok to append (in the AppendFrames sense) to +// aParentFrame if our nextSibling is aNextSibling. aParentFrame must +// be an {ib} special inline. +static PRBool +IsSafeToAppendToSpecialInline(nsIFrame* aParentFrame, nsIFrame* aNextSibling) +{ + NS_PRECONDITION(IsInlineFrame(aParentFrame), + "Must have an inline parent here"); + do { + NS_ASSERTION(IsFrameSpecial(aParentFrame), "How is this not special?"); + if (aNextSibling || aParentFrame->GetNextContinuation() || + GetSpecialSibling(aParentFrame)) { + return PR_FALSE; + } + + aNextSibling = aParentFrame->GetNextSibling(); + aParentFrame = aParentFrame->GetParent(); + } while (IsInlineFrame(aParentFrame)); +} + PRBool nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, nsIFrame* aContainingBlock, @@ -11240,10 +11261,12 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, // Now we're adding kids including some blocks to an inline part of an // {ib} split. If we plan to call AppendFrames, and don't have a next // sibling for the new frames, and our parent is the last continuation of - // the last part of the {ib} split, then AppendFrames will handle things - // for us. Bail out in that case. - if (aIsAppend && !nextSibling && !aFrame->GetNextContinuation() && - !GetSpecialSibling(aFrame)) { + // the last part of the {ib} split, and the same is true of all our + // ancestor inlines (they have no following continuations and they're the + // last part of their {ib} splits and we'd be adding to the end for all + // of them), then AppendFrames will handle things for us. Bail out in + // that case. + if (aIsAppend && IsSafeToAppendToSpecialInline(aFrame, nextSibling)) { return PR_FALSE; } diff --git a/layout/reftests/ib-split/append-to-nested-split-inline-1-noib-ref.html b/layout/reftests/ib-split/append-to-nested-split-inline-1-noib-ref.html new file mode 100644 index 000000000000..3a7bcf5c7d9a --- /dev/null +++ b/layout/reftests/ib-split/append-to-nested-split-inline-1-noib-ref.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + before span + + + + span + + + + after span + + + + + diff --git a/layout/reftests/ib-split/append-to-nested-split-inline-1-ref.html b/layout/reftests/ib-split/append-to-nested-split-inline-1-ref.html new file mode 100644 index 000000000000..fd54f25327a2 --- /dev/null +++ b/layout/reftests/ib-split/append-to-nested-split-inline-1-ref.html @@ -0,0 +1,22 @@ + + + + + + + + + + + before span + span + after span + + + + + diff --git a/layout/reftests/ib-split/append-to-nested-split-inline-1.html b/layout/reftests/ib-split/append-to-nested-split-inline-1.html new file mode 100644 index 000000000000..14c54e1db118 --- /dev/null +++ b/layout/reftests/ib-split/append-to-nested-split-inline-1.html @@ -0,0 +1,32 @@ + + + + + + + + + + + + before span + + + + + diff --git a/layout/reftests/ib-split/insert-into-split-inline-14.html b/layout/reftests/ib-split/insert-into-split-inline-14.html index 8ce3da92c74f..3c0b5d5aaf23 100644 --- a/layout/reftests/ib-split/insert-into-split-inline-14.html +++ b/layout/reftests/ib-split/insert-into-split-inline-14.html @@ -8,7 +8,6 @@ diff --git a/layout/reftests/ib-split/reftest.list b/layout/reftests/ib-split/reftest.list index e6b9664a3a48..779921d2100b 100644 --- a/layout/reftests/ib-split/reftest.list +++ b/layout/reftests/ib-split/reftest.list @@ -81,3 +81,5 @@ == ignored-margins-2b.html ignored-margins-2-ref.html == trailing-inline-with-continuations-1.html trailing-inline-with-continuations-1-ref.html == append-to-empty-trailing-inline-1.html append-to-empty-trailing-inline-1-ref.html +== append-to-nested-split-inline-1.html append-to-nested-split-inline-1-ref.html +== append-to-nested-split-inline-1-ref.html append-to-nested-split-inline-1-noib-ref.html From 9790daa9b2f977f29119ba09e91674d0a0dbf2ce Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 11 Dec 2009 22:36:34 -0800 Subject: [PATCH 158/179] Bug 529749. Make sure nsRuleWalker never has a null mCurrent. r=dbaron --- layout/style/nsHTMLStyleSheet.cpp | 2 +- layout/style/nsRuleNode.cpp | 9 +++++--- layout/style/nsRuleNode.h | 1 + layout/style/nsRuleWalker.h | 23 +++++++++++-------- layout/style/nsStyleSet.cpp | 37 +++++++++++++++---------------- 5 files changed, 40 insertions(+), 32 deletions(-) diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index 301ba8c4eafd..1e5389bb17a6 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -476,7 +476,7 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData) if (aData->mCompatMode == eCompatibility_NavQuirks) { nscolor bodyColor; nsresult rv = - GetBodyColor(ruleWalker->GetCurrentNode()->GetPresContext(), + GetBodyColor(ruleWalker->CurrentNode()->GetPresContext(), &bodyColor); if (NS_SUCCEEDED(rv) && (!mDocumentColorRule || bodyColor != mDocumentColorRule->mColor)) { diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 42fcda8bcacd..e10309831db5 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -965,7 +965,8 @@ nsRuleNode::Transition(nsIStyleRule* aRule, PRUint8 aLevel, ChildrenHashEntry *entry = static_cast (PL_DHashTableOperate(ChildrenHash(), &key, PL_DHASH_ADD)); if (!entry) { - return nsnull; + NS_WARNING("out of memory"); + return this; } if (entry->mRuleNode) next = entry->mRuleNode; @@ -974,7 +975,8 @@ nsRuleNode::Transition(nsIStyleRule* aRule, PRUint8 aLevel, nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule); if (!next) { PL_DHashTableRawRemove(ChildrenHash(), entry); - return nsnull; + NS_WARNING("out of memory"); + return this; } } } else if (!next) { @@ -982,7 +984,8 @@ nsRuleNode::Transition(nsIStyleRule* aRule, PRUint8 aLevel, next = new (mPresContext) nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule); if (!next) { - return nsnull; + NS_WARNING("out of memory"); + return this; } next->mNextSibling = ChildrenList(); SetChildrenList(next); diff --git a/layout/style/nsRuleNode.h b/layout/style/nsRuleNode.h index c7f6ea51aa2d..155411c2dd24 100644 --- a/layout/style/nsRuleNode.h +++ b/layout/style/nsRuleNode.h @@ -735,6 +735,7 @@ private: public: static NS_HIDDEN_(nsRuleNode*) CreateRootNode(nsPresContext* aPresContext); + // Transition never returns null; on out of memory it'll just return |this|. NS_HIDDEN_(nsRuleNode*) Transition(nsIStyleRule* aRule, PRUint8 aLevel, PRPackedBool aIsImportantRule); nsRuleNode* GetParent() const { return mParent; } diff --git a/layout/style/nsRuleWalker.h b/layout/style/nsRuleWalker.h index fd238579d866..e7c314e249c7 100644 --- a/layout/style/nsRuleWalker.h +++ b/layout/style/nsRuleWalker.h @@ -45,15 +45,17 @@ class nsRuleWalker { public: - nsRuleNode* GetCurrentNode() { return mCurrent; } - void SetCurrentNode(nsRuleNode* aNode) { mCurrent = aNode; } + nsRuleNode* CurrentNode() { return mCurrent; } + void SetCurrentNode(nsRuleNode* aNode) { + NS_ASSERTION(aNode, "Must have node here!"); + mCurrent = aNode; + } void Forward(nsIStyleRule* aRule) { - if (mCurrent) { // check for OOM from previous step - mCurrent = mCurrent->Transition(aRule, mLevel, mImportance); - mCheckForImportantRules = - mCheckForImportantRules && !aRule->GetImportantRule(); - } + mCurrent = mCurrent->Transition(aRule, mLevel, mImportance); + mCheckForImportantRules = + mCheckForImportantRules && !aRule->GetImportantRule(); + NS_POSTCONDITION(mCurrent, "Transition messed up"); } void Reset() { mCurrent = mRoot; } @@ -74,7 +76,7 @@ public: PRBool GetCheckForImportantRules() const { return mCheckForImportantRules; } private: - nsRuleNode* mCurrent; // Our current position. + nsRuleNode* mCurrent; // Our current position. Never null. nsRuleNode* mRoot; // The root of the tree we're walking. PRUint8 mLevel; // an nsStyleSet::sheetType PRPackedBool mImportance; @@ -83,6 +85,9 @@ private: // one. public: - nsRuleWalker(nsRuleNode* aRoot) :mCurrent(aRoot), mRoot(aRoot) { MOZ_COUNT_CTOR(nsRuleWalker); } + nsRuleWalker(nsRuleNode* aRoot) :mCurrent(aRoot), mRoot(aRoot) { + NS_ASSERTION(mCurrent, "Caller screwed up and gave us null node"); + MOZ_COUNT_CTOR(nsRuleWalker); + } ~nsRuleWalker() { MOZ_COUNT_DTOR(nsRuleWalker); } }; diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 8224f3c4f3c8..52dbd41a53dd 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -472,9 +472,8 @@ nsStyleSet::AddImportantRules(nsRuleNode* aCurrLevelNode, nsRuleNode* aLastPrevLevelNode, nsRuleWalker* aRuleWalker) { - // The rulewalker will move itself to a null node on OOM. - if (!aCurrLevelNode) - return; + NS_ASSERTION(aCurrLevelNode && + aCurrLevelNode != aLastPrevLevelNode, "How did we get here?"); nsAutoTArray importantRules; for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode; @@ -554,26 +553,26 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc, aRuleWalker->SetLevel(eAgentSheet, PR_FALSE, PR_TRUE); if (mRuleProcessors[eAgentSheet]) (*aCollectorFunc)(mRuleProcessors[eAgentSheet], aData); - nsRuleNode* lastAgentRN = aRuleWalker->GetCurrentNode(); + nsRuleNode* lastAgentRN = aRuleWalker->CurrentNode(); PRBool haveImportantUARules = !aRuleWalker->GetCheckForImportantRules(); aRuleWalker->SetLevel(ePresHintSheet, PR_FALSE, PR_FALSE); if (mRuleProcessors[ePresHintSheet]) (*aCollectorFunc)(mRuleProcessors[ePresHintSheet], aData); - nsRuleNode* lastPresHintRN = aRuleWalker->GetCurrentNode(); + nsRuleNode* lastPresHintRN = aRuleWalker->CurrentNode(); aRuleWalker->SetLevel(eUserSheet, PR_FALSE, PR_TRUE); PRBool skipUserStyles = aContent && aContent->IsInNativeAnonymousSubtree(); if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different (*aCollectorFunc)(mRuleProcessors[eUserSheet], aData); - nsRuleNode* lastUserRN = aRuleWalker->GetCurrentNode(); + nsRuleNode* lastUserRN = aRuleWalker->CurrentNode(); PRBool haveImportantUserRules = !aRuleWalker->GetCheckForImportantRules(); aRuleWalker->SetLevel(eHTMLPresHintSheet, PR_FALSE, PR_FALSE); if (mRuleProcessors[eHTMLPresHintSheet]) (*aCollectorFunc)(mRuleProcessors[eHTMLPresHintSheet], aData); - nsRuleNode* lastHTMLPresHintRN = aRuleWalker->GetCurrentNode(); + nsRuleNode* lastHTMLPresHintRN = aRuleWalker->CurrentNode(); aRuleWalker->SetLevel(eDocSheet, PR_FALSE, PR_TRUE); PRBool cutOffInheritance = PR_FALSE; @@ -590,13 +589,13 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc, aRuleWalker->GetCheckForImportantRules()); if (mRuleProcessors[eStyleAttrSheet]) (*aCollectorFunc)(mRuleProcessors[eStyleAttrSheet], aData); - nsRuleNode* lastDocRN = aRuleWalker->GetCurrentNode(); + nsRuleNode* lastDocRN = aRuleWalker->CurrentNode(); PRBool haveImportantDocRules = !aRuleWalker->GetCheckForImportantRules(); aRuleWalker->SetLevel(eOverrideSheet, PR_FALSE, PR_TRUE); if (mRuleProcessors[eOverrideSheet]) (*aCollectorFunc)(mRuleProcessors[eOverrideSheet], aData); - nsRuleNode* lastOvrRN = aRuleWalker->GetCurrentNode(); + nsRuleNode* lastOvrRN = aRuleWalker->CurrentNode(); PRBool haveImportantOverrideRules = !aRuleWalker->GetCheckForImportantRules(); if (haveImportantDocRules) { @@ -650,13 +649,13 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc, #endif #ifdef DEBUG - nsRuleNode *lastImportantRN = aRuleWalker->GetCurrentNode(); + nsRuleNode *lastImportantRN = aRuleWalker->CurrentNode(); #endif aRuleWalker->SetLevel(eTransitionSheet, PR_FALSE, PR_FALSE); (*aCollectorFunc)(mRuleProcessors[eTransitionSheet], aData); #ifdef DEBUG - AssertNoCSSRules(aRuleWalker->GetCurrentNode(), lastImportantRN); - AssertNoImportantRules(aRuleWalker->GetCurrentNode(), lastImportantRN); + AssertNoCSSRules(aRuleWalker->CurrentNode(), lastImportantRN); + AssertNoImportantRules(aRuleWalker->CurrentNode(), lastImportantRN); #endif } @@ -750,7 +749,7 @@ nsStyleSet::ResolveStyleFor(nsIContent* aContent, FileRules(EnumRulesMatching, &data, aContent, &ruleWalker); result = GetContext(presContext, aParentContext, - ruleWalker.GetCurrentNode(), nsnull, + ruleWalker.CurrentNode(), nsnull, nsCSSPseudoElements::ePseudo_NotPseudoElement).get(); } @@ -779,7 +778,7 @@ nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext, ruleWalker.Forward(aRules.ObjectAt(i)); } result = GetContext(presContext, aParentContext, - ruleWalker.GetCurrentNode(), aPseudoTag, + ruleWalker.CurrentNode(), aPseudoTag, aPseudoType).get(); } return result; @@ -833,7 +832,7 @@ nsStyleSet::ResolvePseudoElementStyle(nsIContent* aParentContent, FileRules(EnumRulesMatching, &data, aParentContent, &ruleWalker); - return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(), + return GetContext(presContext, aParentContext, ruleWalker.CurrentNode(), nsCSSPseudoElements::GetPseudoAtom(aType), aType); } @@ -859,11 +858,11 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, aType); WalkRestrictionRule(aType, &ruleWalker); // not the root if there was a restriction rule - nsRuleNode *adjustedRoot = ruleWalker.GetCurrentNode(); + nsRuleNode *adjustedRoot = ruleWalker.CurrentNode(); FileRules(EnumRulesMatching, &data, aParentContent, &ruleWalker); - nsRuleNode *ruleNode = ruleWalker.GetCurrentNode(); + nsRuleNode *ruleNode = ruleWalker.CurrentNode(); if (ruleNode == adjustedRoot) { return nsnull; } @@ -910,7 +909,7 @@ nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, FileRules(EnumRulesMatching, &data, nsnull, &ruleWalker); - return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(), + return GetContext(presContext, aParentContext, ruleWalker.CurrentNode(), aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox); } @@ -937,7 +936,7 @@ nsStyleSet::ResolveXULTreePseudoStyle(nsIContent* aParentContent, FileRules(EnumRulesMatching, &data, aParentContent, &ruleWalker); - return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(), + return GetContext(presContext, aParentContext, ruleWalker.CurrentNode(), aPseudoTag, nsCSSPseudoElements::ePseudo_XULTree); } #endif From dbe398c5f74a26379db2b5e66e4cb94e42468541 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 11 Dec 2009 22:36:34 -0800 Subject: [PATCH 159/179] Bug 531933. Give HasStateDependentStyle a better signature. r=dbaron --- layout/style/nsCSSRuleProcessor.cpp | 17 ++++++++--------- layout/style/nsCSSRuleProcessor.h | 3 +-- layout/style/nsHTMLCSSStyleSheet.cpp | 11 ++++------- layout/style/nsHTMLStyleSheet.cpp | 16 ++++++---------- layout/style/nsHTMLStyleSheet.h | 3 +-- layout/style/nsIStyleRuleProcessor.h | 10 +++++----- layout/style/nsStyleSet.cpp | 3 +-- layout/style/nsTransitionManager.cpp | 8 +++----- layout/style/nsTransitionManager.h | 3 +-- 9 files changed, 30 insertions(+), 44 deletions(-) diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index e9297abaa84e..588b0578fca9 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -2244,9 +2244,8 @@ IsSiblingOperator(PRUnichar oper) return oper == PRUnichar('+') || oper == PRUnichar('~'); } -NS_IMETHODIMP -nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData, - nsReStyleHint* aResult) +nsReStyleHint +nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData) { NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT), "content must be element"); @@ -2261,8 +2260,8 @@ nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData, // "body > p:hover" will be in |cascade->mStateSelectors|). Note that // |IsStateSelector| below determines which selectors are in // |cascade->mStateSelectors|. + nsReStyleHint hint = nsReStyleHint(0); if (cascade) { - *aResult = nsReStyleHint(0); nsCSSSelector **iter = cascade->mStateSelectors.Elements(), **end = iter + cascade->mStateSelectors.Length(); for(; iter != end; ++iter) { @@ -2271,17 +2270,17 @@ nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData, nsReStyleHint possibleChange = IsSiblingOperator(selector->mOperator) ? eReStyle_LaterSiblings : eReStyle_Self; - // If *aResult already includes all the bits of possibleChange, + // If hint already includes all the bits of possibleChange, // don't bother calling SelectorMatches, since even if it returns false - // *aResult won't change. - if ((possibleChange & ~(*aResult)) && + // hint won't change. + if ((possibleChange & ~hint) && SelectorMatches(*aData, selector, aData->mStateMask, PR_FALSE) && SelectorMatchesTree(*aData, selector->mNext, PR_FALSE)) { - *aResult = nsReStyleHint(*aResult | possibleChange); + hint = nsReStyleHint(hint | possibleChange); } } } - return NS_OK; + return hint; } struct AttributeEnumData { diff --git a/layout/style/nsCSSRuleProcessor.h b/layout/style/nsCSSRuleProcessor.h index 300f934261e8..3998ffcf0c54 100644 --- a/layout/style/nsCSSRuleProcessor.h +++ b/layout/style/nsCSSRuleProcessor.h @@ -101,8 +101,7 @@ public: NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsReStyleHint* aResult); + virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual nsReStyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp index a6f1f0aa185b..c10546d7b1ed 100644 --- a/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/layout/style/nsHTMLCSSStyleSheet.cpp @@ -97,8 +97,7 @@ public: NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsReStyleHint* aResult); + virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual nsReStyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); @@ -201,12 +200,10 @@ HTMLCSSStyleSheetImpl::Init(nsIURI* aURL, nsIDocument* aDocument) } // Test if style is dependent on content state -NS_IMETHODIMP -HTMLCSSStyleSheetImpl::HasStateDependentStyle(StateRuleProcessorData* aData, - nsReStyleHint* aResult) +nsReStyleHint +HTMLCSSStyleSheetImpl::HasStateDependentStyle(StateRuleProcessorData* aData) { - *aResult = nsReStyleHint(0); - return NS_OK; + return nsReStyleHint(0); } // Test if style is dependent on attribute diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index 1e5389bb17a6..0009daf7e233 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -501,23 +501,19 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData) } // Test if style is dependent on content state -NS_IMETHODIMP -nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData, - nsReStyleHint* aResult) +nsReStyleHint +nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData) { - if (aData->mContent && - aData->mIsHTMLContent && + if (aData->mIsHTMLContent && aData->mContentTag == nsGkAtoms::a && aData->IsLink() && ((mActiveRule && (aData->mStateMask & NS_EVENT_STATE_ACTIVE)) || (mLinkRule && (aData->mStateMask & NS_EVENT_STATE_VISITED)) || (mVisitedRule && (aData->mStateMask & NS_EVENT_STATE_VISITED)))) { - *aResult = eReStyle_Self; + return eReStyle_Self; } - else - *aResult = nsReStyleHint(0); - - return NS_OK; + + return nsReStyleHint(0); } nsReStyleHint diff --git a/layout/style/nsHTMLStyleSheet.h b/layout/style/nsHTMLStyleSheet.h index 8f35a136ab06..17a4c52006d7 100644 --- a/layout/style/nsHTMLStyleSheet.h +++ b/layout/style/nsHTMLStyleSheet.h @@ -84,8 +84,7 @@ public: #ifdef MOZ_XUL NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsReStyleHint* aResult); + virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual nsReStyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext, diff --git a/layout/style/nsIStyleRuleProcessor.h b/layout/style/nsIStyleRuleProcessor.h index 63e95249b640..9fc8c84e9a4f 100644 --- a/layout/style/nsIStyleRuleProcessor.h +++ b/layout/style/nsIStyleRuleProcessor.h @@ -61,10 +61,10 @@ struct AttributeRuleProcessorData; class nsPresContext; // IID for the nsIStyleRuleProcessor interface -// {ec92bc0c-9518-48ea-9289-74e654659be9} +// {566a7bea-fdc5-40a5-bf8a-87b5a231d79e} #define NS_ISTYLE_RULE_PROCESSOR_IID \ -{ 0xec92bc0c, 0x9518, 0x48ea, \ - { 0x92, 0x89, 0x74, 0xe6, 0x54, 0x65, 0x9b, 0xe9 } } +{ 0x566a7bea, 0xfdc5, 0x40a5, \ + { 0xbf, 0x8a, 0x87, 0xb5, 0xa2, 0x31, 0xd7, 0x9e } } /* The style rule processor interface is a mechanism to separate the matching * of style rules from style sheet instances. @@ -117,8 +117,8 @@ public: * * Event states are defined in nsIEventStateManager.h. */ - NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsReStyleHint* aResult) = 0; + virtual nsReStyleHint + HasStateDependentStyle(StateRuleProcessorData* aData) = 0; /** * This method will be called twice for every attribute change. diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 52dbd41a53dd..cfeb85808095 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -1076,8 +1076,7 @@ static PRBool SheetHasStatefulStyle(nsIStyleRuleProcessor* aProcessor, void *aData) { StatefulData* data = (StatefulData*)aData; - nsReStyleHint hint; - aProcessor->HasStateDependentStyle(data, &hint); + nsReStyleHint hint = aProcessor->HasStateDependentStyle(data); data->mHint = nsReStyleHint(data->mHint | hint); return PR_TRUE; // continue } diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 47eddac5a9fb..a9849927407d 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -828,12 +828,10 @@ nsTransitionManager::RulesMatching(XULTreeRuleProcessorData* aData) } #endif -NS_IMETHODIMP -nsTransitionManager::HasStateDependentStyle(StateRuleProcessorData* aData, - nsReStyleHint* aResult) +nsReStyleHint +nsTransitionManager::HasStateDependentStyle(StateRuleProcessorData* aData) { - *aResult = nsReStyleHint(0); - return NS_OK; + return nsReStyleHint(0); } nsReStyleHint diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index 53e919b3d849..c91bb81efc60 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -91,8 +91,7 @@ public: #ifdef MOZ_XUL NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, - nsReStyleHint* aResult); + virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual nsReStyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext, From 11e88414f17dd4db8b460feaf49a40d277378f08 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 11 Dec 2009 22:36:34 -0800 Subject: [PATCH 160/179] Bug 533048. Don't do extra work for link targeting in nsDocShellTreeOwner. r=jst --- .../webBrowser/nsDocShellTreeOwner.cpp | 71 +++---------------- .../browser/webBrowser/nsDocShellTreeOwner.h | 4 -- 2 files changed, 10 insertions(+), 65 deletions(-) diff --git a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp index 7c62c71a290b..2bcf5380caa8 100644 --- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp +++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp @@ -241,37 +241,27 @@ nsDocShellTreeOwner::FindItemWithName(const PRUnichar* aName, return NS_OK; // _main is an IE target which should be case-insensitive but isn't // see bug 217886 for details + // XXXbz what if our browser isn't targetable? We need to handle that somehow. if(name.LowerCaseEqualsLiteral("_content") || name.EqualsLiteral("_main")) { *aFoundItem = mWebBrowser->mDocShellAsItem; NS_IF_ADDREF(*aFoundItem); return NS_OK; } - // first, is it us? - { - nsCOMPtr domWindow; - mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); - if (domWindow) { - nsAutoString ourName; - domWindow->GetName(ourName); - if (name.Equals(ourName, nsCaseInsensitiveStringComparator())) { - *aFoundItem = mWebBrowser->mDocShellAsItem; - NS_IF_ADDREF(*aFoundItem); - return NS_OK; - } + if (!SameCOMIdentity(aRequestor, mWebBrowser->mDocShellAsItem)) { + // This isn't a request coming up from our kid, so check with said kid + nsISupports* thisSupports = static_cast(this); + rv = + mWebBrowser->mDocShellAsItem->FindItemWithName(aName, thisSupports, + aOriginalRequestor, aFoundItem); + if (NS_FAILED(rv) || *aFoundItem) { + return rv; } } - // next, check our children - rv = FindChildWithName(aName, PR_TRUE, aRequestor, aOriginalRequestor, - aFoundItem); - if(NS_FAILED(rv) || *aFoundItem) - return rv; - // next, if we have a parent and it isn't the requestor, ask it - nsCOMPtr reqAsTreeOwner(do_QueryInterface(aRequestor)); - if(mTreeOwner) { + nsCOMPtr reqAsTreeOwner(do_QueryInterface(aRequestor)); if (mTreeOwner != reqAsTreeOwner) return mTreeOwner->FindItemWithName(aName, mWebBrowser->mDocShellAsItem, aOriginalRequestor, aFoundItem); @@ -283,47 +273,6 @@ nsDocShellTreeOwner::FindItemWithName(const PRUnichar* aName, aFoundItem); } -nsresult -nsDocShellTreeOwner::FindChildWithName(const PRUnichar *aName, PRBool aRecurse, - nsIDocShellTreeItem* aRequestor, - nsIDocShellTreeItem* aOriginalRequestor, - nsIDocShellTreeItem **aFoundItem) -{ - if (!mWebBrowser) - return NS_OK; - - nsresult rv = NS_OK; - - nsCOMPtr domWindow; - mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); - if (!domWindow) - return NS_OK; - - nsCOMPtr frames; - domWindow->GetFrames(getter_AddRefs(frames)); - if (!frames) - return NS_OK; - - PRUint32 ctr, count; - frames->GetLength(&count); - for (ctr = 0; ctr < count; ctr++) { - nsCOMPtr frame; - frames->Item(ctr, getter_AddRefs(frame)); - nsCOMPtr w(do_QueryInterface(frame)); - if (w) { - nsCOMPtr item = do_QueryInterface(w->GetDocShell()); - if (item && item != aRequestor) { - rv = item->FindItemWithName(aName, mWebBrowser->mDocShellAsItem, - aOriginalRequestor, aFoundItem); - if (NS_FAILED(rv) || *aFoundItem) - break; - } - } - } - - return rv; -} - nsresult nsDocShellTreeOwner::FindItemWithNameAcrossWindows(const PRUnichar* aName, nsIDocShellTreeItem* aRequestor, diff --git a/embedding/browser/webBrowser/nsDocShellTreeOwner.h b/embedding/browser/webBrowser/nsDocShellTreeOwner.h index 3f9be54d1beb..de48b51c84f5 100644 --- a/embedding/browser/webBrowser/nsDocShellTreeOwner.h +++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.h @@ -123,10 +123,6 @@ protected: NS_IMETHOD AddChromeListeners(); NS_IMETHOD RemoveChromeListeners(); - nsresult FindChildWithName(const PRUnichar *aName, - PRBool aRecurse, nsIDocShellTreeItem* aRequestor, - nsIDocShellTreeItem* aOriginalRequestor, - nsIDocShellTreeItem **aFoundItem); nsresult FindItemWithNameAcrossWindows(const PRUnichar* aName, nsIDocShellTreeItem* aRequestor, nsIDocShellTreeItem* aOriginalRequestor, From 2a824622905d179c53dd08fc8abcd73562d4e088 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 11 Dec 2009 22:36:35 -0800 Subject: [PATCH 161/179] Bug 533636. Speed up IsSecurityWrapper. r=mrbkap --- js/src/xpconnect/src/XPCWrapper.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/js/src/xpconnect/src/XPCWrapper.h b/js/src/xpconnect/src/XPCWrapper.h index d88b1156fd8a..c81d5278ef6e 100644 --- a/js/src/xpconnect/src/XPCWrapper.h +++ b/js/src/xpconnect/src/XPCWrapper.h @@ -221,10 +221,8 @@ public: static JSBool IsSecurityWrapper(JSObject *wrapper) { JSClass *clasp = STOBJ_GET_CLASS(wrapper); - return clasp == &sXPC_COW_JSClass.base || - clasp == &sXPC_SJOW_JSClass.base || - clasp == &sXPC_SOW_JSClass.base || - clasp == &sXPC_XOW_JSClass.base; + return (clasp->flags & JSCLASS_IS_EXTENDED) && + ((JSExtendedClass*)clasp)->wrappedObject; } /** From 2688bdb106c74fa2f6cd67870c04bdd7102f395b Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Sat, 12 Dec 2009 00:03:17 -0800 Subject: [PATCH 162/179] Bug 525608 followup. Initialize the variable, and remove the extra branch. r=dbaron --- layout/style/nsCSSParser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 4c0bcaea4136..eb805226387c 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -2505,7 +2505,8 @@ CSSParserImpl::ParseSelectorGroup(nsCSSSelectorList*& aList) } nsCOMPtr pseudoElement; nsAutoPtr pseudoElementArgs; - nsCSSPseudoElements::Type pseudoElementType; + nsCSSPseudoElements::Type pseudoElementType = + nsCSSPseudoElements::ePseudo_NotPseudoElement; nsSelectorParsingStatus parsingStatus = ParseSelector(*newSelector, getter_AddRefs(pseudoElement), getter_Transfers(pseudoElementArgs), @@ -2520,8 +2521,7 @@ CSSParserImpl::ParseSelectorGroup(nsCSSSelectorList*& aList) list = nsnull; break; } - if (pseudoElement && - pseudoElementType == nsCSSPseudoElements::ePseudo_AnonBox && + if (pseudoElementType == nsCSSPseudoElements::ePseudo_AnonBox && (list || !IsUniversalSelector(*newSelector))) { REPORT_UNEXPECTED(PEAnonBoxNotAlone); list = nsnull; From 94fd302245641a64a28889e04b241e5c21b15fb8 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 20:27:45 +0100 Subject: [PATCH 163/179] Bug 529542 - Fix a line that I missed in bug 508739 to give the view button in the history sidebar back its gradient. r=dao --HG-- extra : rebase_source : 5cfdaa9942e33a030cfd81e916be6aa461deae92 --- browser/themes/pinstripe/browser/places/places.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/themes/pinstripe/browser/places/places.css b/browser/themes/pinstripe/browser/places/places.css index 141db8082ea3..d79a8ac7482a 100644 --- a/browser/themes/pinstripe/browser/places/places.css +++ b/browser/themes/pinstripe/browser/places/places.css @@ -68,7 +68,7 @@ -moz-appearance: none; border: 1px solid #7F7F7F; -moz-border-radius: 10px; - background: url("chrome://global/skin/icons/white-gray-gradient.gif") #A09E9D repeat-x top center; + background: @toolbarbuttonBackground@; min-width: 0px; min-height: 0px; -moz-padding-start: 5px; From 5d63a53a22b0be34fa2dbffb5971271ba28db53d Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 20:31:42 +0100 Subject: [PATCH 164/179] Bug 532878 - Call [super viewWillDraw] in viewWillDraw. r=josh --HG-- extra : rebase_source : 7f51c22fc690c8e48b70bc75dd84b35ae288474a --- widget/src/cocoa/nsChildView.mm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 62723d3e7982..811ced6c8b0f 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -2665,11 +2665,11 @@ static const PRInt32 sShadowInvalidationInterval = 100; - (void)viewWillDraw { - if (!mGeckoChild) - return; - - nsPaintEvent paintEvent(PR_TRUE, NS_WILL_PAINT, mGeckoChild); - mGeckoChild->DispatchWindowEvent(paintEvent); + if (mGeckoChild) { + nsPaintEvent paintEvent(PR_TRUE, NS_WILL_PAINT, mGeckoChild); + mGeckoChild->DispatchWindowEvent(paintEvent); + } + [super viewWillDraw]; } // Allows us to turn off setting up the clip region From 694c147808516e802443077ab737663e7a9db171 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 22:53:22 +0100 Subject: [PATCH 165/179] Bug 527696 - Make shadow invalidation always asynchronous and remove the invalidation frequency limit. r=josh --HG-- extra : rebase_source : 9089a5ef0c5a01ca2830a79fb3756b7284a4035a --- widget/src/cocoa/nsChildView.h | 3 --- widget/src/cocoa/nsChildView.mm | 40 ++++--------------------------- widget/src/cocoa/nsCocoaWindow.h | 13 +++++++--- widget/src/cocoa/nsCocoaWindow.mm | 16 +++++++++++++ 4 files changed, 30 insertions(+), 42 deletions(-) diff --git a/widget/src/cocoa/nsChildView.h b/widget/src/cocoa/nsChildView.h index d9f9a932678a..a13cb0ce618e 100644 --- a/widget/src/cocoa/nsChildView.h +++ b/widget/src/cocoa/nsChildView.h @@ -155,9 +155,6 @@ enum { NSMutableArray* mPendingDirtyRects; BOOL mPendingFullDisplay; - PRIntervalTime mLastShadowInvalidation; - BOOL mNeedsShadowInvalidation; - // Holds our drag service across multiple drag calls. The reference to the // service is obtained when the mouse enters the view and is released when // the mouse exits or there is a drop. This prevents us from having to diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 811ced6c8b0f..5c33a2df3358 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -195,9 +195,6 @@ PRUint32 nsChildView::sLastInputEventCount = 0; + (NSEvent*)makeNewCocoaEventWithType:(NSEventType)type fromEvent:(NSEvent*)theEvent; -- (void)maybeInvalidateShadow; -- (void)invalidateShadow; - #if USE_CLICK_HOLD_CONTEXTMENU // called on a timer two seconds after a mouse down to see if we should display // a context menu (click-hold) @@ -2497,37 +2494,6 @@ NSEvent* gLastDragMouseDownEvent = nil; NS_OBJC_END_TRY_ABORT_BLOCK; } -// Limit shadow invalidation to 10 times per second. -static const PRInt32 sShadowInvalidationInterval = 100; -- (void)maybeInvalidateShadow -{ - NSWindow* window = [self window]; - if (!window || [window isOpaque] || ![window hasShadow]) - return; - - PRIntervalTime now = PR_IntervalNow(); - PRInt32 elapsed = PR_IntervalToMilliseconds(now - mLastShadowInvalidation); - if (!mLastShadowInvalidation || - elapsed >= sShadowInvalidationInterval) { - [window invalidateShadow]; - mLastShadowInvalidation = now; - mNeedsShadowInvalidation = NO; - } else if (!mNeedsShadowInvalidation) { - mNeedsShadowInvalidation = YES; - [self performSelector:@selector(invalidateShadow) - withObject:nil - afterDelay:(sShadowInvalidationInterval - elapsed) / 1000.0]; - } -} - -- (void)invalidateShadow -{ - if (![self window] || !mNeedsShadowInvalidation) - return; - [[self window] invalidateShadow]; - mNeedsShadowInvalidation = NO; -} - // The display system has told us that a portion of our view is dirty. Tell // gecko to paint it - (void)drawRect:(NSRect)aRect @@ -2535,9 +2501,11 @@ static const PRInt32 sShadowInvalidationInterval = 100; CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; [self drawRect:aRect inContext:cgContext]; - // If we're a transparent window, and our contents have changed, we need + // If we're a transparent window and our contents have changed, we need // to make sure the shadow is updated to the new contents. - [self maybeInvalidateShadow]; + if ([[self window] isKindOfClass:[BaseWindow class]]) { + [(BaseWindow*)[self window] deferredInvalidateShadow]; + } } - (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext diff --git a/widget/src/cocoa/nsCocoaWindow.h b/widget/src/cocoa/nsCocoaWindow.h index b10f4e1a41db..559bfe62c864 100644 --- a/widget/src/cocoa/nsCocoaWindow.h +++ b/widget/src/cocoa/nsCocoaWindow.h @@ -60,18 +60,22 @@ typedef struct _nsCocoaWindowList { } nsCocoaWindowList; // NSWindow subclass that is the base class for all of our own window classes. -// This class handles the storage of those settings that need to be persisted -// across window destruction and reconstruction, i.e. when switching to and from -// fullscreen mode. +// Among other things, this class handles the storage of those settings that +// need to be persisted across window destruction and reconstruction, i.e. when +// switching to and from fullscreen mode. // We don't save shadow, transparency mode or background color because it's not // worth the hassle - Gecko will reset them anyway as soon as the window is // resized. @interface BaseWindow : NSWindow { + // Data Storage NSMutableDictionary* mState; BOOL mDrawsIntoWindowFrame; NSColor* mActiveTitlebarColor; NSColor* mInactiveTitlebarColor; + + // Shadow + BOOL mScheduledShadowInvalidation; } - (void)importState:(NSDictionary*)aState; @@ -81,6 +85,9 @@ typedef struct _nsCocoaWindowList { - (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive; - (NSColor*)titlebarColorForActiveWindow:(BOOL)aActive; +- (void)deferredInvalidateShadow; +- (void)invalidateShadow; + @end @interface NSWindow (Undocumented) diff --git a/widget/src/cocoa/nsCocoaWindow.mm b/widget/src/cocoa/nsCocoaWindow.mm index c0a134a699c1..d27e589dfb30 100644 --- a/widget/src/cocoa/nsCocoaWindow.mm +++ b/widget/src/cocoa/nsCocoaWindow.mm @@ -1744,6 +1744,7 @@ nsCocoaWindow::UnifiedShading(void* aInfo, const CGFloat* aIn, CGFloat* aOut) mDrawsIntoWindowFrame = NO; mActiveTitlebarColor = nil; mInactiveTitlebarColor = nil; + mScheduledShadowInvalidation = NO; return self; } @@ -1812,6 +1813,21 @@ static const NSString* kStateInactiveTitlebarColorKey = @"inactiveTitlebarColor" return aActive ? mActiveTitlebarColor : mInactiveTitlebarColor; } +- (void)deferredInvalidateShadow +{ + if (mScheduledShadowInvalidation || [self isOpaque] || ![self hasShadow]) + return; + + [self performSelector:@selector(invalidateShadow) withObject:nil afterDelay:0]; + mScheduledShadowInvalidation = YES; +} + +- (void)invalidateShadow +{ + [super invalidateShadow]; + mScheduledShadowInvalidation = NO; +} + @end // This class allows us to have a "unified toolbar" style window. It works like this: From db70dc729f17c7550cfa28b8426882c3d8f01f7c Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 22:56:59 +0100 Subject: [PATCH 166/179] Bug 527748 - Fire mouse enter and exit events when window focus changes. r=josh --HG-- extra : rebase_source : 47ee0c27942b038df0a52242c89747a5821f63d5 --- widget/src/cocoa/nsChildView.h | 1 + widget/src/cocoa/nsChildView.mm | 22 +++++++++++--------- widget/src/cocoa/nsCocoaUtils.h | 1 + widget/src/cocoa/nsCocoaUtils.mm | 2 +- widget/src/cocoa/nsCocoaWindow.mm | 4 ++++ widget/tests/native_mouse_mac_window.xul | 26 ++++++++++++++++-------- 6 files changed, 36 insertions(+), 20 deletions(-) diff --git a/widget/src/cocoa/nsChildView.h b/widget/src/cocoa/nsChildView.h index a13cb0ce618e..efb7029b9448 100644 --- a/widget/src/cocoa/nsChildView.h +++ b/widget/src/cocoa/nsChildView.h @@ -284,6 +284,7 @@ public: static void MouseMoved(NSEvent* aEvent); static void OnDestroyView(ChildView* aView); static BOOL WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent); + static void ReEvaluateMouseEnterState(NSEvent* aEvent = nil); static ChildView* sLastMouseEventView; diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 5c33a2df3358..7273fd4c8260 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -6504,26 +6504,28 @@ ChildViewMouseTracker::OnDestroyView(ChildView* aView) } void -ChildViewMouseTracker::MouseMoved(NSEvent* aEvent) +ChildViewMouseTracker::ReEvaluateMouseEnterState(NSEvent* aEvent) { ChildView* oldView = sLastMouseEventView; - ChildView* newView = ViewForEvent(aEvent); - sLastMouseEventView = newView; - if (newView != oldView) { + sLastMouseEventView = ViewForEvent(aEvent); + if (sLastMouseEventView != oldView) { // Send enter and / or exit events. - nsMouseEvent::exitType type = [newView window] == [oldView window] ? + nsMouseEvent::exitType type = [sLastMouseEventView window] == [oldView window] ? nsMouseEvent::eChild : nsMouseEvent::eTopLevel; [oldView sendMouseEnterOrExitEvent:aEvent enter:NO type:type]; // After the cursor exits the window set it to a visible regular arrow cursor. if (type == nsMouseEvent::eTopLevel) { [[nsCursorManager sharedInstance] setCursor:eCursor_standard]; } - // Sending the exit event to the old view might have destroyed our new view; - // if that has happened, sLastMouseEventView has been set to nil. - newView = sLastMouseEventView; - [newView sendMouseEnterOrExitEvent:aEvent enter:YES type:type]; + [sLastMouseEventView sendMouseEnterOrExitEvent:aEvent enter:YES type:type]; } - [newView handleMouseMoved:aEvent]; +} + +void +ChildViewMouseTracker::MouseMoved(NSEvent* aEvent) +{ + ReEvaluateMouseEnterState(aEvent); + [sLastMouseEventView handleMouseMoved:aEvent]; } ChildView* diff --git a/widget/src/cocoa/nsCocoaUtils.h b/widget/src/cocoa/nsCocoaUtils.h index b1591f1dd36c..e21afa29006e 100644 --- a/widget/src/cocoa/nsCocoaUtils.h +++ b/widget/src/cocoa/nsCocoaUtils.h @@ -138,6 +138,7 @@ class nsCocoaUtils // Gives the location for the event in screen coordinates. Do not call this // unless the window the event was originally targeted at is still alive! + // anEvent may be nil -- in that case the current mouse location is returned. static NSPoint ScreenLocationForEvent(NSEvent* anEvent); // Determines if an event happened over a window, whether or not the event diff --git a/widget/src/cocoa/nsCocoaUtils.mm b/widget/src/cocoa/nsCocoaUtils.mm index ecfcbebd7d72..3e931deafef0 100644 --- a/widget/src/cocoa/nsCocoaUtils.mm +++ b/widget/src/cocoa/nsCocoaUtils.mm @@ -100,7 +100,7 @@ NSPoint nsCocoaUtils::ScreenLocationForEvent(NSEvent* anEvent) NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; // Don't trust mouse locations of mouse move events, see bug 443178. - if ([anEvent type] == NSMouseMoved) + if (!anEvent || [anEvent type] == NSMouseMoved) return [NSEvent mouseLocation]; return [[anEvent window] convertBaseToScreen:[anEvent locationInWindow]]; diff --git a/widget/src/cocoa/nsCocoaWindow.mm b/widget/src/cocoa/nsCocoaWindow.mm index d27e589dfb30..dee63ca767ba 100644 --- a/widget/src/cocoa/nsCocoaWindow.mm +++ b/widget/src/cocoa/nsCocoaWindow.mm @@ -1563,6 +1563,7 @@ nsCocoaWindow::UnifiedShading(void* aInfo, const CGFloat* aIn, CGFloat* aOut) NS_OBJC_BEGIN_TRY_ABORT_BLOCK; RollUpPopups(); + ChildViewMouseTracker::ReEvaluateMouseEnterState(); // [NSApp _isRunningAppModal] will return true if we're running an OS dialog // app modally. If one of those is up then we want it to retain its menu bar. @@ -1578,6 +1579,7 @@ nsCocoaWindow::UnifiedShading(void* aInfo, const CGFloat* aIn, CGFloat* aOut) - (void)windowDidResignMain:(NSNotification *)aNotification { RollUpPopups(); + ChildViewMouseTracker::ReEvaluateMouseEnterState(); // [NSApp _isRunningAppModal] will return true if we're running an OS dialog // app modally. If one of those is up then we want it to retain its menu bar. @@ -1595,6 +1597,7 @@ nsCocoaWindow::UnifiedShading(void* aInfo, const CGFloat* aIn, CGFloat* aOut) NS_OBJC_BEGIN_TRY_ABORT_BLOCK; RollUpPopups(); + ChildViewMouseTracker::ReEvaluateMouseEnterState(); NSWindow* window = [aNotification object]; if ([window isSheet]) @@ -1608,6 +1611,7 @@ nsCocoaWindow::UnifiedShading(void* aInfo, const CGFloat* aIn, CGFloat* aOut) NS_OBJC_BEGIN_TRY_ABORT_BLOCK; RollUpPopups(); + ChildViewMouseTracker::ReEvaluateMouseEnterState(); // If a sheet just resigned key then we should paint the menu bar // for whatever window is now main. diff --git a/widget/tests/native_mouse_mac_window.xul b/widget/tests/native_mouse_mac_window.xul index 9d598df8b5b5..e8d3ae012240 100644 --- a/widget/tests/native_mouse_mac_window.xul +++ b/widget/tests/native_mouse_mac_window.xul @@ -110,6 +110,10 @@ NSEventTypeBeginGesture = 19, NSEventTypeEndGesture = 20; + const gDebug = false; + + function printDebug(msg) { if (gDebug) dump(msg); } + var gExpectedEvents = []; var gRightWindow = null, gPopup = null; @@ -120,6 +124,7 @@ expEv.screenY = y; gExpectedEvents.push(expEv); }); + printDebug("sending event: " + x + ", " + y + " (" + msg + ")\n"); netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor). getInterface(Components.interfaces.nsIDOMWindowUtils); @@ -139,6 +144,7 @@ function focusAndThen(win, callback) { eventListenOnce(win, "focus", callback); + printDebug("focusing a window\n"); win.focus(); } @@ -159,6 +165,7 @@ var gEventNum = 0; function eventMonitor(e) { + printDebug("got event: " + eventToString(e) + "\n"); var expectedEvent = gExpectedEvents.shift(); while (expectedEvent && expectedEvent.todoShouldHaveFired) { todo(false, "Should have got event: " + eventToString(expectedEvent)); @@ -238,22 +245,21 @@ [400, 150, NSMouseMoved, null, right, [ { type: "mouseout", target: leftElem }, ]], - // Clicking an inactive window shouldn't have any effect, other - // than focusing it. + // Clicking an inactive window should make it active and fire a mouseover + // event. [400, 150, NSLeftMouseDown, null, right, [ + { type: "mouseover", target: rightElem }, ]], [400, 150, NSLeftMouseUp, null, right, [ ]], // Now it's focused, so we should get a mousedown event when clicking. [400, 150, NSLeftMouseDown, null, right, [ { type: "mousedown", target: rightElem }, - { type: "mouseover", target: rightElem, todoShouldHaveFired: true }, ]], // Let's drag to the right without letting the button go. It would be better // if the mouseover event had fired as soon as the mouse entered the window, // and not only when dragging, but that's ok. [410, 150, NSLeftMouseDragged, null, right, [ - { type: "mouseover", target: rightElem, todoShouldNotHaveFired: true }, { type: "mousemove", target: rightElem }, ]], // Let go of the mouse. @@ -279,12 +285,15 @@ ]], // Right clicking hasn't focused it, so the window is still inactive. // Let's focus it; this time without the mouse, for variaton's sake. + // Still, mouseout and mouseover events should fire. function raiseLeftWindow(callback) { - focusAndThen(left, callback); + clearExpectedEvents(); + gExpectedEvents.push({ screenX: 150, screenY: 170, type: "mouseout", target: rightElem }); + gExpectedEvents.push({ screenX: 150, screenY: 170, type: "mouseover", target: leftElem }); + focusAndThen(left, function () { SimpleTest.executeSoon(callback); }); }, // It's active, so it should respond to mousemove events now. [150, 170, NSMouseMoved, null, left, [ - { type: "mouseover", target: leftElem }, { type: "mousemove", target: leftElem }, ]], @@ -328,8 +337,9 @@ [400, 180, NSMouseMoved, null, right, [ ]], // Activate the right window with a click. - // This will close the popup. + // This will close the popup and make the mouse enter the right window. [400, 180, NSLeftMouseDown, null, right, [ + { type: "mouseover", target: rightElem }, ]], [400, 180, NSLeftMouseUp, null, right, [ ]], @@ -338,9 +348,7 @@ callback(); }, // Now the right window is active; click it again, just for fun. - // (Would be good to have a mouseover event here.) [400, 180, NSLeftMouseDown, null, right, [ - { type: "mouseover", target: rightElem, todoShouldHaveFired: true }, { type: "mousedown", target: rightElem }, ]], [400, 180, NSLeftMouseUp, null, right, [ From ad6bbe0601a8f67bc1c6b9616139922b76b631b7 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 22:57:40 +0100 Subject: [PATCH 167/179] Bug 529891 - Use a better workaround for context menu clicking while the application is inactive. r=josh --HG-- extra : rebase_source : bdad5f1c76222b39ef20fc6d9e2e6f66417f8005 --- widget/src/cocoa/nsChildView.mm | 18 ++++++++++++ widget/src/cocoa/nsCocoaWindow.mm | 47 ------------------------------- 2 files changed, 18 insertions(+), 47 deletions(-) diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 7273fd4c8260..d2b8eba6a2fd 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -2980,10 +2980,28 @@ NSEvent* gLastDragMouseDownEvent = nil; NS_OBJC_END_TRY_ABORT_BLOCK; } +// Returning NO from this method only disallows ordering on mousedown - in order +// to prevent it for mouseup too, we need to call [NSApp preventWindowOrdering] +// when handling the mousedown event. +- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)aEvent +{ + // Always using system-provided window ordering for normal windows. + if (![[self window] isKindOfClass:[PopupWindow class]]) + return NO; + + // Don't reorder when we're already accepting mouse events, for example + // because we're a context menu. + return ChildViewMouseTracker::WindowAcceptsEvent([self window], aEvent); +} + - (void)mouseDown:(NSEvent*)theEvent { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + if ([self shouldDelayWindowOrderingForEvent:theEvent]) { + [NSApp preventWindowOrdering]; + } + // If we've already seen this event due to direct dispatch from menuForEvent: // just bail; if not, remember it. if (mLastMouseDownEvent == theEvent) { diff --git a/widget/src/cocoa/nsCocoaWindow.mm b/widget/src/cocoa/nsCocoaWindow.mm index dee63ca767ba..185019ee660f 100644 --- a/widget/src/cocoa/nsCocoaWindow.mm +++ b/widget/src/cocoa/nsCocoaWindow.mm @@ -2247,53 +2247,6 @@ ContentPatternDrawCallback(void* aInfo, CGContextRef aContext) case NSScrollWheel: [target scrollWheel:anEvent]; break; - case NSLeftMouseDown: - if ([NSApp isActive]) { - [target mouseDown:anEvent]; - } else if (mIsContextMenu) { - [target mouseDown:anEvent]; - // If we're in a context menu and our NSApp isn't active (i.e. if - // we're in a context menu raised by a right mouse-down event), we - // don't want the OS to send the coming NSLeftMouseUp event to NSApp - // via the window server, but we do want our ChildView to receive an - // NSLeftMouseUp event (and to send a Gecko NS_MOUSE_BUTTON_UP event - // to the corresponding nsChildView object). If our NSApp isn't - // active when it receives the coming NSLeftMouseUp via the window - // server, our app will (in effect) become partially activated, - // which has strange side effects: For example, if another app's - // window had the focus, that window will lose the focus and the - // other app's main menu will be completely disabled (though it will - // continue to be displayed). - // A side effect of not allowing the coming NSLeftMouseUp event to be - // sent to NSApp via the window server is that our custom context - // menus will roll up whenever the user left-clicks on them, whether - // or not the left-click hit an active menu item. This is how native - // context menus behave, but wasn't how our custom context menus - // behaved previously (on the trunk or e.g. in Firefox 2.0.0.4). - // If our ChildView's corresponding nsChildView object doesn't - // dispatch an NS_MOUSE_BUTTON_UP event, none of our active menu items - // will "work" on an NSLeftMouseUp. - NSEvent *newEvent = [NSEvent mouseEventWithType:NSLeftMouseUp - location:windowLocation - modifierFlags:nsCocoaUtils::GetCocoaEventModifierFlags(anEvent) - timestamp:GetCurrentEventTime() - windowNumber:[self windowNumber] - context:nil - eventNumber:0 - clickCount:1 - pressure:0.0]; - [target mouseUp:newEvent]; - RollUpPopups(); - } else { - // If our NSApp isn't active and we're not a context menu (i.e. if - // we're an ordinary popup window), activate us before sending the - // event to its target. This prevents us from being used in the - // background, and resolves bmo bug 434097 (another app focus - // wierdness bug). - [NSApp activateIgnoringOtherApps:YES]; - [target mouseDown:anEvent]; - } - break; case NSLeftMouseUp: [target mouseUp:anEvent]; break; From 525c8d6cd3eb1be91bd8e32170b905297427aa4c Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 23:00:59 +0100 Subject: [PATCH 168/179] Bug 527657 - Send the events we capture in our EventMonitorHandler actually into our app. This happened automatically when we built with the 10.4 SDK. r=josh --HG-- extra : rebase_source : 8bb8e8ec940cf13201fa524670f51e14ae3da7d7 --- widget/src/cocoa/nsToolkit.mm | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/widget/src/cocoa/nsToolkit.mm b/widget/src/cocoa/nsToolkit.mm index 64dcd2f25734..b9b9b68b17a3 100644 --- a/widget/src/cocoa/nsToolkit.mm +++ b/widget/src/cocoa/nsToolkit.mm @@ -192,10 +192,17 @@ nsToolkit::RemoveSleepWakeNotifcations() NS_OBJC_END_TRY_ABORT_BLOCK; } -// We shouldn't do anything here. See RegisterForAllProcessMouseEvents() for -// the reason why. +// This is the callback used in RegisterForAllProcessMouseEvents. static OSStatus EventMonitorHandler(EventHandlerCallRef aCaller, EventRef aEvent, void* aRefcon) { + // Up to Mac OS 10.4 (or when building with the 10.4 SDK), installing a Carbon + // event handler like this one caused the OS to post the equivalent Cocoa + // events to [NSApp sendEvent:]. When using the 10.5 SDK, this doesn't happen + // any more, so we need to do it manually. +#ifdef NS_LEOPARD_AND_LATER + [NSApp sendEvent:[NSEvent eventWithEventRef:aEvent]]; +#endif // NS_LEOPARD_AND_LATER + return eventNotHandledErr; } @@ -265,16 +272,6 @@ nsToolkit::RegisterForAllProcessMouseEvents() return; } if (!mEventMonitorHandler) { - // Installing a handler for particular Carbon events causes the OS to post - // equivalent Cocoa events to the browser's event stream (the one that - // passes through [NSApp sendEvent:]). For this reason installing a - // handler for kEventMouseMoved fixes bmo bug 368077, even though our - // handler does nothing on mouse-moved events. (Actually it's more - // accurate to say that the OS (working in a different process) sends - // events to the window server, from which the OS (acting in the browser's - // process on its behalf) grabs them and turns them into both Carbon - // events (which get fed to our handler) and Cocoa events (which get fed - // to [NSApp sendEvent:]).) EventTypeSpec kEvents[] = {{kEventClassMouse, kEventMouseMoved}}; InstallEventHandler(GetEventMonitorTarget(), EventMonitorHandler, GetEventTypeCount(kEvents), kEvents, 0, From e160d9bd93b1505599fd67db4bdaa23fa67eb9fa Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 23:01:38 +0100 Subject: [PATCH 169/179] Bug 528719 - When rendering popup buttons, use the open attribute to determine whether the control is highlighted, not the mousedown state. r=josh --HG-- extra : rebase_source : 5a40a0caa7bda9c32972dac4585db6adbb3e1444 --- widget/src/cocoa/nsNativeThemeCocoa.mm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/widget/src/cocoa/nsNativeThemeCocoa.mm b/widget/src/cocoa/nsNativeThemeCocoa.mm index d6428d54fed6..ee8401aa63f5 100644 --- a/widget/src/cocoa/nsNativeThemeCocoa.mm +++ b/widget/src/cocoa/nsNativeThemeCocoa.mm @@ -972,7 +972,7 @@ nsNativeThemeCocoa::DrawDropdown(CGContextRef cgContext, const HIRect& inBoxRect [cell setEnabled:!IsDisabled(aFrame)]; [cell setShowsFirstResponder:(IsFocused(aFrame) || (inState & NS_EVENT_STATE_FOCUS))]; - [cell setHighlighted:((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))]; + [cell setHighlighted:IsOpenButton(aFrame)]; [cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] : NSClearControlTint)]; const CellRenderSettings& settings = isEditable ? editableMenulistSettings : dropdownSettings; @@ -2365,7 +2365,8 @@ nsNativeThemeCocoa::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType, aAttribute == nsWidgetAtoms::sortdirection || aAttribute == nsWidgetAtoms::focused || aAttribute == nsWidgetAtoms::_default || - aAttribute == nsWidgetAtoms::step) + aAttribute == nsWidgetAtoms::step || + aAttribute == nsWidgetAtoms::open) *aShouldRepaint = PR_TRUE; } From 49ae0e4f923e0e7a8cc1da0dfafc5ac69d196a75 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 23:02:13 +0100 Subject: [PATCH 170/179] Bug 534184 - Disable smooth scrolling in menus. r=Enn --HG-- extra : rebase_source : 0b56bfc73798fbe9b8765ea93641f4c9ce10120d --- browser/components/places/content/menu.xml | 3 ++- toolkit/content/widgets/popup.xml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/browser/components/places/content/menu.xml b/browser/components/places/content/menu.xml index 96d47393f8fc..3a64d2013caa 100644 --- a/browser/components/places/content/menu.xml +++ b/browser/components/places/content/menu.xml @@ -53,7 +53,8 @@ - + diff --git a/toolkit/content/widgets/popup.xml b/toolkit/content/widgets/popup.xml index 753778c2a9cd..6ec8d77b4762 100644 --- a/toolkit/content/widgets/popup.xml +++ b/toolkit/content/widgets/popup.xml @@ -158,7 +158,8 @@ extends="chrome://global/content/bindings/popup.xml#popup-base"> - + From 3e1b2b0a3c435e99512fae6358714cb3d51fb2a4 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 23:03:31 +0100 Subject: [PATCH 171/179] Bug 534183 - Autorepeatbuttons in menus shouldn't have any initial delay. r=Enn --HG-- extra : rebase_source : a28ce171cfb0bca7070b8f0bfdf0c7da446908d5 --- layout/xul/base/src/nsRepeatService.cpp | 13 +++---------- layout/xul/base/src/nsRepeatService.h | 11 ++++++++++- layout/xul/base/src/nsScrollBoxFrame.cpp | 2 +- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/layout/xul/base/src/nsRepeatService.cpp b/layout/xul/base/src/nsRepeatService.cpp index 4f235cb036d3..1eaa00b09496 100644 --- a/layout/xul/base/src/nsRepeatService.cpp +++ b/layout/xul/base/src/nsRepeatService.cpp @@ -45,14 +45,6 @@ #include "nsRepeatService.h" #include "nsIServiceManager.h" -#ifdef XP_MACOSX -#define INITAL_REPEAT_DELAY 250 -#define REPEAT_DELAY 25 -#else -#define INITAL_REPEAT_DELAY 250 -#define REPEAT_DELAY 50 -#endif - nsRepeatService* nsRepeatService::gInstance = nsnull; nsRepeatService::nsRepeatService() @@ -81,7 +73,8 @@ nsRepeatService::Shutdown() NS_IF_RELEASE(gInstance); } -void nsRepeatService::Start(Callback aCallback, void* aCallbackData) +void nsRepeatService::Start(Callback aCallback, void* aCallbackData, + PRUint32 aInitialDelay) { NS_PRECONDITION(aCallback != nsnull, "null ptr"); @@ -91,7 +84,7 @@ void nsRepeatService::Start(Callback aCallback, void* aCallbackData) mRepeatTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); if (NS_SUCCEEDED(rv)) { - mRepeatTimer->InitWithCallback(this, INITAL_REPEAT_DELAY, nsITimer::TYPE_ONE_SHOT); + mRepeatTimer->InitWithCallback(this, aInitialDelay, nsITimer::TYPE_ONE_SHOT); } } diff --git a/layout/xul/base/src/nsRepeatService.h b/layout/xul/base/src/nsRepeatService.h index 75f922f6cd74..3330587ead4c 100644 --- a/layout/xul/base/src/nsRepeatService.h +++ b/layout/xul/base/src/nsRepeatService.h @@ -44,6 +44,14 @@ #include "nsCOMPtr.h" #include "nsITimer.h" +#define INITAL_REPEAT_DELAY 250 + +#ifdef XP_MACOSX +#define REPEAT_DELAY 25 +#else +#define REPEAT_DELAY 50 +#endif + class nsITimer; class nsRepeatService : public nsITimerCallback @@ -57,7 +65,8 @@ public: // Start dispatching timer events to the callback. There is no memory // management of aData here; it is the caller's responsibility to call // Stop() before aData's memory is released. - void Start(Callback aCallback, void* aData); + void Start(Callback aCallback, void* aData, + PRUint32 aInitialDelay = INITAL_REPEAT_DELAY); // Stop dispatching timer events to the callback. If the repeat service // is not currently configured with the given callback and data, this // is just ignored. diff --git a/layout/xul/base/src/nsScrollBoxFrame.cpp b/layout/xul/base/src/nsScrollBoxFrame.cpp index 79c75756457a..690746bce626 100644 --- a/layout/xul/base/src/nsScrollBoxFrame.cpp +++ b/layout/xul/base/src/nsScrollBoxFrame.cpp @@ -77,7 +77,7 @@ protected: nsButtonBoxFrame(aPresShell, aContext) {} void StartRepeat() { - nsRepeatService::GetInstance()->Start(Notify, this); + nsRepeatService::GetInstance()->Start(Notify, this, 0); } void StopRepeat() { nsRepeatService::GetInstance()->Stop(Notify, this); From a294c94009a6498abb8484413846d5bcbb0502dc Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 23:04:02 +0100 Subject: [PATCH 172/179] Bug 534172 - Tab list should be cleared at popuphidden, not at popuphiding. r=Enn --HG-- extra : rebase_source : e201ed7db24d6f862575809756e68a4d551393db --- browser/base/content/tabbrowser.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 5dff03a893aa..60d5bf682fec 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -3398,7 +3398,7 @@ this._updateTabsVisibilityStatus(); ]]> - + Date: Fri, 11 Dec 2009 23:05:21 +0100 Subject: [PATCH 173/179] Bug 533208 - Only call [NSCursor hide/unhide] when cursor visibility actually changes, since these calls must be balanced. r=josh --HG-- extra : rebase_source : dfd1e28137a60ce51b44e319341fd0a1bc5bac32 --- widget/src/cocoa/nsCursorManager.mm | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/widget/src/cocoa/nsCursorManager.mm b/widget/src/cocoa/nsCursorManager.mm index b2d016689c31..a39c9009e74b 100644 --- a/widget/src/cocoa/nsCursorManager.mm +++ b/widget/src/cocoa/nsCursorManager.mm @@ -223,16 +223,18 @@ static NSArray* sSpinCursorFrames = nil; if (aCursor != mCurrentCursor || ![currentCursor isSet]) { [currentCursor unset]; [[self getCursor: aCursor] set]; - - mCurrentCursor = aCursor; } - if (mCurrentCursor == eCursor_none) { - [NSCursor hide]; - } else { - [NSCursor unhide]; + if (mCurrentCursor != aCursor) { + if (aCursor == eCursor_none) { + [NSCursor hide]; + } else if (mCurrentCursor == eCursor_none) { + [NSCursor unhide]; + } } + mCurrentCursor = aCursor; + NS_OBJC_END_TRY_ABORT_BLOCK; } From 0e4264c6470a9526db329b527bdc12f4b562a926 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 11 Dec 2009 23:05:56 +0100 Subject: [PATCH 174/179] Bug 533913 - Invalid selectors in pinstripe places.css. r=dao --HG-- extra : rebase_source : 9def3eccc8f0d8d5ef1f8c97eb6d9bb0edfb0e18 --- browser/themes/pinstripe/browser/places/places.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/themes/pinstripe/browser/places/places.css b/browser/themes/pinstripe/browser/places/places.css index d79a8ac7482a..5b77f20193b0 100644 --- a/browser/themes/pinstripe/browser/places/places.css +++ b/browser/themes/pinstripe/browser/places/places.css @@ -45,12 +45,12 @@ border-top: @sidebarItemFocusedBorderTop@; } -.sidebar-placesTreechildren::-moz-tree-row(selected):-moz-system-metric(mac-graphite-theme) { +.sidebar-placesTreechildren:-moz-system-metric(mac-graphite-theme)::-moz-tree-row(selected) { background: @sidebarItemGraphiteBackground@; border-top: @sidebarItemGraphiteBorderTop@; } -.sidebar-placesTreechildren::-moz-tree-row(selected,focus):-moz-system-metric(mac-graphite-theme) { +.sidebar-placesTreechildren:-moz-system-metric(mac-graphite-theme)::-moz-tree-row(selected,focus) { background: @sidebarItemGraphiteFocusedBackground@; border-top: @sidebarItemGraphiteFocusedBorderTop@; } From 7f13850dc8146c336bad4fb8d310a11640ff2f50 Mon Sep 17 00:00:00 2001 From: Benjamin Frisch Date: Fri, 11 Dec 2009 23:09:11 +0100 Subject: [PATCH 175/179] Bug 418774 - Make -moz-image-region work in native Mac menus. r=mstange, r=josh --HG-- extra : rebase_source : b877bce6bf55cbbf82711ebb2e5955fccd482edc --- widget/src/cocoa/nsMenuItemIconX.h | 1 + widget/src/cocoa/nsMenuItemIconX.mm | 157 +++++++++++++++++++++++----- 2 files changed, 133 insertions(+), 25 deletions(-) diff --git a/widget/src/cocoa/nsMenuItemIconX.h b/widget/src/cocoa/nsMenuItemIconX.h index ee203ab5b353..2b42438367ba 100644 --- a/widget/src/cocoa/nsMenuItemIconX.h +++ b/widget/src/cocoa/nsMenuItemIconX.h @@ -89,6 +89,7 @@ protected: nsCOMPtr mContent; nsCOMPtr mIconRequest; nsMenuObjectX* mMenuObject; // [weak] + nsIntRect mImageRegionRect; PRPackedBool mLoadedIcon; PRPackedBool mSetIcon; NSMenuItem* mNativeMenuItem; // [weak] diff --git a/widget/src/cocoa/nsMenuItemIconX.mm b/widget/src/cocoa/nsMenuItemIconX.mm index 353eb85cc8e8..d67dc6799b76 100644 --- a/widget/src/cocoa/nsMenuItemIconX.mm +++ b/widget/src/cocoa/nsMenuItemIconX.mm @@ -21,6 +21,7 @@ * Contributor(s): * Mark Mentovai (Original Author) * Josh Aas + * Benjamin Frisch * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -54,6 +55,7 @@ #include "nsIDOMCSSStyleDeclaration.h" #include "nsIDOMCSSValue.h" #include "nsIDOMCSSPrimitiveValue.h" +#include "nsIDOMRect.h" #include "nsThreadUtils.h" #include "nsToolkit.h" #include "nsNetUtil.h" @@ -77,6 +79,8 @@ PRAllocCGFree(void* aInfo, const void* aData, size_t aSize) { free((void*)aData); } +typedef nsresult (nsIDOMRect::*GetRectSideMethod)(nsIDOMCSSPrimitiveValue**); + NS_IMPL_ISUPPORTS2(nsMenuItemIconX, imgIContainerObserver, imgIDecoderObserver) nsMenuItemIconX::nsMenuItemIconX(nsMenuObjectX* aMenuItem, @@ -131,11 +135,40 @@ nsMenuItemIconX::SetupIcon() return NS_OK; } - return LoadIcon(iconURI); + rv = LoadIcon(iconURI); + if (NS_FAILED(rv)) { + // There is no icon for this menu item, as an error occured while loading it. + // An icon might have been set earlier or the place holder icon may have + // been set. Clear it. + [mNativeMenuItem setImage:nil]; + } + return rv; NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } +static PRInt32 +GetDOMRectSide(nsIDOMRect* aRect, GetRectSideMethod aMethod) +{ + nsCOMPtr dimensionValue; + (aRect->*aMethod)(getter_AddRefs(dimensionValue)); + if (!dimensionValue) + return -1; + + PRUint16 primitiveType; + nsresult rv = dimensionValue->GetPrimitiveType(&primitiveType); + if (NS_FAILED(rv) || primitiveType != nsIDOMCSSPrimitiveValue::CSS_PX) + return -1; + + float dimension = 0; + rv = dimensionValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_PX, + &dimension); + if (NS_FAILED(rv)) + return -1; + + return NSToIntRound(dimension); +} + nsresult nsMenuItemIconX::GetIconURI(nsIURI** aIconURI) { @@ -164,6 +197,10 @@ nsMenuItemIconX::GetIconURI(nsIURI** aIconURI) imageURIString); nsresult rv; + nsCOMPtr cssValue; + nsCOMPtr cssStyleDecl; + nsCOMPtr primitiveValue; + PRUint16 primitiveType; if (!hasImageAttr) { // If the content node has no "image" attribute, get the // "list-style-image" property from CSS. @@ -181,23 +218,19 @@ nsMenuItemIconX::GetIconURI(nsIURI** aIconURI) nsCOMPtr domElement = do_QueryInterface(mContent); if (!domElement) return NS_ERROR_FAILURE; - nsCOMPtr cssStyleDecl; nsAutoString empty; rv = domViewCSS->GetComputedStyle(domElement, empty, getter_AddRefs(cssStyleDecl)); if (NS_FAILED(rv)) return rv; NS_NAMED_LITERAL_STRING(listStyleImage, "list-style-image"); - nsCOMPtr cssValue; rv = cssStyleDecl->GetPropertyCSSValue(listStyleImage, getter_AddRefs(cssValue)); if (NS_FAILED(rv)) return rv; - nsCOMPtr primitiveValue = - do_QueryInterface(cssValue); + primitiveValue = do_QueryInterface(cssValue); if (!primitiveValue) return NS_ERROR_FAILURE; - PRUint16 primitiveType; rv = primitiveValue->GetPrimitiveType(&primitiveType); if (NS_FAILED(rv)) return rv; if (primitiveType != nsIDOMCSSPrimitiveValue::CSS_URI) @@ -207,6 +240,11 @@ nsMenuItemIconX::GetIconURI(nsIURI** aIconURI) if (NS_FAILED(rv)) return rv; } + // Empty the mImageRegionRect initially as the image region CSS could + // have been changed and now have an error or have been removed since the + // last GetIconURI call. + mImageRegionRect.Empty(); + // If this menu item shouldn't have an icon, the string will be empty, // and NS_NewURI will fail. nsCOMPtr iconURI; @@ -215,6 +253,44 @@ nsMenuItemIconX::GetIconURI(nsIURI** aIconURI) *aIconURI = iconURI; NS_ADDREF(*aIconURI); + + if (!hasImageAttr) { + // Check if the icon has a specified image region so that it can be + // cropped appropriately before being displayed. + NS_NAMED_LITERAL_STRING(imageRegion, "-moz-image-region"); + rv = cssStyleDecl->GetPropertyCSSValue(imageRegion, + getter_AddRefs(cssValue)); + // Just return NS_OK if there if there is a failure due to no + // moz-image region specified so the whole icon will be drawn anyway. + if (NS_FAILED(rv)) return NS_OK; + + primitiveValue = do_QueryInterface(cssValue); + if (!primitiveValue) return NS_OK; + + rv = primitiveValue->GetPrimitiveType(&primitiveType); + if (NS_FAILED(rv)) return NS_OK; + if (primitiveType != nsIDOMCSSPrimitiveValue::CSS_RECT) + return NS_OK; + + nsCOMPtr imageRegionRect; + rv = primitiveValue->GetRectValue(getter_AddRefs(imageRegionRect)); + if (NS_FAILED(rv)) return NS_OK; + + if (imageRegionRect) { + // Return NS_ERROR_FAILURE if the image region is invalid so the image + // is not drawn, and behavior is similar to XUL menus. + PRInt32 bottom = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetBottom); + PRInt32 right = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetRight); + PRInt32 top = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetTop); + PRInt32 left = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetLeft); + + if (top < 0 || left < 0 || bottom <= top || right <= left) + return NS_ERROR_FAILURE; + + mImageRegionRect.SetRect(left, top, right - left, bottom - top); + } + } + return NS_OK; } @@ -344,46 +420,77 @@ nsMenuItemIconX::OnStopFrame(imgIRequest* aRequest, nsCOMPtr imageContainer; aRequest->GetImage(getter_AddRefs(imageContainer)); - if (!imageContainer) + if (!imageContainer) { + [mNativeMenuItem setImage:nil]; return NS_ERROR_FAILURE; + } nsRefPtr image; nsresult rv = imageContainer->CopyFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_NONE, getter_AddRefs(image)); - if (NS_FAILED(rv) || !image) + if (NS_FAILED(rv) || !image) { + [mNativeMenuItem setImage:nil]; return NS_ERROR_FAILURE; + } - PRInt32 height = image->Height(); - PRInt32 stride = image->Stride(); - PRInt32 width = image->Width(); - PRUint32 imageLength = ((stride * height) / 4); - if ((stride % 4 != 0) || (height < 1) || (width < 1)) + PRInt32 origHeight = image->Height(); + PRInt32 origStride = image->Stride(); + PRInt32 origWidth = image->Width(); + if ((origStride % 4 != 0) || (origHeight < 1) || (origWidth < 1)) { + [mNativeMenuItem setImage:nil]; return NS_ERROR_FAILURE; + } PRUint32* imageData = (PRUint32*)image->Data(); - PRUint32* reorderedData = (PRUint32*)malloc(height * stride); - if (!reorderedData) - return NS_ERROR_OUT_OF_MEMORY; + // If the image region is invalid, don't draw the image to almost match + // the behavior of other platforms. + if (!mImageRegionRect.IsEmpty() && + (mImageRegionRect.XMost() > origWidth || + mImageRegionRect.YMost() > origHeight)) { + [mNativeMenuItem setImage:nil]; + return NS_ERROR_FAILURE; + } - // We have to reorder data to have alpha last because only Tiger can handle - // alpha being first. Also the data must always be big endian (silly). - - for (PRUint32 i = 0; i < imageLength; i++) { - PRUint32 pixel = imageData[i]; - reorderedData[i] = CFSwapInt32HostToBig((pixel << 8) | (pixel >> 24)); + if (mImageRegionRect.IsEmpty()) { + mImageRegionRect.SetRect(0, 0, origWidth, origHeight); + } + + PRInt32 newStride = mImageRegionRect.width * sizeof(PRUint32); + PRInt32 imageLength = mImageRegionRect.height * mImageRegionRect.width; + + PRUint32* reorderedData = (PRUint32*)malloc(imageLength * sizeof(PRUint32)); + if (!reorderedData) { + [mNativeMenuItem setImage:nil]; + return NS_ERROR_OUT_OF_MEMORY; + } + + // We have to clip the data to the image region and reorder the data to have + // alpha last because only Tiger can handle alpha being first. Also the data + // must always be big endian (silly). + for (PRInt32 y = 0; y < mImageRegionRect.height; y++) { + PRInt32 srcLine = (mImageRegionRect.y + y) * (origStride/4); + PRInt32 dstLine = y * mImageRegionRect.width; + for (PRInt32 x = 0; x < mImageRegionRect.width; x++) { + PRUint32 pixel = imageData[srcLine + x + mImageRegionRect.x]; + reorderedData[dstLine + x] = + CFSwapInt32HostToBig((pixel << 8) | (pixel >> 24)); + } } CGDataProviderRef provider = ::CGDataProviderCreateWithData(NULL, reorderedData, imageLength, PRAllocCGFree); if (!provider) { free(reorderedData); + [mNativeMenuItem setImage:nil]; return NS_ERROR_FAILURE; } CGColorSpaceRef colorSpace = ::CGColorSpaceCreateDeviceRGB(); - CGImageRef cgImage = ::CGImageCreate(width, height, 8, 32, stride, colorSpace, - kCGImageAlphaPremultipliedLast, provider, - NULL, true, kCGRenderingIntentDefault); + CGImageRef cgImage = ::CGImageCreate(mImageRegionRect.width, + mImageRegionRect.height, 8, 32, newStride, + colorSpace, kCGImageAlphaPremultipliedLast, + provider, NULL, true, + kCGRenderingIntentDefault); ::CGDataProviderRelease(provider); // The image may not be the right size for a menu icon (16x16). From 0d6afa5cd52438f4f95c92eb87dc013706e46d74 Mon Sep 17 00:00:00 2001 From: "lordpixel@mac.com" Date: Fri, 11 Dec 2009 23:17:27 +0100 Subject: [PATCH 176/179] Bug 489734 - Implement cursor values "alias", "context-menu", "copy", "not-allowed" and "no-drop" on Mac Os 10.6. r=josh --HG-- extra : rebase_source : da270898f5250ffeaf0d5f1225bd81bd63d1dafd --- widget/src/cocoa/nsCursorManager.mm | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/widget/src/cocoa/nsCursorManager.mm b/widget/src/cocoa/nsCursorManager.mm index a39c9009e74b..db4707471bb3 100644 --- a/widget/src/cocoa/nsCursorManager.mm +++ b/widget/src/cocoa/nsCursorManager.mm @@ -107,6 +107,7 @@ static NSArray* sSpinCursorFrames = nil; switch(aCursor) { + SEL cursorSelector; case eCursor_standard: return [nsMacCursor cursorWithCursor: [NSCursor arrowCursor]]; case eCursor_wait: @@ -123,12 +124,20 @@ static NSArray* sSpinCursorFrames = nil; case eCursor_help: return [nsMacCursor cursorWithImageNamed: @"help" hotSpot: NSMakePoint(1,1)]; case eCursor_copy: - return [nsMacCursor cursorWithCursor: [NSCursor arrowCursor]]; //XXX needs real implementation + cursorSelector = @selector(dragCopyCursor); + return [nsMacCursor cursorWithCursor: [NSCursor respondsToSelector: cursorSelector] ? + [NSCursor performSelector: cursorSelector] : + [NSCursor arrowCursor]]; case eCursor_alias: - return [nsMacCursor cursorWithCursor: [NSCursor arrowCursor]]; //XXX needs real implementation + cursorSelector = @selector(dragLinkCursor); + return [nsMacCursor cursorWithCursor: [NSCursor respondsToSelector: cursorSelector] ? + [NSCursor performSelector: cursorSelector] : + [NSCursor arrowCursor]]; case eCursor_context_menu: - return [nsMacCursor cursorWithCursor: [NSCursor arrowCursor]]; //XXX needs real implementation - + cursorSelector = @selector(contextualMenuCursor); + return [nsMacCursor cursorWithCursor: [NSCursor respondsToSelector: cursorSelector] ? + [NSCursor performSelector: cursorSelector] : + [NSCursor arrowCursor]]; case eCursor_cell: return [nsMacCursor cursorWithCursor: [NSCursor crosshairCursor]]; case eCursor_grab: @@ -145,8 +154,10 @@ static NSArray* sSpinCursorFrames = nil; return [nsMacCursor cursorWithCursor: [NSCursor openHandCursor]];; case eCursor_not_allowed: case eCursor_no_drop: - return [nsMacCursor cursorWithCursor: [NSCursor arrowCursor]]; //XXX needs real implementation - + cursorSelector = @selector(operationNotAllowedCursor); + return [nsMacCursor cursorWithCursor: [NSCursor respondsToSelector: cursorSelector] ? + [NSCursor performSelector: cursorSelector] : + [NSCursor arrowCursor]]; // Resize Cursors: //North case eCursor_n_resize: From 654d4b36b97559acaca5238700c64e839c4b8390 Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Sat, 12 Dec 2009 14:37:20 +0000 Subject: [PATCH 177/179] Bug 534216 - Text in anchor tags not placed correctly if viewBox present. r=roc --- layout/reftests/svg/reftest.list | 1 + layout/reftests/svg/text-in-link-02-ref.svg | 12 ++++++++++++ layout/reftests/svg/text-in-link-02.svg | 11 +++++++++++ layout/svg/base/src/nsSVGTextFrame.cpp | 4 ++-- 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 layout/reftests/svg/text-in-link-02-ref.svg create mode 100644 layout/reftests/svg/text-in-link-02.svg diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list index 630802d87a4e..17d67c7981b4 100644 --- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -125,6 +125,7 @@ random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == text-font-weight-01.svg text-font-weigh == switch-01.svg pass.svg == text-gradient-01.svg text-gradient-01-ref.svg == text-in-link-01.svg text-in-link-01-ref.svg +== text-in-link-02.svg text-in-link-02-ref.svg == text-scale-01.svg text-scale-01-ref.svg == text-style-01a.svg text-style-01-ref.svg == text-style-01b.svg text-style-01-ref.svg diff --git a/layout/reftests/svg/text-in-link-02-ref.svg b/layout/reftests/svg/text-in-link-02-ref.svg new file mode 100644 index 000000000000..1ffb7356bb48 --- /dev/null +++ b/layout/reftests/svg/text-in-link-02-ref.svg @@ -0,0 +1,12 @@ + + + Reference to check that links with viewBoxes work + + + + AAAAABBBBBCCCCCDDDDD + + diff --git a/layout/reftests/svg/text-in-link-02.svg b/layout/reftests/svg/text-in-link-02.svg new file mode 100644 index 000000000000..ac86614b0cf2 --- /dev/null +++ b/layout/reftests/svg/text-in-link-02.svg @@ -0,0 +1,11 @@ + + + Testcase to check that links with viewBoxes work + + + + AAAAABBBBBCCCCCDDDDD + diff --git a/layout/svg/base/src/nsSVGTextFrame.cpp b/layout/svg/base/src/nsSVGTextFrame.cpp index 03b838aefe59..64ae328fb435 100644 --- a/layout/svg/base/src/nsSVGTextFrame.cpp +++ b/layout/svg/base/src/nsSVGTextFrame.cpp @@ -189,6 +189,8 @@ nsSVGTextFrame::NotifySVGChanged(PRUint32 aFlags) mCanvasTM = nsnull; } + nsSVGTextFrameBase::NotifySVGChanged(aFlags); + if (aFlags & COORD_CONTEXT_CHANGED) { // If we are positioned using percentage values we need to update our // position whenever our viewport's dimensions change. @@ -198,8 +200,6 @@ nsSVGTextFrame::NotifySVGChanged(PRUint32 aFlags) // may not be worth it as we might need to check each glyph NotifyGlyphMetricsChange(); } - - nsSVGTextFrameBase::NotifySVGChanged(aFlags); } NS_IMETHODIMP From 7fc3cdc6a92cc068f234698adae244ea53283168 Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Sat, 12 Dec 2009 14:37:22 +0000 Subject: [PATCH 178/179] Bug 467477 - View Source should linkify xlink:href. r=mrbkap --- parser/htmlparser/src/nsViewSourceHTML.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/parser/htmlparser/src/nsViewSourceHTML.cpp b/parser/htmlparser/src/nsViewSourceHTML.cpp index b9a4be2b3663..5f905994c511 100644 --- a/parser/htmlparser/src/nsViewSourceHTML.cpp +++ b/parser/htmlparser/src/nsViewSourceHTML.cpp @@ -948,6 +948,8 @@ PRBool CViewSourceHTML::IsUrlAttribute(const nsAString& tagName, PRBool isHref = trimmedAttrName.LowerCaseEqualsLiteral("href"); PRBool isSrc = !isHref && trimmedAttrName.LowerCaseEqualsLiteral("src"); + PRBool isXLink = !isHref && !isSrc && + mDocType == eXML && trimmedAttrName.EqualsLiteral("xlink:href"); // If this is the HREF attribute of a BASE element, then update the base URI. // This doesn't feel like the ideal place for this, but the alternatives don't @@ -959,7 +961,7 @@ PRBool CViewSourceHTML::IsUrlAttribute(const nsAString& tagName, SetBaseURI(expandedBaseSpec); } - return isHref || isSrc; + return isHref || isSrc || isXLink; } void CViewSourceHTML::WriteHrefAttribute(nsTokenAllocator* allocator, From 000f8c948b2bd79c76af4577c5a12404f0ec591d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Sat, 12 Dec 2009 18:22:13 +0100 Subject: [PATCH 179/179] Bug 531519 - getBrowserState sometimes returns two entries for one window. r=zeniko --- browser/components/sessionstore/src/nsSessionStore.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/browser/components/sessionstore/src/nsSessionStore.js b/browser/components/sessionstore/src/nsSessionStore.js index 2e0294012221..bec99c062a61 100644 --- a/browser/components/sessionstore/src/nsSessionStore.js +++ b/browser/components/sessionstore/src/nsSessionStore.js @@ -587,7 +587,7 @@ SessionStoreService.prototype = { // ignore non-browser windows and windows opened while shutting down if (aWindow.document.documentElement.getAttribute("windowtype") != "navigator:browser" || - this._loadState == STATE_QUITTING) + this._loadState == STATE_QUITTING) return; // assign it a unique identifier (timestamp) @@ -595,6 +595,8 @@ SessionStoreService.prototype = { // and create its data object this._windows[aWindow.__SSi] = { tabs: [], selected: 0, _closedTabs: [] }; + if (!this._isWindowLoaded(aWindow)) + this._windows[aWindow.__SSi]._restoring = true; if (!aWindow.toolbar.visible) this._windows[aWindow.__SSi].isPopup = true; @@ -1742,6 +1744,8 @@ SessionStoreService.prototype = { var nonPopupCount = 0; var ix; for (ix in this._windows) { + if (this._windows[ix]._restoring) // window data is still in _statesToRestore + continue; total.push(this._windows[ix]); windows.push(ix); if (!this._windows[ix].isPopup) @@ -2033,6 +2037,7 @@ SessionStoreService.prototype = { // from now on, the data will come from the actual window delete this._statesToRestore[aWindow.__SS_restoreID]; delete aWindow.__SS_restoreID; + delete this._windows[aWindow.__SSi]._restoring; } // helper hash for ensuring unique frame IDs