From ed3b3516a763bc606a278a598aa9ae54a1fdc0e1 Mon Sep 17 00:00:00 2001 From: Leo-Paul Geneau Date: Fri, 11 Oct 2024 15:23:03 +0200 Subject: [PATCH] examples/point.c: add PointEnumerable class It is probably not trivial to guess that classes created like in the point example do not have enumerable properties (at least it was not for #315). Therefore PointEnumerable class describes how to implement such class. --- examples/point.c | 90 +++++++++++++++++++++++++++++++++++++++++- examples/test_point.js | 7 +++- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/examples/point.c b/examples/point.c index 0386230..586ef84 100644 --- a/examples/point.c +++ b/examples/point.c @@ -120,9 +120,77 @@ static const JSCFunctionListEntry js_point_proto_funcs[] = { JS_CFUNC_DEF("norm", 0, js_point_norm), }; +/*PointEnumerable Class*/ + +static JSClassID js_pointEnumerable_class_id; + +static void js_pointEnumerable_finalizer(JSRuntime *rt, JSValue val) +{ + return; +} + +static JSValue js_pointEnumerable_ctor(JSContext *ctx, + JSValueConst new_target, + int argc, JSValueConst *argv) +{ + JSValue obj = JS_UNDEFINED; + JSValue proto; + + /* using new_target to get the prototype is necessary when the + class is extended. */ + proto = JS_GetPropertyStr(ctx, new_target, "prototype"); + if (JS_IsException(proto)) + goto fail; + obj = JS_NewObjectProtoClass(ctx, proto, js_pointEnumerable_class_id); + JS_FreeValue(ctx, proto); + JS_DefinePropertyValueStr(ctx, obj, "x", argv[0], JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "y", argv[1], JS_PROP_C_W_E); + if (JS_IsException(obj)) + goto fail; + return obj; + fail: + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; +} + +static JSValue js_pointEnumerable_norm(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue val; + int ret, x, y; + + val = JS_GetPropertyStr(ctx, this_val, "x"); + if (JS_IsException(val)) + return JS_EXCEPTION; + ret = JS_ToInt32(ctx, &x, val); + JS_FreeValue(ctx, val); + if (ret) + return JS_EXCEPTION; + + val = JS_GetPropertyStr(ctx, this_val, "y"); + if (JS_IsException(val)) + return JS_EXCEPTION; + ret = JS_ToInt32(ctx, &y, val); + JS_FreeValue(ctx, val); + if (ret) + return JS_EXCEPTION; + + return JS_NewFloat64(ctx, sqrt((double)x * x + (double)y * y)); +} + +static JSClassDef js_pointEnumerable_class = { + "PointEnumerable", + .finalizer = js_pointEnumerable_finalizer, +}; + +static const JSCFunctionListEntry js_pointEnumerable_proto_funcs[] = { + JS_CFUNC_DEF("norm", 0, js_pointEnumerable_norm), +}; + static int js_point_init(JSContext *ctx, JSModuleDef *m) { - JSValue point_proto, point_class; + JSValue point_proto, point_class, + pointEnumerable_proto, pointEnumerable_class; /* create the Point class */ JS_NewClassID(&js_point_class_id); @@ -137,6 +205,25 @@ static int js_point_init(JSContext *ctx, JSModuleDef *m) JS_SetClassProto(ctx, js_point_class_id, point_proto); JS_SetModuleExport(ctx, m, "Point", point_class); + + /* create the PointEnumerable class */ + JS_NewClassID(&js_pointEnumerable_class_id); + JS_NewClass(JS_GetRuntime(ctx), js_pointEnumerable_class_id, + &js_pointEnumerable_class); + + pointEnumerable_proto = JS_NewObject(ctx); + JS_SetPropertyFunctionList(ctx, pointEnumerable_proto, + js_pointEnumerable_proto_funcs, + countof(js_pointEnumerable_proto_funcs)); + + pointEnumerable_class = JS_NewCFunction2(ctx, js_pointEnumerable_ctor, + "PointEnumerable", 2, + JS_CFUNC_constructor, 0); + /* set proto.constructor and ctor.prototype */ + JS_SetConstructor(ctx, pointEnumerable_class, pointEnumerable_proto); + JS_SetClassProto(ctx, js_pointEnumerable_class_id, pointEnumerable_proto); + + JS_SetModuleExport(ctx, m, "PointEnumerable", pointEnumerable_class); return 0; } @@ -147,5 +234,6 @@ JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) if (!m) return NULL; JS_AddModuleExport(ctx, m, "Point"); + JS_AddModuleExport(ctx, m, "PointEnumerable"); return m; } diff --git a/examples/test_point.js b/examples/test_point.js index 0659bc3..1eda213 100644 --- a/examples/test_point.js +++ b/examples/test_point.js @@ -1,5 +1,6 @@ /* example of JS module importing a C module */ import { Point } from "./point.so"; +import { PointEnumerable } from "./point.so"; function assert(b, str) { @@ -22,7 +23,7 @@ class ColorPoint extends Point { function main() { - var pt, pt2; + var pt, pt2, pt3; pt = new Point(2, 3); assert(pt.x === 2); @@ -35,6 +36,10 @@ function main() assert(pt2.x === 2); assert(pt2.color === 0xffffff); assert(pt2.get_color() === 0xffffff); + + pt3 = new PointEnumerable(2, 3); + assert(JSON.stringify(pt) === "{}"); + assert(JSON.stringify(pt3) === "{\"x\":2,\"y\":3}"); } main();