details: https://github.com/nginx/njs/commit/5247aac9f4cc6f49ccf4a1dcfb30581ae2837dd4
branches: master
commit: 5247aac9f4cc6f49ccf4a1dcfb30581ae2837dd4
user: Dmitry Volyntsev <xeioex@nginx.com>
date: Thu, 7 Nov 2024 18:41:41 -0800
description:
Fixed resolving when Promise is inherited.
Previously, njs_promise_resolve() might return njs_object_t instead of
njs_promise_t. Later an instance of njs_object_t was put into a
NJS_PROMISE value. Whereas njs_promise_t is always expected to be inside
of a NJS_PROMISE value.
This closes #813 issue on Github.
---
src/njs_promise.c | 37 ++++++++++++++-----------------------
src/njs_promise.h | 4 ++--
src/njs_vmcode.c | 6 ++----
test/js/promise_s27.t.js | 34 ++++++++++++++++++++++++++++++++++
4 files changed, 52 insertions(+), 29 deletions(-)
diff --git a/src/njs_promise.c b/src/njs_promise.c
index 54da0a02..79b93a11 100644
--- a/src/njs_promise.c
+++ b/src/njs_promise.c
@@ -675,27 +675,19 @@ static njs_int_t
njs_promise_object_resolve(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused, njs_value_t *retval)
{
- njs_promise_t *promise;
-
if (njs_slow_path(!njs_is_object(njs_argument(args, 0)))) {
njs_type_error(vm, "this value is not an object");
return NJS_ERROR;
}
- promise = njs_promise_resolve(vm, njs_argument(args, 0),
- njs_arg(args, nargs, 1));
- if (njs_slow_path(promise == NULL)) {
- return NJS_ERROR;
- }
-
- njs_set_promise(retval, promise);
-
- return NJS_OK;
+ return njs_promise_resolve(vm, njs_argument(args, 0),
+ njs_arg(args, nargs, 1), retval);
}
-njs_promise_t *
-njs_promise_resolve(njs_vm_t *vm, njs_value_t *constructor, njs_value_t *x)
+njs_int_t
+njs_promise_resolve(njs_vm_t *vm, njs_value_t *constructor, njs_value_t *x,
+ njs_value_t *retval)
{
njs_int_t ret;
njs_value_t value;
@@ -707,26 +699,28 @@ njs_promise_resolve(njs_vm_t *vm, njs_value_t *constructor, njs_value_t *x)
ret = njs_value_property(vm, x, njs_value_arg(&string_constructor),
&value);
if (njs_slow_path(ret == NJS_ERROR)) {
- return NULL;
+ return NJS_ERROR;
}
if (njs_values_same(&value, constructor)) {
- return njs_promise(x);
+ njs_value_assign(retval, x);
+ return NJS_OK;
}
}
capability = njs_promise_new_capability(vm, constructor);
if (njs_slow_path(capability == NULL)) {
- return NULL;
+ return NJS_ERROR;
}
ret = njs_function_call(vm, njs_function(&capability->resolve),
&njs_value_undefined, x, 1, &value);
if (njs_slow_path(ret != NJS_OK)) {
- return NULL;
+ return ret;
}
- return njs_promise(&capability->promise);
+ njs_value_assign(retval, &capability->promise);
+ return NJS_OK;
}
@@ -1017,7 +1011,6 @@ njs_promise_then_finally_function(njs_vm_t *vm, njs_value_t *args,
{
njs_int_t ret;
njs_value_t value, argument;
- njs_promise_t *promise;
njs_function_t *function;
njs_native_frame_t *frame;
njs_promise_context_t *context;
@@ -1031,13 +1024,11 @@ njs_promise_then_finally_function(njs_vm_t *vm, njs_value_t *args,
return ret;
}
- promise = njs_promise_resolve(vm, &context->constructor, &value);
- if (njs_slow_path(promise == NULL)) {
+ ret = njs_promise_resolve(vm, &context->constructor, &value, &value);
+ if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
- njs_set_promise(&value, promise);
-
function = njs_promise_create_function(vm, sizeof(njs_value_t));
if (njs_slow_path(function == NULL)) {
return NJS_ERROR;
diff --git a/src/njs_promise.h b/src/njs_promise.h
index abf8e1a6..53d179a9 100644
--- a/src/njs_promise.h
+++ b/src/njs_promise.h
@@ -36,8 +36,8 @@ njs_function_t *njs_promise_create_function(njs_vm_t *vm, size_t context_size);
njs_int_t njs_promise_perform_then(njs_vm_t *vm, njs_value_t *value,
njs_value_t *fulfilled, njs_value_t *rejected,
njs_promise_capability_t *capability, njs_value_t *retval);
-njs_promise_t *njs_promise_resolve(njs_vm_t *vm, njs_value_t *constructor,
- njs_value_t *x);
+njs_int_t njs_promise_resolve(njs_vm_t *vm, njs_value_t *constructor,
+ njs_value_t *x, njs_value_t *retval);
extern const njs_object_type_init_t njs_promise_type_init;
diff --git a/src/njs_vmcode.c b/src/njs_vmcode.c
index a95171a3..838e2821 100644
--- a/src/njs_vmcode.c
+++ b/src/njs_vmcode.c
@@ -2637,7 +2637,6 @@ njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await,
njs_int_t ret;
njs_frame_t *frame;
njs_value_t ctor, val, on_fulfilled, on_rejected, *value, retval;
- njs_promise_t *promise;
njs_function_t *fulfilled, *rejected;
njs_native_frame_t *active;
@@ -2651,8 +2650,8 @@ njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await,
njs_set_function(&ctor, &njs_vm_ctor(vm, NJS_OBJ_TYPE_PROMISE));
- promise = njs_promise_resolve(vm, &ctor, value);
- if (njs_slow_path(promise == NULL)) {
+ ret = njs_promise_resolve(vm, &ctor, value, &val);
+ if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
@@ -2710,7 +2709,6 @@ njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await,
rejected->args_count = 1;
rejected->u.native = njs_await_rejected;
- njs_set_promise(&val, promise);
njs_set_function(&on_fulfilled, fulfilled);
njs_set_function(&on_rejected, rejected);
diff --git a/test/js/promise_s27.t.js b/test/js/promise_s27.t.js
new file mode 100644
index 00000000..7a5ac583
--- /dev/null
+++ b/test/js/promise_s27.t.js
@@ -0,0 +1,34 @@
+/*---
+includes: []
+flags: [async]
+---*/
+
+var inherits = (child, parent) => {
+ child.prototype = Object.create(parent.prototype, {
+ constructor: {
+ value: child,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ Object.setPrototypeOf(child, parent);
+};
+
+function BoxedPromise(executor) {
+ var context, args;
+ new Promise(wrappedExecutor);
+ executor.apply(context, args);
+
+ function wrappedExecutor(resolve, reject) {
+ context = this;
+ args = [v => resolve(v),v => reject(v)];
+ }
+}
+
+inherits(BoxedPromise, Promise);
+
+Promise.resolve()
+.then(() => BoxedPromise.resolve())
+.catch(e => assert.sameValue(e.constructor, TypeError))
+.then($DONE, $DONE);
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel