npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@effectful/cc

v2.0.12

Published

Multi-prompt delimited continuations runtime

Readme

@effectful/cc

Runtime library for multi-prompt delimited continuations with EffectfulJS.

From v2 the library uses @effectful/debugger for implementation of control effects. This makes the transpilation to be heavier, but many useful features are enabled by default. Such us:

  • code is debuggable in VSCode using effectfuk.debugger extension
  • continuations and all the functions are serializable
  • and more

It's also now only supports one-layer JavaScript (no overriding of async/await and generators syntaxes at the moment). I simply don't need them, but they are quite simple to add if needed. Let me know if you need them.

Async/await and genrators are still available, though, with the same semantics as in JavaScript. However, it's not clear, why you would need them in the presence of delimited continuations.

API documentation

Description

It is the most generic effects API implementation, and it can be converted into any other one. These include JavaScript built-in effects - state, async/await, generators, exception, etc.

Delimited continuations effect is also, probably, the most complex to understand. I'm trying to explain it using exceptions analogy here. It is like an exception, with execution may be resumed from throw point several times.

This library is multi-prompt one. Prompt is a kind of a label. Imagine JavaScript has labeled try-catch and throw statements. The label is specified as another argument of throw and only catch block with the same label catches it. All the others just rethrow to their upper level. In the library the prompt(label) function is created using CC.newPrompt function.

Function CC.pushPrompt is a replacement of try block. Its first argument is a prompt object (specifying which exceptions) to catch, and the second argument is a try body where an exception (with same prompt) may raise. Note, there is no catch block, it is specified with throw replacement.

The throw replacement is CC.withSubCont. Its first argument is a prompt object again, specifying which CC.pushPrompt should catch it. If there are a few CC.pushPrompt with the same prompt, the innermost will be selected. The second argument is a catch block. Unlike try-catch where the block is adjunct of try statement, here it is specified along with throw replacement. Also, there is no exception object.

The catch block is a function taking continuation object. It captures execution path from CC.withSubCont (throw) to CC.pushPrompt (try). In JavaScript exceptions, it is simply dropped. This object allows resuming execution from the CC.withSubCont (throw) several times.

If the captured continuation never executed the library works precisely like exceptions. First executes catch block and continues after try if the catch block doesn't throw anything else.

The continuation object received in CC.withSubCont may be called anywhere using CC.pushSubCont function. Its first argument is the continuation object captured in CC.withSubCont.

When CC.withSubCont is called, like for throw statement, the execution control is suspended (aborted). When CC.pushSubCont is called the execution is resumed with a resulting value of CC.withSubCont on the resume is a result of the second argument of CC.pushSubCont.

After the resumed execution control reaches CC.pushPrompt (try statement), if not interrupted by anything else, it continues from the CC.pushSubCont call. The call result is a result of CC.pushPrompt block.

These four functions are the base. The others are defined using them.

When resuming continuations several times, if they change some variable values, the change is visible on next run by default. However, the continuation object may be cloned in whatever way your program needs (shallow/deep) to restore variables values. Alternatively, it may be Proxy based copy-on-write for better performance.

The continuations are serializable using @effectful/serialization.

Usage

npm install @effectful/cc
npm install --save-dev @effectful/js

Note, if you need to use eval or Function constructor, --save "@effectful/js" too.

Import into your code, and use babel-plugin-macro to transform the whole file:

import ctrl from "@effectful/js/macro";
import * as CC from "@effectful/cc";

WARNING: the babel plugin for the transpilation must run in a separate pass in the preset, for example:

{
  "passPerPreset": true,
  "presets": [
    "some-other-preset",
    {
      "plugins": ["babel-plugin-macro"]
    }
  ]
}

See @effectful/js for more details about alternative ways to transpile the code.

Since the transpiler currently doesn't support import and thus must be pre-transpiled into CommonJS with @babel/plugin-transform-modules-commonjs. And babel-plugin-macros ignores require if it isn't in variable declarations, we cannot use a shorthand syntax with just import. It must be default import (or some variable declaration for CommonJS require), with the actual imported value never used.

Also @babel/plugin-transform-typescript may remove this import since it isn't used. To avoid this pass { "onlyRemoveTypeImports": true } argument.

References

The library implements interface from A Monadic Framework for Delimited Continuations paper.

License

Distributed under the terms of the The MIT License (MIT).