1.0.0 • Published 10 months ago

@esfx/ref v1.0.0

Weekly downloads
1
License
Apache-2.0
Repository
github
Last release
10 months ago

@esfx/ref

The @esfx/ref package provides a low-level API for defining forward references.

NOTE: This implementation is an approximation of the Reference behavior from https://github.com/rbuckton/proposal-refs.

Overview

Installation

npm i @esfx/ref

Usage

NOTE: Examples adapted from https://github.com/rbuckton/proposal-refs#examples where applicable.

Take a reference to a variable

import { ref } from "@esfx/ref";

let x = 1;
const r = ref(() => x, _ => x = _);
print(r.value); // 1
r.value = 2;
print(x); // 2

Take a reference to a property

import { ref } from "@esfx/ref";

let o = { x: 1 };
const r = ref.at(o, "x");
print(r.value); // 1
r.value = 2;
print(o); // { x: 2 }

Take a reference to an element

import { ref } from "@esfx/ref";

let ar = [1];
const r = ref.at(ar, 0);
print(r.value); // 1
r.value = 2;
print(ar); // [2]

Reference passing

import { ref } from "@esfx/ref";

function update(ref_r) {
    ref_r.value = 2;
}

let x = 1;
update(ref(() => x, _ => x = _));
print(x); // 2

Referencing a local declaration creates a closure

import { ref } from "@esfx/ref";

function f() {
    let x = 1;
    return [ref(() => x, _ => x = _), () => print(x)];
}

const [r, p] = f();
p(); // 1
r.value = 2;
p(); // 2

More complex reference passing

import { ref } from "@esfx/ref";

function max(ref_first, ref_second, ref_third) {
    const ref_max = ref_first.value > ref_second.value ? ref_first : ref_second;
    return ref_max.value > ref_third.value ? ref_max : ref_third;
}

let x = 1, y = 2, z = 3;
const ref_x = ref(() => x, _ => x = _);
const ref_y = ref(() => y, _ => y = _);
const ref_z = ref(() => z, _ => z = _);
const ref_w = max(ref_x, ref_y, ref_z);
ref_w.value = 4;
print(x); // 1
print(y); // 2
print(z); // 4

Forward reference to a var

const ref_a = ref(() => a, _ => a = _);
ref_a.value = 1; // ok, no error as `a` is a var.
var a;

Forward reference to a block-scoped variable

const ref_a = ref(() => a, _ => a = _);
let a;
ref_a.value = 1; // ok, no error as `a` has been declared.

const ref_b = ref(() => b, _ => b = _);
ref_b.value = 1; // error as `b` has not yet been declared.
let b;

Forward reference to a member of a block-scoped variable

const ref_x = ref.at(b, "x"); // error, `b` has not yet been declared
let b = { x: 1 };

Forward references for decorators

import { ref } from "@esfx/ref";
import { metadata } from "@esfx/metadata";

const Type = ref_type => metadata("design:type", ref_type);

class Node {
    @Type(ref(() => Container))
    get parent() { /*...*/ }

    @Type(ref(() => Node)) 
    get nextSibling() { /*...*/ }
}

class Container extends Node {
    @Type(ref(() => Node))
    get firstChild() { /*...*/ }
}

Side effects

let count = 0;
let e = [0, 1, 2];
const ref_e = ref.at(e, count++); // `count++` is evaluated when Reference is taken.
print(ref_e.value); // 0
print(ref_e.value); // 0
print(count); // 1

API

You can read more about the API here.

1.0.0

2 years ago

1.0.0-dev.7

2 years ago

1.0.0-pre.42

2 years ago

1.0.0-dev.8

2 years ago

1.0.0-pre.41

2 years ago

1.0.0-dev.5

2 years ago

1.0.0-pre.44

2 years ago

1.0.0-dev.6

2 years ago

1.0.0-pre.43

2 years ago

1.0.0-dev.4

2 years ago

1.0.0-dev.0

2 years ago

1.0.0-pre.40

2 years ago

1.0.0-pre.31

2 years ago

1.0.0-pre.33

2 years ago

1.0.0-pre.35

2 years ago

1.0.0-pre.34

2 years ago

1.0.0-pre.37

2 years ago

1.0.0-pre.36

2 years ago

1.0.0-pre.39

2 years ago

1.0.0-pre.38

2 years ago

1.0.0-pre.23

3 years ago

1.0.0-pre.19

3 years ago

1.0.0-pre.17

3 years ago

1.0.0-pre.16

3 years ago

1.0.0-pre.15

5 years ago

1.0.0-pre.14

5 years ago

1.0.0-pre.12

5 years ago

1.0.0-pre.11

5 years ago

1.0.0-pre.9

5 years ago

1.0.0-pre.8

5 years ago

1.0.0-pre.6

5 years ago

1.0.0-pre.5

5 years ago

1.0.0-pre.4

5 years ago

1.0.0-pre.3

5 years ago

1.0.0-pre.2

5 years ago

1.0.0-pre.1

5 years ago