Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@garfish/utils

Package Overview
Dependencies
Maintainers
8
Versions
367
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@garfish/utils - npm Package Compare versions

Comparing version 0.0.9 to 0.0.12

346

dist/utils.cjs.js

@@ -33,7 +33,6 @@ 'use strict';

},
// 测试环境允许 delete
configurable: true ,
});
}
// 数组变为对象 `['a'] => { a: true }`
// Array to Object `['a'] => { a: true }`
function makeMap(list) {

@@ -46,2 +45,5 @@ const map = Object.create(null);

}
function inBrowser() {
return typeof window !== 'undefined';
}
const warnPrefix = '[Garfish warning]';

@@ -76,9 +78,2 @@ const processError = (error, fn) => {

}
// 将字符串被设置为对象属性名时,会被尝试改造为常量化版本,避免浏览器重复产生缓存
function internFunc(internalizeString) {
// 暂时不考虑Hash-collision,https://en.wikipedia.org/wiki/Collision_(computer_science)。v8貌似在16383长度时会发生hash-collision,经过测试后发现正常
const temporaryOb = {};
temporaryOb[internalizeString] = true;
return Object.keys(temporaryOb)[0];
}
function validURL(str) {

@@ -93,5 +88,14 @@ const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol

}
// When the string is set as the object property name,
// it will be attempted to be transformed into a constant version to avoid repeated caching by the browser
function internFunc(internalizeString) {
// Don't consider "Hash-collision,https://en.wikipedia.org/wiki/Collision_(computer_science)"
// v8貌似在 16383 长度时会发生 hash-collision,经过测试后发现正常
const temporaryOb = {};
temporaryOb[internalizeString] = true;
return Object.keys(temporaryOb)[0];
}
function evalWithEnv(code, params) {
const keys = Object.keys(params);
// 不可使用随机值,否则无法作为常量字符串复用
// No random value can be used, otherwise it cannot be reused as a constant string
const randomValKey = '__garfish__exec_temporary__';

@@ -144,7 +148,2 @@ const vales = keys.map((k) => `window.${randomValKey}.${k}`);

}
function mixins(...list) {
return function (target) {
Object.assign(target.prototype, ...list);
};
}
// 有些测试 jest.mock 不好测,可用这个工具方法

