als-require
Advanced tools
Comparing version 1.6.0 to 1.7.0
@@ -12,2 +12,3 @@ const UglifyJS = require("uglify-js"); | ||
const getKeys = require('../lib/get-keys') | ||
const standartNodeModules = require('../lib/node-modules') | ||
@@ -17,3 +18,6 @@ const contents = [getFullPath, getNodeModules, getContents, getKeys, getFns, parseError, Require]; | ||
const packageJsonCache = {}; | ||
const standartNodeModules = ${JSON.stringify(standartNodeModules)} | ||
${contents.map(fn => fn.toString()).join('\n')} | ||
${contents.map(fn => `Require.${fn.name} = ${fn.name};`).join('')} | ||
Require.standartNodeModules = standartNodeModules; | ||
return Require; | ||
@@ -20,0 +24,0 @@ })() |
const packageJsonCache = {} | ||
async function getNodeModules(nodeModules, children, content,Require) { | ||
async function getNodeModules(nodeModules, children, content, Require) { | ||
const { logger = console } = Require | ||
if (nodeModules.length === 0) return content | ||
for (let { match, modulePath } of nodeModules) { | ||
let fullPath,relativePath,filename,moduleDir = modulePath | ||
const r = new RegExp(`require\\((["'\`])${modulePath}["'\`]\\)`) | ||
const replaceAndWarn = () => { | ||
content = content.replace(r, '{}') | ||
logger.warn(`The module "${modulePath}" can't be imported and will be replaced with {}`) | ||
} | ||
if (standartNodeModules.includes(modulePath)) { replaceAndWarn(); continue; } | ||
if(modulePath.includes('/')) { | ||
let fullPath, relativePath, filename, moduleDir = modulePath | ||
if (modulePath.includes('/')) { | ||
const arr = modulePath.split('/') | ||
@@ -14,11 +22,6 @@ moduleDir = arr.shift() | ||
let pkgJsonPath = `/node_modules/${moduleDir}/package.json` | ||
const exists = await fetch(pkgJsonPath, { method: 'HEAD' }) | ||
const r = new RegExp(`require\\((["'\`])${modulePath}["'\`]\\)`) | ||
if (exists.ok === false) { | ||
content = content.replace(r, '{}') | ||
console.warn(`The module "${modulePath}" can't be imported and will be replaced with {}`) | ||
continue | ||
} | ||
if(packageJsonCache[pkgJsonPath]) filename = packageJsonCache[pkgJsonPath] | ||
if (exists.ok === false) { replaceAndWarn(); continue; } | ||
if (packageJsonCache[pkgJsonPath]) filename = packageJsonCache[pkgJsonPath] | ||
else { | ||
@@ -30,14 +33,9 @@ const { main = 'index.js' } = await Require.fetch(pkgJsonPath, 'json') | ||
if(relativePath) { | ||
const relativeDir = filename.split('/') | ||
relativeDir.pop() | ||
fullPath = `/node_modules/${moduleDir}/${relativeDir.join('/')}/${relativePath}` | ||
} else { | ||
fullPath = `/node_modules/${moduleDir}/${filename}` | ||
} | ||
fullPath = fullPath.replace(/\/\.?\//g,'/') | ||
if(!fullPath.endsWith('.js')) fullPath += '.js' | ||
if (relativePath) fullPath = `/node_modules/${moduleDir}/${relativePath}` | ||
else fullPath = `/node_modules/${moduleDir}/${filename}` | ||
fullPath = fullPath.replace(/\/\.?\//g, '/') | ||
if (!fullPath.endsWith('.js')) fullPath += '.js' | ||
Require.isCyclyc(fullPath, modulePath) | ||
children.push(fullPath); | ||
content = content.replace(match, match.replace(r, (m,quoute) => { | ||
content = content.replace(match, match.replace(r, (m, quoute) => { | ||
return `require(${quoute}${fullPath}${quoute})` | ||
@@ -44,0 +42,0 @@ })) |
class Require { | ||
static contents = {} | ||
static cyclicDependencies = false | ||
static logger = console | ||
static version | ||
@@ -4,0 +6,0 @@ |
@@ -7,3 +7,4 @@ const rootPath = process.cwd() | ||
function getContents({contents,fullPath},Require) { | ||
function getContents({ contents, fullPath }, Require) { | ||
const { cyclicDependencies, logger } = Require | ||
const getContent = (path) => { | ||
@@ -19,10 +20,10 @@ if (contents[path] !== undefined) return // allready fetched | ||
else { | ||
fullPath = getNodeModules(modulePath,rootPath) | ||
if(fullPath === false) return match.replace(r, '{}') | ||
fullPath = getNodeModules(modulePath, rootPath,logger) | ||
if (fullPath === false) return match.replace(r, '{}') | ||
} | ||
if (Require.contents[fullPath] && Require.contents[fullPath].children.includes(path)) { | ||
throw `cyclic dependency between ${path} and ${fullPath}` | ||
if (!cyclicDependencies && Require.contents[fullPath] && Require.contents[fullPath].children.includes(path)) { | ||
throw `Cyclic dependency between ${path} and ${fullPath}` | ||
} | ||
children.push(fullPath); | ||
return match.replace(r, (m,quoute) => `require(${quoute}${fullPath}${quoute})`) | ||
return match.replace(r, (m, quoute) => `require(${quoute}${fullPath}${quoute})`) | ||
}); | ||
@@ -29,0 +30,0 @@ Require.contents[path] = { content, children } |
@@ -0,12 +1,15 @@ | ||
function getFns(contextName='context',obj) { | ||
function buildFn(fnBody,path) { | ||
return /*js*/`modules['${path}'] = (function (){ | ||
const module = { exports: {} } | ||
const exports = module.exports | ||
${fnBody} | ||
return module.exports; | ||
})();` | ||
} | ||
const modulesLines = {} | ||
let curLastLine = 3 | ||
const fns = obj.keys.map((path, i) => { | ||
const fnBody = obj.contents[path]; | ||
let code = `modules['${path}'] = (function (){ | ||
const module = { exports: {} } | ||
const exports = module.exports | ||
${fnBody} | ||
return module.exports; | ||
})();` | ||
let code = buildFn(obj.contents[path],path) | ||
if (i === obj.keys.length - 1) code += `\nreturn modules['${path}']` | ||
@@ -18,3 +21,3 @@ modulesLines[path] = { from: curLastLine + 1 } | ||
}).join('\n') | ||
const fn = new Function('modules', contextName, `function require(path) { return modules[path] || null }; | ||
const fn = new Function('modules', contextName, /*js*/`function require(path) { return modules[path] || null }; | ||
${fns}`) | ||
@@ -21,0 +24,0 @@ return { fn, modulesLines, curLastLine } |
function getKeys(contents, Require) { | ||
const newKeys = new Set() | ||
const addKeys = (keys) => { | ||
const { cyclicDependencies } = Require | ||
const newKeys = [], cyclic = [] | ||
const addKeys = (keys, ...ancestors) => { | ||
keys.forEach(key => { | ||
if (!contents[key]) return | ||
addKeys(Require.contents[key].children) | ||
newKeys.add(key) | ||
const { children } = Require.contents[key] | ||
if (ancestors.includes(key)) { | ||
cyclic.unshift([key,ancestors]) | ||
return newKeys.push(key) | ||
} | ||
if (!newKeys.includes(key)) { | ||
addKeys(children, ...ancestors, key) | ||
newKeys.push(key) | ||
} | ||
}) | ||
} | ||
addKeys(Object.keys(contents).reverse()) | ||
return Array.from(newKeys) | ||
if(cyclicDependencies === true) { | ||
cyclic.forEach(([cyclicKey,ancestors]) => { | ||
ancestors.reverse() | ||
for (const ancestor of ancestors) { | ||
if (ancestor === cyclicKey) break | ||
for (let i = newKeys.length-1; i >= 0; i--) { | ||
const newKey = newKeys[i] | ||
if (newKey === ancestor) break | ||
if (newKey === cyclicKey) newKeys.splice(i, 1) | ||
} | ||
} | ||
}); | ||
} else if(cyclic.length) throw new Error('Cyclic dependencied: '+ JSON.stringify(cyclic,null,3)) | ||
return newKeys | ||
} | ||
module.exports = getKeys |
@@ -1,8 +0,12 @@ | ||
const fs = require('fs') | ||
const { join } = require('path') | ||
const fs = require('fs'); | ||
const { join } = require('path'); | ||
const standartNodeModules = require('./node-modules'); | ||
const packageJsonCache = {} | ||
function getNodeModules(modulePath,rootPath) { | ||
function getNodeModules(modulePath, rootPath, logger = console) { | ||
const warn = () => { | ||
logger.warn(`The module "${modulePath}" can't be imported and will be replaced with {}`) | ||
return false | ||
} | ||
if (standartNodeModules.includes(modulePath)) return warn() | ||
let fullPath, relativePath, filename, moduleDir = modulePath | ||
if (modulePath.includes('/')) { | ||
@@ -14,6 +18,3 @@ const arr = modulePath.split('/') | ||
let pckgJsonPath = join(rootPath, 'node_modules', moduleDir, 'package.json') | ||
if (!fs.existsSync(pckgJsonPath)) { | ||
console.warn(`The module "${modulePath}" can't be imported and will be replaced with {}`) | ||
return false | ||
} | ||
if (!fs.existsSync(pckgJsonPath)) return warn() | ||
@@ -26,9 +27,4 @@ if (packageJsonCache[pckgJsonPath]) filename = packageJsonCache[pckgJsonPath] | ||
} | ||
if (relativePath) { | ||
const relativeDir = filename.split('/') | ||
relativeDir.pop() | ||
fullPath = `/node_modules/${moduleDir}/${relativeDir.join('/')}/${relativePath}` | ||
} else { | ||
fullPath = `/node_modules/${moduleDir}/${filename}` | ||
} | ||
if (relativePath) fullPath = `/node_modules/${moduleDir}/${relativePath}` | ||
else fullPath = `/node_modules/${moduleDir}/${filename}` | ||
fullPath = fullPath.replace(/\/\.?\//g, '/') | ||
@@ -35,0 +31,0 @@ if (!fullPath.endsWith('.js')) fullPath += '.js' |
@@ -1,10 +0,13 @@ | ||
const getFullPath = require('./get-full-path') | ||
const bundle = require('./bundle') | ||
const calledFrom = require('als-called-from') | ||
const getFullPath = require('./get-full-path'); | ||
const calledFrom = require('als-called-from'); | ||
const getContents = require('./get-contents'); | ||
const getKeys = require('./get-keys') | ||
const getFns = require('./get-fns') | ||
const parseError = require('./parse-error') | ||
const getContents = require('./get-contents') | ||
const getKeys = require('./get-keys') | ||
const bundle = require('./bundle') | ||
class Require { | ||
static contents = {} | ||
static cyclicDependencies = false | ||
static logger = console | ||
static getModule(path, context, contextName, modules) { | ||
@@ -11,0 +14,0 @@ return new Require(path).getContent().build(modules, context, contextName) |
{ | ||
"name": "als-require", | ||
"version": "1.6.0", | ||
"version": "1.7.0", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "node --experimental-test-coverage ./tests/index.test.js", | ||
"test": "node --test --experimental-test-coverage", | ||
"report": "node --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info ./tests/index.test.js", | ||
@@ -27,4 +27,5 @@ "build-browser": "node ./browser/build.js" | ||
"devDependencies": { | ||
"als-browser-test": "^1.1.0" | ||
"als-browser-test": "^1.1.0", | ||
"mock-fs": "^5.4.1" | ||
} | ||
} |
@@ -12,8 +12,3 @@ # als-require | ||
**Where it can be particularly useful:** | ||
* Enables the use of the same codebase on both server and browser. | ||
* Allows for on-the-fly code rendering without the need for building a separate bundle. | ||
## Installation | ||
@@ -45,2 +40,4 @@ | ||
Require.version = '1.0'; // optional - adding version when fetching files | ||
Require.cyclicDependencies = true // false by default | ||
Require.logger = console // console by default | ||
Require.getModule('./some/path') | ||
@@ -65,2 +62,5 @@ .then(module => {/* code */}) | ||
static _requireClass = null | ||
static cyclicDependencies = false // allow cyclic dependencies | ||
static logger = console // logger for logger.warn | ||
static contents = {} | ||
@@ -250,6 +250,1 @@ | ||
## Error Handling | ||
`als-require` throwing errors in case of cyclic dependencies and if some module throwing error. | ||
For the case of module's error, `Require` adds to stack modules paths which has called. |
const Require = (function(){ | ||
const packageJsonCache = {}; | ||
const standartNodeModules = ["assert","async_hooks","buffer","child_process","cluster","console","constants","crypto","dgram","diagnostics_channel","dns","domain","events","fs","http","http2","https","inspector","module","net","os","path","perf_hooks","process","punycode","querystring","readline","repl","stream","string_decoder","sys","timers","timers/promises","tls","trace_events","tty","url","util","v8","vm","wasi","worker_threads","zlib","node:test","abort_controller"] | ||
function getFullPath(path, relative) { | ||
@@ -17,8 +18,16 @@ const pathParts = path.split('/'); | ||
} | ||
async function getNodeModules(nodeModules, children, content,Require) { | ||
async function getNodeModules(nodeModules, children, content, Require) { | ||
const { logger = console } = Require | ||
if (nodeModules.length === 0) return content | ||
for (let { match, modulePath } of nodeModules) { | ||
let fullPath,relativePath,filename,moduleDir = modulePath | ||
const r = new RegExp(`require\\((["'\`])${modulePath}["'\`]\\)`) | ||
const replaceAndWarn = () => { | ||
content = content.replace(r, '{}') | ||
logger.warn(`The module "${modulePath}" can't be imported and will be replaced with {}`) | ||
} | ||
if (standartNodeModules.includes(modulePath)) { replaceAndWarn(); continue; } | ||
if(modulePath.includes('/')) { | ||
let fullPath, relativePath, filename, moduleDir = modulePath | ||
if (modulePath.includes('/')) { | ||
const arr = modulePath.split('/') | ||
@@ -29,11 +38,6 @@ moduleDir = arr.shift() | ||
let pkgJsonPath = `/node_modules/${moduleDir}/package.json` | ||
const exists = await fetch(pkgJsonPath, { method: 'HEAD' }) | ||
const r = new RegExp(`require\\((["'\`])${modulePath}["'\`]\\)`) | ||
if (exists.ok === false) { | ||
content = content.replace(r, '{}') | ||
console.warn(`The module "${modulePath}" can't be imported and will be replaced with {}`) | ||
continue | ||
} | ||
if(packageJsonCache[pkgJsonPath]) filename = packageJsonCache[pkgJsonPath] | ||
if (exists.ok === false) { replaceAndWarn(); continue; } | ||
if (packageJsonCache[pkgJsonPath]) filename = packageJsonCache[pkgJsonPath] | ||
else { | ||
@@ -45,14 +49,9 @@ const { main = 'index.js' } = await Require.fetch(pkgJsonPath, 'json') | ||
if(relativePath) { | ||
const relativeDir = filename.split('/') | ||
relativeDir.pop() | ||
fullPath = `/node_modules/${moduleDir}/${relativeDir.join('/')}/${relativePath}` | ||
} else { | ||
fullPath = `/node_modules/${moduleDir}/${filename}` | ||
} | ||
fullPath = fullPath.replace(/\/\.?\//g,'/') | ||
if(!fullPath.endsWith('.js')) fullPath += '.js' | ||
if (relativePath) fullPath = `/node_modules/${moduleDir}/${relativePath}` | ||
else fullPath = `/node_modules/${moduleDir}/${filename}` | ||
fullPath = fullPath.replace(/\/\.?\//g, '/') | ||
if (!fullPath.endsWith('.js')) fullPath += '.js' | ||
Require.isCyclyc(fullPath, modulePath) | ||
children.push(fullPath); | ||
content = content.replace(match, match.replace(r, (m,quoute) => { | ||
content = content.replace(match, match.replace(r, (m, quoute) => { | ||
return `require(${quoute}${fullPath}${quoute})` | ||
@@ -89,24 +88,47 @@ })) | ||
function getKeys(contents, Require) { | ||
const newKeys = new Set() | ||
const addKeys = (keys) => { | ||
const { cyclicDependencies } = Require | ||
const newKeys = [], cyclic = [] | ||
const addKeys = (keys, ...ancestors) => { | ||
keys.forEach(key => { | ||
if (!contents[key]) return | ||
addKeys(Require.contents[key].children) | ||
newKeys.add(key) | ||
const { children } = Require.contents[key] | ||
if (ancestors.includes(key)) { | ||
cyclic.unshift([key,ancestors]) | ||
return newKeys.push(key) | ||
} | ||
if (!newKeys.includes(key)) { | ||
addKeys(children, ...ancestors, key) | ||
newKeys.push(key) | ||
} | ||
}) | ||
} | ||
addKeys(Object.keys(contents).reverse()) | ||
return Array.from(newKeys) | ||
if(cyclicDependencies === true) { | ||
cyclic.forEach(([cyclicKey,ancestors]) => { | ||
ancestors.reverse() | ||
for (const ancestor of ancestors) { | ||
if (ancestor === cyclicKey) break | ||
for (let i = newKeys.length-1; i >= 0; i--) { | ||
const newKey = newKeys[i] | ||
if (newKey === ancestor) break | ||
if (newKey === cyclicKey) newKeys.splice(i, 1) | ||
} | ||
} | ||
}); | ||
} else if(cyclic.length) throw new Error('Cyclic dependencied: '+ JSON.stringify(cyclic,null,3)) | ||
return newKeys | ||
} | ||
function getFns(contextName='context',obj) { | ||
function buildFn(fnBody,path) { | ||
return /*js*/`modules['${path}'] = (function (){ | ||
const module = { exports: {} } | ||
const exports = module.exports | ||
${fnBody} | ||
return module.exports; | ||
})();` | ||
} | ||
const modulesLines = {} | ||
let curLastLine = 3 | ||
const fns = obj.keys.map((path, i) => { | ||
const fnBody = obj.contents[path]; | ||
let code = `modules['${path}'] = (function (){ | ||
const module = { exports: {} } | ||
const exports = module.exports | ||
${fnBody} | ||
return module.exports; | ||
})();` | ||
let code = buildFn(obj.contents[path],path) | ||
if (i === obj.keys.length - 1) code += `\nreturn modules['${path}']` | ||
@@ -118,3 +140,3 @@ modulesLines[path] = { from: curLastLine + 1 } | ||
}).join('\n') | ||
const fn = new Function('modules', contextName, `function require(path) { return modules[path] || null }; | ||
const fn = new Function('modules', contextName, /*js*/`function require(path) { return modules[path] || null }; | ||
${fns}`) | ||
@@ -142,2 +164,4 @@ return { fn, modulesLines, curLastLine } | ||
static contents = {} | ||
static cyclicDependencies = false | ||
static logger = console | ||
static version | ||
@@ -185,4 +209,6 @@ | ||
} | ||
Require.getFullPath = getFullPath;Require.getNodeModules = getNodeModules;Require.getContents = getContents;Require.getKeys = getKeys;Require.getFns = getFns;Require.parseError = parseError;Require.Require = Require; | ||
Require.standartNodeModules = standartNodeModules; | ||
return Require; | ||
})() | ||
const require = Require.getModule; |
@@ -1,8 +0,9 @@ | ||
let Require=(()=>{let d={};function a(t,e){var n,t=t.split("/"),s=[];for(n of[...e.split("/").slice(0,-1),...t])".."===n?0<s.length&&".."!==s[s.length-1]?s.pop():s.push(n):"."!==n&&s.push(n);e=s.join("/");return e.endsWith(".js")?e:e+".js"}async function t({contents:n,fullPath:t},i){let s=async o=>{if(void 0===n[o]){if(!i.contents[o]){let t=await i.fetch(o),s=[],r=[];t=t.replace(/^(?!\/\/|\/\*.*\*\/).*require\(["'`](.*)["'`]\)/gm,(t,e)=>{var n;return e.startsWith(".")?(n=a(e,o),i.isCyclyc(n,o),s.push(n),t.replace(e,n)):(r.push({match:t,modulePath:e}),t)}),t=await(async(t,r,o,i)=>{if(0!==t.length)for(var{match:a,modulePath:c}of t){let n,t,e,s=c;c.includes("/")&&(l=c.split("/"),s=l.shift(),t=l.join("/"));var l=`/node_modules/${s}/package.json`,u=await fetch(l,{method:"HEAD"}),h=new RegExp(`require\\((["'\`])${c}["'\`]\\)`);!1===u.ok?(o=o.replace(h,"{}"),console.warn(`The module "${c}" can't be imported and will be replaced with {}`)):(e=d[l]||({main:u="index.js"}=await i.fetch(l,"json"),d[l]=u),(n=(n=t?((u=e.split("/")).pop(),`/node_modules/${s}/${u.join("/")}/`+t):`/node_modules/${s}/`+e).replace(/\/\.?\//g,"/")).endsWith(".js")||(n+=".js"),i.isCyclyc(n,c),r.push(n),o=o.replace(a,a.replace(h,(t,e)=>`require(${e}${n}${e})`)))}return o})(r,s,t,i),i.contents[o]={content:t,children:s}}let{content:t,children:e}=i.contents[o];n[o]=t,await Promise.all(e.map(t=>s(t)))}};await s(t)}class r{static contents={};static version;static isCyclyc(t,e){if(this.contents[t]&&this.contents[t].children.includes(e))throw`cyclic dependency between ${e} and `+t}static async fetch(t,e="text"){this.version&&(t+="?version="+this.version);t=await fetch(t);return t.ok||console.error("HTTP error! status: "+t.status),t[e]()}static async getModule(t,e,n,s){t=new r(t);return await t.getContent(),t.build(s,e,n)}constructor(t){this.contents={},this.path=t,this.fullPath=a(t,location.pathname),this.contentReady=!1}async getContent(){return this.contentReady||(await t(this,r),this.keys=((e,n)=>{let s=new Set,r=t=>{t.forEach(t=>{e[t]&&(r(n.contents[t].children),s.add(t))})};return r(Object.keys(e).reverse()),Array.from(s)})(this.contents,r),this.contentReady=!0),this}build(t={},e={},s="context"){var{fn:s,modulesLines:r,curLastLine:o}=((t="context",s)=>{let r={},o=3;var e=s.keys.map((t,e)=>{let n=`modules['${t}'] = (function (){ | ||
const module = { exports: {} } | ||
const exports = module.exports | ||
${s.contents[t]} | ||
return module.exports; | ||
})();`;return e===s.keys.length-1&&(n+=` | ||
return modules['${t}']`),r[t]={from:o+1},o+=n.split("\n").length,r[t].to=o,n}).join("\n");return{fn:new Function("modules",t,`function require(path) { return modules[path] || null }; | ||
`+e),modulesLines:r,curLastLine:o}})(s,this);try{return s(t,e)}catch(n){{s=n;var i=r;var a=o;let[t,...e]=s.stack.split("\n");throw e=e.map(t=>{var e=t.match(/<anonymous>:(\d*):(\d*)\)$/);if(e){let n=Number(e[1]);if(n+1!==a){var s,r,e=Number(e[2]),o=Object.entries(i).filter(([,{from:t,to:e}])=>n>=t&&n<=e);if(0!==o.length)return[o,{from:s,to:r}]=o[0],` at ${t.match(/at\s(.*?)\s/)[1]} ${o} (${n-s-2}:${e})`}}}).filter(Boolean),s.stack=t+"\n"+e.join("\n"),s;return}}}}return r})(),require=Require.getModule; | ||
let Require=(()=>{let d={},n=["assert","async_hooks","buffer","child_process","cluster","console","constants","crypto","dgram","diagnostics_channel","dns","domain","events","fs","http","http2","https","inspector","module","net","os","path","perf_hooks","process","punycode","querystring","readline","repl","stream","string_decoder","sys","timers","timers/promises","tls","trace_events","tty","url","util","v8","vm","wasi","worker_threads","zlib","node:test","abort_controller"];function c(e,t){var n,e=e.split("/"),s=[];for(n of[...t.split("/").slice(0,-1),...e])".."===n?0<s.length&&".."!==s[s.length-1]?s.pop():s.push(n):"."!==n&&s.push(n);t=s.join("/");return t.endsWith(".js")?t:t+".js"}async function a(e,c,a,l){let{logger:t=console}=l;if(0!==e.length)for(let{match:o,modulePath:i}of e){let r=new RegExp(`require\\((["'\`])${i}["'\`]\\)`);var u=()=>{a=a.replace(r,"{}"),t.warn(`The module "${i}" can't be imported and will be replaced with {}`)};if(n.includes(i))u();else{let n,e,t,s=i;i.includes("/")&&(h=i.split("/"),s=h.shift(),e=h.join("/"));var h=`/node_modules/${s}/package.json`;!1===(await fetch(h,{method:"HEAD"})).ok?u():(t=d[h]||({main:u="index.js"}=await l.fetch(h,"json"),d[h]=u),(n=(n=e?`/node_modules/${s}/`+e:`/node_modules/${s}/`+t).replace(/\/\.?\//g,"/")).endsWith(".js")||(n+=".js"),l.isCyclyc(n,i),c.push(n),a=a.replace(o,o.replace(r,(e,t)=>`require(${t}${n}${t})`)))}}return a}async function e({contents:n,fullPath:e},i){let s=async o=>{if(void 0===n[o]){if(!i.contents[o]){let e=await i.fetch(o),s=[],r=[];e=e.replace(/^(?!\/\/|\/\*.*\*\/).*require\(["'`](.*)["'`]\)/gm,(e,t)=>{var n;return t.startsWith(".")?(n=c(t,o),i.isCyclyc(n,o),s.push(n),e.replace(t,n)):(r.push({match:e,modulePath:t}),e)}),e=await a(r,s,e,i),i.contents[o]={content:e,children:s}}let{content:e,children:t}=i.contents[o];n[o]=e,await Promise.all(t.map(e=>s(e)))}};await s(e)}function t(s,r){var e=r.cyclicDependencies;let o=[],i=[],c=(e,...n)=>{e.forEach(e=>{var t;if(s[e])return t=r.contents[e].children,n.includes(e)?(i.unshift([e,n]),o.push(e)):void(o.includes(e)||(c(t,...n,e),o.push(e)))})};if(c(Object.keys(s).reverse()),!0===e)i.forEach(([t,e])=>{e.reverse();for(var n of e){if(n===t)break;for(let e=o.length-1;0<=e;e--){var s=o[e];if(s===n)break;s===t&&o.splice(e,1)}}});else if(i.length)throw new Error("Cyclic dependencied: "+JSON.stringify(i,null,3));return o}function o(e="context",r){let o={},i=3;var t=r.keys.map((e,t)=>{s=r.contents[e];let n=`modules['${e}'] = (function (){ | ||
const module = { exports: {} } | ||
const exports = module.exports | ||
${s} | ||
return module.exports; | ||
})();`;var s;return t===r.keys.length-1&&(n+=` | ||
return modules['${e}']`),o[e]={from:i+1},i+=n.split("\n").length,o[e].to=i,n}).join("\n");return{fn:new Function("modules",e,`function require(path) { return modules[path] || null }; | ||
`+t),modulesLines:o,curLastLine:i}}function i(e,i,c){let[t,...n]=e.stack.split("\n");throw n=n.map(e=>{var t=e.match(/<anonymous>:(\d*):(\d*)\)$/);if(t){let n=Number(t[1]);if(n+1!==c){var s,r,t=Number(t[2]),o=Object.entries(i).filter(([,{from:e,to:t}])=>n>=e&&n<=t);if(0!==o.length)return[o,{from:s,to:r}]=o[0],` at ${e.match(/at\s(.*?)\s/)[1]} ${o} (${n-s-2}:${t})`}}}).filter(Boolean),e.stack=t+"\n"+n.join("\n"),e}class r{static contents={};static cyclicDependencies=!1;static logger=console;static version;static isCyclyc(e,t){if(this.contents[e]&&this.contents[e].children.includes(t))throw`cyclic dependency between ${t} and `+e}static async fetch(e,t="text"){this.version&&(e+="?version="+this.version);e=await fetch(e);return e.ok||console.error("HTTP error! status: "+e.status),e[t]()}static async getModule(e,t,n,s){e=new r(e);return await e.getContent(),e.build(s,t,n)}constructor(e){this.contents={},this.path=e,this.fullPath=c(e,location.pathname),this.contentReady=!1}async getContent(){return this.contentReady||(await e(this,r),this.keys=t(this.contents,r),this.contentReady=!0),this}build(e={},t={},n="context"){var{fn:n,modulesLines:s,curLastLine:r}=o(n,this);try{return n(e,t)}catch(e){i(e,s,r)}}}return r.getFullPath=c,r.getNodeModules=a,r.getContents=e,r.getKeys=t,r.getFns=o,r.parseError=i,(r.Require=r).standartNodeModules=n,r})(); | ||
const require=Require.getModule; |
@@ -110,3 +110,3 @@ const { describe, it } = require('node:test'); | ||
} catch (error) { | ||
assert(error === 'cyclic dependency between /tests/modules/e.js and /tests/modules/d.js') | ||
assert(error === 'Cyclic dependency between /tests/modules/e.js and /tests/modules/d.js') | ||
} | ||
@@ -113,0 +113,0 @@ }); |
Sorry, the diff of this file is not supported yet
73370
36
1177
2
247