]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_bi_error.c
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / third_party / prometheus-cpp / 3rdparty / civetweb / src / third_party / duktape-1.5.2 / src-separate / duk_bi_error.c
diff --git a/ceph/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_bi_error.c b/ceph/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_bi_error.c
new file mode 100644 (file)
index 0000000..b575fff
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ *  Error built-ins
+ */
+
+#include "duk_internal.h"
+
+DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx) {
+       /* Behavior for constructor and non-constructor call is
+        * the same except for augmenting the created error.  When
+        * called as a constructor, the caller (duk_new()) will handle
+        * augmentation; when called as normal function, we need to do
+        * it here.
+        */
+
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_small_int_t bidx_prototype = duk_get_current_magic(ctx);
+
+       /* same for both error and each subclass like TypeError */
+       duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
+                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
+
+       DUK_UNREF(thr);
+
+       duk_push_object_helper(ctx, flags_and_class, bidx_prototype);
+
+       /* If message is undefined, the own property 'message' is not set at
+        * all to save property space.  An empty message is inherited anyway.
+        */
+       if (!duk_is_undefined(ctx, 0)) {
+               duk_to_string(ctx, 0);
+               duk_dup(ctx, 0);  /* [ message error message ] */
+               duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
+       }
+
+       /* Augment the error if called as a normal function.  __FILE__ and __LINE__
+        * are not desirable in this case.
+        */
+
+#ifdef DUK_USE_AUGMENT_ERROR_CREATE
+       if (!duk_is_constructor_call(ctx)) {
+               duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
+       }
+#endif
+
+       return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
+       /* XXX: optimize with more direct internal access */
+
+       duk_push_this(ctx);
+       (void) duk_require_hobject_or_lfunc_coerce(ctx, -1);
+
+       /* [ ... this ] */
+
+       duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME);
+       if (duk_is_undefined(ctx, -1)) {
+               duk_pop(ctx);
+               duk_push_string(ctx, "Error");
+       } else {
+               duk_to_string(ctx, -1);
+       }
+
+       /* [ ... this name ] */
+
+       /* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
+        * accident or are they actually needed?  The first ToString()
+        * could conceivably return 'undefined'.
+        */
+       duk_get_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
+       if (duk_is_undefined(ctx, -1)) {
+               duk_pop(ctx);
+               duk_push_string(ctx, "");
+       } else {
+               duk_to_string(ctx, -1);
+       }
+
+       /* [ ... this name message ] */
+
+       if (duk_get_length(ctx, -2) == 0) {
+               /* name is empty -> return message */
+               return 1;
+       }
+       if (duk_get_length(ctx, -1) == 0) {
+               /* message is empty -> return name */
+               duk_pop(ctx);
+               return 1;
+       }
+       duk_push_string(ctx, ": ");
+       duk_insert(ctx, -2);  /* ... name ': ' message */
+       duk_concat(ctx, 3);
+
+       return 1;
+}
+
+#if defined(DUK_USE_TRACEBACKS)
+
+/*
+ *  Traceback handling
+ *
+ *  The unified helper decodes the traceback and produces various requested
+ *  outputs.  It should be optimized for size, and may leave garbage on stack,
+ *  only the topmost return value matters.  For instance, traceback separator
+ *  and decoded strings are pushed even when looking for filename only.
+ *
+ *  NOTE: although _Tracedata is an internal property, user code can currently
+ *  write to the array (or replace it with something other than an array).
+ *  The code below must tolerate arbitrary _Tracedata.  It can throw errors
+ *  etc, but cannot cause a segfault or memory unsafe behavior.
+ */
+
+/* constants arbitrary, chosen for small loads */
+#define DUK__OUTPUT_TYPE_TRACEBACK   (-1)
+#define DUK__OUTPUT_TYPE_FILENAME    0
+#define DUK__OUTPUT_TYPE_LINENUMBER  1
+
+DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_context *ctx, duk_small_int_t output_type) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_idx_t idx_td;
+       duk_small_int_t i;  /* traceback depth fits into 16 bits */
+       duk_small_int_t t;  /* stack type fits into 16 bits */
+       duk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */
+       const char *str_tailcall = " tailcall";
+       const char *str_strict = " strict";
+       const char *str_construct = " construct";
+       const char *str_prevyield = " preventsyield";
+       const char *str_directeval = " directeval";
+       const char *str_empty = "";
+
+       DUK_ASSERT_TOP(ctx, 0);  /* fixed arg count */
+       DUK_UNREF(thr);
+
+       duk_push_this(ctx);
+       duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TRACEDATA);
+       idx_td = duk_get_top_index(ctx);
+
+       duk_push_hstring_stridx(ctx, DUK_STRIDX_NEWLINE_4SPACE);
+       duk_push_this(ctx);
+
+       /* [ ... this tracedata sep this ] */
+
+       /* XXX: skip null filename? */
+
+       if (duk_check_type(ctx, idx_td, DUK_TYPE_OBJECT)) {
+               /* Current tracedata contains 2 entries per callstack entry. */
+               for (i = 0; ; i += 2) {
+                       duk_int_t pc;
+                       duk_int_t line;
+                       duk_int_t flags;
+                       duk_double_t d;
+                       const char *funcname;
+                       const char *filename;
+                       duk_hobject *h_func;
+                       duk_hstring *h_name;
+
+                       duk_require_stack(ctx, 5);
+                       duk_get_prop_index(ctx, idx_td, i);
+                       duk_get_prop_index(ctx, idx_td, i + 1);
+                       d = duk_to_number(ctx, -1);
+                       pc = (duk_int_t) DUK_FMOD(d, DUK_DOUBLE_2TO32);
+                       flags = (duk_int_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32);
+                       t = (duk_small_int_t) duk_get_type(ctx, -2);
+
+                       if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
+                               /*
+                                *  Ecmascript/native function call or lightfunc call
+                                */
+
+                               count_func++;
+
+                               /* [ ... v1(func) v2(pc+flags) ] */
+
+                               h_func = duk_get_hobject(ctx, -2);  /* NULL for lightfunc */
+
+                               duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);
+                               duk_get_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME);
+
+#if defined(DUK_USE_PC2LINE)
+                               line = duk_hobject_pc2line_query(ctx, -4, (duk_uint_fast32_t) pc);
+#else
+                               line = 0;
+#endif
+
+                               /* [ ... v1 v2 name filename ] */
+
+                               /* When looking for .fileName/.lineNumber, blame first
+                                * function which has a .fileName.
+                                */
+                               if (duk_is_string(ctx, -1)) {
+                                       if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
+                                               return 1;
+                                       } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
+                                               duk_push_int(ctx, line);
+                                               return 1;
+                                       }
+                               }
+
+                               /* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
+                               /* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
+                               h_name = duk_get_hstring(ctx, -2);  /* may be NULL */
+                               funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
+                                          "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
+                               filename = duk_get_string(ctx, -1);
+                               filename = filename ? filename : "";
+                               DUK_ASSERT(funcname != NULL);
+                               DUK_ASSERT(filename != NULL);
+
+                               if (h_func == NULL) {
+                                       duk_push_sprintf(ctx, "at %s light%s%s%s%s%s",
+                                                        (const char *) funcname,
+                                                        (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
+                               } else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h_func)) {
+                                       duk_push_sprintf(ctx, "at %s (%s) native%s%s%s%s%s",
+                                                        (const char *) funcname,
+                                                        (const char *) filename,
+                                                        (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
+                               } else {
+                                       duk_push_sprintf(ctx, "at %s (%s:%ld)%s%s%s%s%s",
+                                                        (const char *) funcname,
+                                                        (const char *) filename,
+                                                        (long) line,
+                                                        (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
+                                                        (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
+                               }
+                               duk_replace(ctx, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
+                               duk_pop_n(ctx, 3);      /* -> [ ... str ] */
+                       } else if (t == DUK_TYPE_STRING) {
+                               /*
+                                *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.
+                                *  Sometimes __FILE__ / __LINE__ is reported as the source for
+                                *  the error (fileName, lineNumber), sometimes not.
+                                */
+
+                               /* [ ... v1(filename) v2(line+flags) ] */
+
+                               /* When looking for .fileName/.lineNumber, blame compilation
+                                * or C call site unless flagged not to do so.
+                                */
+                               if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
+                                       if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
+                                               duk_pop(ctx);
+                                               return 1;
+                                       } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
+                                               duk_push_int(ctx, pc);
+                                               return 1;
+                                       }
+                               }
+
+                               duk_push_sprintf(ctx, "at [anon] (%s:%ld) internal",
+                                                (const char *) duk_get_string(ctx, -2), (long) pc);
+                               duk_replace(ctx, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */
+                               duk_pop(ctx);          /* -> [ ... str ] */
+                       } else {
+                               /* unknown, ignore */
+                               duk_pop_2(ctx);
+                               break;
+                       }
+               }
+
+               if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
+                       /* Possibly truncated; there is no explicit truncation
+                        * marker so this is the best we can do.
+                        */
+
+                       duk_push_hstring_stridx(ctx, DUK_STRIDX_BRACKETED_ELLIPSIS);
+               }
+       }
+
+       /* [ ... this tracedata sep this str1 ... strN ] */
+
+       if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
+               return 0;
+       } else {
+               /* The 'this' after 'sep' will get ToString() coerced by
+                * duk_join() automatically.  We don't want to do that
+                * coercion when providing .fileName or .lineNumber (GH-254).
+                */
+               duk_join(ctx, duk_get_top(ctx) - (idx_td + 2) /*count, not including sep*/);
+               return 1;
+       }
+}
+
+/* XXX: Output type could be encoded into native function 'magic' value to
+ * save space.  For setters the stridx could be encoded into 'magic'.
+ */
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
+       return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_TRACEBACK);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
+       return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_FILENAME);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
+       return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_LINENUMBER);
+}
+
+#undef DUK__OUTPUT_TYPE_TRACEBACK
+#undef DUK__OUTPUT_TYPE_FILENAME
+#undef DUK__OUTPUT_TYPE_LINENUMBER
+
+#else  /* DUK_USE_TRACEBACKS */
+
+/*
+ *  Traceback handling when tracebacks disabled.
+ *
+ *  The fileName / lineNumber stubs are now necessary because built-in
+ *  data will include the accessor properties in Error.prototype.  If those
+ *  are removed for builds without tracebacks, these can also be removed.
+ *  'stack' should still be present and produce a ToString() equivalent:
+ *  this is useful for user code which prints a stacktrace and expects to
+ *  see something useful.  A normal stacktrace also begins with a ToString()
+ *  of the error so this makes sense.
+ */
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
+       /* XXX: remove this native function and map 'stack' accessor
+        * to the toString() implementation directly.
+        */
+       return duk_bi_error_prototype_to_string(ctx);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
+       DUK_UNREF(ctx);
+       return 0;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
+       DUK_UNREF(ctx);
+       return 0;
+}
+
+#endif  /* DUK_USE_TRACEBACKS */
+
+DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_context *ctx, duk_small_uint_t stridx_key) {
+       /* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
+        * user code called Object.defineProperty() to create an overriding
+        * own property.  This allows user code to overwrite .fileName etc
+        * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
+        * See https://github.com/svaarala/duktape/issues/387.
+        */
+
+       DUK_ASSERT_TOP(ctx, 1);  /* fixed arg count: value */
+
+       duk_push_this(ctx);
+       duk_push_hstring_stridx(ctx, (duk_small_int_t) stridx_key);
+       duk_dup(ctx, 0);
+
+       /* [ ... obj key value ] */
+
+       DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
+                          duk_get_tval(ctx, -3), duk_get_tval(ctx, -2), duk_get_tval(ctx, -1)));
+
+       duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |
+                             DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
+                             DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
+                             DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
+       return 0;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx) {
+       return duk__error_setter_helper(ctx, DUK_STRIDX_STACK);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx) {
+       return duk__error_setter_helper(ctx, DUK_STRIDX_FILE_NAME);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx) {
+       return duk__error_setter_helper(ctx, DUK_STRIDX_LINE_NUMBER);
+}