New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

dynohot

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dynohot - npm Package Compare versions

Comparing version 1.1.0 to 1.1.1

8

dist/hot.d.ts
type ModuleNamespace = Record<string, unknown>;
export declare class Hot<Data extends Record<keyof any, unknown> = Record<keyof any, unknown>> {
#private;
/**

@@ -8,3 +9,4 @@ * This is the `data` object passed to the `dispose` handler of the previous `Hot` instance.

*/
readonly data?: Data;
readonly data?: Data | undefined;
constructor(module: unknown, instance: unknown, usesDynamicImport: boolean, data?: Data);
/**

@@ -46,4 +48,8 @@ * Accept updates for this module. When any unaccepted dependencies are updated this module will

prune(onPrune: () => Promise<void> | void): void;
/**
* Listen for informative messages which are sent to `console`.
*/
on(event: "message", callback: (message: string, ...params: unknown[]) => void): () => void;
}
export {};
//# sourceMappingURL=hot.d.ts.map

56

dist/loader/loader.js

@@ -6,2 +6,3 @@ import * as assert from "node:assert/strict";

import Fn from "dynohot/functional";
import { maybeThen } from "dynohot/runtime/utility";
import { transformModuleSource } from "./transform.js";

@@ -12,3 +13,3 @@ const self = new URL(import.meta.url);

const root = String(new URL("..", self));
const runtimeURL = `${root}runtime/runtime.js`;
const runtimeURL = `${root}runtime/runtime.js?${String(self.searchParams)}`;
function extractImportAssertions(params) {

@@ -63,24 +64,2 @@ const entries = Array.from(Fn.transform(Fn.filter(params, entry => entry[0] === "with"), entry => new URLSearchParams(entry[1])));

};
/**
* Resolvers are ~allowed~ to return promises, but actually they shouldn't. nodejs accidentally
* locked themselves into a promise-based API but then the `import.meta.resolve` specification
* changed to be synchronous. So they work around it with some horrific `Atomics.wait` thing which
* hard locks the thread until the promise resolves.
*
* This utility is used to detect a promise from an underlying loader and `then` it, or just execute
* the callback synchronously.
*/
function maybeThen(maybePromise, then) {
// For the life of me, I can't figure out how to type this. `maybePromise` should probably also
// include `& { then?: never }` and maybe the primitives, but that causes other problems.
// @ts-expect-error -- I don't know how to type this
if (typeof maybePromise.then === "function") {
// @ts-expect-error -- I don't know how to type this
return maybePromise.then(then);
}
else {
// @ts-expect-error -- I don't know how to type this
return then(maybePromise);
}
}
function asString(sourceText) {

@@ -104,5 +83,8 @@ if (sourceText instanceof Buffer) {

if (context.parentURL === undefined) {
return maybeThen(nextResolve(specifier, context), result => ({
url: `hot:main?url=${encodeURIComponent(result.url)}`,
}));
return maybeThen(function* () {
const result = yield nextResolve(specifier, context);
return {
url: `hot:main?url=${encodeURIComponent(result.url)}`,
};
});
}

@@ -119,7 +101,8 @@ // [static imports] Convert "hot:module?specifier=..." to "hot:module?url=..."

const importAssertions = extractImportAssertions(resolutionURL.searchParams);
return maybeThen(nextResolve(resolutionSpecifier, {
...context,
parentURL: parentModuleURL,
importAssertions,
}), result => {
return maybeThen(function* () {
const result = yield nextResolve(resolutionSpecifier, {
...context,
parentURL: parentModuleURL,
importAssertions,
});
const params = new URLSearchParams([

@@ -144,7 +127,8 @@ ["url", result.url],

const importAssertions = extractImportAssertions(resolutionURL.searchParams);
return maybeThen(nextResolve(resolutionSpecifier, {
...context,
parentURL: parentModuleURL,
importAssertions,
}), result => {
return maybeThen(function* () {
const result = yield nextResolve(resolutionSpecifier, {
...context,
parentURL: parentModuleURL,
importAssertions,
});
const params = new URLSearchParams([

@@ -151,0 +135,0 @@ ["url", result.url],

@@ -11,3 +11,2 @@ import Fn from "dynohot/functional";

url;
linkIndex = 0;
namespace;

@@ -44,5 +43,2 @@ resolutions;

}
resolveExportInner(exportName) {
return this.resolveExport(exportName);
}
select() {

@@ -49,0 +45,0 @@ return this;

@@ -0,2 +1,49 @@

/// <reference types="node" resolution-mode="require"/>
import type { ModuleNamespace } from "./module.js";
import { EventEmitter } from "node:events";
export interface HotApplication {
dynamicImport: DynamicImport;
emitter: EventEmitter;
log: (message: string, ...params: any[]) => void;
requestUpdate: () => Promise<void>;
requestUpdateResult: () => Promise<UpdateResult>;
}
type DynamicImport = (specifier: string, importAssertions?: Record<string, string>) => Promise<ModuleNamespace>;
type UpdateResult = undefined | UpdateSuccess | UpdateDeclined | UpdateUnaccepted | UpdateEvaluationError | UpdateFatalError | UpdateLinkError;
interface UpdateSuccess {
type: UpdateStatus.success | UpdateStatus.unacceptedEvaluation;
stats: () => UpdateStats;
}
interface UpdateDeclined {
type: UpdateStatus.declined;
declined: readonly ReloadableModuleController[];
}
interface UpdateUnaccepted {
type: UpdateStatus.unaccepted;
chain: readonly InvalidationChain[];
}
interface UpdateEvaluationError {
type: UpdateStatus.evaluationFailure;
error: unknown;
stats: () => UpdateStats;
}
interface UpdateLinkError {
type: UpdateStatus.linkError;
error: unknown;
}
interface UpdateFatalError {
type: UpdateStatus.fatalError;
error: unknown;
}
interface UpdateStats {
duration: number;
loads: number;
reevaluations: number;
}
interface InvalidationChain {
modules: readonly ReloadableModuleController[];
/** `undefined` means it's the end of the chain, `null` means we've seen this branch before */
next: readonly InvalidationChain[] | undefined | null;
}
export {};
//# sourceMappingURL=controller.d.ts.map
import * as assert from "node:assert/strict";
import { EventEmitter } from "node:events";
import { EOL } from "node:os";
import Fn from "dynohot/functional";

@@ -8,10 +10,19 @@ import { BindingType } from "./binding.js";

import { makeAcquireVisitIndex, makeTraversalState, traverseDepthFirst } from "./traverse.js";
import { debounceAsync, debounceTimer, discriminatedTypePredicate, evictModule, iterateWithRollback, makeRelative, plural } from "./utility.js";
import { debounceAsync, debounceTimer, discriminatedTypePredicate, evictModule, makeRelative, maybeAll, maybeThen, plural } from "./utility.js";
import { FileWatcher } from "./watcher.js";
/** @internal */
export function makeAcquire(dynamicImport) {
export function makeAcquire(dynamicImport, params) {
const emitter = new EventEmitter;
const useLogs = params.silent === undefined;
const application = {
dynamicImport,
emitter,
requestUpdate: defaultRequestUpdate,
requestUpdateResult: defaultRequestUpdateResult,
log(message, ...params) {
if (useLogs) {
console.error(`[hot] ${message}`, ...params);
}
emitter.emit("message", message, ...params);
},
};

@@ -28,3 +39,2 @@ const modules = new Map();

function defaultRequestUpdate() {
console.error("[hot] Update requested before fully loaded.");
return Promise.resolve();

@@ -47,3 +57,3 @@ }

})(UpdateStatus || (UpdateStatus = {}));
function logUpdate(update) {
function logUpdate(app, update) {
if (update === undefined) {

@@ -54,6 +64,7 @@ return;

case UpdateStatus.declined:
console.error(`[hot] A pending update was explicitly declined:\n${update.declined.map(module => `- ${makeRelative(module.url)}`).join("\n")}`);
app.log("A pending update was explicitly declined:" +
update.declined.map(() => `${EOL}- %s`).join(), ...update.declined.map(declined => makeRelative(declined.url)));
break;
case UpdateStatus.fatalError:
console.error("[hot] A fatal error was encountered. The application should be restarted!");
app.log("A fatal error was encountered. The application should be restarted!");
break;

@@ -63,4 +74,4 @@ case UpdateStatus.evaluationFailure: {

const ms = Math.round(duration);
console.error(`[hot] Loaded ${loads} new ${plural("module", loads)}, reevaluated ${reevaluations} existing ${plural("module", reevaluations)} in ${ms}ms.`);
console.error("[hot] Caught evaluation error:", update.error);
app.log(`Loaded %d new ${plural("module", loads)}, reevaluated %d existing ${plural("module", reevaluations)} in %dms.`, loads, reevaluations, ms);
app.log("Caught evaluation error:", update.error);
break;

@@ -70,8 +81,9 @@ }

const { error } = update;
console.error("[hot] Caught link error:");
if (error instanceof SyntaxError && "url" in error) {
console.error(`${error.name}: ${error.message}\n at (${String(error.url)})`);
app.log("Caught link error:" + EOL +
"%s: %s" + EOL +
" at (%s)", error.name, error.message, error.url);
}
else {
console.error(error);
app.log(`Caught link error:${EOL}%O`, error);
}

@@ -83,29 +95,9 @@ break;

const ms = Math.round(duration);
console.error(`[hot] Loaded ${loads} new ${plural("module", loads)}, reevaluated ${reevaluations} existing ${plural("module", reevaluations)} in ${ms}ms.`);
app.log(`Loaded %d new ${plural("module", loads)}, reevaluated %d existing ${plural("module", reevaluations)} in %dms.`, loads, reevaluations, ms);
break;
}
case UpdateStatus.unaccepted: {
// Nice:
// https://stackoverflow.com/questions/4965335/how-to-print-binary-tree-diagram-in-java/8948691#8948691
const logChain = (chain, prefix = "", childrenPrefix = "") => {
const suffix = chain.next === undefined ? " 🔄" : "";
console.error(` ${prefix}[${chain.modules.map(module => makeRelative(module.url)).join(", ")}]${suffix}`);
if (chain.next === null) {
console.error(` ${childrenPrefix}[...]`);
}
else if (chain.next !== undefined) {
for (const [ii, child] of chain.next.entries()) {
if (ii === chain.next.length - 1) {
logChain(child, `${childrenPrefix}└─ `, `${childrenPrefix} `);
}
else {
logChain(child, `${childrenPrefix}├─ `, `${childrenPrefix}│ `);
}
}
}
};
console.error("[hot] A pending update was not accepted, and reached the root module:");
for (const chain of update.chain) {
logChain(chain);
}
const messages = [...Fn.transform(update.chain, flattenInvalidationTree)];
app.log("A pending update was not accepted, and reached the root module:" +
messages.map(([message]) => `${EOL}${message}`).join(""), ...Fn.transform(messages, ([, ...params]) => params));
break;

@@ -116,4 +108,4 @@ }

const ms = Math.round(duration);
console.error(`[hot] Loaded ${loads} new ${plural("module", loads)}, reevaluated ${reevaluations} existing ${plural("module", reevaluations)} in ${ms}ms.`);
console.error("[hot] Unaccepted update reached the root module. The application should be restarted!");
app.log(`Loaded %d new ${plural("module", loads)}, reevaluated %d existing ${plural("module", reevaluations)} in %dms.`, loads, reevaluations, ms);
app.log("Unaccepted update reached the root module. The application should be restarted!");
break;

@@ -123,2 +115,24 @@ }

}
// Nice:
// https://stackoverflow.com/questions/4965335/how-to-print-binary-tree-diagram-in-java/8948691#8948691
function* flattenInvalidationTree(chain, prefix = "", childrenPrefix = "") {
const suffix = chain.next === undefined ? " 🔄" : "";
yield [
` ${prefix}[${chain.modules.map(() => "%s").join(", ")}]${suffix}`,
...chain.modules.map(module => makeRelative(module.url)),
];
if (chain.next === null) {
yield [` %s${childrenPrefix}[...]`];
}
else if (chain.next !== undefined) {
for (const [ii, child] of chain.next.entries()) {
if (ii === chain.next.length - 1) {
yield* flattenInvalidationTree(child, `${childrenPrefix}└─ `, `${childrenPrefix} `);
}
else {
yield* flattenInvalidationTree(child, `${childrenPrefix}├─ `, `${childrenPrefix}│ `);
}
}
}
}
const acquireVisitIndex = makeAcquireVisitIndex();

@@ -163,3 +177,3 @@ /** @internal */

catch (error) {
console.log(error);
this.application.log(`Error in module '%s':${EOL}%O`, this.url, error);
return;

@@ -176,3 +190,3 @@ }

const update = await this.requestUpdate();
logUpdate(update);
logUpdate(this.application, update);
}));

@@ -193,25 +207,25 @@ this.application.requestUpdateResult = () => this.requestUpdate();

return node.iterate();
}, async (cycleNodes) => {
}, cycleNodes => maybeThen(function* () {
// Instantiate the cycle (cannot fail)
for (const node of cycleNodes) {
const maybe = node.select().instantiate();
if (maybe) {
await maybe;
}
yield node.select().instantiate();
}
// Link the cycle
const withRollback = iterateWithRollback(cycleNodes, nodes => {
for (const node of nodes) {
if (node.select().unlink()) {
node.current = undefined;
for (let ii = 0; ii < cycleNodes.length; ++ii) {
const node = cycleNodes[ii];
try {
yield node.select().link();
}
catch (error) {
// Unlink failed cycle nodes
for (let jj = ii; jj < cycleNodes.length; ++jj) {
if (node.select().unlink()) {
node.current = undefined;
}
}
throw error;
}
});
for (const node of withRollback) {
const maybe = node.select().link();
if (maybe) {
await maybe;
}
}
}, pendingNodes => {
return undefined;
}), pendingNodes => {
for (const node of pendingNodes) {

@@ -227,14 +241,9 @@ if (node.select().unlink()) {

return node.iterate();
}, async (cycleNodes) => {
for (const node of cycleNodes) {
const current = node.select();
if (current === node.staging) {
node.staging = undefined;
}
const maybe = current.evaluate();
if (maybe) {
await maybe;
}
}, cycleNodes => maybeAll(Fn.map(cycleNodes, node => {
const current = node.select();
if (current === node.staging) {
node.staging = undefined;
}
});
return current.evaluate();
})));
}

@@ -451,3 +460,3 @@ }

return node.iterateWithDynamics(controller => controller.pending, controller => controller.previous ?? controller.pending);
}, async (cycleNodes, forwardResults) => {
}, (cycleNodes, forwardResults) => maybeThen(function* () {
let hasUpdate = Fn.some(forwardResults);

@@ -467,6 +476,3 @@ if (!hasUpdate) {

node.temporary = pending.clone();
const maybe = node.temporary.instantiate();
if (maybe) {
await maybe;
}
yield node.temporary.instantiate();
instantiated.push(node);

@@ -476,10 +482,7 @@ }

const temporary = node.select(controller => controller.temporary);
const maybe = temporary.link(controller => controller.temporary ?? controller.pending);
if (maybe) {
await maybe;
}
yield temporary.link(controller => controller.temporary ?? controller.pending);
}
}
return hasUpdate;
});
}));
}

@@ -538,3 +541,3 @@ catch (error) {

const pending = node.select(controller => controller.pending);
const data = await async function () {
const data = await (async () => {
try {

@@ -544,8 +547,7 @@ return node.current === undefined ? undefined : await dispose(node.current);

catch (error) {
console.error(`[hot] Caught error in module '${node.url}' during dispose:`);
console.error(error);
this.application.log(`Caught error in module '%s' during dispose:${EOL}%O`, node.url, error);
dispatchLinkErrorType = UpdateStatus.fatalError;
throw error;
}
}();
})();
if (node.current === pending) {

@@ -570,12 +572,3 @@ node.current = node.current.clone();

// 3) Evaluate
const withRollback = iterateWithRollback(cycleNodes, nodes => {
for (const node of nodes) {
const current = node.select();
assert.ok(current.state.status === ModuleStatus.evaluated);
if (current.state.evaluationError !== undefined) {
node.current = node.previous;
}
}
});
for (const node of withRollback) {
const maybe = maybeAll(Fn.map(cycleNodes, node => maybeThen(function* () {
const current = node.select();

@@ -588,6 +581,13 @@ if (node.previous !== undefined && current.declaration === node.previous.declaration) {

}
const maybe = current.evaluate();
if (maybe) {
await maybe;
try {
yield current.evaluate();
}
catch (error) {
const current = node.select();
assert.ok(current.state.status === ModuleStatus.evaluated);
if (current.state.evaluationError !== undefined) {
node.current = node.previous;
}
throw error;
}
node.pending = undefined;

@@ -597,2 +597,6 @@ if (current === node.staging) {

}
return undefined;
})));
if (maybe) {
await maybe;
}

@@ -656,4 +660,3 @@ // Try self-accept

catch (error) {
console.error(`[hot] Caught error in module '${controller.url}' during prune:`);
console.error(error);
this.application.log(`Caught error in module '%s' during prune:${EOL}%O`, controller.url, error);
// eslint-disable-next-line no-unsafe-finally

@@ -660,0 +663,0 @@ return this.fatalError = { type: UpdateStatus.fatalError, error };

@@ -47,4 +47,8 @@ type ModuleNamespace = Record<string, unknown>;

prune(onPrune: () => Promise<void> | void): void;
/**
* Listen for informative messages which are sent to `console`.
*/
on(event: "message", callback: (message: string, ...params: unknown[]) => void): () => void;
}
export {};
//# sourceMappingURL=hot.d.ts.map
import * as assert from "node:assert/strict";
import { EOL } from "node:os";
import Fn from "dynohot/functional";

@@ -93,5 +94,5 @@ import { ReloadableModuleController } from "./controller.js";

}));
console.error(`[hot] Warning: ${plural("specifier", specifiers.length)} ${specifiers.map(specifier => JSON.stringify(specifier)).join(", ")} from ${makeRelative(hot.#module.url)} could not be resolved.`);
hot.#module.application.log(`Warning: ${plural("specifier", specifiers.length)} ${specifiers.map(() => "%s").join(", ")} from %s could not be resolved.`, ...specifiers.map(specifier => JSON.stringify(specifier)), makeRelative(hot.#module.url));
if (accepts.localEntries.length > 1) {
console.error(`[hot] The entire accept group of: ${accepts.localEntries.map(entry => JSON.stringify(entry.specifier)).join(", ")} will be ignored.`);
hot.#module.application.log(`The entire accept group of: ${accepts.localEntries.map(() => "%s").join(", ")} will be ignored.`, ...accepts.localEntries.map(entry => JSON.stringify(entry.specifier)));
}

@@ -154,4 +155,3 @@ }

catch (error) {
console.error(`[hot] Caught error in module '${hot.#module.url}' during accept of [${accepts.localEntries.map(entry => `'${entry.specifier}'`).join(", ")}]:`);
console.error(error);
hot.#module.application.log(`Caught error in module '%s' during accept of [${accepts.localEntries.map(() => "%s").join(", ")}]:${EOL}%O`, hot.#module.url, ...accepts.localEntries.map(entry => `'${entry.specifier}'`), error);
return false;

@@ -178,4 +178,3 @@ }

catch (error) {
console.error(`[hot] Caught error in module '${hot.#module.url}' during self-accept:`);
console.error(error);
hot.#module.application.log(`Caught error in module '%s' during self-accept:${EOL}%O`, hot.#module.url, error);
return false;

@@ -262,4 +261,10 @@ }

}
on(event, callback) {
this.#module.application.emitter.addListener(event, callback);
return () => {
this.#module.application.emitter.removeListener(event, callback);
};
}
}
Object.freeze(Hot.prototype);
//# sourceMappingURL=hot.js.map

@@ -8,5 +8,3 @@ import * as assert from "node:assert/strict";

import { ModuleStatus } from "./module.js";
import { makeAcquireVisitIndex } from "./traverse.js";
import { moduleNamespacePropertyDescriptor, withResolvers } from "./utility.js";
const acquireLinkIndex = makeAcquireVisitIndex();
/** @internal */

@@ -17,3 +15,2 @@ export class ReloadableModuleInstance {

reloadable = true;
linkIndex = 0;
state = { status: ModuleStatus.new };

@@ -87,3 +84,3 @@ dynamicImports = [];

module.state.status === ModuleStatus.evaluatingAsync);
return module.resolveExport(exportName, select);
return module.resolveExport(exportName, select, undefined);
});

@@ -96,3 +93,2 @@ const imports = Object.fromEntries(bindings);

environment: this.state.environment,
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
completion: withResolvers(),

@@ -127,3 +123,3 @@ };

