summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-03-04 15:53:52 +0100
committerJo-Philipp Wich <jo@mein.io>2021-03-08 19:18:52 +0100
commit5aceeaa6b9fbfcf80ac4c09474a956f9929bf863 (patch)
treec1f28908139cd117a8db8cf99e6ba27715686bb5
parent37d5e35437df393cd23e90f72579dea8d91fdea0 (diff)
lib: introduce new proto() ucode function
The proto() function allows getting and setting the prototype value of array or object values, which is useful to build object instances. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--README.md13
-rw-r--r--lib.c54
2 files changed, 67 insertions, 0 deletions
diff --git a/README.md b/README.md
index d09ff27..d6e6b25 100644
--- a/README.md
+++ b/README.md
@@ -1060,3 +1060,16 @@ Right now, any positive non-zero value will enable tracing while future
implementation might provide different different verbosity levels or treat
the level argument as bit mask to enable or disable individual debug
elements.
+
+#### 6.54. `proto(val[, proto])`
+
+Get or set the prototype of the array or object value `val`.
+
+When invoked without a second argument, the function returns the current
+prototype of the value in `val` or `null` if there is no prototype or if
+the given value is neither an object, nor an array.
+
+When invoked with a second prototype argument, the given `proto` value is
+set as prototype on the array or object in `val`.
+
+Throws an exception if the given prototype value is not an object.
diff --git a/lib.c b/lib.c
index c8b50b6..ba49927 100644
--- a/lib.c
+++ b/lib.c
@@ -2328,6 +2328,59 @@ uc_trace(uc_vm *vm, size_t nargs)
return xjs_new_int64(prev_level);
}
+static json_object *
+uc_proto(uc_vm *vm, size_t nargs)
+{
+ json_object *val = uc_get_arg(0);
+ json_object *proto = NULL;
+ uc_prototype *p, *ref;
+
+ if (nargs < 2) {
+ switch (uc_object_type(val)) {
+ case UC_OBJ_PROTOTYPE:
+ p = uc_object_as_prototype(val)->parent;
+
+ return p ? uc_value_get(p->header.jso) : NULL;
+
+ case UC_OBJ_RESSOURCE:
+ p = uc_ressource_prototype(val);
+
+ return p ? uc_value_get(p->header.jso) : NULL;
+
+ default:
+ return NULL;
+ }
+ }
+
+ proto = uc_get_arg(1);
+
+ switch (uc_object_type(proto)) {
+ case UC_OBJ_PROTOTYPE:
+ p = uc_object_as_prototype(proto);
+ break;
+
+ case UC_OBJ_RESSOURCE:
+ p = uc_ressource_prototype(proto);
+ break;
+
+ default:
+ switch (json_object_get_type(proto)) {
+ case json_type_object:
+ p = uc_protoref_new(proto, NULL);
+ break;
+
+ default:
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Passed value is neither a prototype, ressource or object");
+
+ return NULL;
+ }
+ }
+
+ ref = uc_protoref_new(val, p);
+
+ return ref ? uc_value_get(ref->header.jso) : NULL;
+}
+
static const uc_cfunction_list functions[] = {
{ "chr", uc_chr },
{ "delete", uc_delete },
@@ -2376,6 +2429,7 @@ static const uc_cfunction_list functions[] = {
{ "warn", uc_warn },
{ "system", uc_system },
{ "trace", uc_trace },
+ { "proto", uc_proto }
};