JSFiddle - React, Tailwind, and code Playground

by DukeLeNoir

JavaScript

// Safari bug
// ==========
//
// Two strings, that share a prefix after a regexp normalization,
// are used as keys in an object. Then, they are traversed character
// by character and recomposed into another string by concatenation,
// and each is put in an array. When they are used to index the object,
// the second one is not found among the keys: the reason is that it
// contains a null byte (copy/paste it into a file and inspect the binary
// representation, e.g. with `xxd`, to see that).
//
// NOTES:
//  1. One string, before normalization, has to contain a 2-bytes character
//  2. Using the strings as object keys and using concatenation both seem necessary
//  3. If the corrupted string is "touched" before being used to index the object,
//     it "fixes itself". By "touched" I mean that it is logged with console.log, or
//     used in a comparison, or any String.prototype method is called on it.
//  4. Interestingly, if a Object.prototype method is called on the string instead,
//     the null byte does not get removed, and the bug occurs.

var strings = ['xxĀ', 'xxx'].map(str => str.replace(/\W/, ''))
var map = {}

strings.forEach((string, i) => {
  map[string] = i
})

var prefix = ''
var words = []

strings.forEach(string => {
  for (var i = 0; i < string.length; i++) {
    if (prefix.length < i + 1) {
      prefix = prefix + string[i]
    }
  }

  words.push(prefix)
})

words.forEach(word => {
  if (map[word] == null) {
    alert("This should not happen! String corrupted with null byte: " + word)
  } else {
    alert("All fine: " + word)
  }
})