module.state.status === ModuleStatus.evaluatingAsync);
return module.resolveExport(exportName, select);
return module.resolveExport(exportName, select, undefined);
});

@@ -171,3 +167,3 @@ if (this.state.status !== ModuleStatus.linked) {

assert.ok(next.done);
completion.resolve();
completion.resolve(undefined);
this.state = {

@@ -198,3 +194,3 @@ status: ModuleStatus.evaluated,

assert.ok(next.done);
completion.resolve();
completion.resolve(undefined);
this.state = {

@@ -299,3 +295,3 @@ status: ModuleStatus.evaluated,

if (entry.binding.type === BindingType.indirectExport) {
const resolution = instance.resolveExport(entry.binding.name, select);
const resolution = instance.resolveExport(entry.binding.name, select, undefined);
assert.ok(resolution != null);

@@ -329,12 +325,3 @@ resolutions.set(entry.binding.as ?? entry.binding.name, resolution);

// 16.2.1.6.3 ResolveExport ( exportName [ , resolveSet ] )
resolveExport(exportName, select) {
const [release, linkIndex] = acquireLinkIndex();
try {
return this.resolveExportInner(exportName, select, linkIndex);
}
finally {
release();
}
}
resolveExportInner(exportName, select, linkIndex) {
resolveExport(exportName, select, resolveSet = new Map) {
// 1. Assert: module.[[Status]] is not new.

@@ -344,22 +331,17 @@ assert.ok(this.state.status !== ModuleStatus.new);

// 3. For each Record { [[Module]], [[ExportName]] } r of resolveSet, do
// TODO: Finish this. `resolveSet` is responsible for detecting unresolved circular
// imports. For well-typed code it isn't a problem
const resolveSet = new Map();
let imports = resolveSet.get(this);
if (imports === undefined) {
imports = new Set();
resolveSet.set(this, imports);
const moduleResolveSet = resolveSet.get(this);
if (moduleResolveSet) {
if (moduleResolveSet.has(exportName)) {
// a. If module and r.[[Module]] are the same Module Record and SameValue(exportName, r.
// [[ExportName]]) is true, then
// i. Assert: This is a circular import request.
// ii. Return null.
return null;
}
moduleResolveSet.add(exportName);
}
else if (imports.has(exportName)) {
// a. If module and r.[[Module]] are the same Module Record and SameValue(exportName, r.
// [[ExportName]]) is true, then
// i. Assert: This is a circular import request.
// ii. Return null.
return null;
else {
// 4. Append the Record { [[Module]]: module, [[ExportName]]: exportName } to resolveSet.
resolveSet.set(this, new Set([exportName]));
}
// 4. Append the Record { [[Module]]: module, [[ExportName]]: exportName } to resolveSet.
if (this.linkIndex === linkIndex) {
return null;
}
this.linkIndex = linkIndex;
// 5. For each ExportEntry Record e of module.[[LocalExportEntries]], do

@@ -391,3 +373,3 @@ const localExport = this.state.environment.exports[exportName];

// 2. Return importedModule.ResolveExport(e.[[ImportName]], resolveSet).
return importedModule.resolveExportInner(indirectExport.binding.name, select, linkIndex);
return importedModule.resolveExport(indirectExport.binding.name, select, resolveSet);
}

@@ -409,3 +391,3 @@ }

// b. Let resolution be importedModule.ResolveExport(exportName, resolveSet).
const resolution = importedModule.resolveExportInner(exportName, select, linkIndex);
const resolution = importedModule.resolveExport(exportName, select, resolveSet);
// c. If resolution is ambiguous, return ambiguous.

@@ -412,0 +394,0 @@ if (resolution === undefined) {

import { AdapterModuleController } from "./adapter.js";
import { makeAcquire } from "./controller.js";
const self = new URL(import.meta.url);
const params = self.searchParams;
/** @internal */
export const acquire = makeAcquire((specifier, assertions) => import(specifier, assertions));
export const acquire = makeAcquire((specifier, assertions) => import(specifier, assertions), Object.fromEntries(params));
/** @internal */

@@ -6,0 +8,0 @@ export function adapter(url, namespace) {

@@ -11,4 +11,9 @@ import * as assert from "node:assert/strict";

lock = true;
const release = () => { lock = false; };
return [release, ++currentVisitIndex];
const visitIndex = ++currentVisitIndex;
const release = () => {
assert.ok(lock);
assert.equal(currentVisitIndex, visitIndex);
lock = false;
};
return [release, visitIndex];
};

@@ -84,3 +89,2 @@ };

const cycleNodes = stack.splice(stackIndex);
cycleNodes.reverse();
// Collect forward results from cycle nodes

@@ -87,0 +91,0 @@ let hasPromise = false;

@@ -1,2 +0,11 @@

export {};
/**
* Given an iterable of "maybe" promises this returns either `undefined` or a promise indicating
* that all the yielded promises have resolved.
*/
export declare function maybeAll(maybePromises: Iterable<MaybePromise<undefined>>): MaybePromise<undefined>;
/**
* Very simple version of something like `gensync`. For functions which might be async, but probably
* aren't.
*/
export declare function maybeThen<Return, Async extends NotPromiseLike>(task: () => Generator<MaybePromise<Async>, MaybePromise<Return>, Async>): MaybePromise<Return>;
//# sourceMappingURL=utility.d.ts.map

@@ -5,2 +5,3 @@ import * as assert from "node:assert";

import { fileURLToPath } from "node:url";
import Fn from "dynohot/functional";
/** @internal */

@@ -91,22 +92,38 @@ export const moduleNamespacePropertyDescriptor = {

/**
* Returns a delegate iterable to an array which invokes a rollback function on the iterated
* elements if iteration didn't complete [due to an exception hopefully].
* @internal
* Given an iterable of "maybe" promises this returns either `undefined` or a promise indicating
* that all the yielded promises have resolved.
*/
export function* iterateWithRollback(vector, rollback) {
let ii = 0;
try {
for (; ii < vector.length; ++ii) {
yield vector[ii];
}
export function maybeAll(maybePromises) {
const promises = Array.from(Fn.filter(maybePromises));
if (promises.length > 0) {
return async function () {
// Don't continue until all settled
await Promise.allSettled(promises);
// Throw on failure
await Promise.all(promises);
}();
}
finally {
if (ii !== vector.length) {
rollback(function* () {
for (let jj = ii; jj >= 0; --jj) {
yield vector[jj];
}
/**
* Very simple version of something like `gensync`. For functions which might be async, but probably
* aren't.
*/
export function maybeThen(task) {
const iterator = task();
let next = iterator.next();
while (!next.done) {
if (next.value != null &&
typeof next.value.then === "function") {
// We are now a promise
return async function () {
while (!next.done) {
next = iterator.next(await next.value);
}
}());
return next.value;
}();
}
// Continue synchronously
next = iterator.next(next.value);
}
return next.value;
}

@@ -113,0 +130,0 @@ const cwd = process.cwd();

{
"name": "dynohot",
"type": "module",
"version": "1.1.0",
"version": "1.1.1",
"exports": {
".": "./dist/loader/loader.js",
"./?": "./dist/loader/loader.js",
"./?*": "./dist/loader/loader.js?*",
"./register": "./dist/loader/register.js",
"./register?": "./dist/loader/register.js",
"./register?*": "./dist/loader/register.js?*",

@@ -21,3 +23,3 @@ "./import-meta": {

"prepare": "rm -rf dist && tsc -b",
"test": "NODE_OPTIONS='--no-warnings --experimental-vm-modules' npx jest --silent"
"test": "NODE_OPTIONS='--no-warnings --experimental-vm-modules' npx jest"
},

@@ -24,0 +26,0 @@ "dependencies": {

@@ -172,2 +172,7 @@ [![npm version](https://badgen.now.sh/npm/v/dynohot)](https://www.npmjs.com/package/dynohot)

prune(onPrune: () => Promise<void> | void): void;
/**
* Listen for informative messages which are sent to `console`.
*/
on(event: "message", callback: (message: string, ...params: unknown[]) => void): () => void;
}

@@ -284,2 +289,13 @@ ```

OPTIONS
-------
You can pass options to dynohot using `--import dynohot/register?option=value` or `--loader dynohot/?option=value`.
* `ignore` - Pass `?ignore=regexpPattern` to explicitly ignore certain file paths. By default this is
`ignore=[/\]node_modules[/\]`.
* `silent` - Pass `?silent` to prevent logging messages to stderr console. You might want this if
you're using something like Winston or Pino. Be sure to use `import.meta.on("message", ...)` to
raise informative dynohot messages to the developer's attention.
TRANSFORMATION

@@ -286,0 +302,0 @@ --------------

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