PageSourceSearch

https://www.gmo-pg.com/common/js/polyfill/ie11CustomProperties.js

js gmo-pg.com collected 2026-09-24 08:38:08 UTC 23,630 bytes, 674 lines download raw bytes

1/*! ie11CustomProperties.js v4.1.0 | MIT License | https://git.io/fjXMN */
2!(function () {
3  'use strict'
4
5  // check for support
6  var testEl = document.createElement('i')
7  testEl.style.setProperty('--x', 'y')
8  if (testEl.style.getPropertyValue('--x') === 'y' || !testEl.msMatchesSelector) return
9
10  if (!Element.prototype.matches) Element.prototype.matches = Element.prototype.msMatchesSelector
11
12  var listeners = [],
13    root = document,
14    Observer
15
16  function qsa(el, selector) {
17    try {
18      return el.querySelectorAll(selector)
19    } catch (e) {
20      // console.warn('the Selector '+selector+' can not be parsed');
21      return []
22    }
23  }
24  function onElement(selector, callback) {
25    var listener = {
26      selector: selector,
27      callback: callback,
28      elements: new WeakMap(),
29    }
30    var els = qsa(root, listener.selector),
31      i = 0,
32      el
33    while ((el = els[i++])) {
34      listener.elements.set(el, true)
35      listener.callback.call(el, el)
36    }
37    listeners.push(listener)
38    if (!Observer) {
39      Observer = new MutationObserver(checkMutations)
40      Observer.observe(root, {
41        childList: true,
42        subtree: true,
43      })
44    }
45    checkListener(listener)
46  }
47  function checkListener(listener, target) {
48    var i = 0,
49      el,
50      els = []
51    try {
52      target && target.matches(listener.selector) && els.push(target)
53    } catch (e) {}
54    if (loaded) {
55      // ok? check inside node on innerHTML - only when loaded
56      Array.prototype.push.apply(els, qsa(target || root, listener.selector))
57    }
58    while ((el = els[i++])) {
59      if (listener.elements.has(el)) continue
60      listener.elements.set(el, true)
61      listener.callback.call(el, el)
62    }
63  }
64  function checkListeners(inside) {
65    var i = 0,
66      listener
67    while ((listener = listeners[i++])) checkListener(listener, inside)
68  }
69  function checkMutations(mutations) {
70    var j = 0,
71      i,
72      mutation,
73      nodes,
74      target
75    while ((mutation = mutations[j++])) {
76      ;(nodes = mutation.addedNodes), (i = 0)
77      while ((target = nodes[i++])) target.nodeType === 1 && checkListeners(target)
78    }
79  }
80
81  var loaded = false
82  document.addEventListener('DOMContentLoaded', function () {
83    loaded = true
84  })
85
86  // svg polyfills
87  function copyProperty(prop, from, to) {
88    var desc = Object.getOwnPropertyDescriptor(from, prop)
89    Object.defineProperty(to, prop, desc)
90  }
91  if (!('classList' in Element.prototype)) {
92    copyProperty('classList', HTMLElement.prototype, Element.prototype)
93  }
94  if (!('innerHTML' in Element.prototype)) {
95    copyProperty('innerHTML', HTMLElement.prototype, Element.prototype)
96  }
97  if (!('runtimeStyle' in Element.prototype)) {
98    // new
99    copyProperty('runtimeStyle', HTMLElement.prototype, Element.prototype)
100  }
101  if (!('sheet' in SVGStyleElement.prototype)) {
102    Object.defineProperty(SVGStyleElement.prototype, 'sheet', {
103      get: function () {
104        var all = document.styleSheets,
105          i = 0,
106          sheet
107        while ((sheet = all[i++])) {
108          if (sheet.ownerNode === this) return sheet
109        }
110      },
111    })
112  }
113
114  // main logic
115  var styles_of_getter_properties = {}
116  var drawQueue = new Set()
117  var collecting = false
118  var drawing = false
119
120  // cached regexps, better performance
121  var regFindSetters = /([\s{;])(--([A-Za-z0-9-_]*)\s*:([^;!}{]+)(!important)?)(?=\s*([;}]|$))/g
122  var regFindGetters = /([{;]\s*)([A-Za-z0-9-_]+\s*:[^;}{]*var\([^!;}{]+)(!important)?(?=\s*([;}$]|$))/g
123  var regRuleIEGetters = /-ieVar-([^:]+):/g
124  var regRuleIESetters = /-ie-([^};]+)/g
125  //const regHasVar = /var\(/;
126  var regPseudos = /:(hover|active|focus|target|visited|link|:before|:after|:first-letter|:first-line)/
127
128  function foundStyle(el) {
129    if (el.ieCP_polyfilled) return
130    if (el.ieCP_elementSheet) return
131    if (!el.sheet) return
132    if (el.href) {
133      return fetchCss(el.href, function (css) {
134        var newCss = rewriteCss(css)
135        if (css === newCss) return
136        activateStyleElement(el, newCss)
137      })
138    }
139
140    var css = el.innerHTML
141    var newCss = rewriteCss(css)
142    if (css === newCss) return
143    activateStyleElement(el, newCss)
144  }
145  onElement('style', foundStyle)
146  onElement('link[rel="stylesheet"]', foundStyle)
147  // immediate, to pass w3c-tests, bud its a bad idea
148  // addEventListener('DOMNodeInserted',function(e){ e.target.tagName === 'STYLE' && foundStyle(e.target); });
149
150  onElement('[ie-style]', function (el) {
151    var newCss = rewriteCss('{' + el.getAttribute('ie-style')).substr(1)
152    el.style.cssText += ';' + newCss
153    var found = parseRewrittenStyle(el.style)
154    if (found.getters) addGetterElement(el, found.getters, '%styleAttr')
155    if (found.setters) addSetterElement(el, found.setters)
156  })
157
158  // ie has a bug, where unknown properties at pseudo-selectors are computed at the element
159  // #el::after { -content:'x'; } => getComputedStyle(el)['-content'] == 'x'
160  // should we add something like -ieVar-pseudo_after-content:'x'?
161  function rewriteCss(css) {
162    /* uncomment if spec finished and needed by someone
163		css = css.replace(/@property ([^{]+){([^}]+)}/, function($0, prop, body){
164			prop = prop.trim();
165			const declaration = {name:prop};
166			body.split(';').forEach(function(pair){
167				const x = pair.split(':');
168				if (x[1]) declaration[ x[0].trim() ] = x[1];
169			});
170			declaration['inherits'] = declaration['inherits'].trim()==='true' ? true : false;
171			declaration['initialValue'] = declaration['initial-value'];
172			CSS.registerProperty(declaration)
173			return '/*\n @property ... removed \n*'+'/';
174		});
175		*/
176    return css
177      .replace(regFindSetters, function ($0, $1, $2, $3, $4, important) {
178        return $1 + '-ie-' + (important ? '❗' : '') + $3 + ':' + encodeValue($4)
179      })
180      .replace(regFindGetters, function ($0, $1, $2, important) {
181        return $1 + '-ieVar-' + (important ? '❗' : '') + $2 + '; ' + $2 // keep the original, so chaining works "--x:var(--y)"
182      })
183  }
184  function encodeValue(value) {
185    return value
186    return value.replace(/ /g, '␣')
187  }
188  var keywords = { initial: 1, inherit: 1, revert: 1, unset: 1 }
189  function decodeValue(value) {
190    return value
191    if (value === undefined) return
192    value = value.replace(/␣/g, ' ')
193    const trimmed = value.trim()
194    if (keywords[trimmed]) return trimmed
195    return value
196  }
197
198  function parseRewrittenStyle(style) {
199    // less memory then parameter cssText?
200
201    // ie11 can access unknown properties in stylesheets only if accessed a dashed known property
202    style['z-index'] === style && x() // do something (compare and call) just for minifiers
203
204    const cssText = style.cssText
205    var matchesGetters = cssText.match(regRuleIEGetters),
206      j,
207      match
208    if (matchesGetters) {
209      var getters = [] // eg. [border,color]
210      for (j = 0; (match = matchesGetters[j++]); ) {
211        let propName = match.slice(7, -1)
212        if (propName[0] === '❗') propName = propName.substr(1)
213        getters.push(propName)
214
215        if (!styles_of_getter_properties[propName]) styles_of_getter_properties[propName] = []
216        styles_of_getter_properties[propName].push(style)
217      }
218    }
219    var matchesSetters = cssText.match(regRuleIESetters)
220    if (matchesSetters) {
221      var setters = {} // eg. [--color:#fff, --padding:10px];
222      for (j = 0; (match = matchesSetters[j++]); ) {
223        let x = match.substr(4).split(':')
224        let propName = x[0]
225        let propValue = x[1]
226        if (propName[0] === '❗') propName = propName.substr(1)
227        setters[propName] = propValue
228      }
229    }
230    return { getters: getters, setters: setters }
231  }
232  function activateStyleElement(style, css) {
233    style.sheet.cssText = css
234    style.ieCP_polyfilled = true
235    var rules = style.sheet.rules,
236      i = 0,
237      rule // cssRules = CSSRuleList, rules = MSCSSRuleList
238    while ((rule = rules[i++])) {
239      const found = parseRewrittenStyle(rule.style)
240      if (found.getters) addGettersSelector(rule.selectorText, found.getters)
241      if (found.setters) addSettersSelector(rule.selectorText, found.setters)
242
243      // mediaQueries: redraw the hole document
244      // better add events for each element?
245      const media = rule.parentRule && rule.parentRule.media && rule.parentRule.media.mediaText
246      if (media && (found.getters || found.setters)) {
247        matchMedia(media).addListener(function () {
248          drawTree(document.documentElement)
249        })
250      }
251    }
252    redrawStyleSheets()
253  }
254
255  function addGettersSelector(selector, properties) {
256    selectorAddPseudoListeners(selector)
257    onElement(unPseudo(selector), function (el) {
258      addGetterElement(el, properties, selector)
259      drawElement(el)
260    })
261  }
262  function addGetterElement(el, properties, selector) {
263    var i = 0,
264      prop,
265      j
266    const selectors = selector.split(',') // split grouped selectors
267    el.setAttribute('iecp-needed', true)
268    if (!el.ieCPSelectors) el.ieCPSelectors = {}
269    while ((prop = properties[i++])) {
270      for (j = 0; (selector = selectors[j++]); ) {
271        const parts = selector.trim().split('::')
272        if (!el.ieCPSelectors[prop]) el.ieCPSelectors[prop] = []
273        el.ieCPSelectors[prop].push({
274          selector: parts[0],
275          pseudo: parts[1] ? '::' + parts[1] : '',
276        })
277      }
278    }
279  }
280  function addSettersSelector(selector, propVals) {
281    selectorAddPseudoListeners(selector)
282    onElement(unPseudo(selector), function (el) {
283      addSetterElement(el, propVals)
284    })
285  }
286  function addSetterElement(el, propVals) {
287    if (!el.ieCP_setters) el.ieCP_setters = {}
288    for (var prop in propVals) {
289      // eg. {foo:#fff, bar:baz}
290      el.ieCP_setters['--' + prop] = 1
291    }
292    drawTree(el)
293  }
294
295  function redrawStyleSheets() {
296    for (var prop in styles_of_getter_properties) {
297      let styles = styles_of_getter_properties[prop]
298      for (var i = 0, style; (style = styles[i++]); ) {
299        if (style.owningElement) continue
300        var value = style['-ieVar-' + prop]
301        if (!value) continue
302        value = styleComputeValueWidthVars(getComputedStyle(document.documentElement), value)
303        if (value === '') continue
304        try {
305          style[prop] = value
306        } catch (e) {}
307      }
308    }
309  }
310
311  var pseudos = {
312    hover: {
313      on: 'mouseenter',
314      off: 'mouseleave',
315    },
316    focus: {
317      on: 'focusin',
318      off: 'focusout',
319    },
320    active: {
321      on: 'CSSActivate',
322      off: 'CSSDeactivate',
323    },
324  }
325  function selectorAddPseudoListeners(selector) {
326    // ie11 has the strange behavoir, that groups of selectors are individual rules, but starting with the full selector:
327    // td, th, button { color:red } results in this rules:
328    // "td, th, button" | "th, th" | "th"
329    selector = selector.split(',')[0]
330    for (var pseudo in pseudos) {
331      var parts = selector.split(':' + pseudo)
332      if (parts.length > 1) {
333        var ending = parts[1].match(/^[^\s]*/) // ending elementpart of selector (used for not(:active))
334        let sel = unPseudo(parts[0] + ending)
335        const listeners = pseudos[pseudo]
336        onElement(sel, function (el) {
337          el.addEventListener(listeners.on, drawTreeEvent)
338          el.addEventListener(listeners.off, drawTreeEvent)
339        })
340      }
341    }
342  }
343
344  var CSSActive = null
345  document.addEventListener('mousedown', function (e) {
346    setTimeout(function () {
347      if (e.target === document.activeElement) {
348        var evt = document.createEvent('Event')
349        evt.initEvent('CSSActivate', true, true)
350        CSSActive = e.target
351        CSSActive.dispatchEvent(evt)
352      }
353    })
354  })
355  document.addEventListener('mouseup', function () {
356    if (CSSActive) {
357      var evt = document.createEvent('Event')
358      evt.initEvent('CSSDeactivate', true, true)
359      CSSActive.dispatchEvent(evt)
360      CSSActive = null
361    }
362  })
363
364  function unPseudo(selector) {
365    return selector.replace(regPseudos, '').replace(':not()', '')
366  }
367
368  // draw queue
369  function drawElement(el) {
370    drawQueue.add(el)
371    if (collecting) return
372    collecting = true
373    requestAnimationFrame(function () {
374      //setImmediate(function(){
375      collecting = false
376      drawing = true
377      drawQueue.forEach(_drawElement)
378      drawQueue.clear()
379      setTimeout(function () {
380        // mutationObserver will trigger delayed, requestAnimationFrame will miss some changes
381        drawing = false
382      })
383    })
384  }
385
386  var uniqueCounter = 0
387  function _drawElement(el) {
388    if (!el.ieCP_unique) {
389      // use el.uniqueNumber? but needs class for the css-selector => test performance
390      el.ieCP_unique = ++uniqueCounter
391      el.classList.add('iecp-u' + el.ieCP_unique)
392    }
393    var style = getComputedStyle(el)
394    let css = ''
395
396    el.runtimeStyle.cssText = '' // new
397
398    for (var prop in el.ieCPSelectors) {
399      var important = style['-ieVar-❗' + prop]
400      let valueWithVar = important || style['-ieVar-' + prop]
401      if (!valueWithVar) continue // todo, what if '0'
402      var details = {}
403      var value = styleComputeValueWidthVars(style, valueWithVar, details)
404      //if (value==='initial') value = initials[prop];
405      if (important) value += ' !important'
406      for (var i = 0, item; (item = el.ieCPSelectors[prop][i++]); ) {
407        // todo: split and use requestAnimationFrame?
408        if (item.selector === '%styleAttr') el.style[prop] = value // i dont know why but i initial have to set style also (seen in demo)
409        if (!important && details.allByRoot !== false) continue // dont have to draw root-properties
410        if (item.pseudo) {
411          css += item.selector + '.iecp-u' + el.ieCP_unique + item.pseudo + '{' + prop + ':' + value + '}\n'
412        } else {
413          el.runtimeStyle[prop] = value // new
414        }
415      }
416    }
417    elementSetCss(el, css)
418  }
419  function elementSetCss(el, css) {
420    if (!el.ieCP_styleEl && css) {
421      const styleEl = document.createElement('style')
422      styleEl.ieCP_elementSheet = 1
423      //el.appendChild(styleEl); // yes! self-closing tags can have style as children, but - if i set innerHTML, the stylesheet is lost
424      document.head.appendChild(styleEl)
425      el.ieCP_styleEl = styleEl
426    }
427    if (el.ieCP_styleEl) el.ieCP_styleEl.innerHTML = css
428  }
429  /* */
430
431  function drawTree(target) {
432    if (!target) return
433
434    target === document.documentElement && redrawStyleSheets() // new
435
436    var els = target.querySelectorAll('[iecp-needed]')
437    if (target.hasAttribute && target.hasAttribute('iecp-needed')) drawElement(target) // self
438    for (var i = 0, el; (el = els[i++]); ) drawElement(el) // tree
439  }
440  function drawTreeEvent(e) {
441    drawTree(e.target)
442  }
443
444  function findVars(str, cb) {
445    // css value parser
446    let level = 0,
447      openedLevel = null,
448      lastPoint = 0,
449      newStr = '',
450      i = 0,
451      char,
452      insideCalc
453    while ((char = str[i++])) {
454      if (char === '(') {
455        ++level
456        if (openedLevel === null && str[i - 4] + str[i - 3] + str[i - 2] === 'var') {
457          openedLevel = level
458          newStr += str.substring(lastPoint, i - 4)
459          lastPoint = i
460        }
461        if (str[i - 5] + str[i - 4] + str[i - 3] + str[i - 2] === 'calc') {
462          insideCalc = level
463        }
464      }
465      if (char === ')' && openedLevel === level) {
466        let variable = str.substring(lastPoint, i - 1).trim(),
467          fallback
468        let x = variable.indexOf(',')
469        if (x !== -1) {
470          fallback = variable.slice(x + 1)
471          variable = variable.slice(0, x)
472        }
473        newStr += cb(variable, fallback, insideCalc)
474        lastPoint = i
475        openedLevel = null
476      }
477      if (char === ')') {
478        --level
479        if (insideCalc === level) insideCalc = null
480      }
481    }
482    newStr += str.substring(lastPoint)
483    return newStr
484  }
485  function styleComputeValueWidthVars(style, valueWithVars, details) {
486    return findVars(valueWithVars, function (variable, fallback, insideCalc) {
487      var value = style.getPropertyValue(variable)
488      if (insideCalc) value = value.replace(/^calc\(/, '(') // prevent nested calc
489      if (details && style.lastPropertyServedBy !== document.documentElement) details.allByRoot = false
490      if (value === '' && fallback) value = styleComputeValueWidthVars(style, fallback, details)
491      return value
492    })
493  }
494
495  // mutation listener
496  var observer = new MutationObserver(function (mutations) {
497    if (drawing) return
498    for (var i = 0, mutation; (mutation = mutations[i++]); ) {
499      if (mutation.attributeName === 'iecp-needed') continue // why?
500      // recheck all selectors if it targets new elements?
501      drawTree(mutation.target)
502    }
503  })
504  setTimeout(function () {
505    observer.observe(document, { attributes: true, subtree: true })
506  })
507
508  // :target listener
509  var oldHash = location.hash
510  addEventListener('hashchange', function (e) {
511    var newEl = document.getElementById(location.hash.substr(1))
512    if (newEl) {
513      var oldEl = document.getElementById(oldHash.substr(1))
514      drawTree(newEl)
515      drawTree(oldEl)
516    } else {
517      drawTree(document)
518    }
519    oldHash = location.hash
520  })
521
522  // add owningElement to Element.style
523  var descriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'style')
524  var styleGetter = descriptor.get
525  descriptor.get = function () {
526    const style = styleGetter.call(this)
527    style.owningElement = this
528    return style
529  }
530  Object.defineProperty(HTMLElement.prototype, 'style', descriptor)
531
532  // add computedFor to computed style-objects
533  var originalGetComputed = getComputedStyle
534  window.getComputedStyle = function (el) {
535    var style = originalGetComputed.apply(this, arguments)
536    style.computedFor = el
537    //style.pseudoElt = pseudoElt; //not needed at the moment
538    return style
539  }
540
541  // getPropertyValue / setProperty hooks
542  var StyleProto = CSSStyleDeclaration.prototype
543
544  var oldGetP = StyleProto.getPropertyValue
545  StyleProto.getPropertyValue = function (property) {
546    this.lastPropertyServedBy = false
547    property = property.trim()
548
549    /* *
550		if (this.owningElement) {
551			const ieProperty = '-ieVar-'+property;
552			const iePropertyImportant = '-ieVar-❗'+property;
553			let value = this[iePropertyImportant] || this[ieProperty];
554			if (value !== undefined) {
555				// todo, test if syntax valid
556				return value;
557			}
558		}
559		/* */
560
561    if (property[0] !== '-' || property[1] !== '-') return oldGetP.apply(this, arguments)
562    const undashed = property.substr(2)
563    const ieProperty = '-ie-' + undashed
564    const iePropertyImportant = '-ie-❗' + undashed
565    let value = decodeValue(this[iePropertyImportant] || this[ieProperty])
566
567    if (this.computedFor) {
568      // computedStyle
569      if (value !== undefined && !inheritingKeywords[value]) {
570        //if (regHasVar.test(value))  // todo: to i need this check?!!! i think its faster without
571        value = styleComputeValueWidthVars(this, value)
572        this.lastPropertyServedBy = this.computedFor
573      } else {
574        // inherited
575        if (inheritingKeywords[value] || !register[property] || register[property].inherits) {
576          //let el = this.pseudoElt ? this.computedFor : this.computedFor.parentNode;
577          let el = this.computedFor.parentNode
578          while (el.nodeType === 1) {
579            // how slower would it be to getComputedStyle for every element, not just with defined ieCP_setters
580            if (el.ieCP_setters && el.ieCP_setters[property]) {
581              // i could make
582              // value = el.nodeType ? getComputedStyle(this.computedFor.parentNode).getPropertyValue(property)
583              // but i fear performance, stupid?
584              var style = getComputedStyle(el)
585              var tmpVal = decodeValue(style[iePropertyImportant] || style[ieProperty])
586              if (tmpVal !== undefined) {
587                // calculated style from current element not from the element the value was inherited from! (style, value)
588                //value = tmpVal; if (regHasVar.test(tmpVal))  // todo: to i need this check?!!! 
588i think its faster without
589                value = styleComputeValueWidthVars(this, tmpVal)
590                this.lastPropertyServedBy = el
591                break
592              }
593            }
594            el = el.parentNode
595          }
596        }
597      }
598      if (value === 'initial') return ''
599    }
600    //if ((value === undefined || value === 'initial') && register[property]) value = register[property].initialValue; // todo?
601    if (value === undefined && register[property]) value = register[property].initialValue
602    if (value === undefined) return ''
603    return value
604  }
605  var inheritingKeywords = { inherit: 1, revert: 1, unset: 1 }
606
607  var oldSetP = StyleProto.setProperty
608  StyleProto.setProperty = function (property, value, prio) {
609    if (property[0] !== '-' || property[1] !== '-') return oldSetP.apply(this, arguments)
610    const el = this.owningElement
611    if (el) {
612      if (!el.ieCP_setters) el.ieCP_setters = {}
613      el.ieCP_setters[property] = 1
614    }
615    property = '-ie-' + (prio === 'important' ? '❗' : '') + property.substr(2)
616    this.cssText += '; ' + property + ':' + encodeValue(value) + ';'
617    //this[property] = value;
618    //		el === document.documentElement && redrawStyleSheets(); new in drawTree
619    el && drawTree(el) // its delayed internal
620  }
621
622  /*
623	var descriptor = Object.getOwnPropertyDescriptor(StyleProto, 'cssText');
624	var cssTextGetter = descriptor.get;
625	var cssTextSetter = descriptor.set;
626	// descriptor.get = function () {
627	// 	const style = styleGetter.call(this);
628	// 	style.owningElement = this;
629	// 	return style;
630	// }
631	descriptor.set = function (css) {
632		var el = this.owningElement;
633		if (el) {
634			css = rewriteCss('{'+css).substr(1);
635			cssTextSetter.call(this, css);
636			var found = parseRewrittenStyle(this);
637			if (found.getters) addGetterElement(el, found.getters, '%styleAttr');
638			if (found.setters) addSetterElement(el, found.setters);
639			return;
640		}
641		return cssTextSetter.call(this, css);
642	}
643	Object.defineProperty(StyleProto, 'cssText', descriptor);
644	*/
645
646  if (!window.CSS) window.CSS = {}
647  var register = {}
648  CSS.registerProperty = function (options) {
649    register[options.name] = options
650  }
651
652  // fix "initial" keyword with generated custom properties, this is not supported ad all by ie, should i make a separate "inherit"-polyfill?
653  /*
654	const computed = getComputedStyle(document.documentElement)
655	const initials = {};
656	for (let i in computed) {
657		initials[i.replace(/([A-Z])/, function(x){ return '-'+x.toLowerCase(x) })] = computed[i];
658	}
659	initials['display'] = 'inline';
660	*/
661
662  // utils
663  function fetchCss(url, callback) {
664    var request = new XMLHttpRequest()
665    request.open('GET', url)
666    request.overrideMimeType('text/css')
667    request.onload = function () {
668      if (request.status >= 200 && request.status < 400) {
669        callback(request.responseText)
670      }
671    }
672    request.send()
673  }
674})()

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.