chain: a

type: user/post

unit: min

data:
@https://www.rfc-editor.org/rfc/rfc8785#name-ecmascript-sample-canonical
senf.in 2026-05-24T12:11:17Z 1min
There is a bug in the ECMAScript Sample Canonicalizer. Properties of objects
with their own §` toJSON§` implementation will not be sorted.

§<javascript
class MyClass {
    constructor(a,b) {
        this.a = a
        this.b = b
        this.c = "constant"
    }

    toJSON() {
        return {
            "3a": this.a,
            "2b": this.b,
            "1c": this.c
        }
    }
}

var x = new MyClass("a value","b value")
console.log(canonicalize(x))
//output:   {"3a":"a value","2b":"b value","1c":"constant"}
//expected: {"1c":"constant","2b":"b value","3a":"a value"}
§>

To fix it replace

§<javascript
/////////////////////////////////////////////////
// Primitive type or toJSON, use "JSON"        //
/////////////////////////////////////////////////
buffer += JSON.stringify(object);
§>

with

§<javascript
/////////////////////////////////////////////////
// Primitive type or toJSON, use "JSON"        //
/////////////////////////////////////////////////
buffer += object.toJSON != null
    ? canonicalize(object.toJSON())
    : JSON.stringify(object);
§>


data:
@https://peggyjs.org/documentation.html#grammar-syntax-and-semantics
senf.in 2026-05-24T12:12:17Z 1min
The parser generated by Peggy for a context-free grammar §$G§$ does not
necessarily recognize §$ L(G)§$ as one might expect. For example:
§<javascript
S = X "b" //does not match "aab"
X = "a" / "aa"
§>

There seems to be no backtracking for a sequence of expressions, i.e.
for a rule §` X = Y Z§` the parser consumes the first match for §` Y§`
and if the rest of the input does not match §` Z§` it fails to match
§` X§` instead of trying to see if there is an alternative match for
§` Y§`.

If the problematic rule is just an alternative of terminals as above
it suffices to sort them in descending order:
§<javascript
S = X "b" //matches "aab"
X = "aa" / "a"
§>

This ensures that no terminal in §` X§` is a prefix of any terminal
that comes after it thereby eliminating the need for backtracking.


data:
@https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams
senf.in 2026-05-24T12:13:17Z 1min
Here's an example of how to construct a §`javascript ReadableStream§` from an async generator function that yields byte arrays.

§<javascript
function asyncGeneratorToStream(gen) {
    return new ReadableStream({
        pull: async (controller) => {
            const res = await gen.next()
            if (res.done) controller.close()
            controller.enqueue(res.value)
        },
        type: "bytes"
    })
}

async function* exampleGenerator(arr) {
    const te = new TextEncoder()
    for(const el of arr) {
        yield te.encode(el)
    }
}

const rs = asyncGeneratorToStream(exampleGenerator(["line1","line2"]))
§>