From 1b172e02cde4bca53c0afd3bfc367f81b6b1a90b Mon Sep 17 00:00:00 2001 From: Demonstrandum Date: Mon, 24 Jul 2023 09:43:17 +0200 Subject: [PATCH] Avoid redefining global properties. --- lib/BasicCanvas.js | 233 ++++++++++++++++++++++++--------------------- 1 file changed, 123 insertions(+), 110 deletions(-) diff --git a/lib/BasicCanvas.js b/lib/BasicCanvas.js index d5be8c8..fdc7658 100755 --- a/lib/BasicCanvas.js +++ b/lib/BasicCanvas.js @@ -19,11 +19,18 @@ if (in_node) { } } +let already_patched = (typeof window !== 'undefined' + && typeof window._basiccanvas_imported !== 'undefined') + || Object.prototype.hasOwnProperty('clone'); + // Basic semi-related tools. export const clone = obj => Object.assign(Object.create(Object.getPrototypeOf(obj)), obj); -Object.prototype.clone = function () { - return clone(this); -}; + +if (!already_patched) { + Object.prototype.clone = function () { + return clone(this); + }; +} export const type = element => ( ({}).toString.call(element).match(/\s([a-zA-Z]+)/)[1].toLowerCase() @@ -60,120 +67,126 @@ export const style = string => { export const css = (s, ...exps) => style(plain(s, ...exps)); // Patching and Monkey Patching prototypes. -Math.TAU = 2 * Math.PI; -Math.HALF_PI = Math.PI * 0.5; -Math.triangle = t => Math.abs(((t - 1) % 4) - 2) - 1; +if (!already_patched) { + Math.TAU = 2 * Math.PI; + Math.HALF_PI = Math.PI * 0.5; + Math.triangle = t => Math.abs(((t - 1) % 4) - 2) - 1; -Number.prototype.roundTo = function (dp) { - return parseFloat((this).toFixed(dp)); -}; -Number.prototype.times = function (fn) { - for (let i = 1; i <= this.valueOf(); ++i) - fn(i); -}; + Number.prototype.roundTo = function (dp) { + return parseFloat((this).toFixed(dp)); + }; + Number.prototype.times = function (fn) { + for (let i = 1; i <= this.valueOf(); ++i) + fn(i); + }; -Array.prototype.each = Array.prototype.forEach; -Array.prototype.select = Array.prototype.filter; -Array.prototype.reject = function (lambda, array) { - return this.filter((e) => !lambda(e), array) -}; -Array.prototype.mag = function () { - return Math.sqrt(this.reduce((i, j) => i + j ** 2, 0)); -}; -Array.prototype.normalize = function () { - if (this.every(e => e === 0)) { - return this; - } - return this.map(e => e / this.mag()); -}; -Array.prototype.rotate = function (theta, origin=[0,0]) { - return [ // Only 2D - origin[0] + (this[0] - origin[0]) * Math.cos(theta) - (this[1] - origin[1]) * Math.sin(theta), - origin[1] + (this[0] - origin[0]) * Math.sin(theta) + (this[1] - origin[1]) * Math.cos(theta) - ]; -}; -Object.defineProperty(Array.prototype, 'x', { - get: function x() { - return this[0]; - }, - set: function x(new_x) { - return this[0] = new_x; - } -}); -Object.defineProperty(Array.prototype, 'y', { - get: function y() { - return this[1]; - }, - set: function y(new_y) { - return this[1] = new_y; - } -}); -Object.defineProperty(Array.prototype, 'z', { - get: function y() { - return this[2]; - }, - set: function z(new_z) { - return this[2] = new_z; - } -}); -Object.defineProperty(Array.prototype, 'first', { - get: function first() { - return this[0]; - }, - set: function first(other) { - return this[0] = other; - } -}); -Object.defineProperty(Array.prototype, 'last', { - get: function last() { - return this[this.length - 1]; - }, - set: function last(other) { - return this[this.length - 1] = other; - } -}); -Object.defineProperty(Array.prototype, 'tail', { - get: function tail() { - return this.slice(1); - } -}); -Object.defineProperty(Array.prototype, 'point', { - get: function point() { - return Point(this[0], this[1]); - } -}); -Array.prototype.head = Array.prototype.first; - -String.prototype.replaceAll = function (search, replacement) { - return this.replace(new RegExp(search, 'g'), replacement); -}; + Array.prototype.each = Array.prototype.forEach; + Array.prototype.select = Array.prototype.filter; + Array.prototype.reject = function (lambda, array) { + return this.filter((e) => !lambda(e), array) + }; + Array.prototype.mag = function () { + return Math.sqrt(this.reduce((i, j) => i + j ** 2, 0)); + }; + Array.prototype.normalize = function () { + if (this.every(e => e === 0)) { + return this; + } + return this.map(e => e / this.mag()); + }; + Array.prototype.rotate = function (theta, origin=[0,0]) { + return [ // Only 2D + origin[0] + (this[0] - origin[0]) * Math.cos(theta) - (this[1] - origin[1]) * Math.sin(theta), + origin[1] + (this[0] - origin[0]) * Math.sin(theta) + (this[1] - origin[1]) * Math.cos(theta) + ]; + }; + Object.defineProperty(Array.prototype, 'x', { + get: function x() { + return this[0]; + }, + set: function x(new_x) { + return this[0] = new_x; + } + }); + Object.defineProperty(Array.prototype, 'y', { + get: function y() { + return this[1]; + }, + set: function y(new_y) { + return this[1] = new_y; + } + }); + Object.defineProperty(Array.prototype, 'z', { + get: function y() { + return this[2]; + }, + set: function z(new_z) { + return this[2] = new_z; + } + }); + Object.defineProperty(Array.prototype, 'first', { + get: function first() { + return this[0]; + }, + set: function first(other) { + return this[0] = other; + } + }); + Object.defineProperty(Array.prototype, 'last', { + get: function last() { + return this[this.length - 1]; + }, + set: function last(other) { + return this[this.length - 1] = other; + } + }); + Object.defineProperty(Array.prototype, 'tail', { + get: function tail() { + return this.slice(1); + } + }); + Object.defineProperty(Array.prototype, 'point', { + get: function point() { + return Point(this[0], this[1]); + } + }); + Array.prototype.head = Array.prototype.first; -HTMLElement.prototype.html = function (s, ...exps) { - const contain = document.createElement('del'); - contain.style.textDecoration = 'none'; - contain.innerHTML = String.raw(s, ...exps); - this.appendChild(contain); -}; + String.prototype.replaceAll = function (search, replacement) { + return this.replace(new RegExp(search, 'g'), replacement); + }; + + HTMLElement.prototype.html = function (s, ...exps) { + const contain = document.createElement('del'); + contain.style.textDecoration = 'none'; + contain.innerHTML = String.raw(s, ...exps); + this.appendChild(contain); + }; -HTMLElement.prototype.css = function (properties) { - for (const property in properties) { - if (Object.prototype.hasOwnProperty.call(properties, property)) { - this.style[property] = properties[property]; + HTMLElement.prototype.css = function (properties) { + for (const property in properties) { + if (Object.prototype.hasOwnProperty.call(properties, property)) { + this.style[property] = properties[property]; + } } - } -}; + }; -Object.prototype.omap = function (lambda) { - return Object.assign({}, - ...Object.keys(this).map(k => - ({[k]: lambda(this[k])}))); -}; + Object.prototype.omap = function (lambda) { + return Object.assign({}, + ...Object.keys(this).map(k => + ({[k]: lambda(this[k])}))); + }; -Object.defineProperty(HTMLElement.prototype, 'elem', { - get: function elem() { - return this; - }, -}); + Object.defineProperty(HTMLElement.prototype, 'elem', { + get: function elem() { + return this; + }, + }); +} + +if (typeof window !== 'undefined') { + window._basiccanvas_imported = true; +} // More interaction-specific tools export const click = (handler, canvas = null) => {