@@ -175,27 +174,26 @@ function callTestCallback(obj, ...args) {

}
// 深度合并两个对象,能处理循环引用,后面的覆盖前面的,可选数组去重
// Deeply merge two objects, can handle circular references, the latter overwrite the previous
function deepMerge(o, n, dp) {
const lRecord = new WeakMap();
const rRecord = new WeakMap();
const vRecord = new WeakMap();
const leftRecord = new WeakMap();
const rightRecord = new WeakMap();
const valueRecord = new WeakMap();
const isArray = Array.isArray;
const isAllRefs = (a, b) => {
// 判断 merge 左右两边,不需要用到 vRecord
if (lRecord.has(a) || rRecord.has(a)) {
return lRecord.has(b) || rRecord.has(b);
if (leftRecord.has(a) || rightRecord.has(a)) {
return leftRecord.has(b) || rightRecord.has(b);
}
};
const clone = (v) => {
// 深拷贝
// Deep clone
if (isPrimitive(v) || typeof v === 'function') {
return v;
}
else if (vRecord.has(v)) {
return vRecord.get(v);
else if (valueRecord.has(v)) {
return valueRecord.get(v);
}
else if (lRecord.has(v)) {
return lRecord.get(v);
else if (leftRecord.has(v)) {
return leftRecord.get(v);
}
else if (rRecord.has(v)) {
return rRecord.get(v);
else if (rightRecord.has(v)) {
return rightRecord.get(v);
}

@@ -205,15 +203,15 @@ else if (isArray(v)) {

v = unique(v);
const res = [];
vRecord.set(v, res);
const arr = [];
valueRecord.set(v, arr);
for (let i = 0, len = v.length; i < len; i++) {
res[i] = clone(v[i]);
arr[i] = clone(v[i]);
}
return res;
return arr;
}
else if (typeof v === 'object') {
const res = {};
vRecord.set(v, res);
const obj = {};
valueRecord.set(v, obj);
const keys = Reflect.ownKeys(v);
keys.forEach((key) => (res[key] = clone(v[key])));
return res;
keys.forEach((key) => (obj[key] = clone(v[key])));
return obj;
}

@@ -235,7 +233,7 @@ };

const res = {};
const lkeys = Reflect.ownKeys(l);
const rkeys = Reflect.ownKeys(r);
lRecord.set(l, res);
rRecord.set(r, res);
lkeys.forEach((key) => {
const leftKeys = Reflect.ownKeys(l);
const rightKeys = Reflect.ownKeys(r);
leftRecord.set(l, res);
rightRecord.set(r, res);
leftKeys.forEach((key) => {
const lv = l[key];

@@ -250,17 +248,17 @@ const rv = r[key];

res[key] = isAllRefs(lv, rv)
? lRecord.get(lv) // 左边右边同一个值,取哪个都行
? leftRecord.get(lv) // The same value on the left and right, whichever is OK
: mergeObject(lv, rv);
}
else {
res[key] = setValue(rRecord, rv);
res[key] = setValue(rightRecord, rv);
}
}
else {
res[key] = setValue(lRecord, lv);
res[key] = setValue(leftRecord, lv);
}
});
rkeys.forEach((key) => {
rightKeys.forEach((key) => {
if (hasOwn(res, key))
return;
res[key] = setValue(rRecord, r[key]);
res[key] = setValue(rightRecord, r[key]);
});

@@ -271,5 +269,61 @@ return res;

}
function inBrowser() {
return typeof window !== 'undefined';
// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
function isAbsolute(url) {
// `c:\\` 这种 case 返回 false,在浏览器中使用本地图片,应该用 file 协议
if (!/^[a-zA-Z]:\\/.test(url)) {
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)) {
return true;
}
}
return false;
}
function transformUrl(resolvePath, curPath) {
const baseUrl = new URL(resolvePath, location.href);
const realPath = new URL(curPath, baseUrl.href);
return realPath.href;
}
function findTarget(el, selectors) {
for (const s of selectors) {
const target = el.querySelector(s);
if (target)
return target;
}
return el;
}
function setDocCurrentScript(target, code, define, url, async) {
if (!target)
return noop;
const el = document.createElement('script');
if (async) {
el.setAttribute('async', 'true');
}
if (url) {
el.setAttribute('src', url);
}
else if (code) {
el.textContent = code;
}
const set = (val) => {
try {
if (define) {
Object.defineProperty(target, 'currentScript', {
value: val,
writable: true,
configurable: true,
});
}
else {
target.currentScript = val;
}
}
catch (e) {
{
warn(e);
}
}
};
set(el);
return () => set(null);
}

@@ -420,61 +474,137 @@ // copy from https://github.com/getsentry/sentry-javascript/blob/6.4.0/packages/browser/src/tracekit.ts

// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
function isAbsolute(url) {
// `c:\\` 这种 case 返回 false,在浏览器中使用本地图片,应该用 file 协议
if (!/^[a-zA-Z]:\\/.test(url)) {
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)) {
return true;
const xChar = 120; // "x" char
const colonChar = 58; // ":" char
const ns = 'http://www.w3.org/2000/svg';
const xlinkNS = 'http://www.w3.org/1999/xlink'; // xmlns:xlink
const xmlNS = 'http://www.w3.org/XML/1998/namespace'; // xmlns
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element
const SVG_TAGS = 'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +
'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +
'feDistanceLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +
'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +
'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +
'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +
'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
'text,textPath,title,tspan,unknown,use,view';
const isSVG = makeMap(SVG_TAGS.split(','));
function attributesString(attributes) {
if (!attributes || attributes.length === 0)
return '';
return attributes.reduce((total, { key, value }) => {
return total + (value ? `${key}="${value}" ` : key);
}, '');
}
const DOMApis = {
isText(node) {
return node && node.type === 'text';
},
isNode(node) {
return node && node.type === 'element';
},
isCommentNode(node) {
return node && node.type === 'comment';
},
isCssLinkNode(node) {
if (this.isNode(node) && node.tagName === 'link') {
return !!node.attributes.find(({ key, value }) => key === 'rel' && value === 'stylesheet');
}
}
return false;
}
function transformUrl(resolvePath, curPath) {
const baseUrl = new URL(resolvePath, location.href);
const realPath = new URL(curPath, baseUrl.href);
return realPath.href;
}
function findTarget(el, selectors) {
for (const s of selectors) {
const target = el.querySelector(s);
if (target)
return target;
}
return el;
}
function setDocCurrentScript(target, code, define, url, async) {
if (!target)
return noop;
const el = document.createElement('script');
if (async) {
el.setAttribute('async', 'true');
}
if (url) {
el.setAttribute('src', url);
}
else if (code) {
el.textContent = code;
}
const set = (val) => {
try {
if (define) {
Object.defineProperty(target, 'currentScript', {
value: val,
writable: true,
configurable: true,
});
return false;
},
isIconLinkNode(node) {
if (this.isNode(node) && node.tagName === 'link') {
return !!node.attributes.find(({ key, value }) => key === 'rel' && value === 'icon');
}
return false;
},
isPrefetchJsLinkNode(node) {
if (!this.isNode(node) || node.tagName !== 'link')
return false;
let hasRelAttr, hasAsAttr;
for (const { key, value } of node.attributes) {
if (key === 'rel') {
hasRelAttr = true;
if (value !== 'preload' && value !== 'prefetch') {
return false;
}
}
else {
target.currentScript = val;
else if (key === 'as') {
hasAsAttr = true;
if (value !== 'script')
return false;
}
}
catch (e) {
{
warn(e);
return Boolean(hasRelAttr && hasAsAttr);
},
removeElement(el) {
const parentNode = el && el.parentNode;
if (parentNode) {
parentNode.removeChild(el);
}
},
createElement(node) {
const { tagName, attributes } = node;
const el = isSVG(tagName)
? document.createElementNS(ns, tagName)
: document.createElement(tagName);
this.applyAttributes(el, attributes);
return el;
},
createTextNode(node) {
return document.createTextNode(node.content);
},
createStyleNode(content) {
const el = document.createElement('style');
content && (el.textContent = content);
this.applyAttributes(el, [{ key: 'type', value: 'text/css' }]);
return el;
},
createLinkCommentNode(node) {
if (this.isNode(node)) {
const ps = attributesString(node.attributes);
return `<link ${ps.slice(0, -1)}></link>`;
}
else {
node = node ? `src="${node}" ` : '';
return document.createComment(`<link ${node}execute by garfish(dynamic)></link>`);
}
},
createScriptCommentNode(node) {
if (this.isNode(node)) {
const { attributes, children } = node;
const ps = attributesString(attributes);
const code = (children === null || children === void 0 ? void 0 : children[0]) ? children[0].content : '';
return document.createComment(`<script ${ps} execute by garfish>${code}</script>`);
}
else {
const { src, code } = node;
const url = src ? `src="${src}" ` : '';
return document.createComment(`<script ${url}execute by garfish(dynamic)>${code}</script>`);
}
},
applyAttributes(el, attributes) {
if (!attributes || attributes.length === 0)
return;
for (const { key, value } of attributes) {
if (value === null) {
el.setAttribute(key, '');
}
else if (typeof value === 'string') {
if (key.charCodeAt(0) !== xChar) {
el.setAttribute(key, value);
}
else if (key.charCodeAt(3) === colonChar) {
el.setAttributeNS(xmlNS, key, value);
}
else if (key.charCodeAt(5) === colonChar) {
el.setAttributeNS(xlinkNS, key, value);
}
else {
el.setAttribute(key, value);
}
}
}
};
set(el);
return () => set(null);
}
},
};

@@ -489,3 +619,3 @@ const __GARFISH_FLAG__ = Symbol.for('__GARFISH_FLAG__');

let type = '';
let subtype = '';
let subType = '';
while (idx < input.length && input[idx] !== '/') {

@@ -501,11 +631,11 @@ type += input[idx];

while (idx < input.length && input[idx] !== ';') {
subtype += input[idx];
subType += input[idx];
idx++;
}
subtype = subtype.replace(/[ \t\n\r]+$/, '');
if (subtype.length === 0)
subType = subType.replace(/[ \t\n\r]+$/, '');
if (subType.length === 0)
return null;
return {
type: type.toLocaleLowerCase(),
subtype: subtype.toLocaleLowerCase(),
subtype: subType.toLocaleLowerCase(),
};

@@ -587,2 +717,3 @@ }

exports.DOMApis = DOMApis;
exports.__GARFISH_FLAG__ = __GARFISH_FLAG__;

@@ -614,3 +745,2 @@ exports.assert = assert;

exports.makeMap = makeMap;
exports.mixins = mixins;
exports.nextTick = nextTick;

@@ -617,0 +747,0 @@ exports.noop = noop;

@@ -28,7 +28,6 @@ 'use strict';

},
// 测试环境允许 delete
configurable: false,
});
}
// 数组变为对象 `['a'] => { a: true }`
// Array to Object `['a'] => { a: true }`
function makeMap(list) {

@@ -41,2 +40,5 @@ const map = Object.create(null);

}
function inBrowser() {
return typeof window !== 'undefined';
}
const warnPrefix = '[Garfish warning]';

@@ -71,9 +73,2 @@ const processError = (error, fn) => {

}
// 将字符串被设置为对象属性名时,会被尝试改造为常量化版本,避免浏览器重复产生缓存
function internFunc(internalizeString) {
// 暂时不考虑Hash-collision,https://en.wikipedia.org/wiki/Collision_(computer_science)。v8貌似在16383长度时会发生hash-collision,经过测试后发现正常
const temporaryOb = {};
temporaryOb[internalizeString] = true;
return Object.keys(temporaryOb)[0];
}
function validURL(str) {

@@ -88,5 +83,14 @@ const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol

}
// When the string is set as the object property name,
// it will be attempted to be transformed into a constant version to avoid repeated caching by the browser
function internFunc(internalizeString) {
// Don't consider "Hash-collision,https://en.wikipedia.org/wiki/Collision_(computer_science)"
// v8貌似在 16383 长度时会发生 hash-collision,经过测试后发现正常
const temporaryOb = {};
temporaryOb[internalizeString] = true;
return Object.keys(temporaryOb)[0];
}
function evalWithEnv(code, params) {
const keys = Object.keys(params);
// 不可使用随机值,否则无法作为常量字符串复用
// No random value can be used, otherwise it cannot be reused as a constant string
const randomValKey = '__garfish__exec_temporary__';

@@ -139,7 +143,2 @@ const vales = keys.map((k) => `window.${randomValKey}.${k}`);

}
function mixins(...list) {
return function (target) {
Object.assign(target.prototype, ...list);
};
}
// 有些测试 jest.mock 不好测,可用这个工具方法

@@ -170,27 +169,26 @@ function callTestCallback(obj, ...args) {

}
// 深度合并两个对象,能处理循环引用,后面的覆盖前面的,可选数组去重
// Deeply merge two objects, can handle circular references, the latter overwrite the previous
function deepMerge(o, n, dp) {
const lRecord = new WeakMap();
const rRecord = new WeakMap();
const vRecord = new WeakMap();
const leftRecord = new WeakMap();
const rightRecord = new WeakMap();
const valueRecord = new WeakMap();
const isArray = Array.isArray;
const isAllRefs = (a, b) => {
// 判断 merge 左右两边,不需要用到 vRecord
if (lRecord.has(a) || rRecord.has(a)) {
return lRecord.has(b) || rRecord.has(b);
if (leftRecord.has(a) || rightRecord.has(a)) {
return leftRecord.has(b) || rightRecord.has(b);
}
};
const clone = (v) => {
// 深拷贝
// Deep clone
if (isPrimitive(v) || typeof v === 'function') {
return v;
}
else if (vRecord.has(v)) {
return vRecord.get(v);
else if (valueRecord.has(v)) {
return valueRecord.get(v);
}
else if (lRecord.has(v)) {
return lRecord.get(v);
else if (leftRecord.has(v)) {
return leftRecord.get(v);
}
else if (rRecord.has(v)) {
return rRecord.get(v);
else if (rightRecord.has(v)) {
return rightRecord.get(v);
}

@@ -200,15 +198,15 @@ else if (isArray(v)) {

v = unique(v);
const res = [];
vRecord.set(v, res);
const arr = [];
valueRecord.set(v, arr);
for (let i = 0, len = v.length; i < len; i++) {
res[i] = clone(v[i]);
arr[i] = clone(v[i]);
}
return res;
return arr;
}
else if (typeof v === 'object') {
const res = {};
vRecord.set(v, res);
const obj = {};
valueRecord.set(v, obj);
const keys = Reflect.ownKeys(v);
keys.forEach((key) => (res[key] = clone(v[key])));
return res;
keys.forEach((key) => (obj[key] = clone(v[key])));
return obj;
}

@@ -230,7 +228,7 @@ };

const res = {};
const lkeys = Reflect.ownKeys(l);
const rkeys = Reflect.ownKeys(r);
lRecord.set(l, res);
rRecord.set(r, res);
lkeys.forEach((key) => {
const leftKeys = Reflect.ownKeys(l);
const rightKeys = Reflect.ownKeys(r);
leftRecord.set(l, res);
rightRecord.set(r, res);
leftKeys.forEach((key) => {
const lv = l[key];

@@ -245,17 +243,17 @@ const rv = r[key];

res[key] = isAllRefs(lv, rv)
? lRecord.get(lv) // 左边右边同一个值,取哪个都行
? leftRecord.get(lv) // The same value on the left and right, whichever is OK
: mergeObject(lv, rv);
}
else {
res[key] = setValue(rRecord, rv);
res[key] = setValue(rightRecord, rv);
}
}
else {
res[key] = setValue(lRecord, lv);
res[key] = setValue(leftRecord, lv);
}
});
rkeys.forEach((key) => {
rightKeys.forEach((key) => {
if (hasOwn(res, key))
return;
res[key] = setValue(rRecord, r[key]);
res[key] = setValue(rightRecord, r[key]);
});

@@ -266,5 +264,58 @@ return res;

}
function inBrowser() {
return typeof window !== 'undefined';
// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
function isAbsolute(url) {
// `c:\\` 这种 case 返回 false,在浏览器中使用本地图片,应该用 file 协议
if (!/^[a-zA-Z]:\\/.test(url)) {
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)) {
return true;
}
}
return false;
}
function transformUrl(resolvePath, curPath) {
const baseUrl = new URL(resolvePath, location.href);
const realPath = new URL(curPath, baseUrl.href);
return realPath.href;
}
function findTarget(el, selectors) {
for (const s of selectors) {
const target = el.querySelector(s);
if (target)
return target;
}
return el;
}
function setDocCurrentScript(target, code, define, url, async) {
if (!target)
return noop;
const el = document.createElement('script');
if (async) {
el.setAttribute('async', 'true');
}
if (url) {
el.setAttribute('src', url);
}
else if (code) {
el.textContent = code;
}
const set = (val) => {
try {
if (define) {
Object.defineProperty(target, 'currentScript', {
value: val,
writable: true,
configurable: true,
});
}
else {
target.currentScript = val;
}
}
catch (e) {
}
};
set(el);
return () => set(null);
}

@@ -415,58 +466,137 @@ // copy from https://github.com/getsentry/sentry-javascript/blob/6.4.0/packages/browser/src/tracekit.ts

// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
function isAbsolute(url) {
// `c:\\` 这种 case 返回 false,在浏览器中使用本地图片,应该用 file 协议
if (!/^[a-zA-Z]:\\/.test(url)) {
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)) {
return true;
const xChar = 120; // "x" char
const colonChar = 58; // ":" char
const ns = 'http://www.w3.org/2000/svg';
const xlinkNS = 'http://www.w3.org/1999/xlink'; // xmlns:xlink
const xmlNS = 'http://www.w3.org/XML/1998/namespace'; // xmlns
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element
const SVG_TAGS = 'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +
'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +
'feDistanceLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +
'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +
'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +
'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +
'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
'text,textPath,title,tspan,unknown,use,view';
const isSVG = makeMap(SVG_TAGS.split(','));
function attributesString(attributes) {
if (!attributes || attributes.length === 0)
return '';
return attributes.reduce((total, { key, value }) => {
return total + (value ? `${key}="${value}" ` : key);
}, '');
}
const DOMApis = {
isText(node) {
return node && node.type === 'text';
},
isNode(node) {
return node && node.type === 'element';
},
isCommentNode(node) {
return node && node.type === 'comment';
},
isCssLinkNode(node) {
if (this.isNode(node) && node.tagName === 'link') {
return !!node.attributes.find(({ key, value }) => key === 'rel' && value === 'stylesheet');
}
}
return false;
}
function transformUrl(resolvePath, curPath) {
const baseUrl = new URL(resolvePath, location.href);
const realPath = new URL(curPath, baseUrl.href);
return realPath.href;
}
function findTarget(el, selectors) {
for (const s of selectors) {
const target = el.querySelector(s);
if (target)
return target;
}
return el;
}
function setDocCurrentScript(target, code, define, url, async) {
if (!target)
return noop;
const el = document.createElement('script');
if (async) {
el.setAttribute('async', 'true');
}
if (url) {
el.setAttribute('src', url);
}
else if (code) {
el.textContent = code;
}
const set = (val) => {
try {
if (define) {
Object.defineProperty(target, 'currentScript', {
value: val,
writable: true,
configurable: true,
});
return false;
},
isIconLinkNode(node) {
if (this.isNode(node) && node.tagName === 'link') {
return !!node.attributes.find(({ key, value }) => key === 'rel' && value === 'icon');
}
return false;
},
isPrefetchJsLinkNode(node) {
if (!this.isNode(node) || node.tagName !== 'link')
return false;
let hasRelAttr, hasAsAttr;
for (const { key, value } of node.attributes) {
if (key === 'rel') {
hasRelAttr = true;
if (value !== 'preload' && value !== 'prefetch') {
return false;
}
}
else {
target.currentScript = val;
else if (key === 'as') {
hasAsAttr = true;
if (value !== 'script')
return false;
}
}
catch (e) {
return Boolean(hasRelAttr && hasAsAttr);
},
removeElement(el) {
const parentNode = el && el.parentNode;
if (parentNode) {
parentNode.removeChild(el);
}
};
set(el);
return () => set(null);
}
},
createElement(node) {
const { tagName, attributes } = node;
const el = isSVG(tagName)
? document.createElementNS(ns, tagName)
: document.createElement(tagName);
this.applyAttributes(el, attributes);
return el;
},
createTextNode(node) {
return document.createTextNode(node.content);
},
createStyleNode(content) {
const el = document.createElement('style');
content && (el.textContent = content);
this.applyAttributes(el, [{ key: 'type', value: 'text/css' }]);
return el;
},
createLinkCommentNode(node) {
if (this.isNode(node)) {
const ps = attributesString(node.attributes);
return `<link ${ps.slice(0, -1)}></link>`;
}
else {
node = node ? `src="${node}" ` : '';
return document.createComment(`<link ${node}execute by garfish(dynamic)></link>`);
}
},
createScriptCommentNode(node) {
if (this.isNode(node)) {
const { attributes, children } = node;
const ps = attributesString(attributes);
const code = (children === null || children === void 0 ? void 0 : children[0]) ? children[0].content : '';
return document.createComment(`<script ${ps} execute by garfish>${code}</script>`);
}
else {
const { src, code } = node;
const url = src ? `src="${src}" ` : '';
return document.createComment(`<script ${url}execute by garfish(dynamic)>${code}</script>`);
}
},
applyAttributes(el, attributes) {
if (!attributes || attributes.length === 0)
return;
for (const { key, value } of attributes) {
if (value === null) {
el.setAttribute(key, '');
}
else if (typeof value === 'string') {
if (key.charCodeAt(0) !== xChar) {
el.setAttribute(key, value);
}
else if (key.charCodeAt(3) === colonChar) {
el.setAttributeNS(xmlNS, key, value);
}
else if (key.charCodeAt(5) === colonChar) {
el.setAttributeNS(xlinkNS, key, value);
}
else {
el.setAttribute(key, value);
}
}
}
},
};

@@ -481,3 +611,3 @@ const __GARFISH_FLAG__ = Symbol.for('__GARFISH_FLAG__');

let type = '';
let subtype = '';
let subType = '';
while (idx < input.length && input[idx] !== '/') {

@@ -493,11 +623,11 @@ type += input[idx];

while (idx < input.length && input[idx] !== ';') {
subtype += input[idx];
subType += input[idx];
idx++;
}
subtype = subtype.replace(/[ \t\n\r]+$/, '');
if (subtype.length === 0)
subType = subType.replace(/[ \t\n\r]+$/, '');
if (subType.length === 0)
return null;
return {
type: type.toLocaleLowerCase(),
subtype: subtype.toLocaleLowerCase(),
subtype: subType.toLocaleLowerCase(),
};

@@ -579,2 +709,3 @@ }

exports.DOMApis = DOMApis;
exports.__GARFISH_FLAG__ = __GARFISH_FLAG__;

@@ -606,3 +737,2 @@ exports.assert = assert;

exports.makeMap = makeMap;
exports.mixins = mixins;
exports.nextTick = nextTick;

@@ -609,0 +739,0 @@ exports.noop = noop;

@@ -29,7 +29,6 @@ const objectToString = Object.prototype.toString;

},
// 测试环境允许 delete
configurable: true ,
});
}
// 数组变为对象 `['a'] => { a: true }`
// Array to Object `['a'] => { a: true }`
function makeMap(list) {

@@ -42,2 +41,5 @@ const map = Object.create(null);

}
function inBrowser() {
return typeof window !== 'undefined';
}
const warnPrefix = '[Garfish warning]';

@@ -72,9 +74,2 @@ const processError = (error, fn) => {

}
// 将字符串被设置为对象属性名时,会被尝试改造为常量化版本,避免浏览器重复产生缓存
function internFunc(internalizeString) {
// 暂时不考虑Hash-collision,https://en.wikipedia.org/wiki/Collision_(computer_science)。v8貌似在16383长度时会发生hash-collision,经过测试后发现正常
const temporaryOb = {};
temporaryOb[internalizeString] = true;
return Object.keys(temporaryOb)[0];
}
function validURL(str) {

@@ -89,5 +84,14 @@ const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol

}
// When the string is set as the object property name,
// it will be attempted to be transformed into a constant version to avoid repeated caching by the browser
function internFunc(internalizeString) {
// Don't consider "Hash-collision,https://en.wikipedia.org/wiki/Collision_(computer_science)"
// v8貌似在 16383 长度时会发生 hash-collision,经过测试后发现正常
const temporaryOb = {};
temporaryOb[internalizeString] = true;
return Object.keys(temporaryOb)[0];
}
function evalWithEnv(code, params) {
const keys = Object.keys(params);
// 不可使用随机值,否则无法作为常量字符串复用
// No random value can be used, otherwise it cannot be reused as a constant string
const randomValKey = '__garfish__exec_temporary__';

@@ -140,7 +144,2 @@ const vales = keys.map((k) => `window.${randomValKey}.${k}`);

}
function mixins(...list) {
return function (target) {
Object.assign(target.prototype, ...list);
};
}
// 有些测试 jest.mock 不好测,可用这个工具方法

@@ -171,27 +170,26 @@ function callTestCallback(obj, ...args) {

}
// 深度合并两个对象,能处理循环引用,后面的覆盖前面的,可选数组去重
// Deeply merge two objects, can handle circular references, the latter overwrite the previous
function deepMerge(o, n, dp) {
const lRecord = new WeakMap();
const rRecord = new WeakMap();
const vRecord = new WeakMap();
const leftRecord = new WeakMap();
const rightRecord = new WeakMap();
const valueRecord = new WeakMap();
const isArray = Array.isArray;
const isAllRefs = (a, b) => {
// 判断 merge 左右两边,不需要用到 vRecord
if (lRecord.has(a) || rRecord.has(a)) {
return lRecord.has(b) || rRecord.has(b);
if (leftRecord.has(a) || rightRecord.has(a)) {
return leftRecord.has(b) || rightRecord.has(b);
}
};
const clone = (v) => {
// 深拷贝
// Deep clone
if (isPrimitive(v) || typeof v === 'function') {
return v;
}
else if (vRecord.has(v)) {
return vRecord.get(v);
else if (valueRecord.has(v)) {
return valueRecord.get(v);
}
else if (lRecord.has(v)) {
return lRecord.get(v);
else if (leftRecord.has(v)) {
return leftRecord.get(v);
}
else if (rRecord.has(v)) {
return rRecord.get(v);
else if (rightRecord.has(v)) {
return rightRecord.get(v);
}

@@ -201,15 +199,15 @@ else if (isArray(v)) {

v = unique(v);
const res = [];
vRecord.set(v, res);
const arr = [];
valueRecord.set(v, arr);
for (let i = 0, len = v.length; i < len; i++) {
res[i] = clone(v[i]);
arr[i] = clone(v[i]);
}
return res;
return arr;
}
else if (typeof v === 'object') {
const res = {};
vRecord.set(v, res);
const obj = {};
valueRecord.set(v, obj);
const keys = Reflect.ownKeys(v);
keys.forEach((key) => (res[key] = clone(v[key])));
return res;
keys.forEach((key) => (obj[key] = clone(v[key])));
return obj;
}

@@ -231,7 +229,7 @@ };

const res = {};
const lkeys = Reflect.ownKeys(l);
const rkeys = Reflect.ownKeys(r);
lRecord.set(l, res);
rRecord.set(r, res);
lkeys.forEach((key) => {
const leftKeys = Reflect.ownKeys(l);
const rightKeys = Reflect.ownKeys(r);
leftRecord.set(l, res);
rightRecord.set(r, res);
leftKeys.forEach((key) => {
const lv = l[key];

@@ -246,17 +244,17 @@ const rv = r[key];

res[key] = isAllRefs(lv, rv)
? lRecord.get(lv) // 左边右边同一个值,取哪个都行
? leftRecord.get(lv) // The same value on the left and right, whichever is OK
: mergeObject(lv, rv);
}
else {
res[key] = setValue(rRecord, rv);
res[key] = setValue(rightRecord, rv);
}
}
else {
res[key] = setValue(lRecord, lv);
res[key] = setValue(leftRecord, lv);
}
});
rkeys.forEach((key) => {
rightKeys.forEach((key) => {
if (hasOwn(res, key))
return;
res[key] = setValue(rRecord, r[key]);
res[key] = setValue(rightRecord, r[key]);
});

@@ -267,5 +265,61 @@ return res;

}
function inBrowser() {
return typeof window !== 'undefined';
// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
function isAbsolute(url) {
// `c:\\` 这种 case 返回 false,在浏览器中使用本地图片,应该用 file 协议
if (!/^[a-zA-Z]:\\/.test(url)) {
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)) {
return true;
}
}
return false;
}
function transformUrl(resolvePath, curPath) {
const baseUrl = new URL(resolvePath, location.href);
const realPath = new URL(curPath, baseUrl.href);
return realPath.href;
}
function findTarget(el, selectors) {
for (const s of selectors) {
const target = el.querySelector(s);
if (target)
return target;
}
return el;
}
function setDocCurrentScript(target, code, define, url, async) {
if (!target)
return noop;
const el = document.createElement('script');
if (async) {
el.setAttribute('async', 'true');
}
if (url) {
el.setAttribute('src', url);
}
else if (code) {
el.textContent = code;
}
const set = (val) => {
try {
if (define) {
Object.defineProperty(target, 'currentScript', {
value: val,
writable: true,
configurable: true,
});
}
else {
target.currentScript = val;
}
}
catch (e) {
{
warn(e);
}
}
};
set(el);
return () => set(null);
}

@@ -416,61 +470,137 @@ // copy from https://github.com/getsentry/sentry-javascript/blob/6.4.0/packages/browser/src/tracekit.ts

// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
function isAbsolute(url) {
// `c:\\` 这种 case 返回 false,在浏览器中使用本地图片,应该用 file 协议
if (!/^[a-zA-Z]:\\/.test(url)) {
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)) {
return true;
const xChar = 120; // "x" char
const colonChar = 58; // ":" char
const ns = 'http://www.w3.org/2000/svg';
const xlinkNS = 'http://www.w3.org/1999/xlink'; // xmlns:xlink
const xmlNS = 'http://www.w3.org/XML/1998/namespace'; // xmlns
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element
const SVG_TAGS = 'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +
'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +
'feDistanceLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +
'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +
'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +
'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +
'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
'text,textPath,title,tspan,unknown,use,view';
const isSVG = makeMap(SVG_TAGS.split(','));
function attributesString(attributes) {
if (!attributes || attributes.length === 0)
return '';
return attributes.reduce((total, { key, value }) => {
return total + (value ? `${key}="${value}" ` : key);
}, '');
}
const DOMApis = {
isText(node) {
return node && node.type === 'text';
},
isNode(node) {
return node && node.type === 'element';
},
isCommentNode(node) {
return node && node.type === 'comment';
},
isCssLinkNode(node) {
if (this.isNode(node) && node.tagName === 'link') {
return !!node.attributes.find(({ key, value }) => key === 'rel' && value === 'stylesheet');
}
}
return false;
}
function transformUrl(resolvePath, curPath) {
const baseUrl = new URL(resolvePath, location.href);
const realPath = new URL(curPath, baseUrl.href);
return realPath.href;
}
function findTarget(el, selectors) {
for (const s of selectors) {
const target = el.querySelector(s);
if (target)
return target;
}
return el;
}
function setDocCurrentScript(target, code, define, url, async) {
if (!target)
return noop;
const el = document.createElement('script');
if (async) {
el.setAttribute('async', 'true');
}
if (url) {
el.setAttribute('src', url);
}
else if (code) {
el.textContent = code;
}
const set = (val) => {
try {
if (define) {
Object.defineProperty(target, 'currentScript', {
value: val,
writable: true,
configurable: true,
});
return false;
},
isIconLinkNode(node) {
if (this.isNode(node) && node.tagName === 'link') {
return !!node.attributes.find(({ key, value }) => key === 'rel' && value === 'icon');
}
return false;
},
isPrefetchJsLinkNode(node) {
if (!this.isNode(node) || node.tagName !== 'link')
return false;
let hasRelAttr, hasAsAttr;
for (const { key, value } of node.attributes) {
if (key === 'rel') {
hasRelAttr = true;
if (value !== 'preload' && value !== 'prefetch') {
return false;
}
}
else {
target.currentScript = val;
else if (key === 'as') {
hasAsAttr = true;
if (value !== 'script')
return false;
}
}
catch (e) {
{
warn(e);
return Boolean(hasRelAttr && hasAsAttr);
},
removeElement(el) {
const parentNode = el && el.parentNode;
if (parentNode) {
parentNode.removeChild(el);
}
},
createElement(node) {
const { tagName, attributes } = node;
const el = isSVG(tagName)
? document.createElementNS(ns, tagName)
: document.createElement(tagName);
this.applyAttributes(el, attributes);
return el;
},
createTextNode(node) {
return document.createTextNode(node.content);
},
createStyleNode(content) {
const el = document.createElement('style');
content && (el.textContent = content);
this.applyAttributes(el, [{ key: 'type', value: 'text/css' }]);
return el;
},
createLinkCommentNode(node) {
if (this.isNode(node)) {
const ps = attributesString(node.attributes);
return `<link ${ps.slice(0, -1)}></link>`;
}
else {
node = node ? `src="${node}" ` : '';
return document.createComment(`<link ${node}execute by garfish(dynamic)></link>`);
}
},
createScriptCommentNode(node) {
if (this.isNode(node)) {
const { attributes, children } = node;
const ps = attributesString(attributes);
const code = (children === null || children === void 0 ? void 0 : children[0]) ? children[0].content : '';
return document.createComment(`<script ${ps} execute by garfish>${code}</script>`);
}
else {
const { src, code } = node;
const url = src ? `src="${src}" ` : '';
return document.createComment(`<script ${url}execute by garfish(dynamic)>${code}</script>`);
}
},
applyAttributes(el, attributes) {
if (!attributes || attributes.length === 0)
return;
for (const { key, value } of attributes) {
if (value === null) {
el.setAttribute(key, '');
}
else if (typeof value === 'string') {
if (key.charCodeAt(0) !== xChar) {
el.setAttribute(key, value);
}
else if (key.charCodeAt(3) === colonChar) {
el.setAttributeNS(xmlNS, key, value);
}
else if (key.charCodeAt(5) === colonChar) {
el.setAttributeNS(xlinkNS, key, value);
}
else {
el.setAttribute(key, value);
}
}
}
};
set(el);
return () => set(null);
}
},
};

@@ -485,3 +615,3 @@ const __GARFISH_FLAG__ = Symbol.for('__GARFISH_FLAG__');

let type = '';
let subtype = '';
let subType = '';
while (idx < input.length && input[idx] !== '/') {

@@ -497,11 +627,11 @@ type += input[idx];

while (idx < input.length && input[idx] !== ';') {
subtype += input[idx];
subType += input[idx];
idx++;
}
subtype = subtype.replace(/[ \t\n\r]+$/, '');
if (subtype.length === 0)
subType = subType.replace(/[ \t\n\r]+$/, '');
if (subType.length === 0)
return null;
return {
type: type.toLocaleLowerCase(),
subtype: subtype.toLocaleLowerCase(),
subtype: subType.toLocaleLowerCase(),
};

@@ -583,2 +713,2 @@ }

export { __GARFISH_FLAG__, assert, callTestCallback, computeErrorUrl, computeStackTraceFromStackProp, createAppContainer, createKey, deepMerge, def, error, evalWithEnv, filterAndWrapEventListener, findTarget, getRenderNode, hasOwn, inBrowser, internFunc, isAbsolute, isCss, isHtml, isJs, isObject, isPlainObject, isPrimitive, isPromise, makeMap, mixins, nextTick, noop, objectToString, parseContentType, remove, setDocCurrentScript, sourceListTags, sourceNode, toBoolean, transformUrl, unique, validURL, warn };
export { DOMApis, __GARFISH_FLAG__, assert, callTestCallback, computeErrorUrl, computeStackTraceFromStackProp, createAppContainer, createKey, deepMerge, def, error, evalWithEnv, filterAndWrapEventListener, findTarget, getRenderNode, hasOwn, inBrowser, internFunc, isAbsolute, isCss, isHtml, isJs, isObject, isPlainObject, isPrimitive, isPromise, makeMap, nextTick, noop, objectToString, parseContentType, remove, setDocCurrentScript, sourceListTags, sourceNode, toBoolean, transformUrl, unique, validURL, warn };

@@ -35,7 +35,6 @@ (function (global, factory) {

},
// 测试环境允许 delete
configurable: true ,
});
}
// 数组变为对象 `['a'] => { a: true }`
// Array to Object `['a'] => { a: true }`
function makeMap(list) {

@@ -48,2 +47,5 @@ const map = Object.create(null);

}
function inBrowser() {
return typeof window !== 'undefined';
}
const warnPrefix = '[Garfish warning]';

@@ -78,9 +80,2 @@ const processError = (error, fn) => {

}
// 将字符串被设置为对象属性名时,会被尝试改造为常量化版本,避免浏览器重复产生缓存
function internFunc(internalizeString) {
// 暂时不考虑Hash-collision,https://en.wikipedia.org/wiki/Collision_(computer_science)。v8貌似在16383长度时会发生hash-collision,经过测试后发现正常
const temporaryOb = {};
temporaryOb[internalizeString] = true;
return Object.keys(temporaryOb)[0];
}
function validURL(str) {

@@ -95,5 +90,14 @@ const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol

}
// When the string is set as the object property name,
// it will be attempted to be transformed into a constant version to avoid repeated caching by the browser
function internFunc(internalizeString) {
// Don't consider "Hash-collision,https://en.wikipedia.org/wiki/Collision_(computer_science)"
// v8貌似在 16383 长度时会发生 hash-collision,经过测试后发现正常
const temporaryOb = {};
temporaryOb[internalizeString] = true;
return Object.keys(temporaryOb)[0];
}
function evalWithEnv(code, params) {
const keys = Object.keys(params);
// 不可使用随机值,否则无法作为常量字符串复用
// No random value can be used, otherwise it cannot be reused as a constant string
const randomValKey = '__garfish__exec_temporary__';

@@ -146,7 +150,2 @@ const vales = keys.map((k) => `window.${randomValKey}.${k}`);

}
function mixins(...list) {
return function (target) {
Object.assign(target.prototype, ...list);
};
}
// 有些测试 jest.mock 不好测,可用这个工具方法

@@ -177,27 +176,26 @@ function callTestCallback(obj, ...args) {

}
// 深度合并两个对象,能处理循环引用,后面的覆盖前面的,可选数组去重
// Deeply merge two objects, can handle circular references, the latter overwrite the previous
function deepMerge(o, n, dp) {
const lRecord = new WeakMap();
const rRecord = new WeakMap();
const vRecord = new WeakMap();
const leftRecord = new WeakMap();
const rightRecord = new WeakMap();
const valueRecord = new WeakMap();
const isArray = Array.isArray;
const isAllRefs = (a, b) => {
// 判断 merge 左右两边,不需要用到 vRecord
if (lRecord.has(a) || rRecord.has(a)) {
return lRecord.has(b) || rRecord.has(b);
if (leftRecord.has(a) || rightRecord.has(a)) {
return leftRecord.has(b) || rightRecord.has(b);
}
};
const clone = (v) => {
// 深拷贝
// Deep clone
if (isPrimitive(v) || typeof v === 'function') {
return v;
}
else if (vRecord.has(v)) {
return vRecord.get(v);
else if (valueRecord.has(v)) {
return valueRecord.get(v);
}
else if (lRecord.has(v)) {
return lRecord.get(v);
else if (leftRecord.has(v)) {
return leftRecord.get(v);
}
else if (rRecord.has(v)) {
return rRecord.get(v);
else if (rightRecord.has(v)) {
return rightRecord.get(v);
}

@@ -207,15 +205,15 @@ else if (isArray(v)) {

v = unique(v);
const res = [];
vRecord.set(v, res);
const arr = [];
valueRecord.set(v, arr);
for (let i = 0, len = v.length; i < len; i++) {
res[i] = clone(v[i]);
arr[i] = clone(v[i]);
}
return res;
return arr;
}
else if (typeof v === 'object') {
const res = {};
vRecord.set(v, res);
const obj = {};
valueRecord.set(v, obj);
const keys = Reflect.ownKeys(v);
keys.forEach((key) => (res[key] = clone(v[key])));
return res;
keys.forEach((key) => (obj[key] = clone(v[key])));
return obj;
}

@@ -237,7 +235,7 @@ };

const res = {};
const lkeys = Reflect.ownKeys(l);
const rkeys = Reflect.ownKeys(r);
lRecord.set(l, res);
rRecord.set(r, res);
lkeys.forEach((key) => {
const leftKeys = Reflect.ownKeys(l);
const rightKeys = Reflect.ownKeys(r);
leftRecord.set(l, res);
rightRecord.set(r, res);
leftKeys.forEach((key) => {
const lv = l[key];

@@ -252,17 +250,17 @@ const rv = r[key];

res[key] = isAllRefs(lv, rv)
? lRecord.get(lv) // 左边右边同一个值,取哪个都行
? leftRecord.get(lv) // The same value on the left and right, whichever is OK
: mergeObject(lv, rv);
}
else {
res[key] = setValue(rRecord, rv);
res[key] = setValue(rightRecord, rv);
}
}
else {
res[key] = setValue(lRecord, lv);
res[key] = setValue(leftRecord, lv);
}
});
rkeys.forEach((key) => {
rightKeys.forEach((key) => {
if (hasOwn(res, key))
return;
res[key] = setValue(rRecord, r[key]);
res[key] = setValue(rightRecord, r[key]);
});

@@ -273,5 +271,61 @@ return res;

}
function inBrowser() {
return typeof window !== 'undefined';
// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
function isAbsolute(url) {
// `c:\\` 这种 case 返回 false,在浏览器中使用本地图片,应该用 file 协议
if (!/^[a-zA-Z]:\\/.test(url)) {
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)) {
return true;
}
}
return false;
}
function transformUrl(resolvePath, curPath) {
const baseUrl = new URL(resolvePath, location.href);
const realPath = new URL(curPath, baseUrl.href);
return realPath.href;
}
function findTarget(el, selectors) {
for (const s of selectors) {
const target = el.querySelector(s);
if (target)
return target;
}
return el;
}
function setDocCurrentScript(target, code, define, url, async) {
if (!target)
return noop;
const el = document.createElement('script');
if (async) {
el.setAttribute('async', 'true');
}
if (url) {
el.setAttribute('src', url);
}
else if (code) {
el.textContent = code;
}
const set = (val) => {
try {
if (define) {
Object.defineProperty(target, 'currentScript', {
value: val,
writable: true,
configurable: true,
});
}
else {
target.currentScript = val;
}
}
catch (e) {
{
warn(e);
}
}
};
set(el);
return () => set(null);
}

@@ -422,61 +476,137 @@ // copy from https://github.com/getsentry/sentry-javascript/blob/6.4.0/packages/browser/src/tracekit.ts

// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
function isAbsolute(url) {
// `c:\\` 这种 case 返回 false,在浏览器中使用本地图片,应该用 file 协议
if (!/^[a-zA-Z]:\\/.test(url)) {
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)) {
return true;
const xChar = 120; // "x" char
const colonChar = 58; // ":" char
const ns = 'http://www.w3.org/2000/svg';
const xlinkNS = 'http://www.w3.org/1999/xlink'; // xmlns:xlink
const xmlNS = 'http://www.w3.org/XML/1998/namespace'; // xmlns
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element
const SVG_TAGS = 'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +
'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +
'feDistanceLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +
'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +
'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +
'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +
'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
'text,textPath,title,tspan,unknown,use,view';
const isSVG = makeMap(SVG_TAGS.split(','));
function attributesString(attributes) {
if (!attributes || attributes.length === 0)
return '';
return attributes.reduce((total, { key, value }) => {
return total + (value ? `${key}="${value}" ` : key);
}, '');
}
const DOMApis = {
isText(node) {
return node && node.type === 'text';
},
isNode(node) {
return node && node.type === 'element';
},
isCommentNode(node) {
return node && node.type === 'comment';
},
isCssLinkNode(node) {
if (this.isNode(node) && node.tagName === 'link') {
return !!node.attributes.find(({ key, value }) => key === 'rel' && value === 'stylesheet');
}
}
return false;
}
function transformUrl(resolvePath, curPath) {
const baseUrl = new URL(resolvePath, location.href);
const realPath = new URL(curPath, baseUrl.href);
return realPath.href;
}
function findTarget(el, selectors) {
for (const s of selectors) {
const target = el.querySelector(s);
if (target)
return target;
}
return el;
}
function setDocCurrentScript(target, code, define, url, async) {
if (!target)
return noop;
const el = document.createElement('script');
if (async) {
el.setAttribute('async', 'true');
}
if (url) {
el.setAttribute('src', url);
}
else if (code) {
el.textContent = code;
}
const set = (val) => {
try {
if (define) {
Object.defineProperty(target, 'currentScript', {
value: val,
writable: true,
configurable: true,
});
return false;
},
isIconLinkNode(node) {
if (this.isNode(node) && node.tagName === 'link') {
return !!node.attributes.find(({ key, value }) => key === 'rel' && value === 'icon');
}
return false;
},
isPrefetchJsLinkNode(node) {
if (!this.isNode(node) || node.tagName !== 'link')
return false;
let hasRelAttr, hasAsAttr;
for (const { key, value } of node.attributes) {
if (key === 'rel') {
hasRelAttr = true;
if (value !== 'preload' && value !== 'prefetch') {
return false;
}
}
else {
target.currentScript = val;
else if (key === 'as') {
hasAsAttr = true;
if (value !== 'script')
return false;
}
}
catch (e) {
{
warn(e);
return Boolean(hasRelAttr && hasAsAttr);
},
removeElement(el) {
const parentNode = el && el.parentNode;
if (parentNode) {
parentNode.removeChild(el);
}
},
createElement(node) {
const { tagName, attributes } = node;
const el = isSVG(tagName)
? document.createElementNS(ns, tagName)
: document.createElement(tagName);
this.applyAttributes(el, attributes);
return el;
},
createTextNode(node) {
return document.createTextNode(node.content);
},
createStyleNode(content) {
const el = document.createElement('style');
content && (el.textContent = content);
this.applyAttributes(el, [{ key: 'type', value: 'text/css' }]);
return el;
},
createLinkCommentNode(node) {
if (this.isNode(node)) {
const ps = attributesString(node.attributes);
return `<link ${ps.slice(0, -1)}></link>`;
}
else {
node = node ? `src="${node}" ` : '';
return document.createComment(`<link ${node}execute by garfish(dynamic)></link>`);
}
},
createScriptCommentNode(node) {
if (this.isNode(node)) {
const { attributes, children } = node;
const ps = attributesString(attributes);
const code = (children === null || children === void 0 ? void 0 : children[0]) ? children[0].content : '';
return document.createComment(`<script ${ps} execute by garfish>${code}</script>`);
}
else {
const { src, code } = node;
const url = src ? `src="${src}" ` : '';
return document.createComment(`<script ${url}execute by garfish(dynamic)>${code}</script>`);
}
},
applyAttributes(el, attributes) {
if (!attributes || attributes.length === 0)
return;
for (const { key, value } of attributes) {
if (value === null) {
el.setAttribute(key, '');
}
else if (typeof value === 'string') {
if (key.charCodeAt(0) !== xChar) {
el.setAttribute(key, value);
}
else if (key.charCodeAt(3) === colonChar) {
el.setAttributeNS(xmlNS, key, value);
}
else if (key.charCodeAt(5) === colonChar) {
el.setAttributeNS(xlinkNS, key, value);
}
else {
el.setAttribute(key, value);
}
}
}
};
set(el);
return () => set(null);
}
},
};

@@ -491,3 +621,3 @@ const __GARFISH_FLAG__ = Symbol.for('__GARFISH_FLAG__');

let type = '';
let subtype = '';
let subType = '';
while (idx < input.length && input[idx] !== '/') {

@@ -503,11 +633,11 @@ type += input[idx];

while (idx < input.length && input[idx] !== ';') {
subtype += input[idx];
subType += input[idx];
idx++;
}
subtype = subtype.replace(/[ \t\n\r]+$/, '');
if (subtype.length === 0)
subType = subType.replace(/[ \t\n\r]+$/, '');
if (subType.length === 0)
return null;
return {
type: type.toLocaleLowerCase(),
subtype: subtype.toLocaleLowerCase(),
subtype: subType.toLocaleLowerCase(),
};

@@ -589,2 +719,3 @@ }

exports.DOMApis = DOMApis;
exports.__GARFISH_FLAG__ = __GARFISH_FLAG__;

@@ -616,3 +747,2 @@ exports.assert = assert;

exports.makeMap = makeMap;
exports.mixins = mixins;
exports.nextTick = nextTick;

@@ -619,0 +749,0 @@ exports.noop = noop;

{
"name": "@garfish/utils",
"version": "0.0.9",
"version": "0.0.12",
"description": "utils module.",

@@ -40,3 +40,3 @@ "keywords": [

},
"gitHead": "e54d52d3757bb6d2fa95eb9d688e737b4e9fb25f"
"gitHead": "306ff92ee38c5ca5b01c60b91453619f885620fe"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc