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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@json-serialization/function

v1.0.2

Published

@json-serialization/function provides a mechanism for function serialization and deserialization, which can implement cross-context function calls without using eval. @json-serialization/function 提供了一种函数序列化和反序列化的机制,能够在不使用 eval 的情况下实现函数的跨上下文调用。

Readme

@json-serialization/function

English | 简体中文

介绍

@json-serialization/function 提供了一种函数序列化和反序列化的机制,能够在不使用 eval 的情况下实现函数的跨上下文调用。

在序列化阶段,原始函数被转换为一个唯一的 UUID 标识,在反序列化阶段,这个标识被转换为一个代理函数。

当代理函数被调用时,调用参数和标识信息会通过指定的信道(实现 onmessagepostMessage 方法的对象)被发送回原始上下文,从而触发原始函数的回调执行。

起步

基本用法

以下示例代码创建了一个 animal 对象,该对象包含 name 属性以及 eatsleep 方法。

var animal = {
    name: 'cat',
    eat() {
        console.log('eat', ...arguments);
    },
    sleep() {
        console.log('sleep', ...arguments);
    },
};

提示: @json-serialization/function 可以配合 json-serialization 使用。这是一个可扩展的异步 JSON 序列化库,你可以通过阅读这篇文档对其有所了解。

假设你现在的场景是需要将定义在客户端的函数序列化,然后通过 WebSocket 传输到服务端。

客户端的代码可能如下:

import { stringify } from 'json-serialization';
import { createFunctionSerDes } from '@json-serialization/function';

var clientSocket = new WebSocket('ws://example.com');
var clientSerDes = createFunctionSerDes(clientSocket);
var jsonText = await stringify([animal, animal.eat, animal.sleep], [clientSerDes.serializer], 4);

@json-serialization/function 提供的 createFunctionSerDes 是一个工厂函数,入参是一个实现了 onmessagepostMessage 方法的信道对象,返回一对序列化器和反序列化器。

序列化后的 jsonText 可能为:

[
    {
        "name": "cat",
        "eat": "$fun:d6c95def-79d3-41c7-bfb2-afc797c300a0",
        "sleep": "$fun:fd5cff004-bb7d-43f3-bae7-ad64aac8be71"
    },
    "$fun:d6c95def-79d3-41c7-bfb2-afc797c300a0",
    "$fun:d5cff004-bb7d-43f3-bae7-ad64aac8be71"
]

每个函数都被分配了一个唯一的 UUID 标识符,并被序列化为带有 $fun: 前缀的字符串。

服务端反序列化的代码可能为:

import { parse } from 'json-serialization';
import { createFunctionSerDes } from '@json-serialization/function';

var serverSerDes = createFunctionSerDes(serverSocket);
var object = await parse(jsonText, [serverSerDes.deserializer]);

反序列化出的 object 为:

[
    {
        name: "cat",
        eat: proxyFunction<link to eat>,
        sleep: proxyFunction<link to sleep>,
    },
    proxyFunction<link to eat>,
    proxyFunction<link to sleep>
]

非函数标识的字段被正常还原,函数标识字段则被转换为了代理函数。

如果对代理函数进行调用,调用参数和内部记录的原始函数标识信息会通过 Socket 信道发送回客户端。

客户端的 eat 函数会以同样入参被调用,在客户端控制台打印 eat fish

// client console output: eat fish
object[0].eat('fish');

对于开发者来说,对反序列化出的代理函数的调用会被转发为对原始函数的调用,这一过程仿佛将函数在不同执行上下文之间进行了透明地序列化与反序列化。

注意事项

为了避免造成内存泄漏,建议在业务逻辑执行完成后,通过 FunctionSerDes 提供的 unref 方法来移除对函数的引用,之后对代理函数调用也将不会再被转发至原函数。

在服务端或客户端任意一方调用即可,析构指令会自动同步到另一方。

// unreferencing function on the client
clientSerDes.unref(animal.eat);

// or unreferencing function on the server
serverSerDes.unref(object[1]);

许可

MIT