artdaq_node_server  v1_00_08
 All Classes Namespaces Files Variables Pages
sax.js
1 ;(function (sax) { // wrapper for non-node envs
2  sax.parser = function (strict, opt) { return new SAXParser(strict, opt) }
3  sax.SAXParser = SAXParser
4  sax.SAXStream = SAXStream
5  sax.createStream = createStream
6 
7  // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns.
8  // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)),
9  // since that's the earliest that a buffer overrun could occur. This way, checks are
10  // as rare as required, but as often as necessary to ensure never crossing this bound.
11  // Furthermore, buffers are only tested at most once per write(), so passing a very
12  // large string into write() might have undesirable effects, but this is manageable by
13  // the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme
14  // edge case, result in creating at most one complete copy of the string passed in.
15  // Set to Infinity to have unlimited buffers.
16  sax.MAX_BUFFER_LENGTH = 64 * 1024
17 
18  var buffers = [
19  'comment', 'sgmlDecl', 'textNode', 'tagName', 'doctype',
20  'procInstName', 'procInstBody', 'entity', 'attribName',
21  'attribValue', 'cdata', 'script'
22  ]
23 
24  sax.EVENTS = [
25  'text',
26  'processinginstruction',
27  'sgmldeclaration',
28  'doctype',
29  'comment',
30  'opentagstart',
31  'attribute',
32  'opentag',
33  'closetag',
34  'opencdata',
35  'cdata',
36  'closecdata',
37  'error',
38  'end',
39  'ready',
40  'script',
41  'opennamespace',
42  'closenamespace'
43  ]
44 
45  function SAXParser (strict, opt) {
46  if (!(this instanceof SAXParser)) {
47  return new SAXParser(strict, opt)
48  }
49 
50  var parser = this
51  clearBuffers(parser)
52  parser.q = parser.c = ''
53  parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH
54  parser.opt = opt || {}
55  parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags
56  parser.looseCase = parser.opt.lowercase ? 'toLowerCase' : 'toUpperCase'
57  parser.tags = []
58  parser.closed = parser.closedRoot = parser.sawRoot = false
59  parser.tag = parser.error = null
60  parser.strict = !!strict
61  parser.noscript = !!(strict || parser.opt.noscript)
62  parser.state = S.BEGIN
63  parser.strictEntities = parser.opt.strictEntities
64  parser.ENTITIES = parser.strictEntities ? Object.create(sax.XML_ENTITIES) : Object.create(sax.ENTITIES)
65  parser.attribList = []
66 
67  // namespaces form a prototype chain.
68  // it always points at the current tag,
69  // which protos to its parent tag.
70  if (parser.opt.xmlns) {
71  parser.ns = Object.create(rootNS)
72  }
73 
74  // mostly just for error reporting
75  parser.trackPosition = parser.opt.position !== false
76  if (parser.trackPosition) {
77  parser.position = parser.line = parser.column = 0
78  }
79  emit(parser, 'onready')
80  }
81 
82  if (!Object.create) {
83  Object.create = function (o) {
84  function F () {}
85  F.prototype = o
86  var newf = new F()
87  return newf
88  }
89  }
90 
91  if (!Object.keys) {
92  Object.keys = function (o) {
93  var a = []
94  for (var i in o) if (o.hasOwnProperty(i)) a.push(i)
95  return a
96  }
97  }
98 
99  function checkBufferLength (parser) {
100  var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10)
101  var maxActual = 0
102  for (var i = 0, l = buffers.length; i < l; i++) {
103  var len = parser[buffers[i]].length
104  if (len > maxAllowed) {
105  // Text/cdata nodes can get big, and since they're buffered,
106  // we can get here under normal conditions.
107  // Avoid issues by emitting the text node now,
108  // so at least it won't get any bigger.
109  switch (buffers[i]) {
110  case 'textNode':
111  closeText(parser)
112  break
113 
114  case 'cdata':
115  emitNode(parser, 'oncdata', parser.cdata)
116  parser.cdata = ''
117  break
118 
119  case 'script':
120  emitNode(parser, 'onscript', parser.script)
121  parser.script = ''
122  break
123 
124  default:
125  error(parser, 'Max buffer length exceeded: ' + buffers[i])
126  }
127  }
128  maxActual = Math.max(maxActual, len)
129  }
130  // schedule the next check for the earliest possible buffer overrun.
131  var m = sax.MAX_BUFFER_LENGTH - maxActual
132  parser.bufferCheckPosition = m + parser.position
133  }
134 
135  function clearBuffers (parser) {
136  for (var i = 0, l = buffers.length; i < l; i++) {
137  parser[buffers[i]] = ''
138  }
139  }
140 
141  function flushBuffers (parser) {
142  closeText(parser)
143  if (parser.cdata !== '') {
144  emitNode(parser, 'oncdata', parser.cdata)
145  parser.cdata = ''
146  }
147  if (parser.script !== '') {
148  emitNode(parser, 'onscript', parser.script)
149  parser.script = ''
150  }
151  }
152 
153  SAXParser.prototype = {
154  end: function () { end(this) },
155  write: write,
156  resume: function () { this.error = null; return this },
157  close: function () { return this.write(null) },
158  flush: function () { flushBuffers(this) }
159  }
160 
161  var Stream
162  try {
163  Stream = require('stream').Stream
164  } catch (ex) {
165  Stream = function () {}
166  }
167 
168  var streamWraps = sax.EVENTS.filter(function (ev) {
169  return ev !== 'error' && ev !== 'end'
170  })
171 
172  function createStream (strict, opt) {
173  return new SAXStream(strict, opt)
174  }
175 
176  function SAXStream (strict, opt) {
177  if (!(this instanceof SAXStream)) {
178  return new SAXStream(strict, opt)
179  }
180 
181  Stream.apply(this)
182 
183  this._parser = new SAXParser(strict, opt)
184  this.writable = true
185  this.readable = true
186 
187  var me = this
188 
189  this._parser.onend = function () {
190  me.emit('end')
191  }
192 
193  this._parser.onerror = function (er) {
194  me.emit('error', er)
195 
196  // if didn't throw, then means error was handled.
197  // go ahead and clear error, so we can write again.
198  me._parser.error = null
199  }
200 
201  this._decoder = null
202 
203  streamWraps.forEach(function (ev) {
204  Object.defineProperty(me, 'on' + ev, {
205  get: function () {
206  return me._parser['on' + ev]
207  },
208  set: function (h) {
209  if (!h) {
210  me.removeAllListeners(ev)
211  me._parser['on' + ev] = h
212  return h
213  }
214  me.on(ev, h)
215  },
216  enumerable: true,
217  configurable: false
218  })
219  })
220  }
221 
222  SAXStream.prototype = Object.create(Stream.prototype, {
223  constructor: {
224  value: SAXStream
225  }
226  })
227 
228  SAXStream.prototype.write = function (data) {
229  if (typeof Buffer === 'function' &&
230  typeof Buffer.isBuffer === 'function' &&
231  Buffer.isBuffer(data)) {
232  if (!this._decoder) {
233  var SD = require('string_decoder').StringDecoder
234  this._decoder = new SD('utf8')
235  }
236  data = this._decoder.write(data)
237  }
238 
239  this._parser.write(data.toString())
240  this.emit('data', data)
241  return true
242  }
243 
244  SAXStream.prototype.end = function (chunk) {
245  if (chunk && chunk.length) {
246  this.write(chunk)
247  }
248  this._parser.end()
249  return true
250  }
251 
252  SAXStream.prototype.on = function (ev, handler) {
253  var me = this
254  if (!me._parser['on' + ev] && streamWraps.indexOf(ev) !== -1) {
255  me._parser['on' + ev] = function () {
256  var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments)
257  args.splice(0, 0, ev)
258  me.emit.apply(me, args)
259  }
260  }
261 
262  return Stream.prototype.on.call(me, ev, handler)
263  }
264 
265  // character classes and tokens
266  var whitespace = '\r\n\t '
267 
268  // this really needs to be replaced with character classes.
269  // XML allows all manner of ridiculous numbers and digits.
270 
271  // (Letter | "_" | ":")
272  var quote = '\'"'
273  var attribEnd = whitespace + '>'
274  var CDATA = '[CDATA['
275  var DOCTYPE = 'DOCTYPE'
276  var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'
277  var XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/'
278  var rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE }
279 
280  // turn all the string character sets into character class objects.
281  whitespace = charClass(whitespace)
282 
283  // http://www.w3.org/TR/REC-xml/#NT-NameStartChar
284  // This implementation works on strings, a single character at a time
285  // as such, it cannot ever support astral-plane characters (10000-EFFFF)
286  // without a significant breaking change to either this parser, or the
287  // JavaScript language. Implementation of an emoji-capable xml parser
288  // is left as an exercise for the reader.
289  var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
290 
291  var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/
292 
293  var entityStart = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
294  var entityBody = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/
295 
296  quote = charClass(quote)
297  attribEnd = charClass(attribEnd)
298 
299  function charClass (str) {
300  return str.split('').reduce(function (s, c) {
301  s[c] = true
302  return s
303  }, {})
304  }
305 
306  function isMatch (regex, c) {
307  return regex.test(c)
308  }
309 
310  function is (charclass, c) {
311  return charclass[c]
312  }
313 
314  function notMatch (regex, c) {
315  return !isMatch(regex, c)
316  }
317 
318  function not (charclass, c) {
319  return !is(charclass, c)
320  }
321 
322  var S = 0
323  sax.STATE = {
324  BEGIN: S++, // leading byte order mark or whitespace
325  BEGIN_WHITESPACE: S++, // leading whitespace
326  TEXT: S++, // general stuff
327  TEXT_ENTITY: S++, // &amp and such.
328  OPEN_WAKA: S++, // <
329  SGML_DECL: S++, // <!BLARG
330  SGML_DECL_QUOTED: S++, // <!BLARG foo "bar
331  DOCTYPE: S++, // <!DOCTYPE
332  DOCTYPE_QUOTED: S++, // <!DOCTYPE "//blah
333  DOCTYPE_DTD: S++, // <!DOCTYPE "//blah" [ ...
334  DOCTYPE_DTD_QUOTED: S++, // <!DOCTYPE "//blah" [ "foo
335  COMMENT_STARTING: S++, // <!-
336  COMMENT: S++, // <!--
337  COMMENT_ENDING: S++, // <!-- blah -
338  COMMENT_ENDED: S++, // <!-- blah --
339  CDATA: S++, // <![CDATA[ something
340  CDATA_ENDING: S++, // ]
341  CDATA_ENDING_2: S++, // ]]
342  PROC_INST: S++, // <?hi
343  PROC_INST_BODY: S++, // <?hi there
344  PROC_INST_ENDING: S++, // <?hi "there" ?
345  OPEN_TAG: S++, // <strong
346  OPEN_TAG_SLASH: S++, // <strong /
347  ATTRIB: S++, // <a
348  ATTRIB_NAME: S++, // <a foo
349  ATTRIB_NAME_SAW_WHITE: S++, // <a foo _
350  ATTRIB_VALUE: S++, // <a foo=
351  ATTRIB_VALUE_QUOTED: S++, // <a foo="bar
352  ATTRIB_VALUE_CLOSED: S++, // <a foo="bar"
353  ATTRIB_VALUE_UNQUOTED: S++, // <a foo=bar
354  ATTRIB_VALUE_ENTITY_Q: S++, // <foo bar="&quot;"
355  ATTRIB_VALUE_ENTITY_U: S++, // <foo bar=&quot
356  CLOSE_TAG: S++, // </a
357  CLOSE_TAG_SAW_WHITE: S++, // </a >
358  SCRIPT: S++, // <script> ...
359  SCRIPT_ENDING: S++ // <script> ... <
360  }
361 
362  sax.XML_ENTITIES = {
363  'amp': '&',
364  'gt': '>',
365  'lt': '<',
366  'quot': '"',
367  'apos': "'"
368  }
369 
370  sax.ENTITIES = {
371  'amp': '&',
372  'gt': '>',
373  'lt': '<',
374  'quot': '"',
375  'apos': "'",
376  'AElig': 198,
377  'Aacute': 193,
378  'Acirc': 194,
379  'Agrave': 192,
380  'Aring': 197,
381  'Atilde': 195,
382  'Auml': 196,
383  'Ccedil': 199,
384  'ETH': 208,
385  'Eacute': 201,
386  'Ecirc': 202,
387  'Egrave': 200,
388  'Euml': 203,
389  'Iacute': 205,
390  'Icirc': 206,
391  'Igrave': 204,
392  'Iuml': 207,
393  'Ntilde': 209,
394  'Oacute': 211,
395  'Ocirc': 212,
396  'Ograve': 210,
397  'Oslash': 216,
398  'Otilde': 213,
399  'Ouml': 214,
400  'THORN': 222,
401  'Uacute': 218,
402  'Ucirc': 219,
403  'Ugrave': 217,
404  'Uuml': 220,
405  'Yacute': 221,
406  'aacute': 225,
407  'acirc': 226,
408  'aelig': 230,
409  'agrave': 224,
410  'aring': 229,
411  'atilde': 227,
412  'auml': 228,
413  'ccedil': 231,
414  'eacute': 233,
415  'ecirc': 234,
416  'egrave': 232,
417  'eth': 240,
418  'euml': 235,
419  'iacute': 237,
420  'icirc': 238,
421  'igrave': 236,
422  'iuml': 239,
423  'ntilde': 241,
424  'oacute': 243,
425  'ocirc': 244,
426  'ograve': 242,
427  'oslash': 248,
428  'otilde': 245,
429  'ouml': 246,
430  'szlig': 223,
431  'thorn': 254,
432  'uacute': 250,
433  'ucirc': 251,
434  'ugrave': 249,
435  'uuml': 252,
436  'yacute': 253,
437  'yuml': 255,
438  'copy': 169,
439  'reg': 174,
440  'nbsp': 160,
441  'iexcl': 161,
442  'cent': 162,
443  'pound': 163,
444  'curren': 164,
445  'yen': 165,
446  'brvbar': 166,
447  'sect': 167,
448  'uml': 168,
449  'ordf': 170,
450  'laquo': 171,
451  'not': 172,
452  'shy': 173,
453  'macr': 175,
454  'deg': 176,
455  'plusmn': 177,
456  'sup1': 185,
457  'sup2': 178,
458  'sup3': 179,
459  'acute': 180,
460  'micro': 181,
461  'para': 182,
462  'middot': 183,
463  'cedil': 184,
464  'ordm': 186,
465  'raquo': 187,
466  'frac14': 188,
467  'frac12': 189,
468  'frac34': 190,
469  'iquest': 191,
470  'times': 215,
471  'divide': 247,
472  'OElig': 338,
473  'oelig': 339,
474  'Scaron': 352,
475  'scaron': 353,
476  'Yuml': 376,
477  'fnof': 402,
478  'circ': 710,
479  'tilde': 732,
480  'Alpha': 913,
481  'Beta': 914,
482  'Gamma': 915,
483  'Delta': 916,
484  'Epsilon': 917,
485  'Zeta': 918,
486  'Eta': 919,
487  'Theta': 920,
488  'Iota': 921,
489  'Kappa': 922,
490  'Lambda': 923,
491  'Mu': 924,
492  'Nu': 925,
493  'Xi': 926,
494  'Omicron': 927,
495  'Pi': 928,
496  'Rho': 929,
497  'Sigma': 931,
498  'Tau': 932,
499  'Upsilon': 933,
500  'Phi': 934,
501  'Chi': 935,
502  'Psi': 936,
503  'Omega': 937,
504  'alpha': 945,
505  'beta': 946,
506  'gamma': 947,
507  'delta': 948,
508  'epsilon': 949,
509  'zeta': 950,
510  'eta': 951,
511  'theta': 952,
512  'iota': 953,
513  'kappa': 954,
514  'lambda': 955,
515  'mu': 956,
516  'nu': 957,
517  'xi': 958,
518  'omicron': 959,
519  'pi': 960,
520  'rho': 961,
521  'sigmaf': 962,
522  'sigma': 963,
523  'tau': 964,
524  'upsilon': 965,
525  'phi': 966,
526  'chi': 967,
527  'psi': 968,
528  'omega': 969,
529  'thetasym': 977,
530  'upsih': 978,
531  'piv': 982,
532  'ensp': 8194,
533  'emsp': 8195,
534  'thinsp': 8201,
535  'zwnj': 8204,
536  'zwj': 8205,
537  'lrm': 8206,
538  'rlm': 8207,
539  'ndash': 8211,
540  'mdash': 8212,
541  'lsquo': 8216,
542  'rsquo': 8217,
543  'sbquo': 8218,
544  'ldquo': 8220,
545  'rdquo': 8221,
546  'bdquo': 8222,
547  'dagger': 8224,
548  'Dagger': 8225,
549  'bull': 8226,
550  'hellip': 8230,
551  'permil': 8240,
552  'prime': 8242,
553  'Prime': 8243,
554  'lsaquo': 8249,
555  'rsaquo': 8250,
556  'oline': 8254,
557  'frasl': 8260,
558  'euro': 8364,
559  'image': 8465,
560  'weierp': 8472,
561  'real': 8476,
562  'trade': 8482,
563  'alefsym': 8501,
564  'larr': 8592,
565  'uarr': 8593,
566  'rarr': 8594,
567  'darr': 8595,
568  'harr': 8596,
569  'crarr': 8629,
570  'lArr': 8656,
571  'uArr': 8657,
572  'rArr': 8658,
573  'dArr': 8659,
574  'hArr': 8660,
575  'forall': 8704,
576  'part': 8706,
577  'exist': 8707,
578  'empty': 8709,
579  'nabla': 8711,
580  'isin': 8712,
581  'notin': 8713,
582  'ni': 8715,
583  'prod': 8719,
584  'sum': 8721,
585  'minus': 8722,
586  'lowast': 8727,
587  'radic': 8730,
588  'prop': 8733,
589  'infin': 8734,
590  'ang': 8736,
591  'and': 8743,
592  'or': 8744,
593  'cap': 8745,
594  'cup': 8746,
595  'int': 8747,
596  'there4': 8756,
597  'sim': 8764,
598  'cong': 8773,
599  'asymp': 8776,
600  'ne': 8800,
601  'equiv': 8801,
602  'le': 8804,
603  'ge': 8805,
604  'sub': 8834,
605  'sup': 8835,
606  'nsub': 8836,
607  'sube': 8838,
608  'supe': 8839,
609  'oplus': 8853,
610  'otimes': 8855,
611  'perp': 8869,
612  'sdot': 8901,
613  'lceil': 8968,
614  'rceil': 8969,
615  'lfloor': 8970,
616  'rfloor': 8971,
617  'lang': 9001,
618  'rang': 9002,
619  'loz': 9674,
620  'spades': 9824,
621  'clubs': 9827,
622  'hearts': 9829,
623  'diams': 9830
624  }
625 
626  Object.keys(sax.ENTITIES).forEach(function (key) {
627  var e = sax.ENTITIES[key]
628  var s = typeof e === 'number' ? String.fromCharCode(e) : e
629  sax.ENTITIES[key] = s
630  })
631 
632  for (var s in sax.STATE) {
633  sax.STATE[sax.STATE[s]] = s
634  }
635 
636  // shorthand
637  S = sax.STATE
638 
639  function emit (parser, event, data) {
640  parser[event] && parser[event](data)
641  }
642 
643  function emitNode (parser, nodeType, data) {
644  if (parser.textNode) closeText(parser)
645  emit(parser, nodeType, data)
646  }
647 
648  function closeText (parser) {
649  parser.textNode = textopts(parser.opt, parser.textNode)
650  if (parser.textNode) emit(parser, 'ontext', parser.textNode)
651  parser.textNode = ''
652  }
653 
654  function textopts (opt, text) {
655  if (opt.trim) text = text.trim()
656  if (opt.normalize) text = text.replace(/\s+/g, ' ')
657  return text
658  }
659 
660  function error (parser, er) {
661  closeText(parser)
662  if (parser.trackPosition) {
663  er += '\nLine: ' + parser.line +
664  '\nColumn: ' + parser.column +
665  '\nChar: ' + parser.c
666  }
667  er = new Error(er)
668  parser.error = er
669  emit(parser, 'onerror', er)
670  return parser
671  }
672 
673  function end (parser) {
674  if (parser.sawRoot && !parser.closedRoot) strictFail(parser, 'Unclosed root tag')
675  if ((parser.state !== S.BEGIN) &&
676  (parser.state !== S.BEGIN_WHITESPACE) &&
677  (parser.state !== S.TEXT)) {
678  error(parser, 'Unexpected end')
679  }
680  closeText(parser)
681  parser.c = ''
682  parser.closed = true
683  emit(parser, 'onend')
684  SAXParser.call(parser, parser.strict, parser.opt)
685  return parser
686  }
687 
688  function strictFail (parser, message) {
689  if (typeof parser !== 'object' || !(parser instanceof SAXParser)) {
690  throw new Error('bad call to strictFail')
691  }
692  if (parser.strict) {
693  error(parser, message)
694  }
695  }
696 
697  function newTag (parser) {
698  if (!parser.strict) parser.tagName = parser.tagName[parser.looseCase]()
699  var parent = parser.tags[parser.tags.length - 1] || parser
700  var tag = parser.tag = { name: parser.tagName, attributes: {} }
701 
702  // will be overridden if tag contails an xmlns="foo" or xmlns:foo="bar"
703  if (parser.opt.xmlns) {
704  tag.ns = parent.ns
705  }
706  parser.attribList.length = 0
707  emitNode(parser, 'onopentagstart', tag)
708  }
709 
710  function qname (name, attribute) {
711  var i = name.indexOf(':')
712  var qualName = i < 0 ? [ '', name ] : name.split(':')
713  var prefix = qualName[0]
714  var local = qualName[1]
715 
716  // <x "xmlns"="http://foo">
717  if (attribute && name === 'xmlns') {
718  prefix = 'xmlns'
719  local = ''
720  }
721 
722  return { prefix: prefix, local: local }
723  }
724 
725  function attrib (parser) {
726  if (!parser.strict) {
727  parser.attribName = parser.attribName[parser.looseCase]()
728  }
729 
730  if (parser.attribList.indexOf(parser.attribName) !== -1 ||
731  parser.tag.attributes.hasOwnProperty(parser.attribName)) {
732  parser.attribName = parser.attribValue = ''
733  return
734  }
735 
736  if (parser.opt.xmlns) {
737  var qn = qname(parser.attribName, true)
738  var prefix = qn.prefix
739  var local = qn.local
740 
741  if (prefix === 'xmlns') {
742  // namespace binding attribute. push the binding into scope
743  if (local === 'xml' && parser.attribValue !== XML_NAMESPACE) {
744  strictFail(parser,
745  'xml: prefix must be bound to ' + XML_NAMESPACE + '\n' +
746  'Actual: ' + parser.attribValue)
747  } else if (local === 'xmlns' && parser.attribValue !== XMLNS_NAMESPACE) {
748  strictFail(parser,
749  'xmlns: prefix must be bound to ' + XMLNS_NAMESPACE + '\n' +
750  'Actual: ' + parser.attribValue)
751  } else {
752  var tag = parser.tag
753  var parent = parser.tags[parser.tags.length - 1] || parser
754  if (tag.ns === parent.ns) {
755  tag.ns = Object.create(parent.ns)
756  }
757  tag.ns[local] = parser.attribValue
758  }
759  }
760 
761  // defer onattribute events until all attributes have been seen
762  // so any new bindings can take effect. preserve attribute order
763  // so deferred events can be emitted in document order
764  parser.attribList.push([parser.attribName, parser.attribValue])
765  } else {
766  // in non-xmlns mode, we can emit the event right away
767  parser.tag.attributes[parser.attribName] = parser.attribValue
768  emitNode(parser, 'onattribute', {
769  name: parser.attribName,
770  value: parser.attribValue
771  })
772  }
773 
774  parser.attribName = parser.attribValue = ''
775  }
776 
777  function openTag (parser, selfClosing) {
778  if (parser.opt.xmlns) {
779  // emit namespace binding events
780  var tag = parser.tag
781 
782  // add namespace info to tag
783  var qn = qname(parser.tagName)
784  tag.prefix = qn.prefix
785  tag.local = qn.local
786  tag.uri = tag.ns[qn.prefix] || ''
787 
788  if (tag.prefix && !tag.uri) {
789  strictFail(parser, 'Unbound namespace prefix: ' +
790  JSON.stringify(parser.tagName))
791  tag.uri = qn.prefix
792  }
793 
794  var parent = parser.tags[parser.tags.length - 1] || parser
795  if (tag.ns && parent.ns !== tag.ns) {
796  Object.keys(tag.ns).forEach(function (p) {
797  emitNode(parser, 'onopennamespace', {
798  prefix: p,
799  uri: tag.ns[p]
800  })
801  })
802  }
803 
804  // handle deferred onattribute events
805  // Note: do not apply default ns to attributes:
806  // http://www.w3.org/TR/REC-xml-names/#defaulting
807  for (var i = 0, l = parser.attribList.length; i < l; i++) {
808  var nv = parser.attribList[i]
809  var name = nv[0]
810  var value = nv[1]
811  var qualName = qname(name, true)
812  var prefix = qualName.prefix
813  var local = qualName.local
814  var uri = prefix === '' ? '' : (tag.ns[prefix] || '')
815  var a = {
816  name: name,
817  value: value,
818  prefix: prefix,
819  local: local,
820  uri: uri
821  }
822 
823  // if there's any attributes with an undefined namespace,
824  // then fail on them now.
825  if (prefix && prefix !== 'xmlns' && !uri) {
826  strictFail(parser, 'Unbound namespace prefix: ' +
827  JSON.stringify(prefix))
828  a.uri = prefix
829  }
830  parser.tag.attributes[name] = a
831  emitNode(parser, 'onattribute', a)
832  }
833  parser.attribList.length = 0
834  }
835 
836  parser.tag.isSelfClosing = !!selfClosing
837 
838  // process the tag
839  parser.sawRoot = true
840  parser.tags.push(parser.tag)
841  emitNode(parser, 'onopentag', parser.tag)
842  if (!selfClosing) {
843  // special case for <script> in non-strict mode.
844  if (!parser.noscript && parser.tagName.toLowerCase() === 'script') {
845  parser.state = S.SCRIPT
846  } else {
847  parser.state = S.TEXT
848  }
849  parser.tag = null
850  parser.tagName = ''
851  }
852  parser.attribName = parser.attribValue = ''
853  parser.attribList.length = 0
854  }
855 
856  function closeTag (parser) {
857  if (!parser.tagName) {
858  strictFail(parser, 'Weird empty close tag.')
859  parser.textNode += '</>'
860  parser.state = S.TEXT
861  return
862  }
863 
864  if (parser.script) {
865  if (parser.tagName !== 'script') {
866  parser.script += '</' + parser.tagName + '>'
867  parser.tagName = ''
868  parser.state = S.SCRIPT
869  return
870  }
871  emitNode(parser, 'onscript', parser.script)
872  parser.script = ''
873  }
874 
875  // first make sure that the closing tag actually exists.
876  // <a><b></c></b></a> will close everything, otherwise.
877  var t = parser.tags.length
878  var tagName = parser.tagName
879  if (!parser.strict) {
880  tagName = tagName[parser.looseCase]()
881  }
882  var closeTo = tagName
883  while (t--) {
884  var close = parser.tags[t]
885  if (close.name !== closeTo) {
886  // fail the first time in strict mode
887  strictFail(parser, 'Unexpected close tag')
888  } else {
889  break
890  }
891  }
892 
893  // didn't find it. we already failed for strict, so just abort.
894  if (t < 0) {
895  strictFail(parser, 'Unmatched closing tag: ' + parser.tagName)
896  parser.textNode += '</' + parser.tagName + '>'
897  parser.state = S.TEXT
898  return
899  }
900  parser.tagName = tagName
901  var s = parser.tags.length
902  while (s-- > t) {
903  var tag = parser.tag = parser.tags.pop()
904  parser.tagName = parser.tag.name
905  emitNode(parser, 'onclosetag', parser.tagName)
906 
907  var x = {}
908  for (var i in tag.ns) {
909  x[i] = tag.ns[i]
910  }
911 
912  var parent = parser.tags[parser.tags.length - 1] || parser
913  if (parser.opt.xmlns && tag.ns !== parent.ns) {
914  // remove namespace bindings introduced by tag
915  Object.keys(tag.ns).forEach(function (p) {
916  var n = tag.ns[p]
917  emitNode(parser, 'onclosenamespace', { prefix: p, uri: n })
918  })
919  }
920  }
921  if (t === 0) parser.closedRoot = true
922  parser.tagName = parser.attribValue = parser.attribName = ''
923  parser.attribList.length = 0
924  parser.state = S.TEXT
925  }
926 
927  function parseEntity (parser) {
928  var entity = parser.entity
929  var entityLC = entity.toLowerCase()
930  var num
931  var numStr = ''
932 
933  if (parser.ENTITIES[entity]) {
934  return parser.ENTITIES[entity]
935  }
936  if (parser.ENTITIES[entityLC]) {
937  return parser.ENTITIES[entityLC]
938  }
939  entity = entityLC
940  if (entity.charAt(0) === '#') {
941  if (entity.charAt(1) === 'x') {
942  entity = entity.slice(2)
943  num = parseInt(entity, 16)
944  numStr = num.toString(16)
945  } else {
946  entity = entity.slice(1)
947  num = parseInt(entity, 10)
948  numStr = num.toString(10)
949  }
950  }
951  entity = entity.replace(/^0+/, '')
952  if (numStr.toLowerCase() !== entity) {
953  strictFail(parser, 'Invalid character entity')
954  return '&' + parser.entity + ';'
955  }
956 
957  return String.fromCodePoint(num)
958  }
959 
960  function beginWhiteSpace (parser, c) {
961  if (c === '<') {
962  parser.state = S.OPEN_WAKA
963  parser.startTagPosition = parser.position
964  } else if (not(whitespace, c)) {
965  // have to process this as a text node.
966  // weird, but happens.
967  strictFail(parser, 'Non-whitespace before first tag.')
968  parser.textNode = c
969  parser.state = S.TEXT
970  }
971  }
972 
973  function charAt (chunk, i) {
974  var result = ''
975  if (i < chunk.length) {
976  result = chunk.charAt(i)
977  }
978  return result
979  }
980 
981  function write (chunk) {
982  var parser = this
983  if (this.error) {
984  throw this.error
985  }
986  if (parser.closed) {
987  return error(parser,
988  'Cannot write after close. Assign an onready handler.')
989  }
990  if (chunk === null) {
991  return end(parser)
992  }
993  if (typeof chunk === 'object') {
994  chunk = chunk.toString()
995  }
996  var i = 0
997  var c = ''
998  while (true) {
999  c = charAt(chunk, i++)
1000  parser.c = c
1001 
1002  if (!c) {
1003  break
1004  }
1005 
1006  if (parser.trackPosition) {
1007  parser.position++
1008  if (c === '\n') {
1009  parser.line++
1010  parser.column = 0
1011  } else {
1012  parser.column++
1013  }
1014  }
1015 
1016  switch (parser.state) {
1017  case S.BEGIN:
1018  parser.state = S.BEGIN_WHITESPACE
1019  if (c === '\uFEFF') {
1020  continue
1021  }
1022  beginWhiteSpace(parser, c)
1023  continue
1024 
1025  case S.BEGIN_WHITESPACE:
1026  beginWhiteSpace(parser, c)
1027  continue
1028 
1029  case S.TEXT:
1030  if (parser.sawRoot && !parser.closedRoot) {
1031  var starti = i - 1
1032  while (c && c !== '<' && c !== '&') {
1033  c = charAt(chunk, i++)
1034  if (c && parser.trackPosition) {
1035  parser.position++
1036  if (c === '\n') {
1037  parser.line++
1038  parser.column = 0
1039  } else {
1040  parser.column++
1041  }
1042  }
1043  }
1044  parser.textNode += chunk.substring(starti, i - 1)
1045  }
1046  if (c === '<' && !(parser.sawRoot && parser.closedRoot && !parser.strict)) {
1047  parser.state = S.OPEN_WAKA
1048  parser.startTagPosition = parser.position
1049  } else {
1050  if (not(whitespace, c) && (!parser.sawRoot || parser.closedRoot)) {
1051  strictFail(parser, 'Text data outside of root node.')
1052  }
1053  if (c === '&') {
1054  parser.state = S.TEXT_ENTITY
1055  } else {
1056  parser.textNode += c
1057  }
1058  }
1059  continue
1060 
1061  case S.SCRIPT:
1062  // only non-strict
1063  if (c === '<') {
1064  parser.state = S.SCRIPT_ENDING
1065  } else {
1066  parser.script += c
1067  }
1068  continue
1069 
1070  case S.SCRIPT_ENDING:
1071  if (c === '/') {
1072  parser.state = S.CLOSE_TAG
1073  } else {
1074  parser.script += '<' + c
1075  parser.state = S.SCRIPT
1076  }
1077  continue
1078 
1079  case S.OPEN_WAKA:
1080  // either a /, ?, !, or text is coming next.
1081  if (c === '!') {
1082  parser.state = S.SGML_DECL
1083  parser.sgmlDecl = ''
1084  } else if (is(whitespace, c)) {
1085  // wait for it...
1086  } else if (isMatch(nameStart, c)) {
1087  parser.state = S.OPEN_TAG
1088  parser.tagName = c
1089  } else if (c === '/') {
1090  parser.state = S.CLOSE_TAG
1091  parser.tagName = ''
1092  } else if (c === '?') {
1093  parser.state = S.PROC_INST
1094  parser.procInstName = parser.procInstBody = ''
1095  } else {
1096  strictFail(parser, 'Unencoded <')
1097  // if there was some whitespace, then add that in.
1098  if (parser.startTagPosition + 1 < parser.position) {
1099  var pad = parser.position - parser.startTagPosition
1100  c = new Array(pad).join(' ') + c
1101  }
1102  parser.textNode += '<' + c
1103  parser.state = S.TEXT
1104  }
1105  continue
1106 
1107  case S.SGML_DECL:
1108  if ((parser.sgmlDecl + c).toUpperCase() === CDATA) {
1109  emitNode(parser, 'onopencdata')
1110  parser.state = S.CDATA
1111  parser.sgmlDecl = ''
1112  parser.cdata = ''
1113  } else if (parser.sgmlDecl + c === '--') {
1114  parser.state = S.COMMENT
1115  parser.comment = ''
1116  parser.sgmlDecl = ''
1117  } else if ((parser.sgmlDecl + c).toUpperCase() === DOCTYPE) {
1118  parser.state = S.DOCTYPE
1119  if (parser.doctype || parser.sawRoot) {
1120  strictFail(parser,
1121  'Inappropriately located doctype declaration')
1122  }
1123  parser.doctype = ''
1124  parser.sgmlDecl = ''
1125  } else if (c === '>') {
1126  emitNode(parser, 'onsgmldeclaration', parser.sgmlDecl)
1127  parser.sgmlDecl = ''
1128  parser.state = S.TEXT
1129  } else if (is(quote, c)) {
1130  parser.state = S.SGML_DECL_QUOTED
1131  parser.sgmlDecl += c
1132  } else {
1133  parser.sgmlDecl += c
1134  }
1135  continue
1136 
1137  case S.SGML_DECL_QUOTED:
1138  if (c === parser.q) {
1139  parser.state = S.SGML_DECL
1140  parser.q = ''
1141  }
1142  parser.sgmlDecl += c
1143  continue
1144 
1145  case S.DOCTYPE:
1146  if (c === '>') {
1147  parser.state = S.TEXT
1148  emitNode(parser, 'ondoctype', parser.doctype)
1149  parser.doctype = true // just remember that we saw it.
1150  } else {
1151  parser.doctype += c
1152  if (c === '[') {
1153  parser.state = S.DOCTYPE_DTD
1154  } else if (is(quote, c)) {
1155  parser.state = S.DOCTYPE_QUOTED
1156  parser.q = c
1157  }
1158  }
1159  continue
1160 
1161  case S.DOCTYPE_QUOTED:
1162  parser.doctype += c
1163  if (c === parser.q) {
1164  parser.q = ''
1165  parser.state = S.DOCTYPE
1166  }
1167  continue
1168 
1169  case S.DOCTYPE_DTD:
1170  parser.doctype += c
1171  if (c === ']') {
1172  parser.state = S.DOCTYPE
1173  } else if (is(quote, c)) {
1174  parser.state = S.DOCTYPE_DTD_QUOTED
1175  parser.q = c
1176  }
1177  continue
1178 
1179  case S.DOCTYPE_DTD_QUOTED:
1180  parser.doctype += c
1181  if (c === parser.q) {
1182  parser.state = S.DOCTYPE_DTD
1183  parser.q = ''
1184  }
1185  continue
1186 
1187  case S.COMMENT:
1188  if (c === '-') {
1189  parser.state = S.COMMENT_ENDING
1190  } else {
1191  parser.comment += c
1192  }
1193  continue
1194 
1195  case S.COMMENT_ENDING:
1196  if (c === '-') {
1197  parser.state = S.COMMENT_ENDED
1198  parser.comment = textopts(parser.opt, parser.comment)
1199  if (parser.comment) {
1200  emitNode(parser, 'oncomment', parser.comment)
1201  }
1202  parser.comment = ''
1203  } else {
1204  parser.comment += '-' + c
1205  parser.state = S.COMMENT
1206  }
1207  continue
1208 
1209  case S.COMMENT_ENDED:
1210  if (c !== '>') {
1211  strictFail(parser, 'Malformed comment')
1212  // allow <!-- blah -- bloo --> in non-strict mode,
1213  // which is a comment of " blah -- bloo "
1214  parser.comment += '--' + c
1215  parser.state = S.COMMENT
1216  } else {
1217  parser.state = S.TEXT
1218  }
1219  continue
1220 
1221  case S.CDATA:
1222  if (c === ']') {
1223  parser.state = S.CDATA_ENDING
1224  } else {
1225  parser.cdata += c
1226  }
1227  continue
1228 
1229  case S.CDATA_ENDING:
1230  if (c === ']') {
1231  parser.state = S.CDATA_ENDING_2
1232  } else {
1233  parser.cdata += ']' + c
1234  parser.state = S.CDATA
1235  }
1236  continue
1237 
1238  case S.CDATA_ENDING_2:
1239  if (c === '>') {
1240  if (parser.cdata) {
1241  emitNode(parser, 'oncdata', parser.cdata)
1242  }
1243  emitNode(parser, 'onclosecdata')
1244  parser.cdata = ''
1245  parser.state = S.TEXT
1246  } else if (c === ']') {
1247  parser.cdata += ']'
1248  } else {
1249  parser.cdata += ']]' + c
1250  parser.state = S.CDATA
1251  }
1252  continue
1253 
1254  case S.PROC_INST:
1255  if (c === '?') {
1256  parser.state = S.PROC_INST_ENDING
1257  } else if (is(whitespace, c)) {
1258  parser.state = S.PROC_INST_BODY
1259  } else {
1260  parser.procInstName += c
1261  }
1262  continue
1263 
1264  case S.PROC_INST_BODY:
1265  if (!parser.procInstBody && is(whitespace, c)) {
1266  continue
1267  } else if (c === '?') {
1268  parser.state = S.PROC_INST_ENDING
1269  } else {
1270  parser.procInstBody += c
1271  }
1272  continue
1273 
1274  case S.PROC_INST_ENDING:
1275  if (c === '>') {
1276  emitNode(parser, 'onprocessinginstruction', {
1277  name: parser.procInstName,
1278  body: parser.procInstBody
1279  })
1280  parser.procInstName = parser.procInstBody = ''
1281  parser.state = S.TEXT
1282  } else {
1283  parser.procInstBody += '?' + c
1284  parser.state = S.PROC_INST_BODY
1285  }
1286  continue
1287 
1288  case S.OPEN_TAG:
1289  if (isMatch(nameBody, c)) {
1290  parser.tagName += c
1291  } else {
1292  newTag(parser)
1293  if (c === '>') {
1294  openTag(parser)
1295  } else if (c === '/') {
1296  parser.state = S.OPEN_TAG_SLASH
1297  } else {
1298  if (not(whitespace, c)) {
1299  strictFail(parser, 'Invalid character in tag name')
1300  }
1301  parser.state = S.ATTRIB
1302  }
1303  }
1304  continue
1305 
1306  case S.OPEN_TAG_SLASH:
1307  if (c === '>') {
1308  openTag(parser, true)
1309  closeTag(parser)
1310  } else {
1311  strictFail(parser, 'Forward-slash in opening tag not followed by >')
1312  parser.state = S.ATTRIB
1313  }
1314  continue
1315 
1316  case S.ATTRIB:
1317  // haven't read the attribute name yet.
1318  if (is(whitespace, c)) {
1319  continue
1320  } else if (c === '>') {
1321  openTag(parser)
1322  } else if (c === '/') {
1323  parser.state = S.OPEN_TAG_SLASH
1324  } else if (isMatch(nameStart, c)) {
1325  parser.attribName = c
1326  parser.attribValue = ''
1327  parser.state = S.ATTRIB_NAME
1328  } else {
1329  strictFail(parser, 'Invalid attribute name')
1330  }
1331  continue
1332 
1333  case S.ATTRIB_NAME:
1334  if (c === '=') {
1335  parser.state = S.ATTRIB_VALUE
1336  } else if (c === '>') {
1337  strictFail(parser, 'Attribute without value')
1338  parser.attribValue = parser.attribName
1339  attrib(parser)
1340  openTag(parser)
1341  } else if (is(whitespace, c)) {
1342  parser.state = S.ATTRIB_NAME_SAW_WHITE
1343  } else if (isMatch(nameBody, c)) {
1344  parser.attribName += c
1345  } else {
1346  strictFail(parser, 'Invalid attribute name')
1347  }
1348  continue
1349 
1350  case S.ATTRIB_NAME_SAW_WHITE:
1351  if (c === '=') {
1352  parser.state = S.ATTRIB_VALUE
1353  } else if (is(whitespace, c)) {
1354  continue
1355  } else {
1356  strictFail(parser, 'Attribute without value')
1357  parser.tag.attributes[parser.attribName] = ''
1358  parser.attribValue = ''
1359  emitNode(parser, 'onattribute', {
1360  name: parser.attribName,
1361  value: ''
1362  })
1363  parser.attribName = ''
1364  if (c === '>') {
1365  openTag(parser)
1366  } else if (isMatch(nameStart, c)) {
1367  parser.attribName = c
1368  parser.state = S.ATTRIB_NAME
1369  } else {
1370  strictFail(parser, 'Invalid attribute name')
1371  parser.state = S.ATTRIB
1372  }
1373  }
1374  continue
1375 
1376  case S.ATTRIB_VALUE:
1377  if (is(whitespace, c)) {
1378  continue
1379  } else if (is(quote, c)) {
1380  parser.q = c
1381  parser.state = S.ATTRIB_VALUE_QUOTED
1382  } else {
1383  strictFail(parser, 'Unquoted attribute value')
1384  parser.state = S.ATTRIB_VALUE_UNQUOTED
1385  parser.attribValue = c
1386  }
1387  continue
1388 
1389  case S.ATTRIB_VALUE_QUOTED:
1390  if (c !== parser.q) {
1391  if (c === '&') {
1392  parser.state = S.ATTRIB_VALUE_ENTITY_Q
1393  } else {
1394  parser.attribValue += c
1395  }
1396  continue
1397  }
1398  attrib(parser)
1399  parser.q = ''
1400  parser.state = S.ATTRIB_VALUE_CLOSED
1401  continue
1402 
1403  case S.ATTRIB_VALUE_CLOSED:
1404  if (is(whitespace, c)) {
1405  parser.state = S.ATTRIB
1406  } else if (c === '>') {
1407  openTag(parser)
1408  } else if (c === '/') {
1409  parser.state = S.OPEN_TAG_SLASH
1410  } else if (isMatch(nameStart, c)) {
1411  strictFail(parser, 'No whitespace between attributes')
1412  parser.attribName = c
1413  parser.attribValue = ''
1414  parser.state = S.ATTRIB_NAME
1415  } else {
1416  strictFail(parser, 'Invalid attribute name')
1417  }
1418  continue
1419 
1420  case S.ATTRIB_VALUE_UNQUOTED:
1421  if (not(attribEnd, c)) {
1422  if (c === '&') {
1423  parser.state = S.ATTRIB_VALUE_ENTITY_U
1424  } else {
1425  parser.attribValue += c
1426  }
1427  continue
1428  }
1429  attrib(parser)
1430  if (c === '>') {
1431  openTag(parser)
1432  } else {
1433  parser.state = S.ATTRIB
1434  }
1435  continue
1436 
1437  case S.CLOSE_TAG:
1438  if (!parser.tagName) {
1439  if (is(whitespace, c)) {
1440  continue
1441  } else if (notMatch(nameStart, c)) {
1442  if (parser.script) {
1443  parser.script += '</' + c
1444  parser.state = S.SCRIPT
1445  } else {
1446  strictFail(parser, 'Invalid tagname in closing tag.')
1447  }
1448  } else {
1449  parser.tagName = c
1450  }
1451  } else if (c === '>') {
1452  closeTag(parser)
1453  } else if (isMatch(nameBody, c)) {
1454  parser.tagName += c
1455  } else if (parser.script) {
1456  parser.script += '</' + parser.tagName
1457  parser.tagName = ''
1458  parser.state = S.SCRIPT
1459  } else {
1460  if (not(whitespace, c)) {
1461  strictFail(parser, 'Invalid tagname in closing tag')
1462  }
1463  parser.state = S.CLOSE_TAG_SAW_WHITE
1464  }
1465  continue
1466 
1467  case S.CLOSE_TAG_SAW_WHITE:
1468  if (is(whitespace, c)) {
1469  continue
1470  }
1471  if (c === '>') {
1472  closeTag(parser)
1473  } else {
1474  strictFail(parser, 'Invalid characters in closing tag')
1475  }
1476  continue
1477 
1478  case S.TEXT_ENTITY:
1479  case S.ATTRIB_VALUE_ENTITY_Q:
1480  case S.ATTRIB_VALUE_ENTITY_U:
1481  var returnState
1482  var buffer
1483  switch (parser.state) {
1484  case S.TEXT_ENTITY:
1485  returnState = S.TEXT
1486  buffer = 'textNode'
1487  break
1488 
1489  case S.ATTRIB_VALUE_ENTITY_Q:
1490  returnState = S.ATTRIB_VALUE_QUOTED
1491  buffer = 'attribValue'
1492  break
1493 
1494  case S.ATTRIB_VALUE_ENTITY_U:
1495  returnState = S.ATTRIB_VALUE_UNQUOTED
1496  buffer = 'attribValue'
1497  break
1498  }
1499 
1500  if (c === ';') {
1501  parser[buffer] += parseEntity(parser)
1502  parser.entity = ''
1503  parser.state = returnState
1504  } else if (isMatch(parser.entity.length ? entityBody : entityStart, c)) {
1505  parser.entity += c
1506  } else {
1507  strictFail(parser, 'Invalid character in entity name')
1508  parser[buffer] += '&' + parser.entity + c
1509  parser.entity = ''
1510  parser.state = returnState
1511  }
1512 
1513  continue
1514 
1515  default:
1516  throw new Error(parser, 'Unknown state: ' + parser.state)
1517  }
1518  } // while
1519 
1520  if (parser.position >= parser.bufferCheckPosition) {
1521  checkBufferLength(parser)
1522  }
1523  return parser
1524  }
1525 
1527  /* istanbul ignore next */
1528  if (!String.fromCodePoint) {
1529  (function () {
1530  var stringFromCharCode = String.fromCharCode
1531  var floor = Math.floor
1532  var fromCodePoint = function () {
1533  var MAX_SIZE = 0x4000
1534  var codeUnits = []
1535  var highSurrogate
1536  var lowSurrogate
1537  var index = -1
1538  var length = arguments.length
1539  if (!length) {
1540  return ''
1541  }
1542  var result = ''
1543  while (++index < length) {
1544  var codePoint = Number(arguments[index])
1545  if (
1546  !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
1547  codePoint < 0 || // not a valid Unicode code point
1548  codePoint > 0x10FFFF || // not a valid Unicode code point
1549  floor(codePoint) !== codePoint // not an integer
1550  ) {
1551  throw RangeError('Invalid code point: ' + codePoint)
1552  }
1553  if (codePoint <= 0xFFFF) { // BMP code point
1554  codeUnits.push(codePoint)
1555  } else { // Astral code point; split in surrogate halves
1556  // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
1557  codePoint -= 0x10000
1558  highSurrogate = (codePoint >> 10) + 0xD800
1559  lowSurrogate = (codePoint % 0x400) + 0xDC00
1560  codeUnits.push(highSurrogate, lowSurrogate)
1561  }
1562  if (index + 1 === length || codeUnits.length > MAX_SIZE) {
1563  result += stringFromCharCode.apply(null, codeUnits)
1564  codeUnits.length = 0
1565  }
1566  }
1567  return result
1568  }
1569  /* istanbul ignore next */
1570  if (Object.defineProperty) {
1571  Object.defineProperty(String, 'fromCodePoint', {
1572  value: fromCodePoint,
1573  configurable: true,
1574  writable: true
1575  })
1576  } else {
1577  String.fromCodePoint = fromCodePoint
1578  }
1579  }())
1580  }
1581 })(typeof exports === 'undefined' ? this.sax = {} : exports)