📄 jsxml.c
字号:
goto fail; } /* * Enforce "Well-formedness constraint: Unique Att Spec", part 2: * this time checking local name and namespace URI. */ for (j = 0; j < i; j++) { attrj = XMLARRAY_MEMBER(&xml->xml_attrs, j, JSXML); attrjqn = attrj->name; if (js_EqualStrings(attrjqn->uri, qn->uri) && js_EqualStrings(attrjqn->localName, qn->localName)) { js_ReportCompileErrorNumber(cx, pn2, JSREPORT_PN | JSREPORT_ERROR, JSMSG_DUPLICATE_XML_ATTR, js_ValueToPrintableString(cx, ATOM_KEY(pn2->pn_atom))); goto fail; } } pn2 = pn2->pn_next; JS_ASSERT(pn2); JS_ASSERT(pn2->pn_type == TOK_XMLATTR); attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE); if (!attr) goto fail; XMLARRAY_SET_MEMBER(&xml->xml_attrs, i, attr); attr->parent = xml; attr->name = qn; attr->xml_value = ATOM_TO_STRING(pn2->pn_atom); } /* Point tag closes its own namespace scope. */ if (pn->pn_type == TOK_XMLPTAGC) XMLARRAY_TRUNCATE(cx, inScopeNSes, length); break; case TOK_XMLSPACE: case TOK_XMLTEXT: case TOK_XMLCDATA: case TOK_XMLCOMMENT: case TOK_XMLPI: str = ATOM_TO_STRING(pn->pn_atom); qn = NULL; if (pn->pn_type == TOK_XMLCOMMENT) { if (flags & XSF_IGNORE_COMMENTS) goto skip_child; xml_class = JSXML_CLASS_COMMENT; } else if (pn->pn_type == TOK_XMLPI) { if (IS_XML(str)) { js_ReportCompileErrorNumber(cx, pn, JSREPORT_PN | JSREPORT_ERROR, JSMSG_RESERVED_ID, js_ValueToPrintableString(cx, STRING_TO_JSVAL(str))); goto fail; } if (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS) goto skip_child; qn = ParseNodeToQName(cx, pn, inScopeNSes, JS_FALSE); if (!qn) goto fail; str = pn->pn_atom2 ? ATOM_TO_STRING(pn->pn_atom2) : cx->runtime->emptyString; xml_class = JSXML_CLASS_PROCESSING_INSTRUCTION; } else { /* CDATA section content, or element text. */ xml_class = JSXML_CLASS_TEXT; } xml = js_NewXML(cx, xml_class); if (!xml) goto fail; xml->name = qn; if (pn->pn_type == TOK_XMLSPACE) xml->xml_flags |= XMLF_WHITESPACE_TEXT; xml->xml_value = str; break; default: goto syntax; } js_LeaveLocalRootScopeWithResult(cx, (jsval) xml); if ((flags & XSF_PRECOMPILED_ROOT) && !js_GetXMLObject(cx, xml)) return NULL; return xml;skip_child: js_LeaveLocalRootScope(cx); return PN2X_SKIP_CHILD;#undef PN2X_SKIP_CHILDsyntax: js_ReportCompileErrorNumber(cx, pn, JSREPORT_PN | JSREPORT_ERROR, JSMSG_BAD_XML_MARKUP);fail: js_LeaveLocalRootScope(cx); return NULL;}/* * XML helper, object-ops, and library functions. We start with the helpers, * in ECMA-357 order, but merging XML (9.1) and XMLList (9.2) helpers. */static JSBoolGetXMLSetting(JSContext *cx, const char *name, jsval *vp){ jsval v; if (!js_FindClassObject(cx, NULL, INT_TO_JSID(JSProto_XML), &v)) return JS_FALSE; if (!VALUE_IS_FUNCTION(cx, v)) { *vp = JSVAL_VOID; return JS_TRUE; } return JS_GetProperty(cx, JSVAL_TO_OBJECT(v), name, vp);}static JSBoolFillSettingsCache(JSContext *cx){ int i; const char *name; jsval v; JSBool isSet; /* Note: XML_PRETTY_INDENT is not a boolean setting. */ for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) { name = xml_static_props[i].name; if (!GetXMLSetting(cx, name, &v) || !js_ValueToBoolean(cx, v, &isSet)) return JS_FALSE; if (isSet) cx->xmlSettingFlags |= JS_BIT(i); else cx->xmlSettingFlags &= ~JS_BIT(i); } cx->xmlSettingFlags |= XSF_CACHE_VALID; return JS_TRUE;}static JSBoolGetBooleanXMLSetting(JSContext *cx, const char *name, JSBool *bp){ int i; if (!(cx->xmlSettingFlags & XSF_CACHE_VALID) && !FillSettingsCache(cx)) return JS_FALSE; for (i = 0; xml_static_props[i].name; i++) { if (!strcmp(xml_static_props[i].name, name)) { *bp = (cx->xmlSettingFlags & JS_BIT(i)) != 0; return JS_TRUE; } } *bp = JS_FALSE; return JS_TRUE;}static JSBoolGetUint32XMLSetting(JSContext *cx, const char *name, uint32 *uip){ jsval v; return GetXMLSetting(cx, name, &v) && js_ValueToECMAUint32(cx, v, uip);}static JSBoolGetXMLSettingFlags(JSContext *cx, uintN *flagsp){ JSBool flag; /* Just get the first flag to validate the setting flags cache. */ if (!GetBooleanXMLSetting(cx, js_ignoreComments_str, &flag)) return JS_FALSE; *flagsp = cx->xmlSettingFlags; return JS_TRUE;}static JSXML *ParseXMLSource(JSContext *cx, JSString *src){ jsval nsval; JSXMLNamespace *ns; size_t urilen, srclen, length, offset, dstlen; jschar *chars; const jschar *srcp, *endp; void *mark; JSTokenStream *ts; uintN lineno; JSStackFrame *fp; JSOp op; JSParseNode *pn; JSXML *xml; JSXMLArray nsarray; uintN flags; static const char prefix[] = "<parent xmlns='"; static const char middle[] = "'>"; static const char suffix[] = "</parent>";#define constrlen(constr) (sizeof(constr) - 1) if (!js_GetDefaultXMLNamespace(cx, &nsval)) return NULL; ns = (JSXMLNamespace *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(nsval)); urilen = JSSTRING_LENGTH(ns->uri); srclen = JSSTRING_LENGTH(src); length = constrlen(prefix) + urilen + constrlen(middle) + srclen + constrlen(suffix); chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); if (!chars) return NULL; dstlen = length; js_InflateStringToBuffer(cx, prefix, constrlen(prefix), chars, &dstlen); offset = dstlen; js_strncpy(chars + offset, JSSTRING_CHARS(ns->uri), urilen); offset += urilen; dstlen = length - offset + 1; js_InflateStringToBuffer(cx, middle, constrlen(middle), chars + offset, &dstlen); offset += dstlen; srcp = JSSTRING_CHARS(src); js_strncpy(chars + offset, srcp, srclen); offset += srclen; dstlen = length - offset + 1; js_InflateStringToBuffer(cx, suffix, constrlen(suffix), chars + offset, &dstlen); chars [offset + dstlen] = 0; mark = JS_ARENA_MARK(&cx->tempPool); ts = js_NewBufferTokenStream(cx, chars, length); if (!ts) return NULL; for (fp = cx->fp; fp && !fp->pc; fp = fp->down) continue; if (fp) { op = (JSOp) *fp->pc; if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) { ts->filename = fp->script->filename; lineno = js_PCToLineNumber(cx, fp->script, fp->pc); for (endp = srcp + srclen; srcp < endp; srcp++) if (*srcp == '\n') --lineno; ts->lineno = lineno; } } JS_KEEP_ATOMS(cx->runtime); pn = js_ParseXMLTokenStream(cx, cx->fp->scopeChain, ts, JS_FALSE); xml = NULL; if (pn && XMLArrayInit(cx, &nsarray, 1)) { if (GetXMLSettingFlags(cx, &flags)) xml = ParseNodeToXML(cx, pn, &nsarray, flags); XMLArrayFinish(cx, &nsarray); } JS_UNKEEP_ATOMS(cx->runtime); JS_ARENA_RELEASE(&cx->tempPool, mark); JS_free(cx, chars); return xml;#undef constrlen}/* * Errata in 10.3.1, 10.4.1, and 13.4.4.24 (at least). * * 10.3.1 Step 6(a) fails to NOTE that implementations that do not enforce * the constraint: * * for all x belonging to XML: * x.[[InScopeNamespaces]] >= x.[[Parent]].[[InScopeNamespaces]] * * must union x.[[InScopeNamespaces]] into x[0].[[InScopeNamespaces]] here * (in new sub-step 6(a), renumbering the others to (b) and (c)). * * Same goes for 10.4.1 Step 7(a). * * In order for XML.prototype.namespaceDeclarations() to work correctly, the * default namespace thereby unioned into x[0].[[InScopeNamespaces]] must be * flagged as not declared, so that 13.4.4.24 Step 8(a) can exclude all such * undeclared namespaces associated with x not belonging to ancestorNS. */static JSXML *OrphanXMLChild(JSContext *cx, JSXML *xml, uint32 i){ JSXMLNamespace *ns; ns = XMLARRAY_MEMBER(&xml->xml_namespaces, 0, JSXMLNamespace); xml = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); if (!ns || !xml) return xml; if (xml->xml_class == JSXML_CLASS_ELEMENT) { if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns)) return NULL; ns->declared = JS_FALSE; } xml->parent = NULL; return xml;}static JSObject *ToXML(JSContext *cx, jsval v){ JSObject *obj; JSXML *xml; JSClass *clasp; JSString *str; uint32 length; if (JSVAL_IS_PRIMITIVE(v)) { if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) goto bad; } else { obj = JSVAL_TO_OBJECT(v); if (OBJECT_IS_XML(cx, obj)) { xml = (JSXML *) JS_GetPrivate(cx, obj); if (xml->xml_class == JSXML_CLASS_LIST) { if (xml->xml_kids.length != 1) goto bad; xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); if (xml) { JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST); return js_GetXMLObject(cx, xml); } } return obj; } clasp = OBJ_GET_CLASS(cx, obj); if (clasp->flags & JSCLASS_DOCUMENT_OBSERVER) { JS_ASSERT(0); } if (clasp != &js_StringClass && clasp != &js_NumberClass && clasp != &js_BooleanClass) { goto bad; } } str = js_ValueToString(cx, v); if (!str) return NULL; if (IS_EMPTY(str)) { length = 0;#ifdef __GNUC__ /* suppress bogus gcc warnings */ xml = NULL;#endif } else { xml = ParseXMLSource(cx, str); if (!xml) return NULL; length = JSXML_LENGTH(xml); } if (length == 0) { obj = js_NewXMLObject(cx, JSXML_CLASS_TEXT); if (!obj) return NULL; } else if (length == 1) { xml = OrphanXMLChild(cx, xml, 0); if (!xml) return NULL; obj = js_GetXMLObject(cx, xml); if (!obj) return NULL; } else { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SYNTAX_ERROR); return NULL; } return obj;bad: str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK, v, NULL); if (str) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_XML_CONVERSION, JS_GetStringBytes(str)); } return NULL;}static JSBoolAppend(JSContext *cx, JSXML *list, JSXML *kid);static JSObject *ToXMLList(JSContext *cx, jsval v){ JSObject *obj, *listobj; JSXML *xml, *list, *kid; JSClass *clasp; JSString *str; uint32 i, length; if (JSVAL_IS_PRIMITIVE(v)) { if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) goto bad; } else { obj = JSVAL_TO_OBJECT(v); if (OBJECT_IS_XML(cx, obj)) { xml = (JSXML *) JS_GetPrivate(cx, obj); if (xml->xml_class != JSXML_CLASS_LIST) { listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); if (!listobj) return NULL; list = (JSXML *) JS_GetPrivate(cx, listobj); if (!Append(cx, list, xml)) return NULL; return listobj; } return obj; } clasp = OBJ_GET_CLASS(cx, obj); if (clasp->flags & JSCLASS_DOCUMENT_OBSERVER) { JS_ASSERT(0); } if (clasp != &js_StringClass && clasp != &js_NumberClass &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -