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

try-as

v1.0.1

Published

Exception handling for AssemblyScript

Readme

Installation

npm install try-as

Add the transform to your asc build and load it last.

asc assembly/index.ts --transform try-as

Or in asconfig.json:

{
  "options": {
    "transform": ["try-as"]
  }
}

If you use multiple transforms, keep try-as last.

Usage

try-as rewrites try/catch/finally, throw, abort, unreachable, and selected stdlib throw paths so they can be handled through a consistent Exception object.

import { Exception } from "try-as";

try {
  throw new Error("boom");
} catch (e) {
  const err = e as Exception;
  console.log(err.toString()); // Error: boom
} finally {
  console.log("done");
}

How It Works

try-as is a source-to-source transform. It analyzes the AssemblyScript call graph, rewrites exception-producing code paths into helper state updates, and lowers each try/catch/finally into explicit control-flow checks.

AssemblyScript source
  -> source linker finds try blocks, throwing calls, methods, imports, and re-exports
  -> exception-aware functions/methods are marked
  -> throw/abort/unreachable are rewritten to helper state writes
  -> try/catch/finally becomes explicit do/break + catch-state checks
  -> catch receives a rebuilt Exception object
throw / abort / unreachable
  -> __ErrorState.error / __AbortState.abort / __UnreachableState.unreachable
  -> __ExceptionState.Failures++
  -> generated break/return exits the current rewritten scope
  -> nearest transformed catch checks __ExceptionState.shouldCatch(mask)
  -> new __Exception(__ExceptionState.Type) reconstructs the caught value

Conceptually, code like this:

try {
  mightFail();
} catch (e) {
  trace((e as Exception).toString());
}

is lowered into code shaped like this:

do {
  __try_mightFail();
  if (__ExceptionState.Failures > 0) break;
} while (false);

if (__ExceptionState.shouldCatch(/* throw|abort|unreachable */ <i32>14)) {
  let e = new __Exception(__ExceptionState.Type);
  __ExceptionState.Failures--;
  trace((e as Exception).toString());
}

The exact generated AST is more verbose, but that is the core model: transformed calls write shared exception state, generated control flow propagates it, and catch reconstructs a typed Exception.

Exception API

import { Exception, ExceptionType } from "try-as";
  • Exception.type: ExceptionType
  • Exception.toString(): string
  • Exception.is<T>(): bool
  • Exception.as<T>(): T
  • Exception.clone(): Exception
  • Exception.rethrow(): never

Exception.as<T>() supports Error subclasses, other managed objects, and primitive payloads like i32, bool, and f64. Exception.rethrow() uses the runtime method body. If err is statically typed as Exception, throw err; is rewritten as err.rethrow();. Other identifier throws still use the generated __try_rethrow() / rethrow() / raw throw fallback chain when available.

ExceptionType:

  • None
  • Abort
  • Throw
  • Unreachable

Examples

Catch abort and throw

import { Exception, ExceptionType } from "try-as";

try {
  abort("fatal");
} catch (e) {
  const err = e as Exception;
  if (err.type == ExceptionType.Abort) {
    console.log(err.toString()); // abort: fatal
  }
}

Type-safe custom errors

import { Exception } from "try-as";

class MyError extends Error {
  constructor(message: string) {
    super(message);
  }
}

try {
  throw new MyError("typed");
} catch (e) {
  const err = e as Exception;
  if (err.is<MyError>()) {
    const typed = err.as<MyError>();
    console.log(typed.message);
  }
}

Throwing non-Error values

throw is not limited to Error.

import { Exception } from "try-as";

class PlainThing {
  constructor(public label: string) {}

  toString(): string {
    return this.label;
  }
}

try {
  throw new PlainThing("plain");
} catch (e) {
  const err = e as Exception;
  if (err.is<PlainThing>()) {
    const value = err.as<PlainThing>();
    console.log(value.label); // plain
  }
}

Rethrow behavior

import { Exception } from "try-as";

try {
  // risky code
} catch (e) {
  const err = e as Exception;
  if (!err.is<Error>()) {
    throw err; // alias of err.rethrow() when `err` is typed as Exception
  }
}

Selective catch kinds

Use a // @try-as: ... comment immediately above a try to control which transformed exception kinds that catch should handle.

Accepted values are throw, abort, and unreachable, comma-separated in that exact format.

import { Exception } from "try-as";

try {
  // @try-as: throw,abort
  try {
    abort("selected");
  } catch (e) {
    console.log((e as Exception).toString()); // abort: selected
  }
} catch (_) {
  // only runs if the inner catch does not select that exception kind
}

Catching stdlib exceptions

Stdlib exceptions such as missing map keys, empty array pops, out-of-range string access, and malformed URI decode errors are catchable.

import { Exception } from "try-as";

try {
  new Map<string, string>().get("missing");
} catch (e) {
  const err = e as Exception;
  console.log(err.toString()); // Error: Key does not exist
}

Limitations

  • The selective catch directive must be written exactly as // @try-as: throw,abort,unreachable with the chosen kinds, immediately above the try.
  • Runtime/internal trap paths are intentionally not rewritten.
  • Exceptions from these internals are not catchable by try-as:
    • ~lib/rt
    • ~lib/shared
    • ~lib/wasi_
    • ~lib/performance
  • This library handles transformed throw/abort flows, not low-level Wasm traps like out-of-bounds memory faults.
  • throw err; becomes err.rethrow(); when err is statically typed as Exception.
  • Other identifier throws still use the generated __try_rethrow() / rethrow() fallback path when available.

Debugging

  • DEBUG=1 enables transform diagnostics.
  • WRITE=pathA,pathB writes transformed source snapshots as *.tmp.ts.

Example:

DEBUG=1 WRITE=./assembly/test.ts,~lib/map asc assembly/test.ts --transform try-as

Transform Modes

  • TRY_AS_REWRITE_STDLIB=0 disables stdlib throw rewriting.
  • TRY_AS_IMPORT_SCOPE=user injects helper imports only into user sources (all by default).
  • TRY_AS_DIAGNOSTICS=1 prints the active mode configuration at transform time.

Example:

TRY_AS_REWRITE_STDLIB=0 TRY_AS_IMPORT_SCOPE=user TRY_AS_DIAGNOSTICS=1 asc assembly/index.ts --transform try-as

Contributing

npm run build:transform
npm test
npm run format

License

This project is distributed under the MIT license.

Contact

  • Issues: https://github.com/JairusSW/try-as/issues
  • Repository: https://github.com/JairusSW/try-as
  • Email: [email protected]
  • Website: https://jairus.dev