{"id":16229209,"url":"https://github.com/morris/cps1","last_synced_at":"2025-07-25T07:38:52.956Z","repository":{"id":26262819,"uuid":"29710076","full_name":"morris/cps1","owner":"morris","description":"A specification for continuation-passing style functions and callbacks in JavaScript.","archived":false,"fork":false,"pushed_at":"2015-09-30T14:43:47.000Z","size":196,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-08T04:52:58.103Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/morris.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-23T01:21:12.000Z","updated_at":"2020-10-28T12:15:43.000Z","dependencies_parsed_at":"2022-08-26T17:50:10.685Z","dependency_job_id":null,"html_url":"https://github.com/morris/cps1","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/morris/cps1","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morris%2Fcps1","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morris%2Fcps1/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morris%2Fcps1/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morris%2Fcps1/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/morris","download_url":"https://codeload.github.com/morris/cps1/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morris%2Fcps1/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266974612,"owners_count":24014943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-25T02:00:09.625Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-10T12:57:41.456Z","updated_at":"2025-07-25T07:38:52.918Z","avatar_url":"https://github.com/morris.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Callback-Passing Style 1 (CPS1)\n\n__Open Standard Draft__\n\nCallback-passing style (CPS) is the predominant way of handling asynchronous operations in JavaScript, especially in [Node.js](http://nodejs.org/).\nCPS functions expect one or more callbacks, or continuations, that continue the program flow after certain events.\nPromises moved in and out of the Node.js core,\nand eventually got specified with [Promises/A+](https://promisesaplus.com/),\nbut even after Node.js went back to CPS, the style used in Node.js was never specified.\n\nThe CPS specified in this document is named __CPS1__ because it was designed to match Node.js\nwhich widely uses a __single callback, error-first\u0026nbsp;CPS__.\n\nThe goal is to provide a common contract on CPS for developers and users of\nasynchronous code.\nCompliance is especially desired in meta-programming, where, for example,\npromises can be generated automatically from CPS1 functions, relying on a common signature.\n\n\n## 1. Preliminaries\n\n- 1.1. A __function__ is any JavaScript function.\n- 1.2. A __value__ is any JavaScript value, including functions.\n- 1.3. A value is __truthy__ if it is considered _true_ in JavaScript.\n- 1.4. A value is __falsy__ if it is not truthy.\n- 1.5. A __function call__ is the evaluation of a function by any means,\nincluding but not limited to `f(...)`, `call`, and `apply`.\n- 1.6. An __argument__ is an entry in the `arguments` list of a function call.\n- 1.7. In a function call, an argument is the __semantically last argument__\nif all following arguments are ignored,\ni.e. neither presence nor value have effect on the function call.\n\n\n## 2. CPS1 Operations\n\nA CPS1 operation is a hereby specified sequence of events and actions:\n\n- 2.1. A CPS1 operation must be started by a function call.\n- 2.2. The operation must reserve the _semantically last argument_ of the function call for a callback.\n- 2.3. If the callback is not a function,\nthe operation may use a default callback instead,\nor should throw an argument error indicating a missing callback immediately.\n- 2.4. The operation should not throw any exceptions besides argument errors in 2.3.\nInstead, exceptions should be caught and passed to the callback (see section E).\n- 2.5. The operation must eventually complete with one of the\n__Error__, __Success__, or __Uncaught Exception__ actions, defined by sections E, S, and U.\n- 2.6. In any case, the callback must be called at most once by the operation.\n- 2.7. The operation must not take any actions after completion.\n\n### E. Error\n\n- E1. The callback is called with an error as its first argument, immediately or at any time.\n- E2. The error argument must be truthy.\n- E3. The error argument should be an instance of a JavaScript error class, e.g. `Error`.\n- E4. Additional arguments may be passed to the callback. They are ignored by CPS1 callbacks.\n\n\n### S. Success\n\n- S1. The callback is called with a falsy first argument and result arguments, if any, immediately or at any time.\n- S2. The result(s) of the operation may be passed to the callback as additional arguments.\n- S3. If no results need to be passed, the callback may be called with an empty argument list.\n- S4. The number of result arguments must be obvious, and should be constant for equivalent contexts.\n- S5. In particular, if the last result argument is intended to be `undefined`, it must be explicitly passed to the callback.\n\n\n### U. Uncaught Exception\n\n- U1. During the operation, an exception is thrown and not caught by the operation,\nimmediately or at any time.\n- U2. Uncaught exceptions should be avoided (see 2.4).\n\n\n## 3. CPS1 callbacks\n\nA CPS1 callback is a function which\n\n- 3.1. must reserve the first argument for an error.\n- 3.2. must ignore any other arguments if the error argument is truthy.\n- 3.3. should not throw any exceptions.\n- 3.4. should return `undefined`.\n\n\n## 4. Notes\n\n- 4.1. Because functions may have multiple signatures and program flows,\nthis specification defines abstract CPS1 operations, _not_ functions.\nThis way, function calls may or may not execute a CPS1 operation, depending on arguments or context\n(that is, anything that may effect a function call, like the current program state and environment).\n- 4.2. Functions designed to be CPS1-compliant should always start a CPS1 operation when called.\nIf not, it must be obvious for which arguments and context a function call starts a CPS1 operation.\nThis may be achieved through documentation, comments, or function signatures.\n\n\n## 5. Examples\n\n```javascript\n// Example 5.1\n// setTimeout is not CPS1\n// Violates 2.2: Callback is not the (semantically) last argument.\n// function setTimeout( callback, t )\n\n// CPS1\nfunction setTimeoutCPS1( t, callback ) {\n\n\treturn setTimeout( callback, t );\n\n}\n\n// Example 5.2\n// func is not CPS1\n// Violates S5: Must explicitly pass undefined as a result.\nfunction func( one, two, callback ) {\n\n\tif ( !two ) callback( null, one );\n\telse callback( null, one, two );\n\n}\n\n// CPS1\nfunction funcCPS1( one, two, callback ) {\n\n\tif ( !two ) callback( null, one, undefined );\n\telse callback( null, one, two );\n\n}\n\n// Example 5.3\n// ready is not a CPS1 callback\n// Violates 3.2.: Must ignore data on error\nload( function ready( err, data ) {\n\n\tif ( err ) console.warn( err );\n\tconsole.log( data );\n\n} );\n\n// CPS1\nload( function readyCPS1( err, data ) {\n\n\tif ( err ) console.warn( err );\n\telse console.log( data );\n\n} );\n```\n\n\n## 6. Status and Contributing\n\nThis is a draft of an open standard that is hoped to help the community.\nPlease feel free to contribute by creating issues or pull requests,\nor by sending any feedback or ideas.\n\nContributors:\n\n- [Morris Brodersen](mailto:mb@morrisbrodersen.de)\n\n\n## 7. License\n\nThis work is dedicated to the public domain.\n\nhttps://creativecommons.org/publicdomain/zero/1.0/\n\n\n## 8. Acknowledgments\n\n- http://thenodeway.io/posts/understanding-error-first-callbacks/\n- https://promisesaplus.com/\n- https://github.com/creationix/safereturn\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorris%2Fcps1","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmorris%2Fcps1","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorris%2Fcps1/lists"}