Skip to content

Instantly share code, notes, and snippets.

@rattrayalex
Created September 6, 2017 07:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rattrayalex/2ec894c546f98627bcfc78b35e4426be to your computer and use it in GitHub Desktop.
Save rattrayalex/2ec894c546f98627bcfc78b35e4426be to your computer and use it in GitHub Desktop.
Example Match Polyfill with "tests"
if (!Symbol.matches) {
const DEFINE_PROPERTY = "defineProperty";
// define Symbol.matches
Object[DEFINE_PROPERTY](Symbol, "matches", {
configurable: false,
writable: false,
value: Symbol("matches"),
});
function defineMatch(O, fn) {
Object[DEFINE_PROPERTY](O, Symbol.matches, {
writable: false,
configurable: false,
enumerable: false,
value: fn
});
}
// Classes
defineMatch(Function.prototype, function (x) {
return x instanceof this;
});
// Primitive Classes
defineMatch(Number, function (x) {
return typeof x === "number";
});
defineMatch(String, function (x) {
return typeof x === "string";
});
defineMatch(Boolean, function (x) {
return typeof x === "boolean";
});
// Objects & Arrays (very unsure of this)
defineMatch(Object.prototype, function (x) {
return _.isMatch(x, this);
});
// RegExp
defineMatch(RegExp.prototype, function (x) {
return this.test(x);
});
// Sets
defineMatch(Set.prototype, function (x) {
return this.has(x);
});
// Math.Range(min, max) – (very unsure of this)
Object[DEFINE_PROPERTY](Math, "Range", {
configurable: false,
writable: false,
value: function Range(min, max) {
if (!(this instanceof Range)) {
return new Range(min, max);
}
this.min = min == null ? -Infinity : min;
this.max = max == null ? Infinity : max;
},
});
defineMatch(Math.Range.prototype, function (x) {
// TODO: allow Range/Range comparisons, return true on overlap(?)
return typeof x === "number" && this.min <= x && this.max >= x;
});
}
function isMatch(pattern, x) {
return Boolean(
x != null && Symbol.matches in pattern
? pattern[Symbol.matches](x)
: x === pattern
);
}
class Foo {}
class FooChild extends Foo {}
class FooSibling {}
class Bar {
static [Symbol.matches](x) {
return x === "bar"
}
}
function OldSchoolCool() {}
console.log([
[isMatch(Array, []), true],
[isMatch(Array, [4, 5]), true],
[isMatch(Array, { 0: 1, length: 1 }), false],
[isMatch(Number, 1), true],
[isMatch(Number, "1"), false],
[isMatch(String, "hi"), true],
[isMatch(String, 1), false],
[isMatch(Boolean, true), true],
[isMatch(Boolean, false), true],
[isMatch(Boolean, null), false],
[isMatch(Boolean, ""), false],
[isMatch(Boolean, 0), false],
[isMatch(Boolean, 1), false],
[isMatch(Foo, new Foo()), true],
[isMatch(Foo, new FooChild()), true],
[isMatch(FooChild, new FooChild()), true],
[isMatch(FooChild, new Foo()), false],
[isMatch(Foo, new FooSibling()), false],
[isMatch(Foo, Foo), false],
[isMatch(Foo, FooChild), false],
[isMatch(Foo, {}), false],
[isMatch(OldSchoolCool, new OldSchoolCool()), true],
[isMatch(OldSchoolCool, OldSchoolCool()), false],
[isMatch(OldSchoolCool, OldSchoolCool), false],
[isMatch(Bar, "bar"), true],
[isMatch(Bar, new Bar()), false],
[isMatch(Bar, Bar), false],
[isMatch(/f(o+)/, "fo"), true],
[isMatch(/f(o+)/, "foooo"), true],
[isMatch(/f(o+)/, "f"), false],
[isMatch(/f(o+)/, null), false],
[isMatch(new Set(["hi", "there"]), "hi"), true],
[isMatch(new Set(["hi", "there"]), "there"), true],
[isMatch(new Set(["hi", "there"]), "bye"), false],
[isMatch(new Set(["hi", "there"]), 0), false],
[isMatch(new Set(["hi", "there"]), "0"), false],
[isMatch(new Set(["hi", "there"]), new Set()), false],
[isMatch(Math.Range(0, 1), 1), true],
[isMatch(Math.Range(0, 1), 2), false],
[isMatch(new Math.Range(0, 1), 1), true],
[isMatch(new Math.Range(0, 1), 0), true],
[isMatch(new Math.Range(-10, 10), 2), true],
[isMatch(new Math.Range(null, 10), 2), true],
[isMatch(new Math.Range(null, 10), 12), false],
[isMatch(new Math.Range(-10, null), 2), true],
[isMatch(new Math.Range(-10, null), -12), false],
].map(x => x.toString()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment