From 8488c629eba79f4a997e69f2758107f800d74d3c Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 11 Apr 2024 17:04:45 +0900 Subject: [PATCH] lottie: integrate JerryScript engine for expressions introduced the JerryScript engine to interpret Lottie expressions, enhancing the capability to support runtime programmable animation logic within Lottie expressions spec. This feature, based on js scripting, represents the most complicated addition to the Lottie spec so far. ThorVG probably could includes an option to toggle this feature at build time, allowing for customizable user configurations according to specific requirements. removed unused features for the optimal size: - DEBUGGER - MEM_STATS - SNAPSHOT - BUILTIN_JSON - BUILTIN_PROXY - BUILTIN_REFLECT - BUILTIN_ATOMICS - PROMISE_CALLBACK - MODULE_SYSTEM - SYSTEM_PORT This is an experimental version. Please manually enable the 'lottie-expressions' in meson.build when you wish to use it. See: https://jerryscript.net/ --- meson.build | 5 + .../jerry-core/api/jerryscript.cpp | 6847 +++++++++++++++++ .../jerryscript/jerry-core/api/meson.build | 8 + .../jerry-core/ecma/base/ecma-alloc.cpp | 232 + .../jerry-core/ecma/base/ecma-alloc.h | 129 + .../ecma/base/ecma-error-messages.inc.h | 743 ++ .../ecma/base/ecma-error-messages.ini | 331 + .../jerry-core/ecma/base/ecma-errors.cpp | 71 + .../jerry-core/ecma/base/ecma-errors.h | 39 + .../ecma/base/ecma-extended-info.cpp | 144 + .../jerry-core/ecma/base/ecma-extended-info.h | 54 + .../jerry-core/ecma/base/ecma-gc.cpp | 2344 ++++++ .../jerry-core/ecma/base/ecma-gc.h | 54 + .../jerry-core/ecma/base/ecma-globals.h | 2271 ++++++ .../ecma/base/ecma-helpers-collection.cpp | 446 ++ .../ecma/base/ecma-helpers-conversion.cpp | 943 +++ .../ecma/base/ecma-helpers-errol.cpp | 245 + .../base/ecma-helpers-external-pointers.cpp | 334 + .../ecma/base/ecma-helpers-number.cpp | 677 ++ .../ecma/base/ecma-helpers-number.h | 245 + .../ecma/base/ecma-helpers-string.cpp | 2780 +++++++ .../ecma/base/ecma-helpers-value.cpp | 1257 +++ .../jerry-core/ecma/base/ecma-helpers.cpp | 1762 +++++ .../jerry-core/ecma/base/ecma-helpers.h | 524 ++ .../ecma/base/ecma-init-finalize.cpp | 106 + .../jerry-core/ecma/base/ecma-init-finalize.h | 34 + .../jerry-core/ecma/base/ecma-lcache.cpp | 221 + .../jerry-core/ecma/base/ecma-lcache.h | 40 + .../jerry-core/ecma/base/ecma-line-info.cpp | 271 + .../jerry-core/ecma/base/ecma-line-info.h | 114 + .../ecma/base/ecma-literal-storage.cpp | 741 ++ .../ecma/base/ecma-literal-storage.h | 72 + .../jerry-core/ecma/base/ecma-module.cpp | 1444 ++++ .../jerry-core/ecma/base/ecma-module.h | 132 + .../ecma/base/ecma-property-hashmap.cpp | 532 ++ .../ecma/base/ecma-property-hashmap.h | 89 + .../jerry-core/ecma/base/meson.build | 39 + .../ecma-builtin-aggregateerror-prototype.cpp | 33 + ...cma-builtin-aggregateerror-prototype.inc.h | 34 + .../ecma-builtin-aggregateerror.cpp | 109 + .../ecma-builtin-aggregateerror.inc.h | 35 + .../ecma-builtin-array-iterator-prototype.cpp | 224 + ...cma-builtin-array-iterator-prototype.inc.h | 28 + ...ma-builtin-array-prototype-unscopables.cpp | 24 + ...-builtin-array-prototype-unscopables.inc.h | 44 + .../ecma-builtin-array-prototype.cpp | 2973 +++++++ .../ecma-builtin-array-prototype.inc.h | 85 + .../builtin-objects/ecma-builtin-array.cpp | 569 ++ .../builtin-objects/ecma-builtin-array.inc.h | 47 + .../ecma-builtin-arraybuffer-prototype.cpp | 116 + .../ecma-builtin-arraybuffer-prototype.inc.h | 43 + .../ecma-builtin-arraybuffer.cpp | 114 + .../ecma-builtin-arraybuffer.inc.h | 47 + ...tin-async-from-sync-iterator-prototype.cpp | 355 + ...n-async-from-sync-iterator-prototype.inc.h | 28 + .../ecma-builtin-async-function-prototype.cpp | 39 + ...cma-builtin-async-function-prototype.inc.h | 28 + .../ecma-builtin-async-function.cpp | 68 + .../ecma-builtin-async-function.inc.h | 34 + .../ecma-builtin-async-generator-function.cpp | 70 + ...cma-builtin-async-generator-function.inc.h | 31 + ...ecma-builtin-async-generator-prototype.cpp | 147 + ...ma-builtin-async-generator-prototype.inc.h | 37 + .../ecma-builtin-async-generator.cpp | 39 + .../ecma-builtin-async-generator.inc.h | 33 + .../ecma-builtin-async-iterator-prototype.cpp | 103 + ...cma-builtin-async-iterator-prototype.inc.h | 26 + .../builtin-objects/ecma-builtin-atomics.cpp | 260 + .../ecma-builtin-atomics.inc.h | 44 + .../ecma-builtin-bigint-prototype.cpp | 186 + .../ecma-builtin-bigint-prototype.inc.h | 41 + .../builtin-objects/ecma-builtin-bigint.cpp | 80 + .../builtin-objects/ecma-builtin-bigint.inc.h | 41 + .../ecma-builtin-boolean-prototype.cpp | 140 + .../ecma-builtin-boolean-prototype.inc.h | 37 + .../builtin-objects/ecma-builtin-boolean.cpp | 99 + .../ecma-builtin-boolean.inc.h | 38 + .../ecma-builtin-dataview-prototype.cpp | 238 + .../ecma-builtin-dataview-prototype.inc.h | 77 + .../builtin-objects/ecma-builtin-dataview.cpp | 71 + .../ecma-builtin-dataview.inc.h | 41 + .../ecma-builtin-date-prototype.cpp | 722 ++ .../ecma-builtin-date-prototype.inc.h | 83 + .../builtin-objects/ecma-builtin-date.cpp | 874 +++ .../builtin-objects/ecma-builtin-date.inc.h | 37 + .../ecma-builtin-error-prototype.cpp | 180 + .../ecma-builtin-error-prototype.inc.h | 38 + .../builtin-objects/ecma-builtin-error.cpp | 93 + .../builtin-objects/ecma-builtin-error.inc.h | 35 + .../ecma-builtin-evalerror-prototype.cpp | 37 + .../ecma-builtin-evalerror-prototype.inc.h | 38 + .../ecma-builtin-evalerror.cpp | 97 + .../ecma-builtin-evalerror.inc.h | 39 + .../ecma-builtin-function-prototype.cpp | 550 ++ .../ecma-builtin-function-prototype.h | 24 + .../ecma-builtin-function-prototype.inc.h | 55 + .../builtin-objects/ecma-builtin-function.cpp | 77 + .../ecma-builtin-function.inc.h | 34 + .../ecma-builtin-generator-function.cpp | 68 + .../ecma-builtin-generator-function.inc.h | 31 + .../ecma-builtin-generator-prototype.cpp | 258 + .../ecma-builtin-generator-prototype.inc.h | 37 + .../ecma-builtin-generator.cpp | 39 + .../ecma-builtin-generator.inc.h | 31 + .../builtin-objects/ecma-builtin-global.cpp | 700 ++ .../builtin-objects/ecma-builtin-global.inc.h | 217 + .../builtin-objects/ecma-builtin-handlers.cpp | 60 + .../builtin-objects/ecma-builtin-handlers.h | 51 + .../ecma-builtin-handlers.inc.h | 27 + .../ecma-builtin-helpers-date.cpp | 766 ++ .../ecma-builtin-helpers-error.cpp | 70 + .../ecma-builtin-helpers-macro-defines.inc.h | 62 + .../ecma-builtin-helpers-macro-undefs.inc.h | 27 + .../ecma-builtin-helpers-sort.cpp | 156 + .../builtin-objects/ecma-builtin-helpers.cpp | 1039 +++ .../builtin-objects/ecma-builtin-helpers.h | 232 + ...a-builtin-internal-routines-template.inc.h | 241 + .../ecma-builtin-intrinsic.cpp | 305 + .../ecma-builtin-intrinsic.inc.h | 35 + .../ecma-builtin-iterator-prototype.cpp | 102 + .../ecma-builtin-iterator-prototype.inc.h | 26 + .../ecma-builtin-map-iterator-prototype.cpp | 106 + .../ecma-builtin-map-iterator-prototype.inc.h | 32 + .../ecma-builtin-map-prototype.cpp | 66 + .../ecma-builtin-map-prototype.inc.h | 55 + .../ecma/builtin-objects/ecma-builtin-map.cpp | 86 + .../builtin-objects/ecma-builtin-map.inc.h | 44 + .../builtin-objects/ecma-builtin-math.cpp | 561 ++ .../builtin-objects/ecma-builtin-math.inc.h | 94 + .../ecma-builtin-number-prototype.cpp | 673 ++ .../ecma-builtin-number-prototype.inc.h | 41 + .../builtin-objects/ecma-builtin-number.cpp | 246 + .../builtin-objects/ecma-builtin-number.inc.h | 72 + .../ecma-builtin-object-prototype.cpp | 513 ++ .../ecma-builtin-object-prototype.inc.h | 49 + .../builtin-objects/ecma-builtin-object.cpp | 1555 ++++ .../builtin-objects/ecma-builtin-object.h | 34 + .../builtin-objects/ecma-builtin-object.inc.h | 59 + .../ecma-builtin-promise-prototype.cpp | 93 + .../ecma-builtin-promise-prototype.inc.h | 30 + .../builtin-objects/ecma-builtin-promise.cpp | 527 ++ .../ecma-builtin-promise.inc.h | 46 + .../builtin-objects/ecma-builtin-proxy.cpp | 160 + .../builtin-objects/ecma-builtin-proxy.inc.h | 38 + .../ecma-builtin-rangeerror-prototype.cpp | 37 + .../ecma-builtin-rangeerror-prototype.inc.h | 38 + .../ecma-builtin-rangeerror.cpp | 97 + .../ecma-builtin-rangeerror.inc.h | 38 + .../ecma-builtin-referenceerror-prototype.cpp | 37 + ...cma-builtin-referenceerror-prototype.inc.h | 38 + .../ecma-builtin-referenceerror.cpp | 97 + .../ecma-builtin-referenceerror.inc.h | 38 + .../builtin-objects/ecma-builtin-reflect.cpp | 344 + .../ecma-builtin-reflect.inc.h | 38 + .../ecma-builtin-regexp-prototype.cpp | 659 ++ .../ecma-builtin-regexp-prototype.inc.h | 64 + ...iltin-regexp-string-iterator-prototype.cpp | 184 + ...tin-regexp-string-iterator-prototype.inc.h | 30 + .../builtin-objects/ecma-builtin-regexp.cpp | 217 + .../builtin-objects/ecma-builtin-regexp.inc.h | 35 + .../ecma-builtin-set-iterator-prototype.cpp | 106 + .../ecma-builtin-set-iterator-prototype.inc.h | 32 + .../ecma-builtin-set-prototype.cpp | 65 + .../ecma-builtin-set-prototype.inc.h | 55 + .../ecma/builtin-objects/ecma-builtin-set.cpp | 86 + .../builtin-objects/ecma-builtin-set.inc.h | 44 + ...a-builtin-shared-arraybuffer-prototype.cpp | 113 + ...builtin-shared-arraybuffer-prototype.inc.h | 43 + .../ecma-builtin-shared-arraybuffer.cpp | 96 + .../ecma-builtin-shared-arraybuffer.inc.h | 46 + ...ecma-builtin-string-iterator-prototype.cpp | 205 + ...ma-builtin-string-iterator-prototype.inc.h | 28 + .../ecma-builtin-string-prototype.cpp | 1560 ++++ .../ecma-builtin-string-prototype.inc.h | 85 + .../builtin-objects/ecma-builtin-string.cpp | 430 ++ .../builtin-objects/ecma-builtin-string.inc.h | 44 + .../ecma-builtin-symbol-prototype.cpp | 111 + .../ecma-builtin-symbol-prototype.inc.h | 37 + .../builtin-objects/ecma-builtin-symbol.cpp | 253 + .../builtin-objects/ecma-builtin-symbol.inc.h | 80 + .../ecma-builtin-syntaxerror-prototype.cpp | 37 + .../ecma-builtin-syntaxerror-prototype.inc.h | 38 + .../ecma-builtin-syntaxerror.cpp | 97 + .../ecma-builtin-syntaxerror.inc.h | 38 + .../ecma-builtin-type-error-thrower.cpp | 82 + .../ecma-builtin-type-error-thrower.inc.h | 31 + .../ecma-builtin-typeerror-prototype.cpp | 37 + .../ecma-builtin-typeerror-prototype.inc.h | 38 + .../ecma-builtin-typeerror.cpp | 97 + .../ecma-builtin-typeerror.inc.h | 38 + .../ecma-builtin-urierror-prototype.cpp | 37 + .../ecma-builtin-urierror-prototype.inc.h | 38 + .../builtin-objects/ecma-builtin-urierror.cpp | 97 + .../ecma-builtin-urierror.inc.h | 38 + .../ecma-builtin-weakmap-prototype.cpp | 65 + .../ecma-builtin-weakmap-prototype.inc.h | 42 + .../builtin-objects/ecma-builtin-weakmap.cpp | 74 + .../ecma-builtin-weakmap.inc.h | 41 + .../ecma-builtin-weakref-prototype.cpp | 114 + .../ecma-builtin-weakref-prototype.inc.h | 37 + .../builtin-objects/ecma-builtin-weakref.cpp | 96 + .../ecma-builtin-weakref.inc.h | 38 + .../ecma-builtin-weakset-prototype.cpp | 67 + .../ecma-builtin-weakset-prototype.inc.h | 41 + .../builtin-objects/ecma-builtin-weakset.cpp | 74 + .../ecma-builtin-weakset.inc.h | 41 + .../builtin-objects/ecma-builtins-internal.h | 98 + .../ecma/builtin-objects/ecma-builtins.cpp | 1524 ++++ .../ecma/builtin-objects/ecma-builtins.h | 136 + .../ecma/builtin-objects/ecma-builtins.inc.h | 747 ++ .../ecma/builtin-objects/meson.build | 182 + .../ecma-builtin-bigint64array-prototype.cpp | 45 + ...ecma-builtin-bigint64array-prototype.inc.h | 28 + .../typedarray/ecma-builtin-bigint64array.cpp | 79 + .../ecma-builtin-bigint64array.inc.h | 27 + .../ecma-builtin-biguint64array-prototype.cpp | 45 + ...cma-builtin-biguint64array-prototype.inc.h | 28 + .../ecma-builtin-biguint64array.cpp | 79 + .../ecma-builtin-biguint64array.inc.h | 29 + .../ecma-builtin-float32array-prototype.cpp | 43 + .../ecma-builtin-float32array-prototype.inc.h | 26 + .../typedarray/ecma-builtin-float32array.cpp | 77 + .../ecma-builtin-float32array.inc.h | 27 + .../ecma-builtin-float64array-prototype.cpp | 45 + .../ecma-builtin-float64array-prototype.inc.h | 28 + .../typedarray/ecma-builtin-float64array.cpp | 79 + .../ecma-builtin-float64array.inc.h | 29 + .../ecma-builtin-int16array-prototype.cpp | 43 + .../ecma-builtin-int16array-prototype.inc.h | 26 + .../typedarray/ecma-builtin-int16array.cpp | 77 + .../typedarray/ecma-builtin-int16array.inc.h | 27 + .../ecma-builtin-int32array-prototype.cpp | 43 + .../ecma-builtin-int32array-prototype.inc.h | 26 + .../typedarray/ecma-builtin-int32array.cpp | 77 + .../typedarray/ecma-builtin-int32array.inc.h | 27 + .../ecma-builtin-int8array-prototype.cpp | 43 + .../ecma-builtin-int8array-prototype.inc.h | 26 + .../typedarray/ecma-builtin-int8array.cpp | 77 + .../typedarray/ecma-builtin-int8array.inc.h | 27 + .../ecma-builtin-typedarray-helpers.cpp | 74 + .../ecma-builtin-typedarray-helpers.h | 39 + ...uiltin-typedarray-prototype-template.inc.h | 39 + .../ecma-builtin-typedarray-prototype.cpp | 2106 +++++ .../ecma-builtin-typedarray-prototype.inc.h | 86 + .../ecma-builtin-typedarray-template.inc.h | 50 + .../typedarray/ecma-builtin-typedarray.cpp | 215 + .../typedarray/ecma-builtin-typedarray.inc.h | 48 + .../ecma-builtin-uint16array-prototype.cpp | 43 + .../ecma-builtin-uint16array-prototype.inc.h | 26 + .../typedarray/ecma-builtin-uint16array.cpp | 77 + .../typedarray/ecma-builtin-uint16array.inc.h | 27 + .../ecma-builtin-uint32array-prototype.cpp | 43 + .../ecma-builtin-uint32array-prototype.inc.h | 26 + .../typedarray/ecma-builtin-uint32array.cpp | 79 + .../typedarray/ecma-builtin-uint32array.inc.h | 27 + .../ecma-builtin-uint8array-prototype.cpp | 43 + .../ecma-builtin-uint8array-prototype.inc.h | 26 + .../typedarray/ecma-builtin-uint8array.cpp | 77 + .../typedarray/ecma-builtin-uint8array.inc.h | 27 + ...ma-builtin-uint8clampedarray-prototype.cpp | 43 + ...-builtin-uint8clampedarray-prototype.inc.h | 26 + .../ecma-builtin-uint8clampedarray.cpp | 79 + .../ecma-builtin-uint8clampedarray.inc.h | 27 + .../builtin-objects/typedarray/meson.build | 59 + .../jerryscript/jerry-core/ecma/meson.build | 3 + .../ecma/operations/ecma-arguments-object.cpp | 461 ++ .../ecma/operations/ecma-arguments-object.h | 42 + .../ecma/operations/ecma-array-object.cpp | 1215 +++ .../ecma/operations/ecma-array-object.h | 110 + .../operations/ecma-arraybuffer-object.cpp | 562 ++ .../ecma/operations/ecma-arraybuffer-object.h | 68 + .../ecma-async-generator-object.cpp | 523 ++ .../operations/ecma-async-generator-object.h | 88 + .../ecma/operations/ecma-atomics-object.cpp | 263 + .../ecma/operations/ecma-atomics-object.h | 56 + .../ecma/operations/ecma-big-uint.cpp | 1775 +++++ .../ecma/operations/ecma-big-uint.h | 135 + .../ecma/operations/ecma-bigint-object.cpp | 66 + .../ecma/operations/ecma-bigint-object.h | 39 + .../ecma/operations/ecma-bigint.cpp | 1703 ++++ .../jerry-core/ecma/operations/ecma-bigint.h | 81 + .../ecma/operations/ecma-boolean-object.cpp | 88 + .../ecma/operations/ecma-boolean-object.h | 35 + .../ecma/operations/ecma-comparison.cpp | 536 ++ .../ecma/operations/ecma-comparison.h | 38 + .../ecma/operations/ecma-container-object.cpp | 1143 +++ .../ecma/operations/ecma-container-object.h | 97 + .../ecma/operations/ecma-conversion.cpp | 1082 +++ .../ecma/operations/ecma-conversion.h | 76 + .../ecma/operations/ecma-dataview-object.cpp | 409 + .../ecma/operations/ecma-dataview-object.h | 46 + .../jerry-core/ecma/operations/ecma-eval.cpp | 100 + .../jerry-core/ecma/operations/ecma-eval.h | 37 + .../ecma/operations/ecma-exceptions.cpp | 520 ++ .../ecma/operations/ecma-exceptions.h | 53 + .../ecma/operations/ecma-function-object.cpp | 2208 ++++++ .../ecma/operations/ecma-function-object.h | 130 + .../ecma/operations/ecma-get-put-value.cpp | 322 + .../ecma/operations/ecma-iterator-object.cpp | 719 ++ .../ecma/operations/ecma-iterator-object.h | 84 + .../ecma/operations/ecma-jobqueue.cpp | 582 ++ .../ecma/operations/ecma-jobqueue.h | 63 + .../ecma/operations/ecma-lex-env.cpp | 643 ++ .../jerry-core/ecma/operations/ecma-lex-env.h | 85 + .../ecma/operations/ecma-number-object.cpp | 95 + .../ecma/operations/ecma-number-object.h | 35 + .../ecma/operations/ecma-objects-general.cpp | 753 ++ .../ecma/operations/ecma-objects-general.h | 50 + .../ecma/operations/ecma-objects.cpp | 3450 +++++++++ .../jerry-core/ecma/operations/ecma-objects.h | 147 + .../ecma/operations/ecma-promise-object.cpp | 1237 +++ .../ecma/operations/ecma-promise-object.h | 146 + .../ecma/operations/ecma-proxy-object.cpp | 1875 +++++ .../ecma/operations/ecma-proxy-object.h | 86 + .../ecma/operations/ecma-reference.cpp | 404 + .../ecma/operations/ecma-reference.h | 40 + .../ecma/operations/ecma-regexp-object.cpp | 3219 ++++++++ .../ecma/operations/ecma-regexp-object.h | 191 + .../ecma-shared-arraybuffer-object.cpp | 161 + .../ecma-shared-arraybuffer-object.h | 45 + .../ecma/operations/ecma-string-object.cpp | 140 + .../ecma/operations/ecma-string-object.h | 40 + .../ecma/operations/ecma-symbol-object.cpp | 177 + .../ecma/operations/ecma-symbol-object.h | 45 + .../operations/ecma-typedarray-object.cpp | 2119 +++++ .../ecma/operations/ecma-typedarray-object.h | 89 + .../jerry-core/ecma/operations/meson.build | 68 + .../jerry-core/include/jerry-config.h | 632 ++ .../jerry-core/include/jerryscript-compiler.h | 187 + .../jerry-core/include/jerryscript-core.h | 1209 +++ .../jerry-core/include/jerryscript-port.h | 313 + .../jerry-core/include/jerryscript-types.h | 865 +++ .../jerry-core/include/jerryscript.h | 36 + .../jerry-core/include/meson.build | 13 + .../jerry-core/jcontext/jcontext.cpp | 156 + .../jerry-core/jcontext/jcontext.h | 322 + .../jerry-core/jcontext/meson.build | 9 + .../jerry-core/jmem/jmem-allocator-internal.h | 78 + .../jerry-core/jmem/jmem-allocator.cpp | 107 + .../jerryscript/jerry-core/jmem/jmem-heap.cpp | 731 ++ .../jerry-core/jmem/jmem-poolman.cpp | 193 + .../lottie/jerryscript/jerry-core/jmem/jmem.h | 282 + .../jerryscript/jerry-core/jmem/meson.build | 12 + .../jerry-core/jrt/jrt-bit-fields.h | 43 + .../jerryscript/jerry-core/jrt/jrt-fatals.cpp | 96 + .../jerry-core/jrt/jrt-libc-includes.h | 26 + .../jerry-core/jrt/jrt-logging.cpp | 40 + .../jerryscript/jerry-core/jrt/jrt-types.h | 24 + .../lottie/jerryscript/jerry-core/jrt/jrt.h | 229 + .../jerryscript/jerry-core/jrt/meson.build | 13 + .../jerry-core/lit/lit-char-helpers.cpp | 995 +++ .../jerry-core/lit/lit-char-helpers.h | 260 + .../jerryscript/jerry-core/lit/lit-globals.h | 121 + .../jerry-core/lit/lit-magic-strings.cpp | 432 ++ .../jerry-core/lit/lit-magic-strings.h | 118 + .../jerry-core/lit/lit-magic-strings.inc.h | 985 +++ .../jerry-core/lit/lit-strings.cpp | 934 +++ .../jerryscript/jerry-core/lit/lit-strings.h | 150 + .../lit/lit-unicode-conversions-sup.inc.h | 27 + .../lit/lit-unicode-conversions.inc.h | 119 + .../jerry-core/lit/lit-unicode-folding.inc.h | 54 + .../lit/lit-unicode-ranges-sup.inc.h | 116 + .../jerry-core/lit/lit-unicode-ranges.inc.h | 176 + .../jerryscript/jerry-core/lit/meson.build | 20 + .../lottie/jerryscript/jerry-core/meson.build | 9 + .../jerry-core/parser/js/byte-code.cpp | 86 + .../jerry-core/parser/js/byte-code.h | 1054 +++ .../jerry-core/parser/js/common.cpp | 550 ++ .../jerryscript/jerry-core/parser/js/common.h | 162 + .../jerry-core/parser/js/js-lexer.cpp | 3622 +++++++++ .../jerry-core/parser/js/js-lexer.h | 357 + .../jerry-core/parser/js/js-parser-expr.cpp | 4182 ++++++++++ .../jerry-core/parser/js/js-parser-internal.h | 900 +++ .../jerry-core/parser/js/js-parser-limits.h | 134 + .../parser/js/js-parser-line-info-create.cpp | 592 ++ .../jerry-core/parser/js/js-parser-mem.cpp | 729 ++ .../jerry-core/parser/js/js-parser-module.cpp | 529 ++ .../jerry-core/parser/js/js-parser-statm.cpp | 3315 ++++++++ .../js/js-parser-tagged-template-literal.cpp | 161 + .../js/js-parser-tagged-template-literal.h | 49 + .../jerry-core/parser/js/js-parser-util.cpp | 874 +++ .../jerry-core/parser/js/js-parser.cpp | 3218 ++++++++ .../jerry-core/parser/js/js-parser.h | 40 + .../parser/js/js-scanner-internal.h | 399 + .../jerry-core/parser/js/js-scanner-ops.cpp | 602 ++ .../jerry-core/parser/js/js-scanner-util.cpp | 2950 +++++++ .../jerry-core/parser/js/js-scanner.cpp | 3715 +++++++++ .../jerry-core/parser/js/js-scanner.h | 303 + .../jerry-core/parser/js/meson.build | 33 + .../parser/js/parser-error-messages.inc.h | 233 + .../jerry-core/parser/js/parser-errors.cpp | 71 + .../jerry-core/parser/js/parser-errors.h | 44 + .../jerryscript/jerry-core/parser/meson.build | 2 + .../jerry-core/parser/regexp/meson.build | 15 + .../jerry-core/parser/regexp/re-bytecode.cpp | 620 ++ .../jerry-core/parser/regexp/re-bytecode.h | 131 + .../parser/regexp/re-compiler-context.h | 60 + .../jerry-core/parser/regexp/re-compiler.cpp | 184 + .../jerry-core/parser/regexp/re-compiler.h | 46 + .../jerry-core/parser/regexp/re-parser.cpp | 1327 ++++ .../jerry-core/parser/regexp/re-parser.h | 59 + .../jerry-core/parser/regexp/re-token.h | 74 + .../jerryscript/jerry-core/vm/meson.build | 18 + .../vm/opcodes-ecma-arithmetics.cpp | 337 + .../jerry-core/vm/opcodes-ecma-bitwise.cpp | 212 + .../vm/opcodes-ecma-relational-equality.cpp | 173 + .../jerryscript/jerry-core/vm/opcodes.cpp | 2302 ++++++ .../jerryscript/jerry-core/vm/opcodes.h | 173 + .../jerryscript/jerry-core/vm/vm-defines.h | 169 + .../jerryscript/jerry-core/vm/vm-stack.cpp | 546 ++ .../jerryscript/jerry-core/vm/vm-stack.h | 140 + .../jerryscript/jerry-core/vm/vm-utils.cpp | 136 + .../lottie/jerryscript/jerry-core/vm/vm.cpp | 5156 +++++++++++++ .../lottie/jerryscript/jerry-core/vm/vm.h | 426 + src/loaders/lottie/jerryscript/meson.build | 1 + src/loaders/lottie/meson.build | 4 + 416 files changed, 142609 insertions(+) create mode 100644 src/loaders/lottie/jerryscript/jerry-core/api/jerryscript.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/api/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.ini create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-globals.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-collection.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-conversion.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-errol.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-string.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-value.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/base/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-error.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-defines.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-undefs.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-sort.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype-template.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-template.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-get-put-value.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/ecma/operations/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/include/jerry-config.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-compiler.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-core.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-port.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-types.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/include/jerryscript.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/include/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jcontext/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator-internal.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-heap.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-poolman.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jmem/jmem.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jmem/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-bit-fields.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-fatals.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-libc-includes.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-logging.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-types.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jrt/jrt.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/jrt/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-globals.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions-sup.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-folding.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges-sup.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/lit/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/common.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/common.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-expr.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-internal.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-limits.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-line-info-create.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-mem.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-module.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-statm.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-util.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-internal.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-ops.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-util.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-error-messages.inc.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/regexp/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler-context.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-token.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/meson.build create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-arithmetics.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-bitwise.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-relational-equality.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/vm-defines.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.h create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/vm-utils.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/vm.cpp create mode 100644 src/loaders/lottie/jerryscript/jerry-core/vm/vm.h create mode 100644 src/loaders/lottie/jerryscript/meson.build diff --git a/meson.build b/meson.build index 5def82ab..23fc4fdf 100644 --- a/meson.build +++ b/meson.build @@ -56,6 +56,11 @@ endif if all_loaders or get_option('loaders').contains('lottie') == true config_h.set10('THORVG_LOTTIE_LOADER_SUPPORT', true) + #Experimental feature, enable it manually + lottie_expressions = false + if lottie_expressions + config_h.set10('THORVG_LOTTIE_EXPRESSIONS_SUPPORT', false) + endif endif if all_loaders or get_option('loaders').contains('ttf') == true diff --git a/src/loaders/lottie/jerryscript/jerry-core/api/jerryscript.cpp b/src/loaders/lottie/jerryscript/jerry-core/api/jerryscript.cpp new file mode 100644 index 00000000..3f0fb2ec --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/api/jerryscript.cpp @@ -0,0 +1,6847 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jerryscript.h" + +#include +#include +#include + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-arraybuffer-object.h" +#include "ecma-bigint.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-comparison.h" +#include "ecma-container-object.h" +#include "ecma-dataview-object.h" +#include "ecma-errors.h" +#include "ecma-eval.h" +#include "ecma-exceptions.h" +#include "ecma-extended-info.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-init-finalize.h" +#include "ecma-iterator-object.h" +#include "ecma-lex-env.h" +#include "ecma-line-info.h" +#include "ecma-literal-storage.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" +#include "ecma-proxy-object.h" +#include "ecma-regexp-object.h" +#include "ecma-shared-arraybuffer-object.h" +#include "ecma-symbol-object.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" +#include "jmem.h" +#include "jrt.h" +#include "js-parser.h" +#include "lit-char-helpers.h" +#include "opcodes.h" +#include "re-compiler.h" + +JERRY_STATIC_ASSERT ((sizeof (jerry_value_t) == sizeof (ecma_value_t)), + size_of_jerry_value_t_must_be_equal_to_size_of_ecma_value_t); + +#if JERRY_BUILTIN_REGEXP +JERRY_STATIC_ASSERT (((int) RE_FLAG_GLOBAL == (int) JERRY_REGEXP_FLAG_GLOBAL) + && ((int) RE_FLAG_MULTILINE == (int) JERRY_REGEXP_FLAG_MULTILINE) + && ((int) RE_FLAG_IGNORE_CASE == (int) JERRY_REGEXP_FLAG_IGNORE_CASE) + && ((int) RE_FLAG_STICKY == (int) JERRY_REGEXP_FLAG_STICKY) + && ((int) RE_FLAG_UNICODE == (int) JERRY_REGEXP_FLAG_UNICODE) + && ((int) RE_FLAG_DOTALL == (int) JERRY_REGEXP_FLAG_DOTALL), + re_flags_t_must_be_equal_to_jerry_regexp_flags_t); +#endif /* JERRY_BUILTIN_REGEXP */ + +/* The internal ECMA_PROMISE_STATE_* values are "one byte away" from the API values */ +JERRY_STATIC_ASSERT (((int) ECMA_PROMISE_IS_PENDING == (int) JERRY_PROMISE_STATE_PENDING) + && ((int) ECMA_PROMISE_IS_FULFILLED == (int) JERRY_PROMISE_STATE_FULFILLED), + promise_internal_state_matches_external); + +/** + * Offset between internal and external arithmetic operator types + */ +#define ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET (JERRY_BIN_OP_SUB - NUMBER_ARITHMETIC_SUBTRACTION) + +JERRY_STATIC_ASSERT (((NUMBER_ARITHMETIC_SUBTRACTION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_SUB) + && ((NUMBER_ARITHMETIC_MULTIPLICATION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) + == JERRY_BIN_OP_MUL) + && ((NUMBER_ARITHMETIC_DIVISION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_DIV) + && ((NUMBER_ARITHMETIC_REMAINDER + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_REM), + number_arithmetics_operation_type_matches_external); + +#if !JERRY_PARSER && !JERRY_SNAPSHOT_EXEC +#error "JERRY_SNAPSHOT_EXEC must be enabled if JERRY_PARSER is disabled!" +#endif /* !JERRY_PARSER && !JERRY_SNAPSHOT_EXEC */ + +/** \addtogroup jerry Jerry engine interface + * @{ + */ + +/** + * Assert that it is correct to call API in current state. + * + * Note: + * By convention, there are some states when API could not be invoked. + * + * The API can be and only be invoked when the ECMA_STATUS_API_ENABLED + * flag is set. + * + * This procedure checks whether the API is available, and terminates + * the engine if it is unavailable. Otherwise it is a no-op. + * + * Note: + * The API could not be invoked in the following cases: + * - before jerry_init and after jerry_cleanup + * - between enter to and return from a native free callback + * + * @return void + */ +static inline void +jerry_assert_api_enabled (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (status_flags) & ECMA_STATUS_API_ENABLED); +} /* jerry_assert_api_enabled */ + +/** + * Turn on API availability + * + * @return void + */ +static inline void +jerry_api_enable (void) +{ +#ifndef JERRY_NDEBUG + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_API_ENABLED; +#endif /* JERRY_NDEBUG */ +} /* jerry_make_api_available */ + +/** + * Turn off API availability + * + * @return void + */ +static inline void +jerry_api_disable (void) +{ +#ifndef JERRY_NDEBUG + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_API_ENABLED; +#endif /* JERRY_NDEBUG */ +} /* jerry_make_api_unavailable */ + +/** + * Create an API compatible return value. + * + * @return return value for Jerry API functions + */ +static jerry_value_t +jerry_return (const jerry_value_t value) /**< return value */ +{ + if (ECMA_IS_VALUE_ERROR (value)) + { + return ecma_create_exception_from_context (); + } + + return value; +} /* jerry_return */ + +/** + * Jerry engine initialization + */ +void +jerry_init (jerry_init_flag_t flags) /**< combination of Jerry flags */ +{ +#if JERRY_EXTERNAL_CONTEXT + size_t total_size = jerry_port_context_alloc (sizeof (jerry_context_t)); + JERRY_UNUSED (total_size); +#endif /* JERRY_EXTERNAL_CONTEXT */ + + jerry_context_t *context_p = &JERRY_CONTEXT_STRUCT; + memset (context_p, 0, sizeof (jerry_context_t)); + +#if JERRY_EXTERNAL_CONTEXT && !JERRY_SYSTEM_ALLOCATOR + uint32_t heap_start_offset = JERRY_ALIGNUP (sizeof (jerry_context_t), JMEM_ALIGNMENT); + uint8_t *heap_p = ((uint8_t *) context_p) + heap_start_offset; + uint32_t heap_size = JERRY_ALIGNDOWN (total_size - heap_start_offset, JMEM_ALIGNMENT); + + JERRY_ASSERT (heap_p + heap_size <= ((uint8_t *) context_p) + total_size); + + context_p->heap_p = (jmem_heap_t *) heap_p; + context_p->heap_size = heap_size; +#endif /* JERRY_EXTERNAL_CONTEXT && !JERRY_SYSTEM_ALLOCATOR */ + + JERRY_CONTEXT (jerry_init_flags) = flags; + + jerry_api_enable (); + + jmem_init (); + ecma_init (); +} /* jerry_init */ + +/** + * Terminate Jerry engine + */ +void +jerry_cleanup (void) +{ + for (jerry_context_data_header_t *this_p = JERRY_CONTEXT (context_data_p); this_p != NULL; this_p = this_p->next_p) + { + if (this_p->manager_p->deinit_cb) + { + void *data = (this_p->manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (this_p) : NULL; + this_p->manager_p->deinit_cb (data); + } + } + + ecma_free_all_enqueued_jobs (); + ecma_finalize (); + jerry_api_disable (); + + for (jerry_context_data_header_t *this_p = JERRY_CONTEXT (context_data_p), *next_p = NULL; this_p != NULL; + this_p = next_p) + { + next_p = this_p->next_p; + + if (this_p->manager_p->finalize_cb) + { + void *data = (this_p->manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (this_p) : NULL; + this_p->manager_p->finalize_cb (data); + } + + jmem_heap_free_block (this_p, sizeof (jerry_context_data_header_t) + this_p->manager_p->bytes_needed); + } + + jmem_finalize (); +#if JERRY_EXTERNAL_CONTEXT + jerry_port_context_free (); +#endif /* JERRY_EXTERNAL_CONTEXT */ +} /* jerry_cleanup */ + +/** + * Retrieve a context data item, or create a new one. + * + * @param manager_p pointer to the manager whose context data item should be returned. + * + * @return a pointer to the user-provided context-specific data item for the given manager, creating such a pointer if + * none was found. + */ +void * +jerry_context_data (const jerry_context_data_manager_t *manager_p) +{ + void *ret = NULL; + jerry_context_data_header_t *item_p; + + for (item_p = JERRY_CONTEXT (context_data_p); item_p != NULL; item_p = item_p->next_p) + { + if (item_p->manager_p == manager_p) + { + return (manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (item_p) : NULL; + } + } + + item_p = (jerry_context_data_header_t *) jmem_heap_alloc_block (sizeof (jerry_context_data_header_t) + manager_p->bytes_needed); + item_p->manager_p = manager_p; + item_p->next_p = JERRY_CONTEXT (context_data_p); + JERRY_CONTEXT (context_data_p) = item_p; + + if (manager_p->bytes_needed > 0) + { + ret = JERRY_CONTEXT_DATA_HEADER_USER_DATA (item_p); + memset (ret, 0, manager_p->bytes_needed); + } + + if (manager_p->init_cb) + { + manager_p->init_cb (ret); + } + + return ret; +} /* jerry_context_data */ + +/** + * Register external magic string array + */ +void +jerry_register_magic_strings (const jerry_char_t *const *ext_strings_p, /**< character arrays, representing + * external magic strings' contents */ + uint32_t count, /**< number of the strings */ + const jerry_length_t *str_lengths_p) /**< lengths of all strings */ +{ + lit_magic_strings_ex_set ((const lit_utf8_byte_t *const *) ext_strings_p, + count, + (const lit_utf8_size_t *) str_lengths_p); +} /* jerry_register_magic_strings */ + +/** + * Run garbage collection + */ +void +jerry_heap_gc (jerry_gc_mode_t mode) /**< operational mode */ +{ + if (mode == JERRY_GC_PRESSURE_LOW) + { + /* Call GC directly, because 'ecma_free_unused_memory' might decide it's not yet worth it. */ + ecma_gc_run (); + return; + } + + ecma_free_unused_memory (JMEM_PRESSURE_HIGH); +} /* jerry_heap_gc */ + +/** + * Get heap memory stats. + * + * @return true - get the heap stats successful + * false - otherwise. Usually it is because the MEM_STATS feature is not enabled. + */ +bool +jerry_heap_stats (jerry_heap_stats_t *out_stats_p) /**< [out] heap memory stats */ +{ + JERRY_UNUSED (out_stats_p); + return false; +} /* jerry_heap_stats */ + +#if JERRY_PARSER +/** + * Common code for parsing a script, module, or function. + * + * @return function object value - if script was parsed successfully, + * thrown error - otherwise + */ +static jerry_value_t +jerry_parse_common (void *source_p, /**< script source */ + const jerry_parse_options_t *options_p, /**< parsing options, can be NULL if not used */ + uint32_t parse_opts) /**< internal parsing options */ +{ + if (options_p != NULL) + { + const uint32_t allowed_options = + (JERRY_PARSE_STRICT_MODE | JERRY_PARSE_MODULE | JERRY_PARSE_HAS_ARGUMENT_LIST | JERRY_PARSE_HAS_SOURCE_NAME + | JERRY_PARSE_HAS_START | JERRY_PARSE_HAS_USER_VALUE); + uint32_t options = options_p->options; + + if ((options & ~allowed_options) != 0 + || ((options_p->options & JERRY_PARSE_HAS_ARGUMENT_LIST) + && ((options_p->options & JERRY_PARSE_MODULE) || !ecma_is_value_string (options_p->argument_list))) + || ((options_p->options & JERRY_PARSE_HAS_SOURCE_NAME) && !ecma_is_value_string (options_p->source_name))) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + } + + if (options_p != NULL) + { + parse_opts |= options_p->options & (JERRY_PARSE_STRICT_MODE | JERRY_PARSE_MODULE); + } + + if ((parse_opts & JERRY_PARSE_MODULE) != 0) + { +#if JERRY_MODULE_SYSTEM + JERRY_CONTEXT (module_current_p) = ecma_module_create (); +#else /* !JERRY_MODULE_SYSTEM */ + return jerry_throw_sz (JERRY_ERROR_SYNTAX, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ + } + + ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = parser_parse_script (source_p, parse_opts, options_p); + + if (JERRY_UNLIKELY (bytecode_data_p == NULL)) + { +#if JERRY_MODULE_SYSTEM + if ((parse_opts & JERRY_PARSE_MODULE) != 0) + { + ecma_module_cleanup_context (); + } +#endif /* JERRY_MODULE_SYSTEM */ + + return ecma_create_exception_from_context (); + } + +#if JERRY_MODULE_SYSTEM + if (JERRY_UNLIKELY (parse_opts & JERRY_PARSE_MODULE)) + { + ecma_module_t *module_p = JERRY_CONTEXT (module_current_p); + module_p->u.compiled_code_p = bytecode_data_p; + + JERRY_CONTEXT (module_current_p) = NULL; + + return ecma_make_object_value ((ecma_object_t *) module_p); + } +#endif /* JERRY_MODULE_SYSTEM */ + + if (JERRY_UNLIKELY (options_p != NULL && (options_p->options & JERRY_PARSE_HAS_ARGUMENT_LIST))) + { + ecma_object_t *global_object_p = ecma_builtin_get_global (); + +#if JERRY_BUILTIN_REALMS + JERRY_ASSERT (global_object_p == (ecma_object_t *) ecma_op_function_get_realm (bytecode_data_p)); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *lex_env_p = ecma_get_global_environment (global_object_p); + ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_data_p); + ecma_bytecode_deref (bytecode_data_p); + + return ecma_make_object_value (func_obj_p); + } + + ecma_object_t *object_p = ecma_create_object (NULL, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_SCRIPT; + ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.cls.u3.value, bytecode_data_p); + + return ecma_make_object_value (object_p); +} /* jerry_parse_common */ + +#endif /* JERRY_PARSER */ + +/** + * Parse a script, module, or function and create a compiled code using a character string + * + * @return function object value - if script was parsed successfully, + * thrown error - otherwise + */ +jerry_value_t +jerry_parse (const jerry_char_t *source_p, /**< script source */ + size_t source_size, /**< script source size */ + const jerry_parse_options_t *options_p) /**< parsing options, can be NULL if not used */ +{ +#if JERRY_PARSER + parser_source_char_t source_char; + source_char.source_p = source_p; + source_char.source_size = source_size; + + return jerry_parse_common ((void *) &source_char, options_p, JERRY_PARSE_NO_OPTS); +#else /* !JERRY_PARSER */ + JERRY_UNUSED (source_p); + JERRY_UNUSED (source_size); + JERRY_UNUSED (options_p); + + return jerry_throw_sz (JERRY_ERROR_SYNTAX, ecma_get_error_msg (ECMA_ERR_PARSER_NOT_SUPPORTED)); +#endif /* JERRY_PARSER */ +} /* jerry_parse */ + +/** + * Parse a script, module, or function and create a compiled code using a string value + * + * @return function object value - if script was parsed successfully, + * thrown error - otherwise + */ +jerry_value_t +jerry_parse_value (const jerry_value_t source, /**< script source */ + const jerry_parse_options_t *options_p) /**< parsing options, can be NULL if not used */ +{ +#if JERRY_PARSER + if (!ecma_is_value_string (source)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + return jerry_parse_common ((void *) &source, options_p, ECMA_PARSE_HAS_SOURCE_VALUE); +#else /* !JERRY_PARSER */ + JERRY_UNUSED (source); + JERRY_UNUSED (options_p); + + return jerry_throw_sz (JERRY_ERROR_SYNTAX, ecma_get_error_msg (ECMA_ERR_PARSER_NOT_SUPPORTED)); +#endif /* JERRY_PARSER */ +} /* jerry_parse_value */ + +/** + * Run a Script or Module created by jerry_parse. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return result of bytecode - if run was successful + * thrown error - otherwise + */ +jerry_value_t +jerry_run (const jerry_value_t script) /**< script or module to run */ +{ + if (!ecma_is_value_object (script)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *object_p = ecma_get_object_from_value (script); + + if (!ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_SCRIPT)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_SCRIPT); + + return jerry_return (vm_run_global (bytecode_data_p, object_p)); +} /* jerry_run */ + +/** + * Perform eval + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return result of eval, may be error value. + */ +jerry_value_t +jerry_eval (const jerry_char_t *source_p, /**< source code */ + size_t source_size, /**< length of source code */ + uint32_t flags) /**< jerry_parse_opts_t flags */ +{ + uint32_t allowed_parse_options = JERRY_PARSE_STRICT_MODE; + + if ((flags & ~allowed_parse_options) != 0) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + parser_source_char_t source_char; + source_char.source_p = source_p; + source_char.source_size = source_size; + + return jerry_return (ecma_op_eval_chars_buffer ((void *) &source_char, flags)); +} /* jerry_eval */ + +/** + * Link modules to their dependencies. The dependencies are resolved by a user callback. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true - if linking is successful, error - otherwise + */ +jerry_value_t +jerry_module_link (const jerry_value_t module, /**< root module */ + jerry_module_resolve_cb_t callback, /**< resolve module callback, uses + * jerry_module_resolve when NULL is passed */ + void *user_p) /**< pointer passed to the resolve callback */ +{ +#if JERRY_MODULE_SYSTEM + if (callback == NULL) + { + callback = jerry_module_resolve; + } + + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + return jerry_return (ecma_module_link (module_p, callback, user_p)); +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_link */ + +/** + * Evaluate a module and its dependencies. The module must be in linked state. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return result of module bytecode execution - if evaluation was successful + * error - otherwise + */ +jerry_value_t +jerry_module_evaluate (const jerry_value_t module) /**< root module */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + if (module_p->header.u.cls.u1.module_state != JERRY_MODULE_STATE_LINKED) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_MUST_BE_IN_LINKED_STATE)); + } + + return jerry_return (ecma_module_evaluate (module_p)); +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_evaluate */ + +/** + * Returns the current status of a module + * + * @return current status - if module is a module, + * JERRY_MODULE_STATE_INVALID - otherwise + */ +jerry_module_state_t +jerry_module_state (const jerry_value_t module) /**< module object */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return JERRY_MODULE_STATE_INVALID; + } + + return (jerry_module_state_t) module_p->header.u.cls.u1.module_state; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + + return JERRY_MODULE_STATE_INVALID; +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_state */ + +/** + * Sets a callback which is called after a module state is changed to linked, evaluated, or error. + */ +void +jerry_module_on_state_changed (jerry_module_state_changed_cb_t callback, /**< callback */ + void *user_p) /**< pointer passed to the callback */ +{ +#if JERRY_MODULE_SYSTEM + JERRY_CONTEXT (module_state_changed_callback_p) = callback; + JERRY_CONTEXT (module_state_changed_callback_user_p) = user_p; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_on_state_changed */ + +/** + * Sets a callback which is called when an import.meta expression of a module is evaluated the first time. + */ +void +jerry_module_on_import_meta (jerry_module_import_meta_cb_t callback, /**< callback */ + void *user_p) /**< pointer passed to the callback */ +{ +#if JERRY_MODULE_SYSTEM + JERRY_CONTEXT (module_import_meta_callback_p) = callback; + JERRY_CONTEXT (module_import_meta_callback_user_p) = user_p; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_on_import_meta */ + +/** + * Returns the number of import/export requests of a module + * + * @return number of import/export requests of a module + */ +size_t +jerry_module_request_count (const jerry_value_t module) /**< module */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return 0; + } + + size_t number_of_requests = 0; + + ecma_module_node_t *node_p = module_p->imports_p; + + while (node_p != NULL) + { + number_of_requests++; + node_p = node_p->next_p; + } + + return number_of_requests; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + + return 0; +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_request_count */ + +/** + * Returns the module request specified by the request_index argument + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return string - if the request has not been resolved yet, + * module object - if the request has been resolved successfully, + * error - otherwise + */ +jerry_value_t +jerry_module_request (const jerry_value_t module, /**< module */ + size_t request_index) /**< request index */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + ecma_module_node_t *node_p = module_p->imports_p; + + while (node_p != NULL) + { + if (request_index == 0) + { + return ecma_copy_value (node_p->u.path_or_module); + } + + --request_index; + node_p = node_p->next_p; + } + + return jerry_throw_sz (JERRY_ERROR_RANGE, ecma_get_error_msg (ECMA_ERR_REQUEST_IS_NOT_AVAILABLE)); +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + JERRY_UNUSED (request_index); + + return jerry_throw_sz (JERRY_ERROR_RANGE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_request */ + +/** + * Returns the namespace object of a module + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return object - if namespace object is available, + * error - otherwise + */ +jerry_value_t +jerry_module_namespace (const jerry_value_t module) /**< module */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + if (module_p->header.u.cls.u1.module_state < JERRY_MODULE_STATE_LINKED + || module_p->header.u.cls.u1.module_state > JERRY_MODULE_STATE_EVALUATED) + { + return jerry_throw_sz (JERRY_ERROR_RANGE, ecma_get_error_msg (ECMA_ERR_NAMESPACE_OBJECT_IS_NOT_AVAILABLE)); + } + + JERRY_ASSERT (module_p->namespace_object_p != NULL); + + ecma_ref_object (module_p->namespace_object_p); + return ecma_make_object_value (module_p->namespace_object_p); +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_namespace */ + +/** + * Sets the callback which is called when dynamic imports are resolved + */ +void +jerry_module_on_import (jerry_module_import_cb_t callback_p, /**< callback which handles + * dynamic import calls */ + void *user_p) /**< user pointer passed to the callback */ +{ +#if JERRY_MODULE_SYSTEM + JERRY_CONTEXT (module_import_callback_p) = callback_p; + JERRY_CONTEXT (module_import_callback_user_p) = user_p; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (callback_p); + JERRY_UNUSED (user_p); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_on_import */ + +/** + * Creates a native module with a list of exports. The initial state of the module is linked. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return native module - if the module is successfully created, + * error - otherwise + */ +jerry_value_t +jerry_native_module (jerry_native_module_evaluate_cb_t callback, /**< evaluation callback for + * native modules */ + const jerry_value_t *const exports_p, /**< list of the exported bindings of the module, + * must be valid string identifiers */ + size_t export_count) /**< number of exports in the exports_p list */ +{ +#if JERRY_MODULE_SYSTEM + ecma_object_t *global_object_p = ecma_builtin_get_global (); + ecma_object_t *scope_p = ecma_create_decl_lex_env (ecma_get_global_environment (global_object_p)); + ecma_module_names_t *local_exports_p = NULL; + + for (size_t i = 0; i < export_count; i++) + { + if (!ecma_is_value_string (exports_p[i])) + { + ecma_deref_object (scope_p); + ecma_module_release_module_names (local_exports_p); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_EXPORTS_MUST_BE_STRING_VALUES)); + } + + ecma_string_t *name_str_p = ecma_get_string_from_value (exports_p[i]); + + bool valid_identifier = false; + + ECMA_STRING_TO_UTF8_STRING (name_str_p, name_start_p, name_size); + + if (name_size > 0) + { + const lit_utf8_byte_t *name_p = name_start_p; + const lit_utf8_byte_t *name_end_p = name_start_p + name_size; + lit_code_point_t code_point; + + lit_utf8_size_t size = lit_read_code_point_from_cesu8 (name_p, name_end_p, &code_point); + + if (lit_code_point_is_identifier_start (code_point)) + { + name_p += size; + + valid_identifier = true; + + while (name_p < name_end_p) + { + size = lit_read_code_point_from_cesu8 (name_p, name_end_p, &code_point); + + if (!lit_code_point_is_identifier_part (code_point)) + { + valid_identifier = false; + break; + } + + name_p += size; + } + } + } + + ECMA_FINALIZE_UTF8_STRING (name_start_p, name_size); + + if (!valid_identifier) + { + ecma_deref_object (scope_p); + ecma_module_release_module_names (local_exports_p); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_EXPORTS_MUST_BE_VALID_IDENTIFIERS)); + } + + if (ecma_find_named_property (scope_p, name_str_p) != NULL) + { + continue; + } + + ecma_create_named_data_property (scope_p, name_str_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + + ecma_module_names_t *new_export_p; + new_export_p = (ecma_module_names_t *) jmem_heap_alloc_block (sizeof (ecma_module_names_t)); + + new_export_p->next_p = local_exports_p; + local_exports_p = new_export_p; + + ecma_ref_ecma_string (name_str_p); + new_export_p->imex_name_p = name_str_p; + + ecma_ref_ecma_string (name_str_p); + new_export_p->local_name_p = name_str_p; + } + + ecma_module_t *module_p = ecma_module_create (); + + module_p->header.u.cls.u2.module_flags |= ECMA_MODULE_IS_NATIVE; + module_p->scope_p = scope_p; + module_p->local_exports_p = local_exports_p; + module_p->u.callback = callback; + + ecma_deref_object (scope_p); + + return ecma_make_object_value (&module_p->header.object); + +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (callback); + JERRY_UNUSED (exports_p); + JERRY_UNUSED (export_count); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_native_module */ + +/** + * Gets the value of an export which belongs to a native module. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the export - if success + * error - otherwise + */ +jerry_value_t +jerry_native_module_get (const jerry_value_t native_module, /**< a native module object */ + const jerry_value_t export_name) /**< string identifier of the export */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (native_module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) || !ecma_is_value_string (export_name)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_property_t *property_p = ecma_find_named_property (module_p->scope_p, ecma_get_string_from_value (export_name)); + + if (property_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_REFERENCE, ecma_get_error_msg (ECMA_ERR_UNKNOWN_EXPORT)); + } + + return ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (native_module); + JERRY_UNUSED (export_name); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_native_module_get */ + +/** + * Sets the value of an export which belongs to a native module. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * error - otherwise + */ +jerry_value_t +jerry_native_module_set (jerry_value_t native_module, /**< a native module object */ + const jerry_value_t export_name, /**< string identifier of the export */ + const jerry_value_t value) /**< new value of the export */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (native_module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) || !ecma_is_value_string (export_name) + || ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_property_t *property_p = ecma_find_named_property (module_p->scope_p, ecma_get_string_from_value (export_name)); + + if (property_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_REFERENCE, ecma_get_error_msg (ECMA_ERR_UNKNOWN_EXPORT)); + } + + ecma_named_data_property_assign_value (module_p->scope_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); + return ECMA_VALUE_TRUE; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (native_module); + JERRY_UNUSED (export_name); + JERRY_UNUSED (value); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_native_module_set */ + +/** + * Run enqueued microtasks created by Promise or AsyncFunction objects. + * Tasks are executed until an exception is thrown or all tasks are executed. + * + * Note: returned value must be freed with jerry_value_free + * + * @return result of last executed job, possibly an exception. + */ +jerry_value_t +jerry_run_jobs (void) +{ + return jerry_return (ecma_process_all_enqueued_jobs ()); +} /* jerry_run_jobs */ + +/** + * Get global object + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return api value of global object + */ +jerry_value_t +jerry_current_realm (void) +{ + ecma_object_t *global_obj_p = ecma_builtin_get_global (); + ecma_ref_object (global_obj_p); + return ecma_make_object_value (global_obj_p); +} /* jerry_current_realm */ + +/** + * Check if the specified value is an abort value. + * + * @return true - if both the error and abort values are set, + * false - otherwise + */ +bool +jerry_value_is_abort (const jerry_value_t value) /**< api value */ +{ + if (!ecma_is_value_exception (value)) + { + return false; + } + + ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); + + return (error_ref_p->refs_and_type & ECMA_ERROR_API_FLAG_ABORT) != 0; +} /* jerry_value_is_abort */ + +/** + * Check if the specified value is an array object value. + * + * @return true - if the specified value is an array object, + * false - otherwise + */ +bool +jerry_value_is_array (const jerry_value_t value) /**< jerry api value */ +{ + return (ecma_is_value_object (value) + && ecma_get_object_base_type (ecma_get_object_from_value (value)) == ECMA_OBJECT_BASE_TYPE_ARRAY); +} /* jerry_value_is_array */ + +/** + * Check if the specified value is boolean. + * + * @return true - if the specified value is boolean, + * false - otherwise + */ +bool +jerry_value_is_boolean (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_boolean (value); +} /* jerry_value_is_boolean */ + +/** + * Check if the specified value is true. + * + * @return true - if the specified value is true + * false - otherwise + */ +bool +jerry_value_is_true (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_true (value); +} /* jerry_value_is_true */ + +/** + * Check if the specified value is false. + * + * @return true - if the specified value is false + * false - otherwise + */ +bool +jerry_value_is_false (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_false (value); +} /* jerry_value_is_false */ + +/** + * Check if the specified value is a constructor function object value. + * + * @return true - if the specified value is a function value that implements [[Construct]], + * false - otherwise + */ +bool +jerry_value_is_constructor (const jerry_value_t value) /**< jerry api value */ +{ + return ecma_is_constructor (value); +} /* jerry_value_is_constructor */ + +/** + * Check if the specified value is an error or abort value. + * + * @return true - if the specified value is an error value, + * false - otherwise + */ +bool +jerry_value_is_exception (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_exception (value); +} /* jerry_value_is_exception */ + +/** + * Check if the specified value is a function object value. + * + * @return true - if the specified value is callable, + * false - otherwise + */ +bool +jerry_value_is_function (const jerry_value_t value) /**< api value */ +{ + return ecma_op_is_callable (value); +} /* jerry_value_is_function */ + +/** + * Check if the specified value is an async function object value. + * + * @return true - if the specified value is an async function, + * false - otherwise + */ +bool +jerry_value_is_async_function (const jerry_value_t value) /**< api value */ +{ + if (ecma_is_value_object (value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) obj_p); + uint16_t type = CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags); + + return (type == CBC_FUNCTION_ASYNC || type == CBC_FUNCTION_ASYNC_ARROW || type == CBC_FUNCTION_ASYNC_GENERATOR); + } + } + + return false; +} /* jerry_value_is_async_function */ + +/** + * Check if the specified value is number. + * + * @return true - if the specified value is number, + * false - otherwise + */ +bool +jerry_value_is_number (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_number (value); +} /* jerry_value_is_number */ + +/** + * Check if the specified value is null. + * + * @return true - if the specified value is null, + * false - otherwise + */ +bool +jerry_value_is_null (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_null (value); +} /* jerry_value_is_null */ + +/** + * Check if the specified value is object. + * + * @return true - if the specified value is object, + * false - otherwise + */ +bool +jerry_value_is_object (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_object (value); +} /* jerry_value_is_object */ + +/** + * Check if the specified value is promise. + * + * @return true - if the specified value is promise, + * false - otherwise + */ +bool +jerry_value_is_promise (const jerry_value_t value) /**< api value */ +{ + return (ecma_is_value_object (value) && ecma_is_promise (ecma_get_object_from_value (value))); +} /* jerry_value_is_promise */ + +/** + * Check if the specified value is a proxy object. + * + * @return true - if the specified value is a proxy object, + * false - otherwise + */ +bool +jerry_value_is_proxy (const jerry_value_t value) /**< api value */ +{ +#if JERRY_BUILTIN_PROXY + return (ecma_is_value_object (value) && ECMA_OBJECT_IS_PROXY (ecma_get_object_from_value (value))); +#else /* !JERRY_BUILTIN_PROXY */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_PROXY */ +} /* jerry_value_is_proxy */ + +/** + * Check if the specified value is string. + * + * @return true - if the specified value is string, + * false - otherwise + */ +bool +jerry_value_is_string (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_string (value); +} /* jerry_value_is_string */ + +/** + * Check if the specified value is symbol. + * + * @return true - if the specified value is symbol, + * false - otherwise + */ +bool +jerry_value_is_symbol (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_symbol (value); +} /* jerry_value_is_symbol */ + +/** + * Check if the specified value is BigInt. + * + * @return true - if the specified value is BigInt, + * false - otherwise + */ +bool +jerry_value_is_bigint (const jerry_value_t value) /**< api value */ +{ +#if JERRY_BUILTIN_BIGINT + return ecma_is_value_bigint (value); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_BIGINT */ +} /* jerry_value_is_bigint */ + +/** + * Check if the specified value is undefined. + * + * @return true - if the specified value is undefined, + * false - otherwise + */ +bool +jerry_value_is_undefined (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_undefined (value); +} /* jerry_value_is_undefined */ + +/** + * Perform the base type of the JavaScript value. + * + * @return jerry_type_t value + */ +jerry_type_t +jerry_value_type (const jerry_value_t value) /**< input value to check */ +{ + if (ecma_is_value_exception (value)) + { + return JERRY_TYPE_EXCEPTION; + } + + lit_magic_string_id_t lit_id = ecma_get_typeof_lit_id (value); + + JERRY_ASSERT (lit_id != LIT_MAGIC_STRING__EMPTY); + + switch (lit_id) + { + case LIT_MAGIC_STRING_UNDEFINED: + { + return JERRY_TYPE_UNDEFINED; + } + case LIT_MAGIC_STRING_BOOLEAN: + { + return JERRY_TYPE_BOOLEAN; + } + case LIT_MAGIC_STRING_NUMBER: + { + return JERRY_TYPE_NUMBER; + } + case LIT_MAGIC_STRING_STRING: + { + return JERRY_TYPE_STRING; + } + case LIT_MAGIC_STRING_SYMBOL: + { + return JERRY_TYPE_SYMBOL; + } + case LIT_MAGIC_STRING_FUNCTION: + { + return JERRY_TYPE_FUNCTION; + } +#if JERRY_BUILTIN_BIGINT + case LIT_MAGIC_STRING_BIGINT: + { + return JERRY_TYPE_BIGINT; + } +#endif /* JERRY_BUILTIN_BIGINT */ + default: + { + JERRY_ASSERT (lit_id == LIT_MAGIC_STRING_OBJECT); + + /* Based on the ECMA 262 5.1 standard the 'null' value is an object. + * Thus we'll do an extra check for 'null' here. + */ + return ecma_is_value_null (value) ? JERRY_TYPE_NULL : JERRY_TYPE_OBJECT; + } + } +} /* jerry_value_type */ + +/** + * Used by jerry_object_type to get the type of class objects + */ +static const uint8_t jerry_class_object_type[] = { + /* These objects require custom property resolving. */ + JERRY_OBJECT_TYPE_STRING, /**< type of ECMA_OBJECT_CLASS_STRING */ + JERRY_OBJECT_TYPE_ARGUMENTS, /**< type of ECMA_OBJECT_CLASS_ARGUMENTS */ +#if JERRY_BUILTIN_TYPEDARRAY + JERRY_OBJECT_TYPE_TYPEDARRAY, /**< type of ECMA_OBJECT_CLASS_TYPEDARRAY */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + JERRY_OBJECT_TYPE_MODULE_NAMESPACE, /**< type of ECMA_OBJECT_CLASS_MODULE_NAMESPACE */ +#endif /* JERRY_MODULE_SYSTEM */ + + /* These objects are marked by Garbage Collector. */ + JERRY_OBJECT_TYPE_GENERATOR, /**< type of ECMA_OBJECT_CLASS_GENERATOR */ + JERRY_OBJECT_TYPE_GENERATOR, /**< type of ECMA_OBJECT_CLASS_ASYNC_GENERATOR */ + JERRY_OBJECT_TYPE_ITERATOR, /**< type of ECMA_OBJECT_CLASS_ARRAY_ITERATOR */ + JERRY_OBJECT_TYPE_ITERATOR, /**< type of ECMA_OBJECT_CLASS_SET_ITERATOR */ + JERRY_OBJECT_TYPE_ITERATOR, /**< type of ECMA_OBJECT_CLASS_MAP_ITERATOR */ +#if JERRY_BUILTIN_REGEXP + JERRY_OBJECT_TYPE_ITERATOR, /**< type of ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR */ +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_MODULE_SYSTEM + JERRY_OBJECT_TYPE_MODULE, /**< type of ECMA_OBJECT_CLASS_MODULE */ +#endif /* JERRY_MODULE_SYSTEM */ + JERRY_OBJECT_TYPE_PROMISE, /**< type of ECMA_OBJECT_CLASS_PROMISE */ + JERRY_OBJECT_TYPE_GENERIC, /**< type of ECMA_OBJECT_CLASS_PROMISE_CAPABILITY */ + JERRY_OBJECT_TYPE_GENERIC, /**< type of ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR */ +#if JERRY_BUILTIN_DATAVIEW + JERRY_OBJECT_TYPE_DATAVIEW, /**< type of ECMA_OBJECT_CLASS_DATAVIEW */ +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_CONTAINER + JERRY_OBJECT_TYPE_CONTAINER, /**< type of ECMA_OBJECT_CLASS_CONTAINER */ +#endif /* JERRY_BUILTIN_CONTAINER */ + + /* Normal objects. */ + JERRY_OBJECT_TYPE_BOOLEAN, /**< type of ECMA_OBJECT_CLASS_BOOLEAN */ + JERRY_OBJECT_TYPE_NUMBER, /**< type of ECMA_OBJECT_CLASS_NUMBER */ + JERRY_OBJECT_TYPE_ERROR, /**< type of ECMA_OBJECT_CLASS_ERROR */ + JERRY_OBJECT_TYPE_GENERIC, /**< type of ECMA_OBJECT_CLASS_INTERNAL_OBJECT */ +#if JERRY_PARSER + JERRY_OBJECT_TYPE_SCRIPT, /**< type of ECMA_OBJECT_CLASS_SCRIPT */ +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_DATE + JERRY_OBJECT_TYPE_DATE, /**< type of ECMA_OBJECT_CLASS_DATE */ +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP + JERRY_OBJECT_TYPE_REGEXP, /**< type of ECMA_OBJECT_CLASS_REGEXP */ +#endif /* JERRY_BUILTIN_REGEXP */ + JERRY_OBJECT_TYPE_SYMBOL, /**< type of ECMA_OBJECT_CLASS_SYMBOL */ + JERRY_OBJECT_TYPE_ITERATOR, /**< type of ECMA_OBJECT_CLASS_STRING_ITERATOR */ +#if JERRY_BUILTIN_TYPEDARRAY + JERRY_OBJECT_TYPE_ARRAYBUFFER, /**< type of ECMA_OBJECT_CLASS_ARRAY_BUFFER */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + JERRY_OBJECT_TYPE_SHARED_ARRAY_BUFFER, /**< type of ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER */ +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT + JERRY_OBJECT_TYPE_BIGINT, /**< type of ECMA_OBJECT_CLASS_BIGINT */ +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_WEAKREF + JERRY_OBJECT_TYPE_WEAKREF, /**< type of ECMA_OBJECT_CLASS_WEAKREF */ +#endif /* JERRY_BUILTIN_WEAKREF */ +}; + +JERRY_STATIC_ASSERT ((sizeof (jerry_class_object_type) == ECMA_OBJECT_CLASS__MAX), + jerry_class_object_type_must_have_object_class_max_elements); + +/** + * Get the object type of the given value + * + * @return JERRY_OBJECT_TYPE_NONE - if the given value is not an object + * jerry_object_type_t value - otherwise + */ +jerry_object_type_t +jerry_object_type (const jerry_value_t value) /**< input value to check */ +{ + if (!ecma_is_value_object (value)) + { + return JERRY_OBJECT_TYPE_NONE; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (value); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + switch (ecma_get_object_type (obj_p)) + { + case ECMA_OBJECT_TYPE_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + { + JERRY_ASSERT (ext_obj_p->u.cls.type < ECMA_OBJECT_CLASS__MAX); + return (jerry_object_type_t) jerry_class_object_type[ext_obj_p->u.cls.type]; + } + case ECMA_OBJECT_TYPE_ARRAY: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + return JERRY_OBJECT_TYPE_ARRAY; + } + case ECMA_OBJECT_TYPE_PROXY: + { + return JERRY_OBJECT_TYPE_PROXY; + } + case ECMA_OBJECT_TYPE_FUNCTION: + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + return JERRY_OBJECT_TYPE_FUNCTION; + } + default: + { + break; + } + } + + return JERRY_OBJECT_TYPE_GENERIC; +} /* jerry_object_type */ + +/** + * Get the function type of the given value + * + * @return JERRY_FUNCTION_TYPE_NONE - if the given value is not a function object + * jerry_function_type_t value - otherwise + */ +jerry_function_type_t +jerry_function_type (const jerry_value_t value) /**< input value to check */ +{ + if (ecma_is_value_object (value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + switch (ecma_get_object_type (obj_p)) + { + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + return JERRY_FUNCTION_TYPE_BOUND; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + return JERRY_FUNCTION_TYPE_GENERIC; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_obj_p); + + switch (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags)) + { + case CBC_FUNCTION_ARROW: + case CBC_FUNCTION_ASYNC_ARROW: + { + return JERRY_FUNCTION_TYPE_ARROW; + } + case CBC_FUNCTION_GENERATOR: + case CBC_FUNCTION_ASYNC_GENERATOR: + { + return JERRY_FUNCTION_TYPE_GENERATOR; + } + case CBC_FUNCTION_ACCESSOR: + { + return JERRY_FUNCTION_TYPE_ACCESSOR; + } + default: + { + break; + } + } + return JERRY_FUNCTION_TYPE_GENERIC; + } + default: + { + break; + } + } + } + + return JERRY_FUNCTION_TYPE_NONE; +} /* jerry_function_type */ + +/** + * Get the itearator type of the given value + * + * @return JERRY_ITERATOR_TYPE_NONE - if the given value is not an iterator object + * jerry_iterator_type_t value - otherwise + */ +jerry_iterator_type_t +jerry_iterator_type (const jerry_value_t value) /**< input value to check */ +{ + if (ecma_is_value_object (value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CLASS) + { + switch (ext_obj_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_ARRAY_ITERATOR: + { + return JERRY_ITERATOR_TYPE_ARRAY; + } +#if JERRY_BUILTIN_CONTAINER + case ECMA_OBJECT_CLASS_SET_ITERATOR: + { + return JERRY_ITERATOR_TYPE_SET; + } + case ECMA_OBJECT_CLASS_MAP_ITERATOR: + { + return JERRY_ITERATOR_TYPE_MAP; + } +#endif /* JERRY_BUILTIN_CONTAINER */ + case ECMA_OBJECT_CLASS_STRING_ITERATOR: + { + return JERRY_ITERATOR_TYPE_STRING; + } + default: + { + break; + } + } + } + } + + return JERRY_ITERATOR_TYPE_NONE; +} /* jerry_iterator_type */ + +/** + * Check if the specified feature is enabled. + * + * @return true - if the specified feature is enabled, + * false - otherwise + */ +bool +jerry_feature_enabled (const jerry_feature_t feature) /**< feature to check */ +{ + JERRY_ASSERT (feature < JERRY_FEATURE__COUNT); + + return (false +#if JERRY_CPOINTER_32_BIT + || feature == JERRY_FEATURE_CPOINTER_32_BIT +#endif /* JERRY_CPOINTER_32_BIT */ +#if JERRY_ERROR_MESSAGES + || feature == JERRY_FEATURE_ERROR_MESSAGES +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_PARSER + || feature == JERRY_FEATURE_JS_PARSER +#endif /* JERRY_PARSER */ +#if JERRY_PARSER_DUMP_BYTE_CODE + || feature == JERRY_FEATURE_PARSER_DUMP +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ +#if JERRY_REGEXP_DUMP_BYTE_CODE + || feature == JERRY_FEATURE_REGEXP_DUMP +#endif /* JERRY_REGEXP_DUMP_BYTE_CODE */ +#if JERRY_SNAPSHOT_SAVE + || feature == JERRY_FEATURE_SNAPSHOT_SAVE +#endif /* JERRY_SNAPSHOT_SAVE */ +#if JERRY_SNAPSHOT_EXEC + || feature == JERRY_FEATURE_SNAPSHOT_EXEC +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_VM_HALT + || feature == JERRY_FEATURE_VM_EXEC_STOP +#endif /* JERRY_VM_HALT */ +#if JERRY_VM_THROW + || feature == JERRY_FEATURE_VM_THROW +#endif /* JERRY_VM_THROW */ +#if JERRY_BUILTIN_TYPEDARRAY + || feature == JERRY_FEATURE_TYPEDARRAY +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATAVIEW + || feature == JERRY_FEATURE_DATAVIEW +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_PROXY + || feature == JERRY_FEATURE_PROXY +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_DATE + || feature == JERRY_FEATURE_DATE +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP + || feature == JERRY_FEATURE_REGEXP +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_LINE_INFO + || feature == JERRY_FEATURE_LINE_INFO +#endif /* JERRY_LINE_INFO */ +#if JERRY_LOGGING + || feature == JERRY_FEATURE_LOGGING +#endif /* JERRY_LOGGING */ +#if JERRY_BUILTIN_GLOBAL_THIS + || feature == JERRY_FEATURE_GLOBAL_THIS +#endif /* JERRY_BUILTIN_GLOBAL_THIS */ +#if JERRY_BUILTIN_CONTAINER + || feature == JERRY_FEATURE_MAP || feature == JERRY_FEATURE_SET || feature == JERRY_FEATURE_WEAKMAP + || feature == JERRY_FEATURE_WEAKSET +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_WEAKREF + || feature == JERRY_FEATURE_WEAKREF +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_BIGINT + || feature == JERRY_FEATURE_BIGINT +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_REALMS + || feature == JERRY_FEATURE_REALM +#endif /* JERRY_BUILTIN_REALMS */ +#if JERRY_MODULE_SYSTEM + || feature == JERRY_FEATURE_MODULE +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_FUNCTION_TO_STRING + || feature == JERRY_FEATURE_FUNCTION_TO_STRING +#endif /* JERRY_FUNCTION_TO_STRING */ + ); +} /* jerry_feature_enabled */ + +/** + * Perform binary operation on the given operands (==, ===, <, >, etc.). + * + * @return error - if argument has an error flag or operation is unsuccessful or unsupported + * true/false - the result of the binary operation on the given operands otherwise + */ +jerry_value_t +jerry_binary_op (jerry_binary_op_t operation, /**< operation */ + const jerry_value_t lhs, /**< first operand */ + const jerry_value_t rhs) /**< second operand */ +{ + if (ecma_is_value_exception (lhs) || ecma_is_value_exception (rhs)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + switch (operation) + { + case JERRY_BIN_OP_EQUAL: + { + return jerry_return (ecma_op_abstract_equality_compare (lhs, rhs)); + } + case JERRY_BIN_OP_STRICT_EQUAL: + { + return ecma_make_boolean_value (ecma_op_strict_equality_compare (lhs, rhs)); + } + case JERRY_BIN_OP_LESS: + { + return jerry_return (opfunc_relation (lhs, rhs, true, false)); + } + case JERRY_BIN_OP_LESS_EQUAL: + { + return jerry_return (opfunc_relation (lhs, rhs, false, true)); + } + case JERRY_BIN_OP_GREATER: + { + return jerry_return (opfunc_relation (lhs, rhs, false, false)); + } + case JERRY_BIN_OP_GREATER_EQUAL: + { + return jerry_return (opfunc_relation (lhs, rhs, true, true)); + } + case JERRY_BIN_OP_INSTANCEOF: + { + if (!ecma_is_value_object (lhs) || !ecma_op_is_callable (rhs)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *proto_obj_p = ecma_get_object_from_value (rhs); + return jerry_return (ecma_op_object_has_instance (proto_obj_p, lhs)); + } + case JERRY_BIN_OP_ADD: + { + return jerry_return (opfunc_addition (lhs, rhs)); + } + case JERRY_BIN_OP_SUB: + case JERRY_BIN_OP_MUL: + case JERRY_BIN_OP_DIV: + case JERRY_BIN_OP_REM: + { + return jerry_return (do_number_arithmetic ((number_arithmetic_op) ((int) operation - ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET), lhs, rhs)); + } + default: + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_UNSUPPORTED_BINARY_OPERATION)); + } + } +} /* jerry_binary_op */ + +/** + * Create an abort value containing the argument value. If the second argument is true + * the function will take ownership ofthe input value, otherwise the value will be copied. + * + * @return api abort value + */ +jerry_value_t +jerry_throw_abort (jerry_value_t value, /**< api value */ + bool take_ownership) /**< release api value */ +{ + if (JERRY_UNLIKELY (ecma_is_value_exception (value))) + { + /* This is a rare case so it is optimized for + * binary size rather than performance. */ + if (jerry_value_is_abort (value)) + { + return take_ownership ? value : jerry_value_copy (value); + } + + value = jerry_exception_value (value, take_ownership); + take_ownership = true; + } + + if (!take_ownership) + { + value = ecma_copy_value (value); + } + + return ecma_create_exception (value, ECMA_ERROR_API_FLAG_ABORT); +} /* jerry_throw_abort */ + +/** + * Create an exception value containing the argument value. If the second argument is true + * the function will take ownership ofthe input value, otherwise the value will be copied. + * + * @return exception value + */ +jerry_value_t +jerry_throw_value (jerry_value_t value, /**< value */ + bool take_ownership) /**< take ownership of the value */ +{ + if (JERRY_UNLIKELY (ecma_is_value_exception (value))) + { + /* This is a rare case so it is optimized for + * binary size rather than performance. */ + if (!jerry_value_is_abort (value)) + { + return take_ownership ? value : jerry_value_copy (value); + } + + value = jerry_exception_value (value, take_ownership); + take_ownership = true; + } + + if (!take_ownership) + { + value = ecma_copy_value (value); + } + + return ecma_create_exception (value, ECMA_ERROR_API_FLAG_NONE); +} /* jerry_throw_value */ + +/** + * Get the value contained in an exception. If the second argument is true + * it will release the argument exception value in the process. + * + * @return value in exception + */ +jerry_value_t +jerry_exception_value (jerry_value_t value, /**< api value */ + bool free_exception) /**< release api value */ +{ + if (!ecma_is_value_exception (value)) + { + return free_exception ? value : ecma_copy_value (value); + } + + jerry_value_t ret_val = jerry_value_copy (ecma_get_extended_primitive_from_value (value)->u.value); + + if (free_exception) + { + jerry_value_free (value); + } + return ret_val; +} /* jerry_exception_value */ + +/** + * Set new decorator callback for Error objects. The decorator can + * create or update any properties of the newly created Error object. + */ +void +jerry_error_on_created (jerry_error_object_created_cb_t callback, /**< new callback */ + void *user_p) /**< user pointer passed to the callback */ +{ + JERRY_CONTEXT (error_object_created_callback_p) = callback; + JERRY_CONTEXT (error_object_created_callback_user_p) = user_p; +} /* jerry_error_on_created */ + +/** + * When JERRY_VM_THROW is enabled, the callback passed to this + * function is called when an error is thrown in ECMAScript code. + */ +void +jerry_on_throw (jerry_throw_cb_t callback, /**< callback which is called on throws */ + void *user_p) /**< pointer passed to the function */ +{ +#if JERRY_VM_THROW + JERRY_CONTEXT (vm_throw_callback_p) = callback; + JERRY_CONTEXT (vm_throw_callback_user_p) = user_p; +#else /* !JERRY_VM_THROW */ + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); +#endif /* JERRY_VM_THROW */ +} /* jerry_on_throw */ + +/** + * Checks whether the callback set by jerry_on_throw captured the error + * + * @return true, if the vm throw callback captured the error + * false, otherwise + */ +bool +jerry_exception_is_captured (const jerry_value_t value) /**< exception value */ +{ +#if JERRY_VM_THROW + if (!ecma_is_value_exception (value)) + { + return false; + } + + ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); + + return (error_ref_p->refs_and_type & ECMA_ERROR_API_FLAG_THROW_CAPTURED) != 0; +#else /* !JERRY_VM_THROW */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_VM_THROW */ +} /* jerry_exception_is_captured */ + +/** + * Sets whether the callback set by jerry_on_throw should capture the exception or not + */ +void +jerry_exception_allow_capture (jerry_value_t value, /**< exception value */ + bool should_capture) /**< callback should capture this error */ +{ +#if JERRY_VM_THROW + if (!ecma_is_value_exception (value)) + { + return; + } + + ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); + + if (should_capture) + { + error_ref_p->refs_and_type &= ~(uint32_t) ECMA_ERROR_API_FLAG_THROW_CAPTURED; + return; + } + + error_ref_p->refs_and_type |= ECMA_ERROR_API_FLAG_THROW_CAPTURED; +#else /* !JERRY_VM_THROW */ + JERRY_UNUSED (value); + JERRY_UNUSED (should_capture); +#endif /* JERRY_VM_THROW */ +} /* jerry_exception_allow_capture */ + +/** + * Check if the given value is an Error object. + * + * @return true - if it is an Error object + * false - otherwise + */ +bool +jerry_value_is_error (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_object (value) + && ecma_object_class_is (ecma_get_object_from_value (value), ECMA_OBJECT_CLASS_ERROR); +} /* jerry_value_is_error */ + +/** + * Return the type of the Error object if possible. + * + * @return one of the jerry_error_t value as the type of the Error object + * JERRY_ERROR_NONE - if the input value is not an Error object + */ +jerry_error_t +jerry_error_type (jerry_value_t value) /**< api value */ +{ + if (JERRY_UNLIKELY (ecma_is_value_exception (value))) + { + value = ecma_get_extended_primitive_from_value (value)->u.value; + } + + if (!ecma_is_value_object (value)) + { + return JERRY_ERROR_NONE; + } + + ecma_object_t *object_p = ecma_get_object_from_value (value); + /* TODO(check if error object) */ + jerry_error_t error_type = ecma_get_error_type (object_p); + + return (jerry_error_t) error_type; +} /* jerry_error_type */ + +/** + * Get number from the specified value as a double. + * + * @return stored number as double + */ +double +jerry_value_as_number (const jerry_value_t value) /**< api value */ +{ + if (!ecma_is_value_number (value)) + { + return 0; + } + + return (double) ecma_get_number_from_value (value); +} /* jerry_value_as_number */ + +/** + * Call ToBoolean operation on the api value. + * + * @return true - if the logical value is true + * false - otherwise + */ +bool +jerry_value_to_boolean (const jerry_value_t value) /**< input value */ +{ + if (ecma_is_value_exception (value)) + { + return false; + } + + return ecma_op_to_boolean (value); +} /* jerry_value_to_boolean */ + +/** + * Call ToNumber operation on the api value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return converted number value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_number (const jerry_value_t value) /**< input value */ +{ + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + ecma_number_t num; + ecma_value_t ret_value = ecma_op_to_number (value, &num); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ecma_create_exception_from_context (); + } + + return ecma_make_number_value (num); +} /* jerry_value_to_number */ + +/** + * Call ToObject operation on the api value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return converted object value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_object (const jerry_value_t value) /**< input value */ +{ + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + return jerry_return (ecma_op_to_object (value)); +} /* jerry_value_to_object */ + +/** + * Call ToPrimitive operation on the api value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return converted primitive value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_primitive (const jerry_value_t value) /**< input value */ +{ + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + return jerry_return (ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NO)); +} /* jerry_value_to_primitive */ + +/** + * Call the ToString ecma builtin operation on the api value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return converted string value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_string (const jerry_value_t value) /**< input value */ +{ + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + ecma_string_t *str_p = ecma_op_to_string (value); + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ecma_create_exception_from_context (); + } + + return ecma_make_string_value (str_p); +} /* jerry_value_to_string */ + +/** + * Call the BigInt constructor ecma builtin operation on the api value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return BigInt value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_bigint (const jerry_value_t value) /**< input value */ +{ +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + return jerry_return (ecma_bigint_to_bigint (value, true)); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (value); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_BIGINT_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* jerry_value_to_bigint */ + +/** + * Convert any number to integer number. + * + * Note: + * For non-number values 0 is returned. + * + * @return integer representation of the number. + */ +double +jerry_value_as_integer (const jerry_value_t value) /**< input value */ +{ + if (!ecma_is_value_number (value)) + { + return 0; + } + + double number = ecma_get_number_from_value (value); + + if (ecma_number_is_nan (number)) + { + return ECMA_NUMBER_ZERO; + } + + if (ecma_number_is_zero (number) || ecma_number_is_infinity (number)) + { + return number; + } + + ecma_number_t floor_fabs = (ecma_number_t) floor (fabs (number)); + + return ecma_number_is_negative (number) ? -floor_fabs : floor_fabs; +} /* jerry_value_as_integer */ + +/** + * Convert any number to int32 number. + * + * Note: + * For non-number values 0 is returned. + * + * @return int32 representation of the number. + */ +int32_t +jerry_value_as_int32 (const jerry_value_t value) /**< input value */ +{ + if (!ecma_is_value_number (value)) + { + return 0; + } + + return ecma_number_to_int32 (ecma_get_number_from_value (value)); +} /* jerry_value_as_int32 */ + +/** + * Convert any number to uint32 number. + * + * Note: + * For non-number values 0 is returned. + * + * @return uint32 representation of the number. + */ +uint32_t +jerry_value_as_uint32 (const jerry_value_t value) /**< input value */ +{ + if (!ecma_is_value_number (value)) + { + return 0; + } + + return ecma_number_to_uint32 (ecma_get_number_from_value (value)); +} /* jerry_value_as_uint32 */ + +/** + * Take additional ownership over the argument value. + * The value will be copied by reference when possible, changes made to the new value will be reflected + * in the original. + * + * @return copied value + */ +jerry_value_t +jerry_value_copy (const jerry_value_t value) /**< value */ +{ + if (JERRY_UNLIKELY (ecma_is_value_exception (value))) + { + ecma_ref_extended_primitive (ecma_get_extended_primitive_from_value (value)); + return value; + } + + return ecma_copy_value (value); +} /* jerry_value_copy */ + +/** + * Release ownership of the argument value + */ +void +jerry_value_free (jerry_value_t value) /**< value */ +{ + if (JERRY_UNLIKELY (ecma_is_value_exception (value))) + { + ecma_deref_exception (ecma_get_extended_primitive_from_value (value)); + return; + } + + ecma_free_value (value); +} /* jerry_value_free */ + +/** + * Create an array object value + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the constructed array object + */ +jerry_value_t +jerry_array (jerry_length_t length) /**< length of array */ +{ + ecma_object_t *array_p = ecma_op_new_array_object (length); + return ecma_make_object_value (array_p); +} /* jerry_array */ + +/** + * Create a jerry_value_t representing a boolean value from the given boolean parameter. + * + * @return value of the created boolean + */ +jerry_value_t +jerry_boolean (bool value) /**< bool value from which a jerry_value_t will be created */ +{ + return ecma_make_boolean_value (value); +} /* jerry_boolean */ + +/** + * Create an Error object with the provided string value as the error message. + * If the message value is not a string, the created error will not have a message property. + * + * @return Error object + */ +jerry_value_t +jerry_error (jerry_error_t error_type, /**< type of error */ + const jerry_value_t message) /**< message of the error */ +{ + ecma_string_t *message_p = NULL; + if (ecma_is_value_string (message)) + { + message_p = ecma_get_string_from_value (message); + } + + ecma_object_t *error_object_p = ecma_new_standard_error ((jerry_error_t) error_type, message_p); + + return ecma_make_object_value (error_object_p); +} /* jerry_error */ + +/** + * Create an Error object with a zero-terminated string as a message. If the message string is NULL, the created error + * will not have a message property. + * + * @return Error object + */ +jerry_value_t +jerry_error_sz (jerry_error_t error_type, /**< type of error */ + const char *message_p) /**< value of 'message' property + * of constructed error object */ +{ + jerry_value_t message = ECMA_VALUE_UNDEFINED; + + if (message_p != NULL) + { + message = jerry_string_sz (message_p); + } + + ecma_value_t error = jerry_error (error_type, message); + ecma_free_value (message); + + return error; +} /* jerry_error_sz */ + +/** + * Create an exception by constructing an Error object with the specified type and the provided string value as the + * error message. If the message value is not a string, the created error will not have a message property. + * + * @return exception value + */ +jerry_value_t +jerry_throw (jerry_error_t error_type, /**< type of error */ + const jerry_value_t message) /**< message value */ +{ + return jerry_throw_value (jerry_error (error_type, message), true); +} /* jerry_throw */ + +/** + * Create an exception by constructing an Error object with the specified type and the provided zero-terminated ASCII + * string as the error message. If the message string is NULL, the created error will not have a message property. + * + * @return exception value + */ +jerry_value_t +jerry_throw_sz (jerry_error_t error_type, /**< type of error */ + const char *message_p) /**< value of 'message' property + * of constructed error object */ +{ + return jerry_throw_value (jerry_error_sz (error_type, message_p), true); +} /* jerry_throw_sz */ + +/** + * Create an external function object + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the constructed function object + */ +jerry_value_t +jerry_function_external (jerry_external_handler_t handler) /**< native handler + * for the function */ +{ + ecma_object_t *func_obj_p = ecma_op_create_external_function_object (handler); + return ecma_make_object_value (func_obj_p); +} /* jerry_function_external */ + +/** + * Creates a jerry_value_t representing a number value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return jerry_value_t created from the given double argument. + */ +jerry_value_t +jerry_number (double value) /**< double value from which a jerry_value_t will be created */ +{ + return ecma_make_number_value ((ecma_number_t) value); +} /* jerry_number */ + +/** + * Creates a jerry_value_t representing a positive or negative infinity value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return jerry_value_t representing an infinity value. + */ +jerry_value_t +jerry_infinity (bool sign) /**< true for negative Infinity + * false for positive Infinity */ +{ + return ecma_make_number_value (ecma_number_make_infinity (sign)); +} /* jerry_infinity */ + +/** + * Creates a jerry_value_t representing a not-a-number value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return jerry_value_t representing a not-a-number value. + */ +jerry_value_t +jerry_nan (void) +{ + return ecma_make_nan_value (); +} /* jerry_nan */ + +/** + * Creates a jerry_value_t representing an undefined value. + * + * @return value of undefined + */ +jerry_value_t +jerry_undefined (void) +{ + return ECMA_VALUE_UNDEFINED; +} /* jerry_undefined */ + +/** + * Creates and returns a jerry_value_t with type null object. + * + * @return jerry_value_t representing null + */ +jerry_value_t +jerry_null (void) +{ + return ECMA_VALUE_NULL; +} /* jerry_null */ + +/** + * Create new JavaScript object, like with new Object(). + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the created object + */ +jerry_value_t +jerry_object (void) +{ + return ecma_make_object_value (ecma_op_create_object_object_noarg ()); +} /* jerry_object */ + +/** + * Create an empty Promise object which can be resolved/rejected later + * by calling jerry_promise_resolve or jerry_promise_reject. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the created object + */ +jerry_value_t +jerry_promise (void) +{ + return jerry_return (ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL)); +} /* jerry_create_promise */ + +/** + * Create a new Proxy object with the given target and handler + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the created Proxy object + */ +jerry_value_t +jerry_proxy (const jerry_value_t target, /**< target argument */ + const jerry_value_t handler) /**< handler argument */ +{ + if (ecma_is_value_exception (target) || ecma_is_value_exception (handler)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + +#if JERRY_BUILTIN_PROXY + ecma_object_t *proxy_p = ecma_proxy_create (target, handler, 0); + + if (proxy_p == NULL) + { + return ecma_create_exception_from_context (); + } + + return ecma_make_object_value (proxy_p); +#else /* !JERRY_BUILTIN_PROXY */ + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_PROXY_IS_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_PROXY */ +} /* jerry_proxy */ + +#if JERRY_BUILTIN_PROXY + +JERRY_STATIC_ASSERT (((int) JERRY_PROXY_SKIP_RESULT_VALIDATION == (int) ECMA_PROXY_SKIP_RESULT_VALIDATION), + jerry_and_ecma_proxy_skip_result_validation_must_be_equal); + +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * Create a new Proxy object with the given target, handler, and special options + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the created Proxy object + */ +jerry_value_t +jerry_proxy_custom (const jerry_value_t target, /**< target argument */ + const jerry_value_t handler, /**< handler argument */ + uint32_t flags) /**< jerry_proxy_custom_behavior_t option bits */ +{ + if (ecma_is_value_exception (target) || ecma_is_value_exception (handler)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + +#if JERRY_BUILTIN_PROXY + flags &= JERRY_PROXY_SKIP_RESULT_VALIDATION; + + ecma_object_t *proxy_p = ecma_proxy_create (target, handler, flags); + + if (proxy_p == NULL) + { + return ecma_create_exception_from_context (); + } + + return ecma_make_object_value (proxy_p); +#else /* !JERRY_BUILTIN_PROXY */ + JERRY_UNUSED (flags); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_PROXY_IS_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_PROXY */ +} /* jerry_proxy_custom */ + +/** + * Create string value from the input zero-terminated ASCII string. + * + * @return created string + */ +jerry_value_t +jerry_string_sz (const char *str_p) /**< pointer to string */ +{ + const jerry_char_t *data_p = (const jerry_char_t *) str_p; + return jerry_string (data_p, lit_zt_utf8_string_size (data_p), JERRY_ENCODING_CESU8); +} /* jerry_string_sz */ + +/** + * Create a string value from the input buffer using the specified encoding. + * The content of the buffer is assumed to be valid in the specified encoding, it's the callers responsibility to + * validate the input. + * + * See also: jerry_validate_string + * + * @return created string + */ +jerry_value_t +jerry_string (const jerry_char_t *buffer_p, /**< pointer to buffer */ + jerry_size_t buffer_size, /**< buffer size */ + jerry_encoding_t encoding) /**< buffer encoding */ +{ + ecma_string_t *ecma_str_p = NULL; + JERRY_ASSERT (jerry_validate_string (buffer_p, buffer_size, encoding)); + + switch (encoding) + { + case JERRY_ENCODING_CESU8: + { + ecma_str_p = ecma_new_ecma_string_from_utf8 (buffer_p, buffer_size); + break; + } + case JERRY_ENCODING_UTF8: + { + ecma_str_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (buffer_p, buffer_size); + break; + } + default: + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INVALID_ENCODING)); + } + } + + return ecma_make_string_value (ecma_str_p); +} /* jerry_string */ + +/** + * Create external string from input zero-terminated ASCII string. + * + * @return created external string + */ +jerry_value_t +jerry_string_external_sz (const char *str_p, /**< pointer to string */ + void *user_p) /**< user pointer passed to the callback when the string is freed */ +{ + const jerry_char_t *data_p = (const jerry_char_t *) str_p; + return jerry_string_external (data_p, lit_zt_utf8_string_size (data_p), user_p); +} /* jerry_string_external_sz */ + +/** + * Create external string from a valid CESU-8 encoded string. + * The content of the buffer is assumed be encoded correctly, it's the callers responsibility to + * validate the input. + * + * See also: jerry_validate_string + * + * @return created external string + */ +jerry_value_t +jerry_string_external (const jerry_char_t *buffer_p, /**< pointer to string */ + jerry_size_t buffer_size, /**< string size */ + void *user_p) /**< user pointer passed to the callback when the string is freed */ +{ + JERRY_ASSERT (jerry_validate_string (buffer_p, buffer_size, JERRY_ENCODING_CESU8)); + ecma_string_t *ecma_str_p = ecma_new_ecma_external_string_from_cesu8 (buffer_p, buffer_size, user_p); + return ecma_make_string_value (ecma_str_p); +} /* jerry_string_external_sz_sz */ + +/** + * Create symbol with a description value + * + * Note: The given argument is converted to string. This operation can throw an exception. + * + * @return created symbol, + * or thrown exception + */ +jerry_value_t +jerry_symbol_with_description (const jerry_value_t value) /**< api value */ +{ + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + return jerry_return (ecma_op_create_symbol (&value, 1)); +} /* jerry_create_symbol */ + +/** + * Create BigInt from a sequence of uint64 digits. + * + * Note: This operation can throw an exception. + * + * @return created bigint, + * or thrown exception + */ +jerry_value_t +jerry_bigint (const uint64_t *digits_p, /**< BigInt digits (lowest digit first) */ + uint32_t digit_count, /**< number of BigInt digits */ + bool sign) /**< sign bit, true if the result should be negative */ +{ +#if JERRY_BUILTIN_BIGINT + return jerry_return (ecma_bigint_create_from_digits (digits_p, digit_count, sign)); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (digits_p); + JERRY_UNUSED (digit_count); + JERRY_UNUSED (sign); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_BIGINT_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* jerry_bigint */ + +/** + * Creates a RegExp object with the given ASCII pattern and flags. + * + * @return value of the constructed RegExp object. + */ +jerry_value_t +jerry_regexp_sz (const char *pattern_p, /**< RegExp pattern as zero-terminated ASCII string */ + uint16_t flags) /**< RegExp flags */ +{ + jerry_value_t pattern = jerry_string_sz (pattern_p); + jerry_value_t result = jerry_regexp (pattern, flags); + + jerry_value_free (pattern); + return jerry_return (result); +} /* jerry_regexp_sz */ + +/** + * Creates a RegExp object with the given pattern and flags. + * + * @return value of the constructed RegExp object. + */ +jerry_value_t +jerry_regexp (const jerry_value_t pattern, /**< pattern string */ + uint16_t flags) /**< RegExp flags */ +{ +#if JERRY_BUILTIN_REGEXP + if (!ecma_is_value_string (pattern)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL); + + if (JERRY_UNLIKELY (regexp_obj_p == NULL)) + { + return ecma_create_exception_from_context (); + } + + jerry_value_t result = ecma_op_create_regexp_with_flags (regexp_obj_p, pattern, flags); + + return jerry_return (result); + +#else /* !JERRY_BUILTIN_REGEXP */ + JERRY_UNUSED (pattern); + JERRY_UNUSED (flags); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_REGEXP_IS_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_REGEXP */ +} /* jerry_regexp */ + +/** + * Creates a new realm (global object). + * + * @return new realm object + */ +jerry_value_t +jerry_realm (void) +{ +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *global_object_p = ecma_builtin_create_global_object (); + return ecma_make_object_value ((ecma_object_t *) global_object_p); +#else /* !JERRY_BUILTIN_REALMS */ + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_REALMS_ARE_DISABLED)); +#endif /* JERRY_BUILTIN_REALMS */ +} /* jerry_realm */ + +/** + * Get length of an array object + * + * Note: + * Returns 0, if the value parameter is not an array object. + * + * @return length of the given array + */ +jerry_length_t +jerry_array_length (const jerry_value_t value) /**< api value */ +{ + if (!jerry_value_is_object (value)) + { + return 0; + } + + ecma_object_t *object_p = ecma_get_object_from_value (value); + + if (JERRY_LIKELY (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY)) + { + return ecma_array_get_length (object_p); + } + + return 0; +} /* jerry_array_length */ + +/** + * Get the size of a string value in the specified encoding. + * + * @return number of bytes required by the string, + * 0 - if value is not a string + */ +jerry_size_t +jerry_string_size (const jerry_value_t value, /**< input string */ + jerry_encoding_t encoding) /**< encoding */ +{ + if (!ecma_is_value_string (value)) + { + return 0; + } + + switch (encoding) + { + case JERRY_ENCODING_CESU8: + { + return ecma_string_get_size (ecma_get_string_from_value (value)); + } + case JERRY_ENCODING_UTF8: + { + return ecma_string_get_utf8_size (ecma_get_string_from_value (value)); + } + default: + { + return 0; + } + } +} /* jerry_string_size */ + +/** + * Get length of a string value + * + * @return number of characters in the string + * 0 - if value is not a string + */ +jerry_length_t +jerry_string_length (const jerry_value_t value) /**< input string */ +{ + if (!ecma_is_value_string (value)) + { + return 0; + } + + return ecma_string_get_length (ecma_get_string_from_value (value)); +} /* jerry_string_length */ + +/** + * Copy the characters of a string into the specified buffer using the specified encoding. The string is truncated to + * fit the buffer. If the value is not a string, nothing will be copied to the buffer. + * + * @return number of bytes copied to the buffer + */ +jerry_size_t +jerry_string_to_buffer (const jerry_value_t value, /**< input string value */ + jerry_encoding_t encoding, /**< output encoding */ + jerry_char_t *buffer_p, /**< [out] output characters buffer */ + jerry_size_t buffer_size) /**< size of output buffer */ +{ + if (!ecma_is_value_string (value) || buffer_p == NULL) + { + return 0; + } + + ecma_string_t *str_p = ecma_get_string_from_value (value); + + return ecma_string_copy_to_buffer (str_p, (lit_utf8_byte_t *) buffer_p, buffer_size, encoding); +} /* jerry_string_to_char_buffer */ + +/** + * Create a substring of the input string value. + * Return an empty string if input value is not a string. + * + * @param value the input string value + * @param start start position of the substring + * @param end end position of the substring + * + * @return created string + */ +jerry_value_t +jerry_string_substr (const jerry_value_t value, jerry_length_t start, jerry_length_t end) +{ + if (!ecma_is_value_string (value)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + return ecma_make_string_value (ecma_string_substr (ecma_get_string_from_value (value), start, end)); +} /* jerry_string_substr */ + +/** + * Iterate over the input string value in the specified encoding, visiting each unit of the encoded string once. If + * the input value is not a string, the function will do nothing. + * + * @param value the input string value + * @param callback callback function called for each byte of the encoded string. + * @param encoding the requested encoding for the string + * @param user_p User pointer passed to the callback function + */ +void +jerry_string_iterate (const jerry_value_t value, + jerry_encoding_t encoding, + jerry_string_iterate_cb_t callback, + void *user_p) +{ + if (!ecma_is_value_string (value)) + { + return; + } + + ecma_string_t *str_p = ecma_get_string_from_value (value); + ECMA_STRING_TO_UTF8_STRING (str_p, buffer_p, buffer_size); + + const lit_utf8_byte_t *current_p = buffer_p; + const lit_utf8_byte_t *end_p = buffer_p + buffer_size; + + switch (encoding) + { + case JERRY_ENCODING_UTF8: + { + while (current_p < end_p) + { + if (JERRY_UNLIKELY (*current_p >= LIT_UTF8_3_BYTE_MARKER)) + { + lit_code_point_t cp; + lit_utf8_size_t read_size = lit_read_code_point_from_cesu8 (current_p, end_p, &cp); + + lit_utf8_byte_t bytes[LIT_UTF8_MAX_BYTES_IN_CODE_POINT]; + lit_utf8_size_t encoded_size = lit_code_point_to_utf8 (cp, bytes); + + for (uint32_t i = 0; i < encoded_size; i++) + { + callback (bytes[i], user_p); + } + + current_p += read_size; + continue; + } + + callback (*current_p++, user_p); + } + + break; + } + case JERRY_ENCODING_CESU8: + { + while (current_p < end_p) + { + callback (*current_p++, user_p); + } + + break; + } + default: + { + break; + } + } + ECMA_FINALIZE_UTF8_STRING (buffer_p, buffer_size); +} /* jerry_string_iterate */ + +/** + * Sets the global callback which is called when an external string is freed. + */ +void +jerry_string_external_on_free (jerry_external_string_free_cb_t callback) /**< free callback */ +{ + JERRY_CONTEXT (external_string_free_callback_p) = callback; +} /* jerry_string_external_on_free */ + +/** + * Returns the user pointer assigned to an external string. + * + * @return user pointer, if value is an external string + * NULL, otherwise + */ +void * +jerry_string_user_ptr (const jerry_value_t value, /**< string value */ + bool *is_external) /**< [out] true - if value is an external string, + * false - otherwise */ +{ + if (is_external != NULL) + { + *is_external = false; + } + + if (!ecma_is_value_string (value)) + { + return NULL; + } + + ecma_string_t *string_p = ecma_get_string_from_value (value); + + if (ECMA_IS_DIRECT_STRING (string_p) + || ECMA_STRING_GET_CONTAINER (string_p) != ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING) + { + return NULL; + } + + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + + if (long_string_p->string_p == ECMA_LONG_STRING_BUFFER_START (long_string_p)) + { + return NULL; + } + + if (is_external != NULL) + { + *is_external = true; + } + + return ((ecma_external_string_t *) string_p)->user_p; +} /* jerry_string_user_ptr */ + +/** + * Checks whether the object or it's prototype objects have the given property. + * + * @return raised error - if the operation fail + * true/false API value - depend on whether the property exists + */ +jerry_value_t +jerry_object_has (const jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name (string value) */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return ECMA_VALUE_FALSE; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (key); + + return jerry_return (ecma_op_object_has_property (obj_p, prop_name_p)); +} /* jerry_object_has */ + +/** + * Checks whether the object or it's prototype objects have the given property. + * + * @return raised error - if the operation fail + * true/false API value - depend on whether the property exists + */ +jerry_value_t +jerry_object_has_sz (const jerry_value_t object, /**< object value */ + const char *key_p) /**< property key */ +{ + jerry_value_t key_str = jerry_string_sz (key_p); + jerry_value_t result = jerry_object_has (object, key_str); + ecma_free_value (key_str); + + return result; +} /* jerry_object_has */ + +/** + * Checks whether the object has the given property. + * + * @return ECMA_VALUE_ERROR - if the operation raises error + * ECMA_VALUE_{TRUE, FALSE} - based on whether the property exists + */ +jerry_value_t +jerry_object_has_own (const jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name (string value) */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return ECMA_VALUE_FALSE; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (key); + + return jerry_return (ecma_op_object_has_own_property (obj_p, prop_name_p)); +} /* jerry_has_own_property */ + +/** + * Checks whether the object has the given internal property. + * + * @return true - if the internal property exists + * false - otherwise + */ +bool +jerry_object_has_internal (const jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name value */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return false; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + + ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL); + + if (ecma_op_object_is_fast_array (obj_p)) + { + return false; + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p); + + if (property_p == NULL) + { + return false; + } + + ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (key)); + + return property_p != NULL; +} /* jerry_object_has_internal */ + +/** + * Delete a property from an object. + * + * @return boolean value - wether the property was deleted successfully + * exception - otherwise + */ +jerry_value_t +jerry_object_delete (jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name (string value) */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return false; + } + + return ecma_op_object_delete (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key), false); +} /* jerry_object_delete */ + +/** + * Delete a property from an object. + * + * @return boolean value - wether the property was deleted successfully + * exception - otherwise + */ +jerry_value_t +jerry_object_delete_sz (jerry_value_t object, /**< object value */ + const char *key_p) /**< property key */ +{ + jerry_value_t key_str = jerry_string_sz (key_p); + jerry_value_t result = jerry_object_delete (object, key_str); + ecma_free_value (key_str); + + return result; +} /* jerry_object_delete */ + +/** + * Delete indexed property from the specified object. + * + * @return boolean value - wether the property was deleted successfully + * false - otherwise + */ +jerry_value_t +jerry_object_delete_index (jerry_value_t object, /**< object value */ + uint32_t index) /**< index to be written */ +{ + if (!ecma_is_value_object (object)) + { + return false; + } + + ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 (index); + ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (object), str_idx_p, false); + ecma_deref_ecma_string (str_idx_p); + + return ret_value; +} /* jerry_object_delete_index */ + +/** + * Delete an internal property from an object. + * + * @return true - if property was deleted successfully + * false - otherwise + */ +bool +jerry_object_delete_internal (jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name value */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return false; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + + ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL); + + if (ecma_op_object_is_fast_array (obj_p)) + { + return true; + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p); + + if (property_p == NULL) + { + return true; + } + + ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (key)); + + if (property_p == NULL) + { + return true; + } + + ecma_delete_property (internal_object_p, ECMA_PROPERTY_VALUE_PTR (property_p)); + + return true; +} /* jerry_object_delete_internal */ + +/** + * Get value of a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the property - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_get (const jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name (string value) */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + jerry_value_t ret_value = + ecma_op_object_get (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key)); + return jerry_return (ret_value); +} /* jerry_object_get */ + +/** + * Get value of a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the property - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_get_sz (const jerry_value_t object, /**< object value */ + const char *key_p) /**< property key */ +{ + jerry_value_t key_str = jerry_string_sz (key_p); + jerry_value_t result = jerry_object_get (object, key_str); + ecma_free_value (key_str); + + return result; +} /* jerry_object_get */ + +/** + * Get value by an index from the specified object. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the property specified by the index - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_get_index (const jerry_value_t object, /**< object value */ + uint32_t index) /**< index to be written */ +{ + if (!ecma_is_value_object (object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_value_t ret_value = ecma_op_object_get_by_index (ecma_get_object_from_value (object), index); + + return jerry_return (ret_value); +} /* jerry_object_get_index */ + +/** + * Get the own property value of an object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the property - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_find_own (const jerry_value_t object, /**< object value */ + const jerry_value_t key, /**< property name (string value) */ + const jerry_value_t receiver, /**< receiver object value */ + bool *found_p) /**< [out] true, if the property is found + * or object is a Proxy object, false otherwise */ +{ + if (found_p != NULL) + { + *found_p = false; + } + + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key) || !ecma_is_value_object (receiver)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *object_p = ecma_get_object_from_value (object); + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (key); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + if (found_p != NULL) + { + *found_p = true; + } + + return jerry_return (ecma_proxy_object_get (object_p, property_name_p, receiver)); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t ret_value = ecma_op_object_find_own (receiver, object_p, property_name_p); + + if (ecma_is_value_found (ret_value)) + { + if (found_p != NULL) + { + *found_p = true; + } + + return jerry_return (ret_value); + } + + return ECMA_VALUE_UNDEFINED; +} /* jerry_object_find_own */ + +/** + * Get value of an internal property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the internal property - if the internal property exists + * undefined value - if the internal does not property exists + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_get_internal (const jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name value */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + + ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL); + + if (ecma_op_object_is_fast_array (obj_p)) + { + return jerry_return (ECMA_VALUE_UNDEFINED); + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p); + + if (property_p == NULL) + { + return jerry_return (ECMA_VALUE_UNDEFINED); + } + + ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (key)); + + if (property_p == NULL) + { + return jerry_return (ECMA_VALUE_UNDEFINED); + } + + return jerry_return (ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value)); +} /* jerry_object_get_internal */ + +/** + * Set a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_set (jerry_value_t object, /**< object value */ + const jerry_value_t key, /**< property name (string value) */ + const jerry_value_t value) /**< value to set */ +{ + if (ecma_is_value_exception (value) || !ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + return jerry_return ( + ecma_op_object_put (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key), value, true)); +} /* jerry_object_set */ + +/** + * Set a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_set_sz (jerry_value_t object, /**< object value */ + const char *key_p, /**< property key */ + const jerry_value_t value) /**< value to set */ +{ + jerry_value_t key_str = jerry_string_sz (key_p); + jerry_value_t result = jerry_object_set (object, key_str, value); + ecma_free_value (key_str); + + return result; +} /* jerry_object_set */ + +/** + * Set indexed value in the specified object + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_set_index (jerry_value_t object, /**< object value */ + uint32_t index, /**< index to be written */ + const jerry_value_t value) /**< value to set */ +{ + if (ecma_is_value_exception (value) || !ecma_is_value_object (object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_value_t ret_value = ecma_op_object_put_by_index (ecma_get_object_from_value (object), index, value, true); + + return jerry_return (ret_value); +} /* jerry_object_set_index */ + +/** + * Set an internal property to the specified object with the given name. + * + * Note: + * - the property cannot be accessed from the JavaScript context, only from the public API + * - returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * value marked with error flag - otherwise + */ +bool +jerry_object_set_internal (jerry_value_t object, /**< object value */ + const jerry_value_t key, /**< property name value */ + const jerry_value_t value) /**< value to set */ +{ + if (ecma_is_value_exception (value) || !ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return false; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + + ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL); + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_fast_array_convert_to_normal (obj_p); + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p); + ecma_object_t *internal_object_p; + + if (property_p == NULL) + { + ecma_property_value_t *value_p = + ecma_create_named_data_property (obj_p, internal_string_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + + internal_object_p = ecma_create_object (NULL, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + { + ecma_extended_object_t *container_p = (ecma_extended_object_t *) internal_object_p; + container_p->u.cls.type = ECMA_OBJECT_CLASS_INTERNAL_OBJECT; + } + + value_p->value = ecma_make_object_value (internal_object_p); + ecma_deref_object (internal_object_p); + } + else + { + internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + } + + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (key); + property_p = ecma_find_named_property (internal_object_p, prop_name_p); + + if (property_p == NULL) + { + ecma_property_value_t *value_p = ecma_create_named_data_property (internal_object_p, + prop_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + value_p->value = ecma_copy_value_if_not_object (value); + } + else + { + ecma_named_data_property_assign_value (internal_object_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); + } + + return true; +} /* jerry_object_set_internal */ + +/** + * Construct empty property descriptor, i.e.: + * property descriptor with all is_defined flags set to false and the rest - to default value. + * + * @return empty property descriptor + */ +jerry_property_descriptor_t +jerry_property_descriptor (void) +{ + jerry_property_descriptor_t prop_desc; + + prop_desc.flags = JERRY_PROP_NO_OPTS; + prop_desc.value = ECMA_VALUE_UNDEFINED; + prop_desc.getter = ECMA_VALUE_UNDEFINED; + prop_desc.setter = ECMA_VALUE_UNDEFINED; + + return prop_desc; +} /* jerry_property_descriptor */ + +/** + * Convert a ecma_property_descriptor_t to a jerry_property_descriptor_t + * + * if error occurs the property descriptor's value field is filled with ECMA_VALUE_ERROR + * + * @return jerry_property_descriptor_t + */ +static jerry_property_descriptor_t +jerry_property_descriptor_from_ecma (const ecma_property_descriptor_t *prop_desc_p) /**<[out] property_descriptor */ +{ + jerry_property_descriptor_t prop_desc = jerry_property_descriptor (); + + prop_desc.flags = prop_desc_p->flags; + + if (prop_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED)) + { + prop_desc.value = prop_desc_p->value; + } + + if (prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + prop_desc.getter = ECMA_VALUE_NULL; + + if (prop_desc_p->get_p != NULL) + { + prop_desc.getter = ecma_make_object_value (prop_desc_p->get_p); + JERRY_ASSERT (ecma_op_is_callable (prop_desc.getter)); + } + } + + if (prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + prop_desc.setter = ECMA_VALUE_NULL; + + if (prop_desc_p->set_p != NULL) + { + prop_desc.setter = ecma_make_object_value (prop_desc_p->set_p); + JERRY_ASSERT (ecma_op_is_callable (prop_desc.setter)); + } + } + + return prop_desc; +} /* jerry_property_descriptor_from_ecma */ + +/** + * Convert a jerry_property_descriptor_t to a ecma_property_descriptor_t + * + * Note: + * if error occurs the property descriptor's value field + * is set to ECMA_VALUE_ERROR, but no error is thrown + * + * @return ecma_property_descriptor_t + */ +static ecma_property_descriptor_t +jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_p) /**< input property_descriptor */ +{ + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + + prop_desc.flags = prop_desc_p->flags; + + /* Copy data property info. */ + if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + if (ecma_is_value_exception (prop_desc_p->value) + || (prop_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED))) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + + prop_desc.value = prop_desc_p->value; + } + + /* Copy accessor property info. */ + if (prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + ecma_value_t getter = prop_desc_p->getter; + + if (ecma_is_value_exception (getter)) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + + if (ecma_op_is_callable (getter)) + { + prop_desc.get_p = ecma_get_object_from_value (getter); + } + else if (!ecma_is_value_null (getter)) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + } + + if (prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + ecma_value_t setter = prop_desc_p->setter; + + if (ecma_is_value_exception (setter)) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + + if (ecma_op_is_callable (setter)) + { + prop_desc.set_p = ecma_get_object_from_value (setter); + } + else if (!ecma_is_value_null (setter)) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + } + + const uint16_t configurable_mask = JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED; + const uint16_t enumerable_mask = JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_ENUMERABLE_DEFINED; + const uint16_t writable_mask = JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED; + + if ((prop_desc_p->flags & configurable_mask) == JERRY_PROP_IS_CONFIGURABLE + || (prop_desc_p->flags & enumerable_mask) == JERRY_PROP_IS_ENUMERABLE + || (prop_desc_p->flags & writable_mask) == JERRY_PROP_IS_WRITABLE) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + + prop_desc.flags |= (uint16_t) (prop_desc_p->flags | JERRY_PROP_SHOULD_THROW); + + return prop_desc; +} /* jerry_property_descriptor_to_ecma */ + +/** Helper function to return false value or error depending on the given flag. + * + * @return value marked with error flag - if is_throw is true + * false value - otherwise + */ +static jerry_value_t +jerry_type_error_or_false (ecma_error_msg_t msg, /**< message */ + uint16_t flags) /**< property descriptor flags */ +{ + if (!(flags & JERRY_PROP_SHOULD_THROW)) + { + return ECMA_VALUE_FALSE; + } + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (msg)); +} /* jerry_type_error_or_false */ + +/** + * Define a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * false value - if the property cannot be defined and JERRY_PROP_SHOULD_THROW is not set + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_define_own_prop (jerry_value_t object, /**< object value */ + const jerry_value_t key, /**< property name (string value) */ + const jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return jerry_type_error_or_false (ECMA_ERR_WRONG_ARGS_MSG, prop_desc_p->flags); + } + + if (prop_desc_p->flags & (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_VALUE_DEFINED) + && prop_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + return jerry_type_error_or_false (ECMA_ERR_WRONG_ARGS_MSG, prop_desc_p->flags); + } + + ecma_property_descriptor_t prop_desc = jerry_property_descriptor_to_ecma (prop_desc_p); + + if (ECMA_IS_VALUE_ERROR (prop_desc.value)) + { + return jerry_type_error_or_false (ECMA_ERR_WRONG_ARGS_MSG, prop_desc_p->flags); + } + + return jerry_return (ecma_op_object_define_own_property (ecma_get_object_from_value (object), + ecma_get_prop_name_from_value (key), + &prop_desc)); +} /* jerry_object_define_own_prop */ + +/** + * Construct property descriptor from specified property. + * + * @return true - if success, the prop_desc_p fields contains the property info + * false - otherwise, the prop_desc_p is unchanged + */ +jerry_value_t +jerry_object_get_own_prop (const jerry_value_t object, /**< object value */ + const jerry_value_t key, /**< property name (string value) */ + jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return ECMA_VALUE_FALSE; + } + + ecma_property_descriptor_t prop_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (object), + ecma_get_prop_name_from_value (key), + &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + return ecma_create_exception_from_context (); + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (!ecma_is_value_true (status)) + { + return ECMA_VALUE_FALSE; + } + + /* The flags are always filled in the returned descriptor. */ + JERRY_ASSERT ( + (prop_desc.flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) && (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + && ((prop_desc.flags & JERRY_PROP_IS_WRITABLE_DEFINED) || !(prop_desc.flags & JERRY_PROP_IS_VALUE_DEFINED))); + + prop_desc_p->flags = prop_desc.flags; + prop_desc_p->value = ECMA_VALUE_UNDEFINED; + prop_desc_p->getter = ECMA_VALUE_UNDEFINED; + prop_desc_p->setter = ECMA_VALUE_UNDEFINED; + + if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + prop_desc_p->value = prop_desc.value; + } + + if (prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + if (prop_desc.get_p != NULL) + { + prop_desc_p->getter = ecma_make_object_value (prop_desc.get_p); + } + else + { + prop_desc_p->getter = ECMA_VALUE_NULL; + } + } + + if (prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + if (prop_desc.set_p != NULL) + { + prop_desc_p->setter = ecma_make_object_value (prop_desc.set_p); + } + else + { + prop_desc_p->setter = ECMA_VALUE_NULL; + } + } + + return ECMA_VALUE_TRUE; +} /* jerry_object_get_own_prop */ + +/** + * Free fields of property descriptor (setter, getter and value). + */ +void +jerry_property_descriptor_free (jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + jerry_value_free (prop_desc_p->value); + } + + if (prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + jerry_value_free (prop_desc_p->getter); + } + + if (prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + jerry_value_free (prop_desc_p->setter); + } +} /* jerry_property_descriptor_free */ + +/** + * Call function specified by a function value + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * error flag must not be set for any arguments of this function. + * + * @return returned jerry value of the called function + */ +jerry_value_t +jerry_call (const jerry_value_t func_object, /**< function object to call */ + const jerry_value_t this_value, /**< object for 'this' binding */ + const jerry_value_t *args_p, /**< function's call arguments */ + jerry_size_t args_count) /**< number of the arguments */ +{ + if (ecma_is_value_exception (this_value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + for (jerry_size_t i = 0; i < args_count; i++) + { + if (ecma_is_value_exception (args_p[i])) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + } + + return jerry_return (ecma_op_function_validated_call (func_object, this_value, args_p, args_count)); +} /* jerry_call */ + +/** + * Construct object value invoking specified function value as a constructor + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * error flag must not be set for any arguments of this function. + * + * @return returned jerry value of the invoked constructor + */ +jerry_value_t +jerry_construct (const jerry_value_t func_object, /**< function object to call */ + const jerry_value_t *args_p, /**< function's call arguments + * (NULL if arguments number is zero) */ + jerry_size_t args_count) /**< number of the arguments */ +{ + if (!jerry_value_is_constructor (func_object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + for (jerry_size_t i = 0; i < args_count; i++) + { + if (ecma_is_value_exception (args_p[i])) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + } + + return jerry_return (ecma_op_function_construct (ecma_get_object_from_value (func_object), + ecma_get_object_from_value (func_object), + args_p, + args_count)); +} /* jerry_construct */ + +/** + * Get keys of the specified object value + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return array object value - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_keys (const jerry_value_t object) /**< object value */ +{ + if (!ecma_is_value_object (object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_collection_t *prop_names = + ecma_op_object_get_enumerable_property_names (ecma_get_object_from_value (object), ECMA_ENUMERABLE_PROPERTY_KEYS); + +#if JERRY_BUILTIN_PROXY + if (JERRY_UNLIKELY (prop_names == NULL)) + { + return ecma_create_exception_from_context (); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ecma_op_new_array_object_from_collection (prop_names, false); +} /* jerry_object_keys */ + +/** + * Get the prototype of the specified object + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return prototype object or null value - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_proto (const jerry_value_t object) /**< object value */ +{ + if (!ecma_is_value_object (object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return jerry_return (ecma_proxy_object_get_prototype_of (obj_p)); + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (obj_p->u2.prototype_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_NULL; + } + + ecma_object_t *proto_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_p->u2.prototype_cp); + ecma_ref_object (proto_obj_p); + + return ecma_make_object_value (proto_obj_p); +} /* jerry_object_proto */ + +/** + * Set the prototype of the specified object + * + * @return true value - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_set_proto (jerry_value_t object, /**< object value */ + const jerry_value_t proto) /**< prototype object value */ +{ + if (!ecma_is_value_object (object) || ecma_is_value_exception (proto) + || (!ecma_is_value_object (proto) && !ecma_is_value_null (proto))) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + ecma_object_t *obj_p = ecma_get_object_from_value (object); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return jerry_return (ecma_proxy_object_set_prototype_of (obj_p, proto)); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ecma_op_ordinary_object_set_prototype_of (obj_p, proto); +} /* jerry_object_set_proto */ + +/** + * Utility to check if a given object can be used for the foreach api calls. + * + * Some objects/classes uses extra internal objects to correctly store data. + * These extre object should never be exposed externally to the API user. + * + * @returns true - if the user can access the object in the callback. + * false - if the object is an internal object which should no be accessed by the user. + */ +static bool +jerry_object_is_valid_foreach (ecma_object_t *object_p) /**< object to test */ +{ + if (ecma_is_lexical_environment (object_p)) + { + return false; + } + + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + if (object_type == ECMA_OBJECT_TYPE_CLASS) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + switch (ext_object_p->u.cls.type) + { + /* An object's internal property object should not be iterable by foreach. */ + case ECMA_OBJECT_CLASS_INTERNAL_OBJECT: + { + return false; + } + } + } + + return true; +} /* jerry_object_is_valid_foreach */ + +/** + * Traverse objects. + * + * @return true - traversal was interrupted by the callback. + * false - otherwise - traversal visited all objects. + */ +bool +jerry_foreach_live_object (jerry_foreach_live_object_cb_t callback, /**< function pointer of the iterator function */ + void *user_data_p) /**< pointer to user data */ +{ + JERRY_ASSERT (callback != NULL); + + jmem_cpointer_t iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp); + + while (iter_cp != JMEM_CP_NULL) + { + ecma_object_t *iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, iter_cp); + + if (jerry_object_is_valid_foreach (iter_p) && !callback (ecma_make_object_value (iter_p), user_data_p)) + { + return true; + } + + iter_cp = iter_p->gc_next_cp; + } + + return false; +} /* jerry_foreach_live_object */ + +/** + * Traverse objects having a given native type info. + * + * @return true - traversal was interrupted by the callback. + * false - otherwise - traversal visited all objects. + */ +bool +jerry_foreach_live_object_with_info (const jerry_object_native_info_t *native_info_p, /**< the type info + * of the native pointer */ + jerry_foreach_live_object_with_info_cb_t callback, /**< function to apply for + * each matching object */ + void *user_data_p) /**< pointer to user data */ +{ + JERRY_ASSERT (native_info_p != NULL); + JERRY_ASSERT (callback != NULL); + + ecma_native_pointer_t *native_pointer_p; + + jmem_cpointer_t iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp); + + while (iter_cp != JMEM_CP_NULL) + { + ecma_object_t *iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, iter_cp); + + if (jerry_object_is_valid_foreach (iter_p)) + { + native_pointer_p = ecma_get_native_pointer_value (iter_p, (jerry_object_native_info_t *) native_info_p); + if (native_pointer_p && !callback (ecma_make_object_value (iter_p), native_pointer_p->native_p, user_data_p)) + { + return true; + } + } + + iter_cp = iter_p->gc_next_cp; + } + + return false; +} /* jerry_foreach_live_object_with_info */ + +/** + * Get native pointer and its type information, associated with the given native type info. + * + * Note: + * If native pointer is present, its type information is returned in out_native_pointer_p + * + * @return found native pointer, + * or NULL + */ +void * +jerry_object_get_native_ptr (const jerry_value_t object, /**< object to get native pointer from */ + const jerry_object_native_info_t *native_info_p) /**< the type info + * of the native pointer */ +{ + if (!ecma_is_value_object (object)) + { + return NULL; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + ecma_native_pointer_t *native_pointer_p = ecma_get_native_pointer_value (obj_p, (jerry_object_native_info_t *) native_info_p); + + if (native_pointer_p == NULL) + { + return NULL; + } + + return native_pointer_p->native_p; +} /* jerry_object_get_native_ptr */ + +/** + * Set native pointer and an optional type info for the specified object. + * + * + * Note: + * If native pointer was already set for the object, its value is updated. + * + * Note: + * If a non-NULL free callback is specified in the native type info, + * it will be called by the garbage collector when the object is freed. + * Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition) + * The type info always overwrites the previous value, so passing + * a NULL value deletes the current type info. + */ +void +jerry_object_set_native_ptr (jerry_value_t object, /**< object to set native pointer in */ + const jerry_object_native_info_t *native_info_p, /**< object's native type info */ + void *native_pointer_p) /**< native pointer */ +{ + if (ecma_is_value_object (object)) + { + ecma_object_t *object_p = ecma_get_object_from_value (object); + + ecma_create_native_pointer_property (object_p, native_pointer_p, native_info_p); + } +} /* jerry_object_set_native_ptr */ + +/** + * Checks wether the argument object has a native poitner set for the specified native type info. + * + * @return true if the native pointer has been set, + * false otherwise + */ +bool +jerry_object_has_native_ptr (const jerry_value_t object, /**< object to set native pointer in */ + const jerry_object_native_info_t *native_info_p) /**< object's native type info */ +{ + if (!ecma_is_value_object (object)) + { + return false; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + ecma_native_pointer_t *native_pointer_p = ecma_get_native_pointer_value (obj_p, (jerry_object_native_info_t *) native_info_p); + + return native_pointer_p != NULL; +} /* jerry_object_has_native_ptr */ + +/** + * Delete the previously set native pointer by the native type info from the specified object. + * + * Note: + * If the specified object has no matching native pointer for the given native type info + * the function has no effect. + * + * Note: + * This operation cannot throw an exception. + * + * @return true - if the native pointer has been deleted succesfully + * false - otherwise + */ +bool +jerry_object_delete_native_ptr (jerry_value_t object, /**< object to delete native pointer from */ + const jerry_object_native_info_t *native_info_p) /**< object's native type info */ +{ + if (ecma_is_value_object (object)) + { + ecma_object_t *object_p = ecma_get_object_from_value (object); + + return ecma_delete_native_pointer_property (object_p, (jerry_object_native_info_t *) native_info_p); + } + + return false; +} /* jerry_object_delete_native_ptr */ + +/** + * Initialize the references stored in a buffer pointed by a native pointer. + * The references are initialized to undefined. + */ +void +jerry_native_ptr_init (void *native_pointer_p, /**< a valid non-NULL pointer to a native buffer */ + const jerry_object_native_info_t *native_info_p) /**< the type info of + * the native pointer */ +{ + if (native_pointer_p == NULL || native_info_p == NULL) + { + return; + } + + ecma_value_t *value_p = (ecma_value_t *) (((uint8_t *) native_pointer_p) + native_info_p->offset_of_references); + ecma_value_t *end_p = value_p + native_info_p->number_of_references; + + while (value_p < end_p) + { + *value_p++ = ECMA_VALUE_UNDEFINED; + } +} /* jerry_native_ptr_init */ + +/** + * Release the value references after a buffer pointed by a native pointer + * is not attached to an object anymore. All references are set to undefined + * similar to jerry_native_ptr_init. + */ +void +jerry_native_ptr_free (void *native_pointer_p, /**< a valid non-NULL pointer to a native buffer */ + const jerry_object_native_info_t *native_info_p) /**< the type info of + * the native pointer */ +{ + if (native_pointer_p == NULL || native_info_p == NULL) + { + return; + } + + ecma_value_t *value_p = (ecma_value_t *) (((uint8_t *) native_pointer_p) + native_info_p->offset_of_references); + ecma_value_t *end_p = value_p + native_info_p->number_of_references; + + while (value_p < end_p) + { + ecma_free_value_if_not_object (*value_p); + *value_p++ = ECMA_VALUE_UNDEFINED; + } +} /* jerry_native_ptr_free */ + +/** + * Updates a value reference inside the area specified by the number_of_references and + * offset_of_references fields in its corresponding jerry_object_native_info_t data. + * The area must be part of a buffer which is currently assigned to an object. + * + * Note: + * Error references are not supported, they are replaced by undefined values. + */ +void +jerry_native_ptr_set (jerry_value_t *reference_p, /**< a valid non-NULL pointer to + * a reference in a native buffer. */ + const jerry_value_t value) /**< new value of the reference */ +{ + if (reference_p == NULL) + { + return; + } + + ecma_free_value_if_not_object (*reference_p); + + if (ecma_is_value_exception (value)) + { + *reference_p = ECMA_VALUE_UNDEFINED; + return; + } + + *reference_p = ecma_copy_value_if_not_object (value); +} /* jerry_native_ptr_set */ + +/** + * Applies the given function to the every property in the object. + * + * @return true - if object fields traversal was performed successfully, i.e.: + * - no unhandled exceptions were thrown in object fields traversal; + * - object fields traversal was stopped on callback that returned false; + * false - otherwise, + * if getter of field threw a exception or unhandled exceptions were thrown during traversal; + */ +bool +jerry_object_foreach (const jerry_value_t object, /**< object value */ + jerry_object_property_foreach_cb_t foreach_p, /**< foreach function */ + void *user_data_p) /**< user data for foreach function */ +{ + if (!ecma_is_value_object (object)) + { + return false; + } + + ecma_object_t *object_p = ecma_get_object_from_value (object); + ecma_collection_t *names_p = ecma_op_object_enumerate (object_p); + +#if JERRY_BUILTIN_PROXY + if (names_p == NULL) + { + // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release + jcontext_release_exception (); + return false; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *buffer_p = names_p->buffer_p; + + ecma_value_t property_value = ECMA_VALUE_EMPTY; + + bool continuous = true; + + for (uint32_t i = 0; continuous && (i < names_p->item_count); i++) + { + ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]); + + property_value = ecma_op_object_get (object_p, property_name_p); + + if (ECMA_IS_VALUE_ERROR (property_value)) + { + break; + } + + continuous = foreach_p (buffer_p[i], property_value, user_data_p); + ecma_free_value (property_value); + } + + ecma_collection_free (names_p); + + if (!ECMA_IS_VALUE_ERROR (property_value)) + { + return true; + } + + jcontext_release_exception (); + return false; +} /* jerry_object_foreach */ + +/** + * Gets the property keys for the given object using the selected filters. + * + * @return array containing the filtered property keys in successful operation + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_property_names (const jerry_value_t object, /**< object */ + jerry_property_filter_t filter) /**< property filter options */ +{ + if (!ecma_is_value_object (object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + ecma_object_t *obj_iter_p = obj_p; + ecma_collection_t *result_p = ecma_new_collection (); + + ecma_ref_object (obj_iter_p); + + while (true) + { + /* Step 1. Get Object.[[OwnKeys]] */ + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_iter_p, filter); + +#if JERRY_BUILTIN_PROXY + if (prop_names_p == NULL) + { + ecma_deref_object (obj_iter_p); + return ecma_create_exception_from_context (); + } +#endif /* JERRY_BUILTIN_PROXY */ + + for (uint32_t i = 0; i < prop_names_p->item_count; i++) + { + ecma_value_t key = prop_names_p->buffer_p[i]; + ecma_string_t *key_p = ecma_get_prop_name_from_value (key); + uint32_t index = ecma_string_get_array_index (key_p); + + /* Step 2. Filter by key type */ + if (filter + & (JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS | JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS + | JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + if (ecma_is_value_symbol (key)) + { + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) + { + continue; + } + } + else if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + if ((filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES) + || ((filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + && !(filter & JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER))) + { + continue; + } + } + else if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + continue; + } + } + + /* Step 3. Filter property attributes */ + if (filter + & (JERRY_PROPERTY_FILTER_EXCLUDE_NON_CONFIGURABLE | JERRY_PROPERTY_FILTER_EXCLUDE_NON_ENUMERABLE + | JERRY_PROPERTY_FILTER_EXCLUDE_NON_WRITABLE)) + { + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_iter_p, key_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_free (prop_names_p); + ecma_collection_free (result_p); + ecma_deref_object (obj_iter_p); + return ecma_create_exception_from_context (); + } +#endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT (ecma_is_value_true (status)); + uint16_t flags = prop_desc.flags; + ecma_free_property_descriptor (&prop_desc); + + if ((!(flags & JERRY_PROP_IS_CONFIGURABLE) && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_CONFIGURABLE)) + || (!(flags & JERRY_PROP_IS_ENUMERABLE) && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_ENUMERABLE)) + || (!(flags & JERRY_PROP_IS_WRITABLE) && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_WRITABLE))) + { + continue; + } + } + + if (index != ECMA_STRING_NOT_ARRAY_INDEX && (filter & JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER)) + { + ecma_deref_ecma_string (key_p); + key = ecma_make_uint32_value (index); + } + else + { + ecma_ref_ecma_string (key_p); + } + + if ((filter & JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) && obj_iter_p != obj_p) + { + uint32_t duplicate_idx = 0; + while (duplicate_idx < result_p->item_count) + { + ecma_value_t value = result_p->buffer_p[duplicate_idx]; + JERRY_ASSERT (ecma_is_value_prop_name (value) || ecma_is_value_number (value)); + if (JERRY_UNLIKELY (ecma_is_value_number (value))) + { + if (ecma_get_number_from_value (value) == ecma_get_number_from_value (key)) + { + break; + } + } + else if (ecma_compare_ecma_strings (ecma_get_prop_name_from_value (value), key_p)) + { + break; + } + + duplicate_idx++; + } + + if (duplicate_idx == result_p->item_count) + { + ecma_collection_push_back (result_p, key); + } + } + else + { + ecma_collection_push_back (result_p, key); + } + } + + ecma_collection_free (prop_names_p); + + /* Step 4: Traverse prototype chain */ + + if ((filter & JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) != JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) + { + break; + } + + ecma_object_t *proto_p = ecma_op_object_get_prototype_of (obj_iter_p); + + if (proto_p == NULL) + { + break; + } + + ecma_deref_object (obj_iter_p); + + if (JERRY_UNLIKELY (proto_p == ECMA_OBJECT_POINTER_ERROR)) + { + ecma_collection_free (result_p); + return ecma_create_exception_from_context (); + } + + obj_iter_p = proto_p; + } + + ecma_deref_object (obj_iter_p); + + return ecma_op_new_array_object_from_collection (result_p, false); +} /* jerry_object_property_names */ + +/** + * FromPropertyDescriptor abstract operation. + * + * @return new jerry_value_t - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_property_descriptor_to_object (const jerry_property_descriptor_t *src_prop_desc_p) /**< property descriptor */ +{ + ecma_property_descriptor_t prop_desc = jerry_property_descriptor_to_ecma (src_prop_desc_p); + + if (ECMA_IS_VALUE_ERROR (prop_desc.value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); + + return ecma_make_object_value (desc_obj_p); +} /* jerry_property_descriptor_to_object */ + +/** + * ToPropertyDescriptor abstract operation. + * + * @return true - if the conversion is successful + * thrown error - otherwise + */ +jerry_value_t +jerry_property_descriptor_from_object (const jerry_value_t object, /**< object value */ + jerry_property_descriptor_t *out_prop_desc_p) /**< [out] filled property + * descriptor if return value is + * true, unmodified otherwise */ +{ + ecma_property_descriptor_t prop_desc; + jerry_value_t result = ecma_op_to_property_descriptor (object, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return ecma_create_exception_from_context (); + } + + JERRY_ASSERT (result == ECMA_VALUE_EMPTY); + + *out_prop_desc_p = jerry_property_descriptor_from_ecma (&prop_desc); + return ECMA_VALUE_TRUE; +} /* jerry_property_descriptor_from_object */ + +/** + * Resolve a promise value with an argument. + * + * @return undefined - if success, + * exception - otherwise + */ +jerry_value_t +jerry_promise_resolve (jerry_value_t promise, /**< the promise value */ + const jerry_value_t argument) /**< the argument */ +{ + if (!jerry_value_is_promise (promise)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + if (ecma_is_value_exception (argument)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + return ecma_fulfill_promise_with_checks (promise, argument); +} /* jerry_promise_resolve */ + +/** + * Reject a promise value with an argument. + * + * @return undefined - if success, + * exception - otherwise + */ +jerry_value_t +jerry_promise_reject (jerry_value_t promise, /**< the promise value */ + const jerry_value_t argument) /**< the argument */ +{ + if (!jerry_value_is_promise (promise)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + if (ecma_is_value_exception (argument)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + return ecma_reject_promise_with_checks (promise, argument); +} /* jerry_promise_reject */ + +/** + * Get the result of a promise. + * + * @return - Promise result + * - Type error if the promise support was not enabled or the input was not a promise object + */ +jerry_value_t +jerry_promise_result (const jerry_value_t promise) /**< promise object to get the result from */ +{ + if (!jerry_value_is_promise (promise)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + return ecma_promise_get_result (ecma_get_object_from_value (promise)); +} /* jerry_get_promise_result */ + +/** + * Get the state of a promise object. + * + * @return - the state of the promise (one of the jerry_promise_state_t enum values) + * - JERRY_PROMISE_STATE_NONE is only returned if the input is not a promise object + * or the promise support was not enabled. + */ +jerry_promise_state_t +jerry_promise_state (const jerry_value_t promise) /**< promise object to get the state from */ +{ + if (!jerry_value_is_promise (promise)) + { + return JERRY_PROMISE_STATE_NONE; + } + + uint16_t flags = ecma_promise_get_flags (ecma_get_object_from_value (promise)); + flags &= (ECMA_PROMISE_IS_PENDING | ECMA_PROMISE_IS_FULFILLED); + + return (flags ? (jerry_promise_state_t) flags : JERRY_PROMISE_STATE_REJECTED); +} /* jerry_get_promise_state */ + +/** + * Sets a callback for tracking Promise and async operations. + * + * Note: + * the previous callback is overwritten + */ +void +jerry_promise_on_event (jerry_promise_event_filter_t filters, /**< combination of event filters */ + jerry_promise_event_cb_t callback, /**< notification callback */ + void *user_p) /**< user pointer passed to the callback */ +{ + JERRY_UNUSED (filters); + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); +} /* jerry_promise_set_callback */ + +/** + * Get the well-knwon symbol represented by the given `symbol` enum value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return undefined value - if invalid well-known symbol was requested + * well-known symbol value - otherwise + */ +jerry_value_t +jerry_symbol (jerry_well_known_symbol_t symbol) /**< jerry_well_known_symbol_t enum value */ +{ + lit_magic_string_id_t id = (lit_magic_string_id_t) (LIT_GLOBAL_SYMBOL__FIRST + symbol); + + if (!LIT_IS_GLOBAL_SYMBOL (id)) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_make_symbol_value (ecma_op_get_global_symbol (id)); +} /* jerry_get_well_known_symbol */ + +/** + * Returns the description internal property of a symbol. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return string or undefined value containing the symbol's description - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_symbol_description (const jerry_value_t symbol) /**< symbol value */ +{ + if (!ecma_is_value_symbol (symbol)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + /* Note: This operation cannot throw an error */ + return ecma_copy_value (ecma_get_symbol_description (ecma_get_symbol_from_value (symbol))); +} /* jerry_get_symbol_description */ + +/** + * Call the SymbolDescriptiveString ecma builtin operation on the symbol value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return string value containing the symbol's descriptive string - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_symbol_descriptive_string (const jerry_value_t symbol) /**< symbol value */ +{ + if (!ecma_is_value_symbol (symbol)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + /* Note: This operation cannot throw an error */ + return ecma_get_symbol_descriptive_string (symbol); +} /* jerry_get_symbol_descriptive_string */ + +/** + * Get the number of uint64 digits of a BigInt value + * + * @return number of uint64 digits + */ +uint32_t +jerry_bigint_digit_count (const jerry_value_t value) /**< BigInt value */ +{ +#if JERRY_BUILTIN_BIGINT + if (!ecma_is_value_bigint (value)) + { + return 0; + } + + return ecma_bigint_get_size_in_digits (value); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (value); + return 0; +#endif /* JERRY_BUILTIN_BIGINT */ +} /* jerry_bigint_digit_count */ + +/** + * Get the uint64 digits of a BigInt value (lowest digit first) + */ +void +jerry_bigint_to_digits (const jerry_value_t value, /**< BigInt value */ + uint64_t *digits_p, /**< [out] buffer for digits */ + uint32_t digit_count, /**< buffer size in digits */ + bool *sign_p) /**< [out] sign of BigInt */ +{ +#if JERRY_BUILTIN_BIGINT + if (!ecma_is_value_bigint (value)) + { + if (sign_p != NULL) + { + *sign_p = false; + } + memset (digits_p, 0, digit_count * sizeof (uint64_t)); + } + + ecma_bigint_get_digits_and_sign (value, digits_p, digit_count, sign_p); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (value); + + if (sign_p != NULL) + { + *sign_p = false; + } + memset (digits_p, 0, digit_count * sizeof (uint64_t)); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* jerry_bigint_to_digits */ + +/** + * Get the target object of a Proxy object + * + * @return type error - if proxy_value is not a Proxy object + * target object - otherwise + */ +jerry_value_t +jerry_proxy_target (const jerry_value_t proxy_value) /**< proxy value */ +{ +#if JERRY_BUILTIN_PROXY + if (ecma_is_value_object (proxy_value)) + { + ecma_object_t *object_p = ecma_get_object_from_value (proxy_value); + + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + ecma_proxy_object_t *proxy_object_p = (ecma_proxy_object_t *) object_p; + + if (!ecma_is_value_null (proxy_object_p->target)) + { + ecma_ref_object (ecma_get_object_from_value (proxy_object_p->target)); + } + return proxy_object_p->target; + } + } +#else /* !JERRY_BUILTIN_PROXY */ + JERRY_UNUSED (proxy_value); +#endif /* JERRY_BUILTIN_PROXY */ + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_ARGUMENT_IS_NOT_A_PROXY)); +} /* jerry_proxy_target */ + +/** + * Get the handler object of a Proxy object + * + * @return type error - if proxy_value is not a Proxy object + * handler object - otherwise + */ +jerry_value_t +jerry_proxy_handler (const jerry_value_t proxy_value) /**< proxy value */ +{ +#if JERRY_BUILTIN_PROXY + if (ecma_is_value_object (proxy_value)) + { + ecma_object_t *object_p = ecma_get_object_from_value (proxy_value); + + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + ecma_proxy_object_t *proxy_object_p = (ecma_proxy_object_t *) object_p; + + if (!ecma_is_value_null (proxy_object_p->handler)) + { + ecma_ref_object (ecma_get_object_from_value (proxy_object_p->handler)); + } + return proxy_object_p->handler; + } + } +#else /* !JERRY_BUILTIN_PROXY */ + JERRY_UNUSED (proxy_value); +#endif /* JERRY_BUILTIN_PROXY */ + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_ARGUMENT_IS_NOT_A_PROXY)); +} /* jerry_proxy_handler */ + +/** + * Validate string buffer for the specified encoding + * + * @return true - if string is well-formed + * false - otherwise + */ +bool +jerry_validate_string (const jerry_char_t *buffer_p, /**< string buffer */ + jerry_size_t buffer_size, /**< buffer size */ + jerry_encoding_t encoding) /**< buffer encoding */ +{ + switch (encoding) + { + case JERRY_ENCODING_CESU8: + { + return lit_is_valid_cesu8_string (buffer_p, buffer_size); + } + case JERRY_ENCODING_UTF8: + { + return lit_is_valid_utf8_string (buffer_p, buffer_size, true); + } + default: + { + return false; + } + } +} /* jerry_validate_string */ + +/** + * Set the log level of the engine. + * + * Log messages with lower significance than the current log level will be ignored by `jerry_log`. + * + * @param level: requested log level + */ +void +jerry_log_set_level (jerry_log_level_t level) +{ + jerry_jrt_set_log_level (level); +} /* jerry_log_set_level */ + +/** + * Log buffer size + */ +#define JERRY_LOG_BUFFER_SIZE 64 + +/** + * Log a zero-terminated string message. + * + * @param str_p: message + */ +static void +jerry_log_string (const char *str_p) +{ + jerry_port_log (str_p); + +} /* jerry_log_string */ + +/** + * Log a fixed-size string message. + * + * @param str_p: message + * @param size: size + * @param buffer_p: buffer to use + */ +static void +jerry_log_string_fixed (const char *str_p, size_t size, char *buffer_p) +{ + const size_t batch_size = JERRY_LOG_BUFFER_SIZE - 1; + + while (size > batch_size) + { + memcpy (buffer_p, str_p, batch_size); + buffer_p[batch_size] = '\0'; + jerry_log_string (buffer_p); + + str_p += batch_size; + size -= batch_size; + } + + memcpy (buffer_p, str_p, size); + buffer_p[size] = '\0'; + jerry_log_string (buffer_p); +} /* jerry_log_string_fixed */ + +/** + * Format an unsigned number. + * + * @param num: number + * @param width: minimum width of the number + * @param padding: padding to be used when extending to minimum width + * @param radix: number radix + * @param buffer_p: buffer used to construct the number string + * + * @return formatted number as string + */ +static char * +jerry_format_unsigned (unsigned int num, uint8_t width, char padding, uint8_t radix, char *buffer_p) +{ + static const char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + char *cursor_p = buffer_p + JERRY_LOG_BUFFER_SIZE; + *(--cursor_p) = '\0'; + uint8_t count = 0; + + do + { + *(--cursor_p) = digits[num % radix]; + num /= radix; + count++; + } while (num > 0); + + while (count < width) + { + *(--cursor_p) = padding; + count++; + } + + return cursor_p; +} /* jerry_format_unsigned */ + +/** + * Format an integer number. + * + * @param num: number + * @param width: minimum width of the number + * @param padding: padding to be used when extending to minimum width + * @param buffer_p: buffer used to construct the number string + * + * @return formatted number as string + */ +static char * +jerry_format_int (int num, uint8_t width, char padding, char *buffer_p) +{ + if (num >= 0) + { + return jerry_format_unsigned ((unsigned) num, width, padding, 10, buffer_p); + } + + num = -num; + + if (padding == '0' && width > 0) + { + char *cursor_p = jerry_format_unsigned ((unsigned) num, --width, padding, 10, buffer_p); + *(--cursor_p) = '-'; + return cursor_p; + } + + char *cursor_p = jerry_format_unsigned ((unsigned) num, 0, ' ', 10, buffer_p); + *(--cursor_p) = '-'; + + char *indent_p = buffer_p + JERRY_LOG_BUFFER_SIZE - width - 1; + + while (cursor_p > indent_p) + { + *(--cursor_p) = ' '; + } + + return cursor_p; +} /* jerry_foramt_int */ + +/** + * Log a zero-terminated formatted message with the specified log level. + * + * Supported format specifiers: + * %s: zero-terminated string + * %c: character + * %u: unsigned integer + * %d: decimal integer + * %x: unsigned hexadecimal + * + * Width and padding sub-modifiers are also supported. + * + * @param format_p: format string + * @param level: message log level + */ +void +jerry_log (jerry_log_level_t level, const char *format_p, ...) +{ + if (level > jerry_jrt_get_log_level ()) + { + return; + } + + va_list vl; + char buffer_p[JERRY_LOG_BUFFER_SIZE]; + uint32_t buffer_index = 0; + const char *cursor_p = format_p; + va_start (vl, format_p); + + while (*cursor_p != '\0') + { + if (*cursor_p == '%' || buffer_index > JERRY_LOG_BUFFER_SIZE - 2) + { + buffer_p[buffer_index] = '\0'; + jerry_log_string (buffer_p); + buffer_index = 0; + } + + if (*cursor_p != '%') + { + buffer_p[buffer_index++] = *cursor_p++; + continue; + } + + ++cursor_p; + uint8_t width = 0; + size_t precision = 0; + char padding = ' '; + + if (*cursor_p == '0') + { + padding = '0'; + cursor_p++; + } + + if (lit_char_is_decimal_digit ((ecma_char_t) *cursor_p)) + { + width = (uint8_t) (*cursor_p - '0'); + cursor_p++; + } + else if (*cursor_p == '*') + { + width = (uint8_t) JERRY_MAX (va_arg (vl, int), 10); + cursor_p++; + } + else if (*cursor_p == '.' && *(cursor_p + 1) == '*') + { + precision = (size_t) va_arg (vl, int); + cursor_p += 2; + } + + if (*cursor_p == '\0') + { + buffer_p[buffer_index++] = '%'; + break; + } + + /* The buffer is always flushed before a substitution, and can be reused to for formatting. */ + switch (*cursor_p++) + { + case 's': + { + char *str_p = va_arg (vl, char *); + + if (precision == 0) + { + jerry_log_string (str_p); + break; + } + + jerry_log_string_fixed (str_p, precision, buffer_p); + break; + } + case 'c': + { + /* Arguments of types narrower than int are promoted to int for variadic functions */ + buffer_p[buffer_index++] = (char) va_arg (vl, int); + break; + } + case 'd': + { + jerry_log_string (jerry_format_int (va_arg (vl, int), width, padding, buffer_p)); + break; + } + case 'u': + { + jerry_log_string (jerry_format_unsigned (va_arg (vl, unsigned int), width, padding, 10, buffer_p)); + break; + } + case 'x': + { + jerry_log_string (jerry_format_unsigned (va_arg (vl, unsigned int), width, padding, 16, buffer_p)); + break; + } + default: + { + buffer_p[buffer_index++] = '%'; + break; + } + } + } + + if (buffer_index > 0) + { + buffer_p[buffer_index] = '\0'; + jerry_log_string (buffer_p); + } + + va_end (vl); +} /* jerry_log */ + +/** + * Allocate memory on the engine's heap. + * + * Note: + * This function may take away memory from the executed JavaScript code. + * If any other dynamic memory allocation API is available (e.g., libc + * malloc), it should be used instead. + * + * @return allocated memory on success + * NULL otherwise + */ +void * +jerry_heap_alloc (jerry_size_t size) /**< size of the memory block */ +{ + return jmem_heap_alloc_block_null_on_error (size); +} /* jerry_heap_alloc */ + +/** + * Free memory allocated on the engine's heap. + */ +void +jerry_heap_free (void *mem_p, /**< value returned by jerry_heap_alloc */ + jerry_size_t size) /**< same size as passed to jerry_heap_alloc */ +{ + jmem_heap_free_block (mem_p, size); +} /* jerry_heap_free */ + +/** + * When JERRY_VM_HALT is enabled, the callback passed to this function + * is periodically called with the user_p argument. If interval is greater + * than 1, the callback is only called at every interval ticks. + */ +void +jerry_halt_handler (uint32_t interval, /**< interval of the function call */ + jerry_halt_cb_t callback, /**< periodically called user function */ + void *user_p) /**< pointer passed to the function */ +{ +#if JERRY_VM_HALT + if (interval == 0) + { + interval = 1; + } + + JERRY_CONTEXT (vm_exec_stop_frequency) = interval; + JERRY_CONTEXT (vm_exec_stop_counter) = interval; + JERRY_CONTEXT (vm_exec_stop_cb) = callback; + JERRY_CONTEXT (vm_exec_stop_user_p) = user_p; +#else /* !JERRY_VM_HALT */ + JERRY_UNUSED (interval); + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); +#endif /* JERRY_VM_HALT */ +} /* jerry_halt_handler */ + +/** + * Get backtrace. The backtrace is an array of strings where + * each string contains the position of the corresponding frame. + * The array length is zero if the backtrace is not available. + * + * @return array value + */ +jerry_value_t +jerry_backtrace (uint32_t max_depth) /**< depth limit of the backtrace */ +{ + return vm_get_backtrace (max_depth); +} /* jerry_backtrace */ + +/** + * Low-level function to capture each backtrace frame. + * The captured frame data is passed to a callback function. + */ +void +jerry_backtrace_capture (jerry_backtrace_cb_t callback, /**< callback function */ + void *user_p) /**< user pointer passed to the callback function */ +{ + jerry_frame_t frame; + vm_frame_ctx_t *context_p = JERRY_CONTEXT (vm_top_context_p); + + while (context_p != NULL) + { + frame.context_p = context_p; + frame.frame_type = JERRY_BACKTRACE_FRAME_JS; + + if (!callback (&frame, user_p)) + { + return; + } + + context_p = context_p->prev_context_p; + } +} /* jerry_backtrace */ + +/** + * Returns with the type of the backtrace frame. + * + * @return frame type listed in jerry_frame_type_t + */ +jerry_frame_type_t +jerry_frame_type (const jerry_frame_t *frame_p) /**< frame pointer */ +{ + return (jerry_frame_type_t) frame_p->frame_type; +} /* jerry_frame_type */ + +/** + * Initialize and return with the location private field of a backtrace frame. + * + * @return pointer to the location private field - if the location is available, + * NULL - otherwise + */ +const jerry_frame_location_t * +jerry_frame_location (jerry_frame_t *frame_p) /**< frame pointer */ +{ + JERRY_UNUSED (frame_p); + +#if JERRY_LINE_INFO + if (frame_p->frame_type == JERRY_BACKTRACE_FRAME_JS) + { + vm_frame_ctx_t *context_p = frame_p->context_p; + const ecma_compiled_code_t *bytecode_header_p = context_p->shared_p->bytecode_header_p; + + if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO)) + { + return NULL; + } + + frame_p->location.source_name = ecma_get_source_name (bytecode_header_p); + + ecma_line_info_get (ecma_compiled_code_get_line_info (bytecode_header_p), + (uint32_t) (context_p->byte_code_p - context_p->byte_code_start_p), + &frame_p->location); + + return &frame_p->location; + } +#endif /* JERRY_LINE_INFO */ + + return NULL; +} /* jerry_frame_location */ + +/** + * Initialize and return with the called function private field of a backtrace frame. + * The backtrace frame is created for running the code bound to this function. + * + * @return pointer to the called function - if the function is available, + * NULL - otherwise + */ +const jerry_value_t * +jerry_frame_callee (jerry_frame_t *frame_p) /**< frame pointer */ +{ + if (frame_p->frame_type == JERRY_BACKTRACE_FRAME_JS) + { + vm_frame_ctx_t *context_p = frame_p->context_p; + + if (context_p->shared_p->function_object_p != NULL) + { + frame_p->function = ecma_make_object_value (context_p->shared_p->function_object_p); + return &frame_p->function; + } + } + + return NULL; +} /* jerry_frame_callee */ + +/** + * Initialize and return with the 'this' binding private field of a backtrace frame. + * The 'this' binding is a hidden value passed to the called function. As for arrow + * functions, the 'this' binding is assigned at function creation. + * + * @return pointer to the 'this' binding - if the binding is available, + * NULL - otherwise + */ +const jerry_value_t * +jerry_frame_this (jerry_frame_t *frame_p) /**< frame pointer */ +{ + if (frame_p->frame_type == JERRY_BACKTRACE_FRAME_JS) + { + frame_p->this_binding = frame_p->context_p->this_binding; + return &frame_p->this_binding; + } + + return NULL; +} /* jerry_frame_this */ + +/** + * Returns true, if the code bound to the backtrace frame is strict mode code. + * + * @return true - if strict mode code is bound to the frame, + * false - otherwise + */ +bool +jerry_frame_is_strict (jerry_frame_t *frame_p) /**< frame pointer */ +{ + return (frame_p->frame_type == JERRY_BACKTRACE_FRAME_JS + && (frame_p->context_p->status_flags & VM_FRAME_CTX_IS_STRICT) != 0); +} /* jerry_frame_is_strict */ + +/** + * Get the source name (usually a file name) of the currently executed script or the given function object + * + * Note: returned value must be freed with jerry_value_free, when it is no longer needed + * + * @return JS string constructed from + * - the currently executed function object's source name, if the given value is undefined + * - source name of the function object, if the given value is a function object + * - "", otherwise + */ +jerry_value_t +jerry_source_name (const jerry_value_t value) /**< jerry api value */ +{ +#if JERRY_SOURCE_NAME + if (ecma_is_value_undefined (value) && JERRY_CONTEXT (vm_top_context_p) != NULL) + { + return ecma_copy_value (ecma_get_source_name (JERRY_CONTEXT (vm_top_context_p)->shared_p->bytecode_header_p)); + } + + ecma_value_t script_value = ecma_script_get_from_value (value); + + if (script_value == JMEM_CP_NULL) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_ANON); + } + + const cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + return ecma_copy_value (script_p->source_name); +#else /* !JERRY_SOURCE_NAME */ + JERRY_UNUSED (value); + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_ANON); +#endif /* JERRY_SOURCE_NAME */ +} /* jerry_source_name */ + +/** + * Returns the user value assigned to a script / module / function. + * + * Note: + * This value is usually set by the parser when + * the JERRY_PARSE_HAS_USER_VALUE flag is passed. + * + * @return user value + */ +jerry_value_t +jerry_source_user_value (const jerry_value_t value) /**< jerry api value */ +{ + ecma_value_t script_value = ecma_script_get_from_value (value); + + if (script_value == JMEM_CP_NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + const cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (!(script_p->refs_and_type & CBC_SCRIPT_HAS_USER_VALUE)) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_copy_value (CBC_SCRIPT_GET_USER_VALUE (script_p)); +} /* jerry_source_user_value */ + +/** + * Checks whether an ECMAScript code is compiled by eval + * like (eval, new Function, jerry_eval, etc.) command. + * + * @return true, if code is compiled by eval like command + * false, otherwise + */ +bool +jerry_function_is_dynamic (const jerry_value_t value) /**< jerry api value */ +{ + ecma_value_t script_value = ecma_script_get_from_value (value); + + if (script_value == JMEM_CP_NULL) + { + return false; + } + + const cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + return (script_p->refs_and_type & CBC_SCRIPT_IS_EVAL_CODE) != 0; +} /* jerry_function_is_dynamic */ + +/** + * Returns a newly created source info structure corresponding to the passed script/module/function. + * + * @return a newly created source info, if at least one field is available, NULL otherwise + */ +jerry_source_info_t * +jerry_source_info (const jerry_value_t value) /**< jerry api value */ +{ +#if JERRY_FUNCTION_TO_STRING + if (!ecma_is_value_object (value)) + { + return NULL; + } + + jerry_source_info_t source_info; + + source_info.enabled_fields = 0; + source_info.source_code = ECMA_VALUE_UNDEFINED; + source_info.function_arguments = ECMA_VALUE_UNDEFINED; + source_info.source_range_start = 0; + source_info.source_range_length = 0; + + ecma_object_t *object_p = ecma_get_object_from_value (value); + cbc_script_t *script_p = NULL; + + while (true) + { + switch (ecma_get_object_type (object_p)) + { + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + const ecma_compiled_code_t *bytecode_p = NULL; + + if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_SCRIPT) + { + bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + } +#if JERRY_MODULE_SYSTEM + else if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_MODULE) + { + ecma_module_t *module_p = (ecma_module_t *) object_p; + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)) + { + bytecode_p = module_p->u.compiled_code_p; + } + } +#endif /* JERRY_MODULE_SYSTEM */ + + if (bytecode_p == NULL) + { + return NULL; + } + + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + const ecma_compiled_code_t *bytecode_p; + bytecode_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) + { + uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (bytecode_p); + uint8_t extended_info = *extended_info_p; + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) + { + ecma_extended_info_decode_vlq (&extended_info_p); + } + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS) + { + ecma_value_t function_arguments = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, script_p->refs_and_type); + + ecma_ref_ecma_string (ecma_get_string_from_value (function_arguments)); + + source_info.enabled_fields |= JERRY_SOURCE_INFO_HAS_SOURCE_CODE; + source_info.source_code = function_arguments; + script_p = NULL; + } + + source_info.enabled_fields |= JERRY_SOURCE_INFO_HAS_SOURCE_RANGE; + source_info.source_range_start = ecma_extended_info_decode_vlq (&extended_info_p); + source_info.source_range_length = ecma_extended_info_decode_vlq (&extended_info_p); + } + + JERRY_ASSERT (script_p != NULL || (source_info.enabled_fields & JERRY_SOURCE_INFO_HAS_SOURCE_CODE)); + + if (source_info.enabled_fields == 0 && (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)) + { + ecma_value_t function_arguments = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, script_p->refs_and_type); + + ecma_ref_ecma_string (ecma_get_string_from_value (function_arguments)); + + source_info.enabled_fields |= JERRY_SOURCE_INFO_HAS_FUNCTION_ARGUMENTS; + source_info.function_arguments = function_arguments; + } + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + object_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_object_p->u.bound_function.target_function); + continue; + } + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + ecma_value_t script_value = ((ecma_extended_object_t *) object_p)->u.constructor_function.script_value; + script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + break; + } + default: + { + return NULL; + } + } + + break; + } + + jerry_source_info_t *source_info_p = jmem_heap_alloc_block_null_on_error (sizeof (jerry_source_info_t)); + + if (source_info_p == NULL) + { + return NULL; + } + + if (script_p != NULL) + { + ecma_ref_ecma_string (ecma_get_string_from_value (script_p->source_code)); + + source_info.enabled_fields |= JERRY_SOURCE_INFO_HAS_SOURCE_CODE; + source_info.source_code = script_p->source_code; + } + + JERRY_ASSERT (source_info.enabled_fields != 0); + + *source_info_p = source_info; + return source_info_p; +#else /* !JERRY_FUNCTION_TO_STRING */ + JERRY_UNUSED (value); + return NULL; +#endif /* JERRY_FUNCTION_TO_STRING */ +} /* jerry_source_info */ + +/** + * Frees the the source info structure returned by jerry_source_info. + */ +void +jerry_source_info_free (jerry_source_info_t *source_info_p) /**< source info block */ +{ +#if JERRY_FUNCTION_TO_STRING + if (source_info_p != NULL) + { + ecma_free_value (source_info_p->source_code); + ecma_free_value (source_info_p->function_arguments); + jmem_heap_free_block (source_info_p, sizeof (jerry_source_info_t)); + } +#else /* !JERRY_FUNCTION_TO_STRING */ + JERRY_UNUSED (source_info_p); +#endif /* JERRY_FUNCTION_TO_STRING */ +} /* jerry_source_info_free */ + +/** + * Replaces the currently active realm with another realm. + * + * The replacement should be temporary, and the original realm must be + * restored after the tasks are completed. During the replacement, the + * realm must be referenced by the application (i.e. the gc must not + * reclaim it). This is also true to the returned previously active + * realm, so there is no need to free the value after the restoration. + * + * @return previous realm value - if the passed value is a realm + * exception - otherwise + */ +jerry_value_t +jerry_set_realm (jerry_value_t realm_value) /**< jerry api value */ +{ +#if JERRY_BUILTIN_REALMS + if (ecma_is_value_object (realm_value)) + { + ecma_object_t *object_p = ecma_get_object_from_value (realm_value); + + if (ecma_builtin_is_global (object_p)) + { + ecma_global_object_t *previous_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = (ecma_global_object_t *) object_p; + return ecma_make_object_value ((ecma_object_t *) previous_global_object_p); + } + } + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_PASSED_ARGUMENT_IS_NOT_A_REALM)); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_UNUSED (realm_value); + return jerry_throw_sz (JERRY_ERROR_REFERENCE, ecma_get_error_msg (ECMA_ERR_REALM_IS_NOT_AVAILABLE)); +#endif /* JERRY_BUILTIN_REALMS */ +} /* jerry_set_realm */ + +/** + * Gets the 'this' binding of a realm + * + * @return type error - if realm_value is not a realm + * this value - otherwise + */ +jerry_value_t +jerry_realm_this (jerry_value_t realm) /**< realm value */ +{ +#if JERRY_BUILTIN_REALMS + if (ecma_is_value_object (realm)) + { + ecma_object_t *object_p = ecma_get_object_from_value (realm); + + if (ecma_builtin_is_global (object_p)) + { + ecma_global_object_t *global_object_p = (ecma_global_object_t *) object_p; + + ecma_ref_object (ecma_get_object_from_value (global_object_p->this_binding)); + return global_object_p->this_binding; + } + } + +#else /* !JERRY_BUILTIN_REALMS */ + ecma_object_t *global_object_p = ecma_builtin_get_global (); + + if (realm == ecma_make_object_value (global_object_p)) + { + ecma_ref_object (global_object_p); + return realm; + } +#endif /* JERRY_BUILTIN_REALMS */ + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_PASSED_ARGUMENT_IS_NOT_A_REALM)); +} /* jerry_realm_this */ + +/** + * Sets the 'this' binding of a realm + * + * This function must be called before executing any script on the realm. + * Otherwise the operation is undefined. + * + * @return type error - if realm_value is not a realm or this_value is not object + * true - otherwise + */ +jerry_value_t +jerry_realm_set_this (jerry_value_t realm, /**< realm value */ + jerry_value_t this_value) /**< this value */ +{ +#if JERRY_BUILTIN_REALMS + if (!ecma_is_value_object (this_value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_SECOND_ARGUMENT_MUST_BE_AN_OBJECT)); + } + + if (ecma_is_value_object (realm)) + { + ecma_object_t *object_p = ecma_get_object_from_value (realm); + + if (ecma_builtin_is_global (object_p)) + { + ecma_global_object_t *global_object_p = (ecma_global_object_t *) object_p; + global_object_p->this_binding = this_value; + + ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL, ecma_get_object_from_value (this_value)); + + ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, global_lex_env_p); + global_object_p->global_scope_cp = global_object_p->global_env_cp; + + ecma_deref_object (global_lex_env_p); + return ECMA_VALUE_TRUE; + } + } + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_FIRST_ARGUMENT_IS_NOT_A_REALM)); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_UNUSED (realm); + JERRY_UNUSED (this_value); + return jerry_throw_sz (JERRY_ERROR_REFERENCE, ecma_get_error_msg (ECMA_ERR_REALM_IS_NOT_AVAILABLE)); +#endif /* JERRY_BUILTIN_REALMS */ +} /* jerry_realm_set_this */ + +/** + * Check if the given value is an ArrayBuffer object. + * + * @return true - if it is an ArrayBuffer object + * false - otherwise + */ +bool +jerry_value_is_arraybuffer (const jerry_value_t value) /**< value to check if it is an ArrayBuffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + return ecma_is_arraybuffer (value); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_value_is_arraybuffer */ + +/** + * Creates an ArrayBuffer object with the given length (size). + * + * Notes: + * * the length is specified in bytes. + * * returned value must be freed with jerry_value_free, when it is no longer needed. + * * if the typed arrays are disabled this will return a TypeError. + * + * @return value of the constructed ArrayBuffer object + */ +jerry_value_t +jerry_arraybuffer (const jerry_length_t size) /**< size of the backing store allocated + * for the array buffer in bytes */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + return jerry_return (ecma_make_object_value (ecma_arraybuffer_new_object (size))); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (size); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer */ + +/** + * Creates an ArrayBuffer object with user specified buffer. + * + * Notes: + * * the size is specified in bytes. + * * the buffer passed should be at least the specified bytes big. + * * if the typed arrays are disabled this will return a TypeError. + * * if the size is zero or buffer_p is a null pointer this will return an empty ArrayBuffer. + * + * @return value of the newly constructed array buffer object + */ +jerry_value_t +jerry_arraybuffer_external (uint8_t *buffer_p, /**< the backing store used by the array buffer object */ + jerry_length_t size, /**< size of the buffer in bytes */ + void *user_p) /**< user pointer assigned to the array buffer object */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + ecma_object_t *arraybuffer_p; + + if (JERRY_UNLIKELY (size == 0)) + { + arraybuffer_p = ecma_arraybuffer_new_object (0); + } + else + { + arraybuffer_p = ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_ARRAY_BUFFER, size); + + ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p; + arraybuffer_pointer_p->arraybuffer_user_p = user_p; + + if (buffer_p != NULL) + { + arraybuffer_pointer_p->extended_object.u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED; + arraybuffer_pointer_p->buffer_p = buffer_p; + } + } + + return jerry_return (ecma_make_object_value (arraybuffer_p)); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (size); + JERRY_UNUSED (buffer_p); + JERRY_UNUSED (user_p); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_external */ + +/** + * Check if the given value is a SharedArrayBuffer object. + * + * @return true - if it is a SharedArrayBuffer object + * false - otherwise + */ +bool +jerry_value_is_shared_arraybuffer (const jerry_value_t value) /**< value to check if it is a SharedArrayBuffer */ +{ + return ecma_is_shared_arraybuffer (value); +} /* jerry_value_is_shared_arraybuffer */ + +/** + * Creates a SharedArrayBuffer object with the given length (size). + * + * Notes: + * * the length is specified in bytes. + * * returned value must be freed with jerry_value_free, when it is no longer needed. + * * if the typed arrays are disabled this will return a TypeError. + * + * @return value of the constructed SharedArrayBuffer object + */ +jerry_value_t +jerry_shared_arraybuffer (jerry_length_t size) /**< size of the backing store allocated + * for the shared array buffer in bytes */ +{ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + return jerry_return (ecma_make_object_value (ecma_shared_arraybuffer_new_object (size))); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_UNUSED (size); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_SHARED_ARRAYBUFFER_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +} /* jerry_shared_arraybuffer */ + +/** + * Creates a SharedArrayBuffer object with user specified buffer. + * + * Notes: + * * the size is specified in bytes. + * * the buffer passed should be at least the specified bytes big. + * * if the typed arrays are disabled this will return a TypeError. + * * if the size is zero or buffer_p is a null pointer this will return an empty SharedArrayBuffer. + * + * @return value of the newly constructed shared array buffer object + */ +jerry_value_t +jerry_shared_arraybuffer_external (uint8_t *buffer_p, /**< the backing store used by the + * shared array buffer object */ + jerry_length_t size, /**< size of the buffer in bytes */ + void *user_p) /**< user pointer assigned to the + * shared array buffer object */ +{ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + ecma_object_t *shared_arraybuffer_p; + + if (JERRY_UNLIKELY (size == 0)) + { + shared_arraybuffer_p = ecma_shared_arraybuffer_new_object (0); + } + else + { + shared_arraybuffer_p = ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, size); + + ecma_arraybuffer_pointer_t *shared_arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) shared_arraybuffer_p; + shared_arraybuffer_pointer_p->arraybuffer_user_p = user_p; + + if (buffer_p != NULL) + { + shared_arraybuffer_pointer_p->extended_object.u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED; + shared_arraybuffer_pointer_p->buffer_p = buffer_p; + } + } + + return ecma_make_object_value (shared_arraybuffer_p); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_UNUSED (size); + JERRY_UNUSED (buffer_p); + JERRY_UNUSED (user_p); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_SHARED_ARRAYBUFFER_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +} /* jerry_shared_arraybuffer_external */ + +#if JERRY_BUILTIN_TYPEDARRAY + +/** + * Allocate a backing store for an array buffer, ignores allocation fails. + * + * @return true on success, + * false otherwise + */ +static bool +jerry_arraybuffer_allocate_buffer_no_throw (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */ +{ + JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)); + + if (ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_DETACHED) + { + return false; + } + + return ecma_arraybuffer_allocate_buffer (arraybuffer_p) != ECMA_VALUE_ERROR; +} /* jerry_arraybuffer_allocate_buffer_no_throw */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +/** + * Copy bytes into the ArrayBuffer or SharedArrayBuffer from a buffer. + * + * Note: + * * returns 0, if the passed object is not an ArrayBuffer or SharedArrayBuffer + * + * @return number of bytes copied into the ArrayBuffer or SharedArrayBuffer. + */ +jerry_length_t +jerry_arraybuffer_write (jerry_value_t value, /**< target ArrayBuffer or SharedArrayBuffer */ + jerry_length_t offset, /**< start offset of the ArrayBuffer */ + const uint8_t *buf_p, /**< buffer to copy from */ + jerry_length_t buf_size) /**< number of bytes to copy from the buffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!(ecma_is_arraybuffer (value) || ecma_is_shared_arraybuffer (value))) + { + return 0; + } + + ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value); + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED) + && !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p)) + { + return 0; + } + + jerry_length_t length = ecma_arraybuffer_get_length (arraybuffer_p); + + if (offset >= length) + { + return 0; + } + + jerry_length_t copy_count = JERRY_MIN (length - offset, buf_size); + + if (copy_count > 0) + { + lit_utf8_byte_t *buffer_p = ecma_arraybuffer_get_buffer (arraybuffer_p); + + memcpy ((void *) (buffer_p + offset), (void *) buf_p, copy_count); + } + + return copy_count; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + JERRY_UNUSED (offset); + JERRY_UNUSED (buf_p); + JERRY_UNUSED (buf_size); + return 0; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_write */ + +/** + * Copy bytes from a buffer into an ArrayBuffer or SharedArrayBuffer. + * + * Note: + * * if the object passed is not an ArrayBuffer or SharedArrayBuffer will return 0. + * + * @return number of bytes read from the ArrayBuffer. + */ +jerry_length_t +jerry_arraybuffer_read (const jerry_value_t value, /**< ArrayBuffer or SharedArrayBuffer to read from */ + jerry_length_t offset, /**< start offset of the ArrayBuffer or SharedArrayBuffer */ + uint8_t *buf_p, /**< destination buffer to copy to */ + jerry_length_t buf_size) /**< number of bytes to copy into the buffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!(ecma_is_arraybuffer (value) || ecma_is_shared_arraybuffer (value))) + { + return 0; + } + + ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value); + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED) + && !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p)) + { + return 0; + } + + jerry_length_t length = ecma_arraybuffer_get_length (arraybuffer_p); + + if (offset >= length) + { + return 0; + } + + jerry_length_t copy_count = JERRY_MIN (length - offset, buf_size); + + if (copy_count > 0) + { + lit_utf8_byte_t *buffer_p = ecma_arraybuffer_get_buffer (arraybuffer_p); + + memcpy ((void *) buf_p, (void *) (buffer_p + offset), copy_count); + } + + return copy_count; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + JERRY_UNUSED (offset); + JERRY_UNUSED (buf_p); + JERRY_UNUSED (buf_size); + return 0; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_read */ + +/** + * Get the length (size) of the ArrayBuffer or SharedArrayBuffer in bytes. + * + * Note: + * This is the 'byteLength' property of an ArrayBuffer or SharedArrayBuffer. + * + * @return the length of the ArrayBuffer in bytes. + */ +jerry_length_t +jerry_arraybuffer_size (const jerry_value_t value) /**< ArrayBuffer or SharedArrayBuffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_arraybuffer (value) || ecma_is_shared_arraybuffer (value)) + { + ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value); + return ecma_arraybuffer_get_length (arraybuffer_p); + } +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + return 0; +} /* jerry_arraybuffer_size */ + +/** + * Get a pointer for the start of the ArrayBuffer. + * + * Note: + * * This is a high-risk operation as the bounds are not checked + * when accessing the pointer elements. + * + * @return pointer to the back-buffer of the ArrayBuffer. + * pointer is NULL if: + * - the parameter is not an ArrayBuffer + * - an external ArrayBuffer has been detached + */ +uint8_t * +jerry_arraybuffer_data (const jerry_value_t array_buffer) /**< Array Buffer to use */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!(ecma_is_arraybuffer (array_buffer) || ecma_is_shared_arraybuffer (array_buffer))) + { + return NULL; + } + + ecma_object_t *arraybuffer_p = ecma_get_object_from_value (array_buffer); + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED) + && !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p)) + { + return NULL; + } + + return (uint8_t *) ecma_arraybuffer_get_buffer (arraybuffer_p); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (array_buffer); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + return NULL; +} /* jerry_arraybuffer_data */ + +/** + * Get if the ArrayBuffer is detachable. + * + * @return boolean value - if success + * value marked with error flag - otherwise + */ +bool +jerry_arraybuffer_is_detachable (const jerry_value_t value) /**< ArrayBuffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_arraybuffer (value)) + { + ecma_object_t *buffer_p = ecma_get_object_from_value (value); + return !ecma_arraybuffer_is_detached (buffer_p); + } +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + return false; +} /* jerry_arraybuffer_is_detachable */ + +/** + * Detach the underlying data block from ArrayBuffer and set its bytelength to 0. + * + * Note: if the ArrayBuffer has a separate data buffer, the free callback set by + * jerry_arraybuffer_set_allocation_callbacks is called for this buffer + * + * @return null value - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_arraybuffer_detach (jerry_value_t value) /**< ArrayBuffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_arraybuffer (value)) + { + ecma_object_t *buffer_p = ecma_get_object_from_value (value); + if (ecma_arraybuffer_detach (buffer_p)) + { + return ECMA_VALUE_NULL; + } + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_ARRAY_BUFFER_DETACHED)); + } +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_EXPECTED_AN_ARRAYBUFFER)); +} /* jerry_arraybuffer_detach */ + +/** + * Checks whether a buffer is currently allocated for an array buffer or typed array. + * + * @return true, if a buffer is allocated for an array buffer or typed array + * false, otherwise + */ +bool +jerry_arraybuffer_has_buffer (const jerry_value_t value) /**< array buffer or typed array value */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!ecma_is_value_object (value)) + { + return false; + } + + ecma_object_t *object_p = ecma_get_object_from_value (value); + + if (ecma_object_is_typedarray (object_p)) + { + object_p = ecma_typedarray_get_arraybuffer (object_p); + } + else if (!(ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (object_p))) + { + return false; + } + + return (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_ALLOCATED) != 0; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_has_buffer */ + +/** + * Array buffers which size is less or equal than the limit passed to this function are allocated in + * a single memory block. The allocator callbacks set by jerry_arraybuffer_set_allocation_callbacks + * are not called for these array buffers. The default limit is 256 bytes. + */ +void +jerry_arraybuffer_heap_allocation_limit (jerry_length_t allocation_limit) /**< maximum size of + * compact allocation */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + JERRY_CONTEXT (arraybuffer_compact_allocation_limit) = allocation_limit; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (allocation_limit); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_heap_allocation_limit */ + +/** + * Set callbacks for allocating and freeing backing stores for array buffer objects. + */ +void +jerry_arraybuffer_allocator (jerry_arraybuffer_allocate_cb_t allocate_callback, /**< callback for allocating + * array buffer memory */ + jerry_arraybuffer_free_cb_t free_callback, /**< callback for freeing + * array buffer memory */ + void *user_p) /**< user pointer passed to the callbacks */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + JERRY_CONTEXT (arraybuffer_allocate_callback) = allocate_callback; + JERRY_CONTEXT (arraybuffer_free_callback) = free_callback; + JERRY_CONTEXT (arraybuffer_allocate_callback_user_p) = user_p; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (allocate_callback); + JERRY_UNUSED (free_callback); + JERRY_UNUSED (user_p); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_allocator */ + +/** + * DataView related functions + */ + +/** + * Creates a DataView object with the given ArrayBuffer, ByteOffset and ByteLength arguments. + * + * Notes: + * * returned value must be freed with jerry_value_free, when it is no longer needed. + * * if the DataView bulitin is disabled this will return a TypeError. + * + * @return value of the constructed DataView object - if success + * created error - otherwise + */ +jerry_value_t +jerry_dataview (const jerry_value_t array_buffer, /**< arraybuffer to create DataView from */ + jerry_length_t byte_offset, /**< offset in bytes, to the first byte in the buffer */ + jerry_length_t byte_length) /**< number of elements in the byte array */ +{ +#if JERRY_BUILTIN_DATAVIEW + if (ecma_is_value_exception (array_buffer)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_value_t arguments_p[3] = { array_buffer, + ecma_make_uint32_value (byte_offset), + ecma_make_uint32_value (byte_length) }; + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + if (old_new_target_p == NULL) + { + JERRY_CONTEXT (current_new_target_p) = ecma_builtin_get (ECMA_BUILTIN_ID_DATAVIEW); + } + + ecma_value_t dataview_value = ecma_op_dataview_create (arguments_p, 3); + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + return jerry_return (dataview_value); +#else /* !JERRY_BUILTIN_DATAVIEW */ + JERRY_UNUSED (array_buffer); + JERRY_UNUSED (byte_offset); + JERRY_UNUSED (byte_length); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_DATA_VIEW_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_DATAVIEW */ +} /* jerry_dataview */ + +/** + * Check if the given value is a DataView object. + * + * @return true - if it is a DataView object + * false - otherwise + */ +bool +jerry_value_is_dataview (const jerry_value_t value) /**< value to check if it is a DataView object */ +{ +#if JERRY_BUILTIN_DATAVIEW + return ecma_is_dataview (value); +#else /* !JERRY_BUILTIN_DATAVIEW */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_DATAVIEW */ +} /* jerry_value_is_dataview */ + +/** + * Get the underlying ArrayBuffer from a DataView. + * + * Additionally the byteLength and byteOffset properties are also returned + * which were specified when the DataView was created. + * + * Note: + * the returned value must be freed with a jerry_value_free call + * + * @return ArrayBuffer of a DataView + * TypeError if the object is not a DataView. + */ +jerry_value_t +jerry_dataview_buffer (const jerry_value_t value, /**< DataView to get the arraybuffer from */ + jerry_length_t *byte_offset, /**< [out] byteOffset property */ + jerry_length_t *byte_length) /**< [out] byteLength property */ +{ +#if JERRY_BUILTIN_DATAVIEW + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_dataview_object_t *dataview_p = ecma_op_dataview_get_object (value); + + if (JERRY_UNLIKELY (dataview_p == NULL)) + { + return ecma_create_exception_from_context (); + } + + if (byte_offset != NULL) + { + *byte_offset = dataview_p->byte_offset; + } + + if (byte_length != NULL) + { + *byte_length = dataview_p->header.u.cls.u3.length; + } + + ecma_object_t *arraybuffer_p = dataview_p->buffer_p; + ecma_ref_object (arraybuffer_p); + + return ecma_make_object_value (arraybuffer_p); +#else /* !JERRY_BUILTIN_DATAVIEW */ + JERRY_UNUSED (value); + JERRY_UNUSED (byte_offset); + JERRY_UNUSED (byte_length); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_DATA_VIEW_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_DATAVIEW */ +} /* jerry_dataview_buffer */ + +/** + * TypedArray related functions + */ + +/** + * Check if the given value is a TypedArray object. + * + * @return true - if it is a TypedArray object + * false - otherwise + */ +bool +jerry_value_is_typedarray (const jerry_value_t value) /**< value to check if it is a TypedArray */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + return ecma_is_typedarray (value); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_value_is_typedarray */ + +#if JERRY_BUILTIN_TYPEDARRAY +/** + * TypedArray mapping type + */ +typedef struct +{ + jerry_typedarray_type_t api_type; /**< api type */ + ecma_builtin_id_t prototype_id; /**< prototype ID */ + ecma_typedarray_type_t id; /**< typedArray ID */ + uint8_t element_size_shift; /**< element size shift */ +} jerry_typedarray_mapping_t; + +/** + * List of TypedArray mappings + */ +static jerry_typedarray_mapping_t jerry_typedarray_mappings[] = { +#define TYPEDARRAY_ENTRY(NAME, LIT_NAME, SIZE_SHIFT) \ + { \ + JERRY_TYPEDARRAY_##NAME, ECMA_BUILTIN_ID_##NAME##ARRAY_PROTOTYPE, ECMA_##LIT_NAME##_ARRAY, SIZE_SHIFT \ + } + + TYPEDARRAY_ENTRY (UINT8, UINT8, 0), TYPEDARRAY_ENTRY (UINT8CLAMPED, UINT8_CLAMPED, 0), + TYPEDARRAY_ENTRY (INT8, INT8, 0), TYPEDARRAY_ENTRY (UINT16, UINT16, 1), + TYPEDARRAY_ENTRY (INT16, INT16, 1), TYPEDARRAY_ENTRY (UINT32, UINT32, 2), + TYPEDARRAY_ENTRY (INT32, INT32, 2), TYPEDARRAY_ENTRY (FLOAT32, FLOAT32, 2), +#if JERRY_NUMBER_TYPE_FLOAT64 + TYPEDARRAY_ENTRY (FLOAT64, FLOAT64, 3), +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + TYPEDARRAY_ENTRY (BIGINT64, BIGINT64, 3), TYPEDARRAY_ENTRY (BIGUINT64, BIGUINT64, 3), +#endif /* JERRY_BUILTIN_BIGINT */ +#undef TYPEDARRAY_ENTRY +}; + +/** + * Helper function to get the TypedArray prototype, typedArray id, and element size shift + * information. + * + * @return true - if the TypedArray information was found + * false - if there is no such TypedArray type + */ +static bool +jerry_typedarray_find_by_type (jerry_typedarray_type_t type_name, /**< type of the TypedArray */ + ecma_builtin_id_t *prototype_id, /**< [out] found prototype object id */ + ecma_typedarray_type_t *id, /**< [out] found typedArray id */ + uint8_t *element_size_shift) /**< [out] found element size shift value */ +{ + JERRY_ASSERT (prototype_id != NULL); + JERRY_ASSERT (id != NULL); + JERRY_ASSERT (element_size_shift != NULL); + + for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++) + { + if (type_name == jerry_typedarray_mappings[i].api_type) + { + *prototype_id = jerry_typedarray_mappings[i].prototype_id; + *id = jerry_typedarray_mappings[i].id; + *element_size_shift = jerry_typedarray_mappings[i].element_size_shift; + return true; + } + } + + return false; +} /* jerry_typedarray_find_by_type */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +/** + * Create a TypedArray object with a given type and length. + * + * Notes: + * * returns TypeError if an incorrect type (type_name) is specified. + * * byteOffset property will be set to 0. + * * byteLength property will be a multiple of the length parameter (based on the type). + * + * @return - new TypedArray object + */ +jerry_value_t +jerry_typedarray (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */ + jerry_length_t length) /**< element count of the new TypedArray */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + ecma_builtin_id_t prototype_id = (ecma_builtin_id_t) 0; + ecma_typedarray_type_t id = (ecma_typedarray_type_t) 0; + uint8_t element_size_shift = 0; + + if (!jerry_typedarray_find_by_type (type_name, &prototype_id, &id, &element_size_shift)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_FOR_TYPEDARRAY)); + } + + ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id); + + ecma_value_t array_value = + ecma_typedarray_create_object_with_length (length, NULL, prototype_obj_p, element_size_shift, id); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (array_value)); + + return array_value; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (type_name); + JERRY_UNUSED (length); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_typedarray */ + +/** + * Create a TypedArray object using the given arraybuffer and size information. + * + * Notes: + * * returns TypeError if an incorrect type (type_name) is specified. + * * this is the 'new %TypedArray%(arraybuffer, byteOffset, length)' equivalent call. + * + * @return - new TypedArray object + */ +jerry_value_t +jerry_typedarray_with_buffer_span (jerry_typedarray_type_t type, /**< type of TypedArray to create */ + const jerry_value_t arraybuffer, /**< ArrayBuffer to use */ + jerry_length_t byte_offset, /**< offset for the ArrayBuffer */ + jerry_length_t length) /**< number of elements to use from ArrayBuffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_value_exception (arraybuffer)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + ecma_builtin_id_t prototype_id = (ecma_builtin_id_t) 0; + ecma_typedarray_type_t id = (ecma_typedarray_type_t) 0; + uint8_t element_size_shift = 0; + + if (!jerry_typedarray_find_by_type (type, &prototype_id, &id, &element_size_shift)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_FOR_TYPEDARRAY)); + } + + if (!ecma_is_arraybuffer (arraybuffer)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_ARGUMENT_NOT_ARRAY_BUFFER)); + } + + ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id); + ecma_value_t arguments_p[3] = { arraybuffer, ecma_make_uint32_value (byte_offset), ecma_make_uint32_value (length) }; + + ecma_value_t array_value = ecma_op_create_typedarray (arguments_p, 3, prototype_obj_p, element_size_shift, id); + ecma_free_value (arguments_p[1]); + ecma_free_value (arguments_p[2]); + + return jerry_return (array_value); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (type); + JERRY_UNUSED (arraybuffer); + JERRY_UNUSED (byte_offset); + JERRY_UNUSED (length); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_typedarray_with_buffer_span */ + +/** + * Create a TypedArray object using the given arraybuffer and size information. + * + * Notes: + * * returns TypeError if an incorrect type (type_name) is specified. + * * this is the 'new %TypedArray%(arraybuffer)' equivalent call. + * + * @return - new TypedArray object + */ +jerry_value_t +jerry_typedarray_with_buffer (jerry_typedarray_type_t type, /**< type of TypedArray to create */ + const jerry_value_t arraybuffer) /**< ArrayBuffer to use */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_value_exception (arraybuffer)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + jerry_length_t byte_length = jerry_arraybuffer_size (arraybuffer); + return jerry_typedarray_with_buffer_span (type, arraybuffer, 0, byte_length); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (type); + JERRY_UNUSED (arraybuffer); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_typedarray_with_buffer */ + +/** + * Get the type of the TypedArray. + * + * @return - type of the TypedArray + * - JERRY_TYPEDARRAY_INVALID if the argument is not a TypedArray + */ +jerry_typedarray_type_t +jerry_typedarray_type (const jerry_value_t value) /**< object to get the TypedArray type */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!ecma_is_typedarray (value)) + { + return JERRY_TYPEDARRAY_INVALID; + } + + ecma_object_t *array_p = ecma_get_object_from_value (value); + ecma_typedarray_type_t class_type = ecma_get_typedarray_id (array_p); + + for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++) + { + if (class_type == jerry_typedarray_mappings[i].id) + { + return jerry_typedarray_mappings[i].api_type; + } + } +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + return JERRY_TYPEDARRAY_INVALID; +} /* jerry_typedarray_type */ + +/** + * Get the element count of the TypedArray. + * + * @return length of the TypedArray. + */ +jerry_length_t +jerry_typedarray_length (const jerry_value_t value) /**< TypedArray to query */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_typedarray (value)) + { + ecma_object_t *array_p = ecma_get_object_from_value (value); + return ecma_typedarray_get_length (array_p); + } +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + return 0; +} /* jerry_typedarray_length */ + +/** + * Get the underlying ArrayBuffer from a TypedArray. + * + * Additionally the byteLength and byteOffset properties are also returned + * which were specified when the TypedArray was created. + * + * Note: + * the returned value must be freed with a jerry_value_free call + * + * @return ArrayBuffer of a TypedArray + * TypeError if the object is not a TypedArray. + */ +jerry_value_t +jerry_typedarray_buffer (const jerry_value_t value, /**< TypedArray to get the arraybuffer from */ + jerry_length_t *byte_offset, /**< [out] byteOffset property */ + jerry_length_t *byte_length) /**< [out] byteLength property */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!ecma_is_typedarray (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_OBJECT_IS_NOT_A_TYPEDARRAY)); + } + + ecma_object_t *array_p = ecma_get_object_from_value (value); + uint8_t shift = ecma_typedarray_get_element_size_shift (array_p); + + if (byte_length != NULL) + { + *byte_length = (jerry_length_t) (ecma_typedarray_get_length (array_p) << shift); + } + + if (byte_offset != NULL) + { + *byte_offset = (jerry_length_t) ecma_typedarray_get_offset (array_p); + } + + ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (array_p); + ecma_ref_object (arraybuffer_p); + return jerry_return (ecma_make_object_value (arraybuffer_p)); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + JERRY_UNUSED (byte_length); + JERRY_UNUSED (byte_offset); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_typedarray_buffer */ + + +/** + * Create a container type specified in jerry_container_type_t. + * The container can be created with a list of arguments, which will be passed to the container constructor to be + * inserted to the container. + * + * Note: + * The returned value must be freed with jerry_value_free + * @return jerry_value_t representing a container with the given type. + */ +jerry_value_t +jerry_container (jerry_container_type_t container_type, /**< Type of the container */ + const jerry_value_t *arguments_list_p, /**< arguments list */ + jerry_length_t arguments_list_len) /**< Length of arguments list */ +{ +#if JERRY_BUILTIN_CONTAINER + for (jerry_length_t i = 0; i < arguments_list_len; i++) + { + if (ecma_is_value_exception (arguments_list_p[i])) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + } + + lit_magic_string_id_t lit_id; + ecma_builtin_id_t proto_id; + ecma_builtin_id_t ctor_id; + + switch (container_type) + { + case JERRY_CONTAINER_TYPE_MAP: + { + lit_id = LIT_MAGIC_STRING_MAP_UL; + proto_id = ECMA_BUILTIN_ID_MAP_PROTOTYPE; + ctor_id = ECMA_BUILTIN_ID_MAP; + break; + } + case JERRY_CONTAINER_TYPE_SET: + { + lit_id = LIT_MAGIC_STRING_SET_UL; + proto_id = ECMA_BUILTIN_ID_SET_PROTOTYPE; + ctor_id = ECMA_BUILTIN_ID_SET; + break; + } + case JERRY_CONTAINER_TYPE_WEAKMAP: + { + lit_id = LIT_MAGIC_STRING_WEAKMAP_UL; + proto_id = ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE; + ctor_id = ECMA_BUILTIN_ID_WEAKMAP; + break; + } + case JERRY_CONTAINER_TYPE_WEAKSET: + { + lit_id = LIT_MAGIC_STRING_WEAKSET_UL; + proto_id = ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE; + ctor_id = ECMA_BUILTIN_ID_WEAKSET; + break; + } + default: + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INVALID_CONTAINER_TYPE)); + } + } + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + + if (old_new_target_p == NULL) + { + JERRY_CONTEXT (current_new_target_p) = ecma_builtin_get (ctor_id); + } + + ecma_value_t container_value = ecma_op_container_create (arguments_list_p, arguments_list_len, lit_id, proto_id); + + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + return jerry_return (container_value); +#else /* !JERRY_BUILTIN_CONTAINER */ + JERRY_UNUSED (arguments_list_p); + JERRY_UNUSED (arguments_list_len); + JERRY_UNUSED (container_type); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_CONTAINER */ +} /* jerry_container */ + +/** + * Get the type of the given container object. + * + * @return Corresponding type to the given container object. + */ +jerry_container_type_t +jerry_container_type (const jerry_value_t value) /**< the container object */ +{ +#if JERRY_BUILTIN_CONTAINER + if (ecma_is_value_object (value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + if (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_CONTAINER)) + { + switch (((ecma_extended_object_t *) obj_p)->u.cls.u2.container_id) + { + case LIT_MAGIC_STRING_MAP_UL: + { + return JERRY_CONTAINER_TYPE_MAP; + } + case LIT_MAGIC_STRING_SET_UL: + { + return JERRY_CONTAINER_TYPE_SET; + } + case LIT_MAGIC_STRING_WEAKMAP_UL: + { + return JERRY_CONTAINER_TYPE_WEAKMAP; + } + case LIT_MAGIC_STRING_WEAKSET_UL: + { + return JERRY_CONTAINER_TYPE_WEAKSET; + } + default: + { + return JERRY_CONTAINER_TYPE_INVALID; + } + } + } + } + +#else /* !JERRY_BUILTIN_CONTAINER */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_CONTAINER */ + return JERRY_CONTAINER_TYPE_INVALID; +} /* jerry_container_type */ + +/** + * Return a new array containing elements from a Container or a Container Iterator. + * Sets the boolean input value to `true` if the container object has key/value pairs. + * + * Note: + * the returned value must be freed with a jerry_value_free call + * + * @return an array of items for maps/sets or their iterators, error otherwise + */ +jerry_value_t +jerry_container_to_array (const jerry_value_t value, /**< the container or iterator object */ + bool *is_key_value_p) /**< [out] is key-value structure */ +{ +#if JERRY_BUILTIN_CONTAINER + if (!ecma_is_value_object (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NEEDED)); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_CLASS) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NEEDED)); + } + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + uint32_t entry_count; + uint8_t entry_size; + + uint32_t index = 0; + uint8_t iterator_kind = ECMA_ITERATOR__COUNT; + ecma_value_t *start_p; + + *is_key_value_p = false; + + if (ext_obj_p->u.cls.type == ECMA_OBJECT_CLASS_MAP_ITERATOR + || ext_obj_p->u.cls.type == ECMA_OBJECT_CLASS_SET_ITERATOR) + { + ecma_value_t iterated_value = ext_obj_p->u.cls.u3.iterated_value; + + if (ecma_is_value_empty (iterated_value)) + { + return ecma_op_new_array_object_from_collection (ecma_new_collection (), false); + } + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) (ecma_get_object_from_value (iterated_value)); + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + index = ext_obj_p->u.cls.u2.iterator_index; + + entry_size = ecma_op_container_entry_size ((lit_magic_string_id_t) map_object_p->u.cls.u2.container_id); + start_p = ECMA_CONTAINER_START (container_p); + + iterator_kind = ext_obj_p->u.cls.u1.iterator_kind; + } + else if (jerry_container_type (value) != JERRY_CONTAINER_TYPE_INVALID) + { + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, ext_obj_p->u.cls.u3.value); + entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + entry_size = ecma_op_container_entry_size ((lit_magic_string_id_t) ext_obj_p->u.cls.u2.container_id); + + index = 0; + iterator_kind = ECMA_ITERATOR_KEYS; + start_p = ECMA_CONTAINER_START (container_p); + + if (ext_obj_p->u.cls.u2.container_id == LIT_MAGIC_STRING_MAP_UL + || ext_obj_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKMAP_UL) + { + iterator_kind = ECMA_ITERATOR_ENTRIES; + } + } + else + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NEEDED)); + } + + *is_key_value_p = (iterator_kind == ECMA_ITERATOR_ENTRIES); + ecma_collection_t *collection_buffer = ecma_new_collection (); + + for (uint32_t i = index; i < entry_count; i += entry_size) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_is_value_empty (*entry_p)) + { + continue; + } + + if (iterator_kind != ECMA_ITERATOR_VALUES) + { + ecma_collection_push_back (collection_buffer, ecma_copy_value_if_not_object (entry_p[0])); + } + + if (iterator_kind != ECMA_ITERATOR_KEYS) + { + ecma_collection_push_back (collection_buffer, ecma_copy_value_if_not_object (entry_p[1])); + } + } + return ecma_op_new_array_object_from_collection (collection_buffer, false); +#else /* !JERRY_BUILTIN_CONTAINER */ + JERRY_UNUSED (value); + JERRY_UNUSED (is_key_value_p); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_CONTAINER */ +} /* jerry_container_to_array */ + +/** + * Perform container operation on the given operands (add, get, set, has, delete, size, clear). + * + * @return error - if argument is invalid or operation is unsuccessful or unsupported + * result of the container operation - otherwise. + */ +jerry_value_t +jerry_container_op (jerry_container_op_t operation, /**< container operation */ + jerry_value_t container, /**< container */ + const jerry_value_t *arguments, /**< list of arguments */ + uint32_t arguments_number) /**< number of arguments */ +{ +#if JERRY_BUILTIN_CONTAINER + if (!ecma_is_value_object (container)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_IS_NOT_AN_OBJECT)); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (container); + + if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_CLASS) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_IS_NOT_A_CONTAINER_OBJECT)); + } + uint16_t type = ((ecma_extended_object_t *) obj_p)->u.cls.u2.container_id; + ecma_extended_object_t *container_object_p = ecma_op_container_get_object (container, (lit_magic_string_id_t) type); + + if (container_object_p == NULL) + { + return ecma_create_exception_from_context (); + } + + switch (operation) + { + case JERRY_CONTAINER_OP_ADD: + case JERRY_CONTAINER_OP_DELETE: + case JERRY_CONTAINER_OP_GET: + case JERRY_CONTAINER_OP_HAS: + { + if (arguments_number != 1 || ecma_is_value_exception (arguments[0])) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + break; + } + case JERRY_CONTAINER_OP_SET: + { + if (arguments_number != 2 || ecma_is_value_exception (arguments[0]) || ecma_is_value_exception (arguments[1])) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + break; + } + case JERRY_CONTAINER_OP_CLEAR: + case JERRY_CONTAINER_OP_SIZE: + { + if (arguments_number != 0) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + break; + } + default: + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + } + + jerry_value_t result; + + switch (operation) + { + case JERRY_CONTAINER_OP_ADD: + { + if (type == LIT_MAGIC_STRING_MAP_UL || type == LIT_MAGIC_STRING_WEAKMAP_UL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_CALL)); + } + result = ecma_op_container_set (container_object_p, arguments[0], arguments[0], (lit_magic_string_id_t) type); + break; + } + case JERRY_CONTAINER_OP_GET: + { + if (type == LIT_MAGIC_STRING_SET_UL || type == LIT_MAGIC_STRING_WEAKSET_UL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_CALL)); + } + result = ecma_op_container_get (container_object_p, arguments[0], (lit_magic_string_id_t) type); + break; + } + case JERRY_CONTAINER_OP_SET: + { + if (type == LIT_MAGIC_STRING_SET_UL || type == LIT_MAGIC_STRING_WEAKSET_UL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_CALL)); + } + result = ecma_op_container_set (container_object_p, arguments[0], arguments[1], (lit_magic_string_id_t) type); + break; + } + case JERRY_CONTAINER_OP_HAS: + { + result = ecma_op_container_has (container_object_p, arguments[0], (lit_magic_string_id_t) type); + break; + } + case JERRY_CONTAINER_OP_DELETE: + { + if (type == LIT_MAGIC_STRING_WEAKMAP_UL || type == LIT_MAGIC_STRING_WEAKSET_UL) + { + result = ecma_op_container_delete_weak (container_object_p, arguments[0], (lit_magic_string_id_t) type); + break; + } + result = ecma_op_container_delete (container_object_p, arguments[0], (lit_magic_string_id_t) type); + break; + } + case JERRY_CONTAINER_OP_SIZE: + { + result = ecma_op_container_size (container_object_p); + break; + } + case JERRY_CONTAINER_OP_CLEAR: + { + if (type == LIT_MAGIC_STRING_WEAKSET_UL || type == LIT_MAGIC_STRING_WEAKMAP_UL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_CALL)); + } + result = ecma_op_container_clear (container_object_p); + break; + } + default: + { + result = jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_UNSUPPORTED_CONTAINER_OPERATION)); + break; + } + } + return jerry_return (result); +#else /* !JERRY_BUILTIN_CONTAINER */ + JERRY_UNUSED (operation); + JERRY_UNUSED (container); + JERRY_UNUSED (arguments); + JERRY_UNUSED (arguments_number); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_CONTAINER */ +} /* jerry_container_op */ + +/** + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/api/meson.build b/src/loaders/lottie/jerryscript/jerry-core/api/meson.build new file mode 100644 index 00000000..b20f50cd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/api/meson.build @@ -0,0 +1,8 @@ +source_file = [ + 'jerryscript.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.cpp new file mode 100644 index 00000000..0a39565b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.cpp @@ -0,0 +1,232 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" + +#include "ecma-gc.h" +#include "ecma-globals.h" + +#include "jmem.h" +#include "jrt.h" + +JERRY_STATIC_ASSERT ((sizeof (ecma_property_value_t) == sizeof (ecma_value_t)), + size_of_ecma_property_value_t_must_be_equal_to_size_of_ecma_value_t); +JERRY_STATIC_ASSERT (((sizeof (ecma_property_value_t) - 1) & sizeof (ecma_property_value_t)) == 0, + size_of_ecma_property_value_t_must_be_power_of_2); + +JERRY_STATIC_ASSERT ((sizeof (ecma_extended_object_t) - sizeof (ecma_object_t) <= sizeof (uint64_t)), + size_of_ecma_extended_object_part_must_be_less_than_or_equal_to_8_bytes); + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types + * @{ + */ + +/** + * Implementation of routines for allocation/freeing memory for ECMA data types. + * + * All allocation routines from this module have the same structure: + * 1. Try to allocate memory. + * 2. If allocation was successful, return pointer to the allocated block. + * 3. Run garbage collection. + * 4. Try to allocate memory. + * 5. If allocation was successful, return pointer to the allocated block; + * else - shutdown engine. + */ + +/** + * Allocate memory for ecma-number + * + * @return pointer to allocated memory + */ +ecma_number_t * +ecma_alloc_number (void) +{ + return (ecma_number_t *) jmem_pools_alloc (sizeof (ecma_number_t)); +} /* ecma_alloc_number */ + +/** + * Dealloc memory from an ecma-number + * + * @return void + */ +void +ecma_dealloc_number (ecma_number_t *number_p) /**< number to be freed */ +{ + jmem_pools_free ((uint8_t *) number_p, sizeof (ecma_number_t)); +} /* ecma_dealloc_number */ + +/** + * Allocate memory for ecma-object + * + * @return pointer to allocated memory + */ +ecma_object_t * +ecma_alloc_object (void) +{ + return (ecma_object_t *) jmem_pools_alloc (sizeof (ecma_object_t)); +} /* ecma_alloc_object */ + +/** + * Dealloc memory from an ecma-object + * + * @return void + */ +void +ecma_dealloc_object (ecma_object_t *object_p) /**< object to be freed */ +{ + jmem_pools_free (object_p, sizeof (ecma_object_t)); +} /* ecma_dealloc_object */ + +/** + * Allocate memory for extended object + * + * @return pointer to allocated memory + */ +ecma_extended_object_t * +ecma_alloc_extended_object (size_t size) /**< size of object */ +{ + return (ecma_extended_object_t *) jmem_heap_alloc_block (size); +} /* ecma_alloc_extended_object */ + +/** + * Dealloc memory of an extended object + * + * @return void + */ +void +ecma_dealloc_extended_object (ecma_object_t *object_p, /**< extended object */ + size_t size) /**< size of object */ +{ + jmem_heap_free_block (object_p, size); +} /* ecma_dealloc_extended_object */ + +/** + * Allocate memory for ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_string_t * +ecma_alloc_string (void) +{ + return (ecma_string_t *) jmem_pools_alloc (sizeof (ecma_string_t)); +} /* ecma_alloc_string */ + +/** + * Dealloc memory from ecma-string descriptor + * + * @return void + */ +void +ecma_dealloc_string (ecma_string_t *string_p) /**< string to be freed */ +{ + jmem_pools_free (string_p, sizeof (ecma_string_t)); +} /* ecma_dealloc_string */ + +/** + * Allocate memory for extended ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_extended_string_t * +ecma_alloc_extended_string (void) +{ + return (ecma_extended_string_t *) jmem_heap_alloc_block (sizeof (ecma_extended_string_t)); +} /* ecma_alloc_extended_string */ + +/** + * Dealloc memory from extended ecma-string descriptor + * + * @return void + */ +void +ecma_dealloc_extended_string (ecma_extended_string_t *ext_string_p) /**< extended string to be freed */ +{ + jmem_heap_free_block (ext_string_p, sizeof (ecma_extended_string_t)); +} /* ecma_dealloc_extended_string */ + +/** + * Allocate memory for external ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_external_string_t * +ecma_alloc_external_string (void) +{ + return (ecma_external_string_t *) jmem_heap_alloc_block (sizeof (ecma_external_string_t)); +} /* ecma_alloc_external_string */ + +/** + * Dealloc memory from external ecma-string descriptor + * + * @return void + */ +void +ecma_dealloc_external_string (ecma_external_string_t *ext_string_p) /**< external string to be freed */ +{ + jmem_heap_free_block (ext_string_p, sizeof (ecma_external_string_t)); +} /* ecma_dealloc_external_string */ + +/** + * Allocate memory for an string with character data + * + * @return pointer to allocated memory + */ +ecma_string_t * +ecma_alloc_string_buffer (size_t size) /**< size of string */ +{ + return (ecma_string_t *) jmem_heap_alloc_block (size); +} /* ecma_alloc_string_buffer */ + +/** + * Dealloc memory of a string with character data + * + * @return void + */ +void +ecma_dealloc_string_buffer (ecma_string_t *string_p, /**< string with data */ + size_t size) /**< size of string */ +{ + jmem_heap_free_block (string_p, size); +} /* ecma_dealloc_string_buffer */ + +/** + * Allocate memory for ecma-property pair + * + * @return pointer to allocated memory + */ +ecma_property_pair_t * +ecma_alloc_property_pair (void) +{ + return (ecma_property_pair_t *) jmem_heap_alloc_block (sizeof (ecma_property_pair_t)); +} /* ecma_alloc_property_pair */ + +/** + * Dealloc memory of an ecma-property + * + * @return void + */ +void +ecma_dealloc_property_pair (ecma_property_pair_t *property_pair_p) /**< property pair to be freed */ +{ + jmem_heap_free_block (property_pair_p, sizeof (ecma_property_pair_t)); +} /* ecma_dealloc_property_pair */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.h new file mode 100644 index 00000000..a5af9d1a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.h @@ -0,0 +1,129 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ALLOC_H +#define ECMA_ALLOC_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types + * @{ + */ + +/** + * Allocate memory for ecma-object + * + * @return pointer to allocated memory + */ +ecma_object_t *ecma_alloc_object (void); + +/** + * Dealloc memory from an ecma-object + */ +void ecma_dealloc_object (ecma_object_t *object_p); + +/** + * Allocate memory for extended object + * + * @return pointer to allocated memory + */ +ecma_extended_object_t *ecma_alloc_extended_object (size_t size); + +/** + * Dealloc memory of an extended object + */ +void ecma_dealloc_extended_object (ecma_object_t *object_p, size_t size); + +/** + * Allocate memory for ecma-number + * + * @return pointer to allocated memory + */ +ecma_number_t *ecma_alloc_number (void); + +/** + * Dealloc memory from an ecma-number + */ +void ecma_dealloc_number (ecma_number_t *number_p); + +/** + * Allocate memory for ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_string_t *ecma_alloc_string (void); + +/** + * Dealloc memory from ecma-string descriptor + */ +void ecma_dealloc_string (ecma_string_t *string_p); + +/** + * Allocate memory for extended ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_extended_string_t *ecma_alloc_extended_string (void); + +/** + * Dealloc memory from extended ecma-string descriptor + */ +void ecma_dealloc_extended_string (ecma_extended_string_t *string_p); + +/** + * Allocate memory for external ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_external_string_t *ecma_alloc_external_string (void); + +/** + * Dealloc memory from external ecma-string descriptor + */ +void ecma_dealloc_external_string (ecma_external_string_t *string_p); + +/** + * Allocate memory for string with character data + * + * @return pointer to allocated memory + */ +ecma_string_t *ecma_alloc_string_buffer (size_t size); + +/** + * Dealloc memory of a string with character data + */ +void ecma_dealloc_string_buffer (ecma_string_t *string_p, size_t size); + +/** + * Allocate memory for ecma-property pair + * + * @return pointer to allocated memory + */ +ecma_property_pair_t *ecma_alloc_property_pair (void); + +/** + * Dealloc memory from an ecma-property pair + */ +void ecma_dealloc_property_pair (ecma_property_pair_t *property_pair_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_ALLOC_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.inc.h new file mode 100644 index 00000000..ff4d936e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.inc.h @@ -0,0 +1,743 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-strings.py script + * from ecma-error-messages.ini. Do not edit! */ + +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_GROUP, "Invalid group") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ESCAPE, "Invalid escape") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_LENGTH, "Invalid length") +#endif /* JERRY_BUILTIN_ATOMICS \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_OFFSET, "Invalid offset") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_OBJECT_EXPECTED, "Object expected") +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ARGUMENT, "Invalid argument") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ENCODING, "Invalid encoding") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_NOTHING_TO_REPEAT, "Nothing to repeat") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_AN_OBJECT, "Expected an object") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CAPABILITY, "Invalid capability") +#if JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CODE_POINT, "Invalid code point") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_QUANTIFIER, "Invalid quantifier") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_NO_SOURCE_ARGUMENT, "No source argument") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_UNTERMINATED_GROUP, "Unterminated group") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_A_FUNCTION, "Expected a function") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_UTF8_STRING, "Invalid UTF8 string") +#if JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_INVALID_COUNT_VALUE, "Invalid count value") +#endif /* JERRY_BUILTIN_STRING */ +#if !(JERRY_BUILTIN_REALMS) +ECMA_ERROR_DEF (ECMA_ERR_REALMS_ARE_DISABLED, "Realms are disabled") +#endif /* !(JERRY_BUILTIN_REALMS) */ +ECMA_ERROR_DEF (ECMA_ERR_UNDEFINED_REFERENCE, "Undefined reference") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ARRAY_LENGTH, "Invalid Array length") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_REGEXP_FLAGS, "Invalid RegExp flags") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_STACK_LIMIT_EXCEEDED, "Stack limit exceeded") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_WEAKREF +ECMA_ERROR_DEF (ECMA_ERR_TARGET_IS_NOT_OBJECT, "Target is not Object") +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_BIGINT_VALUE_EXCPECTED, "BigInt value expected") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_BINDING_CANNOT_SET, "Binding cannot be set") +#if JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_INVALID_STRING_, "Invalid string length") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_KEY_MUST_BE_AN_OBJECT, "Key must be an object") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_MISSING_ARRAY_ELEMENT, "Missing Array element") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_WEAKREF +ECMA_ERROR_DEF (ECMA_ERR_TARGET_IS_NOT_WEAKREF, "Target is not weakRef") +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TARGET_NOT_EXTENSIBLE, "Target not extensible") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_ANNEXB +ECMA_ERROR_DEF (ECMA_ERR_GETTER_IS_NOT_CALLABLE, "Getter is not callable") +#endif /* JERRY_BUILTIN_ANNEXB */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_HANDLER_CANNOT_BE_NULL, "Handler cannot be null") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_UTF8_CHARACTER, "Invalid UTF8 character") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_UTF8_CODEPOINT, "Invalid UTF8 codepoint") +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CONTAINER_TYPE, "Invalid container type") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_RANGE_OF_INDEX, "Invalid range of index") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if !(JERRY_BUILTIN_PROXY) +ECMA_ERROR_DEF (ECMA_ERR_PROXY_IS_NOT_SUPPORTED, "Proxy is not supported") +#endif /* !(JERRY_BUILTIN_PROXY) */ +#if !(JERRY_BUILTIN_REALMS) +ECMA_ERROR_DEF (ECMA_ERR_REALM_IS_NOT_AVAILABLE, "Realm is not available") +#endif /* !(JERRY_BUILTIN_REALMS) */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_BIGINT_ZERO_DIVISION, "BigInt division by zero") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_AN_ARRAYBUFFER, "Expected an ArrayBuffer") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CHARACTER_CLASS, "Invalid character class") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ESCAPE_SEQUENCE, "Invalid escape sequence") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_INVALID_SNAPSHOT_FORMAT, "Invalid snapshot format") +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_LONE_QUANTIFIER_BRACKET, "Lone quantifier bracket") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_OBJECT_CANNOT_BE_FROZEN, "Object cannot be frozen") +ECMA_ERROR_DEF (ECMA_ERR_OBJECT_CANNOT_BE_SEALED, "Object cannot be sealed") +#endif /* JERRY_BUILTIN_PROXY */ +#if !(JERRY_BUILTIN_REGEXP) +ECMA_ERROR_DEF (ECMA_ERR_REGEXP_IS_NOT_SUPPORTED, "RegExp is not supported") +#endif /* !(JERRY_BUILTIN_REGEXP) */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_UNMATCHED_CLOSE_BRACKET, "Unmatched close bracket") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_NOT_MODULE, "Argument is not a module") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_SET_PROTOTYPE, "Cannot set [[Prototype]]") +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_NEW_ARRAY_LENGTH, "Invalid new Array length") +#endif /* JERRY_BUILTIN_ARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_IS_NOT_CALLABLE, "Iterator is not callable") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_IS_IN_ERROR_STATE, "Module is in error state") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_REJECT_MUST_BE_UNDEFINED, "Reject must be undefined") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_REQUEST_IS_NOT_AVAILABLE, "Request is not available") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT, "Argument is not an object") +#if JERRY_BUILTIN_ATOMICS +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_NOT_SUPPORTED, "Argument is not supported") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CODE_POINT_ERROR, "Error: Invalid code point") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_TYPEDARRAY_LENGTH, "Invalid TypedArray length") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_HEXADECIMAL_VALUE, "Invalid hexadecimal value") +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_IS_NOT_AN_OBJECT, "Iterator is not an object") +ECMA_ERROR_DEF (ECMA_ERR_RESOLVE_MUST_BE_UNDEFINED, "Resolve must be undefined") +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_SNAPSHOT_BUFFER_SMALL, "Snapshot buffer too small") +#endif /* JERRY_SNAPSHOT_SAVE */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_UNEXPECTED_END_OF_PATTERN, "Unexpected end of pattern") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_SNAPSHOT_UNSUPPORTED_COMPILED_CODE, "Unsupported compiled code") +#endif /* JERRY_SNAPSHOT_SAVE */ +#if !(JERRY_BUILTIN_BIGINT) +ECMA_ERROR_DEF (ECMA_ERR_BIGINT_NOT_SUPPORTED, "BigInt support is disabled") +#endif /* !(JERRY_BUILTIN_BIGINT) */ +#if JERRY_BUILTIN_DATAVIEW +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_A_DATAVIEW_OBJECT, "Expected a DataView object") +#endif /* JERRY_BUILTIN_DATAVIEW */ +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_A_FUNCTION_OBJECT, "Expected a function object") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ARRAYBUFFER_LENGTH, "Invalid ArrayBuffer length") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if !(JERRY_MODULE_SYSTEM) +ECMA_ERROR_DEF (ECMA_ERR_MODULE_NOT_SUPPORTED, "Module support is disabled") +#endif /* !(JERRY_MODULE_SYSTEM) */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_OBJECT_IS_NOT_A_TYPEDARRAY, "Object is not a TypedArray") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT, "Receiver must be an object") +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_BIGINT_SERIALIZED, "BigInt cannot be serialized") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_CONTAINER_IS_NOT_AN_OBJECT, "Container is not an object.") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_HEX_ESCAPE_SEQUENCE, "Invalid hex escape sequence") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_SPECIES_CONSTRUCTOR, "Invalid species constructor") +ECMA_ERROR_DEF (ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH, "Proxy trap returned falsish") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_MIN_GREATER_THAN_MAX, "Quantifier error: min > max") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_SYMBOL_IS_NOT_A_CONSTRUCTOR, "Symbol is not a constructor") +#if JERRY_BUILTIN_REFLECT +ECMA_ERROR_DEF (ECMA_ERR_TARGET_IS_NOT_A_CONSTRUCTOR, "Target is not a constructor") +#endif /* JERRY_BUILTIN_REFLECT */ +ECMA_ERROR_DEF (ECMA_ERR_ACCESSOR_WRITABLE, "Accessors cannot be writable") +#if !(JERRY_BUILTIN_DATAVIEW) +ECMA_ERROR_DEF (ECMA_ERR_DATA_VIEW_NOT_SUPPORTED, "DataView support is disabled") +#endif /* !(JERRY_BUILTIN_DATAVIEW) */ +#if JERRY_BUILTIN_DATE +ECMA_ERROR_DEF (ECMA_ERR_DATE_MUST_BE_A_FINITE_NUMBER, "Date must be a finite number") +#endif /* JERRY_BUILTIN_DATE */ +ECMA_ERROR_DEF (ECMA_ERR_LOCAL_VARIABLE_IS_REDECLARED, "Local variable is redeclared") +ECMA_ERROR_DEF (ECMA_ERR_UNSUPPORTED_BINARY_OPERATION, "Unsupported binary operation") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_UNTERMINATED_CHARACTER_CLASS, "Unterminated character class") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_ARRAYBUFFER_IS_DETACHED, "ArrayBuffer has been detached") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_NOT_AN_OBJECT, "Constructor must be an object") +#if !(JERRY_BUILTIN_CONTAINER) +ECMA_ERROR_DEF (ECMA_ERR_CONTAINER_NOT_SUPPORTED, "Container support is disabled") +#endif /* !(JERRY_BUILTIN_CONTAINER) */ +#if JERRY_BUILTIN_REALMS +ECMA_ERROR_DEF (ECMA_ERR_FIRST_ARGUMENT_IS_NOT_A_REALM, "First argument is not a realm") +#endif /* JERRY_BUILTIN_REALMS */ +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INCOMPATIBLE_TYPEDARRAY_TYPES, "Incompatible TypedArray types") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INCORRECT_TYPE_FOR_TYPEDARRAY, "Incorrect type for TypedArray") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_OR_OUT_OF_RANGE_INDEX, "Invalid or out-of-range index") +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_MAXIMUM_SNAPSHOT_SIZE, "Maximum snapshot size reached") +#endif /* JERRY_SNAPSHOT_SAVE */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_CANNOT_BE_INSTANTIATED, "Module cannot be instantiated") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_SPECIES_MUST_BE_A_CONSTRUCTOR, "Species must be a constructor") +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_IS_NOT_A_PROXY, "Argument is not a Proxy object") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_NOT_ARRAY_BUFFER, "Argument is not an ArrayBuffer") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_MAP_REQUIRES_NEW, "Constructor Map requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_SET_REQUIRES_NEW, "Constructor Set requires 'new'") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_MUST_BE_IN_LINKED_STATE, "Module must be in linked state") +ECMA_ERROR_DEF (ECMA_ERR_UNKNOWN_EXPORT, "Native module export not found") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_PASSED_ARGUMENT_IS_NOT_A_REALM, "Passed argument is not a realm") +ECMA_ERROR_DEF (ECMA_ERR_PRIVATE_METHOD_IS_NOT_WRITABLE, "Private method is not writable") +#if JERRY_BUILTIN_BIGINT || JERRY_BUILTIN_NUMBER +ECMA_ERROR_DEF (ECMA_ERR_RADIX_IS_OUT_OF_RANGE, "Radix must be between 2 and 36") +#endif /* JERRY_BUILTIN_BIGINT \ +|| JERRY_BUILTIN_NUMBER */ +#if !(JERRY_SNAPSHOT_EXEC) +ECMA_ERROR_DEF (ECMA_ERR_SNAPSHOT_EXEC_DISABLED, "Snapshot execution is disabled") +#endif /* !(JERRY_SNAPSHOT_EXEC) */ +#if !(JERRY_BUILTIN_TYPEDARRAY) +ECMA_ERROR_DEF (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED, "TypedArray support is disabled") +#endif /* !(JERRY_BUILTIN_TYPEDARRAY) */ +ECMA_ERROR_DEF (ECMA_ERR_UNICODE_SURROGATE_PAIR_MISSING, "Unicode surrogate pair missing") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CONTROL_ESCAPE_SEQUENCE, "Invalid control escape sequence") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE, "Invalid unicode escape sequence") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_NEXT_IS_NOT_CALLABLE, "Iterator 'next' is not callable") +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_VALUE_IS_NOT_AN_OBJECT, "Iterator value is not an object") +ECMA_ERROR_DEF (ECMA_ERR_RESOLVE_METHOD_MUST_BE_CALLABLE, "Resolve method must be callable") +#if !(JERRY_SNAPSHOT_SAVE) +ECMA_ERROR_DEF (ECMA_ERR_SNAPSHOT_SAVE_DISABLED, "Snapshot generation is disabled") +#endif /* !(JERRY_SNAPSHOT_SAVE) */ +#if !(JERRY_PARSER) +ECMA_ERROR_DEF (ECMA_ERR_PARSER_NOT_SUPPORTED, "Source code parsing is disabled") +#endif /* !(JERRY_PARSER) */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_MUST_RETURN_WITH_AN_OBJECT, "Trap must return with an object") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_UNSUPPORTED_CONTAINER_OPERATION, "Unsupported container operation") +#endif /* JERRY_BUILTIN_CONTAINER */ +ECMA_ERROR_DEF (ECMA_ERR_METHOD_RETURN_IS_NOT_CALLABLE, "method 'return' is not callable") +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_PROMISE, "Argument 'this' is not a Promise") +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT, "Argument 'this' is not an object") +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_SYMBOL, "Argument 'this' must be a Symbol") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_CALLBACK_RESULT_NOT_MODULE, "Callback result must be a module") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_CLASS_CONSTRUCTOR_REQUIRES_NEW, "Class constructor requires 'new'") +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_COMPARE_FUNC_NOT_CALLABLE, "Compare function is not callable") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_PROXY_REQUIRES_NEW, "Constructor Proxy requires 'new'") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_A_CONFIGURABLE_PROPERTY, "Expected a configurable property") +ECMA_ERROR_DEF (ECMA_ERR_FIRST_PARAMETER_MUST_BE_CALLABLE, "First parameter must be callable") +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_FUNCTION_ADD_ORSET_IS_NOT_CALLABLE, "Function add/set is not callable") +#endif /* JERRY_BUILTIN_CONTAINER */ +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_RESULT_IS_NOT_AN_OBJECT, "Iterator result is not an object") +#if (JERRY_STACK_LIMIT != 0) +ECMA_ERROR_DEF (ECMA_ERR_MAXIMUM_CALL_STACK_SIZE_EXCEEDED, "Maximum call stack size exceeded") +#endif /* (JERRY_STACK_LIMIT != 0) */ +ECMA_ERROR_DEF (ECMA_ERR_MAXIMUM_STRING_LENGTH_IS_REACHED, "Maximum string length is reached") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_MUST_BE_IN_UNLINKED_STATE, "Module must be in unlinked state") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_STATIC_SNAPSHOTS_ARE_NOT_ENABLED, "Static snapshots are not enabled") +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_BUILTIN_WEAKREF +ECMA_ERROR_DEF (ECMA_ERR_WEAKREF_TARGET_MUST_BE_AN_OBJECT, "WeakRef target must be an object") +#endif /* JERRY_BUILTIN_WEAKREF */ +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_FUNCTION, "Argument 'this' is not a function") +#if JERRY_BUILTIN_ATOMICS +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_NOT_SHARED_ARRAY_BUFFER, "Argument is not SharedArrayBuffer") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_CONTAINER || JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE, "Callback function is not callable") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_CONTAINER \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INITIAL_VALUE_CANNOT_BE_UNDEFINED, "Initial value cannot be undefined") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +ECMA_ERROR_DEF (ECMA_ERR_INVALID_SHARED_ARRAYBUFFER_LENGTH, "Invalid Shared ArrayBuffer length") +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_TYPE_FOR_CONSTRUCTOR_CALL, "Invalid type for constructor call") +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE, "Iterator 'throw' is not available") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_NAMESPACE_OBJECT_IS_NOT_AVAILABLE, "Namespace object is not available") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_PROXY_TARGET_IS_NOT_A_CONSTRUCTOR, "Proxy target is not a constructor") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_REALMS +ECMA_ERROR_DEF (ECMA_ERR_SECOND_ARGUMENT_MUST_BE_AN_OBJECT, "Second argument must be an object") +#endif /* JERRY_BUILTIN_REALMS */ +#if JERRY_BUILTIN_DATAVIEW +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_BUFFER_NOT_OBJECT, "Argument 'buffer' is not an object") +#endif /* JERRY_BUILTIN_DATAVIEW */ +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR, "Argument 'this' is not an iterator") +ECMA_ERROR_DEF (ECMA_ERR_VALUE_MSG, "Argument cannot be marked as error") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_PROMISE_REQUIRES_NEW, "Constructor Promise requires 'new'") +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_WEAKMAP_REQUIRES_NEW, "Constructor WeakMap requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_WEAKSET_REQUIRES_NEW, "Constructor WeakSet requires 'new'") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_MAXIMUM_TYPEDARRAY_SIZE_IS_REACHED, "Maximum TypedArray size is reached") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_THE_GIVEN_ARGUMENT_IS_NOT_A_SYMBOL, "The given argument is not a Symbol") +ECMA_ERROR_DEF (ECMA_ERR_PARAMETER_REJECT_MUST_BE_CALLABLE, "'reject' parameter must be callable") +#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY, "Argument 'this' is not a TypedArray") +#endif /* JERRY_BUILTIN_ATOMICS \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_ALLOCATE_MEMORY_LITERALS, "Cannot allocate memory for literals") +#endif /* JERRY_SNAPSHOT_SAVE */ +ECMA_ERROR_DEF (ECMA_ERR_INVOKE_NULLABLE_SUPER_METHOD, "Cannot invoke nullable super method") +#if JERRY_BUILTIN_DATAVIEW +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_DATAVIEW_REQUIRES_NEW, "Constructor DataView requires 'new'") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_WEAKREF +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_WEAKREF_REQUIRES_NEW, "Constructor WeakRef requires 'new'.") +#endif /* JERRY_BUILTIN_WEAKREF */ +ECMA_ERROR_DEF (ECMA_ERR_SUPER_BINDING_MUST_BE_A_CONSTRUCTOR, "Super binding must be a constructor") +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_VALUE_CANNOT_BE_CONVERTED_TO_BIGINT, "Value cannot be converted to BigInt") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_PARAMETER_RESOLVE_MUST_BE_CALLABLE, "'resolve' parameter must be callable") +#if JERRY_BUILTIN_DATE +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_DATE_OBJECT, "Argument 'this' is not a Date object") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_CONSTRUCTOR, "Argument 'this' is not a constructor") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_BIGINT_FUNCTION_NOT_CONSTRUCTOR, "BigInt function is not a constructor") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTED_OBJECT_IS_NOT_TYPEDARRAY, "Constructed object is not TypedArray") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_INT8_ARRAY_REQUIRES_NEW, "Constructor Int8Array requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_CONTAINER_IS_NOT_A_CONTAINER_OBJECT, "Container is not a container object.") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_DATE +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ARGUMENT_TYPE_IN_TOPRIMITIVE, "Invalid argument type in toPrimitive") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_METHODS_INVOKE_WITH_NEW, "Methods cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_EXPORTS_MUST_BE_STRING_VALUES, "Module exports must be string values") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_PROTOTYPE_IS_NEITHER_OBJECT_NOR_NULL, "Prototype is neither object nor null") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_THE_MAPFN_ARGUMENT_IS_NOT_CALLABLE, "The 'mapfn' argument is not callable") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE, "The two descriptors are incompatible") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_WRONG_ARGS_MSG, "This type of argument is not allowed") +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_CONTAINER_NEEDED, "Value is not a Container or Iterator") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP, "Argument 'this' is not a valid RegExp") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARRAY_BUFFER_DETACHED, "ArrayBuffer has already been detached") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_BULTIN_ROUTINES_HAVE_NO_CONSTRUCTOR, "Built-in routines have no constructor") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_INT16_ARRAY_REQUIRES_NEW, "Constructor Int16Array requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_INT32_ARRAY_REQUIRES_NEW, "Constructor Int32Array requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_UINT8_ARRAY_REQUIRES_NEW, "Constructor Uint8Array requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_FUNCTION_INDEX_IS_HIGHER_THAN_MAXIMUM, "Function index is higher than maximum") +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_RANGE_OUT_OF_ORDER_IN_CHARACTER_CLASS, "Range out of order in character class") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_RESULT_OF_DEFAULTVALUE_IS_INVALID, "Result of [[DefaultValue]] is invalid") +ECMA_ERROR_DEF (ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT, "Right value of 'in' must be an object") +#if !(JERRY_BUILTIN_SHAREDARRAYBUFFER) +ECMA_ERROR_DEF (ECMA_ERR_SHARED_ARRAYBUFFER_NOT_SUPPORTED, "SharedArrayBuffer support is disabled") +#endif /* !(JERRY_BUILTIN_SHAREDARRAYBUFFER) */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_RETURNED_NEITHER_OBJECT_NOR_NULL, "Trap returned neither object nor null") +ECMA_ERROR_DEF (ECMA_ERR_TRAP_WITH_DUPLICATED_ENTRIES, "Trap returned with duplicated entries") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_UNARY_PLUS_IS_NOT_ALLOWED_FOR_BIGINTS, "Unary plus is not allowed for BigInts") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_IS_NOT_AN_REGEXP, "Argument 'this' is not a RegExp object") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ALLOCATE_ARRAY_BUFFER, "Cannot allocate memory for ArrayBuffer") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_CONSTANT_BINDINGS_CANNOT_BE_REASSIGNED, "Constant bindings cannot be reassigned") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_ARRAYBUFFER_REQUIRES_NEW, "Constructor ArrayBuffer requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_UINT16_ARRAY_REQUIRES_NEW, "Constructor Uint16Array requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_UINT32_ARRAY_REQUIRES_NEW, "Constructor Uint32Array requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_GENERATOR_IS_CURRENTLY_UNDER_EXECUTION, "Generator is currently under execution") +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_RETURN_RESULT_IS_NOT_OBJECT, "Iterator 'return' result is not object") +ECMA_ERROR_DEF (ECMA_ERR_SEARCH_STRING_CANNOT_BE_OF_TYPE_REGEXP, "Search string can't be of type: RegExp") +ECMA_ERROR_DEF (ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT, "Value received by yield* is not object") +#if JERRY_BUILTIN_BOOLEAN +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_BOOLEAN_OBJECT, "Argument 'this' is not a Boolean object") +#endif /* JERRY_BUILTIN_BOOLEAN */ +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE, "Cannot declare same private field twice") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_FLOAT32_ARRAY_REQUIRES_NEW, "Constructor Float32Array requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY && JERRY_NUMBER_TYPE_FLOAT64 +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_FLOAT64_ARRAY_REQUIRES_NEW, "Constructor Float64Array requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY && JERRY_NUMBER_TYPE_FLOAT64 */ +ECMA_ERROR_DEF (ECMA_ERR_FUNCTION_PROTOTYPE_NOT_A_CONSTRUCTOR, "Function.prototype is not a constructor") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_IMPORTED_BINDING_SHADOWS_LOCAL_VARIABLE, "Imported binding shadows local variable") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_PROTOTYPE_FROM_REVOKED_PROXY_IS_INVALID, "Prototype from revoked Proxy is invalid") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_REGEXP && JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_REGEXP_ARGUMENT_SHOULD_HAVE_GLOBAL_FLAG, "RegExp argument should have global flag") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_IS_NEITHER_AN_OBJECT_NOR_UNDEFINED, "Trap is neither an object nor undefined") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_PROMISE_RESOLVE_ITSELF, "A promise cannot be resolved with itself") +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_BIGINT64_ARRAY_REQUIRES_NEW, "Constructor BigInt64Array requires 'new'") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_EXPORTS_MUST_BE_VALID_IDENTIFIERS, "Module exports must be valid identifiers") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_GENERATOR_OBJECT, "Argument 'this' is not a generator object") +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_CANNOT_CONVERT_TO_OBJECT, "Argument cannot be converted to an object") +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_ALLOCATE_BIGINT_VALUE, "Cannot allocate memory for a BigInt value") +ECMA_ERROR_DEF (ECMA_ERR_CONVERT_BIGINT_TO_NUMBER, "Cannot convert a BigInt value to a number") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_CONVERT_SYMBOL_TO_NUMBER, "Cannot convert a Symbol value to a number") +ECMA_ERROR_DEF (ECMA_ERR_CONVERT_SYMBOL_TO_STRING, "Cannot convert a Symbol value to a string") +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_BIG_UINT64_ARRAY_REQUIRES_NEW, "Constructor BigUInt64Array requires 'new'") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_NUMBER +ECMA_ERROR_DEF (ECMA_ERR_FRACTION_DIGITS_OUT_OF_RANGE, "Fraction digits must be between 0 and 100") +#endif /* JERRY_BUILTIN_NUMBER */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_RETURN_VALUE_IS_NOT_AN_ARRAYBUFFER_OBJECT, "Return value is not an ArrayBuffer object") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_SUPER_CONSTRUCTOR_MAY_ONLY_BE_CALLED_ONCE, "Super constructor may only be called once") +ECMA_ERROR_DEF (ECMA_ERR_BINDING_NOT_EXIST_OR_UNINITIALIZED, "Binding does not exist or is uninitialised") +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_CONVERT_TO_OBJECT, "Cannot convert undefined or null to object") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_NUMBER +ECMA_ERROR_DEF (ECMA_ERR_PRECISION_DIGITS_MUST_BE_BETWEEN_IN_RANGE, "Precision digits must be between 1 and 100") +#endif /* JERRY_BUILTIN_NUMBER */ +ECMA_ERROR_DEF (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_GETTER, "Private field was defined without a getter") +ECMA_ERROR_DEF (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_SETTER, "Private field was defined without a setter") +ECMA_ERROR_DEF (ECMA_ERR_PROPERTY_NAME_IS_NEITHER_SYMBOL_NOR_STRING, "Property name is neither Symbol nor string") +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_STRING_CANNOT_BE_CONVERTED_TO_BIGINT_VALUE, "String cannot be converted to BigInt value") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_INCORRECT_TYPE_CALL, "Operator called on incorrect container type") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE, "Reduce of empty Array with no initial value") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP_OBJECT, "Argument 'this' is not a valid RegExp object") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_ARRAY_BUFFER_OBJECT, "Argument 'this' is not an ArrayBuffer object") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_ARROW_FUNCTIONS_INVOKE_WITH_NEW, "Arrow functions cannot be invoked with 'new'") +ECMA_ERROR_DEF (ECMA_ERR_ASYNC_FUNCTIONS_INVOKE_WITH_NEW, "Async functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_SET_EXTENSIBLE_PROPERTY, "Cannot set [[Extensible]] property of object") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_SHAREDARRAYBUFFER_REQUIRES_NEW, "Constructor SharedArrayBuffer requires 'new'") +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_UINT8_CLAMPED_ARRAY_REQUIRES_NEW, "Constructor Uint8ClampedArray requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_NEGATIVE_EXPONENT_IS_NOT_ALLOWED_FOR_BIGINTS, "Negative exponent is not allowed for BigInts") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_PROMISE_ALL_REMAINING_ELEMENTS_LIMIT_REACHED, "Promise.all remaining elements limit reached") +ECMA_ERROR_DEF (ECMA_ERR_VALUE_RECEIVED_BY_FOR_ASYNC_OF_IS_NOT_OBJECT, "Value received by for-async-of is not object") +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_INFINITY_OR_NAN_CANNOT_BE_CONVERTED_TO_BIGINT, "Infinity or NaN cannot be converted to BigInt") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_OPERATOR_DELETE_RETURNED_FALSE_IN_STRICT_MODE, "Operator delete returned false in strict mode") +ECMA_ERROR_DEF (ECMA_ERR_PROPERTY_PROTOTYPE_IS_NOT_AN_OBJECT, "Property 'prototype' is not an object or null") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_PROXY_HANDLER_IS_NULL_FOR_ISARRAY_OPERATION, "Proxy handler is null for 'isArray' operation") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_REGULAR_EXPRESSION_NOT_SUPPORTED, "Regular expression literals are not supported") +#endif /* JERRY_SNAPSHOT_SAVE */ +ECMA_ERROR_DEF (ECMA_ERR_RIGHT_VALUE_OF_INSTANCEOF_MUST_BE_AN_OBJECT, "Right value of 'instanceof' must be an object") +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_STATIC_SNAPSHOTS_CANNOT_BE_COPIED_INTO_MEMORY, "Static snapshots cannot be copied into memory") +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_TAGGED_TEMPLATE_LITERALS, "Unsupported feature: tagged template literals") +ECMA_ERROR_DEF (ECMA_ERR_SNAPSHOT_FLAG_NOT_SUPPORTED, "Unsupported generate snapshot flags specified") +#endif /* JERRY_SNAPSHOT_SAVE */ +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_UNSUPPORTED_SNAPSHOT_EXEC_FLAGS_ARE_SPECIFIED, "Unsupported snapshot exec flags are specified") +#endif /* JERRY_SNAPSHOT_EXEC */ +ECMA_ERROR_DEF (ECMA_ERR_VALUE_FOR_CLASS_HERITAGE_IS_NOT_A_CONSTRUCTOR, "Value for class heritage is not a constructor") +ECMA_ERROR_DEF (ECMA_ERR_TOO_MANY_ARGUMENTS_DECLARED_FOR_FUNCTION_APPLY, + "Too many arguments declared for Function.apply") +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_ACCESSOR_FUNCTIONS_INVOKE_WITH_NEW, "Accessor functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_LINK_TO_MODULE_IN_ERROR_STATE, "Cannot link to a module which is in error state") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_ONLY_INTEGER_NUMBERS_CAN_BE_CONVERTED_TO_BIGINT, + "Only integer numbers can be converted to BigInt") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_TYPEDARRAY_INTRINSTIC_DIRECTLY_CALLED, "TypedArray intrinstic cannot be directly called") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_UNSIGNED_RIGHT_SHIFT_IS_NOT_ALLOWED_FOR_BIGINTS, + "Unsigned right shift is not allowed for BigInts") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_ASYNC_GENERATOR, "Argument 'this' is not an async generator object") +ECMA_ERROR_DEF (ECMA_ERR_CLASS_EXTENDS_NOT_CONSTRUCTOR, "Class extends value is not a constructor or null") +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW, "Generator functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_RETURN_VALUE_OF_EXEC_MUST_BE_AN_OBJECT_OR_NULL, + "Return value of 'exec' must be an object or null") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_DATAVIEW +ECMA_ERROR_DEF (ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER, + "Start offset is outside the bounds of the buffer") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER, "Argument 'this' is not a SharedArrayBuffer object") +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +ECMA_ERROR_DEF (ECMA_ERR_CLASS_CONSTRUCTOR_NEW, "Class constructor cannot be invoked without 'new'") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_INCORRECT_RETURN_PROXY_GET_TRAP, "Incorrect value is returned by a Proxy 'get' trap") +ECMA_ERROR_DEF (ECMA_ERR_INCORRECT_RETURN_PROXY_SET_TRAP, "Incorrect value is returned by a Proxy 'set' trap") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE, "Prototype property of a class is non-configurable") +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_PUSHING_TOO_HIGH_ELEMENT, "Pushing element over 2**53-1 length is disallowed") +#endif /* JERRY_BUILTIN_ARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_THE_REQUESTED_PROPERTY_UPDATE_CANNOT_BE_PERFORMED, + "The requested property update cannot be performed") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_CONFIGURABLE_KEYS, + "Trap result did not include all configurable keys") +ECMA_ERROR_DEF (ECMA_ERR_TRAP_TRUISH_TARGET_NOT_EXTENSIBLE, "Trap returned truish for target is not extensible") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_NUMBER +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_NUMBER, "Argument 'this' is not a number or a Number object") +#endif /* JERRY_BUILTIN_NUMBER */ +#if JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_STRING_OBJECT, "Argument 'this' is not a string or a String object") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER_OBJECT, + "Argument 'this' is not an SharedArrayBuffer object") +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_ASYNC_ARROW_FUNCTIONS_INVOKE_WITH_NEW, "Async arrow functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_UNSHIFT_TOO_HIGH, "Unshift elements over 2**53-1 length is disallowed") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_NON_CONFIGURABLE_KEYS, + "Trap result did not include all non-configurable keys") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_ASYNC_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW, + "Async generator functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_BUILTIN_REFLECT +ECMA_ERROR_DEF (ECMA_ERR_REFLECT_EXPECTS_AN_OBJECT_AS_SECOND_ARGUMENT, + "Reflect.construct expects an object as second argument") +#endif /* JERRY_BUILTIN_REFLECT */ +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_SCRIPT_GLOBAL_FUNCTIONS_INVOKE_WITH_NEW, + "Script (global) functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_CREATE_PROXY, "Cannot create Proxy with a non-object target or handler") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_DERIVED_CTOR_RETURN_NOR_OBJECT_OR_UNDEFINED, + "Derived constructors may only return object or undefined") +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_INVALID_SNAPSHOT_VERSION_OR_FEATURES, + "Invalid snapshot version or unsupported features present") +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_TYPEDARRAY_SMALLER_THAN_FILTER_CALL_RESULT, + "Constructed TypedArray is smaller than filter call result") +ECMA_ERROR_DEF (ECMA_ERR_DERIVED_ARRAY_BUFFER_CTOR_BUFFER_TOO_SMALL, + "Derived ArrayBuffer constructor created a too small buffer") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_EXTENSIBILITY, + "Trap result does not reflect extensibility of Proxy target") +ECMA_ERROR_DEF (ECMA_ERR_TRAP_EXTRA_KEYS_FOR_A_NON_EXTENSIBLE_TARGET, + "Trap returned extra keys for a non-extensible Proxy target") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARRAY_BUFFER_RETURNED_THIS_FROM_CONSTRUCTOR, + "ArrayBuffer subclass returned this from species constructor") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATAVIEW +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_BUFFER_NOT_ARRAY_OR_SHARED_BUFFER, + "Argument 'buffer' is not an ArrayBuffer or SharedArrayBuffer") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_INEXTENSIBILITY, + "Trap result does not reflect inextensibility of Proxy target") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_TYPEDARRAY_INTRINSTIC_CALLED_BY_NEW_EXPRESSION, + "TypedArray intrinstic cannot be called by a 'new' expression") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONTENTTYPE_RETURNED_TYPEDARRAY_NOT_MATCH_SOURCE, + "TypedArray returned by [[ContentType]] does not match source") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_ALLOCATE_BIGINT_STRING, "Cannot allocate memory for a string representation of a BigInt value") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TARGET_NOT_EXTENSIBLE_DIFFERENT_PROTOTYPE_RETURNED, + "Target object is non-extensible and trap returned different prototype") +ECMA_ERROR_DEF (ECMA_ERR_TRAP_TRUISH_ADDING_PROPERTY_NON_EXTENSIBLE_TARGET, + "Trap returned truish for adding property to the non-extensible target") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_READ_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT, + "Cannot read private member to an object whose class did not declare it") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_GIVEN_PROPERTY_IS_A_NON_CONFIGURABLE, + "Given property is a non-configurable data property on the proxy target") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_WRITE_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT, + "Cannot write private member to an object whose class did not declare it") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_FALSISH_PROPERTY_TARGET_NOT_EXTENSIBLE, + "Trap returned falsish for property but the proxy target is not extensible") +ECMA_ERROR_DEF (ECMA_ERR_PROXY_PROPERTY_NOT_CONFIGURABLE_NOT_HAVE_GETTER, + "Property of a Proxy is non-configurable and does not have a getter function") +ECMA_ERROR_DEF (ECMA_ERR_TARGET_PROPERTY_CONFIGURE_ACCESSOR_WITHOUT_SETTER, + "The property of a Proxy target is a non configurable accessor without a setter") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_LET_CONST_NOT_INITIALIZED, + "Variables declared by let/const must be initialized before reading their value") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_TRUISH_PROPERTY_NON_CONFIGURABLE, + "Trap returned truish for property which is non-configurable in the proxy target") +ECMA_ERROR_DEF (ECMA_ERR_TARGET_NOT_EXTENSIBLE_NOT_RETURNED_ITS_PROTOTYPE, + "Proxy target is non-extensible, but the trap did not return its actual prototype") +ECMA_ERROR_DEF (ECMA_ERR_TRAP_FALSISH_PROPERTY_NON_CONFIGURABLE, + "Trap returned falsish for property which exists in the proxy target as non-configurable") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_CALL_SUPER_CONSTRUCTOR_DERIVED_CLASS_BEFORE_THIS, + "Must call super constructor in derived class before accessing 'this' or returning from it") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY, + "Trap returned truish for defining non-configurable property which is non-existent in the target") +ECMA_ERROR_DEF ( + ECMA_ERR_TRAP_TRUISH_ADD_PROPERTY_INCOMPATIBLE_OTHER_PROP, + "Trap returned truish for adding property that is incompatible with the existing property in the target") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_ACCESS_CALLER_CALLE_ARGUMENTS, + "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the " + "arguments objects for calls to them") diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.ini b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.ini new file mode 100644 index 00000000..c2d7031a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.ini @@ -0,0 +1,331 @@ +# Copyright JS Foundation and other contributors, http://js.foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[ECMA_ERROR_MESSAGES] + +ECMA_ERR_CANNOT_ACCESS_CALLER_CALLE_ARGUMENTS = "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them" +ECMA_ERR_PARAMETER_REJECT_MUST_BE_CALLABLE = "'reject' parameter must be callable" +ECMA_ERR_PARAMETER_RESOLVE_MUST_BE_CALLABLE = "'resolve' parameter must be callable" +ECMA_ERR_PROMISE_RESOLVE_ITSELF = "A promise cannot be resolved with itself" +ECMA_ERR_ACCESSOR_WRITABLE = "Accessors cannot be writable" +ECMA_ERR_ARGUMENT_BUFFER_NOT_ARRAY_OR_SHARED_BUFFER = "Argument 'buffer' is not an ArrayBuffer or SharedArrayBuffer" +ECMA_ERR_ARGUMENT_BUFFER_NOT_OBJECT = "Argument 'buffer' is not an object" +ECMA_ERR_ARGUMENT_THIS_NOT_ARRAY_BUFFER_OBJECT = "Argument 'this' is not an ArrayBuffer object" +ECMA_ERR_ARGUMENT_THIS_NOT_BOOLEAN_OBJECT = "Argument 'this' is not a Boolean object" +ECMA_ERR_ARGUMENT_THIS_NOT_DATE_OBJECT = "Argument 'this' is not a Date object" +ECMA_ERR_ARGUMENT_THIS_NOT_PROMISE = "Argument 'this' is not a Promise" +ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER = "Argument 'this' is not a SharedArrayBuffer object" +ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY = "Argument 'this' is not a TypedArray" +ECMA_ERR_ARGUMENT_THIS_NOT_CONSTRUCTOR = "Argument 'this' is not a constructor" +ECMA_ERR_ARGUMENT_THIS_NOT_FUNCTION = "Argument 'this' is not a function" +ECMA_ERR_ARGUMENT_THIS_NOT_GENERATOR_OBJECT = "Argument 'this' is not a generator object" +ECMA_ERR_ARGUMENT_THIS_NOT_NUMBER = "Argument 'this' is not a number or a Number object" +ECMA_ERR_ARGUMENT_THIS_NOT_STRING_OBJECT = "Argument 'this' is not a string or a String object" +ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP = "Argument 'this' is not a valid RegExp" +ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP_OBJECT = "Argument 'this' is not a valid RegExp object" +ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER_OBJECT = "Argument 'this' is not an SharedArrayBuffer object" +ECMA_ERR_ARGUMENT_THIS_NOT_ASYNC_GENERATOR = "Argument 'this' is not an async generator object" +ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR = "Argument 'this' is not an iterator" +ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT = "Argument 'this' is not an object" +ECMA_ERR_ARGUMENT_THIS_NOT_SYMBOL = "Argument 'this' must be a Symbol" +ECMA_ERR_ARGUMENT_CANNOT_CONVERT_TO_OBJECT = "Argument cannot be converted to an object" +ECMA_ERR_ARGUMENT_NOT_SHARED_ARRAY_BUFFER = "Argument is not SharedArrayBuffer" +ECMA_ERR_ARGUMENT_NOT_ARRAY_BUFFER = "Argument is not an ArrayBuffer" +ECMA_ERR_ARGUMENT_NOT_SUPPORTED = "Argument is not supported" +ECMA_ERR_ARRAY_BUFFER_DETACHED = "ArrayBuffer has already been detached" +ECMA_ERR_ARRAY_BUFFER_RETURNED_THIS_FROM_CONSTRUCTOR = "ArrayBuffer subclass returned this from species constructor" +ECMA_ERR_BIGINT_SERIALIZED = "BigInt cannot be serialized" +ECMA_ERR_BIGINT_ZERO_DIVISION = "BigInt division by zero" +ECMA_ERR_BIGINT_FUNCTION_NOT_CONSTRUCTOR = "BigInt function is not a constructor" +ECMA_ERR_BIGINT_VALUE_EXCPECTED = "BigInt value expected" +ECMA_ERR_BINDING_CANNOT_SET = "Binding cannot be set" +ECMA_ERR_BINDING_NOT_EXIST_OR_UNINITIALIZED = "Binding does not exist or is uninitialised" +ECMA_ERR_BULTIN_ROUTINES_HAVE_NO_CONSTRUCTOR = "Built-in routines have no constructor" +ECMA_ERR_CALLBACK_RESULT_NOT_MODULE = "Callback result must be a module" +ECMA_ERR_ALLOCATE_ARRAY_BUFFER = "Cannot allocate memory for ArrayBuffer" +ECMA_ERR_ALLOCATE_BIGINT_VALUE = "Cannot allocate memory for a BigInt value" +ECMA_ERR_ALLOCATE_BIGINT_STRING = "Cannot allocate memory for a string representation of a BigInt value" +ECMA_ERR_CONVERT_BIGINT_TO_NUMBER = "Cannot convert a BigInt value to a number" +ECMA_ERR_CONVERT_SYMBOL_TO_NUMBER = "Cannot convert a Symbol value to a number" +ECMA_ERR_CONVERT_SYMBOL_TO_STRING = "Cannot convert a Symbol value to a string" +ECMA_ERR_CANNOT_CREATE_PROXY = "Cannot create Proxy with a non-object target or handler" +ECMA_ERR_INVOKE_NULLABLE_SUPER_METHOD = "Cannot invoke nullable super method" +ECMA_ERR_LINK_TO_MODULE_IN_ERROR_STATE = "Cannot link to a module which is in error state" +ECMA_ERR_SET_EXTENSIBLE_PROPERTY = "Cannot set [[Extensible]] property of object" +ECMA_ERR_SET_PROTOTYPE = "Cannot set [[Prototype]]" +ECMA_ERR_CLASS_CONSTRUCTOR_REQUIRES_NEW = "Class constructor requires 'new'" +ECMA_ERR_CLASS_EXTENDS_NOT_CONSTRUCTOR = "Class extends value is not a constructor or null" +ECMA_ERR_COMPARE_FUNC_NOT_CALLABLE = "Compare function is not callable" +ECMA_ERR_CONSTANT_BINDINGS_CANNOT_BE_REASSIGNED = "Constant bindings cannot be reassigned" +ECMA_ERR_TYPEDARRAY_SMALLER_THAN_FILTER_CALL_RESULT = "Constructed TypedArray is smaller than filter call result" +ECMA_ERR_CONSTRUCTED_OBJECT_IS_NOT_TYPEDARRAY = "Constructed object is not TypedArray" +ECMA_ERR_CONSTRUCTOR_ARRAYBUFFER_REQUIRES_NEW = "Constructor ArrayBuffer requires 'new'" +ECMA_ERR_CONSTRUCTOR_BIGINT64_ARRAY_REQUIRES_NEW = "Constructor BigInt64Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_BIG_UINT64_ARRAY_REQUIRES_NEW = "Constructor BigUInt64Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_DATAVIEW_REQUIRES_NEW = "Constructor DataView requires 'new'" +ECMA_ERR_CONSTRUCTOR_FLOAT32_ARRAY_REQUIRES_NEW = "Constructor Float32Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_FLOAT64_ARRAY_REQUIRES_NEW = "Constructor Float64Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_INT16_ARRAY_REQUIRES_NEW = "Constructor Int16Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_INT32_ARRAY_REQUIRES_NEW = "Constructor Int32Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_INT8_ARRAY_REQUIRES_NEW = "Constructor Int8Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_MAP_REQUIRES_NEW = "Constructor Map requires 'new'" +ECMA_ERR_CONSTRUCTOR_PROMISE_REQUIRES_NEW = "Constructor Promise requires 'new'" +ECMA_ERR_CONSTRUCTOR_PROXY_REQUIRES_NEW = "Constructor Proxy requires 'new'" +ECMA_ERR_CONSTRUCTOR_SET_REQUIRES_NEW = "Constructor Set requires 'new'" +ECMA_ERR_CONSTRUCTOR_SHAREDARRAYBUFFER_REQUIRES_NEW = "Constructor SharedArrayBuffer requires 'new'" +ECMA_ERR_CONSTRUCTOR_UINT16_ARRAY_REQUIRES_NEW = "Constructor Uint16Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_UINT32_ARRAY_REQUIRES_NEW = "Constructor Uint32Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_UINT8_ARRAY_REQUIRES_NEW = "Constructor Uint8Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_UINT8_CLAMPED_ARRAY_REQUIRES_NEW = "Constructor Uint8ClampedArray requires 'new'" +ECMA_ERR_CONSTRUCTOR_WEAKMAP_REQUIRES_NEW = "Constructor WeakMap requires 'new'" +ECMA_ERR_CONSTRUCTOR_WEAKREF_REQUIRES_NEW = "Constructor WeakRef requires 'new'." +ECMA_ERR_CONSTRUCTOR_WEAKSET_REQUIRES_NEW = "Constructor WeakSet requires 'new'" +ECMA_ERR_CONSTRUCTOR_NOT_AN_OBJECT = "Constructor must be an object" +ECMA_ERR_CONTAINER_IS_NOT_A_CONTAINER_OBJECT = "Container is not a container object." +ECMA_ERR_CONTAINER_IS_NOT_AN_OBJECT = "Container is not an object." +ECMA_ERR_DATE_MUST_BE_A_FINITE_NUMBER = "Date must be a finite number" +ECMA_ERR_DERIVED_ARRAY_BUFFER_CTOR_BUFFER_TOO_SMALL = "Derived ArrayBuffer constructor created a too small buffer" +ECMA_ERR_DERIVED_CTOR_RETURN_NOR_OBJECT_OR_UNDEFINED = "Derived constructors may only return object or undefined" +ECMA_ERR_INVALID_CODE_POINT_ERROR = "Error: Invalid code point" +ECMA_ERR_EXPECTED_A_DATAVIEW_OBJECT = "Expected a DataView object" +ECMA_ERR_EXPECTED_A_CONFIGURABLE_PROPERTY = "Expected a configurable property" +ECMA_ERR_EXPECTED_A_FUNCTION_OBJECT = "Expected a function object" +ECMA_ERR_EXPECTED_AN_ARRAYBUFFER = "Expected an ArrayBuffer" +ECMA_ERR_EXPECTED_AN_OBJECT = "Expected an object" +ECMA_ERR_FIRST_ARGUMENT_IS_NOT_A_REALM = "First argument is not a realm" +ECMA_ERR_FIRST_PARAMETER_MUST_BE_CALLABLE = "First parameter must be callable" +ECMA_ERR_FRACTION_DIGITS_OUT_OF_RANGE = "Fraction digits must be between 0 and 100" +ECMA_ERR_FUNCTION_ADD_ORSET_IS_NOT_CALLABLE = "Function add/set is not callable" +ECMA_ERR_FUNCTION_INDEX_IS_HIGHER_THAN_MAXIMUM = "Function index is higher than maximum" +ECMA_ERR_FUNCTION_PROTOTYPE_NOT_A_CONSTRUCTOR = "Function.prototype is not a constructor" +ECMA_ERR_GENERATOR_IS_CURRENTLY_UNDER_EXECUTION = "Generator is currently under execution" +ECMA_ERR_GETTER_IS_NOT_CALLABLE = "Getter is not callable" +ECMA_ERR_GIVEN_PROPERTY_IS_A_NON_CONFIGURABLE = "Given property is a non-configurable data property on the proxy target" +ECMA_ERR_HANDLER_CANNOT_BE_NULL = "Handler cannot be null" +ECMA_ERR_IMPORTED_BINDING_SHADOWS_LOCAL_VARIABLE = "Imported binding shadows local variable" +ECMA_ERR_INCOMPATIBLE_TYPEDARRAY_TYPES = "Incompatible TypedArray types" +ECMA_ERR_INCORRECT_TYPE_FOR_TYPEDARRAY = "Incorrect type for TypedArray" +ECMA_ERR_INCORRECT_RETURN_PROXY_GET_TRAP = "Incorrect value is returned by a Proxy 'get' trap" +ECMA_ERR_INCORRECT_RETURN_PROXY_SET_TRAP = "Incorrect value is returned by a Proxy 'set' trap" +ECMA_ERR_INFINITY_OR_NAN_CANNOT_BE_CONVERTED_TO_BIGINT = "Infinity or NaN cannot be converted to BigInt" +ECMA_ERR_INITIAL_VALUE_CANNOT_BE_UNDEFINED = "Initial value cannot be undefined" +ECMA_ERR_INVALID_ARRAYBUFFER_LENGTH = "Invalid ArrayBuffer length" +ECMA_ERR_INVALID_JSON_FORMAT = "Invalid JSON format" +ECMA_ERR_INVALID_REGEXP_FLAGS = "Invalid RegExp flags" +ECMA_ERR_INVALID_SHARED_ARRAYBUFFER_LENGTH = "Invalid Shared ArrayBuffer length" +ECMA_ERR_INVALID_TYPEDARRAY_LENGTH = "Invalid TypedArray length" +ECMA_ERR_INVALID_UTF8_CHARACTER = "Invalid UTF8 character" +ECMA_ERR_INVALID_UTF8_CODEPOINT = "Invalid UTF8 codepoint" +ECMA_ERR_INVALID_UTF8_STRING = "Invalid UTF8 string" +ECMA_ERR_INVALID_ENCODING = "Invalid encoding" +ECMA_ERR_INVALID_ARGUMENT = "Invalid argument" +ECMA_ERR_INVALID_ARGUMENT_TYPE_IN_TOPRIMITIVE = "Invalid argument type in toPrimitive" +ECMA_ERR_INVALID_CAPABILITY = "Invalid capability" +ECMA_ERR_INVALID_CHARACTER_CLASS = "Invalid character class" +ECMA_ERR_INVALID_CODE_POINT = "Invalid code point" +ECMA_ERR_INVALID_CONTAINER_TYPE = "Invalid container type" +ECMA_ERR_INVALID_CONTROL_ESCAPE_SEQUENCE = "Invalid control escape sequence" +ECMA_ERR_INVALID_COUNT_VALUE = "Invalid count value" +ECMA_ERR_INVALID_ESCAPE = "Invalid escape" +ECMA_ERR_INVALID_ESCAPE_SEQUENCE = "Invalid escape sequence" +ECMA_ERR_INVALID_GROUP = "Invalid group" +ECMA_ERR_INVALID_HEX_ESCAPE_SEQUENCE = "Invalid hex escape sequence" +ECMA_ERR_INVALID_HEXADECIMAL_VALUE = "Invalid hexadecimal value" +ECMA_ERR_INVALID_LENGTH = "Invalid length" +ECMA_ERR_INVALID_NEW_ARRAY_LENGTH = "Invalid new Array length" +ECMA_ERR_INVALID_OFFSET = "Invalid offset" +ECMA_ERR_INVALID_OR_OUT_OF_RANGE_INDEX = "Invalid or out-of-range index" +ECMA_ERR_INVALID_QUANTIFIER = "Invalid quantifier" +ECMA_ERR_INVALID_RANGE_OF_INDEX = "Invalid range of index" +ECMA_ERR_INVALID_SCOPE_CHAIN_INDEX_FOR_EVAL = "Invalid scope chain index for eval" +ECMA_ERR_INVALID_SPECIES_CONSTRUCTOR = "Invalid species constructor" +ECMA_ERR_INVALID_STRING_ = "Invalid string length" +ECMA_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE = "Invalid unicode escape sequence" +ECMA_ERR_ITERATOR_NEXT_IS_NOT_CALLABLE = "Iterator 'next' is not callable" +ECMA_ERR_ITERATOR_RETURN_RESULT_IS_NOT_OBJECT = "Iterator 'return' result is not object" +ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE = "Iterator 'throw' is not available" +ECMA_ERR_ITERATOR_IS_NOT_AN_OBJECT = "Iterator is not an object" +ECMA_ERR_ITERATOR_IS_NOT_CALLABLE = "Iterator is not callable" +ECMA_ERR_ITERATOR_RESULT_IS_NOT_AN_OBJECT = "Iterator result is not an object" +ECMA_ERR_ITERATOR_VALUE_IS_NOT_AN_OBJECT = "Iterator value is not an object" +ECMA_ERR_JSON_STRING_PARSE_ERROR = "JSON string parse error" +ECMA_ERR_JSON_STRINGIFY_ERROR = "JSON stringify error" +ECMA_ERR_KEY_MUST_BE_AN_OBJECT = "Key must be an object" +ECMA_ERR_LONE_QUANTIFIER_BRACKET = "Lone quantifier bracket" +ECMA_ERR_MAXIMUM_TYPEDARRAY_SIZE_IS_REACHED = "Maximum TypedArray size is reached" +ECMA_ERR_MAXIMUM_STRING_LENGTH_IS_REACHED = "Maximum string length is reached" +ECMA_ERR_MISSING_ARRAY_ELEMENT = "Missing Array element" +ECMA_ERR_MODULE_CANNOT_BE_INSTANTIATED = "Module cannot be instantiated" +ECMA_ERR_MODULE_EXPORTS_MUST_BE_STRING_VALUES = "Module exports must be string values" +ECMA_ERR_MODULE_EXPORTS_MUST_BE_VALID_IDENTIFIERS = "Module exports must be valid identifiers" +ECMA_ERR_MODULE_IS_IN_ERROR_STATE = "Module is in error state" +ECMA_ERR_MODULE_MUST_BE_IN_LINKED_STATE = "Module must be in linked state" +ECMA_ERR_MODULE_MUST_BE_IN_UNLINKED_STATE = "Module must be in unlinked state" +ECMA_ERR_CALL_SUPER_CONSTRUCTOR_DERIVED_CLASS_BEFORE_THIS = "Must call super constructor in derived class before accessing 'this' or returning from it" +ECMA_ERR_NAMESPACE_OBJECT_IS_NOT_AVAILABLE = "Namespace object is not available" +ECMA_ERR_NEGATIVE_EXPONENT_IS_NOT_ALLOWED_FOR_BIGINTS = "Negative exponent is not allowed for BigInts" +ECMA_ERR_NO_SOURCE_ARGUMENT = "No source argument" +ECMA_ERR_NOTHING_TO_REPEAT = "Nothing to repeat" +ECMA_ERR_OBJECT_CANNOT_BE_FROZEN = "Object cannot be frozen" +ECMA_ERR_OBJECT_CANNOT_BE_SEALED = "Object cannot be sealed" +ECMA_ERR_OBJECT_EXPECTED = "Object expected" +ECMA_ERR_OBJECT_IS_NOT_A_TYPEDARRAY = "Object is not a TypedArray" +ECMA_ERR_ONLY_INTEGER_NUMBERS_CAN_BE_CONVERTED_TO_BIGINT = "Only integer numbers can be converted to BigInt" +ECMA_ERR_OPERATOR_DELETE_RETURNED_FALSE_IN_STRICT_MODE = "Operator delete returned false in strict mode" +ECMA_ERR_PASSED_ARGUMENT_IS_NOT_A_REALM = "Passed argument is not a realm" +ECMA_ERR_PRECISION_DIGITS_MUST_BE_BETWEEN_IN_RANGE = "Precision digits must be between 1 and 100" +ECMA_ERR_PROMISE_ALL_REMAINING_ELEMENTS_LIMIT_REACHED = "Promise.all remaining elements limit reached" +ECMA_ERR_PROPERTY_PROTOTYPE_IS_NOT_AN_OBJECT = "Property 'prototype' is not an object or null" +ECMA_ERR_PROPERTY_NAME_IS_NEITHER_SYMBOL_NOR_STRING = "Property name is neither Symbol nor string" +ECMA_ERR_PROXY_PROPERTY_NOT_CONFIGURABLE_NOT_HAVE_GETTER = "Property of a Proxy is non-configurable and does not have a getter function" +ECMA_ERR_PROTOTYPE_FROM_REVOKED_PROXY_IS_INVALID = "Prototype from revoked Proxy is invalid" +ECMA_ERR_PROTOTYPE_IS_NEITHER_OBJECT_NOR_NULL = "Prototype is neither object nor null" +ECMA_ERR_PROXY_HANDLER_IS_NULL_FOR_ISARRAY_OPERATION = "Proxy handler is null for 'isArray' operation" +ECMA_ERR_PROXY_IS_NOT_SUPPORTED = "Proxy is not supported" +ECMA_ERR_TARGET_NOT_EXTENSIBLE_NOT_RETURNED_ITS_PROTOTYPE = "Proxy target is non-extensible, but the trap did not return its actual prototype" +ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH = "Proxy trap returned falsish" +ECMA_ERR_PUSHING_TOO_HIGH_ELEMENT = "Pushing element over 2**53-1 length is disallowed" +ECMA_ERR_MIN_GREATER_THAN_MAX = "Quantifier error: min > max" +ECMA_ERR_RADIX_IS_OUT_OF_RANGE = "Radix must be between 2 and 36" +ECMA_ERR_RANGE_OUT_OF_ORDER_IN_CHARACTER_CLASS = "Range out of order in character class" +ECMA_ERR_REALM_IS_NOT_AVAILABLE = "Realm is not available" +ECMA_ERR_REALMS_ARE_DISABLED = "Realms are disabled" +ECMA_ERR_REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE = "Reduce of empty Array with no initial value" +ECMA_ERR_REFLECT_EXPECTS_AN_OBJECT_AS_SECOND_ARGUMENT = "Reflect.construct expects an object as second argument" +ECMA_ERR_REGEXP_ARGUMENT_SHOULD_HAVE_GLOBAL_FLAG = "RegExp argument should have global flag" +ECMA_ERR_REGEXP_IS_NOT_SUPPORTED = "RegExp is not supported" +ECMA_ERR_REJECT_MUST_BE_UNDEFINED = "Reject must be undefined" +ECMA_ERR_REQUEST_IS_NOT_AVAILABLE = "Request is not available" +ECMA_ERR_RESOLVE_METHOD_MUST_BE_CALLABLE = "Resolve method must be callable" +ECMA_ERR_RESOLVE_MUST_BE_UNDEFINED = "Resolve must be undefined" +ECMA_ERR_RESULT_OF_DEFAULTVALUE_IS_INVALID = "Result of [[DefaultValue]] is invalid" +ECMA_ERR_RETURN_VALUE_IS_NOT_AN_ARRAYBUFFER_OBJECT = "Return value is not an ArrayBuffer object" +ECMA_ERR_RETURN_VALUE_OF_EXEC_MUST_BE_AN_OBJECT_OR_NULL = "Return value of 'exec' must be an object or null" +ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT = "Right value of 'in' must be an object" +ECMA_ERR_RIGHT_VALUE_OF_INSTANCEOF_MUST_BE_AN_OBJECT = "Right value of 'instanceof' must be an object" +ECMA_ERR_SEARCH_STRING_CANNOT_BE_OF_TYPE_REGEXP = "Search string can't be of type: RegExp" +ECMA_ERR_SECOND_ARGUMENT_MUST_BE_AN_OBJECT = "Second argument must be an object" +ECMA_ERR_SPECIES_MUST_BE_A_CONSTRUCTOR = "Species must be a constructor" +ECMA_ERR_STACK_LIMIT_EXCEEDED = "Stack limit exceeded" +ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER = "Start offset is outside the bounds of the buffer" +ECMA_ERR_STATIC_SNAPSHOTS_ARE_NOT_ENABLED = "Static snapshots are not enabled" +ECMA_ERR_STATIC_SNAPSHOTS_CANNOT_BE_COPIED_INTO_MEMORY = "Static snapshots cannot be copied into memory" +ECMA_ERR_STRING_CANNOT_BE_CONVERTED_TO_BIGINT_VALUE = "String cannot be converted to BigInt value" +ECMA_ERR_SUPER_BINDING_MUST_BE_A_CONSTRUCTOR = "Super binding must be a constructor" +ECMA_ERR_SUPER_CONSTRUCTOR_MAY_ONLY_BE_CALLED_ONCE = "Super constructor may only be called once" +ECMA_ERR_SYMBOL_IS_NOT_A_CONSTRUCTOR = "Symbol is not a constructor" +ECMA_ERR_TARGET_IS_NOT_OBJECT = "Target is not Object" +ECMA_ERR_TARGET_IS_NOT_WEAKREF = "Target is not weakRef" +ECMA_ERR_TARGET_NOT_EXTENSIBLE = "Target not extensible" +ECMA_ERR_TARGET_NOT_EXTENSIBLE_DIFFERENT_PROTOTYPE_RETURNED = "Target object is non-extensible and trap returned different prototype" +ECMA_ERR_THE_MAPFN_ARGUMENT_IS_NOT_CALLABLE = "The 'mapfn' argument is not callable" +ECMA_ERR_THE_GIVEN_ARGUMENT_IS_NOT_A_SYMBOL = "The given argument is not a Symbol" +ECMA_ERR_TARGET_PROPERTY_CONFIGURE_ACCESSOR_WITHOUT_SETTER = "The property of a Proxy target is a non configurable accessor without a setter" +ECMA_ERR_THE_REQUESTED_PROPERTY_UPDATE_CANNOT_BE_PERFORMED = "The requested property update cannot be performed" +ECMA_ERR_THE_STRUCTURE_IS_CYCLICAL = "The structure is cyclical" +ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE = "The two descriptors are incompatible" +ECMA_ERR_TOO_MANY_ARGUMENTS_DECLARED_FOR_FUNCTION_APPLY = "Too many arguments declared for Function.apply" +ECMA_ERR_TRAP_IS_NEITHER_AN_OBJECT_NOR_UNDEFINED = "Trap is neither an object nor undefined" +ECMA_ERR_TRAP_MUST_RETURN_WITH_AN_OBJECT = "Trap must return with an object" +ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_CONFIGURABLE_KEYS = "Trap result did not include all configurable keys" +ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_NON_CONFIGURABLE_KEYS = "Trap result did not include all non-configurable keys" +ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_EXTENSIBILITY = "Trap result does not reflect extensibility of Proxy target" +ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_INEXTENSIBILITY = "Trap result does not reflect inextensibility of Proxy target" +ECMA_ERR_TRAP_EXTRA_KEYS_FOR_A_NON_EXTENSIBLE_TARGET = "Trap returned extra keys for a non-extensible Proxy target" +ECMA_ERR_TRAP_FALSISH_PROPERTY_TARGET_NOT_EXTENSIBLE = "Trap returned falsish for property but the proxy target is not extensible" +ECMA_ERR_TRAP_FALSISH_PROPERTY_NON_CONFIGURABLE = "Trap returned falsish for property which exists in the proxy target as non-configurable" +ECMA_ERR_TRAP_RETURNED_NEITHER_OBJECT_NOR_NULL = "Trap returned neither object nor null" +ECMA_ERR_TRAP_TRUISH_ADDING_PROPERTY_NON_EXTENSIBLE_TARGET = "Trap returned truish for adding property to the non-extensible target" +ECMA_ERR_TRAP_TRUISH_ADD_PROPERTY_INCOMPATIBLE_OTHER_PROP = "Trap returned truish for adding property that is incompatible with the existing property in the target" +ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY = "Trap returned truish for defining non-configurable property which is non-existent in the target" +ECMA_ERR_TRAP_TRUISH_PROPERTY_NON_CONFIGURABLE = "Trap returned truish for property which is non-configurable in the proxy target" +ECMA_ERR_TRAP_TRUISH_TARGET_NOT_EXTENSIBLE = "Trap returned truish for target is not extensible" +ECMA_ERR_TRAP_WITH_DUPLICATED_ENTRIES = "Trap returned with duplicated entries" +ECMA_ERR_TYPEDARRAY_INTRINSTIC_CALLED_BY_NEW_EXPRESSION = "TypedArray intrinstic cannot be called by a 'new' expression" +ECMA_ERR_TYPEDARRAY_INTRINSTIC_DIRECTLY_CALLED = "TypedArray intrinstic cannot be directly called" +ECMA_ERR_CONTENTTYPE_RETURNED_TYPEDARRAY_NOT_MATCH_SOURCE = "TypedArray returned by [[ContentType]] does not match source" +ECMA_ERR_UNARY_PLUS_IS_NOT_ALLOWED_FOR_BIGINTS = "Unary plus is not allowed for BigInts" +ECMA_ERR_UNDEFINED_REFERENCE = "Undefined reference" +ECMA_ERR_UNEXPECTED_END_OF_PATTERN = "Unexpected end of pattern" +ECMA_ERR_UNICODE_SURROGATE_PAIR_MISSING = "Unicode surrogate pair missing" +ECMA_ERR_UNMATCHED_CLOSE_BRACKET = "Unmatched close bracket" +ECMA_ERR_UNSHIFT_TOO_HIGH = "Unshift elements over 2**53-1 length is disallowed" +ECMA_ERR_UNSIGNED_RIGHT_SHIFT_IS_NOT_ALLOWED_FOR_BIGINTS = "Unsigned right shift is not allowed for BigInts" +ECMA_ERR_UNSUPPORTED_BINARY_OPERATION = "Unsupported binary operation" +ECMA_ERR_UNSUPPORTED_CONTAINER_OPERATION = "Unsupported container operation" +ECMA_ERR_UNSUPPORTED_SNAPSHOT_EXEC_FLAGS_ARE_SPECIFIED = "Unsupported snapshot exec flags are specified" +ECMA_ERR_UNTERMINATED_CHARACTER_CLASS = "Unterminated character class" +ECMA_ERR_UNTERMINATED_GROUP = "Unterminated group" +ECMA_ERR_VALUE_CANNOT_BE_CONVERTED_TO_BIGINT = "Value cannot be converted to BigInt" +ECMA_ERR_VALUE_FOR_CLASS_HERITAGE_IS_NOT_A_CONSTRUCTOR = "Value for class heritage is not a constructor" +ECMA_ERR_VALUE_RECEIVED_BY_FOR_ASYNC_OF_IS_NOT_OBJECT = "Value received by for-async-of is not object" +ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT = "Value received by yield* is not object" +ECMA_ERR_WEAKREF_TARGET_MUST_BE_AN_OBJECT = "WeakRef target must be an object" +ECMA_ERR_METHOD_RETURN_IS_NOT_CALLABLE = "method 'return' is not callable" +ECMA_ERR_VALUE_MSG = "Argument cannot be marked as error" +ECMA_ERR_WRONG_ARGS_MSG = "This type of argument is not allowed" +ECMA_ERR_PARSER_NOT_SUPPORTED = "Source code parsing is disabled" +ECMA_ERR_JSON_NOT_SUPPORTED = "JSON support is disabled" +ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED = "TypedArray support is disabled" +ECMA_ERR_SHARED_ARRAYBUFFER_NOT_SUPPORTED = "SharedArrayBuffer support is disabled" +ECMA_ERR_DATA_VIEW_NOT_SUPPORTED = "DataView support is disabled" +ECMA_ERR_BIGINT_NOT_SUPPORTED = "BigInt support is disabled" +ECMA_ERR_CONTAINER_NOT_SUPPORTED = "Container support is disabled" +ECMA_ERR_NOT_MODULE = "Argument is not a module" +ECMA_ERR_UNKNOWN_EXPORT = "Native module export not found" +ECMA_ERR_MODULE_NOT_SUPPORTED = "Module support is disabled" +ECMA_ERR_CALLBACK_IS_NOT_CALLABLE = "Callback function is not callable" +ECMA_ERR_ARRAYBUFFER_IS_DETACHED = "ArrayBuffer has been detached" +ECMA_ERR_CANNOT_CONVERT_TO_OBJECT = "Cannot convert undefined or null to object" +ECMA_ERR_CLASS_IS_NON_CONFIGURABLE = "Prototype property of a class is non-configurable" +ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT = "Argument is not an object" +ECMA_ERR_ARGUMENT_IS_NOT_A_PROXY = "Argument is not a Proxy object" +ECMA_ERR_TARGET_IS_NOT_A_CONSTRUCTOR = "Target is not a constructor" +ECMA_ERR_ARGUMENT_IS_NOT_AN_REGEXP = "Argument 'this' is not a RegExp object" +ECMA_ERR_INVALID_ARRAY_LENGTH = "Invalid Array length" +ECMA_ERR_LOCAL_VARIABLE_IS_REDECLARED = "Local variable is redeclared" +ECMA_ERR_EXPECTED_A_FUNCTION = "Expected a function" +ECMA_ERR_CLASS_CONSTRUCTOR_NEW = "Class constructor cannot be invoked without 'new'" +ECMA_ERR_LET_CONST_NOT_INITIALIZED = "Variables declared by let/const must be initialized before reading their value" +ECMA_ERR_MAXIMUM_SNAPSHOT_SIZE = "Maximum snapshot size reached" +ECMA_ERR_REGULAR_EXPRESSION_NOT_SUPPORTED = "Regular expression literals are not supported" +ECMA_ERR_SNAPSHOT_BUFFER_SMALL = "Snapshot buffer too small" +ECMA_ERR_SNAPSHOT_UNSUPPORTED_COMPILED_CODE = "Unsupported compiled code" +ECMA_ERR_SNAPSHOT_FLAG_NOT_SUPPORTED = "Unsupported generate snapshot flags specified" +ECMA_ERR_SNAPSHOT_SAVE_DISABLED = "Snapshot generation is disabled" +ECMA_ERR_SNAPSHOT_EXEC_DISABLED = "Snapshot execution is disabled" +ECMA_ERR_CANNOT_ALLOCATE_MEMORY_LITERALS = "Cannot allocate memory for literals" +ECMA_ERR_TAGGED_TEMPLATE_LITERALS = "Unsupported feature: tagged template literals" +ECMA_ERR_CONTAINER_NEEDED = "Value is not a Container or Iterator" +ECMA_ERR_INCORRECT_TYPE_CALL = "Operator called on incorrect container type" +ECMA_ERR_INVALID_TYPE_FOR_CONSTRUCTOR_CALL = "Invalid type for constructor call" +ECMA_ERR_SCRIPT_GLOBAL_FUNCTIONS_INVOKE_WITH_NEW = "Script (global) functions cannot be invoked with 'new'" +ECMA_ERR_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW = "Generator functions cannot be invoked with 'new'" +ECMA_ERR_ASYNC_FUNCTIONS_INVOKE_WITH_NEW = "Async functions cannot be invoked with 'new'" +ECMA_ERR_ASYNC_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW = "Async generator functions cannot be invoked with 'new'" +ECMA_ERR_ACCESSOR_FUNCTIONS_INVOKE_WITH_NEW = "Accessor functions cannot be invoked with 'new'" +ECMA_ERR_METHODS_INVOKE_WITH_NEW = "Methods cannot be invoked with 'new'" +ECMA_ERR_ARROW_FUNCTIONS_INVOKE_WITH_NEW = "Arrow functions cannot be invoked with 'new'" +ECMA_ERR_ASYNC_ARROW_FUNCTIONS_INVOKE_WITH_NEW = "Async arrow functions cannot be invoked with 'new'" +ECMA_ERR_PROXY_TARGET_IS_NOT_A_CONSTRUCTOR = "Proxy target is not a constructor" +ECMA_ERR_MAXIMUM_CALL_STACK_SIZE_EXCEEDED = "Maximum call stack size exceeded" +ECMA_ERR_INVALID_SNAPSHOT_FORMAT = "Invalid snapshot format" +ECMA_ERR_INVALID_SNAPSHOT_VERSION_OR_FEATURES = "Invalid snapshot version or unsupported features present" +ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT = "Receiver must be an object" +ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE = "Cannot declare same private field twice" +ECMA_ERR_CANNOT_WRITE_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT = "Cannot write private member to an object whose class did not declare it" +ECMA_ERR_PRIVATE_METHOD_IS_NOT_WRITABLE = "Private method is not writable" +ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_SETTER = "Private field was defined without a setter" +ECMA_ERR_CANNOT_READ_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT = "Cannot read private member to an object whose class did not declare it" +ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_GETTER = "Private field was defined without a getter" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.cpp new file mode 100644 index 00000000..7592fe82 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.cpp @@ -0,0 +1,71 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-errors.h" + +#if JERRY_ERROR_MESSAGES +/** + * Struct to store ecma error message with its size. + */ +typedef struct +{ + char *text; /* Text of ecma error message. */ + uint8_t size; /* Size of ecma error message. */ +} ecma_error_message_t; + +/* Error message texts with size. */ +static ecma_error_message_t ecma_error_messages[] JERRY_ATTR_CONST_DATA = { + { "", 0 }, /* ECMA_ERR_EMPTY */ +/** @cond doxygen_suppress */ +#define ECMA_ERROR_DEF(id, string) { string, sizeof (string) - 1 }, +#include "ecma-error-messages.inc.h" +#undef ECMA_ERROR_DEF + /** @endcond */ +}; +#endif /* JERRY_ERROR_MESSAGES */ + +/** + * Get specified ecma error as zero-terminated string + * + * @return pointer to zero-terminated ecma error + */ +const char * +ecma_get_error_msg (ecma_error_msg_t id) /**< ecma error id */ +{ + JERRY_ASSERT (id != ECMA_IS_VALID_CONSTRUCTOR); + +#if JERRY_ERROR_MESSAGES + return ecma_error_messages[id].text; +#else /* !JERRY_ERROR_MESSAGES */ + return NULL; +#endif /* JERRY_ERROR_MESSAGES */ +} /* ecma_get_error_msg */ + +/** + * Get size of specified ecma error + * + * @return size in bytes + */ +lit_utf8_size_t +ecma_get_error_size (ecma_error_msg_t id) /**< ecma error id */ +{ + JERRY_ASSERT (id != ECMA_IS_VALID_CONSTRUCTOR); + +#if JERRY_ERROR_MESSAGES + return ecma_error_messages[id].size; +#else /* !JERRY_ERROR_MESSAGES */ + return 0; +#endif /* JERRY_ERROR_MESSAGES */ +} /* ecma_get_error_size */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.h new file mode 100644 index 00000000..72947e6e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.h @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ERRORS_H +#define ECMA_ERRORS_H + +#include "lit-globals.h" + +typedef enum +{ + ECMA_ERR_EMPTY, +/** @cond doxygen_suppress */ +#if JERRY_ERROR_MESSAGES +#define ECMA_ERROR_DEF(id, ascii_zt_string) id, +#else /* !JERRY_ERROR_MESSAGES */ +#define ECMA_ERROR_DEF(id, ascii_zt_string) id = ECMA_ERR_EMPTY, +#endif /* JERRY_ERROR_MESSAGES */ +#include "ecma-error-messages.inc.h" +#undef ECMA_ERROR_DEF + /** @endcond */ + ECMA_IS_VALID_CONSTRUCTOR /* used as return value when checking constructor */ +} ecma_error_msg_t; + +const char* ecma_get_error_msg (ecma_error_msg_t id); +lit_utf8_size_t ecma_get_error_size (ecma_error_msg_t id); + +#endif /* !ECMA_ERRORS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.cpp new file mode 100644 index 00000000..1dcf3d34 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.cpp @@ -0,0 +1,144 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-extended-info.h" + +#include "ecma-helpers.h" + +#include "byte-code.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaextendedinfo Extended info + * @{ + */ + +/** + * Decodes an uint32_t number, and updates the buffer position. + * + * @return the decoded value + */ +uint32_t +ecma_extended_info_decode_vlq (uint8_t **buffer_p) /**< [in/out] target buffer */ +{ + uint8_t *source_p = *buffer_p; + uint32_t value = 0; + + do + { + source_p--; + value = (value << ECMA_EXTENDED_INFO_VLQ_SHIFT) | (*source_p & ECMA_EXTENDED_INFO_VLQ_MASK); + } while (*source_p & ECMA_EXTENDED_INFO_VLQ_CONTINUE); + + *buffer_p = source_p; + return value; +} /* ecma_extended_info_decode_vlq */ + +/** + * Encodes an uint32_t number into a buffer. + */ +void +ecma_extended_info_encode_vlq (uint8_t **buffer_p, /**< target buffer */ + uint32_t value) /**< encoded value */ +{ + uint8_t *destination_p = *buffer_p - 1; + + if (value <= ECMA_EXTENDED_INFO_VLQ_MASK) + { + *destination_p = (uint8_t) value; + *buffer_p = destination_p; + return; + } + + uint32_t length = 0; + uint32_t current_value = value >> ECMA_EXTENDED_INFO_VLQ_SHIFT; + + do + { + current_value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT; + length++; + } while (current_value > 0); + + destination_p -= length; + *buffer_p = destination_p; + + do + { + *destination_p++ = (uint8_t) (value | ECMA_EXTENDED_INFO_VLQ_CONTINUE); + value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT; + } while (value > 0); + + **buffer_p &= ECMA_EXTENDED_INFO_VLQ_MASK; +} /* ecma_extended_info_encode_vlq */ + +/** + * Gets the encoded length of a number. + * + * @return encoded length + */ +uint32_t +ecma_extended_info_get_encoded_length (uint32_t value) /**< encoded value */ +{ + uint32_t length = 0; + + do + { + value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT; + length++; + } while (value > 0); + + return length; +} /* ecma_extended_info_get_encoded_length */ + +/** + * Get the extended info from a byte code + * + * @return pointer to the extended info + */ +uint8_t * +ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO); + + ecma_value_t *base_p = ecma_compiled_code_resolve_arguments_start (bytecode_header_p); + + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR) + { + base_p--; + } + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS) + { + base_p--; + } + +#if JERRY_LINE_INFO + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO) + { + base_p--; + } +#endif /* JERRY_LINE_INFO */ + + JERRY_ASSERT (((uint8_t *) base_p)[-1] != 0); + + return ((uint8_t *) base_p) - 1; +} /* ecma_compiled_code_resolve_extended_info */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.h new file mode 100644 index 00000000..57046bd2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.h @@ -0,0 +1,54 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_EXTENDED_INFO_H +#define ECMA_EXTENDED_INFO_H + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaextendedinfo Extended info + * @{ + */ + +#include "ecma-globals.h" + +/** + * Vlq encoding: flag which is set for all bytes except the last one. + */ +#define ECMA_EXTENDED_INFO_VLQ_CONTINUE 0x80 + +/** + * Vlq encoding: mask to decode the number fragment. + */ +#define ECMA_EXTENDED_INFO_VLQ_MASK 0x7f + +/** + * Vlq encoding: number of bits stored in a byte. + */ +#define ECMA_EXTENDED_INFO_VLQ_SHIFT 7 + +uint32_t ecma_extended_info_decode_vlq (uint8_t **buffer_p); +void ecma_extended_info_encode_vlq (uint8_t **buffer_p, uint32_t value); +uint32_t ecma_extended_info_get_encoded_length (uint32_t value); + +uint8_t *ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_EXTENDED_INFO_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.cpp new file mode 100644 index 00000000..ea6f380c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.cpp @@ -0,0 +1,2344 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Garbage collector implementation + */ + +#include "ecma-gc.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-arraybuffer-object.h" +#include "ecma-builtin-handlers.h" +#include "ecma-container-object.h" +#include "ecma-function-object.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lcache.h" +#include "ecma-objects.h" +#include "ecma-property-hashmap.h" +#include "ecma-proxy-object.h" + +#include "jcontext.h" +#include "jrt-bit-fields.h" +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "re-compiler.h" +#include "vm-defines.h" +#include "vm-stack.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#include "ecma-typedarray-object.h" +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#include "ecma-promise-object.h" + +/* TODO: Extract GC to a separate component */ + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmagc Garbage collector + * @{ + */ + +/* + * The garbage collector uses the reference counter + * of object: it increases the counter by one when + * the object is marked at the first time. + */ + +/** + * Get visited flag of the object. + * + * @return true - if visited + * false - otherwise + */ +static inline bool +ecma_gc_is_object_visited (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + + return (object_p->type_flags_refs < ECMA_OBJECT_NON_VISITED); +} /* ecma_gc_is_object_visited */ + +/** + * Mark objects as visited starting from specified object as root + */ +static void ecma_gc_mark (ecma_object_t *object_p); + +/** + * Set visited flag of the object. + */ +static void +ecma_gc_set_object_visited (ecma_object_t *object_p) /**< object */ +{ + if (object_p->type_flags_refs >= ECMA_OBJECT_NON_VISITED) + { +#if (JERRY_GC_MARK_LIMIT != 0) + if (JERRY_CONTEXT (ecma_gc_mark_recursion_limit) != 0) + { + JERRY_CONTEXT (ecma_gc_mark_recursion_limit)--; + /* Set the reference count of gray object to 0 */ + object_p->type_flags_refs &= (ecma_object_descriptor_t) (ECMA_OBJECT_REF_ONE - 1); + ecma_gc_mark (object_p); + JERRY_CONTEXT (ecma_gc_mark_recursion_limit)++; + } + else + { + /* Set the reference count of the non-marked gray object to 1 */ + object_p->type_flags_refs &= (ecma_object_descriptor_t) ((ECMA_OBJECT_REF_ONE << 1) - 1); + JERRY_ASSERT (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE); + } +#else /* (JERRY_GC_MARK_LIMIT == 0) */ + /* Set the reference count of gray object to 0 */ + object_p->type_flags_refs &= (ecma_object_descriptor_t) (ECMA_OBJECT_REF_ONE - 1); +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + } +} /* ecma_gc_set_object_visited */ + +/** + * Initialize GC information for the object + */ +void +ecma_init_gc_info (ecma_object_t *object_p) /**< object */ +{ + JERRY_CONTEXT (ecma_gc_objects_number)++; + JERRY_CONTEXT (ecma_gc_new_objects)++; + + JERRY_ASSERT (object_p->type_flags_refs < ECMA_OBJECT_REF_ONE); + object_p->type_flags_refs |= ECMA_OBJECT_REF_ONE; + + object_p->gc_next_cp = JERRY_CONTEXT (ecma_gc_objects_cp); + ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (ecma_gc_objects_cp), object_p); +} /* ecma_init_gc_info */ + +/** + * Increase reference counter of an object + * + * @return void + */ +void +ecma_ref_object_inline (ecma_object_t *object_p) /**< object */ +{ + if (JERRY_LIKELY (object_p->type_flags_refs < ECMA_OBJECT_MAX_REF)) + { + object_p->type_flags_refs = (ecma_object_descriptor_t) (object_p->type_flags_refs + ECMA_OBJECT_REF_ONE); + } + else + { + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } +} /* ecma_ref_object_inline */ + +/** + * Increase reference counter of an object + */ +void +ecma_ref_object (ecma_object_t *object_p) /**< object */ +{ + ecma_ref_object_inline (object_p); +} /* ecma_ref_object */ + +/** + * Decrease reference counter of an object + * + * @return void + */ +void +ecma_deref_object (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE); + object_p->type_flags_refs = (ecma_object_descriptor_t) (object_p->type_flags_refs - ECMA_OBJECT_REF_ONE); +} /* ecma_deref_object */ + +/** + * Mark objects referenced by global object + */ +static void +ecma_gc_mark_global_object (ecma_global_object_t *global_object_p) /**< global object */ +{ + JERRY_ASSERT (global_object_p->extended_object.u.built_in.routine_id == 0); + + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, global_object_p->global_env_cp)); + +#if JERRY_BUILTIN_REALMS + ecma_gc_set_object_visited (ecma_get_object_from_value (global_object_p->this_binding)); +#endif /* JERRY_BUILTIN_REALMS */ + + if (global_object_p->global_scope_cp != global_object_p->global_env_cp) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, global_object_p->global_scope_cp)); + } + + jmem_cpointer_t *builtin_objects_p = global_object_p->builtin_objects; + + for (int i = 0; i < ECMA_BUILTIN_OBJECTS_COUNT; i++) + { + if (builtin_objects_p[i] != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, builtin_objects_p[i])); + } + } +} /* ecma_gc_mark_global_object */ + +/** + * Mark objects referenced by arguments object + */ +static void +ecma_gc_mark_arguments_object (ecma_extended_object_t *ext_object_p) /**< arguments object */ +{ + JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) ext_object_p) == ECMA_OBJECT_TYPE_CLASS); + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) ext_object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (arguments_p->callee)); + + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + + if (ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env)); + } + + uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; + + for (uint32_t i = 0; i < arguments_number; i++) + { + if (ecma_is_value_object (argv_p[i])) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (argv_p[i])); + } + } +} /* ecma_gc_mark_arguments_object */ + +/** + * Mark referenced object from property + */ +static void +ecma_gc_mark_properties (ecma_object_t *object_p, /**< object */ + bool mark_references) /**< mark references */ +{ + JERRY_UNUSED (mark_references); + +#if !JERRY_MODULE_SYSTEM + JERRY_ASSERT (!mark_references); +#endif /* !JERRY_MODULE_SYSTEM */ + + jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (uint32_t index = 0; index < ECMA_PROPERTY_PAIR_ITEM_COUNT; index++) + { + uint8_t property = property_pair_p->header.types[index]; + + if (JERRY_LIKELY (ECMA_PROPERTY_IS_RAW (property))) + { + if (property & ECMA_PROPERTY_FLAG_DATA) + { + ecma_value_t value = property_pair_p->values[index].value; + + if (ecma_is_value_object (value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (value)); + } + continue; + } + +#if JERRY_MODULE_SYSTEM + if (mark_references) + { + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + + ecma_property_value_t *accessor_objs_p = property_pair_p->values + index; + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (accessor_objs_p); + + if (get_set_pair_p->getter_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp)); + } + + if (get_set_pair_p->setter_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp)); + } + + continue; + } + + if (!ECMA_PROPERTY_IS_INTERNAL (property)) + { + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_DELETED || property == ECMA_PROPERTY_TYPE_HASHMAP); + continue; + } + + JERRY_ASSERT (property_pair_p->names_cp[index] >= LIT_INTERNAL_MAGIC_STRING_FIRST_DATA + && property_pair_p->names_cp[index] < LIT_MAGIC_STRING__COUNT); + + switch (property_pair_p->names_cp[index]) + { + case LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD: + { + ecma_environment_record_t *environment_record_p; + environment_record_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_environment_record_t, property_pair_p->values[index].value); + + if (environment_record_p->this_binding != ECMA_VALUE_UNINITIALIZED) + { + JERRY_ASSERT (ecma_is_value_object (environment_record_p->this_binding)); + ecma_gc_set_object_visited (ecma_get_object_from_value (environment_record_p->this_binding)); + } + + JERRY_ASSERT (ecma_is_value_object (environment_record_p->function_object)); + ecma_gc_set_object_visited (ecma_get_object_from_value (environment_record_p->function_object)); + break; + } + case LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS: + { + ecma_value_t *compact_collection_p; + compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, property_pair_p->values[index].value); + + ecma_value_t *end_p = ecma_compact_collection_end (compact_collection_p); + ecma_value_t *current_p = compact_collection_p + 1; + + while (end_p - current_p >= ECMA_PRIVATE_ELEMENT_LIST_SIZE) + { + current_p++; /* skip the type */ + current_p++; /* skip the name */ + ecma_value_t value = *current_p++; + + if (!ecma_is_value_undefined (value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (value)); + } + } + break; + } +#if JERRY_BUILTIN_CONTAINER + case LIT_INTERNAL_MAGIC_STRING_WEAK_REFS: + { + ecma_value_t key_arg = ecma_make_object_value (object_p); + ecma_collection_t *refs_p; + + refs_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, property_pair_p->values[index].value); + + for (uint32_t j = 0; j < refs_p->item_count; j++) + { + const ecma_value_t reference_value = refs_p->buffer_p[j]; + + if (ecma_is_value_empty (reference_value)) + { + continue; + } + + ecma_object_t *reference_object_p = ecma_get_object_from_value (reference_value); + + JERRY_ASSERT (ecma_get_object_type (reference_object_p) == ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) reference_object_p; + + if (map_object_p->u.cls.type != ECMA_OBJECT_CLASS_CONTAINER + || map_object_p->u.cls.u2.container_id != LIT_MAGIC_STRING_WEAKMAP_UL + || !ecma_gc_is_object_visited (reference_object_p)) + { + continue; + } + + ecma_value_t value = ecma_op_container_find_weak_value (reference_object_p, key_arg); + + if (ecma_is_value_object (value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (value)); + } + } + break; + } +#endif /* JERRY_BUILTIN_CONTAINER */ + case LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES: + { + jerry_value_t value = property_pair_p->values[index].value; + + if (value == JMEM_CP_NULL) + { + JERRY_ASSERT (!(property & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)); + break; + } + + ecma_native_pointer_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value); + + do + { + jerry_object_native_info_t *native_info_p = item_p->native_info_p; + + JERRY_ASSERT (native_info_p != NULL && native_info_p->number_of_references > 0); + + uint8_t *start_p = ((uint8_t *) item_p->native_p) + native_info_p->offset_of_references; + ecma_value_t *value_p = (ecma_value_t *) start_p; + ecma_value_t *end_p = value_p + native_info_p->number_of_references; + + do + { + if (ecma_is_value_object (*value_p)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*value_p)); + } + } while (++value_p < end_p); + + if (property & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL) + { + break; + } + + item_p = &(((ecma_native_pointer_chain_t *) item_p)->next_p->data); + } while (item_p != NULL); + + break; + } + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } +} /* ecma_gc_mark_properties */ + +/** + * Mark compiled code. + */ +static void +ecma_gc_mark_compiled_code (ecma_value_t script_value) /**< script value */ +{ + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (script_p->refs_and_type & CBC_SCRIPT_USER_VALUE_IS_OBJECT) + { + ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p); + + JERRY_ASSERT (ecma_is_value_object (user_value)); + ecma_gc_set_object_visited (ecma_get_object_from_value (user_value)); + } + +#if JERRY_MODULE_SYSTEM + if (script_p->refs_and_type & CBC_SCRIPT_HAS_IMPORT_META) + { + ecma_value_t import_meta = CBC_SCRIPT_GET_IMPORT_META (script_p, script_p->refs_and_type); + + JERRY_ASSERT (ecma_is_value_object (import_meta)); + ecma_gc_set_object_visited (ecma_get_object_from_value (import_meta)); + } +#endif /* JERRY_MODULE_SYSTEM */ + +#if JERRY_BUILTIN_REALMS + ecma_gc_set_object_visited (script_p->realm_p); +#endif /* JERRY_BUILTIN_REALMS */ +} /* ecma_gc_mark_compiled_code */ + +/** + * Mark objects referenced by bound function object. + * + * @return void + */ +static void JERRY_ATTR_NOINLINE +ecma_gc_mark_bound_function_object (ecma_object_t *object_p) /**< bound function object */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + + ecma_object_t *target_func_p; + target_func_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + + ecma_gc_set_object_visited (target_func_p); + + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + + if (!ecma_is_value_integer_number (args_len_or_this)) + { + if (ecma_is_value_object (args_len_or_this)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (args_len_or_this)); + } + + return; + } + + ecma_integer_value_t args_length = ecma_get_integer_from_value (args_len_or_this); + ecma_value_t *args_p = (ecma_value_t *) (bound_func_p + 1); + + JERRY_ASSERT (args_length > 0); + + for (ecma_integer_value_t i = 0; i < args_length; i++) + { + if (ecma_is_value_object (args_p[i])) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (args_p[i])); + } + } +} /* ecma_gc_mark_bound_function_object */ + +/** + * Mark objects referenced by Promise built-in. + */ +static void +ecma_gc_mark_promise_object (ecma_extended_object_t *ext_object_p) /**< extended object */ +{ + /* Mark promise result. */ + ecma_value_t result = ext_object_p->u.cls.u3.value; + + if (ecma_is_value_object (result)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (result)); + } + + /* Mark all reactions. */ + ecma_promise_object_t *promise_object_p = (ecma_promise_object_t *) ext_object_p; + + ecma_collection_t *collection_p = promise_object_p->reactions; + + if (collection_p != NULL) + { + ecma_value_t *buffer_p = collection_p->buffer_p; + ecma_value_t *buffer_end_p = buffer_p + collection_p->item_count; + + while (buffer_p < buffer_end_p) + { + ecma_value_t value = *buffer_p++; + + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, value)); + + if (JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*buffer_p++)); + } + + if (JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*buffer_p++)); + } + } + } +} /* ecma_gc_mark_promise_object */ + +#if JERRY_BUILTIN_CONTAINER +/** + * Mark objects referenced by Map built-in. + */ +static void +ecma_gc_mark_map_object (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE) + { + ecma_container_pair_t *entry_p = (ecma_container_pair_t *) (start_p + i); + + if (ecma_is_value_empty (entry_p->key)) + { + continue; + } + + if (ecma_is_value_object (entry_p->key)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (entry_p->key)); + } + + if (ecma_is_value_object (entry_p->value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (entry_p->value)); + } + } +} /* ecma_gc_mark_map_object */ + +/** + * Mark objects referenced by WeakMap built-in. + */ +static void +ecma_gc_mark_weakmap_object (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE) + { + ecma_container_pair_t *entry_p = (ecma_container_pair_t *) (start_p + i); + + if (ecma_is_value_empty (entry_p->key)) + { + continue; + } + + JERRY_ASSERT (ecma_is_value_object (entry_p->key)); + + if (ecma_is_value_object (entry_p->value) && ecma_gc_is_object_visited (ecma_get_object_from_value (entry_p->key))) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (entry_p->value)); + } + } +} /* ecma_gc_mark_weakmap_object */ + +/** + * Mark objects referenced by Set built-in. + */ +static void +ecma_gc_mark_set_object (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_VALUE_SIZE) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_is_value_empty (*entry_p)) + { + continue; + } + + if (ecma_is_value_object (*entry_p)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*entry_p)); + } + } +} /* ecma_gc_mark_set_object */ +#endif /* JERRY_BUILTIN_CONTAINER */ + +/** + * Mark objects referenced by inactive generator functions, async functions, etc. + */ +static void +ecma_gc_mark_executable_object (ecma_object_t *object_p) /**< object */ +{ + vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p; + + if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_ASYNC_GENERATOR_CALLED) + { + ecma_value_t task = executable_object_p->extended_object.u.cls.u3.head; + + while (!ECMA_IS_INTERNAL_VALUE_NULL (task)) + { + ecma_async_generator_task_t *task_p; + task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, task); + + JERRY_ASSERT (ecma_is_value_object (task_p->promise)); + ecma_gc_set_object_visited (ecma_get_object_from_value (task_p->promise)); + + if (ecma_is_value_object (task_p->operation_value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (task_p->operation_value)); + } + + task = task_p->next; + } + } + + ecma_gc_set_object_visited (executable_object_p->frame_ctx.lex_env_p); + ecma_gc_set_object_visited (executable_object_p->shared.function_object_p); + + if (!ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED (executable_object_p) + && !(executable_object_p->extended_object.u.cls.u2.executable_obj_flags + & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD)) + { + /* All objects referenced by running executable objects are strong roots, + * and a finished executable object cannot refer to other values. */ + return; + } + + if (ecma_is_value_object (executable_object_p->frame_ctx.this_binding)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (executable_object_p->frame_ctx.this_binding)); + } + + const ecma_compiled_code_t *bytecode_header_p = executable_object_p->shared.bytecode_header_p; + size_t register_end; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + register_end = args_p->register_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + register_end = args_p->register_end; + } + + ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx); + ecma_value_t *register_end_p = register_p + register_end; + + while (register_p < register_end_p) + { + if (ecma_is_value_object (*register_p)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*register_p)); + } + + register_p++; + } + + if (executable_object_p->frame_ctx.context_depth > 0) + { + ecma_value_t *context_end_p = register_p; + + register_p += executable_object_p->frame_ctx.context_depth; + + ecma_value_t *context_top_p = register_p; + + do + { + if (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (context_top_p[-1]))) + { + ecma_value_t *last_item_p = context_top_p - VM_GET_CONTEXT_END (context_top_p[-1]); + JERRY_ASSERT (last_item_p >= context_end_p); + context_top_p--; + + do + { + --context_top_p; + if (ecma_is_value_object (*context_top_p)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*context_top_p)); + } + } while (context_top_p > last_item_p); + + continue; + } + + uint32_t offsets = vm_get_context_value_offsets (context_top_p); + + while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets)) + { + int32_t offset = VM_CONTEXT_GET_NEXT_OFFSET (offsets); + + if (ecma_is_value_object (context_top_p[offset])) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (context_top_p[offset])); + } + + offsets >>= VM_CONTEXT_OFFSET_SHIFT; + } + + JERRY_ASSERT (context_top_p >= context_end_p + offsets); + context_top_p -= offsets; + } while (context_top_p > context_end_p); + } + + register_end_p = executable_object_p->frame_ctx.stack_top_p; + + while (register_p < register_end_p) + { + if (ecma_is_value_object (*register_p)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*register_p)); + } + + register_p++; + } + + if (ecma_is_value_object (executable_object_p->iterator)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (executable_object_p->iterator)); + } +} /* ecma_gc_mark_executable_object */ + +#if JERRY_BUILTIN_PROXY +/** + * Mark the objects referenced by a proxy object + */ +static void +ecma_gc_mark_proxy_object (ecma_object_t *object_p) /**< proxy object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (object_p)); + + ecma_proxy_object_t *proxy_p = (ecma_proxy_object_t *) object_p; + + if (!ecma_is_value_null (proxy_p->target)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (proxy_p->target)); + } + + if (!ecma_is_value_null (proxy_p->handler)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (proxy_p->handler)); + } +} /* ecma_gc_mark_proxy_object */ +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * Mark objects as visited starting from specified object as root + */ +static void +ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (ecma_gc_is_object_visited (object_p)); + + if (ecma_is_lexical_environment (object_p)) + { + jmem_cpointer_t outer_lex_env_cp = object_p->u2.outer_reference_cp; + + if (outer_lex_env_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, outer_lex_env_cp)); + } + + switch (ecma_get_lex_env_type (object_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { +#if JERRY_MODULE_SYSTEM + if (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) + { + if (ECMA_LEX_ENV_CLASS_IS_MODULE (object_p)) + { + ecma_gc_mark_properties (object_p, true); + } + + ecma_gc_set_object_visited (((ecma_lexical_environment_class_t *) object_p)->object_p); + return; + } +#endif /* JERRY_MODULE_SYSTEM */ + /* FALLTHRU */ + } + case ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND: + { + ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p); + ecma_gc_set_object_visited (binding_object_p); + return; + } + default: + { + break; + } + } + } + else + { + /** + * Have the object's prototype here so the object could set it to JMEM_CP_NULL + * if the prototype should be ignored (like in case of PROXY). + */ + jmem_cpointer_t proto_cp = object_p->u2.prototype_cp; + + switch (ecma_get_object_type (object_p)) + { + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + { + ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) object_p; + + if (extended_object_p->u.built_in.id == ECMA_BUILTIN_ID_GLOBAL) + { + ecma_gc_mark_global_object ((ecma_global_object_t *) object_p); + } + +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value = extended_object_p->u.built_in.realm_value; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, realm_value)); +#endif /* JERRY_BUILTIN_REALMS */ + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + { +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value = ((ecma_extended_built_in_object_t *) object_p)->built_in.realm_value; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, realm_value)); +#endif /* JERRY_BUILTIN_REALMS */ + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + ecma_gc_mark_arguments_object (ext_object_p); + break; + } +#if JERRY_PARSER + case ECMA_OBJECT_CLASS_SCRIPT: + { + const ecma_compiled_code_t *compiled_code_p; + compiled_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + + JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + ecma_gc_mark_compiled_code (((cbc_uint8_arguments_t *) compiled_code_p)->script_value); + break; + } +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_TYPEDARRAY + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + ecma_gc_set_object_visited (ecma_typedarray_get_arraybuffer (object_p)); + break; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: + { + JERRY_ASSERT (proto_cp == JMEM_CP_NULL); + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ext_object_p->u.cls.u3.value)); + ecma_gc_mark_properties (object_p, true); + return; + } +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE: + { + ecma_module_t *module_p = ((ecma_module_t *) ext_object_p); + + if (module_p->scope_p != NULL) + { + ecma_gc_set_object_visited (((ecma_module_t *) ext_object_p)->scope_p); + } + + if (module_p->namespace_object_p != NULL) + { + ecma_gc_set_object_visited (((ecma_module_t *) ext_object_p)->namespace_object_p); + } + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) + && module_p->u.compiled_code_p != NULL) + { + const ecma_compiled_code_t *compiled_code_p = module_p->u.compiled_code_p; + + JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + ecma_gc_mark_compiled_code (((cbc_uint8_arguments_t *) compiled_code_p)->script_value); + } + + ecma_module_node_t *node_p = module_p->imports_p; + + while (node_p != NULL) + { + if (ecma_is_value_object (node_p->u.path_or_module)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (node_p->u.path_or_module)); + } + + node_p = node_p->next_p; + } + break; + } +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_DATAVIEW + case ECMA_OBJECT_CLASS_DATAVIEW: + { + ecma_dataview_object_t *dataview_p = (ecma_dataview_object_t *) object_p; + ecma_gc_set_object_visited (dataview_p->buffer_p); + break; + } +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_CONTAINER + case ECMA_OBJECT_CLASS_CONTAINER: + { + if (ext_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_MAP_UL) + { + ecma_gc_mark_map_object (object_p); + break; + } + if (ext_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKMAP_UL) + { + ecma_gc_mark_weakmap_object (object_p); + break; + } + if (ext_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_SET_UL) + { + ecma_gc_mark_set_object (object_p); + break; + } + JERRY_ASSERT (ext_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKSET_UL); + break; + } +#endif /* JERRY_BUILTIN_CONTAINER */ + case ECMA_OBJECT_CLASS_GENERATOR: + case ECMA_OBJECT_CLASS_ASYNC_GENERATOR: + { + ecma_gc_mark_executable_object (object_p); + break; + } + case ECMA_OBJECT_CLASS_PROMISE: + { + ecma_gc_mark_promise_object (ext_object_p); + break; + } + case ECMA_OBJECT_CLASS_PROMISE_CAPABILITY: + { + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) object_p; + + if (ecma_is_value_object (capability_p->header.u.cls.u3.promise)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (capability_p->header.u.cls.u3.promise)); + } + if (ecma_is_value_object (capability_p->resolve)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (capability_p->resolve)); + } + if (ecma_is_value_object (capability_p->reject)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (capability_p->reject)); + } + break; + } + case ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR: + { + ecma_async_from_sync_iterator_object_t *iter_p = (ecma_async_from_sync_iterator_object_t *) ext_object_p; + + ecma_gc_set_object_visited (ecma_get_object_from_value (iter_p->header.u.cls.u3.sync_iterator)); + + if (!ecma_is_value_undefined (iter_p->sync_next_method)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (iter_p->sync_next_method)); + } + + break; + } + case ECMA_OBJECT_CLASS_ARRAY_ITERATOR: + case ECMA_OBJECT_CLASS_SET_ITERATOR: + case ECMA_OBJECT_CLASS_MAP_ITERATOR: + { + ecma_value_t iterated_value = ext_object_p->u.cls.u3.iterated_value; + if (!ecma_is_value_empty (iterated_value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (iterated_value)); + } + break; + } +#if JERRY_BUILTIN_REGEXP + case ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR: + { + ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) object_p; + ecma_value_t regexp = regexp_string_iterator_obj->iterating_regexp; + ecma_gc_set_object_visited (ecma_get_object_from_value (regexp)); + break; + } +#endif /* JERRY_BUILTIN_REGEXP */ + default: + { + /* The ECMA_OBJECT_CLASS__MAX type represents an uninitialized class. */ + JERRY_ASSERT (ext_object_p->u.cls.type <= ECMA_OBJECT_CLASS__MAX); + break; + } + } + + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value = ((ecma_extended_built_in_object_t *) object_p)->built_in.realm_value; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, realm_value)); +#endif /* JERRY_BUILTIN_REALMS */ + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_ARRAY: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (JERRY_UNLIKELY (ext_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL)) + { + /* Template objects are never marked. */ + JERRY_ASSERT (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE); + return; + } + + if (ecma_op_array_is_fast_array (ext_object_p)) + { + if (object_p->u1.property_list_cp != JMEM_CP_NULL) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + for (uint32_t i = 0; i < ext_object_p->u.array.length; i++) + { + if (ecma_is_value_object (values_p[i])) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (values_p[i])); + } + } + } + + if (proto_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp)); + } + return; + } + break; + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + ecma_gc_mark_proxy_object (object_p); + /* Prototype of proxy object is a bit set. */ + proto_cp = JMEM_CP_NULL; + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_OBJECT_TYPE_FUNCTION: + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + ecma_gc_set_object_visited ( + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp)); + + const ecma_compiled_code_t *compiled_code_p = ecma_op_function_get_compiled_code (ext_func_p); + + if (CBC_FUNCTION_IS_ARROW (compiled_code_p->status_flags)) + { + ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) object_p; + + if (ecma_is_value_object (arrow_func_p->this_binding)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (arrow_func_p->this_binding)); + } + + if (ecma_is_value_object (arrow_func_p->new_target)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (arrow_func_p->new_target)); + } + } + +#if JERRY_SNAPSHOT_EXEC + if (JERRY_UNLIKELY (compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + { + /* Static snapshot functions have a global realm */ + break; + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + ecma_gc_mark_compiled_code (((cbc_uint8_arguments_t *) compiled_code_p)->script_value); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_gc_mark_bound_function_object (object_p); + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value = ext_func_p->u.built_in.realm_value; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, realm_value)); +#endif /* JERRY_BUILTIN_REALMS */ + + if (ext_func_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER) + { + switch (ext_func_p->u.built_in.routine_id) + { + case ECMA_NATIVE_HANDLER_PROMISE_RESOLVE: + case ECMA_NATIVE_HANDLER_PROMISE_REJECT: + { + ecma_promise_resolver_t *resolver_obj_p = (ecma_promise_resolver_t *) object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (resolver_obj_p->promise)); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_THEN_FINALLY: + case ECMA_NATIVE_HANDLER_PROMISE_CATCH_FINALLY: + { + ecma_promise_finally_function_t *finally_obj_p = (ecma_promise_finally_function_t *) object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (finally_obj_p->constructor)); + ecma_gc_set_object_visited (ecma_get_object_from_value (finally_obj_p->on_finally)); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_CAPABILITY_EXECUTOR: + { + ecma_promise_capability_executor_t *executor_p = (ecma_promise_capability_executor_t *) object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->capability)); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER: + { + ecma_promise_all_executor_t *executor_p = (ecma_promise_all_executor_t *) object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->capability)); + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->values)); + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->remaining_elements)); + break; + } +#if JERRY_BUILTIN_PROXY + case ECMA_NATIVE_HANDLER_PROXY_REVOKE: + { + ecma_revocable_proxy_object_t *rev_proxy_p = (ecma_revocable_proxy_object_t *) object_p; + + if (!ecma_is_value_null (rev_proxy_p->proxy)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (rev_proxy_p->proxy)); + } + + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_NATIVE_HANDLER_VALUE_THUNK: + case ECMA_NATIVE_HANDLER_VALUE_THROWER: + { + ecma_promise_value_thunk_t *thunk_obj_p = (ecma_promise_value_thunk_t *) object_p; + + if (ecma_is_value_object (thunk_obj_p->value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (thunk_obj_p->value)); + } + break; + } + case ECMA_NATIVE_HANDLER_ASYNC_FROM_SYNC_ITERATOR_UNWRAP: + { + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + } + break; + } + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + ecma_gc_mark_compiled_code (((ecma_extended_object_t *) object_p)->u.constructor_function.script_value); + break; + } +#if JERRY_BUILTIN_REALMS + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + ecma_native_function_t *native_function_p = (ecma_native_function_t *) object_p; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, native_function_p->realm_value)); + break; + } +#endif /* JERRY_BUILTIN_REALMS */ + default: + { + break; + } + } + + if (proto_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp)); + } + } + + ecma_gc_mark_properties (object_p, false); +} /* ecma_gc_mark */ + +/** + * Free the native handle/pointer by calling its free callback. + */ +static void +ecma_gc_free_native_pointer (ecma_property_t property, /**< property descriptor */ + ecma_value_t value) /**< property value */ +{ + if (JERRY_LIKELY (property & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)) + { + JERRY_ASSERT (value != JMEM_CP_NULL); + + ecma_native_pointer_t *native_pointer_p; + native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value); + + if (native_pointer_p->native_info_p != NULL) + { + jerry_object_native_free_cb_t free_cb = native_pointer_p->native_info_p->free_cb; + + if (free_cb != NULL) + { + free_cb (native_pointer_p->native_p, native_pointer_p->native_info_p); + } + } + + jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); + return; + } + + if (value == JMEM_CP_NULL) + { + return; + } + + ecma_native_pointer_chain_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value); + + do + { + if (item_p->data.native_info_p != NULL) + { + jerry_object_native_free_cb_t free_cb = item_p->data.native_info_p->free_cb; + + if (free_cb != NULL) + { + free_cb (item_p->data.native_p, item_p->data.native_info_p); + } + } + + ecma_native_pointer_chain_t *next_p = item_p->next_p; + + jmem_heap_free_block (item_p, sizeof (ecma_native_pointer_chain_t)); + + item_p = next_p; + } while (item_p != NULL); +} /* ecma_gc_free_native_pointer */ + +/** + * Free specified arguments object. + * + * @return allocated object's size + */ +static size_t +ecma_free_arguments_object (ecma_extended_object_t *ext_object_p) /**< arguments object */ +{ + JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) ext_object_p) == ECMA_OBJECT_TYPE_CLASS); + + size_t object_size = sizeof (ecma_unmapped_arguments_t); + + if (ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + object_size = sizeof (ecma_mapped_arguments_t); + +#if JERRY_SNAPSHOT_EXEC + if (!(mapped_arguments_p->unmapped.header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE)) +#endif /* JERRY_SNAPSHOT_EXEC */ + { + ecma_compiled_code_t *byte_code_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, mapped_arguments_p->u.byte_code); + + ecma_bytecode_deref (byte_code_p); + } + } + + ecma_value_t *argv_p = (ecma_value_t *) (((uint8_t *) ext_object_p) + object_size); + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) ext_object_p; + uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; + + for (uint32_t i = 0; i < arguments_number; i++) + { + ecma_free_value_if_not_object (argv_p[i]); + } + + uint32_t saved_argument_count = JERRY_MAX (arguments_number, arguments_p->header.u.cls.u2.formal_params_number); + + return object_size + (saved_argument_count * sizeof (ecma_value_t)); +} /* ecma_free_arguments_object */ + +/** + * Free specified fast access mode array object. + */ +static void +ecma_free_fast_access_array (ecma_object_t *object_p) /**< fast access mode array object to free */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (ext_object_p->u.array.length); + + if (object_p->u1.property_list_cp != JMEM_CP_NULL) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + for (uint32_t i = 0; i < aligned_length; i++) + { + ecma_free_value_if_not_object (values_p[i]); + } + + jmem_heap_free_block (values_p, aligned_length * sizeof (ecma_value_t)); + } + + ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t)); +} /* ecma_free_fast_access_array */ + +/** + * Free non-objects referenced by inactive generator functions, async functions, etc. + * + * @return total object size + */ +static size_t +ecma_gc_free_executable_object (ecma_object_t *object_p) /**< object */ +{ + vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p; + + const ecma_compiled_code_t *bytecode_header_p = executable_object_p->shared.bytecode_header_p; + size_t size, register_end; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + + register_end = args_p->register_end; + size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + + register_end = args_p->register_end; + size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t); + } + + size = JERRY_ALIGNUP (sizeof (vm_executable_object_t) + size, sizeof (uintptr_t)); + ecma_bytecode_deref ((ecma_compiled_code_t *) bytecode_header_p); + + uint16_t executable_obj_flags = executable_object_p->extended_object.u.cls.u2.executable_obj_flags; + + JERRY_ASSERT (!(executable_obj_flags & ECMA_EXECUTABLE_OBJECT_RUNNING)); + + if (executable_obj_flags & ECMA_ASYNC_GENERATOR_CALLED) + { + ecma_value_t task = executable_object_p->extended_object.u.cls.u3.head; + + while (!ECMA_IS_INTERNAL_VALUE_NULL (task)) + { + ecma_async_generator_task_t *task_p; + task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, task); + + JERRY_ASSERT (ecma_is_value_object (task_p->promise)); + ecma_free_value_if_not_object (task_p->operation_value); + + task = task_p->next; + jmem_heap_free_block (task_p, sizeof (ecma_async_generator_task_t)); + } + } + + if (executable_obj_flags & ECMA_EXECUTABLE_OBJECT_COMPLETED) + { + return size; + } + + ecma_free_value_if_not_object (executable_object_p->frame_ctx.this_binding); + + ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx); + ecma_value_t *register_end_p = register_p + register_end; + + while (register_p < register_end_p) + { + ecma_free_value_if_not_object (*register_p++); + } + + if (executable_object_p->frame_ctx.context_depth > 0) + { + ecma_value_t *context_end_p = register_p; + + register_p += executable_object_p->frame_ctx.context_depth; + + ecma_value_t *context_top_p = register_p; + + do + { + context_top_p[-1] &= (uint32_t) ~VM_CONTEXT_HAS_LEX_ENV; + + if (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (context_top_p[-1]))) + { + ecma_value_t *last_item_p = context_top_p - VM_GET_CONTEXT_END (context_top_p[-1]); + JERRY_ASSERT (last_item_p >= context_end_p); + context_top_p--; + + do + { + ecma_free_value_if_not_object (*(--context_top_p)); + } while (context_top_p > last_item_p); + + continue; + } + + uint32_t offsets = vm_get_context_value_offsets (context_top_p); + + while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets)) + { + int32_t offset = VM_CONTEXT_GET_NEXT_OFFSET (offsets); + + if (ecma_is_value_object (context_top_p[offset])) + { + context_top_p[offset] = ECMA_VALUE_UNDEFINED; + } + + offsets >>= VM_CONTEXT_OFFSET_SHIFT; + } + + context_top_p = vm_stack_context_abort (&executable_object_p->frame_ctx, context_top_p); + } while (context_top_p > context_end_p); + } + + register_end_p = executable_object_p->frame_ctx.stack_top_p; + + while (register_p < register_end_p) + { + ecma_free_value_if_not_object (*register_p++); + } + + return size; +} /* ecma_gc_free_executable_object */ + +JERRY_STATIC_ASSERT (!ECMA_PROPERTY_IS_RAW (ECMA_PROPERTY_TYPE_DELETED), + ecma_property_type_deleted_must_not_be_raw_property); +JERRY_STATIC_ASSERT ((((int)ECMA_PROPERTY_TYPE_DELETED & (int)ECMA_PROPERTY_FLAG_LCACHED) == 0), + ecma_property_type_deleted_must_not_have_lcached_flag); +JERRY_STATIC_ASSERT ((((int)ECMA_GC_FREE_SECOND_PROPERTY) == 1), ecma_gc_free_second_must_be_one); + +/** + * Free property of an object + */ +void +ecma_gc_free_property (ecma_object_t *object_p, /**< object */ + ecma_property_pair_t *prop_pair_p, /**< property pair */ + uint32_t options) /**< option bits including property index */ +{ + /* Both cannot be deleted. */ + JERRY_ASSERT (prop_pair_p->header.types[0] != ECMA_PROPERTY_TYPE_DELETED + || prop_pair_p->header.types[1] != ECMA_PROPERTY_TYPE_DELETED); + JERRY_ASSERT (prop_pair_p->header.types[0] != ECMA_PROPERTY_TYPE_HASHMAP); + + uint32_t index = (options & ECMA_GC_FREE_SECOND_PROPERTY); + jmem_cpointer_t name_cp = prop_pair_p->names_cp[index]; + ecma_property_t *property_p = prop_pair_p->header.types + index; + ecma_property_t property = *property_p; + +#if JERRY_LCACHE + if ((property & ECMA_PROPERTY_FLAG_LCACHED) != 0) + { + ecma_lcache_invalidate (object_p, name_cp, property_p); + } +#endif /* JERRY_LCACHE */ + + if (ECMA_PROPERTY_IS_RAW (property)) + { + if (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_DIRECT_STRING_PTR) + { + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, name_cp); + ecma_deref_ecma_string (prop_name_p); + } + + if (property & ECMA_PROPERTY_FLAG_DATA) + { + ecma_free_value_if_not_object (prop_pair_p->values[index].value); + return; + } + + if (JERRY_UNLIKELY (options & ECMA_GC_FREE_REFERENCES)) + { + return; + } + +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = + ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_pair_p->values[index].getter_setter_pair_cp); + jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t)); +#endif /* JERRY_CPOINTER_32_BIT */ + return; + } + + if (property == ECMA_PROPERTY_TYPE_DELETED) + { + return; + } + + ecma_value_t value = prop_pair_p->values[index].value; + + switch (name_cp) + { + case LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD: + { + ecma_environment_record_t *environment_record_p; + environment_record_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_environment_record_t, value); + jmem_heap_free_block (environment_record_p, sizeof (ecma_environment_record_t)); + break; + } + case LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED: + { + ecma_value_t *compact_collection_p; + compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value); + ecma_compact_collection_free (compact_collection_p); + break; + } + case LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS: + { + ecma_value_t *compact_collection_p; + compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value); + + ecma_value_t *end_p = ecma_compact_collection_end (compact_collection_p); + ecma_value_t *current_p = compact_collection_p + 1; + + JERRY_ASSERT ((end_p - current_p) % ECMA_PRIVATE_ELEMENT_LIST_SIZE == 0); + + while (current_p < end_p) + { + current_p++; /* skip the type */ + ecma_deref_ecma_string (ecma_get_prop_name_from_value (*current_p++)); + current_p++; /* skip the value */ + } + + ecma_compact_collection_destroy (compact_collection_p); + break; + } +#if JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER + case LIT_INTERNAL_MAGIC_STRING_WEAK_REFS: + { + ecma_collection_t *refs_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, value); + for (uint32_t j = 0; j < refs_p->item_count; j++) + { + const ecma_value_t reference_value = refs_p->buffer_p[j]; + + if (!ecma_is_value_empty (reference_value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (reference_value); + + if (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_WEAKREF)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + ext_obj_p->u.cls.u3.target = ECMA_VALUE_UNDEFINED; + continue; + } + ecma_op_container_remove_weak_entry (obj_p, ecma_make_object_value (object_p)); + } + } + + ecma_collection_destroy (refs_p); + break; + } +#endif /* JERRY_BUILTIN_CONTAINER */ + default: + { + JERRY_ASSERT (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER + || name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES); + ecma_gc_free_native_pointer (property, value); + break; + } + } +} /* ecma_gc_free_property */ + +/** + * Free properties of an object + */ +void +ecma_gc_free_properties (ecma_object_t *object_p, /**< object */ + uint32_t options) /**< option bits */ +{ + jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + ecma_property_hashmap_free (object_p); + prop_iter_cp = object_p->u1.property_list_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (uint32_t i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + ecma_gc_free_property (object_p, prop_pair_p, i | options); + } + + prop_iter_cp = prop_iter_p->next_property_cp; + + ecma_dealloc_property_pair (prop_pair_p); + } +} /* ecma_gc_free_properties */ + +/** + * Free specified object. + */ +static void +ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_gc_is_object_visited (object_p)); + + JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_objects_number) > 0); + JERRY_CONTEXT (ecma_gc_objects_number)--; + + if (ecma_is_lexical_environment (object_p)) + { +#if JERRY_MODULE_SYSTEM + if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA)) + { + if (ECMA_LEX_ENV_CLASS_IS_MODULE (object_p)) + { + ecma_gc_free_properties (object_p, ECMA_GC_FREE_REFERENCES); + } + + ecma_dealloc_extended_object (object_p, sizeof (ecma_lexical_environment_class_t)); + return; + } +#endif /* JERRY_MODULE_SYSTEM */ + + if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_gc_free_properties (object_p, ECMA_GC_FREE_NO_OPTIONS); + } + + ecma_dealloc_object (object_p); + return; + } + + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + size_t ext_object_size = sizeof (ecma_extended_object_t); + + switch (object_type) + { + case ECMA_OBJECT_TYPE_GENERAL: + { + ecma_gc_free_properties (object_p, ECMA_GC_FREE_NO_OPTIONS); + ecma_dealloc_object (object_p); + return; + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + { + if (((ecma_extended_object_t *) object_p)->u.built_in.id == ECMA_BUILTIN_ID_GLOBAL) + { + ext_object_size = sizeof (ecma_global_object_t); + break; + } + + uint8_t bitset_size = ((ecma_extended_object_t *) object_p)->u.built_in.u.length_and_bitset_size; + ext_object_size += sizeof (uint64_t) * (bitset_size >> ECMA_BUILT_IN_BITSET_SHIFT); + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + { + ext_object_size = sizeof (ecma_extended_built_in_object_t); + uint8_t bitset_size = ((ecma_extended_built_in_object_t *) object_p)->built_in.u.length_and_bitset_size; + ext_object_size += sizeof (uint64_t) * (bitset_size >> ECMA_BUILT_IN_BITSET_SHIFT); + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_STRING: + case ECMA_OBJECT_CLASS_NUMBER: + case ECMA_OBJECT_CLASS_SYMBOL: +#if JERRY_BUILTIN_BIGINT + case ECMA_OBJECT_CLASS_BIGINT: +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_free_value (ext_object_p->u.cls.u3.value); + break; + } + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + ext_object_size = ecma_free_arguments_object (ext_object_p); + break; + } +#if JERRY_BUILTIN_TYPEDARRAY + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + if (ext_object_p->u.cls.u2.typedarray_flags & ECMA_TYPEDARRAY_IS_EXTENDED) + { + ext_object_size = sizeof (ecma_extended_typedarray_object_t); + } + break; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: + { + ecma_gc_free_properties (object_p, ECMA_GC_FREE_REFERENCES); + ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t)); + return; + } +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_PARSER + case ECMA_OBJECT_CLASS_SCRIPT: + { + ecma_compiled_code_t *compiled_code_p; + compiled_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + + ecma_bytecode_deref (compiled_code_p); + break; + } +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_DATE + case ECMA_OBJECT_CLASS_DATE: + { + ext_object_size = sizeof (ecma_date_object_t); + break; + } +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP + case ECMA_OBJECT_CLASS_REGEXP: + { + ecma_compiled_code_t *bytecode_p = + ECMA_GET_INTERNAL_VALUE_ANY_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + + ecma_bytecode_deref (bytecode_p); + + break; + } +#endif /* JERRY_BUILTIN_REGEXP */ + case ECMA_OBJECT_CLASS_STRING_ITERATOR: + { + ecma_value_t iterated_value = ext_object_p->u.cls.u3.iterated_value; + + if (!ecma_is_value_empty (iterated_value)) + { + ecma_deref_ecma_string (ecma_get_string_from_value (iterated_value)); + } + + break; + } +#if JERRY_BUILTIN_REGEXP + case ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR: + { + ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) object_p; + ecma_value_t iterated_string = regexp_string_iterator_obj->iterated_string; + + if (!ecma_is_value_empty (iterated_string)) + { + ecma_deref_ecma_string (ecma_get_string_from_value (iterated_string)); + } + + ext_object_size = sizeof (ecma_regexp_string_iterator_t); + break; + } +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_TYPEDARRAY + case ECMA_OBJECT_CLASS_ARRAY_BUFFER: +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + case ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER: +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + { + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (ext_object_p) & ECMA_ARRAYBUFFER_HAS_POINTER)) + { + ext_object_size += ext_object_p->u.cls.u3.length; + break; + } + + ext_object_size = sizeof (ecma_arraybuffer_pointer_t); + + if (ECMA_ARRAYBUFFER_GET_FLAGS (ext_object_p) & ECMA_ARRAYBUFFER_ALLOCATED) + { + ecma_arraybuffer_release_buffer (object_p); + } + break; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_WEAKREF + case ECMA_OBJECT_CLASS_WEAKREF: + { + ecma_value_t target = ext_object_p->u.cls.u3.target; + + if (!ecma_is_value_undefined (target)) + { + ecma_op_object_unref_weak (ecma_get_object_from_value (target), ecma_make_object_value (object_p)); + } + break; + } +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_CONTAINER + case ECMA_OBJECT_CLASS_CONTAINER: + { + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + ecma_collection_t *container_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + ecma_op_container_free_entries (object_p); + ecma_collection_destroy (container_p); + break; + } +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_DATAVIEW + case ECMA_OBJECT_CLASS_DATAVIEW: + { + ext_object_size = sizeof (ecma_dataview_object_t); + break; + } +#endif /* JERRY_BUILTIN_DATAVIEW */ + case ECMA_OBJECT_CLASS_GENERATOR: + case ECMA_OBJECT_CLASS_ASYNC_GENERATOR: + { + ext_object_size = ecma_gc_free_executable_object (object_p); + break; + } + case ECMA_OBJECT_CLASS_PROMISE: + { + ecma_free_value_if_not_object (ext_object_p->u.cls.u3.value); + + /* Reactions only contains objects. */ + ecma_collection_destroy (((ecma_promise_object_t *) object_p)->reactions); + + ext_object_size = sizeof (ecma_promise_object_t); + break; + } + case ECMA_OBJECT_CLASS_PROMISE_CAPABILITY: + { + ext_object_size = sizeof (ecma_promise_capabality_t); + break; + } + case ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR: + { + ext_object_size = sizeof (ecma_async_from_sync_iterator_object_t); + break; + } +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE: + { + ecma_module_release_module ((ecma_module_t *) ext_object_p); + ext_object_size = sizeof (ecma_module_t); + break; + } +#endif /* JERRY_MODULE_SYSTEM */ + default: + { + /* The ECMA_OBJECT_CLASS__MAX type represents an uninitialized class. */ + JERRY_ASSERT (ext_object_p->u.cls.type <= ECMA_OBJECT_CLASS__MAX); + break; + } + } + + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + ext_object_size = sizeof (ecma_extended_built_in_object_t); + uint8_t bitset_size = ((ecma_extended_built_in_object_t *) object_p)->built_in.u.length_and_bitset_size; + ext_object_size += sizeof (uint64_t) * (bitset_size >> ECMA_BUILT_IN_BITSET_SHIFT); + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_ARRAY: + { + if (ecma_op_array_is_fast_array ((ecma_extended_object_t *) object_p)) + { + ecma_free_fast_access_array (object_p); + return; + } + break; + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + ext_object_size = sizeof (ecma_proxy_object_t); + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_OBJECT_TYPE_FUNCTION: + { + /* Function with byte-code (not a built-in function). */ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + +#if JERRY_SNAPSHOT_EXEC + if (ext_func_p->u.function.bytecode_cp != ECMA_NULL_POINTER) + { +#endif /* JERRY_SNAPSHOT_EXEC */ + ecma_compiled_code_t *byte_code_p = + (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_func_p->u.function.bytecode_cp)); + + if (CBC_FUNCTION_IS_ARROW (byte_code_p->status_flags)) + { + ecma_free_value_if_not_object (((ecma_arrow_function_t *) object_p)->this_binding); + ecma_free_value_if_not_object (((ecma_arrow_function_t *) object_p)->new_target); + ext_object_size = sizeof (ecma_arrow_function_t); + } + + ecma_bytecode_deref (byte_code_p); +#if JERRY_SNAPSHOT_EXEC + } + else + { + ext_object_size = sizeof (ecma_static_function_t); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + ecma_extended_object_t *extended_func_p = (ecma_extended_object_t *) object_p; + + if (!ecma_builtin_function_is_routine (object_p)) + { + uint8_t bitset_size = extended_func_p->u.built_in.u.length_and_bitset_size; + ext_object_size += sizeof (uint64_t) * (bitset_size >> ECMA_BUILT_IN_BITSET_SHIFT); + break; + } + + if (extended_func_p->u.built_in.id != ECMA_BUILTIN_ID_HANDLER) + { + break; + } + + switch (extended_func_p->u.built_in.routine_id) + { + case ECMA_NATIVE_HANDLER_PROMISE_RESOLVE: + case ECMA_NATIVE_HANDLER_PROMISE_REJECT: + { + ext_object_size = sizeof (ecma_promise_resolver_t); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_THEN_FINALLY: + case ECMA_NATIVE_HANDLER_PROMISE_CATCH_FINALLY: + { + ext_object_size = sizeof (ecma_promise_finally_function_t); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_CAPABILITY_EXECUTOR: + { + ext_object_size = sizeof (ecma_promise_capability_executor_t); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER: + { + ext_object_size = sizeof (ecma_promise_all_executor_t); + break; + } +#if JERRY_BUILTIN_PROXY + case ECMA_NATIVE_HANDLER_PROXY_REVOKE: + { + ext_object_size = sizeof (ecma_revocable_proxy_object_t); + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_NATIVE_HANDLER_VALUE_THUNK: + case ECMA_NATIVE_HANDLER_VALUE_THROWER: + { + ecma_free_value_if_not_object (((ecma_promise_value_thunk_t *) object_p)->value); + ext_object_size = sizeof (ecma_promise_value_thunk_t); + break; + } + case ECMA_NATIVE_HANDLER_ASYNC_FROM_SYNC_ITERATOR_UNWRAP: + { + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ext_object_size = sizeof (ecma_bound_function_t); + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + + ecma_free_value (bound_func_p->target_length); + + if (!ecma_is_value_integer_number (args_len_or_this)) + { + ecma_free_value_if_not_object (args_len_or_this); + break; + } + + ecma_integer_value_t args_length = ecma_get_integer_from_value (args_len_or_this); + ecma_value_t *args_p = (ecma_value_t *) (bound_func_p + 1); + + for (ecma_integer_value_t i = 0; i < args_length; i++) + { + ecma_free_value_if_not_object (args_p[i]); + } + + size_t args_size = ((size_t) args_length) * sizeof (ecma_value_t); + ext_object_size += args_size; + break; + } + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + ecma_script_deref (((ecma_extended_object_t *) object_p)->u.constructor_function.script_value); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + ext_object_size = sizeof (ecma_native_function_t); + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + + ecma_gc_free_properties (object_p, ECMA_GC_FREE_NO_OPTIONS); + ecma_dealloc_extended_object (object_p, ext_object_size); +} /* ecma_gc_free_object */ + +/** + * Run garbage collection, freeing objects that are no longer referenced. + */ +void +ecma_gc_run (void) +{ +#if (JERRY_GC_MARK_LIMIT != 0) + JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_mark_recursion_limit) == JERRY_GC_MARK_LIMIT); +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + + JERRY_CONTEXT (ecma_gc_new_objects) = 0; + + ecma_object_t black_list_head; + black_list_head.gc_next_cp = JMEM_CP_NULL; + ecma_object_t *black_end_p = &black_list_head; + + ecma_object_t white_gray_list_head; + white_gray_list_head.gc_next_cp = JERRY_CONTEXT (ecma_gc_objects_cp); + + ecma_object_t *obj_prev_p = &white_gray_list_head; + jmem_cpointer_t obj_iter_cp = obj_prev_p->gc_next_cp; + ecma_object_t *obj_iter_p; + + /* Move root objects (i.e. they have global or stack references) to the black list. */ + while (obj_iter_cp != JMEM_CP_NULL) + { + obj_iter_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_object_t, obj_iter_cp); + const jmem_cpointer_t obj_next_cp = obj_iter_p->gc_next_cp; + + JERRY_ASSERT (obj_prev_p == NULL + || ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_prev_p->gc_next_cp) == obj_iter_p); + + if (obj_iter_p->type_flags_refs >= ECMA_OBJECT_REF_ONE) + { + /* Moving the object to list of marked objects. */ + obj_prev_p->gc_next_cp = obj_next_cp; + + black_end_p->gc_next_cp = obj_iter_cp; + black_end_p = obj_iter_p; + } + else + { + obj_iter_p->type_flags_refs |= ECMA_OBJECT_NON_VISITED; + obj_prev_p = obj_iter_p; + } + + obj_iter_cp = obj_next_cp; + } + + black_end_p->gc_next_cp = JMEM_CP_NULL; + + /* Mark root objects. */ + obj_iter_cp = black_list_head.gc_next_cp; + while (obj_iter_cp != JMEM_CP_NULL) + { + obj_iter_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_object_t, obj_iter_cp); + ecma_gc_mark (obj_iter_p); + obj_iter_cp = obj_iter_p->gc_next_cp; + } + + /* Mark non-root objects. */ + bool marked_anything_during_current_iteration; + + do + { +#if (JERRY_GC_MARK_LIMIT != 0) + JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_mark_recursion_limit) == JERRY_GC_MARK_LIMIT); +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + + marked_anything_during_current_iteration = false; + + obj_prev_p = &white_gray_list_head; + obj_iter_cp = obj_prev_p->gc_next_cp; + + while (obj_iter_cp != JMEM_CP_NULL) + { + obj_iter_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_object_t, obj_iter_cp); + const jmem_cpointer_t obj_next_cp = obj_iter_p->gc_next_cp; + + JERRY_ASSERT (obj_prev_p == NULL + || ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_prev_p->gc_next_cp) == obj_iter_p); + + if (ecma_gc_is_object_visited (obj_iter_p)) + { + /* Moving the object to list of marked objects */ + obj_prev_p->gc_next_cp = obj_next_cp; + + black_end_p->gc_next_cp = obj_iter_cp; + black_end_p = obj_iter_p; + +#if (JERRY_GC_MARK_LIMIT != 0) + if (obj_iter_p->type_flags_refs >= ECMA_OBJECT_REF_ONE) + { + /* Set the reference count of non-marked gray object to 0 */ + obj_iter_p->type_flags_refs &= (ecma_object_descriptor_t) (ECMA_OBJECT_REF_ONE - 1); + ecma_gc_mark (obj_iter_p); + marked_anything_during_current_iteration = true; + } +#else /* (JERRY_GC_MARK_LIMIT == 0) */ + marked_anything_during_current_iteration = true; +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + } + else + { + obj_prev_p = obj_iter_p; + } + + obj_iter_cp = obj_next_cp; + } + } while (marked_anything_during_current_iteration); + + black_end_p->gc_next_cp = JMEM_CP_NULL; + JERRY_CONTEXT (ecma_gc_objects_cp) = black_list_head.gc_next_cp; + + /* Sweep objects that are currently unmarked. */ + obj_iter_cp = white_gray_list_head.gc_next_cp; + + while (obj_iter_cp != JMEM_CP_NULL) + { + obj_iter_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_object_t, obj_iter_cp); + const jmem_cpointer_t obj_next_cp = obj_iter_p->gc_next_cp; + + JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p)); + + ecma_gc_free_object (obj_iter_p); + obj_iter_cp = obj_next_cp; + } + +#if JERRY_BUILTIN_REGEXP + /* Free RegExp bytecodes stored in cache */ + re_cache_gc (); +#endif /* JERRY_BUILTIN_REGEXP */ +} /* ecma_gc_run */ + +/** + * Try to free some memory (depending on memory pressure). + * + * When called with JMEM_PRESSURE_FULL, the engine will be terminated with JERRY_FATAL_OUT_OF_MEMORY. + */ +void +ecma_free_unused_memory (jmem_pressure_t pressure) /**< current pressure */ +{ + if (JERRY_LIKELY (pressure == JMEM_PRESSURE_LOW)) + { +#if JERRY_PROPERTY_HASHMAP + if (JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) > ECMA_PROP_HASHMAP_ALLOC_ON) + { + --JERRY_CONTEXT (ecma_prop_hashmap_alloc_state); + } + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_HIGH_PRESSURE_GC; +#endif /* JERRY_PROPERTY_HASHMAP */ + /* + * If there is enough newly allocated objects since last GC, probably it is worthwhile to start GC now. + * Otherwise, probability to free sufficient space is considered to be low. + */ + size_t new_objects_fraction = CONFIG_ECMA_GC_NEW_OBJECTS_FRACTION; + + if (JERRY_CONTEXT (ecma_gc_new_objects) * new_objects_fraction > JERRY_CONTEXT (ecma_gc_objects_number)) + { + ecma_gc_run (); + } + + return; + } + else if (pressure == JMEM_PRESSURE_HIGH) + { + /* Freeing as much memory as we currently can */ +#if JERRY_PROPERTY_HASHMAP + if (JERRY_CONTEXT (status_flags) & ECMA_STATUS_HIGH_PRESSURE_GC) + { + JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) = ECMA_PROP_HASHMAP_ALLOC_MAX; + } + else if (JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) < ECMA_PROP_HASHMAP_ALLOC_MAX) + { + ++JERRY_CONTEXT (ecma_prop_hashmap_alloc_state); + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_HIGH_PRESSURE_GC; + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + ecma_gc_run (); + +#if JERRY_PROPERTY_HASHMAP + /* Free hashmaps of remaining objects. */ + jmem_cpointer_t obj_iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp); + + while (obj_iter_cp != JMEM_CP_NULL) + { + ecma_object_t *obj_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_iter_cp); + + if (!ecma_is_lexical_environment (obj_iter_p) + || ecma_get_lex_env_type (obj_iter_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + if (!ecma_is_lexical_environment (obj_iter_p) && ecma_op_object_is_fast_array (obj_iter_p)) + { + obj_iter_cp = obj_iter_p->gc_next_cp; + continue; + } + + jmem_cpointer_t prop_iter_cp = obj_iter_p->u1.property_list_cp; + + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + ecma_property_hashmap_free (obj_iter_p); + } + } + } + + obj_iter_cp = obj_iter_p->gc_next_cp; + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + jmem_pools_collect_empty (); + return; + } + else if (JERRY_UNLIKELY (pressure == JMEM_PRESSURE_FULL)) + { + jerry_fatal (JERRY_FATAL_OUT_OF_MEMORY); + } + else + { + JERRY_ASSERT (pressure == JMEM_PRESSURE_NONE); + JERRY_UNREACHABLE (); + } +} /* ecma_free_unused_memory */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.h new file mode 100644 index 00000000..94a6d2a9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.h @@ -0,0 +1,54 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_GC_H +#define ECMA_GC_H + +#include "ecma-globals.h" + +#include "jmem.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmagc Garbage collector + * @{ + */ + +/** + * Free option flags + */ +typedef enum +{ + ECMA_GC_FREE_NO_OPTIONS = 0, /**< no options */ + ECMA_GC_FREE_SECOND_PROPERTY = (1 << 0), /**< free second property of a property pair */ + ECMA_GC_FREE_REFERENCES = (1 << 1), /**< free references */ +} ecma_gc_free_options_t; + +void ecma_init_gc_info (ecma_object_t *object_p); +void ecma_ref_object (ecma_object_t *object_p); +void ecma_ref_object_inline (ecma_object_t *object_p); +void ecma_deref_object (ecma_object_t *object_p); +void ecma_gc_free_property (ecma_object_t *object_p, ecma_property_pair_t *prop_pair_p, uint32_t options); +void ecma_gc_free_properties (ecma_object_t *object_p, uint32_t options); +void ecma_gc_run (void); +void ecma_free_unused_memory (jmem_pressure_t pressure); + +/** + * @} + * @} + */ + +#endif /* !ECMA_GC_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-globals.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-globals.h new file mode 100644 index 00000000..acfea5f3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-globals.h @@ -0,0 +1,2271 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_GLOBALS_H +#define ECMA_GLOBALS_H + +#include "jerry-config.h" +#include "ecma-errors.h" +#include "jmem.h" +#include "jrt.h" +#include "lit-magic-strings.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmatypes ECMA types + * @{ + * + * \addtogroup compressedpointer Compressed pointer + * @{ + */ + +/** + * The NULL value for compressed pointers + */ +#define ECMA_NULL_POINTER JMEM_CP_NULL + +#if defined(JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY) + +/** + * JMEM_ALIGNMENT_LOG aligned pointers can be stored directly in ecma_value_t + */ +#define ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + +#endif /* JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY */ + +/** + * @} + */ + +/** + * JerryScript status flags. + */ +typedef enum +{ + ECMA_STATUS_API_ENABLED = (1u << 0), /**< api available */ + ECMA_STATUS_DIRECT_EVAL = (1u << 1), /**< eval is called directly */ +#if JERRY_PROPERTY_HASHMAP + ECMA_STATUS_HIGH_PRESSURE_GC = (1u << 2), /**< last gc was under high pressure */ +#endif /* JERRY_PROPERTY_HASHMAP */ + ECMA_STATUS_EXCEPTION = (1u << 3), /**< last exception is a normal exception */ + ECMA_STATUS_ABORT = (1u << 4), /**< last exception is an abort */ + ECMA_STATUS_ERROR_UPDATE = (1u << 5), /**< the error_object_created_callback_p is called */ +#if JERRY_VM_THROW + ECMA_STATUS_ERROR_THROWN = (1u << 6), /**< the vm_throw_callback_p is called */ +#endif /* JERRY_VM_THROW */ +} ecma_status_flag_t; + +/** + * Type of ecma value + */ +typedef enum +{ + ECMA_TYPE_DIRECT = 0, /**< directly encoded value, a 28 bit signed integer or a simple value */ + ECMA_TYPE_STRING = 1, /**< pointer to description of a string */ + ECMA_TYPE_FLOAT = 2, /**< pointer to a 64 or 32 bit floating point number */ + ECMA_TYPE_OBJECT = 3, /**< pointer to description of an object */ + ECMA_TYPE_SYMBOL = 4, /**< pointer to description of a symbol */ + ECMA_TYPE_DIRECT_STRING = 5, /**< directly encoded string values */ + ECMA_TYPE_BIGINT = 6, /**< pointer to a bigint primitive */ + ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference (only supported by C API) */ + ECMA_TYPE_SNAPSHOT_OFFSET = ECMA_TYPE_ERROR, /**< offset to a snapshot number/string */ + ECMA_TYPE___MAX = ECMA_TYPE_ERROR /** highest value for ecma types */ +} ecma_type_t; + +/** + * Option flags for parser_parse_script and internal flags for global_status_flags in parser context. + */ +typedef enum +{ + ECMA_PARSE_NO_OPTS = 0, /**< no options passed */ + ECMA_PARSE_STRICT_MODE = (1u << 0), /**< enable strict mode, must be same as PARSER_IS_STRICT */ + ECMA_PARSE_MODULE = (1u << 1), /**< module is parsed */ + ECMA_PARSE_EVAL = (1u << 2), /**< eval is called */ + ECMA_PARSE_DIRECT_EVAL = (1u << 3), /**< eval is called directly (ECMA-262 v5, 15.1.2.1.1) */ + ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 4), /**< a class constructor is being parsed */ + + /* These five status flags must be in this order. The first four are also parser status flags. + * See PARSER_SAVE_STATUS_FLAGS / PARSER_RESTORE_STATUS_FLAGS. */ + ECMA_PARSE_ALLOW_SUPER = (1u << 5), /**< allow super property access */ + ECMA_PARSE_ALLOW_SUPER_CALL = (1u << 6), /**< allow super constructor call */ + ECMA_PARSE_FUNCTION_IS_PARSING_ARGS = (1u << 7), /**< set when parsing function arguments */ + ECMA_PARSE_INSIDE_CLASS_FIELD = (1u << 8), /**< a class field is being parsed */ + ECMA_PARSE_ALLOW_NEW_TARGET = (1u << 9), /**< allow new.target access */ + ECMA_PARSE_FUNCTION_CONTEXT = (1u << 10), /**< function context is present (ECMA_PARSE_DIRECT_EVAL must be set) */ + + ECMA_PARSE_HAS_SOURCE_VALUE = (1u << 11), /**< source_p points to a value list + * and the first value is the source code */ + ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE = (1u << 12), /**< source_p points to a value list + * and the second value is the argument list */ + ECMA_PARSE_GENERATOR_FUNCTION = (1u << 13), /**< generator function is parsed */ + ECMA_PARSE_ASYNC_FUNCTION = (1u << 14), /**< async function is parsed */ + + /* These flags are internally used by the parser. */ + ECMA_PARSE_INTERNAL_FREE_SOURCE = (1u << 15), /**< free source_p data */ + ECMA_PARSE_INTERNAL_FREE_ARG_LIST = (1u << 16), /**< free arg_list_p data */ + ECMA_PARSE_INTERNAL_PRE_SCANNING = (1u << 17), /**< the parser is in pre-scanning mode */ +#if JERRY_MODULE_SYSTEM + ECMA_PARSE_INTERNAL_HAS_IMPORT_META = (1u << 18), /**< module has import.meta expression */ +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_FUNCTION_TO_STRING + ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER = (1u << 19), /**< source has 4 byte marker */ +#endif /* JERRY_FUNCTION_TO_STRING */ +#ifndef JERRY_NDEBUG + /** + * This flag represents an error in for in/of statements, which cannot be set + * if the parsing is completed successfully. + */ + ECMA_PARSE_INTERNAL_FOR_IN_OFF_CONTEXT_ERROR = (1u << 30), +#endif /* !JERRY_NDEBUG */ +} ecma_parse_opts_t; + +/** + * Description of an ecma value + * + * Bit-field structure: type (3) | value (29) + */ +typedef uint32_t ecma_value_t; + +/** + * Type for directly encoded integer numbers in JerryScript. + */ +typedef int32_t ecma_integer_value_t; + +/** + * Mask for ecma types in ecma_value_t + */ +#define ECMA_VALUE_TYPE_MASK 0x7u + +/** + * Shift for value part in ecma_value_t + */ +#define ECMA_VALUE_SHIFT 3 + +/** + * Mask for directly encoded values + */ +#define ECMA_DIRECT_TYPE_MASK ((1u << ECMA_VALUE_SHIFT) | ECMA_VALUE_TYPE_MASK) + +/** + * Ecma integer value type + */ +#define ECMA_DIRECT_TYPE_INTEGER_VALUE ((0u << ECMA_VALUE_SHIFT) | ECMA_TYPE_DIRECT) + +/** + * Ecma simple value type + */ +#define ECMA_DIRECT_TYPE_SIMPLE_VALUE ((1u << ECMA_VALUE_SHIFT) | ECMA_TYPE_DIRECT) + +/** + * Shift for directly encoded values in ecma_value_t + */ +#define ECMA_DIRECT_SHIFT 4 + +/** + * ECMA make simple value + */ +#define ECMA_MAKE_VALUE(value) ((((ecma_value_t) (value)) << ECMA_DIRECT_SHIFT) | ECMA_DIRECT_TYPE_SIMPLE_VALUE) + +/** + * Simple ecma values + */ +enum +{ + /** + * Empty value is implementation defined value, used for representing: + * - empty (uninitialized) values + * - immutable binding values + * - special register or stack values for vm + */ + ECMA_VALUE_EMPTY = ECMA_MAKE_VALUE (0), /**< uninitialized value */ + ECMA_VALUE_ERROR = ECMA_MAKE_VALUE (1), /**< an error is currently thrown */ + ECMA_VALUE_FALSE = ECMA_MAKE_VALUE (2), /**< boolean false */ + ECMA_VALUE_TRUE = ECMA_MAKE_VALUE (3), /**< boolean true */ + ECMA_VALUE_UNDEFINED = ECMA_MAKE_VALUE (4), /**< undefined value */ + ECMA_VALUE_NULL = ECMA_MAKE_VALUE (5), /**< null value */ + ECMA_VALUE_UNINITIALIZED = ECMA_MAKE_VALUE (6), /**< a special value for uninitialized let/const declarations */ + ECMA_VALUE_NOT_FOUND = ECMA_MAKE_VALUE (7), /**< a special value returned by + * ecma_op_object_find */ + /* Values for controlling the VM */ + ECMA_VALUE_ARRAY_HOLE = ECMA_MAKE_VALUE (8), /**< array hole, used for + * initialization of an array literal */ + ECMA_VALUE_REGISTER_REF = ECMA_MAKE_VALUE (9), /**< register reference, + * a special "base" value for vm */ + ECMA_VALUE_RELEASE_LEX_ENV = ECMA_MAKE_VALUE (10), /**< if this error remains on the stack when an exception occurs + the top lexical environment of the VM frame should be popped */ + ECMA_VALUE_SPREAD_ELEMENT = ECMA_MAKE_VALUE (11), /**< a special value for spread elements in array initialization + * or function call argument list */ + /* Other values */ + ECMA_VALUE_ARGUMENT_NO_TRACK = ECMA_MAKE_VALUE (12), /**< represents not-tracked arguments formal parameter */ + ECMA_VALUE_SYNC_ITERATOR = ECMA_MAKE_VALUE (13), /**< option for ecma_op_get_iterator: sync iterator is requested */ + ECMA_VALUE_ASYNC_ITERATOR = ECMA_MAKE_VALUE (14), /**< option for ecma_op_get_iterator: async iterator is requested */ +#if JERRY_BUILTIN_GLOBAL_THIS + ECMA_VALUE_GLOBAL_THIS = ECMA_MAKE_VALUE (15), /**< globalThis built-in */ +#endif /* JERRY_BUILTIN_GLOBAL_THIS */ +}; + +#if !JERRY_NUMBER_TYPE_FLOAT64 +/** + * Maximum integer number for an ecma value + */ +#define ECMA_INTEGER_NUMBER_MAX 0x7fffff +/** + * Maximum integer number for an ecma value (shifted left with ECMA_DIRECT_SHIFT) + */ +#define ECMA_INTEGER_NUMBER_MAX_SHIFTED 0x7fffff0 +#else /* JERRY_NUMBER_TYPE_FLOAT64 */ +/** + * Maximum integer number for an ecma value + */ +#define ECMA_INTEGER_NUMBER_MAX 0x7ffffff +/** + * Maximum integer number for an ecma value (shifted left with ECMA_DIRECT_SHIFT) + */ +#define ECMA_INTEGER_NUMBER_MAX_SHIFTED 0x7ffffff0 +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +#if !JERRY_NUMBER_TYPE_FLOAT64 +/** + * Minimum integer number for an ecma value + */ +#define ECMA_INTEGER_NUMBER_MIN -0x7fffff +/** + * Minimum integer number for an ecma value (shifted left with ECMA_DIRECT_SHIFT) + */ +#define ECMA_INTEGER_NUMBER_MIN_SHIFTED -0x7fffff0 +#else /* JERRY_NUMBER_TYPE_FLOAT64 */ +/** + * Minimum integer number for an ecma value + */ +#define ECMA_INTEGER_NUMBER_MIN -0x8000000 +/** + * Minimum integer number for an ecma value (shifted left with ECMA_DIRECT_SHIFT) + */ +#define ECMA_INTEGER_NUMBER_MIN_SHIFTED (-0x7fffffff - 1) /* -0x80000000 */ +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +#if ECMA_DIRECT_SHIFT != 4 +#error "Please update ECMA_INTEGER_NUMBER_MIN/MAX_SHIFTED according to the new value of ECMA_DIRECT_SHIFT." +#endif /* ECMA_DIRECT_SHIFT != 4 */ + +/** + * Checks whether the integer number is in the integer number range. + */ +#define ECMA_IS_INTEGER_NUMBER(num) (ECMA_INTEGER_NUMBER_MIN <= (num) && (num) <= ECMA_INTEGER_NUMBER_MAX) + +/** + * Maximum integer number, which if squared, still fits in ecma_integer_value_t + */ +#if !JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_INTEGER_MULTIPLY_MAX 0xb50 +#else /* JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_INTEGER_MULTIPLY_MAX 0x2d41 +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Checks whether the error flag is set. + */ +#define ECMA_IS_VALUE_ERROR(value) (JERRY_UNLIKELY ((value) == ECMA_VALUE_ERROR)) + +/** + * Callback which tells whether the ECMAScript execution should be stopped. + */ +typedef ecma_value_t (*ecma_vm_exec_stop_callback_t) (void *user_p); + +/** + * Forward definition of jerry_call_info_t. + */ +struct jerry_call_info_t; + +/** + * Type of an external function handler. + */ +typedef ecma_value_t (*ecma_native_handler_t) (const struct jerry_call_info_t *call_info_p, + const ecma_value_t args_p[], + const uint32_t args_count); + +/** + * Representation of native pointer data. + */ +typedef struct +{ + void *native_p; /**< points to the data of the object */ + jerry_object_native_info_t *native_info_p; /**< native info */ +} ecma_native_pointer_t; + +/** + * Representation of native pointer data chain. + */ +typedef struct ecma_native_pointer_chain_t +{ + ecma_native_pointer_t data; /**< pointer data */ + struct ecma_native_pointer_chain_t *next_p; /**< next in the list */ +} ecma_native_pointer_chain_t; + +/** + * Representation for class constructor environment record. + */ +typedef struct +{ + ecma_value_t this_binding; /**< this binding */ + ecma_value_t function_object; /**< function object */ +} ecma_environment_record_t; + +/** + * Property list: + * The property list of an object is a chain list of various items. + * The type of each item is stored in the first byte of the item. + * + * The most common item is the property pair, which contains two + * ecmascript properties. It is also important, that after the + * first property pair, only property pair items are allowed. + * + * Example for other items is property name hash map, or array of items. + */ + +/** + * Property name listing options. + */ +typedef enum +{ + ECMA_LIST_NO_OPTS = (0), /**< no options are provided */ + ECMA_LIST_ARRAY_INDICES = (1 << 0), /**< exclude properties with names + * that are not indices */ + ECMA_LIST_ENUMERABLE = (1 << 1), /**< exclude non-enumerable properties */ + ECMA_LIST_PROTOTYPE = (1 << 2), /**< list properties from prototype chain */ + ECMA_LIST_SYMBOLS = (1 << 3), /**< list symbol properties */ + ECMA_LIST_SYMBOLS_ONLY = (1 << 4), /**< list symbol properties only */ + ECMA_LIST_CONVERT_FAST_ARRAYS = (1 << 5), /**< after listing the properties convert + * the fast access mode array back to normal array */ +} ecma_list_properties_options_t; + +/** + * Enumerable property name listing options. + */ +typedef enum +{ + ECMA_ENUMERABLE_PROPERTY_KEYS, /**< List only property names */ + ECMA_ENUMERABLE_PROPERTY_VALUES, /**< List only property values */ + ECMA_ENUMERABLE_PROPERTY_ENTRIES, /**< List both propery names and values */ + + ECMA_ENUMERABLE_PROPERTY__COUNT /**< Number of enumerable property listing types */ +} ecma_enumerable_property_names_options_t; + +/** + * List enumerable properties and include the prototype chain. + */ +#define ECMA_LIST_ENUMERABLE_PROTOTYPE (ECMA_LIST_ENUMERABLE | ECMA_LIST_PROTOTYPE) + +/** + * Property flag list. Several flags are alias + */ +typedef enum +{ + ECMA_PROPERTY_FLAG_CONFIGURABLE = (1u << 0), /**< property is configurable */ + ECMA_PROPERTY_FLAG_ENUMERABLE = (1u << 1), /**< property is enumerable */ + ECMA_PROPERTY_FLAG_WRITABLE = (1u << 2), /**< property is writable */ + ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL = (1u << 2), /**< only one external pointer is assigned to this object */ + ECMA_PROPERTY_FLAG_DELETED = (1u << 3), /**< property is deleted */ + ECMA_PROPERTY_FLAG_BUILT_IN = (1u << 3), /**< property is defined by the ECMAScript standard */ + ECMA_FAST_ARRAY_FLAG = (1u << 3), /**< array is fast array */ + ECMA_PROPERTY_FLAG_LCACHED = (1u << 4), /**< property is lcached */ + ECMA_ARRAY_TEMPLATE_LITERAL = (1u << 4), /**< array is a template literal constructed by the parser */ + ECMA_PROPERTY_FLAG_DATA = (1u << 5), /**< property contains data */ + /* The last two bits contains an ECMA_DIRECT_STRING value. */ +} ecma_property_flags_t; + +/** + * Property flags configurable, enumerable, writable. + */ +#define ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE \ + (ECMA_PROPERTY_FLAG_CONFIGURABLE | ECMA_PROPERTY_FLAG_ENUMERABLE | ECMA_PROPERTY_FLAG_WRITABLE) + +/** + * Property flags configurable, enumerable. + */ +#define ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE (ECMA_PROPERTY_FLAG_CONFIGURABLE | ECMA_PROPERTY_FLAG_ENUMERABLE) + +/** + * Property flags configurable, enumerable. + */ +#define ECMA_PROPERTY_CONFIGURABLE_WRITABLE (ECMA_PROPERTY_FLAG_CONFIGURABLE | ECMA_PROPERTY_FLAG_WRITABLE) + +/** + * Property flag built-in. + */ +#define ECMA_PROPERTY_BUILT_IN_FIXED (ECMA_PROPERTY_FLAG_BUILT_IN) + +/** + * Property flags enumerable, writable. + */ +#define ECMA_PROPERTY_ENUMERABLE_WRITABLE (ECMA_PROPERTY_FLAG_ENUMERABLE | ECMA_PROPERTY_FLAG_WRITABLE) + +/** + * Property flags built-in, configurable. + */ +#define ECMA_PROPERTY_BUILT_IN_CONFIGURABLE (ECMA_PROPERTY_FLAG_BUILT_IN | ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/** + * Property flags built-in, configurable, enumerable. + */ +#define ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE \ + (ECMA_PROPERTY_FLAG_BUILT_IN | ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE) + +/** + * Property flags built-in, configurable, writable. + */ +#define ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE (ECMA_PROPERTY_FLAG_BUILT_IN | ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/** + * Property flags built-in, writable. + */ +#define ECMA_PROPERTY_BUILT_IN_WRITABLE (ECMA_PROPERTY_FLAG_BUILT_IN | ECMA_PROPERTY_FLAG_WRITABLE) + +/** + * Property flags built-in, configurable, enumerable, writable. + */ +#define ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE_WRITABLE \ + (ECMA_PROPERTY_FLAG_BUILT_IN | ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +/** + * No attributes can be changed for this property. + */ +#define ECMA_PROPERTY_FIXED 0 + +/** + * Default flag of length property. + */ +#define ECMA_PROPERTY_FLAG_DEFAULT_LENGTH ECMA_PROPERTY_FLAG_CONFIGURABLE + +/** + * Shift for property name part. + */ +#define ECMA_PROPERTY_NAME_TYPE_SHIFT 6 + +/** + * Type of hash-map property. + */ +#define ECMA_PROPERTY_TYPE_HASHMAP (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT) + +/** + * Type of deleted property. + */ +#define ECMA_PROPERTY_TYPE_DELETED \ + (ECMA_PROPERTY_FLAG_DELETED | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) + +/** + * Type of property not found. + */ +#define ECMA_PROPERTY_TYPE_NOT_FOUND ECMA_PROPERTY_TYPE_HASHMAP + +/** + * Type of property not found and no more searching in the proto chain. + */ +#define ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP ECMA_PROPERTY_TYPE_DELETED + +/** + * Type of property not found and an exception is thrown. + */ +#define ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW \ + (ECMA_PROPERTY_FLAG_LCACHED | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) + +/** + * Checks whether a property is not found. + */ +#define ECMA_PROPERTY_IS_FOUND(property) \ + (((property) & (ECMA_PROPERTY_FLAG_DATA | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT))) \ + != (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) + +/** + * Abstract property representation. + * + * A property is a type_and_flags byte and an ecma_value_t value pair. + * This pair is represented by a single pointer in JerryScript. Although + * a packed struct would only consume sizeof(ecma_value_t)+1 memory + * bytes, accessing such structure is inefficient from the CPU viewpoint + * because the value is not naturally aligned. To improve performance, + * two type bytes and values are packed together. The memory layout is + * the following: + * + * [type 1, type 2, unused byte 1, unused byte 2][value 1][value 2] + * + * The unused two bytes are used to store a compressed pointer for the + * next property pair. + * + * The advantage of this layout is that the value reference can be computed + * from the property address. However, property pointers cannot be compressed + * anymore. + */ +typedef uint8_t ecma_property_t; /**< ecma_property_types_t (3 bit) and ecma_property_flags_t */ + +/** + * Number of items in a property pair. + */ +#define ECMA_PROPERTY_PAIR_ITEM_COUNT 2 + +/** + * Property header for all items in a property list. + */ +typedef struct +{ +#if JERRY_CPOINTER_32_BIT + jmem_cpointer_t next_property_cp; /**< next cpointer */ +#endif /* JERRY_CPOINTER_32_BIT */ + ecma_property_t types[ECMA_PROPERTY_PAIR_ITEM_COUNT]; /**< two property type slot. The first represent + * the type of this property (e.g. property pair) */ +#if JERRY_CPOINTER_32_BIT + uint16_t padding; /**< an unused value */ +#else /* !JERRY_CPOINTER_32_BIT */ + jmem_cpointer_t next_property_cp; /**< next cpointer */ +#endif /* JERRY_CPOINTER_32_BIT */ +} ecma_property_header_t; + +/** + * Pair of pointers - to property's getter and setter + */ +typedef struct +{ + jmem_cpointer_t getter_cp; /**< compressed pointer to getter object */ + jmem_cpointer_t setter_cp; /**< compressed pointer to setter object */ +} ecma_getter_setter_pointers_t; + +/** + * Property data. + */ +typedef union +{ + ecma_value_t value; /**< value of a property */ +#if JERRY_CPOINTER_32_BIT + jmem_cpointer_t getter_setter_pair_cp; /**< cpointer to getter setter pair */ +#else /* !JERRY_CPOINTER_32_BIT */ + ecma_getter_setter_pointers_t getter_setter_pair; /**< getter setter pair */ +#endif /* JERRY_CPOINTER_32_BIT */ +} ecma_property_value_t; + +/** + * Property pair. + */ +typedef struct +{ + ecma_property_header_t header; /**< header of the property */ + ecma_property_value_t values[ECMA_PROPERTY_PAIR_ITEM_COUNT]; /**< property value slots */ + jmem_cpointer_t names_cp[ECMA_PROPERTY_PAIR_ITEM_COUNT]; /**< property name slots */ +} ecma_property_pair_t; + +/** + * Get property name type. + */ +#define ECMA_PROPERTY_GET_NAME_TYPE(property) ((property) >> ECMA_PROPERTY_NAME_TYPE_SHIFT) + +/** + * Returns true if the property pointer is a property pair. + */ +#define ECMA_PROPERTY_IS_PROPERTY_PAIR(property_header_p) ((property_header_p)->types[0] != ECMA_PROPERTY_TYPE_HASHMAP) + +/** + * Property value of all internal properties + */ +#define ECMA_PROPERTY_INTERNAL (ECMA_PROPERTY_FLAG_DATA | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) + +/** + * Checks whether a property is internal property + */ +#define ECMA_PROPERTY_IS_INTERNAL(property) ((property) >= ECMA_PROPERTY_INTERNAL) + +/** + * Checks whether a property is raw data or accessor property + */ +#define ECMA_PROPERTY_IS_RAW(property) ((property) < (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) + +/** + * Checks whether a property is raw data property (should only be used in assertions) + */ +#define ECMA_PROPERTY_IS_RAW_DATA(property) \ + (((property) &ECMA_PROPERTY_FLAG_DATA) && (property) < ECMA_PROPERTY_INTERNAL) + +/** + * Create internal property. + */ +#define ECMA_CREATE_INTERNAL_PROPERTY(object_p, name_p, property_p, property_value_p) \ + do \ + { \ + (property_value_p) = ecma_create_named_data_property ((object_p), (name_p), 0, &(property_p)); \ + JERRY_ASSERT (*(property_p) == ECMA_PROPERTY_INTERNAL); \ + } while (0) + +/** + * Property type of all virtual properties + */ +#define ECMA_PROPERTY_VIRTUAL ECMA_PROPERTY_INTERNAL + +/** + * Checks whether a property is virtual property + */ +#define ECMA_PROPERTY_IS_VIRTUAL(property) ECMA_PROPERTY_IS_INTERNAL (property) + +/** + * Returns true if the property is named property. + */ +#define ECMA_PROPERTY_IS_NAMED_PROPERTY(property) \ + ((property) < ECMA_PROPERTY_TYPE_HASHMAP || (property) >= ECMA_PROPERTY_INTERNAL) + +/** + * Add the offset part to a property for computing its property data pointer. + */ +#define ECMA_PROPERTY_VALUE_ADD_OFFSET(property_p) \ + ((uintptr_t) ((((uint8_t *) (property_p)) + (sizeof (ecma_property_value_t) * 2 - 1)))) + +/** + * Align the property for computing its property data pointer. + */ +#define ECMA_PROPERTY_VALUE_DATA_PTR(property_p) \ + (ECMA_PROPERTY_VALUE_ADD_OFFSET (property_p) & ~(sizeof (ecma_property_value_t) - 1)) + +/** + * Compute the property data pointer of a property. + * The property must be part of a property pair. + */ +#define ECMA_PROPERTY_VALUE_PTR(property_p) ((ecma_property_value_t *) ECMA_PROPERTY_VALUE_DATA_PTR (property_p)) + +/** + * Property reference. It contains the value pointer + * for real, and the value itself for virtual properties. + */ +typedef union +{ + ecma_property_value_t *value_p; /**< property value pointer for real properties */ + ecma_value_t virtual_value; /**< property value for virtual properties */ +} ecma_property_ref_t; + +/** + * Extended property reference, which also contains the + * property descriptor pointer for real properties. + */ +typedef struct +{ + ecma_property_ref_t property_ref; /**< property reference */ + ecma_property_t *property_p; /**< property descriptor pointer for real properties */ +} ecma_extended_property_ref_t; + +/** + * Option flags for ecma_op_object_get_property. + */ +typedef enum +{ + ECMA_PROPERTY_GET_NO_OPTIONS = 0, /**< no option flags for ecma_op_object_get_property */ + ECMA_PROPERTY_GET_VALUE = 1u << 0, /**< fill virtual_value field for virtual properties */ + ECMA_PROPERTY_GET_EXT_REFERENCE = 1u << 1, /**< get extended reference to the property */ +} ecma_property_get_option_bits_t; + +/** + * Internal object types. + */ +typedef enum +{ + ECMA_OBJECT_TYPE_GENERAL = 0, /**< all objects that are not belongs to the sub-types below */ + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL = 1, /**< built-in general object */ + ECMA_OBJECT_TYPE_CLASS = 2, /**< Objects with class property */ + ECMA_OBJECT_TYPE_BUILT_IN_CLASS = 3, /**< built-in object with class property */ + ECMA_OBJECT_TYPE_ARRAY = 4, /**< Array object (15.4) */ + ECMA_OBJECT_TYPE_BUILT_IN_ARRAY = 5, /**< Built-in array object */ + ECMA_OBJECT_TYPE_PROXY = 6, /**< Proxy object ECMAScript v6 26.2 */ + /* Note: these 4 types must be in this order. See IsCallable operation. */ + ECMA_OBJECT_TYPE_FUNCTION = 7, /**< Function objects (15.3), created through 13.2 routine */ + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION = 8, /**< Native built-in function object */ + ECMA_OBJECT_TYPE_BOUND_FUNCTION = 9, /**< Function objects (15.3), created through 15.3.4.5 routine */ + ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION = 10, /**< implicit class constructor function */ + ECMA_OBJECT_TYPE_NATIVE_FUNCTION = 11, /**< Native function object */ + + ECMA_OBJECT_TYPE__MAX /**< maximum value */ +} ecma_object_type_t; + +/** + * Base object types without built-in flag. + * + * Note: + * only these types can be checked with ecma_get_object_base_type. + */ +typedef enum +{ + ECMA_OBJECT_BASE_TYPE_GENERAL = ECMA_OBJECT_TYPE_GENERAL, /**< generic objects */ + ECMA_OBJECT_BASE_TYPE_CLASS = ECMA_OBJECT_TYPE_CLASS, /**< Objects with class property */ + ECMA_OBJECT_BASE_TYPE_ARRAY = ECMA_OBJECT_TYPE_ARRAY, /**< Array object (15.4) */ +} ecma_object_base_type_t; + +/** + * Types of objects with class property. + * + * Note: + * when this type is changed, both ecma_class_object_magic_string_id + * and jerry_class_object_type must be updated as well + */ +typedef enum +{ + /* These objects require custom property resolving. */ + ECMA_OBJECT_CLASS_STRING, /**< String Object (ECMAScript v5.1, 4.3.18) */ + ECMA_OBJECT_CLASS_ARGUMENTS, /**< Arguments object (10.6) */ +#if JERRY_BUILTIN_TYPEDARRAY + ECMA_OBJECT_CLASS_TYPEDARRAY, /**< TypedArray which does NOT need extra space to store length and offset */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + ECMA_OBJECT_CLASS_MODULE_NAMESPACE, /**< Module Namespace (ECMAScript v11, 9.4.6) */ +#endif /* JERRY_MODULE_SYSTEM */ + + /* These objects are marked by Garbage Collector. */ + ECMA_OBJECT_CLASS_GENERATOR, /**< Generator object (ECMAScript v6, 25.2) */ + ECMA_OBJECT_CLASS_ASYNC_GENERATOR, /**< Async generator object (ECMAScript v11, 25.3) */ + ECMA_OBJECT_CLASS_ARRAY_ITERATOR, /**< Array iterator object (ECMAScript v6, 22.1.5.1) */ + ECMA_OBJECT_CLASS_SET_ITERATOR, /**< Set iterator object (ECMAScript v6, 23.2.5.1) */ + ECMA_OBJECT_CLASS_MAP_ITERATOR, /**< Map iterator object (ECMAScript v6, 23.1.5.1) */ +#if JERRY_BUILTIN_REGEXP + ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR, /** RegExp string iterator object (ECMAScript v11, 21.2.7) */ +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_MODULE_SYSTEM + ECMA_OBJECT_CLASS_MODULE, /**< Module (ECMAScript v6, 15.2) */ +#endif /* JERRY_MODULE_SYSTEM */ + ECMA_OBJECT_CLASS_PROMISE, /**< Promise (ECMAScript v6, 25.4) */ + ECMA_OBJECT_CLASS_PROMISE_CAPABILITY, /**< Promise capability (ECMAScript v6, 25.4.1.1) */ + ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR, /**< AsyncFromSyncIterator (ECMAScript v11, 25.1.4) */ +#if JERRY_BUILTIN_DATAVIEW + ECMA_OBJECT_CLASS_DATAVIEW, /**< DataView (ECMAScript v6, 24.2) */ +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_CONTAINER + ECMA_OBJECT_CLASS_CONTAINER, /**< Container (Map, WeakMap, Set, WeakSet) */ +#endif /* JERRY_BUILTIN_CONTAINER */ + + /* Normal objects. */ + ECMA_OBJECT_CLASS_BOOLEAN, /**< Boolean Object (ECMAScript v5.1, 4.3.15) */ + ECMA_OBJECT_CLASS_NUMBER, /**< Number Object (ECMAScript v5.1, 4.3.21) */ + ECMA_OBJECT_CLASS_ERROR, /**< Error Object (ECMAScript v5.1, 15.11) */ + ECMA_OBJECT_CLASS_INTERNAL_OBJECT, /**< object for internal properties */ +#if JERRY_PARSER + ECMA_OBJECT_CLASS_SCRIPT, /**< Compiled ECMAScript byte code */ +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_DATE + ECMA_OBJECT_CLASS_DATE, /**< Date Object (ECMAScript v5.1, 15.9) */ +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP + ECMA_OBJECT_CLASS_REGEXP, /**< RegExp Object (ECMAScript v5.1, 15.10) */ +#endif /* JERRY_BUILTIN_REGEXP */ + ECMA_OBJECT_CLASS_SYMBOL, /**< Symbol object (ECMAScript v6, 4.3.27) */ + ECMA_OBJECT_CLASS_STRING_ITERATOR, /**< String iterator object (ECMAScript v6, 22.1.5.1) */ +#if JERRY_BUILTIN_TYPEDARRAY + ECMA_OBJECT_CLASS_ARRAY_BUFFER, /**< Array Buffer (ECMAScript v6, 24.1) */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, /**< Shared Array Buffer (ECMAScript v11 24.2) */ +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#if JERRY_BUILTIN_BIGINT + ECMA_OBJECT_CLASS_BIGINT, /**< Bigint (ECMAScript v11, 4.3.27) */ +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_WEAKREF + ECMA_OBJECT_CLASS_WEAKREF, /**< WeakRef (Not standardized yet) */ +#endif /* JERRY_BUILTIN_WEAKREF */ + + ECMA_OBJECT_CLASS__MAX /**< maximum value */ +} ecma_object_class_type_t; + +/** + * Types of lexical environments. + */ +typedef enum +{ + /* Types between 0 - 12 are ecma_object_type_t. */ + ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE = 13, /**< declarative lexical environment */ + ECMA_LEXICAL_ENVIRONMENT_CLASS = 14, /**< lexical environment with class */ + ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND = 15, /**< object-bound lexical environment */ + + ECMA_LEXICAL_ENVIRONMENT_TYPE_START = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE, /**< first lexical + * environment type */ + ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX = ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND /**< maximum value */ +} ecma_lexical_environment_type_t; + +/** + * Types of array iterators. + */ +typedef enum +{ + ECMA_ITERATOR_KEYS, /**< keys iterator */ + ECMA_ITERATOR_VALUES, /**< values iterator */ + ECMA_ITERATOR_ENTRIES, /**< entries iterator */ + ECMA_ITERATOR__COUNT, /**< number of iterator kinds */ +} ecma_iterator_kind_t; + +/** + * Offset for JERRY_CONTEXT (status_flags) top 8 bits. + */ +#define ECMA_LOCAL_PARSE_OPTS_OFFSET ((sizeof (uint32_t) - sizeof (uint8_t)) * JERRY_BITSINBYTE) + +/** + * Set JERRY_CONTEXT (status_flags) top 8 bits to the specified 'opts'. + */ +#define ECMA_SET_LOCAL_PARSE_OPTS(opts) \ + do \ + { \ + JERRY_CONTEXT (status_flags) |= ((uint32_t) opts << ECMA_LOCAL_PARSE_OPTS_OFFSET) | ECMA_STATUS_DIRECT_EVAL; \ + } while (0) + +/** + * Get JERRY_CONTEXT (status_flags) top 8 bits. + */ +#define ECMA_GET_LOCAL_PARSE_OPTS() \ + (JERRY_CONTEXT (status_flags) >> (ECMA_LOCAL_PARSE_OPTS_OFFSET - JERRY_LOG2 (ECMA_PARSE_ALLOW_SUPER))) + +/** + * Clear JERRY_CONTEXT (status_flags) top 8 bits. + */ +#define ECMA_CLEAR_LOCAL_PARSE_OPTS() \ + do \ + { \ + JERRY_CONTEXT (status_flags) &= ((1 << ECMA_LOCAL_PARSE_OPTS_OFFSET) - 1); \ + } while (0) + +/** + * Ecma object type mask for getting the object type. + */ +#define ECMA_OBJECT_TYPE_MASK 0x00fu + +/** + * Extensible object. + */ +#define ECMA_OBJECT_FLAG_EXTENSIBLE 0x10 + +/** + * Declarative lexical environments created for non-closure code blocks + */ +#define ECMA_OBJECT_FLAG_BLOCK ECMA_OBJECT_FLAG_EXTENSIBLE + +/** + * Lexical environments with class has extra data + */ +#define ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA ECMA_OBJECT_FLAG_EXTENSIBLE + +/** + * Bitshift index for an ecma-object reference count field + */ +#define ECMA_OBJECT_REF_SHIFT 5 + +/** + * Value for increasing or decreasing the object reference counter. + */ +#define ECMA_OBJECT_REF_ONE (1u << ECMA_OBJECT_REF_SHIFT) + +#if JERRY_CPOINTER_32_BIT + +/** + * Type of the descriptor field of an object + */ +typedef uint32_t ecma_object_descriptor_t; + +#else /* !JERRY_CPOINTER_32_BIT */ + +/** + * Type of the descriptor field of an object + */ +typedef uint16_t ecma_object_descriptor_t; + +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Bitmask for an ecma-object reference count field + */ +#define ECMA_OBJECT_REF_MASK ((ecma_object_descriptor_t) (~0u << ECMA_OBJECT_REF_SHIFT)) + +/** + * Represents non-visited white object + */ +#define ECMA_OBJECT_NON_VISITED ECMA_OBJECT_REF_MASK + +/** + * Maximum value of the object reference counter (1022 / 67108862). + */ +#define ECMA_OBJECT_MAX_REF (ECMA_OBJECT_NON_VISITED - ECMA_OBJECT_REF_ONE) + +/** + * Description of ECMA-object or lexical environment + * (depending on is_lexical_environment). + */ +typedef struct +{ + /** type : 4 bit : ecma_object_type_t or ecma_lexical_environment_type_t + depending on ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV + flags : 2 bit : ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV, + ECMA_OBJECT_FLAG_EXTENSIBLE or ECMA_OBJECT_FLAG_BLOCK + refs : 10 / 26 bit (max 1022 / 67108862) */ + ecma_object_descriptor_t type_flags_refs; + + /** next in the object chain maintained by the garbage collector */ + jmem_cpointer_t gc_next_cp; + + /** compressed pointer to property list or bound object */ + union + { + jmem_cpointer_t property_list_cp; /**< compressed pointer to object's + * or declerative lexical environments's property list */ + jmem_cpointer_t bound_object_cp; /**< compressed pointer to lexical environments's the bound object */ + jmem_cpointer_t home_object_cp; /**< compressed pointer to lexical environments's the home object */ + } u1; + + /** object prototype or outer reference */ + union + { + jmem_cpointer_t prototype_cp; /**< compressed pointer to the object's prototype */ + jmem_cpointer_t outer_reference_cp; /**< compressed pointer to the lexical environments's outer reference */ + } u2; +} ecma_object_t; + +/** + * Description of built-in properties of an object. + */ +typedef struct +{ + uint8_t id; /**< built-in id */ + uint8_t routine_id; /**< routine id for built-in functions */ + /** built-in specific field */ + union + { + uint8_t length_and_bitset_size; /**< length and bit set size for generic built-ins */ + uint8_t routine_index; /**< property descriptor index for built-in routines */ + } u; + /** extra built-in info */ + union + { + uint8_t instantiated_bitset[1]; /**< instantiated property bit set for generic built-ins */ + uint8_t routine_flags; /**< flags for built-in routines */ + } u2; + +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value; /**< realm value */ +#else /* !JERRY_BUILTIN_REALMS */ + uint32_t continue_instantiated_bitset[1]; /**< bit set for instantiated properties */ +#endif /* JERRY_BUILTIN_REALMS */ +} ecma_built_in_props_t; + +/** + * Type of a built-in function handler. + */ +typedef ecma_value_t (*ecma_builtin_handler_t) (ecma_object_t *function_obj_p, + const ecma_value_t args_p[], + const uint32_t args_count); + +#if JERRY_BUILTIN_REALMS + +/** + * Number of bits available in the instantiated bitset without allocation + */ +#define ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE (8) + +#else /* !JERRY_BUILTIN_REALMS */ + +/** + * Number of bits available in the instantiated bitset without allocation + */ +#define ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE (8 + 32) + +#endif /* JERRY_BUILTIN_REALMS */ + +/** + * Builtin routine function object status flags + */ +typedef enum +{ + ECMA_BUILTIN_ROUTINE_NO_OPTS = 0, /**< No options are provided */ + ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED = (1u << 0), /**< 'length' property has been initialized */ + ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED = (1u << 1), /**< 'name' property has been initialized */ + ECMA_BUILTIN_ROUTINE_GETTER = (1u << 2), /**< this routine is getter */ + ECMA_BUILTIN_ROUTINE_SETTER = (1u << 3), /**< this routine is setter */ +} ecma_builtin_routine_flags_t; + +/** + * Start position of bit set size in length_and_bitset_size field. + */ +#define ECMA_BUILT_IN_BITSET_SHIFT 5 + +/** + * Description of extended ECMA-object. + * + * The extended object is an object with extra fields. + */ +typedef struct +{ + ecma_object_t object; /**< object header */ + + /** + * Description of extra fields. These extra fields depend on the object type. + */ + union + { + ecma_built_in_props_t built_in; /**< built-in object part */ + + /** + * Description of objects with class. + * + * Note: + * class is a reserved word in c++, so cls is used instead + */ + struct + { + uint8_t type; /**< class type of the object */ + /** + * Description of 8 bit extra fields. These extra fields depend on the type. + */ + union + { + uint8_t arguments_flags; /**< arguments object flags */ + uint8_t error_type; /**< jerry_error_t type of native error objects */ +#if JERRY_BUILTIN_DATE + uint8_t date_flags; /**< flags for date objects */ +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_MODULE_SYSTEM + uint8_t module_state; /**< Module state */ +#endif /* JERRY_MODULE_SYSTEM */ + uint8_t iterator_kind; /**< type of iterator */ + uint8_t regexp_string_iterator_flags; /**< flags for RegExp string iterator */ + uint8_t promise_flags; /**< Promise object flags */ +#if JERRY_BUILTIN_CONTAINER + uint8_t container_flags; /**< container object flags */ +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_TYPEDARRAY + uint8_t array_buffer_flags; /**< ArrayBuffer flags */ + uint8_t typedarray_type; /**< type of typed array */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + } u1; + /** + * Description of 16 bit extra fields. These extra fields depend on the type. + */ + union + { + uint16_t formal_params_number; /**< for arguments: formal parameters number */ +#if JERRY_MODULE_SYSTEM + uint16_t module_flags; /**< Module flags */ +#endif /* JERRY_MODULE_SYSTEM */ + uint16_t iterator_index; /**< for %Iterator%: [[%Iterator%NextIndex]] property */ + uint16_t executable_obj_flags; /**< executable object flags */ +#if JERRY_BUILTIN_CONTAINER + uint16_t container_id; /**< magic string id of a container */ +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_TYPEDARRAY + uint16_t typedarray_flags; /**< typed array object flags */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + } u2; + /** + * Description of 32 bit / value. These extra fields depend on the type. + */ + union + { + ecma_value_t value; /**< value of the object (e.g. boolean, number, string, etc.) */ + ecma_value_t target; /**< [[ProxyTarget]] or [[WeakRefTarget]] internal property */ +#if JERRY_BUILTIN_TYPEDARRAY + ecma_value_t arraybuffer; /**< for typedarray: ArrayBuffer reference */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + ecma_value_t head; /**< points to the async generator task queue head item */ + ecma_value_t iterated_value; /**< for %Iterator%: [[IteratedObject]] property */ + ecma_value_t promise; /**< PromiseCapability[[Promise]] internal slot */ + ecma_value_t sync_iterator; /**< IteratorRecord [[Iterator]] internal slot for AsyncFromSyncIterator */ + ecma_value_t spread_value; /**< for spread object: spreaded element */ + int32_t tza; /**< TimeZone adjustment for date objects */ + uint32_t length; /**< length related property (e.g. length of ArrayBuffer) */ + uint32_t arguments_number; /**< for arguments: arguments number */ +#if JERRY_MODULE_SYSTEM + uint32_t dfs_ancestor_index; /**< module dfs ancestor index (ES2020 15.2.1.16) */ +#endif /* JERRY_MODULE_SYSTEM */ + } u3; + } cls; + + /** + * Description of function objects. + */ + struct + { + jmem_cpointer_tag_t scope_cp; /**< function scope */ + ecma_value_t bytecode_cp; /**< function byte code */ + } function; + + /** + * Description of array objects. + */ + struct + { + uint32_t length; /**< length property value */ + uint32_t length_prop_and_hole_count; /**< length property attributes and number of array holes in + * a fast access mode array multiplied ECMA_FAST_ACCESS_HOLE_ONE */ + } array; + + /** + * Description of bound function object. + */ + struct + { + jmem_cpointer_tag_t target_function; /**< target function */ + ecma_value_t args_len_or_this; /**< length of arguments or this value */ + } bound_function; + + /** + * Description of implicit class constructor function. + */ + struct + { + ecma_value_t script_value; /**< script value */ + uint8_t flags; /**< constructor flags */ + } constructor_function; + } u; +} ecma_extended_object_t; + +/** + * Description of built-in extended ECMA-object. + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + ecma_built_in_props_t built_in; /**< built-in object part */ +} ecma_extended_built_in_object_t; + +/** + * Type of lexical environment with class + */ +typedef enum +{ + ECMA_LEX_ENV_CLASS_TYPE_MODULE, /**< module object reference */ + ECMA_LEX_ENV_CLASS_TYPE_CLASS_ENV, /**< class constructor object reference */ +} ecma_lexical_environment_class_type_t; + +/** + * Description of lexical environment with class + */ +typedef struct +{ + ecma_object_t lexical_env; /**< lexical environment header */ + uint32_t type; /**< element of ecma_lexical_environment_class_type_t */ + ecma_object_t *object_p; /**< object reference */ +} ecma_lexical_environment_class_t; + +/** + * Check whether the given lexical class environment is a module + */ +#define ECMA_LEX_ENV_CLASS_IS_MODULE(lex_env_p) \ + (((lex_env_p)->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) \ + && ((ecma_lexical_environment_class_t *) (lex_env_p))->type == ECMA_LEX_ENV_CLASS_TYPE_MODULE) + +/** + * Description of native functions + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value; /**< realm value */ +#endif /* JERRY_BUILTIN_REALMS */ + ecma_native_handler_t native_handler_cb; /**< external function */ +} ecma_native_function_t; + +/** + * Alignment for the fast access mode array length. + * The real length is aligned up for allocating the underlying buffer. + */ +#define ECMA_FAST_ARRAY_ALIGNMENT (8) + +/** + * Align the length of the fast mode array to get the allocated size of the underlying buffer + */ +#define ECMA_FAST_ARRAY_ALIGN_LENGTH(length) \ + (uint32_t) ((((length)) + ECMA_FAST_ARRAY_ALIGNMENT - 1) / ECMA_FAST_ARRAY_ALIGNMENT * ECMA_FAST_ARRAY_ALIGNMENT) + +/** + * Compiled byte code data. + */ +typedef struct +{ + uint16_t size; /**< real size >> JMEM_ALIGNMENT_LOG */ + uint16_t refs; /**< reference counter for the byte code */ + uint16_t status_flags; /**< various status flags: + * CBC_IS_FUNCTION check tells whether the byte code + * is function or regular expression. + * If function, the other flags must be CBC_CODE_FLAGS... + * If regexp, the other flags must be RE_FLAG... */ +} ecma_compiled_code_t; + +/** + * Description of bound function objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object header */ + ecma_value_t target_length; /**< length of target function */ +} ecma_bound_function_t; + +#if JERRY_SNAPSHOT_EXEC + +/** + * Description of static function objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< header part */ + const ecma_compiled_code_t *bytecode_p; /**< real byte code pointer */ +} ecma_static_function_t; + +#endif /* JERRY_SNAPSHOT_EXEC */ + +/** + * Description of arrow function objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object header */ + ecma_value_t this_binding; /**< value of 'this' binding */ + ecma_value_t new_target; /**< value of new.target */ +} ecma_arrow_function_t; + +#if JERRY_SNAPSHOT_EXEC + +/** + * Description of static arrow function objects. + */ +typedef struct +{ + ecma_arrow_function_t header; + const ecma_compiled_code_t *bytecode_p; +} ecma_static_arrow_function_t; + +#endif /* JERRY_SNAPSHOT_EXEC */ + +#if JERRY_BUILTIN_CONTAINER +/** + * Flags for container objects + */ +typedef enum +{ + ECMA_CONTAINER_FLAGS_EMPTY = (0), /** empty flags */ + ECMA_CONTAINER_FLAGS_WEAK = (1 << 0) /** container object is weak */ +} ecma_container_flags_t; + +/** + * Description of map collection. + */ +typedef struct +{ + ecma_value_t key; /**< key value */ + ecma_value_t value; /**< value of the key */ +} ecma_container_pair_t; + +/** + * Size of a single element (in ecma_value_t unit). + */ +#define ECMA_CONTAINER_VALUE_SIZE 1 + +/** + * Size of a key - value pair (in ecma_value_t unit). + */ +#define ECMA_CONTAINER_PAIR_SIZE 2 + +/** + * Size of the internal buffer. + */ +#define ECMA_CONTAINER_GET_SIZE(container_p) (container_p->buffer_p[0]) + +/** + * Remove the size field of the internal buffer. + */ +#define ECMA_CONTAINER_SET_SIZE(container_p, size) (container_p->buffer_p[0] = (ecma_value_t) (size)) + +/** + * Number of entries of the internal buffer. + */ +#define ECMA_CONTAINER_ENTRY_COUNT(collection_p) (collection_p->item_count - 1) + +/** + * Pointer to the first entry of the internal buffer. + */ +#define ECMA_CONTAINER_START(collection_p) (collection_p->buffer_p + 1) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +/** + * Description of ECMA property descriptor + * + * See also: ECMA-262 v5, 8.10. + * + * Note: + * If a component of descriptor is undefined then corresponding + * field should contain it's default value. + */ +typedef struct +{ + uint16_t flags; /**< any combination of jerry_property_descriptor_flags_t bits */ + ecma_value_t value; /**< [[Value]] */ + ecma_object_t *get_p; /**< [[Get]] */ + ecma_object_t *set_p; /**< [[Set]] */ +} ecma_property_descriptor_t; + +/** + * Bitfield which represents a namedata property options in an ecma_property_descriptor_t + * Attributes: + * - is_get_defined, is_set_defined : false + * - is_configurable, is_writable, is_enumerable : undefined (false) + * - is_throw : undefined (false) + * - is_value_defined : true + * - is_configurable_defined, is_writable_defined, is_enumerable_defined : true + */ +#define ECMA_NAME_DATA_PROPERTY_DESCRIPTOR_BITS \ + ((uint16_t) (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE_DEFINED \ + | JERRY_PROP_IS_WRITABLE_DEFINED)) + +/** + * Bitmask to get a the physical property flags from an ecma_property_descriptor + */ +#define ECMA_PROPERTY_FLAGS_MASK \ + ((uint16_t) (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_WRITABLE)) + +/** + * Description of an ecma-number + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +typedef double ecma_number_t; +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +typedef float ecma_number_t; +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Convert double to an ecma-number. + */ +#define DOUBLE_TO_ECMA_NUMBER_T(value) ((ecma_number_t) (value)) + +/** + * Value '0' of ecma_number_t + */ +#define ECMA_NUMBER_ZERO ((ecma_number_t) 0.0f) + +/** + * Value '1' of ecma_number_t + */ +#define ECMA_NUMBER_ONE ((ecma_number_t) 1.0f) + +/** + * Value '2' of ecma_number_t + */ +#define ECMA_NUMBER_TWO ((ecma_number_t) 2.0f) + +/** + * Value '0.5' of ecma_number_t + */ +#define ECMA_NUMBER_HALF ((ecma_number_t) 0.5f) + +/** + * Value '-1' of ecma_number_t + */ +#define ECMA_NUMBER_MINUS_ONE ((ecma_number_t) -1.0f) + +/** + * Maximum number of characters in string representation of ecma-number + */ +#define ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER 64 + +/** + * Maximum number of characters in string representation of ecma-uint32 + */ +#define ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32 10 + +/** + * String is not a valid array index. + */ +#define ECMA_STRING_NOT_ARRAY_INDEX UINT32_MAX + +/** + * Ecma-collection: a growable list of ecma-values. + */ +typedef struct +{ + uint32_t item_count; /**< number of items in the collection */ + uint32_t capacity; /**< number of items can be stored in the underlying buffer */ + ecma_value_t *buffer_p; /**< underlying data buffer */ +} ecma_collection_t; + +/** + * Initial capacity of an ecma-collection + */ +#define ECMA_COLLECTION_INITIAL_CAPACITY 4 + +/** + * Ecma-collenction grow factor when the collection underlying buffer need to be reallocated + */ +#define ECMA_COLLECTION_GROW_FACTOR (ECMA_COLLECTION_INITIAL_CAPACITY * 2) + +/** + * Compute the total allocated size of the collection based on it's capacity + */ +#define ECMA_COLLECTION_ALLOCATED_SIZE(capacity) (uint32_t) (capacity * sizeof (ecma_value_t)) + +/** + * Initial allocated size of an ecma-collection + */ +#define ECMA_COLLECTION_INITIAL_SIZE ECMA_COLLECTION_ALLOCATED_SIZE (ECMA_COLLECTION_INITIAL_CAPACITY) + +/** + * Size shift of a compact collection + */ +#define ECMA_COMPACT_COLLECTION_SIZE_SHIFT 3 + +/** + * Get the size of the compact collection + */ +#define ECMA_COMPACT_COLLECTION_GET_SIZE(compact_collection_p) \ + ((compact_collection_p)[0] >> ECMA_COMPACT_COLLECTION_SIZE_SHIFT) + +/** + * Direct string types (2 bit). + */ +typedef enum +{ + ECMA_DIRECT_STRING_PTR = 0, /**< string is a string pointer, only used by property names */ + ECMA_DIRECT_STRING_MAGIC = 1, /**< string is a magic string */ + ECMA_DIRECT_STRING_UINT = 2, /**< string is an unsigned int */ + ECMA_DIRECT_STRING_SPECIAL = 3, /**< string is special */ +} ecma_direct_string_type_t; + +/** + * Maximum value of the immediate part of a direct magic string. + * Must be compatible with the immediate property name. + */ +#if JERRY_CPOINTER_32_BIT +#define ECMA_DIRECT_STRING_MAX_IMM 0x07ffffff +#else /* !JERRY_CPOINTER_32_BIT */ +#define ECMA_DIRECT_STRING_MAX_IMM 0x0000ffff +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Shift for direct string value part in ecma_value_t. + */ +#define ECMA_DIRECT_STRING_SHIFT (ECMA_VALUE_SHIFT + 2) + +/** + * Full mask for direct strings. + */ +#define ECMA_DIRECT_STRING_MASK ((uintptr_t) (ECMA_DIRECT_TYPE_MASK | (0x3u << ECMA_VALUE_SHIFT))) + +/** + * Create an ecma direct string. + */ +#define ECMA_CREATE_DIRECT_STRING(type, value) \ + ((uintptr_t) (ECMA_TYPE_DIRECT_STRING | ((type) << ECMA_VALUE_SHIFT) | (value) << ECMA_DIRECT_STRING_SHIFT)) + +/** + * Create an ecma direct string from the given number. + * + * Note: the given number must be less or equal than ECMA_DIRECT_STRING_MAX_IMM + */ +#define ECMA_CREATE_DIRECT_UINT32_STRING(uint32_number) \ + ((ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) uint32_number)) + +/** + * Checks whether the string is direct. + */ +#define ECMA_IS_DIRECT_STRING(string_p) ((((uintptr_t) (string_p)) & 0x1) != 0) + +/** + * Checks whether the string is direct. + */ +#define ECMA_IS_DIRECT_STRING_WITH_TYPE(string_p, type) \ + ((((uintptr_t) (string_p)) & ECMA_DIRECT_STRING_MASK) == ECMA_CREATE_DIRECT_STRING (type, 0)) + +/** + * Returns the type of a direct string. + */ +#define ECMA_GET_DIRECT_STRING_TYPE(string_p) ((((uintptr_t) (string_p)) >> ECMA_VALUE_SHIFT) & 0x3) + +/** + * Shift applied to type conversions. + */ +#define ECMA_STRING_TYPE_CONVERSION_SHIFT (ECMA_PROPERTY_NAME_TYPE_SHIFT - ECMA_VALUE_SHIFT) + +/** + * Converts direct string type to property name type. + */ +#define ECMA_DIRECT_STRING_TYPE_TO_PROP_NAME_TYPE(string_p) \ + ((((uintptr_t) (string_p)) & (0x3 << ECMA_VALUE_SHIFT)) << ECMA_STRING_TYPE_CONVERSION_SHIFT) + +/** + * Returns the value of a direct string. + */ +#define ECMA_GET_DIRECT_STRING_VALUE(string_p) (((uintptr_t) (string_p)) >> ECMA_DIRECT_STRING_SHIFT) + +/** + * Maximum number of bytes that a long-utf8-string is able to store + */ +#define ECMA_STRING_SIZE_LIMIT UINT32_MAX + +typedef enum +{ + ECMA_STRING_CONTAINER_HEAP_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string + * maximum size is 2^16. */ + ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING, /**< the string is a long string or provided externally + * and only its attributes are stored. */ + ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< string representation of an uint32 number */ + ECMA_STRING_CONTAINER_HEAP_ASCII_STRING, /**< actual data is on the heap as an ASCII string + * maximum size is 2^16. */ + ECMA_STRING_CONTAINER_MAGIC_STRING_EX, /**< the ecma-string is equal to one of external magic strings */ + ECMA_STRING_CONTAINER_SYMBOL, /**< the ecma-string is a symbol */ + + ECMA_STRING_CONTAINER__MAX = ECMA_STRING_CONTAINER_SYMBOL /**< maximum value */ +} ecma_string_container_t; + +/** + * Mask for getting the container of a string. + */ +#define ECMA_STRING_CONTAINER_MASK 0x7u + +/** + * Value for increasing or decreasing the reference counter. + */ +#define ECMA_STRING_REF_ONE (1u << 4) + +/** + * Maximum value of the reference counter (4294967280). + */ +#define ECMA_STRING_MAX_REF (0xFFFFFFF0) + +/** + * Flag that identifies that the string is static which means it is stored in JERRY_CONTEXT (string_list_cp) + */ +#define ECMA_STATIC_STRING_FLAG (1 << 3) + +/** + * Set an ecma-string as static string + */ +#define ECMA_SET_STRING_AS_STATIC(string_p) (string_p)->refs_and_container |= ECMA_STATIC_STRING_FLAG + +/** + * Checks whether the ecma-string is static string + */ +#define ECMA_STRING_IS_STATIC(string_p) ((string_p)->refs_and_container & ECMA_STATIC_STRING_FLAG) + +/** + * Returns with the container type of a string. + */ +#define ECMA_STRING_GET_CONTAINER(string_desc_p) \ + ((ecma_string_container_t) ((string_desc_p)->refs_and_container & ECMA_STRING_CONTAINER_MASK)) + +/** + * Checks whether the reference counter is 1 of a string. + */ +#define ECMA_STRING_IS_REF_EQUALS_TO_ONE(string_desc_p) (((string_desc_p)->refs_and_container >> 4) == 1) + +/** + * Checks whether the reference counter is 1 of an extended primitive. + */ +#define ECMA_EXTENDED_PRIMITIVE_IS_REF_EQUALS_TO_ONE(extended_primitive_p) \ + (((extended_primitive_p)->refs_and_type >> 3) == 1) + +/** + * ECMA string-value descriptor + */ +typedef struct +{ + /** Reference counter for the string */ + uint32_t refs_and_container; + + /** + * Actual data or identifier of it's place in container (depending on 'container' field) + */ + union + { + lit_string_hash_t hash; /**< hash of the ASCII/UTF8 string */ + uint32_t magic_string_ex_id; /**< identifier of an external magic string (lit_magic_string_ex_id_t) */ + uint32_t uint32_number; /**< uint32-represented number placed locally in the descriptor */ + } u; +} ecma_string_t; + +/** + * ECMA UTF8 string-value descriptor + */ +typedef struct +{ + ecma_string_t header; /**< string header */ + uint16_t size; /**< size of this utf-8 string in bytes */ + uint16_t length; /**< length of this utf-8 string in characters */ +} ecma_short_string_t; + +/** + * Long or external CESU8 string-value descriptor + */ +typedef struct +{ + ecma_string_t header; /**< string header */ + const lit_utf8_byte_t *string_p; /**< string data */ + lit_utf8_size_t size; /**< size of this external string in bytes */ + lit_utf8_size_t length; /**< length of this external string in characters */ +} ecma_long_string_t; + +/** + * External UTF8 string-value descriptor + */ +typedef struct +{ + ecma_long_string_t header; /**< long string header */ + void *user_p; /**< user pointer passed to the callback when the string is freed */ +} ecma_external_string_t; + +/** + * Header size of an ecma ASCII string + */ +#define ECMA_ASCII_STRING_HEADER_SIZE ((lit_utf8_size_t) (sizeof (ecma_string_t) + sizeof (uint8_t))) + +/** + * Get the size of an ecma ASCII string + */ +#define ECMA_ASCII_STRING_GET_SIZE(string_p) \ + ((lit_utf8_size_t) * ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_string_t)) + 1) + +/** + * Set the size of an ecma ASCII string + */ +#define ECMA_ASCII_STRING_SET_SIZE(string_p, size) \ + (*((lit_utf8_byte_t *) (string_p) + sizeof (ecma_string_t)) = (uint8_t) ((size) -1)) + +/** + * Get the start position of the string buffer of an ecma ASCII string + */ +#define ECMA_ASCII_STRING_GET_BUFFER(string_p) ((lit_utf8_byte_t *) (string_p) + ECMA_ASCII_STRING_HEADER_SIZE) + +/** + * Get the start position of the string buffer of an ecma UTF8 string + */ +#define ECMA_SHORT_STRING_GET_BUFFER(string_p) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_short_string_t)) + +/** + * Get the start position of the string buffer of an ecma long CESU8 string + */ +#define ECMA_LONG_STRING_BUFFER_START(string_p) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_long_string_t)) + +/** + * ECMA extended string-value descriptor + */ +typedef struct +{ + ecma_string_t header; /**< string header */ + + union + { + ecma_value_t symbol_descriptor; /**< symbol descriptor string-value */ + ecma_value_t value; /**< original key value corresponds to the map key string */ + } u; +} ecma_extended_string_t; + +/** + * Required number of ecma values in a compact collection to represent PrivateElement + */ +#define ECMA_PRIVATE_ELEMENT_LIST_SIZE 3 + +/** + * String builder header + */ +typedef struct +{ + lit_utf8_size_t current_size; /**< size of the data in the buffer */ +} ecma_stringbuilder_header_t; + +/** + * Get pointer to the beginning of the stored string in the string builder + */ +#define ECMA_STRINGBUILDER_STRING_PTR(header_p) \ + ((lit_utf8_byte_t *) (((lit_utf8_byte_t *) header_p) + ECMA_ASCII_STRING_HEADER_SIZE)) + +/** + * Get the size of the stored string in the string builder + */ +#define ECMA_STRINGBUILDER_STRING_SIZE(header_p) \ + ((lit_utf8_size_t) (header_p->current_size - ECMA_ASCII_STRING_HEADER_SIZE)) + +/** + * String builder handle + */ +typedef struct +{ + ecma_stringbuilder_header_t *header_p; /**< pointer to header */ +} ecma_stringbuilder_t; + +#ifndef JERRY_BUILTIN_BIGINT +/** + * BigInt type. + */ +#define ECMA_EXTENDED_PRIMITIVE_BIGINT 0 +#endif /* !defined (JERRY_BUILTIN_BIGINT) */ + +/** + * Flags for exception values. + */ +typedef enum +{ + ECMA_ERROR_API_FLAG_NONE = 0, + ECMA_ERROR_API_FLAG_ABORT = (1u << 0), /**< abort flag */ + ECMA_ERROR_API_FLAG_THROW_CAPTURED = (1u << 1), /**< throw captured flag */ +} ecma_error_api_flags_t; + +/** + * Representation of a thrown value on API level. + */ +typedef struct +{ + uint32_t refs_and_type; /**< reference counter and type */ + union + { + ecma_value_t value; /**< referenced value */ + uint32_t bigint_sign_and_size; /**< BigInt properties */ + } u; +} ecma_extended_primitive_t; + +/** + * Value for increasing or decreasing the reference counter. + */ +#define ECMA_EXTENDED_PRIMITIVE_REF_ONE (1u << 3) + +/** + * Maximum value of the reference counter. + */ +#define ECMA_EXTENDED_PRIMITIVE_MAX_REF (UINT32_MAX - (ECMA_EXTENDED_PRIMITIVE_REF_ONE - 1)) + +#if JERRY_PROPERTY_HASHMAP + +/** + * The lowest state of the ecma_prop_hashmap_alloc_state counter. + * If ecma_prop_hashmap_alloc_state other other than this value, it is + * disabled. + */ +#define ECMA_PROP_HASHMAP_ALLOC_ON 0 + +/** + * The highest state of the ecma_prop_hashmap_alloc_state counter. + */ +#define ECMA_PROP_HASHMAP_ALLOC_MAX 4 + +#endif /* JERRY_PROPERTY_HASHMAP */ + +/** + * Number of values in a literal storage item + */ +#define ECMA_LIT_STORAGE_VALUE_COUNT 3 + +/** + * Literal storage item + */ +typedef struct +{ + jmem_cpointer_t next_cp; /**< cpointer ot next item */ + jmem_cpointer_t values[ECMA_LIT_STORAGE_VALUE_COUNT]; /**< list of values */ +} ecma_lit_storage_item_t; + +#if JERRY_LCACHE +/** + * Container of an LCache entry identifier + */ +#if JERRY_CPOINTER_32_BIT +typedef uint64_t ecma_lcache_hash_entry_id_t; +#else /* !JERRY_CPOINTER_32_BIT */ +typedef uint32_t ecma_lcache_hash_entry_id_t; +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Entry of LCache hash table + */ +typedef struct +{ + /** Pointer to a property of the object */ + ecma_property_t *prop_p; + + /** Entry identifier in LCache */ + ecma_lcache_hash_entry_id_t id; +} ecma_lcache_hash_entry_t; + +/** + * Number of rows in LCache's hash table + */ +#define ECMA_LCACHE_HASH_ROWS_COUNT 128 + +/** + * Number of entries in a row of LCache's hash table + */ +#define ECMA_LCACHE_HASH_ROW_LENGTH 2 + +#endif /* JERRY_LCACHE */ + +#if JERRY_BUILTIN_TYPEDARRAY + +/** + * Function callback descriptor of a %TypedArray% object getter + */ +typedef ecma_value_t (*ecma_typedarray_getter_fn_t) (lit_utf8_byte_t *src); + +/** + * Function callback descriptor of a %TypedArray% object setter + */ +typedef ecma_value_t (*ecma_typedarray_setter_fn_t) (lit_utf8_byte_t *src, ecma_value_t value); + +/** + * Builtin id for the different types of TypedArray's + */ +typedef enum +{ + ECMA_INT8_ARRAY, /**< Int8Array */ + ECMA_UINT8_ARRAY, /**< Uint8Array */ + ECMA_UINT8_CLAMPED_ARRAY, /**< Uint8ClampedArray */ + ECMA_INT16_ARRAY, /**< Int16Array */ + ECMA_UINT16_ARRAY, /**< Uint16Array */ + ECMA_INT32_ARRAY, /**< Int32Array */ + ECMA_UINT32_ARRAY, /**< Uint32Array */ + ECMA_FLOAT32_ARRAY, /**< Float32Array */ + ECMA_FLOAT64_ARRAY, /**< Float64Array */ + /* ECMA_TYPEDARRAY_IS_BIGINT_TYPE macro should be updated when new types are added */ + ECMA_BIGINT64_ARRAY, /**< BigInt64Array */ + ECMA_BIGUINT64_ARRAY, /**< BigUInt64Array */ +} ecma_typedarray_type_t; + +/** + * TypedArray flags. + */ +typedef enum +{ + ECMA_TYPEDARRAY_IS_EXTENDED = (1u << 0), /* an ecma_extended_typedarray_object_t is allocated for the TypedArray */ +} ecma_typedarray_flag_t; + +/** + * Array buffer flags. + */ +typedef enum +{ + ECMA_ARRAYBUFFER_HAS_POINTER = (1u << 0), /* ArrayBuffer has a buffer pointer. */ + ECMA_ARRAYBUFFER_ALLOCATED = (1u << 1), /* ArrayBuffer memory is allocated */ + ECMA_ARRAYBUFFER_DETACHED = (1u << 2), /* ArrayBuffer has been detached */ +} ecma_arraybuffer_flag_t; + +/** + * Structure for array buffers with a backing store pointer. + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + void *buffer_p; /**< pointer to the backing store of the array buffer object */ + void *arraybuffer_user_p; /**< user pointer passed to the free callback */ +} ecma_arraybuffer_pointer_t; + +/** + * Some internal properties of TypedArray object. + * It is only used when the offset is not 0, and + * the array-length is not buffer-length / element_size. + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + uint32_t byte_offset; /**< the byteoffset of the above arraybuffer */ + uint32_t array_length; /**< the array length */ +} ecma_extended_typedarray_object_t; + +/** + * General structure for query %TypedArray% object's properties. + **/ +typedef struct +{ + ecma_object_t *array_buffer_p; /**< pointer to the typedArray's [[ViewedArrayBuffer]] internal slot */ + ecma_typedarray_type_t id; /**< [[TypedArrayName]] internal slot */ + uint32_t length; /**< [[ByteLength]] internal slot */ + uint32_t offset; /**< [[ByteOffset]] internal slot. */ + uint8_t shift; /**< the element size shift in the typedArray */ + uint8_t element_size; /**< element size based on [[TypedArrayName]] in Table 49 */ +} ecma_typedarray_info_t; + +#if JERRY_BUILTIN_BIGINT +/** + * Checks whether a given typedarray is BigInt type or not. + **/ +#define ECMA_TYPEDARRAY_IS_BIGINT_TYPE(id) ((id) >= ECMA_BIGINT64_ARRAY) + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +/** + * Executable (e.g. generator, async) object flags. + */ +typedef enum +{ + ECMA_EXECUTABLE_OBJECT_COMPLETED = (1u << 0), /**< executable object is completed and cannot be resumed */ + ECMA_EXECUTABLE_OBJECT_RUNNING = (1u << 1), /**< executable object is currently running */ + /* Generator specific flags. */ + ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD = (1u << 2), /**< the executable object performs + * an await or a yield* operation */ + ECMA_ASYNC_GENERATOR_CALLED = (1u << 3), /**< the async generator was executed before */ + /* This must be the last generator specific flag. */ + ECMA_AWAIT_STATE_SHIFT = 4, /**< shift for await states */ +} ecma_executable_object_flags_t; + +/** + * Async function states after an await is completed. + */ +typedef enum +{ + ECMA_AWAIT_YIELD_NEXT, /**< wait for an iterator result object */ + ECMA_AWAIT_YIELD_NEXT_RETURN, /**< wait for an iterator result object after a return operation */ + ECMA_AWAIT_YIELD_RETURN, /**< wait for the argument passed to return operation */ + ECMA_AWAIT_YIELD_NEXT_VALUE, /**< wait for the value property of an iterator result object */ + ECMA_AWAIT_YIELD_OPERATION, /**< wait for the generator operation (next/throw/return) */ + ECMA_AWAIT_YIELD_CLOSE, /**< wait for the result of iterator close operation */ + /* After adding new ECMA_AWAIT_YIELD items, the ECMA_AWAIT_YIELD_END should be updated. */ + ECMA_AWAIT_FOR_CLOSE, /**< wait for a close iterator result object of for-await-of statement */ + ECMA_AWAIT_FOR_NEXT, /**< wait for an iterator result object of for-await-of statement */ +} ecma_await_states_t; + +/** + * Checks whether the executable object is waiting for resuming. + */ +#define ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED(executable_object_p) \ + (!((executable_object_p)->extended_object.u.cls.u2.executable_obj_flags \ + & (ECMA_EXECUTABLE_OBJECT_COMPLETED | ECMA_EXECUTABLE_OBJECT_RUNNING))) + +/** + * Last item of yield* related await states. + */ +#define ECMA_AWAIT_YIELD_END ECMA_AWAIT_YIELD_CLOSE + +/** + * Helper macro for ECMA_EXECUTABLE_OBJECT_RESUME_EXEC. + */ +#define ECMA_EXECUTABLE_OBJECT_RESUME_EXEC_MASK ((uint16_t) ~ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + +/** + * Resume execution of the byte code. + */ +#define ECMA_EXECUTABLE_OBJECT_RESUME_EXEC(executable_object_p) \ + ((executable_object_p)->extended_object.u.cls.u2.executable_obj_flags &= ECMA_EXECUTABLE_OBJECT_RESUME_EXEC_MASK) + +/** + * Enqueued task of an AsyncGenerator. + * + * An execution of a task has three steps: + * 1) Perform a next/throw/return operation + * 2) Resume the execution of the AsyncGenerator + * 3) Fulfill or reject a promise if the AsyncGenerator yielded a value + * (these Promises are created by the AsyncGenerator itself) + */ +typedef struct +{ + ecma_value_t next; /**< points to the next task which will be performed after this task is completed */ + ecma_value_t promise; /**< promise which will be fulfilled or rejected after this task is completed */ + ecma_value_t operation_value; /**< value argument of the operation */ + uint8_t operation_type; /**< type of operation (see ecma_async_generator_operation_type_t) */ +} ecma_async_generator_task_t; + +/** + * Definition of PromiseCapability Records + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header, and [[Promise]] internal slot */ + ecma_value_t resolve; /**< [[Resolve]] internal slot */ + ecma_value_t reject; /**< [[Reject]] internal slot */ +} ecma_promise_capabality_t; + +/** + * Definition of GetCapabilitiesExecutor Functions + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_value_t capability; /**< [[Capability]] internal slot */ +} ecma_promise_capability_executor_t; + +/** + * Definition of Promise.all Resolve Element Functions + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_value_t remaining_elements; /**< [[Remaining elements]] internal slot */ + ecma_value_t capability; /**< [[Capabilities]] internal slot */ + ecma_value_t values; /**< [[Values]] or [[Errors]] internal slot */ + uint32_t index; /**< [[Index]] and [[AlreadyCalled]] internal slot + * 0 - if the element has been resolved + * real index + 1 in the [[Values]] list - otherwise */ +} ecma_promise_all_executor_t; + +/** + * Promise prototype methods helper. + */ +typedef enum +{ + ECMA_PROMISE_ALL_RESOLVE, /**< promise.all resolve */ + ECMA_PROMISE_ALLSETTLED_RESOLVE, /**< promise.allSettled resolve */ + ECMA_PROMISE_ALLSETTLED_REJECT, /**< promise.allSettled reject */ + ECMA_PROMISE_ANY_REJECT, /**< promise.any reject */ +} ecma_promise_executor_type_t; + +#if JERRY_BUILTIN_DATAVIEW +/** + * Description of DataView objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< header part */ + ecma_object_t *buffer_p; /**< [[ViewedArrayBuffer]] internal slot */ + uint32_t byte_offset; /**< [[ByteOffset]] internal slot */ +} ecma_dataview_object_t; +#endif /* JERRY_BUILTIN_DATAVIEW */ + +typedef enum +{ + ECMA_SYMBOL_FLAG_NONE = 0, /**< no options */ + ECMA_SYMBOL_FLAG_GLOBAL = (1 << 0), /**< symbol is a well known symbol, See also: 6.1.5.1 */ + ECMA_SYMBOL_FLAG_PRIVATE_KEY = (1 << 1), /**< symbol is a private field */ + ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD = (1 << 2), /**< symbol is a private method or accessor */ +} ecma_symbol_flags_t; + +/** + * Bitshift index for the symbol hash property + */ +#define ECMA_SYMBOL_FLAGS_SHIFT 3 + +/** + * Bitmask for symbol hash flags + */ +#define ECMA_SYMBOL_FLAGS_MASK ((1 << ECMA_SYMBOL_FLAGS_SHIFT) - 1) + +#if (JERRY_STACK_LIMIT != 0) +/** + * Check the current stack usage. If the limit is reached a RangeError is raised. + * The macro argument specifies the return value which is usally ECMA_VALUE_ERROR or NULL. + */ +#define ECMA_CHECK_STACK_USAGE_RETURN(RETURN_VALUE) \ + do \ + { \ + if (ecma_get_current_stack_usage () > CONFIG_MEM_STACK_LIMIT) \ + { \ + ecma_raise_maximum_callstack_error (); \ + return RETURN_VALUE; \ + } \ + } while (0) + +/** + * Specialized version of ECMA_CHECK_STACK_USAGE_RETURN which returns ECMA_VALUE_ERROR. + * This version should be used in most cases. + */ +#define ECMA_CHECK_STACK_USAGE() ECMA_CHECK_STACK_USAGE_RETURN (ECMA_VALUE_ERROR) +#else /* JERRY_STACK_LIMIT == 0) */ +/** + * If the stack limit is unlimited, this check is an empty macro. + */ +#define ECMA_CHECK_STACK_USAGE_RETURN(RETURN_VALUE) + +/** + * If the stack limit is unlimited, this check is an empty macro. + */ +#define ECMA_CHECK_STACK_USAGE() +#endif /* (JERRY_STACK_LIMIT != 0) */ + +/** + * Invalid object pointer which represents abrupt completion + */ +#define ECMA_OBJECT_POINTER_ERROR ((ecma_object_t *) 0x01) + +/** + * Invalid property pointer which represents abrupt completion + */ +#define ECMA_PROPERTY_POINTER_ERROR ((ecma_property_t *) 0x01) + +#if JERRY_BUILTIN_PROXY + +/** + * Proxy object flags. + */ +typedef enum +{ + ECMA_PROXY_SKIP_RESULT_VALIDATION = (1u << 0), /**< skip result validation for [[GetPrototypeOf]], + * [[SetPrototypeOf]], [[IsExtensible]], + * [[PreventExtensions]], [[GetOwnProperty]], + * [[DefineOwnProperty]], [[HasProperty]], [[Get]], + * [[Set]], [[Delete]] and [[OwnPropertyKeys]] */ + ECMA_PROXY_IS_CALLABLE = (1u << 1), /**< proxy is callable */ + ECMA_PROXY_IS_CONSTRUCTABLE = (1u << 2), /**< proxy is constructable */ +} ecma_proxy_flag_types_t; + +/** + * Description of Proxy objects. + * + * A Proxy object's property list is used to store extra information: + * * The "header.u2.prototype_cp" 1st tag bit stores the IsCallable information. + * * The "header.u2.prototype_cp" 2nd tag bit stores the IsConstructor information. + */ +typedef struct +{ + ecma_object_t header; /**< header part */ + ecma_value_t target; /**< [[ProxyTarget]] internal slot */ + ecma_value_t handler; /**< [[ProxyHandler]] internal slot */ +} ecma_proxy_object_t; + +/** + * Description of Proxy objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< header part */ + ecma_value_t proxy; /**< [[RevocableProxy]] internal slot */ +} ecma_revocable_proxy_object_t; +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * Type to repesent the maximum property index + * + * For ES6+ the maximum valid property index is 2**53 - 1 + */ +typedef uint64_t ecma_length_t; + +#if JERRY_BUILTIN_BIGINT + +/** + * BigUInt data is a sequence of uint32_t numbers. + */ +typedef uint32_t ecma_bigint_digit_t; + +/** + * Special BigInt value representing zero. + */ +#define ECMA_BIGINT_ZERO ((ecma_value_t) ECMA_TYPE_BIGINT) + +/** + * Special BigInt value representing zero when the result is pointer. + */ +#define ECMA_BIGINT_POINTER_TO_ZERO ((ecma_extended_primitive_t *) 0x1) + +/** + * Return the size of a BigInt value in ecma_bigint_data_t units. + */ +#define ECMA_BIGINT_GET_SIZE(value_p) \ + ((value_p)->u.bigint_sign_and_size & ~(uint32_t) (sizeof (ecma_bigint_digit_t) - 1)) + +/** + * Size of memory needs to be allocated for the digits of a BigInt. + * The value is rounded up for two digits. + */ +#define ECMA_BIGINT_GET_BYTE_SIZE(size) \ + (size_t) (((size) + sizeof (ecma_bigint_digit_t)) & ~(2 * sizeof (ecma_bigint_digit_t) - 1)) + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Struct for counting the different types properties in objects + */ +typedef struct +{ + uint32_t array_index_named_props; /**< number of array index named properties */ + uint32_t string_named_props; /**< number of string named properties */ + uint32_t symbol_named_props; /**< number of symbol named properties */ +} ecma_property_counter_t; + +/** + * Arguments object related status flags + */ +typedef enum +{ + ECMA_ARGUMENTS_OBJECT_NO_FLAGS = 0, /* unmapped arguments object */ + ECMA_ARGUMENTS_OBJECT_MAPPED = (1 << 0), /* mapped arguments object */ + ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE = (1 << 1), /* static mapped arguments object */ + ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED = (1 << 2), /* 'callee' property has been lazy initialized */ + ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED = (1 << 3), /* 'length' property has been lazy initialized */ + ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED = (1 << 4), /* 'Symbol.iterator' property has been lazy initialized */ +} ecma_arguments_object_flags_t; + +/** + * Definition of unmapped arguments object + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_value_t callee; /**< 'callee' property */ +} ecma_unmapped_arguments_t; + +/** + * Definition of mapped arguments object + */ +typedef struct +{ + ecma_unmapped_arguments_t unmapped; /**< unmapped arguments object header */ + ecma_value_t lex_env; /**< environment reference */ + union + { + ecma_value_t byte_code; /**< callee's compiled code */ +#if JERRY_SNAPSHOT_EXEC + ecma_compiled_code_t *byte_code_p; /**< real byte code pointer */ +#endif /* JERRY_SNAPSHOT_EXEC */ + } u; +} ecma_mapped_arguments_t; + +/** + * Date object descriptor flags + */ +typedef enum +{ + ECMA_DATE_TZA_NONE = 0, /**< no time-zone adjustment is set */ + ECMA_DATE_TZA_SET = (1 << 0), /**< time-zone adjustment is set */ +} ecma_date_object_flags_t; + +/** + * Definition of date object + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_number_t date_value; /**< [[DateValue]] internal property */ +} ecma_date_object_t; + +/** + * Implicit class constructor flags + */ +typedef enum +{ + ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE = (1 << 0), /**< heritage object is present */ +} ecma_constructor_function_flags_t; + +/** + * Description of AsyncFromSyncIterator objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< header part */ + ecma_value_t sync_next_method; /**< IteratorRecord [[NextMethod]] internal slot */ +} ecma_async_from_sync_iterator_object_t; + +/** + * Private method kind + */ +typedef enum +{ + ECMA_PRIVATE_FIELD = 0, /**< private field */ + ECMA_PRIVATE_METHOD, /**< private method */ + ECMA_PRIVATE_GETTER, /**< private setter */ + ECMA_PRIVATE_SETTER, /**< private getter */ +} ecma_private_property_kind_t; + +/** + * Private static property flag + */ +#define ECMA_PRIVATE_PROPERTY_STATIC_FLAG (1 << 2) + +/* + * Get private property kind from a descriptor + */ +#define ECMA_PRIVATE_PROPERTY_KIND(prop) ((ecma_private_property_kind_t) ((int) (prop) & (ECMA_PRIVATE_PROPERTY_STATIC_FLAG - 1))) + +/** + * @} + * @} + */ + +#endif /* !ECMA_GLOBALS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-collection.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-collection.cpp new file mode 100644 index 00000000..cd814324 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-collection.cpp @@ -0,0 +1,446 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-conversion.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +/** + * Allocate a collection of ecma values. + * + * @return pointer to the collection + */ +ecma_collection_t * +ecma_new_collection (void) +{ + ecma_collection_t *collection_p; + collection_p = (ecma_collection_t *) jmem_heap_alloc_block (sizeof (ecma_collection_t)); + + collection_p->item_count = 0; + collection_p->capacity = ECMA_COLLECTION_INITIAL_CAPACITY; + const uint32_t size = ECMA_COLLECTION_ALLOCATED_SIZE (ECMA_COLLECTION_INITIAL_CAPACITY); + collection_p->buffer_p = (ecma_value_t *) jmem_heap_alloc_block (size); + + return collection_p; +} /* ecma_new_collection */ + +/** + * Deallocate a collection of ecma values without freeing it's values + * + * @return void + */ +void +ecma_collection_destroy (ecma_collection_t *collection_p) /**< value collection */ +{ + JERRY_ASSERT (collection_p != NULL); + + jmem_heap_free_block (collection_p->buffer_p, ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity)); + jmem_heap_free_block (collection_p, sizeof (ecma_collection_t)); +} /* ecma_collection_destroy */ + +/** + * Free the object collection elements and deallocate the collection + */ +void +ecma_collection_free_objects (ecma_collection_t *collection_p) /**< value collection */ +{ + JERRY_ASSERT (collection_p != NULL); + + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + if (ecma_is_value_object (buffer_p[i])) + { + ecma_deref_object (ecma_get_object_from_value (buffer_p[i])); + } + } + + ecma_collection_destroy (collection_p); +} /* ecma_collection_free_objects */ + +/** + * Free the template literal objects and deallocate the collection + */ +void +ecma_collection_free_template_literal (ecma_collection_t *collection_p) /**< value collection */ +{ + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + ecma_object_t *object_p = ecma_get_object_from_value (collection_p->buffer_p[i]); + + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY); + + ecma_extended_object_t *array_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (array_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL); + array_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_ARRAY_TEMPLATE_LITERAL; + + ecma_property_value_t *property_value_p; + + property_value_p = ecma_get_named_data_property (object_p, ecma_get_magic_string (LIT_MAGIC_STRING_RAW)); + ecma_object_t *raw_object_p = ecma_get_object_from_value (property_value_p->value); + + JERRY_ASSERT (ecma_get_object_type (raw_object_p) == ECMA_OBJECT_TYPE_ARRAY); + + array_object_p = (ecma_extended_object_t *) raw_object_p; + + JERRY_ASSERT (array_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL); + array_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_ARRAY_TEMPLATE_LITERAL; + + ecma_deref_object (raw_object_p); + ecma_deref_object (object_p); + } + + ecma_collection_destroy (collection_p); +} /* ecma_collection_free_template_literal */ + +/** + * Free the non-object collection elements and deallocate the collection + */ +void +ecma_collection_free_if_not_object (ecma_collection_t *collection_p) /**< value collection */ +{ + JERRY_ASSERT (collection_p != NULL); + + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + ecma_free_value_if_not_object (buffer_p[i]); + } + + ecma_collection_destroy (collection_p); +} /* ecma_collection_free_if_not_object */ + +/** + * Free the collection elements and deallocate the collection + */ +void +ecma_collection_free (ecma_collection_t *collection_p) /**< value collection */ +{ + JERRY_ASSERT (collection_p != NULL); + + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + ecma_free_value (buffer_p[i]); + } + + ecma_collection_destroy (collection_p); +} /* ecma_collection_free */ + +/** + * Append new value to ecma values collection + * + * Note: The reference count of the values are not increased + */ +void +ecma_collection_push_back (ecma_collection_t *collection_p, /**< value collection */ + ecma_value_t value) /**< ecma value to append */ +{ + JERRY_ASSERT (collection_p != NULL); + + ecma_value_t *buffer_p = collection_p->buffer_p; + + if (JERRY_LIKELY (collection_p->item_count < collection_p->capacity)) + { + buffer_p[collection_p->item_count++] = value; + return; + } + + const uint32_t new_capacity = collection_p->capacity + ECMA_COLLECTION_GROW_FACTOR; + const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity); + const uint32_t new_size = ECMA_COLLECTION_ALLOCATED_SIZE (new_capacity); + + buffer_p = (ecma_value_t *) jmem_heap_realloc_block (buffer_p, old_size, new_size); + buffer_p[collection_p->item_count++] = value; + collection_p->capacity = new_capacity; + + collection_p->buffer_p = buffer_p; +} /* ecma_collection_push_back */ + +/** + * Reserve space for the given amount of ecma_values in the collection + */ +void +ecma_collection_reserve (ecma_collection_t *collection_p, /**< value collection */ + uint32_t count) /**< number of ecma values to reserve */ +{ + JERRY_ASSERT (collection_p != NULL); + JERRY_ASSERT (UINT32_MAX - count > collection_p->capacity); + + const uint32_t new_capacity = collection_p->capacity + count; + const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity); + const uint32_t new_size = ECMA_COLLECTION_ALLOCATED_SIZE (new_capacity); + + ecma_value_t *buffer_p = collection_p->buffer_p; + buffer_p = (ecma_value_t *) jmem_heap_realloc_block (buffer_p, old_size, new_size); + + collection_p->capacity = new_capacity; + collection_p->buffer_p = buffer_p; +} /* ecma_collection_reserve */ + +/** + * Append a list of values to the end of the collection + */ +void +ecma_collection_append (ecma_collection_t *collection_p, /**< value collection */ + const ecma_value_t *buffer_p, /**< values to append */ + uint32_t count) /**< number of ecma values to append */ +{ + JERRY_ASSERT (collection_p != NULL); + JERRY_ASSERT (collection_p->capacity >= collection_p->item_count); + + uint32_t free_count = collection_p->capacity - collection_p->item_count; + + if (free_count < count) + { + ecma_collection_reserve (collection_p, count - free_count); + } + + memcpy (collection_p->buffer_p + collection_p->item_count, buffer_p, count * sizeof (ecma_value_t)); + collection_p->item_count += count; +} /* ecma_collection_append */ + +/** + * Helper function to check if a given collection have duplicated properties or not + * + * @return true - if there are duplicated properties in the collection + * false - otherwise + */ +bool +ecma_collection_check_duplicated_entries (ecma_collection_t *collection_p) /**< prop name collection */ +{ + if (collection_p->item_count == 0) + { + return false; + } + + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t i = 0; i < collection_p->item_count - 1; i++) + { + ecma_string_t *current_name_p = ecma_get_prop_name_from_value (buffer_p[i]); + + for (uint32_t j = i + 1; j < collection_p->item_count; j++) + { + if (ecma_compare_ecma_strings (current_name_p, ecma_get_prop_name_from_value (buffer_p[j]))) + { + return true; + } + } + } + + return false; +} /* ecma_collection_check_duplicated_entries */ + +/** + * Check the string value existance in the collection. + * + * Used by: + * - ecma_builtin_json_stringify step 4.b.ii.5 + * - ecma_op_object_enumerate + * + * @return true, if the string is already in the collection. + */ +bool +ecma_collection_has_string_value (ecma_collection_t *collection_p, /**< collection */ + ecma_string_t *string_p) /**< string */ +{ + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + ecma_string_t *current_p = ecma_get_string_from_value (buffer_p[i]); + + if (ecma_compare_ecma_strings (current_p, string_p)) + { + return true; + } + } + + return false; +} /* ecma_collection_has_string_value */ + +/** + * Initial capacity of an ecma-collection + */ +#define ECMA_COMPACT_COLLECTION_GROWTH 8 + +/** + * Set the size of the compact collection + */ +#define ECMA_COMPACT_COLLECTION_SET_SIZE(compact_collection_p, item_count, unused_items) \ + ((compact_collection_p)[0] = (((item_count) << ECMA_COMPACT_COLLECTION_SIZE_SHIFT) | (unused_items))) + +/** + * Set the size of the compact collection + */ +#define ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT(compact_collection_p) \ + ((compact_collection_p)[0] & ((1 << ECMA_COMPACT_COLLECTION_SIZE_SHIFT) - 1)) + +/** + * Allocate a compact collection of ecma values + * + * @return pointer to the compact collection + */ +ecma_value_t * +ecma_new_compact_collection (void) +{ + size_t size = (ECMA_COMPACT_COLLECTION_GROWTH / 2) * sizeof (ecma_value_t); + ecma_value_t *compact_collection_p = (ecma_value_t *) jmem_heap_alloc_block (size); + + ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p, + ECMA_COMPACT_COLLECTION_GROWTH / 2, + (ECMA_COMPACT_COLLECTION_GROWTH / 2) - 1); + return compact_collection_p; +} /* ecma_new_compact_collection */ + +/** + * Append a value to the compact collection + * + * @return updated pointer to the compact collection + */ +ecma_value_t * +ecma_compact_collection_push_back (ecma_value_t *compact_collection_p, /**< compact collection */ + ecma_value_t value) /**< ecma value to append */ +{ + ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p); + ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p); + + if (unused_items > 0) + { + compact_collection_p[size - unused_items] = value; + (*compact_collection_p)--; + return compact_collection_p; + } + + if (size == ECMA_COMPACT_COLLECTION_GROWTH / 2) + { + size_t old_size = (ECMA_COMPACT_COLLECTION_GROWTH / 2) * sizeof (ecma_value_t); + size_t new_size = ECMA_COMPACT_COLLECTION_GROWTH * sizeof (ecma_value_t); + compact_collection_p = (ecma_value_t *) jmem_heap_realloc_block (compact_collection_p, old_size, new_size); + + compact_collection_p[ECMA_COMPACT_COLLECTION_GROWTH / 2] = value; + + ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p, + ECMA_COMPACT_COLLECTION_GROWTH, + (ECMA_COMPACT_COLLECTION_GROWTH / 2) - 1); + return compact_collection_p; + } + + size_t old_size = size * sizeof (ecma_value_t); + size_t new_size = old_size + (ECMA_COMPACT_COLLECTION_GROWTH * sizeof (ecma_value_t)); + + compact_collection_p = (ecma_value_t *) jmem_heap_realloc_block (compact_collection_p, old_size, new_size); + compact_collection_p[size] = value; + + ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p, + size + ECMA_COMPACT_COLLECTION_GROWTH, + ECMA_COMPACT_COLLECTION_GROWTH - 1); + return compact_collection_p; +} /* ecma_compact_collection_push_back */ + +/** + * Discard the unused elements of a compact collection + * + * Note: + * further items should not be added after this call + * + * @return updated pointer to the compact collection + */ +ecma_value_t * +ecma_compact_collection_shrink (ecma_value_t *compact_collection_p) /**< compact collection */ +{ + ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p); + + if (unused_items == 0) + { + return compact_collection_p; + } + + ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p); + + size_t old_size = size * sizeof (ecma_value_t); + size_t new_size = (size - unused_items) * sizeof (ecma_value_t); + + compact_collection_p = (ecma_value_t *) jmem_heap_realloc_block (compact_collection_p, old_size, new_size); + + ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p, size - unused_items, 0); + return compact_collection_p; +} /* ecma_compact_collection_shrink */ + +/** + * Free a compact collection + */ +void +ecma_compact_collection_free (ecma_value_t *compact_collection_p) /**< compact collection */ +{ + ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p); + ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p); + + ecma_value_t *end_p = compact_collection_p + size - unused_items; + ecma_value_t *current_p = compact_collection_p + 1; + + while (current_p < end_p) + { + ecma_free_value (*current_p++); + } + + jmem_heap_free_block (compact_collection_p, size * sizeof (ecma_value_t)); +} /* ecma_compact_collection_free */ + +/** + * Get the end of a compact collection + * + * @return pointer to the compact collection end + */ +ecma_value_t * +ecma_compact_collection_end (ecma_value_t *compact_collection_p) /**< compact collection */ +{ + ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p); + ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p); + + return compact_collection_p + size - unused_items; +} /* ecma_compact_collection_end */ + +/** + * Destroy a compact collection + */ +void +ecma_compact_collection_destroy (ecma_value_t *compact_collection_p) /**< compact collection */ +{ + ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p); + + jmem_heap_free_block (compact_collection_p, size * sizeof (ecma_value_t)); +} /* ecma_compact_collection_destroy */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-conversion.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-conversion.cpp new file mode 100644 index 00000000..8ee7fb9f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-conversion.cpp @@ -0,0 +1,943 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" + +#include "jrt-libc-includes.h" +#include "lit-char-helpers.h" +#include "lit-magic-strings.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +#if JERRY_NUMBER_TYPE_FLOAT64 + +/** + * \addtogroup ecmahelpersbigintegers Helpers for operations intermediate 128-bit integers + * @{ + */ + +/** + * 128-bit integer type + */ +typedef struct +{ + uint64_t hi; /**< high 64 bits */ + uint64_t lo; /**< low 64 bits */ +} ecma_uint128_t; + +/** + * Round high part of 128-bit integer to uint64_t + * + * @return rounded high to uint64_t + */ +static uint64_t +ecma_round_high_to_uint64 (ecma_uint128_t *num_p) +{ + uint64_t masked_lo = num_p->lo & ~(1ULL << 63u); + uint64_t masked_hi = num_p->hi & 0x1; + + if ((num_p->lo >> 63u != 0) && (masked_lo > 0 || masked_hi != 0)) + { + return (num_p->hi + 1); + } + + return num_p->hi; +} /* ecma_round_high_to_uint64 */ + +/** + * Left shift 128-bit integer by max 63 bits. + */ +static void +ecma_uint128_shift_left (ecma_uint128_t *num_p, int32_t shift) +{ + num_p->hi = (num_p->hi << shift) | (num_p->lo >> (64 - shift)); + num_p->lo <<= shift; +} /* ecma_uint128_shift_left */ + +/** + * Right shift 128-bit integer by max 63 bits. + */ +static void +ecma_uint128_shift_right (ecma_uint128_t *num_p, int32_t shift) +{ + num_p->lo = (num_p->lo >> shift) | (num_p->hi << (64 - shift)); + num_p->hi >>= shift; +} /* ecma_uint128_shift_right */ + +/** + * Add two 128-bit integer values and assign the result to the left one. + */ +static void +ecma_uint128_add (ecma_uint128_t *left_p, ecma_uint128_t *right_p) +{ + left_p->hi += right_p->hi; + left_p->lo += right_p->lo; + + if (left_p->lo < right_p->lo) + { + left_p->hi++; + } +} /* ecma_uint128_add */ + +/** + * Multiply 128-bit integer by 10 + */ +static void +ecma_uint128_mul10 (ecma_uint128_t *num_p) +{ + ecma_uint128_shift_left (num_p, 1u); + + ecma_uint128_t tmp = { num_p->hi, num_p->lo }; + ecma_uint128_shift_left (&tmp, 2u); + + ecma_uint128_add (num_p, &tmp); +} /* ecma_uint128_mul10 */ + +/** + * Divide 128-bit integer by 10 + * + * N = N3 *2^96 + N2 *2^64 + N1 *2^32 + N0 *2^0 // 128-bit dividend + * T = T3 *2^-32 + T2 *2^-64 + T1 *2^-96 + T0 *2^-128 // 128-bit divisor reciprocal, 1/10 * 2^-128 + * + * N * T = N3*T3 *2^64 + N2*T3 *2^32 + N1*T3 *2^0 + N0*T3 *2^-32 + * + N3*T2 *2^32 + N2*T2 *2^0 + N1*T2 *2^-32 + N0*T2 *2^-64 + * + N3*T1 *2^0 + N2*T1 *2^-32 + N1*T1 *2^-64 + N0*T1 *2^-96 + * + N3*T0 *2^-32 + N2*T0 *2^-64 + N1*T0 *2^-96 + N0*T0 *2^-128 + * + * Q3=carry Q2=^+carry Q1=^+carry Q0=^+carry fraction=^... + * + * Q = Q3 *2^96 + Q2 *2^64 + Q1 *2^32 + Q0 *2^0 // 128-bit quotient + */ +static void +ecma_uint128_div10 (ecma_uint128_t *num_p) +{ + /* estimation of reciprocal of 10, 128 bits right of the binary point (T1 == T2) */ + const uint64_t tenth_l = 0x9999999aul; + const uint64_t tenth_m = 0x99999999ul; + const uint64_t tenth_h = 0x19999999ul; + + const uint64_t l0 = ((uint32_t) num_p->lo) * tenth_l; + const uint64_t l1 = (num_p->lo >> 32u) * tenth_l; + const uint64_t l2 = ((uint32_t) num_p->hi) * tenth_l; + const uint64_t l3 = (num_p->hi >> 32u) * tenth_l; + const uint64_t m0 = ((uint32_t) num_p->lo) * tenth_m; + const uint64_t m1 = (num_p->lo >> 32u) * tenth_m; + const uint64_t m2 = ((uint32_t) num_p->hi) * tenth_m; + const uint64_t m3 = (num_p->hi >> 32u) * tenth_m; + const uint64_t h0 = ((uint32_t) num_p->lo) * tenth_h; + const uint64_t h1 = (num_p->lo >> 32u) * tenth_h; + const uint64_t h2 = ((uint32_t) num_p->hi) * tenth_h; + const uint64_t h3 = (num_p->hi >> 32u) * tenth_h; + + uint64_t q0 = l0 >> 32u; + q0 += (uint32_t) l1; + q0 += (uint32_t) m0; + + q0 >>= 32u; + q0 += l1 >> 32u; + q0 += m0 >> 32u; + q0 += (uint32_t) l2; + q0 += (uint32_t) m1; + q0 += (uint32_t) m0; + + q0 >>= 32u; + q0 += l2 >> 32u; + q0 += m1 >> 32u; + q0 += m0 >> 32u; + q0 += (uint32_t) l3; + q0 += (uint32_t) m2; + q0 += (uint32_t) m1; + q0 += (uint32_t) h0; + + q0 >>= 32u; + q0 += l3 >> 32u; + q0 += m2 >> 32u; + q0 += m1 >> 32u; + q0 += h0 >> 32u; + q0 += (uint32_t) m3; + q0 += (uint32_t) m2; + q0 += (uint32_t) h1; + + uint64_t q1 = q0 >> 32u; + q1 += m3 >> 32u; + q1 += m2 >> 32u; + q1 += h1 >> 32u; + q1 += (uint32_t) m3; + q1 += (uint32_t) h2; + + uint64_t q32 = q1 >> 32u; + q32 += m3 >> 32u; + q32 += h2 >> 32u; + q32 += h3; + + num_p->lo = (q1 << 32u) | ((uint32_t) q0); + num_p->hi = q32; +} /* ecma_uint128_div10 */ + +/** + * Count leading zeros in a 64-bit integer. The behaviour is undefined for 0. + * + * @return number of leading zeros. + */ +inline static int JERRY_ATTR_CONST +ecma_uint64_clz (uint64_t n) /**< integer to count leading zeros in */ +{ +#if defined(__GNUC__) || defined(__clang__) + return __builtin_clzll (n); +#else /* !defined (__GNUC__) && !defined (__clang__) */ + JERRY_ASSERT (n != 0); + + int cnt = 0; + uint64_t one = 0x8000000000000000ull; + + while ((n & one) == 0) + { + cnt++; + one >>= 1; + } + + return cnt; +#endif /* !defined (__GNUC__) && !defined (__clang__) */ +} /* ecma_uint64_clz */ + +/** + * Count leading zeros in the top 4 bits of a 64-bit integer. + * + * @return number of leading zeros in top 4 bits. + */ +inline static int JERRY_ATTR_CONST +ecma_uint64_clz_top4 (uint64_t n) /**< integer to count leading zeros in */ +{ + static const uint8_t ecma_uint4_clz[] = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; + return ecma_uint4_clz[n >> 60]; +} /* ecma_uint64_clz */ + +/** + * Shift required to clear 4 bits of a 64-bit integer. + * + * @return 0-4 + */ +inline static int JERRY_ATTR_CONST +ecma_uint64_normalize_shift (uint64_t n) /**< integer to count leading zeros in */ +{ + static const uint8_t ecma_uint4_shift[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 }; + + return ecma_uint4_shift[n >> 60]; +} /* ecma_uint64_normalize_shift */ + +/** + * @} + */ + +/** + * Number.MAX_VALUE exponent part when using 64 bit float representation. + */ +#define NUMBER_MAX_DECIMAL_EXPONENT 308 +/** + * Number.MIN_VALUE exponent part when using 64 bit float representation. + */ +#define NUMBER_MIN_DECIMAL_EXPONENT -324 + +#elif !JERRY_NUMBER_TYPE_FLOAT64 + +/** + * Number.MAX_VALUE exponent part when using 32 bit float representation. + */ +#define NUMBER_MAX_DECIMAL_EXPONENT 38 +/** + * Number.MIN_VALUE exponent part when using 32 bit float representation. + */ +#define NUMBER_MIN_DECIMAL_EXPONENT -45 + +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Value of epsilon + */ +#define EPSILON 0.0000001 + +/** + * ECMA-defined conversion from string to number for different radixes (2, 8, 16). + * + * See also: + * ECMA-262 v5 9.3.1 + * ECMA-262 v6 7.1.3.1 + * + * @return NaN - if the conversion fails + * converted number - otherwise + */ +ecma_number_t +ecma_utf8_string_to_number_by_radix (const lit_utf8_byte_t *str_p, /**< utf-8 string */ + const lit_utf8_size_t string_size, /**< end of utf-8 string */ + uint32_t radix, /**< radix */ + uint32_t options) /**< option flags */ +{ + JERRY_ASSERT (radix == 2 || radix == 8 || radix == 16); + JERRY_ASSERT (*str_p == LIT_CHAR_0); + + const lit_utf8_byte_t *end_p = str_p + string_size; + + /* Skip leading zero */ + str_p++; + + if (radix != 8 || LEXER_TO_ASCII_LOWERCASE (*str_p) == LIT_CHAR_LOWERCASE_O) + { + /* Skip radix specifier */ + str_p++; + } + + ecma_number_t num = ECMA_NUMBER_ZERO; + + while (str_p < end_p) + { + lit_utf8_byte_t digit = *str_p++; + + if (digit == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE)) + { + continue; + } + + if (!lit_char_is_hex_digit (digit)) + { + return ecma_number_make_nan (); + } + + uint32_t value = lit_char_hex_to_int (digit); + + if (value >= radix) + { + return ecma_number_make_nan (); + } + + num = num * radix + value; + } + + return num; +} /* ecma_utf8_string_to_number_by_radix */ + +/** + * ECMA-defined conversion of string to Number. + * + * See also: + * ECMA-262 v5, 9.3.1 + * + * @return NaN - if the conversion fails + * converted number - otherwise + */ +ecma_number_t +ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */ + lit_utf8_size_t str_size, /**< string size */ + uint32_t options) /**< allowing underscore option bit */ +{ + ecma_string_trim_helper (&str_p, &str_size); + const lit_utf8_byte_t *end_p = str_p + str_size; + + if (str_size == 0) + { + return ECMA_NUMBER_ZERO; + } + + bool sign = false; + + if (str_p + 2 < end_p && str_p[0] == LIT_CHAR_0) + { + uint8_t radix = lit_char_to_radix (str_p[1]); + + if (radix != 10) + { + return ecma_utf8_string_to_number_by_radix (str_p, str_size, radix, options); + } + } + + if (*str_p == LIT_CHAR_PLUS) + { + str_p++; + } + else if (*str_p == LIT_CHAR_MINUS) + { + sign = true; + str_p++; + } + + /* Check if string is equal to "Infinity". */ + const lit_utf8_byte_t *infinity_str_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING_INFINITY_UL); + const lit_utf8_size_t infinity_length = lit_get_magic_string_size (LIT_MAGIC_STRING_INFINITY_UL); + + if ((lit_utf8_size_t) (end_p - str_p) == infinity_length && memcmp (infinity_str_p, str_p, infinity_length) == 0) + { + return ecma_number_make_infinity (sign); + } + + uint64_t significand = 0; + uint32_t digit_count = 0; + int32_t decimal_exponent = 0; + bool has_significand = false; + + /* Parsing integer part */ + while (str_p < end_p) + { + if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE)) + { + str_p++; + continue; + } + + if (!lit_char_is_decimal_digit (*str_p)) + { + break; + } + + has_significand = true; + uint32_t digit_value = (uint32_t) (*str_p++ - LIT_CHAR_0); + + if (digit_count == 0 && digit_value == 0) + { + /* Leading zeros are omitted. */ + continue; + } + + if (digit_count >= ECMA_NUMBER_MAX_DIGITS) + { + decimal_exponent++; + continue; + } + + significand = significand * 10 + digit_value; + digit_count++; + } + + /* Parse fraction part */ + if (str_p < end_p && *str_p == LIT_CHAR_DOT) + { + str_p++; + + while (str_p < end_p) + { + if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE)) + { + str_p++; + continue; + } + + if (!lit_char_is_decimal_digit (*str_p)) + { + break; + } + + has_significand = true; + uint32_t digit_value = (uint32_t) (*str_p++ - LIT_CHAR_0); + + if (digit_count == 0 && digit_value == 0) + { + /* Leading zeros are omitted. */ + decimal_exponent--; + continue; + } + + if (digit_count < ECMA_NUMBER_MAX_DIGITS) + { + significand = significand * 10 + digit_value; + digit_count++; + decimal_exponent--; + } + } + } + + /* Parsing exponent */ + if (str_p < end_p && LEXER_TO_ASCII_LOWERCASE (*str_p) == LIT_CHAR_LOWERCASE_E) + { + str_p++; + + int32_t exponent = 0; + int32_t exponent_sign = 1; + + if (str_p >= end_p) + { + return ecma_number_make_nan (); + } + + if (*str_p == LIT_CHAR_PLUS) + { + str_p++; + } + else if (*str_p == LIT_CHAR_MINUS) + { + exponent_sign = -1; + str_p++; + } + + if (str_p >= end_p || !lit_char_is_decimal_digit (*str_p)) + { + return ecma_number_make_nan (); + } + + while (str_p < end_p) + { + if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE)) + { + str_p++; + continue; + } + + if (!lit_char_is_decimal_digit (*str_p)) + { + break; + } + + int32_t digit_value = (*str_p++ - LIT_CHAR_0); + exponent = exponent * 10 + digit_value; + + if (exponent_sign * exponent > NUMBER_MAX_DECIMAL_EXPONENT) + { + return ecma_number_make_infinity (sign); + } + + if (exponent_sign * exponent < NUMBER_MIN_DECIMAL_EXPONENT) + { + return sign ? -ECMA_NUMBER_ZERO : ECMA_NUMBER_ZERO; + } + } + + decimal_exponent += exponent_sign * exponent; + } + + if (!has_significand || str_p < end_p) + { + return ecma_number_make_nan (); + } + + if (significand == 0) + { + return sign ? -ECMA_NUMBER_ZERO : ECMA_NUMBER_ZERO; + } + +#if JERRY_NUMBER_TYPE_FLOAT64 + /* + * 128-bit mantissa storage + * + * Normalized: |4 bits zero|124-bit mantissa with highest bit set to 1| + */ + ecma_uint128_t significand_uint128 = { significand, 0 }; + + /* Normalizing mantissa */ + int shift = 4 - ecma_uint64_clz (significand_uint128.hi); + + if (shift < 0) + { + ecma_uint128_shift_left (&significand_uint128, -shift); + } + else + { + ecma_uint128_shift_right (&significand_uint128, shift); + } + + int32_t binary_exponent = ECMA_NUMBER_FRACTION_WIDTH + shift; + + while (decimal_exponent > 0) + { + JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) == 4); + + ecma_uint128_mul10 (&significand_uint128); + decimal_exponent--; + + /* Re-normalizing mantissa */ + shift = ecma_uint64_normalize_shift (significand_uint128.hi); + JERRY_ASSERT (shift >= 0 && shift <= 4); + + ecma_uint128_shift_right (&significand_uint128, shift); + binary_exponent += shift; + } + + while (decimal_exponent < 0) + { + /* Denormalizing mantissa, moving highest 1 to bit 127 */ + JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) <= 4); + shift = ecma_uint64_clz_top4 (significand_uint128.hi); + JERRY_ASSERT (shift >= 0 && shift <= 4); + + ecma_uint128_shift_left (&significand_uint128, shift); + binary_exponent -= shift; + + ecma_uint128_div10 (&significand_uint128); + decimal_exponent++; + } + + /* + * Preparing mantissa for conversion to 52-bit representation, converting it to: + * + * |11 zero bits|1|116 mantissa bits| + */ + JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) <= 4); + shift = 11 - ecma_uint64_clz_top4 (significand_uint128.hi); + ecma_uint128_shift_right (&significand_uint128, shift); + binary_exponent += shift; + + JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) == 11); + + binary_exponent += ECMA_NUMBER_EXPONENT_BIAS; + + /* Handle denormal numbers */ + if (binary_exponent < 1) + { + ecma_uint128_shift_right (&significand_uint128, -binary_exponent + 1); + binary_exponent = 0; + } + + significand = ecma_round_high_to_uint64 (&significand_uint128); + + if (significand >= 1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) + { + /* Rounding carried over to the most significant bit, re-normalize. + * No need to shift mantissa right, as the low 52 bits will be 0 regardless. */ + binary_exponent++; + } + + if (binary_exponent >= ((1 << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)) + { + return ecma_number_make_infinity (sign); + } + + /* Mask low 52 bits. */ + significand &= ((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1); + + JERRY_ASSERT (binary_exponent < (1 << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1); + JERRY_ASSERT (significand < (1ull << ECMA_NUMBER_FRACTION_WIDTH)); + + return ecma_number_create (sign, (uint32_t) binary_exponent, significand); +#elif !JERRY_NUMBER_TYPE_FLOAT64 + /* Less precise conversion */ + ecma_number_t num = (ecma_number_t) (uint32_t) fraction_uint64; + + ecma_number_t m = e_sign ? (ecma_number_t) 0.1 : (ecma_number_t) 10.0; + + while (e) + { + if (e % 2) + { + num *= m; + } + + m *= m; + e /= 2; + } + + return num; +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +} /* ecma_utf8_string_to_number */ + +/** + * ECMA-defined conversion of UInt32 to String (zero-terminated). + * + * See also: + * ECMA-262 v5, 9.8.1 + * + * @return number of bytes copied to buffer + */ +lit_utf8_size_t +ecma_uint32_to_utf8_string (uint32_t value, /**< value to convert */ + lit_utf8_byte_t *out_buffer_p, /**< buffer for string */ + lit_utf8_size_t buffer_size) /**< size of buffer */ +{ + lit_utf8_byte_t *buf_p = out_buffer_p + buffer_size; + + do + { + JERRY_ASSERT (buf_p >= out_buffer_p); + + buf_p--; + *buf_p = (lit_utf8_byte_t) ((value % 10) + LIT_CHAR_0); + value /= 10; + } while (value != 0); + + JERRY_ASSERT (buf_p >= out_buffer_p); + + lit_utf8_size_t bytes_copied = (lit_utf8_size_t) (out_buffer_p + buffer_size - buf_p); + + if (JERRY_LIKELY (buf_p != out_buffer_p)) + { + memmove (out_buffer_p, buf_p, bytes_copied); + } + + return bytes_copied; +} /* ecma_uint32_to_utf8_string */ + +/** + * ECMA-defined conversion of Number value to UInt32 value + * + * See also: + * ECMA-262 v5, 9.6 + * + * @return 32-bit unsigned integer - result of conversion. + */ +uint32_t +ecma_number_to_uint32 (ecma_number_t num) /**< ecma-number */ +{ + if (JERRY_UNLIKELY (ecma_number_is_zero (num) || !ecma_number_is_finite (num))) + { + return 0; + } + + const bool sign = ecma_number_is_negative (num); + const ecma_number_t abs_num = sign ? -num : num; + + /* 2 ^ 32 */ + const uint64_t uint64_2_pow_32 = (1ull << 32); + + const ecma_number_t num_2_pow_32 = (float) uint64_2_pow_32; + + ecma_number_t num_in_uint32_range; + + if (abs_num >= num_2_pow_32) + { + num_in_uint32_range = ecma_number_remainder (abs_num, num_2_pow_32); + } + else + { + num_in_uint32_range = abs_num; + } + + /* Check that the floating point value can be represented with uint32_t. */ + JERRY_ASSERT (num_in_uint32_range < uint64_2_pow_32); + uint32_t uint32_num = (uint32_t) num_in_uint32_range; + + const uint32_t ret = sign ? (uint32_t)(-(int32_t)uint32_num) : uint32_num; + +#ifndef JERRY_NDEBUG + if (sign && uint32_num != 0) + { + JERRY_ASSERT (ret == uint64_2_pow_32 - uint32_num); + } + else + { + JERRY_ASSERT (ret == uint32_num); + } +#endif /* !JERRY_NDEBUG */ + + return ret; +} /* ecma_number_to_uint32 */ + +/** + * ECMA-defined conversion of Number value to Int32 value + * + * See also: + * ECMA-262 v5, 9.5 + * + * @return 32-bit signed integer - result of conversion. + */ +int32_t +ecma_number_to_int32 (ecma_number_t num) /**< ecma-number */ +{ + uint32_t uint32_num = ecma_number_to_uint32 (num); + + /* 2 ^ 32 */ + const int64_t int64_2_pow_32 = (1ll << 32); + + /* 2 ^ 31 */ + const uint32_t uint32_2_pow_31 = (1ull << 31); + + int32_t ret; + + if (uint32_num >= uint32_2_pow_31) + { + ret = (int32_t) (uint32_num - int64_2_pow_32); + } + else + { + ret = (int32_t) uint32_num; + } + +#ifndef JERRY_NDEBUG + int64_t int64_num = uint32_num; + + JERRY_ASSERT (int64_num >= 0); + + if (int64_num >= uint32_2_pow_31) + { + JERRY_ASSERT (ret == int64_num - int64_2_pow_32); + } + else + { + JERRY_ASSERT (ret == int64_num); + } +#endif /* !JERRY_NDEBUG */ + + return ret; +} /* ecma_number_to_int32 */ + +/** + * Perform conversion of ecma-number to decimal representation with decimal exponent. + * + * Note: + * The calculated values correspond to s, n, k parameters in ECMA-262 v5, 9.8.1, item 5: + * - parameter out_digits_p corresponds to s, the digits of the number; + * - parameter out_decimal_exp_p corresponds to n, the decimal exponent; + * - return value corresponds to k, the number of digits. + * + * @return the number of digits + */ +lit_utf8_size_t +ecma_number_to_decimal (ecma_number_t num, /**< ecma-number */ + lit_utf8_byte_t *out_digits_p, /**< [out] buffer to fill with digits */ + int32_t *out_decimal_exp_p) /**< [out] decimal exponent */ +{ + JERRY_ASSERT (!ecma_number_is_nan (num)); + JERRY_ASSERT (!ecma_number_is_zero (num)); + JERRY_ASSERT (!ecma_number_is_infinity (num)); + JERRY_ASSERT (!ecma_number_is_negative (num)); + + return ecma_errol0_dtoa ((double) num, out_digits_p, out_decimal_exp_p); +} /* ecma_number_to_decimal */ + +/** + * Convert ecma-number to zero-terminated string + * + * See also: + * ECMA-262 v5, 9.8.1 + * + * + * @return size of utf-8 string + */ +lit_utf8_size_t +ecma_number_to_utf8_string (ecma_number_t num, /**< ecma-number */ + lit_utf8_byte_t *buffer_p, /**< buffer for utf-8 string */ + lit_utf8_size_t buffer_size) /**< size of buffer */ +{ + lit_utf8_byte_t *dst_p; + + if (ecma_number_is_nan (num)) + { + /* 1. */ + dst_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_NAN, buffer_p, buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + if (ecma_number_is_zero (num)) + { + /* 2. */ + *buffer_p = LIT_CHAR_0; + JERRY_ASSERT (1 <= buffer_size); + return 1; + } + + dst_p = buffer_p; + + if (ecma_number_is_negative (num)) + { + /* 3. */ + *dst_p++ = LIT_CHAR_MINUS; + num = -num; + } + + if (ecma_number_is_infinity (num)) + { + /* 4. */ + dst_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_INFINITY_UL, + dst_p, + (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + /* 5. */ + uint32_t num_uint32 = ecma_number_to_uint32 (num); + + if (((ecma_number_t) num_uint32) == num) + { + dst_p += ecma_uint32_to_utf8_string (num_uint32, dst_p, (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + /* decimal exponent */ + int32_t n; + /* number of digits in mantissa */ + int32_t k; + + k = (int32_t) ecma_number_to_decimal (num, dst_p, &n); + + if (k <= n && n <= 21) + { + /* 6. */ + dst_p += k; + + memset (dst_p, LIT_CHAR_0, (size_t) (n - k)); + dst_p += n - k; + + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + if (0 < n && n <= 21) + { + /* 7. */ + memmove (dst_p + n + 1, dst_p + n, (size_t) (k - n)); + *(dst_p + n) = LIT_CHAR_DOT; + dst_p += k + 1; + + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + if (-6 < n && n <= 0) + { + /* 8. */ + memmove (dst_p + 2 - n, dst_p, (size_t) k); + memset (dst_p + 2, LIT_CHAR_0, (size_t) -n); + *dst_p = LIT_CHAR_0; + *(dst_p + 1) = LIT_CHAR_DOT; + dst_p += k - n + 2; + + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + if (k == 1) + { + /* 9. */ + dst_p++; + } + else + { + /* 10. */ + memmove (dst_p + 2, dst_p + 1, (size_t) (k - 1)); + *(dst_p + 1) = LIT_CHAR_DOT; + dst_p += k + 1; + } + + /* 9., 10. */ + *dst_p++ = LIT_CHAR_LOWERCASE_E; + *dst_p++ = (n >= 1) ? LIT_CHAR_PLUS : LIT_CHAR_MINUS; + uint32_t t = (uint32_t) (n >= 1 ? (n - 1) : -(n - 1)); + + dst_p += ecma_uint32_to_utf8_string (t, dst_p, (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); + + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + + return (lit_utf8_size_t) (dst_p - buffer_p); +} /* ecma_number_to_utf8_string */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-errol.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-errol.cpp new file mode 100644 index 00000000..07932429 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-errol.cpp @@ -0,0 +1,245 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is based on work under the following copyright and permission + * notice: + * + * Copyright (c) 2016 Marc Andrysco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +#include "ecma-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +/** + * Printing Floating-Point Numbers + * + * available at http://cseweb.ucsd.edu/~mandrysc/pub/dtoa.pdf + */ + +/** + * Floating point format definitions (next float value) + */ +#define ECMA_NEXT_FLOAT(value) (nextafter ((value), INFINITY)) +/** + * Floating point format definitions (previous float value) + */ +#define ECMA_PREV_FLOAT(value) (nextafter ((value), -INFINITY)) + +/** + * Value of epsilon + */ +#define ERROL0_EPSILON 0.0000001 + +/** + * High-precision data structure. + */ +typedef struct +{ + double value; /**< value */ + double offset; /**< offset */ +} ecma_high_prec_t; + +/** + * Normalize the number by factoring in the error. + * + * @return void + */ +static inline void +ecma_normalize_high_prec_data (ecma_high_prec_t *hp_data_p) /**< [in, out] float pair */ +{ + double val = hp_data_p->value; + + hp_data_p->value += hp_data_p->offset; + hp_data_p->offset += val - hp_data_p->value; +} /* ecma_normalize_high_prec_data */ + +/** + * Multiply the high-precision number by ten. + * + * @return void + */ +static inline void +ecma_multiply_high_prec_by_10 (ecma_high_prec_t *hp_data_p) /**< [in, out] high-precision number */ +{ + double value = hp_data_p->value; + + hp_data_p->value *= 10.0; + hp_data_p->offset *= 10.0; + + double offset = hp_data_p->value; + + offset -= value * 8.0; + offset -= value * 2.0; + + hp_data_p->offset -= offset; + + ecma_normalize_high_prec_data (hp_data_p); +} /* ecma_multiply_high_prec_by_10 */ + +/** + * Divide the high-precision number by ten. + */ +static void +ecma_divide_high_prec_by_10 (ecma_high_prec_t *hp_data_p) /**< [in, out] high-precision number */ +{ + double value = hp_data_p->value; + + hp_data_p->value /= 10.0; + hp_data_p->offset /= 10.0; + + value -= hp_data_p->value * 8.0; + value -= hp_data_p->value * 2.0; + + hp_data_p->offset += value / 10.0; + + ecma_normalize_high_prec_data (hp_data_p); +} /* ecma_divide_high_prec_by_10 */ + +/** + * Errol0 double to ASCII conversion, guaranteed correct but possibly not optimal. + * + * @return number of generated digits + */ +lit_utf8_size_t +ecma_errol0_dtoa (double val, /**< ecma number */ + lit_utf8_byte_t *buffer_p, /**< buffer to generate digits into */ + int32_t *exp_p) /**< [out] exponent */ +{ + double power_of_10 = 1.0; + int32_t exponent = 1; + + /* normalize the midpoint */ + ecma_high_prec_t mid; + + mid.value = val; + mid.offset = 0.0; + + while (((mid.value > 10.0) || ((mid.value == 10.0) && (mid.offset >= 0.0))) && (exponent < 308)) + { + exponent++; + ecma_divide_high_prec_by_10 (&mid); + power_of_10 /= 10.0; + } + + while (((mid.value < 1.0) || ((mid.value == 1.0) && (mid.offset < 0.0))) && (exponent > -307)) + { + exponent--; + ecma_multiply_high_prec_by_10 (&mid); + power_of_10 *= 10.0; + } + + ecma_high_prec_t high_bound, low_bound; + + high_bound.value = mid.value; + high_bound.offset = mid.offset; + + if (ECMA_NEXT_FLOAT (val) != INFINITY) + { + high_bound.offset += (ECMA_NEXT_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON); + } + + low_bound.value = mid.value; + low_bound.offset = mid.offset + (ECMA_PREV_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON); + + ecma_normalize_high_prec_data (&high_bound); + ecma_normalize_high_prec_data (&low_bound); + + /* normalized boundaries */ + + while (high_bound.value > 10.0 || (high_bound.value == 10.0 && (high_bound.offset >= 0.0))) + { + exponent++; + ecma_divide_high_prec_by_10 (&high_bound); + ecma_divide_high_prec_by_10 (&low_bound); + } + + while (high_bound.value < 1.0 || (high_bound.value == 1.0 && (high_bound.offset < 0.0))) + { + exponent--; + ecma_multiply_high_prec_by_10 (&high_bound); + ecma_multiply_high_prec_by_10 (&low_bound); + } + + /* digit generation */ + + lit_utf8_byte_t *dst_p = buffer_p; + + while (high_bound.value != 0.0 || high_bound.offset != 0.0) + { + uint8_t high_digit = (uint8_t) high_bound.value; + + if ((high_bound.value == high_digit) && (high_bound.offset < 0)) + { + high_digit = (uint8_t) (high_digit - 1u); + } + + uint8_t low_digit = (uint8_t) low_bound.value; + + if ((low_bound.value == low_digit) && (low_bound.offset < 0)) + { + low_digit = (uint8_t) (low_digit - 1u); + } + + if (low_digit != high_digit) + { + break; + } + + *dst_p++ = (lit_utf8_byte_t) ('0' + high_digit); + + high_bound.value -= high_digit; + ecma_multiply_high_prec_by_10 (&high_bound); + + low_bound.value -= low_digit; + ecma_multiply_high_prec_by_10 (&low_bound); + } + + double mdig = (high_bound.value + low_bound.value) / 2.0 + 0.5; + *dst_p++ = (lit_utf8_byte_t) ('0' + (uint8_t) mdig); + + *exp_p = exponent; + + return (lit_utf8_size_t) (dst_p - buffer_p); +} /* ecma_errol0_dtoa */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp new file mode 100644 index 00000000..66d542a0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp @@ -0,0 +1,334 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +/** + * Create a native pointer property to store the native pointer and its type info. + * + * @return true - if property was just created with specified value, + * false - otherwise, if property existed before the call, it's value was updated + */ +bool +ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create property in */ + void *native_p, /**< native pointer */ + const jerry_object_native_info_t *native_info_p) /**< native type info */ +{ + ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); + + if (native_info_p != NULL && native_info_p->number_of_references > 0) + { + name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES); + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_fast_array_convert_to_normal (obj_p); + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); + + bool is_new = (property_p == NULL); + + ecma_native_pointer_t *native_pointer_p; + + if (property_p == NULL) + { + native_pointer_p = (ecma_native_pointer_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); + + ecma_property_value_t *value_p; + ECMA_CREATE_INTERNAL_PROPERTY (obj_p, name_p, property_p, value_p); + + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p); + *property_p |= ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + } + else if (*property_p & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL) + { + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value); + + if (native_pointer_p->native_info_p == native_info_p) + { + native_pointer_p->native_p = native_p; + return false; + } + + value_p->value = JMEM_CP_NULL; + (void) value_p->value; /* Make cppcheck happy. */ + *property_p &= (ecma_property_t) ~ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + + ecma_native_pointer_chain_t *item_p; + item_p = (ecma_native_pointer_chain_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_chain_t)); + item_p->data = *native_pointer_p; + + jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); + + item_p->next_p = (ecma_native_pointer_chain_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_chain_t)); + item_p->next_p->next_p = NULL; + + native_pointer_p = &item_p->next_p->data; + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, item_p); + } + else + { + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (value_p->value == JMEM_CP_NULL) + { + native_pointer_p = (ecma_native_pointer_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p); + + *property_p |= ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + } + else + { + ecma_native_pointer_chain_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value_p->value); + + /* There should be at least 2 native pointers in the chain */ + JERRY_ASSERT (item_p != NULL && item_p->next_p != NULL); + + while (true) + { + if (item_p->data.native_info_p == native_info_p) + { + /* The native info already exists -> update the corresponding data */ + item_p->data.native_p = native_p; + return false; + } + + if (item_p->next_p == NULL) + { + /* The native info does not exist -> append a new element to the chain */ + break; + } + + item_p = item_p->next_p; + } + + ecma_native_pointer_chain_t *new_item_p; + + new_item_p = (ecma_native_pointer_chain_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_chain_t)); + item_p->next_p = new_item_p; + new_item_p->next_p = NULL; + + native_pointer_p = &new_item_p->data; + } + } + + native_pointer_p->native_p = native_p; + native_pointer_p->native_info_p = (jerry_object_native_info_t *) native_info_p; + + return is_new; +} /* ecma_create_native_pointer_property */ + +/** + * Get value of native package stored in the object's property with specified identifier + * + * Note: + * property identifier should be one of the following: + * - LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER + * + * @return native pointer data if property exists + * NULL otherwise + */ +ecma_native_pointer_t * +ecma_get_native_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */ + const jerry_object_native_info_t *native_info_p) /**< native type info */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + /* Fast access mode array can not have native pointer properties */ + return NULL; + } + + ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); + + if (native_info_p != NULL && native_info_p->number_of_references > 0) + { + name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES); + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); + + if (property_p == NULL) + { + return NULL; + } + + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (JERRY_LIKELY (*property_p & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)) + { + ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value); + + if (native_pointer_p->native_info_p == native_info_p) + { + return native_pointer_p; + } + + return NULL; + } + + if (value_p->value == JMEM_CP_NULL) + { + return NULL; + } + + ecma_native_pointer_chain_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value_p->value); + + /* There should be at least 2 native pointers in the chain */ + JERRY_ASSERT (item_p != NULL && item_p->next_p != NULL); + + do + { + if (item_p->data.native_info_p == native_info_p) + { + return &item_p->data; + } + + item_p = item_p->next_p; + } while (item_p != NULL); + + return NULL; +} /* ecma_get_native_pointer_value */ + +/** + * Delete the previously set native pointer by the native type info from the specified object. + * + * Note: + * If the specified object has no matching native pointer for the given native type info + * the function has no effect. + * + * @return true - if the native pointer has been deleted succesfully + * false - otherwise + */ +bool +ecma_delete_native_pointer_property (ecma_object_t *obj_p, /**< object to delete property from */ + const jerry_object_native_info_t *native_info_p) /**< native type info */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + /* Fast access mode array can not have native pointer properties */ + return false; + } + + ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); + + if (native_info_p != NULL && native_info_p->number_of_references > 0) + { + name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES); + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); + + if (property_p == NULL) + { + return false; + } + + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (JERRY_LIKELY (*property_p & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)) + { + ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value); + + if (native_pointer_p->native_info_p != native_info_p) + { + return false; + } + + value_p->value = JMEM_CP_NULL; + *property_p &= (ecma_property_t) ~ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); + return true; + } + + if (value_p->value == JMEM_CP_NULL) + { + return false; + } + + ecma_native_pointer_chain_t *first_p; + first_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value_p->value); + + /* There should be at least 2 native pointers in the chain */ + JERRY_ASSERT (first_p != NULL && first_p->next_p != NULL); + + ecma_native_pointer_chain_t *item_p = first_p; + ecma_native_pointer_chain_t *prev_p = NULL; + + do + { + if (item_p->data.native_info_p == native_info_p) + { + if (prev_p == NULL) + { + /* The first element is deleted from the chain: change the property value. */ + first_p = item_p->next_p; + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, first_p); + } + else + { + /* A non-first element is deleted from the chain: update the previous pointer. */ + prev_p->next_p = item_p->next_p; + } + + jmem_heap_free_block (item_p, sizeof (ecma_native_pointer_chain_t)); + + if (first_p->next_p != NULL) + { + return true; + } + + /* Only one item remained. The ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL flag is + * set early to avoid using the chain if the allocation below triggers a GC. */ + *property_p |= ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + + ecma_native_pointer_t *native_pointer_p; + native_pointer_p = (ecma_native_pointer_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); + *native_pointer_p = first_p->data; + + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p); + + jmem_heap_free_block (first_p, sizeof (ecma_native_pointer_chain_t)); + return true; + } + + prev_p = item_p; + item_p = item_p->next_p; + } while (item_p != NULL); + + return false; +} /* ecma_delete_native_pointer_property */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.cpp new file mode 100644 index 00000000..cde5524d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.cpp @@ -0,0 +1,677 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-helpers-number.h" + +#include + +#include "ecma-conversion.h" + +#include "lit-char-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +JERRY_STATIC_ASSERT ((sizeof (ecma_value_t) == sizeof (ecma_integer_value_t)), + size_of_ecma_value_t_must_be_equal_to_the_size_of_ecma_integer_value_t); + +JERRY_STATIC_ASSERT ((((int)ECMA_DIRECT_SHIFT) == (((int)ECMA_VALUE_SHIFT) + 1)), currently_directly_encoded_values_has_one_extra_flag); + +JERRY_STATIC_ASSERT ((((1 << (ECMA_DIRECT_SHIFT - 1)) | ECMA_TYPE_DIRECT) == ECMA_DIRECT_TYPE_SIMPLE_VALUE), + currently_directly_encoded_values_start_after_direct_type_simple_value); + +JERRY_STATIC_ASSERT ((sizeof (ecma_number_t) == sizeof (ecma_binary_num_t)), + size_of_ecma_number_t_must_be_equal_to_binary_representation); + +/** + * Convert an ecma-number to it's binary representation. + * + * @return binary representation + */ +ecma_binary_num_t JERRY_ATTR_CONST +ecma_number_to_binary (ecma_number_t number) /**< ecma number */ +{ + ecma_number_accessor_t f; + f.as_number = number; + + return f.as_binary; +} /* ecma_number_to_binary */ + +/** + * Convert a binary representation to the corresponding ecma-number. + * + * @return ecma-number + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_from_binary (ecma_binary_num_t binary) /**< binary representation */ +{ + ecma_number_accessor_t f; + f.as_binary = binary; + + return f.as_number; +} /* ecma_number_from_binary */ + +/** + * Check signedness of the binary number. + * + * @return true - if sign bit is set + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_number_sign (ecma_binary_num_t binary) /**< binary representation */ +{ + return (binary & ECMA_NUMBER_SIGN_BIT) != 0; +} /* ecma_number_sign */ + +/** + * Get biased exponent field of the binary number. + * + * @return unsigned integer value of the biased exponent field + */ +uint32_t JERRY_ATTR_CONST +ecma_number_biased_exp (ecma_binary_num_t binary) /**< binary representation */ +{ + return (uint32_t) ((binary & ~ECMA_NUMBER_SIGN_BIT) >> ECMA_NUMBER_FRACTION_WIDTH); +} /* ecma_number_biased_exp */ + +/** + * Get fraction field of the binary number. + * + * @return unsigned integer value of the fraction field + */ +uint64_t JERRY_ATTR_CONST +ecma_number_fraction (ecma_binary_num_t binary) /**< binary representation */ +{ + return binary & ((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1); +} /* ecma_number_fraction */ + +/** + * Packing sign, fraction and biased exponent to ecma-number + * + * @return ecma-number with specified sign, biased_exponent and fraction + */ +ecma_number_t +ecma_number_create (bool sign, /**< sign */ + uint32_t biased_exp, /**< biased exponent */ + uint64_t fraction) /**< fraction */ +{ + JERRY_ASSERT ((biased_exp & ~((1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)) == 0); + JERRY_ASSERT ((fraction & ~((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1)) == 0); + + ecma_binary_num_t binary = biased_exp; + binary <<= ECMA_NUMBER_FRACTION_WIDTH; + + binary |= fraction; + + if (sign) + { + binary |= ECMA_NUMBER_SIGN_BIT; + } + + return ecma_number_from_binary (binary); +} /* ecma_number_create */ + +/** + * Check if ecma-number is NaN + * + * @return true - if biased exponent is filled with 1 bits and + fraction is filled with anything but not all zero bits, + * false - otherwise + */ +bool +ecma_number_is_nan (ecma_number_t num) /**< ecma-number */ +{ + bool is_nan = (num != num); + +#ifndef JERRY_NDEBUG + /* IEEE-754 2008, 3.4, a */ + ecma_binary_num_t binary = ecma_number_to_binary (num); + bool is_nan_exponent = (ecma_number_biased_exp (binary) == (1 << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1); + bool is_nan_fraction = (ecma_number_fraction (binary) > 0); + + bool is_nan_ieee754 = is_nan_exponent && is_nan_fraction; + JERRY_ASSERT (is_nan == is_nan_ieee754); +#endif /* !JERRY_NDEBUG */ + + return is_nan; +} /* ecma_number_is_nan */ + +/** + * Make a NaN. + * + * @return NaN value + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_make_nan (void) +{ + ecma_number_accessor_t f; + f.as_binary = ECMA_NUMBER_BINARY_QNAN; + + return f.as_number; +} /* ecma_number_make_nan */ + +/** + * Make an Infinity. + * + * @return if !sign - +Infinity value, + * else - -Infinity value. + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_make_infinity (bool sign) /**< sign of the value */ +{ + ecma_number_accessor_t f; + f.as_binary = ECMA_NUMBER_BINARY_INF; + + if (sign) + { + f.as_binary |= ECMA_NUMBER_SIGN_BIT; + } + + return f.as_number; +} /* ecma_number_make_infinity */ + +/** + * Check if ecma-number is negative + * + * @return true - if sign bit of ecma-number is set + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_number_is_negative (ecma_number_t num) /**< ecma-number */ +{ + JERRY_ASSERT (!ecma_number_is_nan (num)); + + return (ecma_number_to_binary (num) & ECMA_NUMBER_SIGN_BIT) != 0; +} /* ecma_number_is_negative */ + +/** + * Check if ecma-number is zero + * + * @return true - if fraction is zero and biased exponent is zero, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_number_is_zero (ecma_number_t num) /**< ecma-number */ +{ + bool is_zero = (num == ECMA_NUMBER_ZERO); + +#ifndef JERRY_NDEBUG + bool is_zero_ieee754 = ((ecma_number_to_binary (num) & ~ECMA_NUMBER_SIGN_BIT) == 0); + JERRY_ASSERT (is_zero == is_zero_ieee754); +#endif /* !JERRY_NDEBUG */ + + return is_zero; +} /* ecma_number_is_zero */ + +/** + * Check if number is infinity + * + * @return true - if biased exponent is filled with 1 bits and + * fraction is filled with zero bits, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_number_is_infinity (ecma_number_t num) /**< ecma-number */ +{ + return (ecma_number_to_binary (num) & ~ECMA_NUMBER_SIGN_BIT) == ECMA_NUMBER_BINARY_INF; +} /* ecma_number_is_infinity */ + +/** + * Check if number is finite + * + * @return true - if number is finite + * false - if number is NaN or infinity + */ +bool JERRY_ATTR_CONST +ecma_number_is_finite (ecma_number_t num) /**< ecma-number */ +{ +#if defined(__GNUC__) || defined(__clang__) + return __builtin_isfinite (num); +#elif defined(_WIN32) + return isfinite (num); +#else /* !(defined(__GNUC__) || defined(__clang__) || defined(_WIN32)) */ + return !ecma_number_is_nan (num) && !ecma_number_is_infinity (num); +#endif /* defined (__GNUC__) || defined (__clang__) */ +} /* ecma_number_is_finite */ + +/** + * Get previous representable ecma-number + * + * @return maximum ecma-number that is less compared to passed argument + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_get_prev (ecma_number_t num) /**< ecma-number */ +{ +#if defined(__GNUC__) || defined(__clang__) + return __builtin_nextafter (num, -INFINITY); +#else /* !defined (__GNUC__) && !defined (__clang__) */ + JERRY_ASSERT (!ecma_number_is_nan (num)); + ecma_binary_num_t binary = ecma_number_to_binary (num); + + /* If -Infinity, return self */ + if (binary == (ECMA_NUMBER_SIGN_BIT | ECMA_NUMBER_BINARY_INF)) + { + return num; + } + + /* If +0.0, return -0.0 */ + if (binary == ECMA_NUMBER_BINARY_ZERO) + { + return -num; + } + + if (ecma_number_sign (binary)) + { + return ecma_number_from_binary (binary + 1); + } + + return ecma_number_from_binary (binary - 1); +#endif /* !defined (__GNUC__) && !defined (__clang__) */ +} /* ecma_number_get_prev */ + +/** + * Get next representable ecma-number + * + * @return minimum ecma-number that is greater compared to passed argument + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_get_next (ecma_number_t num) /**< ecma-number */ +{ +#if defined(__GNUC__) || defined(__clang__) + return __builtin_nextafter (num, INFINITY); +#else /* !defined (__GNUC__) && !defined (__clang__) */ + JERRY_ASSERT (!ecma_number_is_nan (num)); + ecma_binary_num_t binary = ecma_number_to_binary (num); + + /* If +Infinity, return self */ + if (binary == ECMA_NUMBER_BINARY_INF) + { + return num; + } + + /* If -0.0, return +0.0 */ + if (binary == (ECMA_NUMBER_SIGN_BIT | ECMA_NUMBER_BINARY_ZERO)) + { + return -num; + } + + if (ecma_number_sign (binary)) + { + return ecma_number_from_binary (binary - 1); + } + + return ecma_number_from_binary (binary + 1); +#endif /* !defined (__GNUC__) && !defined (__clang__) */ +} /* ecma_number_get_next */ + +/** + * Truncate fractional part of the number + * + * @return integer part of the number + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_trunc (ecma_number_t num) /**< ecma-number */ +{ + JERRY_ASSERT (!ecma_number_is_nan (num)); + + ecma_binary_num_t binary = ecma_number_to_binary (num); + uint32_t exponent = ecma_number_biased_exp (binary); + + if (exponent < ECMA_NUMBER_EXPONENT_BIAS) + { + return ECMA_NUMBER_ZERO; + } + + uint32_t unbiased_exp = exponent - ECMA_NUMBER_EXPONENT_BIAS; + + if (unbiased_exp >= ECMA_NUMBER_FRACTION_WIDTH) + { + return num; + } + + binary &= ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH - unbiased_exp)) - 1); + return ecma_number_from_binary (binary); +} /* ecma_number_trunc */ + +/** + * Calculate remainder of division of two numbers, + * as specified in ECMA-262 v5, 11.5.3, item 6. + * + * Note: + * operands shouldn't contain NaN, Infinity, or zero. + * + * @return number - calculated remainder. + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_remainder (ecma_number_t left_num, /**< left operand */ + ecma_number_t right_num) /**< right operand */ +{ + JERRY_ASSERT (ecma_number_is_finite (left_num) && !ecma_number_is_zero (left_num)); + JERRY_ASSERT (ecma_number_is_finite (right_num) && !ecma_number_is_zero (right_num)); + + const ecma_number_t q = ecma_number_trunc (left_num / right_num); + ecma_number_t r = left_num - right_num * q; + + if (ecma_number_is_zero (r) && ecma_number_is_negative (left_num)) + { + r = -r; + } + + return r; +} /* ecma_number_remainder */ + +/** + * Compute power operation according to the ES standard. + * + * @return x ** y + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_pow (ecma_number_t x, /**< left operand */ + ecma_number_t y) /**< right operand */ +{ + if (ecma_number_is_nan (y) || (ecma_number_is_infinity (y) && (x == ECMA_NUMBER_ONE || x == ECMA_NUMBER_MINUS_ONE))) + { + /* Handle differences between ES5.1 and ISO C standards for pow. */ + return ecma_number_make_nan (); + } + + if (ecma_number_is_zero (y)) + { + /* Handle differences between ES5.1 and ISO C standards for pow. */ + return ECMA_NUMBER_ONE; + } + + return DOUBLE_TO_ECMA_NUMBER_T (pow (x, y)); +} /* ecma_number_pow */ + +/** + * ECMA-integer number multiplication. + * + * @return number - result of multiplication. + */ +ecma_value_t JERRY_ATTR_CONST +ecma_integer_multiply (ecma_integer_value_t left_integer, /**< left operand */ + ecma_integer_value_t right_integer) /**< right operand */ +{ +#if defined(__GNUC__) || defined(__clang__) + /* Check if either integer is power of 2 */ + if (JERRY_UNLIKELY ((left_integer & (left_integer - 1)) == 0)) + { + /* Right shift right_integer with log2 (left_integer) */ + return ecma_make_integer_value ( + (int32_t) ((uint32_t) right_integer << (__builtin_ctz ((unsigned int) left_integer)))); + } + + if (JERRY_UNLIKELY ((right_integer & (right_integer - 1)) == 0)) + { + /* Right shift left_integer with log2 (right_integer) */ + return ecma_make_integer_value ( + (int32_t) ((uint32_t) left_integer << (__builtin_ctz ((unsigned int) right_integer)))); + } +#endif /* defined (__GNUC__) || defined (__clang__) */ + + return ecma_make_integer_value (left_integer * right_integer); +} /* ecma_integer_multiply */ + +/** + * The Number object's 'parseInt' routine + * + * See also: + * ECMA-262 v5, 15.1.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_number_parse_int (const lit_utf8_byte_t *str_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t str_size, /**< routine's first argument's + * string buffer's size */ + ecma_value_t radix_value) /**< routine's second argument */ +{ + /* 2. Remove leading whitespace. */ + ecma_string_trim_helper (&str_p, &str_size); + + if (str_size == 0) + { + return ecma_make_nan_value (); + } + + const lit_utf8_byte_t *str_end_p = str_p + str_size; + + /* 3. */ + bool sign = false; + + /* 4. */ + if (*str_p == LIT_CHAR_MINUS) + { + sign = true; + str_p++; + } + /* 5. */ + else if (*str_p == LIT_CHAR_PLUS) + { + str_p++; + } + + /* 6. */ + ecma_number_t radix_num; + radix_value = ecma_op_to_number (radix_value, &radix_num); + + if (ECMA_IS_VALUE_ERROR (radix_value)) + { + return ECMA_VALUE_ERROR; + } + + int32_t radix = ecma_number_to_int32 (radix_num); + + /* 7.*/ + bool strip_prefix = true; + + /* 8. */ + if (radix != 0) + { + /* 8.a */ + if (radix < 2 || radix > 36) + { + return ecma_make_nan_value (); + } + /* 8.b */ + else if (radix != 16) + { + strip_prefix = false; + } + } + /* 9. */ + else + { + radix = 10; + } + + /* 10. */ + if (strip_prefix && ((str_end_p - str_p) >= 2) && (str_p[0] == LIT_CHAR_0) + && (LEXER_TO_ASCII_LOWERCASE (str_p[1]) == LIT_CHAR_LOWERCASE_X)) + { + str_p += 2; + radix = 16; + } + + ecma_number_t value = ECMA_NUMBER_ZERO; + const lit_utf8_byte_t *digit_start_p = str_p; + + /* 11. Check if characters are in [0, Radix - 1]. We also convert them to number values in the process. */ + while (str_p < str_end_p) + { + ecma_char_t ch = *str_p; + + int32_t digit = 0; + + if (lit_char_is_decimal_digit (ch)) + { + digit = ch - LIT_CHAR_0; + } + else if (LEXER_TO_ASCII_LOWERCASE (ch) >= LIT_CHAR_LOWERCASE_A + && LEXER_TO_ASCII_LOWERCASE (ch) <= LIT_CHAR_LOWERCASE_Z) + { + digit = LEXER_TO_ASCII_LOWERCASE (ch) - LIT_CHAR_LOWERCASE_A + 10; + } + else + { + /* Not a valid digit char, set to invalid value */ + digit = radix; + } + + if (digit >= radix) + { + break; + } + + value *= radix; + value += digit; + + str_p++; + } + + /* 12. */ + if (str_p == digit_start_p) + { + return ecma_make_nan_value (); + } + + /* 15. */ + if (sign) + { + value *= ECMA_NUMBER_MINUS_ONE; + } + + return ecma_make_number_value (value); +} /* ecma_number_parse_int */ + +/** + * The Number object's 'parseFloat' routine + * + * See also: + * ECMA-262 v5, 15.1.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_number_parse_float (const lit_utf8_byte_t *str_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t str_size) /**< routine's first argument's + * string buffer's size */ +{ + /* 2. Remove leading whitespace. */ + ecma_string_trim_helper (&str_p, &str_size); + + const lit_utf8_byte_t *str_end_p = str_p + str_size; + bool sign = false; + + if (str_size == 0) + { + return ecma_make_nan_value (); + } + + if (*str_p == LIT_CHAR_PLUS) + { + str_p++; + } + else if (*str_p == LIT_CHAR_MINUS) + { + sign = true; + str_p++; + } + + /* Check if string is equal to "Infinity". */ + const lit_utf8_byte_t *infinity_str_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING_INFINITY_UL); + const lit_utf8_size_t infinity_length = lit_get_magic_string_size (LIT_MAGIC_STRING_INFINITY_UL); + + /* The input string should be at least the length of "Infinity" to be correctly processed as + * the infinity value. + */ + if ((lit_utf8_size_t) (str_end_p - str_p) >= infinity_length && memcmp (infinity_str_p, str_p, infinity_length) == 0) + { + return ecma_make_number_value (ecma_number_make_infinity (sign)); + } + + const lit_utf8_byte_t *num_start_p = str_p; + const lit_utf8_byte_t *num_end_p = str_p; + + while (str_p < str_end_p && lit_char_is_decimal_digit (*str_p)) + { + str_p++; + } + + if (str_p < str_end_p && *str_p == LIT_CHAR_DOT) + { + str_p++; + + while (str_p < str_end_p && lit_char_is_decimal_digit (*str_p)) + { + str_p++; + } + } + + num_end_p = str_p; + + if (str_p < str_end_p && LEXER_TO_ASCII_LOWERCASE (*str_p) == LIT_CHAR_LOWERCASE_E) + { + str_p++; + + if (str_p < str_end_p && (*str_p == LIT_CHAR_PLUS || *str_p == LIT_CHAR_MINUS)) + { + str_p++; + } + + if (str_p < str_end_p && lit_char_is_decimal_digit (*str_p)) + { + str_p++; + + while (str_p < str_end_p && lit_char_is_decimal_digit (*str_p)) + { + str_p++; + } + + num_end_p = str_p; + } + } + + lit_utf8_size_t num_size = (lit_utf8_size_t) (num_end_p - num_start_p); + + if (num_size == 0) + { + return ecma_make_nan_value (); + } + + /* 5. */ + ecma_number_t ret_num = ecma_utf8_string_to_number (num_start_p, num_size, 0); + + if (sign) + { + ret_num *= ECMA_NUMBER_MINUS_ONE; + } + + return ecma_make_number_value (ret_num); +} /* ecma_number_parse_float */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.h new file mode 100644 index 00000000..19ac8b51 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.h @@ -0,0 +1,245 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_HELPERS_NUMBER_H +#define ECMA_HELPERS_NUMBER_H + +#include "ecma-globals.h" + +#include "jerry-config.h" + +/** + * Binary representation of an ecma-number + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +typedef uint64_t ecma_binary_num_t; +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +typedef uint32_t ecma_binary_num_t; +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Makes it possible to read/write the binary representation of an ecma_number_t + * without strict aliasing rule violation. + */ +typedef union +{ + ecma_number_t as_number; /**< ecma-number */ + ecma_binary_num_t as_binary; /**< binary representation */ +} ecma_number_accessor_t; + +ecma_binary_num_t ecma_number_to_binary (ecma_number_t number); +ecma_number_t ecma_number_from_binary (ecma_binary_num_t binary); + +bool ecma_number_sign (ecma_binary_num_t binary); +uint32_t ecma_number_biased_exp (ecma_binary_num_t binary); +uint64_t ecma_number_fraction (ecma_binary_num_t binary); +ecma_number_t ecma_number_create (bool sign, uint32_t biased_exp, uint64_t fraction); + +/** + * Maximum number of significant decimal digits that an ecma-number can store + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_MAX_DIGITS (19) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_MAX_DIGITS (9) +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Width of sign field + * + * See also: + * IEEE-754 2008, 3.6, Table 3.5 + */ +#define ECMA_NUMBER_SIGN_WIDTH (1) + +/** + * Width of biased exponent field + * + * See also: + * IEEE-754 2008, 3.6, Table 3.5 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_BIASED_EXP_WIDTH (11) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_BIASED_EXP_WIDTH (8) +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Exponent bias + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_EXPONENT_BIAS (1023) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_EXPONENT_BIAS (127) +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Width of fraction field + * + * See also: + * IEEE-754 2008, 3.6, Table 3.5 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_FRACTION_WIDTH (52) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_FRACTION_WIDTH (23) +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Sign bit in ecma-numbers + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_SIGN_BIT 0x8000000000000000ull +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_SIGN_BIT 0x7f800000u +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Binary representation of an IEEE-754 QNaN value. + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_BINARY_QNAN 0x7ff8000000000000ull +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_BINARY_QNAN 0x7fc00000u +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Binary representation of an IEEE-754 Infinity value. + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_BINARY_INF 0x7ff0000000000000ull +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_BINARY_INF 0x7f800000u +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Binary representation of an IEEE-754 zero value. + */ +#define ECMA_NUMBER_BINARY_ZERO 0x0ull + +/** + * Number.MIN_VALUE (i.e., the smallest positive value of ecma-number) + * + * See also: ECMA_262 v5, 15.7.3.3 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_MIN_VALUE ((ecma_number_t) 5e-324) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_MIN_VALUE (FLT_MIN) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.MAX_VALUE (i.e., the maximum value of ecma-number) + * + * See also: ECMA_262 v5, 15.7.3.2 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_MAX_VALUE ((ecma_number_t) 1.7976931348623157e+308) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_MAX_VALUE (FLT_MAX) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.EPSILON + * + * See also: ECMA_262 v6, 20.1.2.1 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_EPSILON ((ecma_number_t) 2.2204460492503130808472633361816e-16) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_EPSILON ((ecma_number_t) 1.1920928955078125e-7) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.MAX_SAFE_INTEGER + * + * See also: ECMA_262 v6, 20.1.2.6 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_MAX_SAFE_INTEGER ((ecma_number_t) 0x1FFFFFFFFFFFFF) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_MAX_SAFE_INTEGER ((ecma_number_t) 0xFFFFFF) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.MIN_SAFE_INTEGER + * + * See also: ECMA_262 v6, 20.1.2.8 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_MIN_SAFE_INTEGER ((ecma_number_t) -0x1FFFFFFFFFFFFF) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_MIN_SAFE_INTEGER ((ecma_number_t) -0xFFFFFF) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.MAX_VALUE exponent part + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define NUMBER_MAX_DECIMAL_EXPONENT 308 +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define NUMBER_MAX_DECIMAL_EXPONENT 38 +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.MIN_VALUE exponent part + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define NUMBER_MIN_DECIMAL_EXPONENT -324 +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define NUMBER_MIN_DECIMAL_EXPONENT -45 +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Euler number + */ +#define ECMA_NUMBER_E ((ecma_number_t) 2.7182818284590452354) + +/** + * Natural logarithm of 10 + */ +#define ECMA_NUMBER_LN10 ((ecma_number_t) 2.302585092994046) + +/** + * Natural logarithm of 2 + */ +#define ECMA_NUMBER_LN2 ((ecma_number_t) 0.6931471805599453) + +/** + * Logarithm base 2 of the Euler number + */ +#define ECMA_NUMBER_LOG2E ((ecma_number_t) 1.4426950408889634) + +/** + * Logarithm base 10 of the Euler number + */ +#define ECMA_NUMBER_LOG10E ((ecma_number_t) 0.4342944819032518) + +/** + * Pi number + */ +#define ECMA_NUMBER_PI ((ecma_number_t) 3.1415926535897932) + +/** + * Square root of 0.5 + */ +#define ECMA_NUMBER_SQRT_1_2 ((ecma_number_t) 0.7071067811865476) + +/** + * Square root of 2 + */ +#define ECMA_NUMBER_SQRT2 ((ecma_number_t) 1.4142135623730951) + +#endif /* !ECMA_HELPERS_NUMBER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-string.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-string.cpp new file mode 100644 index 00000000..2b186a8e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-string.cpp @@ -0,0 +1,2780 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "lit-char-helpers.h" +#include "lit-magic-strings.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +JERRY_STATIC_ASSERT ((((int)ECMA_STRING_CONTAINER_MASK) >= ((int)ECMA_STRING_CONTAINER__MAX)), + ecma_string_container_types_must_be_lower_than_the_container_mask); + +JERRY_STATIC_ASSERT (((ECMA_STRING_MAX_REF | ECMA_STRING_CONTAINER_MASK | ECMA_STATIC_STRING_FLAG) == UINT32_MAX), + ecma_string_ref_and_container_fields_should_fill_the_32_bit_field); + +JERRY_STATIC_ASSERT (((uint32_t)ECMA_STRING_NOT_ARRAY_INDEX == UINT32_MAX), + ecma_string_not_array_index_must_be_equal_to_uint32_max); + +JERRY_STATIC_ASSERT ((ECMA_TYPE_DIRECT_STRING & 0x1) != 0, ecma_type_direct_string_must_be_odd_number); + +JERRY_STATIC_ASSERT ((((int)LIT_MAGIC_STRING__COUNT) <= ((int)ECMA_DIRECT_STRING_MAX_IMM)), + all_magic_strings_must_be_encoded_as_direct_string); + +JERRY_STATIC_ASSERT (((int) ECMA_DIRECT_STRING_UINT == (int) ECMA_STRING_CONTAINER_UINT32_IN_DESC), + ecma_direct_and_container_types_must_match); + +JERRY_STATIC_ASSERT ((((int)ECMA_PROPERTY_NAME_TYPE_SHIFT) > ((int)ECMA_VALUE_SHIFT)), + ecma_property_name_type_shift_must_be_greater_than_ecma_value_shift); + +JERRY_STATIC_ASSERT ((sizeof (ecma_stringbuilder_header_t) <= ECMA_ASCII_STRING_HEADER_SIZE), + ecma_stringbuilder_header_must_not_be_larger_than_ecma_ascii_string); + +/** + * Convert a string to an unsigned 32 bit value if possible + * + * @return true if the conversion is successful + * false otherwise + */ +static bool +ecma_string_to_array_index (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size, /**< string size */ + uint32_t *result_p) /**< [out] converted value */ +{ + JERRY_ASSERT (string_size > 0 && *string_p >= LIT_CHAR_0 && *string_p <= LIT_CHAR_9); + + if (*string_p == LIT_CHAR_0) + { + *result_p = 0; + return (string_size == 1); + } + + if (string_size > ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) + { + return false; + } + + uint32_t index = 0; + const lit_utf8_byte_t *string_end_p = string_p + string_size; + + if (string_size == ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) + { + string_end_p--; + } + + do + { + if (*string_p > LIT_CHAR_9 || *string_p < LIT_CHAR_0) + { + return false; + } + + index = (index * 10) + (uint32_t) (*string_p++ - LIT_CHAR_0); + } while (string_p < string_end_p); + + if (string_size < ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) + { + *result_p = index; + return true; + } + + /* Overflow must be checked as well when size is + * equal to ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32. */ + if (*string_p > LIT_CHAR_9 || *string_p < LIT_CHAR_0 || index > (UINT32_MAX / 10) + || (index == (UINT32_MAX / 10) && *string_p > LIT_CHAR_5)) + { + return false; + } + + *result_p = (index * 10) + (uint32_t) (*string_p - LIT_CHAR_0); + return true; +} /* ecma_string_to_array_index */ + +/** + * Returns the characters and size of a string. + * + * Note: + * UINT type is not supported + * + * @return byte array start - if the byte array of a string is available + * NULL - otherwise + */ +static const lit_utf8_byte_t * +ecma_string_get_chars_fast (const ecma_string_t *string_p, /**< ecma-string */ + lit_utf8_size_t *size_p) /**< [out] size of the ecma string */ +{ + if (ECMA_IS_DIRECT_STRING (string_p)) + { + if (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC) + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (id >= LIT_MAGIC_STRING__COUNT) + { + id -= LIT_MAGIC_STRING__COUNT; + + *size_p = lit_get_magic_string_ex_size (id); + return lit_get_magic_string_ex_utf8 (id); + } + + *size_p = lit_get_magic_string_size (id); + return lit_get_magic_string_utf8 (id); + } + } + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + *size_p = ((ecma_short_string_t *) string_p)->size; + return ECMA_SHORT_STRING_GET_BUFFER (string_p); + } + case ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING: + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + *size_p = long_string_p->size; + return long_string_p->string_p; + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + *size_p = ECMA_ASCII_STRING_GET_SIZE (string_p); + return ECMA_ASCII_STRING_GET_BUFFER (string_p); + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + *size_p = lit_get_magic_string_ex_size (id); + return lit_get_magic_string_ex_utf8 (id); + } + } +} /* ecma_string_get_chars_fast */ + +/** + * Allocate new ecma-string and fill it with reference to ECMA magic string + * + * @return pointer to ecma-string descriptor + */ +static ecma_string_t * +ecma_new_ecma_string_from_magic_string_ex_id (lit_magic_string_ex_id_t id) /**< identifier of externl magic string */ +{ + JERRY_ASSERT (id < lit_get_magic_string_ex_count ()); + + uintptr_t string_id = (uintptr_t) (id + LIT_MAGIC_STRING__COUNT); + + if (JERRY_LIKELY (string_id <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_MAGIC, string_id); + } + + ecma_string_t *string_desc_p = ecma_alloc_string (); + + string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_MAGIC_STRING_EX | ECMA_STRING_REF_ONE; + string_desc_p->u.magic_string_ex_id = id + LIT_MAGIC_STRING__COUNT; + + return string_desc_p; +} /* ecma_new_ecma_string_from_magic_string_ex_id */ + +/** + * Allocate new ecma-string and fill it with reference to the symbol descriptor + * + * Note: + * Takes the reference to the string_desc + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_symbol_from_descriptor_string (ecma_value_t string_desc) /**< ecma-string */ +{ + JERRY_ASSERT (!ecma_is_value_symbol (string_desc)); + + ecma_extended_string_t *symbol_p = ecma_alloc_extended_string (); + symbol_p->header.refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_CONTAINER_SYMBOL; + symbol_p->u.symbol_descriptor = string_desc; + symbol_p->header.u.hash = (lit_string_hash_t) (((uintptr_t) symbol_p) & (uintptr_t) ~ECMA_SYMBOL_FLAGS_MASK); + + return (ecma_string_t *) symbol_p; +} /* ecma_new_symbol_from_descriptor_string */ + +/** + * Check whether an ecma-string contains an ecma-symbol + * + * @return true - if the ecma-string contains an ecma-symbol + * false - otherwise + */ +bool +ecma_prop_name_is_symbol (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + + return (!ECMA_IS_DIRECT_STRING (string_p) && ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_SYMBOL); +} /* ecma_prop_name_is_symbol */ + +/** + * Allocate new UTF8 ecma-string and fill it with characters from the given utf8 buffer + * + * @return pointer to ecma-string descriptor + */ +static inline ecma_string_t * +ecma_new_ecma_string_from_utf8_buffer (lit_utf8_size_t length, /**< length of the buffer */ + lit_utf8_size_t size, /**< size of the buffer */ + lit_utf8_byte_t **data_p) /**< [out] pointer to the start of the string buffer */ +{ + if (JERRY_LIKELY (size <= UINT16_MAX)) + { + if (JERRY_LIKELY (length == size) && size <= (UINT8_MAX + 1)) + { + ecma_string_t *string_desc_p; + string_desc_p = (ecma_string_t *) ecma_alloc_string_buffer (size + ECMA_ASCII_STRING_HEADER_SIZE); + string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_ASCII_STRING | ECMA_STRING_REF_ONE; + ECMA_ASCII_STRING_SET_SIZE (string_desc_p, size); + + *data_p = ECMA_ASCII_STRING_GET_BUFFER (string_desc_p); + return (ecma_string_t *) string_desc_p; + } + + ecma_short_string_t *string_desc_p; + string_desc_p = (ecma_short_string_t *) ecma_alloc_string_buffer (size + sizeof (ecma_short_string_t)); + string_desc_p->header.refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; + string_desc_p->size = (uint16_t) size; + string_desc_p->length = (uint16_t) length; + + *data_p = ECMA_SHORT_STRING_GET_BUFFER (string_desc_p); + return (ecma_string_t *) string_desc_p; + } + + ecma_long_string_t *long_string_p; + long_string_p = (ecma_long_string_t *) ecma_alloc_string_buffer (size + sizeof (ecma_long_string_t)); + long_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING | ECMA_STRING_REF_ONE; + long_string_p->string_p = ECMA_LONG_STRING_BUFFER_START (long_string_p); + long_string_p->size = size; + long_string_p->length = length; + + *data_p = ECMA_LONG_STRING_BUFFER_START (long_string_p); + return (ecma_string_t *) long_string_p; +} /* ecma_new_ecma_string_from_utf8_buffer */ + +/** + * Checks whether a string has a special representation, that is, the string is either a magic string, + * an external magic string, or an uint32 number, and creates an ecma string using the special representation, + * if available. + * + * @return pointer to ecma string with the special representation + * NULL, if there is no special representation for the string + */ +static ecma_string_t * +ecma_find_special_string (const lit_utf8_byte_t *string_p, /**< utf8 string */ + lit_utf8_size_t string_size) /**< string size */ +{ + JERRY_ASSERT (string_p != NULL || string_size == 0); + lit_magic_string_id_t magic_string_id = lit_is_utf8_string_magic (string_p, string_size); + + if (magic_string_id != LIT_MAGIC_STRING__COUNT) + { + return ecma_get_magic_string (magic_string_id); + } + + JERRY_ASSERT (string_size > 0); + + if (*string_p >= LIT_CHAR_0 && *string_p <= LIT_CHAR_9) + { + uint32_t array_index; + + if (ecma_string_to_array_index (string_p, string_size, &array_index)) + { + return ecma_new_ecma_string_from_uint32 (array_index); + } + } + + if (lit_get_magic_string_ex_count () > 0) + { + lit_magic_string_ex_id_t magic_string_ex_id = lit_is_ex_utf8_string_magic (string_p, string_size); + + if (magic_string_ex_id < lit_get_magic_string_ex_count ()) + { + return ecma_new_ecma_string_from_magic_string_ex_id (magic_string_ex_id); + } + } + + return NULL; +} /* ecma_find_special_string */ + +/** + * Allocate new ecma-string and fill it with characters from ascii characters + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_ascii (const lit_utf8_byte_t *string_p, /**< ascii string */ + lit_utf8_size_t string_size) /**< string size */ +{ + JERRY_ASSERT (string_p != NULL || string_size == 0); + + ecma_string_t *string_desc_p = ecma_find_special_string (string_p, string_size); + + if (string_desc_p != NULL) + { + return string_desc_p; + } + + lit_utf8_byte_t *data_p; + string_desc_p = ecma_new_ecma_string_from_utf8_buffer (string_size, string_size, &data_p); + + string_desc_p->u.hash = lit_utf8_string_calc_hash (string_p, string_size); + memcpy (data_p, string_p, string_size); + + return string_desc_p; +} /* ecma_new_ecma_string_from_ascii */ + +/** + * Allocate new ecma-string and fill it with characters from the utf8 string + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size) /**< string size */ +{ + JERRY_ASSERT (string_p != NULL || string_size == 0); + JERRY_ASSERT (lit_is_valid_cesu8_string (string_p, string_size)); + + ecma_string_t *string_desc_p = ecma_find_special_string (string_p, string_size); + + if (string_desc_p != NULL) + { + return string_desc_p; + } + + lit_utf8_byte_t *data_p; + string_desc_p = + ecma_new_ecma_string_from_utf8_buffer (lit_utf8_string_length (string_p, string_size), string_size, &data_p); + + string_desc_p->u.hash = lit_utf8_string_calc_hash (string_p, string_size); + memcpy (data_p, string_p, string_size); + + return string_desc_p; +} /* ecma_new_ecma_string_from_utf8 */ + +/** + * Allocate a new ecma-string and initialize it from the utf8 string argument. + * All 4-bytes long unicode sequences are converted into two 3-bytes long sequences. + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size) /**< utf-8 string size */ +{ + JERRY_ASSERT (string_p != NULL || string_size == 0); + + lit_utf8_size_t converted_string_length = 0; + lit_utf8_size_t converted_string_size = 0; + lit_utf8_size_t pos = 0; + + /* Calculate the required length and size information of the converted cesu-8 encoded string */ + while (pos < string_size) + { + if ((string_p[pos] & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER) + { + pos++; + } + else if ((string_p[pos] & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + pos += 2; + } + else if ((string_p[pos] & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER) + { + pos += 3; + } + else + { + JERRY_ASSERT ((string_p[pos] & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER); + pos += 4; + converted_string_size += 2; + converted_string_length++; + } + + converted_string_length++; + } + + JERRY_ASSERT (pos == string_size); + + if (converted_string_size == 0) + { + return ecma_new_ecma_string_from_utf8 (string_p, string_size); + } + + converted_string_size += string_size; + + JERRY_ASSERT (lit_is_valid_utf8_string (string_p, string_size, false)); + + lit_utf8_byte_t *data_p; + ecma_string_t *string_desc_p = + ecma_new_ecma_string_from_utf8_buffer (converted_string_length, converted_string_size, &data_p); + + const lit_utf8_byte_t *const begin_data_p = data_p; + pos = 0; + + while (pos < string_size) + { + if ((string_p[pos] & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER) + { + /* Processing 4 byte unicode sequence. Always converted to two 3 byte long sequence. */ + lit_four_byte_utf8_char_to_cesu8 (data_p, string_p + pos); + data_p += 3 * 2; + pos += 4; + } + else + { + *data_p++ = string_p[pos++]; + } + } + + JERRY_ASSERT (pos == string_size); + + string_desc_p->u.hash = lit_utf8_string_calc_hash (begin_data_p, converted_string_size); + + return (ecma_string_t *) string_desc_p; +} /* ecma_new_ecma_string_from_utf8_converted_to_cesu8 */ + +/** + * Allocate new ecma-external-string and fill it with characters from the cesu8 string + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, /**< cesu-8 string */ + lit_utf8_size_t string_size, /**< string size */ + void *user_p) /**< user pointer passed to the callback + * when the string is freed */ +{ + JERRY_ASSERT (string_p != NULL || string_size == 0); + JERRY_ASSERT (lit_is_valid_cesu8_string (string_p, string_size)); + + if (string_size < (sizeof (ecma_external_string_t) - sizeof (ecma_short_string_t))) + { + /* Normal strings are created for short strings. */ + ecma_string_t *string_desc_p = ecma_new_ecma_string_from_utf8 (string_p, string_size); + + jerry_external_string_free_cb_t free_cb = JERRY_CONTEXT (external_string_free_callback_p); + + if (free_cb != NULL) + { + free_cb ((lit_utf8_byte_t *) string_p, string_size, user_p); + } + return string_desc_p; + } + + ecma_string_t *string_desc_p = ecma_find_special_string (string_p, string_size); + + if (string_desc_p != NULL) + { + jerry_external_string_free_cb_t free_cb = JERRY_CONTEXT (external_string_free_callback_p); + + if (free_cb != NULL) + { + free_cb ((lit_utf8_byte_t *) string_p, string_size, user_p); + } + return string_desc_p; + } + + ecma_external_string_t *external_string_p = ecma_alloc_external_string (); + ecma_long_string_t *long_string_p = (ecma_long_string_t *) external_string_p; + + long_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING | ECMA_STRING_REF_ONE; + long_string_p->header.u.hash = lit_utf8_string_calc_hash (string_p, string_size); + long_string_p->string_p = string_p; + long_string_p->size = string_size; + long_string_p->length = lit_utf8_string_length (string_p, string_size); + external_string_p->user_p = user_p; + + return (ecma_string_t *) external_string_p; +} /* ecma_new_ecma_external_string_from_cesu8 */ + +/** + * Allocate new ecma-string and fill it with cesu-8 character which represents specified code unit + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_code_unit (ecma_char_t code_unit) /**< code unit */ +{ + lit_utf8_byte_t lit_utf8_bytes[LIT_UTF8_MAX_BYTES_IN_CODE_UNIT]; + lit_utf8_size_t bytes_size = lit_code_unit_to_utf8 (code_unit, lit_utf8_bytes); + + return ecma_new_ecma_string_from_utf8 (lit_utf8_bytes, bytes_size); +} /* ecma_new_ecma_string_from_code_unit */ + +/** + * Allocate new ecma-string and fill it with cesu-8 character which represents specified code units + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_code_units (ecma_char_t first_code_unit, /**< code unit */ + ecma_char_t second_code_unit) /**< code unit */ +{ + lit_utf8_byte_t lit_utf8_bytes[2 * LIT_UTF8_MAX_BYTES_IN_CODE_UNIT]; + lit_utf8_size_t bytes_size = lit_code_unit_to_utf8 (first_code_unit, lit_utf8_bytes); + bytes_size += lit_code_unit_to_utf8 (second_code_unit, lit_utf8_bytes + bytes_size); + + return ecma_new_ecma_string_from_utf8 (lit_utf8_bytes, bytes_size); +} /* ecma_new_ecma_string_from_code_units */ + +/** + * Allocate new ecma-string and fill it with ecma-number + * + * Note: the number cannot be represented as direct string + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_non_direct_string_from_uint32 (uint32_t uint32_number) /**< uint32 value of the string */ +{ + JERRY_ASSERT (uint32_number > ECMA_DIRECT_STRING_MAX_IMM); + + ecma_string_t *string_p = ecma_alloc_string (); + + string_p->refs_and_container = ECMA_STRING_CONTAINER_UINT32_IN_DESC | ECMA_STRING_REF_ONE; + string_p->u.uint32_number = uint32_number; + + return string_p; +} /* ecma_new_non_direct_string_from_uint32 */ + +/** + * Allocate new ecma-string and fill it with property length number + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_length (ecma_length_t number) /**< property length */ +{ + if (JERRY_LIKELY (number <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) number); + } + + JERRY_ASSERT ((ecma_number_t) number <= ECMA_NUMBER_MAX_SAFE_INTEGER); + + if (JERRY_UNLIKELY (number > UINT32_MAX)) + { + return ecma_new_ecma_string_from_number ((ecma_number_t) number); + } + + return ecma_new_non_direct_string_from_uint32 ((uint32_t) number); +} /* ecma_new_ecma_string_from_length */ + +/** + * Allocate new ecma-string and fill it with uint32 number + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_uint32 (uint32_t uint32_number) /**< uint32 value of the string */ +{ + if (JERRY_LIKELY (uint32_number <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) uint32_number); + } + + return ecma_new_non_direct_string_from_uint32 (uint32_number); +} /* ecma_new_ecma_string_from_uint32 */ + +/** + * Returns the constant assigned to the uint32 number. + * + * Note: + * Calling ecma_deref_ecma_string on the returned pointer is optional. + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_get_ecma_string_from_uint32 (uint32_t uint32_number) /**< input number */ +{ + JERRY_ASSERT (uint32_number <= ECMA_DIRECT_STRING_MAX_IMM); + + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) uint32_number); +} /* ecma_get_ecma_string_from_uint32 */ + +/** + * Allocate new ecma-string and fill it with ecma-number + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */ +{ + uint32_t uint32_num = ecma_number_to_uint32 (num); + if (num == ((ecma_number_t) uint32_num)) + { + return ecma_new_ecma_string_from_uint32 (uint32_num); + } + + if (ecma_number_is_nan (num)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_NAN); + } + + if (ecma_number_is_infinity (num)) + { + lit_magic_string_id_t id = + (ecma_number_is_negative (num) ? LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL : LIT_MAGIC_STRING_INFINITY_UL); + return ecma_get_magic_string (id); + } + + lit_utf8_byte_t str_buf[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; + lit_utf8_size_t str_size = ecma_number_to_utf8_string (num, str_buf, sizeof (str_buf)); + + JERRY_ASSERT (str_size > 0); +#ifndef JERRY_NDEBUG + JERRY_ASSERT (lit_is_utf8_string_magic (str_buf, str_size) == LIT_MAGIC_STRING__COUNT + && lit_is_ex_utf8_string_magic (str_buf, str_size) == lit_get_magic_string_ex_count ()); +#endif /* !JERRY_NDEBUG */ + + lit_utf8_byte_t *data_p; + ecma_string_t *string_desc_p = + ecma_new_ecma_string_from_utf8_buffer (lit_utf8_string_length (str_buf, str_size), str_size, &data_p); + + string_desc_p->u.hash = lit_utf8_string_calc_hash (str_buf, str_size); + memcpy (data_p, str_buf, str_size); + + return string_desc_p; +} /* ecma_new_ecma_string_from_number */ + +/** + * Returns the constant assigned to the magic string id. + * + * Note: + * Calling ecma_deref_ecma_string on the returned pointer is optional. + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_get_magic_string (lit_magic_string_id_t id) /**< identifier of magic string */ +{ + JERRY_ASSERT (id < LIT_MAGIC_STRING__COUNT); + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_MAGIC, (uintptr_t) id); +} /* ecma_get_magic_string */ + +/** + * Returns the constant assigned to the internal magic string id. + * + * Note: + * Calling ecma_deref_ecma_string on the returned pointer is optional. + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_get_internal_string (lit_magic_string_id_t id) /**< identifier of magic string */ +{ + JERRY_ASSERT (id >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT && id < LIT_MAGIC_STRING__COUNT); + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_SPECIAL, (uintptr_t) id); +} /* ecma_get_internal_string */ + +/** + * Append a cesu8 string after an ecma-string + * + * Note: + * The string1_p argument is freed. If it needs to be preserved, + * call ecma_ref_ecma_string with string1_p before the call. + * + * @return concatenation of an ecma-string and a cesu8 string + */ +ecma_string_t * +ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */ + const lit_utf8_byte_t *cesu8_string2_p, /**< characters to be appended */ + lit_utf8_size_t cesu8_string2_size, /**< byte size of cesu8_string2_p */ + lit_utf8_size_t cesu8_string2_length) /**< character length of cesu8_string2_p */ +{ + JERRY_ASSERT (string1_p != NULL && cesu8_string2_size > 0 && cesu8_string2_length > 0); + + if (JERRY_UNLIKELY (ecma_string_is_empty (string1_p))) + { + return ecma_new_ecma_string_from_utf8 (cesu8_string2_p, cesu8_string2_size); + } + + lit_utf8_size_t cesu8_string1_size; + lit_utf8_size_t cesu8_string1_length; + uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; + lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + + const lit_utf8_byte_t *cesu8_string1_p = + ecma_string_get_chars (string1_p, &cesu8_string1_size, &cesu8_string1_length, uint32_to_string_buffer, &flags); + + JERRY_ASSERT (!(flags & ECMA_STRING_FLAG_MUST_BE_FREED)); + JERRY_ASSERT (cesu8_string1_length > 0); + JERRY_ASSERT (cesu8_string1_length <= cesu8_string1_size); + + lit_utf8_size_t new_size = cesu8_string1_size + cesu8_string2_size; + + /* Poor man's carry flag check: it is impossible to allocate this large string. */ + if (new_size < (cesu8_string1_size | cesu8_string2_size)) + { + jerry_fatal (JERRY_FATAL_OUT_OF_MEMORY); + } + + lit_magic_string_id_t magic_string_id; + magic_string_id = + lit_is_utf8_string_pair_magic (cesu8_string1_p, cesu8_string1_size, cesu8_string2_p, cesu8_string2_size); + + if (magic_string_id != LIT_MAGIC_STRING__COUNT) + { + ecma_deref_ecma_string (string1_p); + return ecma_get_magic_string (magic_string_id); + } + + if ((flags & ECMA_STRING_FLAG_IS_UINT32) && new_size <= ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) + { + memcpy (uint32_to_string_buffer + cesu8_string1_size, cesu8_string2_p, cesu8_string2_size); + + uint32_t array_index; + + if (ecma_string_to_array_index (uint32_to_string_buffer, new_size, &array_index)) + { + ecma_deref_ecma_string (string1_p); + return ecma_new_ecma_string_from_uint32 (array_index); + } + } + + if (lit_get_magic_string_ex_count () > 0) + { + lit_magic_string_ex_id_t magic_string_ex_id; + magic_string_ex_id = + lit_is_ex_utf8_string_pair_magic (cesu8_string1_p, cesu8_string1_size, cesu8_string2_p, cesu8_string2_size); + + if (magic_string_ex_id < lit_get_magic_string_ex_count ()) + { + ecma_deref_ecma_string (string1_p); + return ecma_new_ecma_string_from_magic_string_ex_id (magic_string_ex_id); + } + } + + lit_utf8_byte_t *data_p; + ecma_string_t *string_desc_p = + ecma_new_ecma_string_from_utf8_buffer (cesu8_string1_length + cesu8_string2_length, new_size, &data_p); + + lit_string_hash_t hash_start; + + if (JERRY_UNLIKELY (flags & ECMA_STRING_FLAG_REHASH_NEEDED)) + { + hash_start = lit_utf8_string_calc_hash (cesu8_string1_p, cesu8_string1_size); + } + else + { + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string1_p)); + hash_start = string1_p->u.hash; + } + + string_desc_p->u.hash = lit_utf8_string_hash_combine (hash_start, cesu8_string2_p, cesu8_string2_size); + + memcpy (data_p, cesu8_string1_p, cesu8_string1_size); + memcpy (data_p + cesu8_string1_size, cesu8_string2_p, cesu8_string2_size); + + ecma_deref_ecma_string (string1_p); + return (ecma_string_t *) string_desc_p; +} /* ecma_append_chars_to_string */ + +/** + * Concatenate ecma-strings + * + * Note: + * The string1_p argument is freed. If it needs to be preserved, + * call ecma_ref_ecma_string with string1_p before the call. + * + * @return concatenation of two ecma-strings + */ +ecma_string_t * +ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ + ecma_string_t *string2_p) /**< second ecma-string */ +{ + JERRY_ASSERT (string1_p != NULL && string2_p != NULL); + + if (JERRY_UNLIKELY (ecma_string_is_empty (string1_p))) + { + ecma_ref_ecma_string (string2_p); + return string2_p; + } + else if (JERRY_UNLIKELY (ecma_string_is_empty (string2_p))) + { + return string1_p; + } + + lit_utf8_size_t cesu8_string2_size; + lit_utf8_size_t cesu8_string2_length; + lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; + + const lit_utf8_byte_t *cesu8_string2_p = + ecma_string_get_chars (string2_p, &cesu8_string2_size, &cesu8_string2_length, uint32_to_string_buffer, &flags); + + JERRY_ASSERT (cesu8_string2_p != NULL); + + ecma_string_t *result_p = + ecma_append_chars_to_string (string1_p, cesu8_string2_p, cesu8_string2_size, cesu8_string2_length); + + JERRY_ASSERT (!(flags & ECMA_STRING_FLAG_MUST_BE_FREED)); + + return result_p; +} /* ecma_concat_ecma_strings */ + +/** + * Increase reference counter of non-direct ecma-string. + * + * @return void + */ +void +ecma_ref_ecma_string_non_direct (ecma_string_t *string_p) /**< string descriptor */ +{ + JERRY_ASSERT (string_p != NULL); + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string_p)); + +#ifdef JERRY_NDEBUG + if (ECMA_STRING_IS_STATIC (string_p)) + { + return; + } +#endif /* JERRY_NDEBUG */ + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (JERRY_LIKELY (string_p->refs_and_container < ECMA_STRING_MAX_REF)) + { + /* Increase reference counter. */ + string_p->refs_and_container += ECMA_STRING_REF_ONE; + } + else + { + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } +} /* ecma_ref_ecma_string_non_direct */ + +/** + * Increase reference counter of ecma-string. + */ +void +ecma_ref_ecma_string (ecma_string_t *string_p) /**< string descriptor */ +{ + JERRY_ASSERT (string_p != NULL); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return; + } + + ecma_ref_ecma_string_non_direct (string_p); +} /* ecma_ref_ecma_string */ + +/** + * Decrease reference counter and deallocate a non-direct ecma-string + * if the counter becomes zero. + * + * @return void + */ +void +ecma_deref_ecma_string_non_direct (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string_p)); + +#ifdef JERRY_NDEBUG + if (ECMA_STRING_IS_STATIC (string_p)) + { + return; + } +#endif /* JERRY_NDEBUG */ + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + /* Decrease reference counter. */ + string_p->refs_and_container -= ECMA_STRING_REF_ONE; + + if (string_p->refs_and_container >= ECMA_STRING_REF_ONE) + { + return; + } + + ecma_destroy_ecma_string (string_p); +} /* ecma_deref_ecma_string_non_direct */ + +/** + * Decrease reference counter and deallocate ecma-string + * if the counter becomes zero. + */ +void +ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return; + } + + ecma_deref_ecma_string_non_direct (string_p); +} /* ecma_deref_ecma_string */ + +/** + * Deallocate an ecma-string + */ +void +ecma_destroy_ecma_string (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string_p)); + JERRY_ASSERT ((string_p->refs_and_container < ECMA_STRING_REF_ONE) || ECMA_STRING_IS_STATIC (string_p)); + + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + ecma_dealloc_string_buffer (string_p, ((ecma_short_string_t *) string_p)->size + sizeof (ecma_short_string_t)); + return; + } + case ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING: + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + + if (long_string_p->string_p == ECMA_LONG_STRING_BUFFER_START (long_string_p)) + { + ecma_dealloc_string_buffer (string_p, long_string_p->size + sizeof (ecma_long_string_t)); + return; + } + + ecma_external_string_t *external_string_p = (ecma_external_string_t *) string_p; + jerry_external_string_free_cb_t free_cb = JERRY_CONTEXT (external_string_free_callback_p); + + if (free_cb != NULL) + { + free_cb ((lit_utf8_byte_t *) external_string_p->header.string_p, + external_string_p->header.size, + external_string_p->user_p); + } + + ecma_dealloc_external_string (external_string_p); + return; + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + ecma_dealloc_string_buffer (string_p, ECMA_ASCII_STRING_GET_SIZE (string_p) + ECMA_ASCII_STRING_HEADER_SIZE); + return; + } + case ECMA_STRING_CONTAINER_SYMBOL: + { + ecma_extended_string_t *symbol_p = (ecma_extended_string_t *) string_p; + ecma_free_value (symbol_p->u.symbol_descriptor); + ecma_dealloc_extended_string (symbol_p); + return; + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC + || ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + /* only the string descriptor itself should be freed */ + ecma_dealloc_string (string_p); + } + } +} /* ecma_destroy_ecma_string */ + +/** + * Convert ecma-string to number + * + * @return converted ecma-number + */ +ecma_number_t +ecma_string_to_number (const ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (string_p, ECMA_DIRECT_STRING_UINT)) + { + return (ecma_number_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + } + } + else if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ((ecma_number_t) string_p->u.uint32_number); + } + + lit_utf8_size_t size; + const lit_utf8_byte_t *chars_p = ecma_string_get_chars_fast (string_p, &size); + + JERRY_ASSERT (chars_p != NULL); + + if (size == 0) + { + return ECMA_NUMBER_ZERO; + } + + return ecma_utf8_string_to_number (chars_p, size, 0); +} /* ecma_string_to_number */ + +/** + * Check if string is array index. + * + * @return ECMA_STRING_NOT_ARRAY_INDEX if string is not array index + * the array index otherwise + */ +uint32_t +ecma_string_get_array_index (const ecma_string_t *str_p) /**< ecma-string */ +{ + if (ECMA_IS_DIRECT_STRING (str_p)) + { + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (str_p, ECMA_DIRECT_STRING_UINT)) + { + /* Value cannot be equal to the maximum value of a 32 bit unsigned number. */ + return (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (str_p); + } + + return ECMA_STRING_NOT_ARRAY_INDEX; + } + + if (ECMA_STRING_GET_CONTAINER (str_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + /* When the uint32_number is equal to the maximum value of 32 bit unsigned integer number, + * it is also an invalid array index. The comparison to ECMA_STRING_NOT_ARRAY_INDEX will + * be true in this case. */ + return str_p->u.uint32_number; + } + + return ECMA_STRING_NOT_ARRAY_INDEX; +} /* ecma_string_get_array_index */ + +/** + * Copy digits of uint32 number, truncating if buffer is not large enough. + * + * @return number of digits copied + */ +static lit_utf8_size_t +ecma_uint32_to_buffer (uint32_t num, /**< number */ + lit_utf8_byte_t *buffer_p /**< destination buffer */, + lit_utf8_size_t buffer_size /**< buffer size */) +{ + lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + lit_utf8_size_t digit_count = ecma_uint32_to_utf8_string (num, digits, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + + digit_count = JERRY_MIN (buffer_size, digit_count); + memcpy (buffer_p, digits, digit_count); + return digit_count; +} /* ecma_uint32_to_buffer */ + +/** + * Convert ecma-string's contents to the specified encoding and copy it to the buffer. + * String data will be truncated to fit the buffer. + * + * @return number of bytes copied to the buffer. + */ +lit_utf8_size_t JERRY_ATTR_WARN_UNUSED_RESULT +ecma_string_copy_to_buffer (const ecma_string_t *string_p, /**< ecma-string descriptor */ + lit_utf8_byte_t *buffer_p, /**< destination buffer pointer + * (can be NULL if buffer_size == 0) */ + lit_utf8_size_t buffer_size, /**< size of buffer */ + jerry_encoding_t encoding) /**< encoding */ +{ + JERRY_ASSERT (string_p != NULL); + JERRY_ASSERT (buffer_p != NULL || buffer_size == 0); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (string_p, ECMA_DIRECT_STRING_UINT)) + { + return ecma_uint32_to_buffer ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p), buffer_p, buffer_size); + } + } + else + { + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ecma_uint32_to_buffer (string_p->u.uint32_number, buffer_p, buffer_size); + } + } + + lit_utf8_size_t string_size; + const lit_utf8_byte_t *chars_p = ecma_string_get_chars_fast (string_p, &string_size); + lit_utf8_size_t copy_size = 0; + + JERRY_ASSERT (chars_p != NULL); + + switch (encoding) + { + case JERRY_ENCODING_CESU8: + { + copy_size = JERRY_MIN (string_size, buffer_size); + + if (copy_size < string_size) + { + /* Do not copy partial characters */ + while ((chars_p[copy_size] & LIT_UTF8_EXTRA_BYTE_MASK) == LIT_UTF8_EXTRA_BYTE_MARKER) + { + copy_size--; + } + } + + memcpy (buffer_p, chars_p, copy_size); + break; + } + case JERRY_ENCODING_UTF8: + { + if (string_size == ecma_string_get_length (string_p)) + { + copy_size = JERRY_MIN (string_size, buffer_size); + + memcpy (buffer_p, chars_p, copy_size); + break; + } + + copy_size = lit_convert_cesu8_string_to_utf8_string (chars_p, string_size, buffer_p, buffer_size); + break; + } + default: + { + break; + } + } + + return copy_size; +} /* ecma_string_copy_to_buffer */ + +/** + * Convert ecma-string's contents to a cesu-8 string and put it to the buffer. + * It is the caller's responsibility to make sure that the string fits in the buffer. + * Check if the size of the string is equal with the size of the buffer. + * + * @return void + */ +void +ecma_string_to_cesu8_bytes (const ecma_string_t *string_desc_p, /**< ecma-string descriptor */ + lit_utf8_byte_t *buffer_p, /**< destination buffer pointer + * (can be NULL if buffer_size == 0) */ + lit_utf8_size_t buffer_size) /**< size of buffer */ +{ + const lit_utf8_size_t size = ecma_string_copy_to_buffer (string_desc_p, buffer_p, buffer_size, JERRY_ENCODING_CESU8); + JERRY_ASSERT (size == buffer_size); +} /* ecma_string_to_cesu8_bytes */ + +/** + * Get size of the uint32 number stored locally in the string's descriptor + * + * Note: the represented number size and length are equal + * + * @return size in bytes + */ +static inline lit_utf8_size_t +ecma_string_get_uint32_size (const uint32_t uint32_number) /**< number in the string-descriptor */ +{ + uint32_t prev_number = 1; + uint32_t next_number = 100; + lit_utf8_size_t size = 1; + + const uint32_t max_size = 9; + + while (size < max_size && uint32_number >= next_number) + { + prev_number = next_number; + next_number *= 100; + size += 2; + } + + if (uint32_number >= prev_number * 10) + { + size++; + } + + return size; +} /* ecma_string_get_uint32_size */ + +/** + * Checks whether the given string is a sequence of ascii characters. + */ +#define ECMA_STRING_IS_ASCII(char_p, size) ((size) == lit_utf8_string_length ((char_p), (size))) + +/** + * Returns with the cesu8 character array of a string. + * + * Note: + * - This function returns with a newly allocated buffer for uint32 strings, + * which must be freed if the optional uint32_buff_p parameter is NULL. + * - The ASCII check only happens if the flags parameter gets + * 'ECMA_STRING_FLAG_IS_ASCII' as an input. + * + * @return start of cesu8 characters + */ +const lit_utf8_byte_t * +ecma_string_get_chars (const ecma_string_t *string_p, /**< ecma-string */ + lit_utf8_size_t *size_p, /**< [out] size of the ecma string */ + lit_utf8_size_t *length_p, /**< [out] optional argument. If the pointer is not NULL the pointed + * memory area is filled with the length of the ecma string */ + lit_utf8_byte_t *uint32_buff_p, /**< [out] optional argument. If the pointer is not NULL the + * pointed memory area is filled with the string converted + * uint32 string descriptor */ + uint8_t *flags_p) /**< [in,out] any combination of ecma_string_flag_t bits */ +{ + lit_utf8_size_t length; + lit_utf8_size_t size; + const lit_utf8_byte_t *result_p; + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + *flags_p |= ECMA_STRING_FLAG_REHASH_NEEDED; + + switch (ECMA_GET_DIRECT_STRING_TYPE (string_p)) + { + case ECMA_DIRECT_STRING_MAGIC: + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (id >= LIT_MAGIC_STRING__COUNT) + { + id -= LIT_MAGIC_STRING__COUNT; + size = lit_get_magic_string_ex_size (id); + result_p = lit_get_magic_string_ex_utf8 (id); + length = 0; + + if (JERRY_UNLIKELY (*flags_p & ECMA_STRING_FLAG_IS_ASCII)) + { + length = lit_utf8_string_length (result_p, size); + } + } + else + { + size = lit_get_magic_string_size (id); + length = size; + + result_p = lit_get_magic_string_utf8 (id); + + /* All magic strings must be ascii strings. */ + JERRY_ASSERT (ECMA_STRING_IS_ASCII (result_p, size)); + } + break; + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_UINT); + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + size = (lit_utf8_size_t) ecma_string_get_uint32_size (uint32_number); + + if (uint32_buff_p != NULL) + { + result_p = uint32_buff_p; + } + else + { + result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size); + *flags_p |= ECMA_STRING_FLAG_MUST_BE_FREED; + } + + length = ecma_uint32_to_utf8_string (uint32_number, (lit_utf8_byte_t *) result_p, size); + + JERRY_ASSERT (length == size); + *flags_p |= ECMA_STRING_FLAG_IS_UINT32; + break; + } + } + } + else + { + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) string_p; + size = short_string_p->size; + length = short_string_p->length; + result_p = ECMA_SHORT_STRING_GET_BUFFER (short_string_p); + break; + } + case ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING: + { + ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string_p; + size = long_string_desc_p->size; + length = long_string_desc_p->length; + result_p = long_string_desc_p->string_p; + break; + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + size = ECMA_ASCII_STRING_GET_SIZE (string_p); + length = size; + result_p = ECMA_ASCII_STRING_GET_BUFFER (string_p); + break; + } + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + { + size = (lit_utf8_size_t) ecma_string_get_uint32_size (string_p->u.uint32_number); + + if (uint32_buff_p != NULL) + { + result_p = uint32_buff_p; + } + else + { + result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size); + *flags_p |= ECMA_STRING_FLAG_MUST_BE_FREED; + } + + length = ecma_uint32_to_utf8_string (string_p->u.uint32_number, (lit_utf8_byte_t *) result_p, size); + + JERRY_ASSERT (length == size); + *flags_p |= ECMA_STRING_FLAG_IS_UINT32 | ECMA_STRING_FLAG_REHASH_NEEDED; + break; + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + size = lit_get_magic_string_ex_size (id); + length = 0; + + if (JERRY_UNLIKELY (*flags_p & ECMA_STRING_FLAG_IS_ASCII)) + { + length = lit_utf8_string_length (lit_get_magic_string_ex_utf8 (id), size); + } + + result_p = lit_get_magic_string_ex_utf8 (id); + *flags_p |= ECMA_STRING_FLAG_REHASH_NEEDED; + break; + } + } + } + + *size_p = size; + if (length_p != NULL) + { + *length_p = length; + } + + if ((*flags_p & ECMA_STRING_FLAG_IS_ASCII) && length != size) + { + *flags_p = (uint8_t) (*flags_p & (uint8_t) ~ECMA_STRING_FLAG_IS_ASCII); + } + + return result_p; +} /* ecma_string_get_chars */ + +/** + * Checks whether the string equals to the magic string id. + * + * @return true - if the string equals to the magic string id + * false - otherwise + */ +bool +ecma_compare_ecma_string_to_magic_id (const ecma_string_t *string_p, /**< property name */ + lit_magic_string_id_t id) /**< magic string id */ +{ + return (string_p == ecma_get_magic_string (id)); +} /* ecma_compare_ecma_string_to_magic_id */ + +/** + * Checks whether ecma string is empty or not + * + * @return true - if the string is an empty string + * false - otherwise + */ +bool +ecma_string_is_empty (const ecma_string_t *string_p) /**< ecma-string */ +{ + return ecma_compare_ecma_string_to_magic_id (string_p, LIT_MAGIC_STRING__EMPTY); +} /* ecma_string_is_empty */ + +/** + * Checks whether the string equals to "length". + * + * @return true - if the string equals to "length" + * false - otherwise + */ +bool +ecma_string_is_length (const ecma_string_t *string_p) /**< property name */ +{ + return ecma_compare_ecma_string_to_magic_id (string_p, LIT_MAGIC_STRING_LENGTH); +} /* ecma_string_is_length */ + +/** + * Converts a property name into a string + * + * @return pointer to the converted ecma string + */ +static inline ecma_string_t * +ecma_property_to_string (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + uintptr_t property_string = ((uintptr_t) (property)) & (0x3 << ECMA_PROPERTY_NAME_TYPE_SHIFT); + property_string = (property_string >> ECMA_STRING_TYPE_CONVERSION_SHIFT) | ECMA_TYPE_DIRECT_STRING; + return (ecma_string_t *) (property_string | (((uintptr_t) prop_name_cp) << ECMA_DIRECT_STRING_SHIFT)); +} /* ecma_property_to_string */ + +/** + * Converts a string into a property name + * + * @return the compressed pointer part of the name + */ +jmem_cpointer_t +ecma_string_to_property_name (ecma_string_t *prop_name_p, /**< property name */ + ecma_property_t *name_type_p) /**< [out] property name type */ +{ + if (ECMA_IS_DIRECT_STRING (prop_name_p)) + { + *name_type_p = (ecma_property_t) ECMA_DIRECT_STRING_TYPE_TO_PROP_NAME_TYPE (prop_name_p); + return (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (prop_name_p); + } + + *name_type_p = ECMA_DIRECT_STRING_PTR << ECMA_PROPERTY_NAME_TYPE_SHIFT; + + ecma_ref_ecma_string (prop_name_p); + + jmem_cpointer_t prop_name_cp; + ECMA_SET_NON_NULL_POINTER (prop_name_cp, prop_name_p); + return prop_name_cp; +} /* ecma_string_to_property_name */ + +/** + * Converts a property name into a string + * + * @return the string pointer + * string must be released with ecma_deref_ecma_string + */ +ecma_string_t * +ecma_string_from_property_name (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + if (ECMA_PROPERTY_GET_NAME_TYPE (property) != ECMA_DIRECT_STRING_PTR) + { + return ecma_property_to_string (property, prop_name_cp); + } + + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + ecma_ref_ecma_string (prop_name_p); + return prop_name_p; +} /* ecma_string_from_property_name */ + +/** + * Get hash code of property name + * + * @return hash code of property name + */ +lit_string_hash_t +ecma_string_get_property_name_hash (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + if (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_DIRECT_STRING_PTR) + { + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + return prop_name_p->u.hash; + } + + return (lit_string_hash_t) prop_name_cp; +} /* ecma_string_get_property_name_hash */ + +/** + * Check if property name is array index. + * + * @return ECMA_STRING_NOT_ARRAY_INDEX if string is not array index + * the array index otherwise + */ +uint32_t +ecma_string_get_property_index (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + switch (ECMA_PROPERTY_GET_NAME_TYPE (property)) + { + case ECMA_DIRECT_STRING_UINT: + { + return (uint32_t) prop_name_cp; + } + case ECMA_DIRECT_STRING_PTR: + { + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + return ecma_string_get_array_index (prop_name_p); + } + default: + { + return ECMA_STRING_NOT_ARRAY_INDEX; + } + } +} /* ecma_string_get_property_index */ + +/** + * Compare a property name to a string + * + * @return true if they are equals + * false otherwise + */ +bool +ecma_string_compare_to_property_name (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp, /**< property name compressed pointer */ + const ecma_string_t *string_p) /**< other string */ +{ + if (ECMA_PROPERTY_GET_NAME_TYPE (property) != ECMA_DIRECT_STRING_PTR) + { + return ecma_property_to_string (property, prop_name_cp) == string_p; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return false; + } + + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + return ecma_compare_ecma_non_direct_strings (prop_name_p, string_p); +} /* ecma_string_compare_to_property_name */ + +/** + * Helper for ecma_compare_ecma_strings_longpath to get string data + * + * @return string characters + */ +static const lit_utf8_byte_t * +ecma_compare_get_string_chars (const ecma_string_t *string_p, /**< ecma-string */ + lit_utf8_size_t *size_and_length_p) /**< [out] size and length */ +{ + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) string_p; + size_and_length_p[0] = short_string_p->size; + size_and_length_p[1] = short_string_p->length; + return ECMA_SHORT_STRING_GET_BUFFER (string_p); + } + case ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING: + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + size_and_length_p[0] = long_string_p->size; + size_and_length_p[1] = long_string_p->length; + return long_string_p->string_p; + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + size_and_length_p[0] = ECMA_ASCII_STRING_GET_SIZE (string_p); + size_and_length_p[1] = size_and_length_p[0]; + return ECMA_ASCII_STRING_GET_BUFFER (string_p); + } + default: + { + return NULL; + } + } +} /* ecma_compare_get_string_chars */ + +/** + * Long path part of ecma-string to ecma-string comparison routine + * + * See also: + * ecma_compare_ecma_strings + * + * @return true - if strings are equal; + * false - otherwise + */ +static bool JERRY_ATTR_NOINLINE +ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ +{ + const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p; + lit_utf8_size_t string1_size_and_length[2], string2_size_and_length[2]; + + utf8_string1_p = ecma_compare_get_string_chars (string1_p, string1_size_and_length); + utf8_string2_p = ecma_compare_get_string_chars (string2_p, string2_size_and_length); + + if (utf8_string1_p == NULL || utf8_string2_p == NULL) + { + return false; + } + + if (string1_size_and_length[0] != string2_size_and_length[0] + || string1_size_and_length[1] != string2_size_and_length[1]) + { + return false; + } + + return !memcmp ((char *) utf8_string1_p, (char *) utf8_string2_p, string1_size_and_length[0]); +} /* ecma_compare_ecma_strings_longpath */ + +/** + * Compare two ecma-strings + * + * @return true - if strings are equal; + * false - otherwise + */ +bool +ecma_compare_ecma_strings (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ +{ + JERRY_ASSERT (string1_p != NULL && string2_p != NULL); + + /* Fast paths first. */ + if (string1_p == string2_p) + { + return true; + } + + /* Either string is direct, return with false. */ + if (ECMA_IS_DIRECT_STRING (((uintptr_t) string1_p) | ((uintptr_t) string2_p))) + { + return false; + } + + /* Also compares uint32 values in descriptor. */ + if (string1_p->u.hash != string2_p->u.hash) + { + return false; + } + + if (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC; + } + + return ecma_compare_ecma_strings_longpath (string1_p, string2_p); +} /* ecma_compare_ecma_strings */ + +/** + * Compare two non-direct ecma-strings + * + * @return true - if strings are equal; + * false - otherwise + */ +bool +ecma_compare_ecma_non_direct_strings (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ +{ + JERRY_ASSERT (string1_p != NULL && string2_p != NULL); + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string1_p) && !ECMA_IS_DIRECT_STRING (string2_p)); + + /* Fast paths first. */ + if (string1_p == string2_p) + { + return true; + } + + if (string1_p->u.hash != string2_p->u.hash) + { + return false; + } + + if (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC; + } + + return ecma_compare_ecma_strings_longpath (string1_p, string2_p); +} /* ecma_compare_ecma_non_direct_strings */ + +/** + * Relational compare of ecma-strings. + * + * First string is less than second string if: + * - strings are not equal; + * - first string is prefix of second or is lexicographically less than second. + * + * @return true - if first string is less than second string, + * false - otherwise + */ +bool +ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ +{ + if (ecma_compare_ecma_strings (string1_p, string2_p)) + { + return false; + } + + const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p; + lit_utf8_size_t utf8_string1_size, utf8_string2_size; + + lit_utf8_byte_t uint32_to_string_buffer1[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + + if (ECMA_IS_DIRECT_STRING (string1_p)) + { + if (ECMA_GET_DIRECT_STRING_TYPE (string1_p) != ECMA_DIRECT_STRING_UINT) + { + utf8_string1_p = ecma_string_get_chars_fast (string1_p, &utf8_string1_size); + } + else + { + utf8_string1_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string1_p), + uint32_to_string_buffer1, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + utf8_string1_p = uint32_to_string_buffer1; + } + } + else + { + JERRY_ASSERT (string1_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string1_p) != ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + utf8_string1_p = ecma_string_get_chars_fast (string1_p, &utf8_string1_size); + } + else + { + utf8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number, + uint32_to_string_buffer1, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + utf8_string1_p = uint32_to_string_buffer1; + } + } + + if (ECMA_IS_DIRECT_STRING (string2_p)) + { + if (ECMA_GET_DIRECT_STRING_TYPE (string2_p) != ECMA_DIRECT_STRING_UINT) + { + utf8_string2_p = ecma_string_get_chars_fast (string2_p, &utf8_string2_size); + } + else + { + utf8_string2_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string2_p), + uint32_to_string_buffer2, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + utf8_string2_p = uint32_to_string_buffer2; + } + } + else + { + JERRY_ASSERT (string2_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string2_p) != ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + utf8_string2_p = ecma_string_get_chars_fast (string2_p, &utf8_string2_size); + } + else + { + utf8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number, + uint32_to_string_buffer2, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + utf8_string2_p = uint32_to_string_buffer2; + } + } + + return lit_compare_utf8_strings_relational (utf8_string1_p, utf8_string1_size, utf8_string2_p, utf8_string2_size); +} /* ecma_compare_ecma_strings_relational */ + +/** + * Special value to represent that no size is available. + */ +#define ECMA_STRING_NO_ASCII_SIZE 0xffffffff + +/** + * Return the size of uint32 and magic strings. + * The length of these strings are equal to their size. + * + * @return number of characters in the string + */ +static lit_utf8_size_t +ecma_string_get_ascii_size (const ecma_string_t *string_p) /**< ecma-string */ +{ + if (ECMA_IS_DIRECT_STRING (string_p)) + { + switch (ECMA_GET_DIRECT_STRING_TYPE (string_p)) + { + case ECMA_DIRECT_STRING_MAGIC: + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (id >= LIT_MAGIC_STRING__COUNT) + { + return ECMA_STRING_NO_ASCII_SIZE; + } + + JERRY_ASSERT (ECMA_STRING_IS_ASCII (lit_get_magic_string_utf8 (id), lit_get_magic_string_size (id))); + + return lit_get_magic_string_size (id); + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_UINT); + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + return ecma_string_get_uint32_size (uint32_number); + } + } + } + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ecma_string_get_uint32_size (string_p->u.uint32_number); + } + else if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_ASCII_STRING) + { + return ECMA_ASCII_STRING_GET_SIZE (string_p); + } + + return ECMA_STRING_NO_ASCII_SIZE; +} /* ecma_string_get_ascii_size */ + +/** + * Get length of ecma-string + * + * @return number of characters in the string + */ +lit_utf8_size_t +ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */ +{ + lit_utf8_size_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC); + JERRY_ASSERT ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) >= LIT_MAGIC_STRING__COUNT); + + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) - LIT_MAGIC_STRING__COUNT; + return lit_utf8_string_length (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + { + return ((ecma_short_string_t *) string_p)->length; + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING) + { + return ((ecma_long_string_t *) string_p)->length; + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + return lit_utf8_string_length (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); +} /* ecma_string_get_length */ + +/** + * Get length of UTF-8 encoded string length from ecma-string + * + * @return number of characters in the UTF-8 encoded string + */ +lit_utf8_size_t +ecma_string_get_utf8_length (const ecma_string_t *string_p) /**< ecma-string */ +{ + lit_utf8_size_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC); + JERRY_ASSERT ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) >= LIT_MAGIC_STRING__COUNT); + + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) - LIT_MAGIC_STRING__COUNT; + return lit_get_utf8_length_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) string_p; + lit_utf8_size_t size = short_string_p->size; + + if (size == short_string_p->length) + { + return size; + } + + return lit_get_utf8_length_of_cesu8_string (ECMA_SHORT_STRING_GET_BUFFER (string_p), size); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING) + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + lit_utf8_size_t size = long_string_p->size; + + if (size == long_string_p->length) + { + return size; + } + + return lit_get_utf8_length_of_cesu8_string (long_string_p->string_p, size); + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + + return lit_get_utf8_length_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); +} /* ecma_string_get_utf8_length */ + +/** + * Get size of ecma-string + * + * @return number of bytes in the buffer needed to represent the string + */ +lit_utf8_size_t +ecma_string_get_size (const ecma_string_t *string_p) /**< ecma-string */ +{ + lit_utf8_size_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC); + JERRY_ASSERT ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) >= LIT_MAGIC_STRING__COUNT); + + return lit_get_magic_string_ex_size ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) - LIT_MAGIC_STRING__COUNT); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + { + return ((ecma_short_string_t *) string_p)->size; + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING) + { + return ((ecma_long_string_t *) string_p)->size; + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + return lit_get_magic_string_ex_size (LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id); +} /* ecma_string_get_size */ + +/** + * Get the UTF-8 encoded string size from ecma-string + * + * @return number of bytes in the buffer needed to represent an UTF-8 encoded string + */ +lit_utf8_size_t +ecma_string_get_utf8_size (const ecma_string_t *string_p) /**< ecma-string */ +{ + lit_utf8_size_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC); + JERRY_ASSERT ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) >= LIT_MAGIC_STRING__COUNT); + + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) - LIT_MAGIC_STRING__COUNT; + return lit_get_utf8_size_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) string_p; + lit_utf8_size_t size = short_string_p->size; + + if (size == short_string_p->length) + { + return size; + } + + return lit_get_utf8_size_of_cesu8_string (ECMA_SHORT_STRING_GET_BUFFER (string_p), size); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING) + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + + if (long_string_p->size == long_string_p->length) + { + return long_string_p->size; + } + + return lit_get_utf8_size_of_cesu8_string (long_string_p->string_p, long_string_p->size); + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + return lit_get_utf8_size_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); +} /* ecma_string_get_utf8_size */ + +/** + * Get character from specified position in an external ecma-string. + * + * @return character value + */ +static ecma_char_t JERRY_ATTR_NOINLINE +ecma_external_string_get_char_at_pos (lit_utf8_size_t id, /**< id of the external magic string */ + lit_utf8_size_t index) /**< index of character */ +{ + id -= LIT_MAGIC_STRING__COUNT; + const lit_utf8_byte_t *data_p = lit_get_magic_string_ex_utf8 (id); + lit_utf8_size_t size = lit_get_magic_string_ex_size (id); + lit_utf8_size_t length = lit_utf8_string_length (data_p, size); + + if (JERRY_LIKELY (size == length)) + { + return (ecma_char_t) data_p[index]; + } + + return lit_utf8_string_code_unit_at (data_p, size, index); +} /* ecma_external_string_get_char_at_pos */ + +/** + * Get character from specified position in the ecma-string. + * + * @return character value + */ +ecma_char_t +ecma_string_get_char_at_pos (const ecma_string_t *string_p, /**< ecma-string */ + lit_utf8_size_t index) /**< index of character */ +{ + JERRY_ASSERT (index < ecma_string_get_length (string_p)); + + lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + switch (ECMA_GET_DIRECT_STRING_TYPE (string_p)) + { + case ECMA_DIRECT_STRING_MAGIC: + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (JERRY_LIKELY (id < LIT_MAGIC_STRING__COUNT)) + { + /* All magic strings must be ascii strings. */ + const lit_utf8_byte_t *data_p = lit_get_magic_string_utf8 (id); + + return (ecma_char_t) data_p[index]; + } + + return ecma_external_string_get_char_at_pos (id, index); + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_UINT); + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + ecma_uint32_to_utf8_string (uint32_number, uint32_to_string_buffer, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + + return (ecma_char_t) uint32_to_string_buffer[index]; + } + } + } + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) string_p; + lit_utf8_size_t size = short_string_p->size; + const lit_utf8_byte_t *data_p = ECMA_SHORT_STRING_GET_BUFFER (string_p); + + if (JERRY_LIKELY (size == short_string_p->length)) + { + return (ecma_char_t) data_p[index]; + } + + return lit_utf8_string_code_unit_at (data_p, size, index); + } + case ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING: + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + lit_utf8_size_t size = long_string_p->size; + const lit_utf8_byte_t *data_p = long_string_p->string_p; + + if (JERRY_LIKELY (size == long_string_p->length)) + { + return (ecma_char_t) data_p[index]; + } + + return lit_utf8_string_code_unit_at (data_p, size, index); + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + const lit_utf8_byte_t *data_p = ECMA_ASCII_STRING_GET_BUFFER (string_p); + return (ecma_char_t) data_p[index]; + } + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + { + ecma_uint32_to_utf8_string (string_p->u.uint32_number, + uint32_to_string_buffer, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + + return (ecma_char_t) uint32_to_string_buffer[index]; + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + return ecma_external_string_get_char_at_pos (string_p->u.magic_string_ex_id, index); + } + } +} /* ecma_string_get_char_at_pos */ + +/** + * Check if passed string equals to one of magic strings + * and if equal magic string was found, return it's id in 'out_id_p' argument. + * + * @return id - if magic string equal to passed string was found, + * LIT_MAGIC_STRING__COUNT - otherwise. + */ +lit_magic_string_id_t +ecma_get_string_magic (const ecma_string_t *string_p) /**< ecma-string */ +{ + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (string_p, ECMA_DIRECT_STRING_MAGIC)) + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (id < LIT_MAGIC_STRING__COUNT) + { + return (lit_magic_string_id_t) id; + } + } + + return LIT_MAGIC_STRING__COUNT; +} /* ecma_get_string_magic */ + +/** + * Try to calculate hash of the ecma-string + * + * @return calculated hash + */ +lit_string_hash_t +ecma_string_hash (const ecma_string_t *string_p) /**< ecma-string to calculate hash for */ +{ + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return (lit_string_hash_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + } + + return (lit_string_hash_t) string_p->u.hash; +} /* ecma_string_hash */ + +/** + * Create a substring from an ecma string + * + * @return a newly consturcted ecma string with its value initialized to a copy of a substring of the first argument + */ +ecma_string_t * +ecma_string_substr (const ecma_string_t *string_p, /**< pointer to an ecma string */ + lit_utf8_size_t start_pos, /**< start position, should be less or equal than string length */ + lit_utf8_size_t end_pos) /**< end position, should be less or equal than string length */ +{ + const lit_utf8_size_t string_length = ecma_string_get_length (string_p); + JERRY_ASSERT (start_pos <= string_length); + JERRY_ASSERT (end_pos <= string_length); + + if (start_pos >= end_pos) + { + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_string_t *ecma_string_p = NULL; + end_pos -= start_pos; + + ECMA_STRING_TO_UTF8_STRING (string_p, start_p, buffer_size); + + if (string_length == buffer_size) + { + ecma_string_p = ecma_new_ecma_string_from_utf8 (start_p + start_pos, (lit_utf8_size_t) end_pos); + } + else + { + while (start_pos--) + { + start_p += lit_get_unicode_char_size_by_utf8_first_byte (*start_p); + } + + const lit_utf8_byte_t *end_p = start_p; + while (end_pos--) + { + end_p += lit_get_unicode_char_size_by_utf8_first_byte (*end_p); + } + + ecma_string_p = ecma_new_ecma_string_from_utf8 (start_p, (lit_utf8_size_t) (end_p - start_p)); + } + + ECMA_FINALIZE_UTF8_STRING (start_p, buffer_size); + + return ecma_string_p; +} /* ecma_string_substr */ + +/** + * Helper function for trimming. + * + * Used by: + * - ecma_string_trim_helper + * - ecma_builtin_global_object_parse_int + * - ecma_builtin_global_object_parse_float + * + * @return position of the first non whitespace character. + */ +const lit_utf8_byte_t * +ecma_string_trim_front (const lit_utf8_byte_t *start_p, /**< current string's start position */ + const lit_utf8_byte_t *end_p) /**< current string's end position */ +{ + ecma_char_t ch; + + while (start_p < end_p) + { + lit_utf8_size_t read_size = lit_read_code_unit_from_cesu8 (start_p, &ch); + + if (!lit_char_is_white_space (ch)) + { + break; + } + + start_p += read_size; + } + + return start_p; +} /* ecma_string_trim_front */ + +/** + * Helper function for trimming. + * + * Used by: + * - ecma_string_trim_helper + * + * @return position of the last non whitespace character. + */ +const lit_utf8_byte_t * +ecma_string_trim_back (const lit_utf8_byte_t *start_p, /**< current string's start position */ + const lit_utf8_byte_t *end_p) /**< current string's end position */ +{ + ecma_char_t ch; + + while (end_p > start_p) + { + lit_utf8_size_t read_size = lit_read_prev_code_unit_from_utf8 (end_p, &ch); + + if (!lit_char_is_white_space (ch)) + { + break; + } + + end_p -= read_size; + } + + return end_p; +} /* ecma_string_trim_back */ + +/** + * Helper function for trimming. + * + * Used by: + * - ecma_string_trim + * - ecma_utf8_string_to_number + * + * @return void + */ +void +ecma_string_trim_helper (const lit_utf8_byte_t **utf8_str_p, /**< [in, out] current string position */ + lit_utf8_size_t *utf8_str_size) /**< [in, out] size of the given string */ +{ + const lit_utf8_byte_t *end_p = *utf8_str_p + *utf8_str_size; + const lit_utf8_byte_t *start_p = *utf8_str_p; + + const lit_utf8_byte_t *new_start_p = ecma_string_trim_front (start_p, end_p); + const lit_utf8_byte_t *new_end_p = ecma_string_trim_back (new_start_p, end_p); + + *utf8_str_size = (lit_utf8_size_t) (new_end_p - new_start_p); + *utf8_str_p = new_start_p; +} /* ecma_string_trim_helper */ + +/** + * Trim leading and trailing whitespace characters from string. + * + * @return trimmed ecma string + */ +ecma_string_t * +ecma_string_trim (const ecma_string_t *string_p) /**< pointer to an ecma string */ +{ + ecma_string_t *ret_string_p; + + lit_utf8_size_t utf8_str_size; + uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; + const lit_utf8_byte_t *utf8_str_p = ecma_string_get_chars (string_p, &utf8_str_size, NULL, NULL, &flags); + + if (utf8_str_size > 0) + { + ecma_string_trim_helper (&utf8_str_p, &utf8_str_size); + ret_string_p = ecma_new_ecma_string_from_utf8 (utf8_str_p, utf8_str_size); + } + else + { + ret_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + if (flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) utf8_str_p, utf8_str_size); + } + + return ret_string_p; +} /* ecma_string_trim */ + +/** + * Pad the beginning or the end of string with parameter given in fill_string to the length of max_length. + * + * @return new string from original, padded with given parameters + */ +ecma_value_t +ecma_string_pad (ecma_value_t original_string_p, /**< Input ecma string */ + ecma_value_t max_length, /**< Length to pad to, including original length */ + ecma_value_t fill_string, /**< The string to pad with */ + bool pad_on_start) /**< true - if we are padding to the start, calling with padStart + false - if we are padding to the end, calling with padEnd */ +{ + /* 3 */ + ecma_length_t int_max_length; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_length (max_length, &int_max_length))) + { + return ECMA_VALUE_ERROR; + } + /* 4 */ + ecma_string_t *original_str_val_p = ecma_get_string_from_value (original_string_p); + const uint32_t string_length = ecma_string_get_length (original_str_val_p); + /* 5 */ + if (int_max_length <= string_length) + { + ecma_ref_ecma_string (original_str_val_p); + return original_string_p; + } + + ecma_string_t *filler_p = ecma_get_magic_string (LIT_MAGIC_STRING_SPACE_CHAR); + /* 6 - 7 */ + if (!ecma_is_value_undefined (fill_string)) + { + filler_p = ecma_op_to_string (fill_string); + if (filler_p == NULL) + { + return ECMA_VALUE_ERROR; + } + if (ecma_string_is_empty (filler_p)) + { + ecma_ref_ecma_string (original_str_val_p); + return original_string_p; + } + } + + if (int_max_length >= UINT32_MAX) + { + ecma_deref_ecma_string (filler_p); + return ecma_raise_range_error (ECMA_ERR_MAXIMUM_STRING_LENGTH_IS_REACHED); + } + + /* 9 */ + uint32_t fill_len = (uint32_t) int_max_length - string_length; + + /* 10 */ + uint32_t filler_length = ecma_string_get_length (filler_p); + uint32_t prepend_count = fill_len / filler_length; + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + if (!pad_on_start) + { + ecma_stringbuilder_append (&builder, original_str_val_p); + } + + for (uint32_t i = 0; i < prepend_count; i++) + { + ecma_stringbuilder_append (&builder, filler_p); + } + + uint32_t remaining = fill_len - (prepend_count * filler_length); + + ECMA_STRING_TO_UTF8_STRING (filler_p, start_p, utf8_str_size); + const lit_utf8_byte_t *temp_start_p = start_p; + while (remaining > 0) + { + ecma_char_t ch; + lit_utf8_size_t read_size = lit_read_code_unit_from_cesu8 (temp_start_p, &ch); + ecma_stringbuilder_append_char (&builder, ch); + temp_start_p += read_size; + remaining--; + } + ECMA_FINALIZE_UTF8_STRING (start_p, utf8_str_size); + ecma_deref_ecma_string (filler_p); + + /* 11 - 12 */ + if (pad_on_start) + { + ecma_stringbuilder_append (&builder, original_str_val_p); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_string_pad */ + +/** + * Create an empty string builder + * + * @return new string builder + */ +ecma_stringbuilder_t +ecma_stringbuilder_create (void) +{ + const lit_utf8_size_t initial_size = ECMA_ASCII_STRING_HEADER_SIZE; + ecma_stringbuilder_header_t *header_p = (ecma_stringbuilder_header_t *) jmem_heap_alloc_block (initial_size); + header_p->current_size = initial_size; + + ecma_stringbuilder_t ret = { header_p }; + return ret; +} /* ecma_stringbuilder_create */ + +/** + * Create a string builder from an ecma string + * + * @return new string builder + */ +ecma_stringbuilder_t +ecma_stringbuilder_create_from (ecma_string_t *string_p) /**< ecma string */ +{ + const lit_utf8_size_t string_size = ecma_string_get_size (string_p); + const lit_utf8_size_t initial_size = string_size + ECMA_ASCII_STRING_HEADER_SIZE; + + ecma_stringbuilder_header_t *header_p = (ecma_stringbuilder_header_t *) jmem_heap_alloc_block (initial_size); + header_p->current_size = initial_size; + + ecma_string_to_cesu8_bytes (string_p, ECMA_STRINGBUILDER_STRING_PTR (header_p), string_size); + + ecma_stringbuilder_t ret = { header_p }; + return ret; +} /* ecma_stringbuilder_create_from */ + +/** + * Create a string builder from a raw string + * + * @return new string builder + */ +ecma_stringbuilder_t +ecma_stringbuilder_create_raw (const lit_utf8_byte_t *data_p, /**< pointer to data */ + const lit_utf8_size_t data_size) /**< size of the data */ +{ + const lit_utf8_size_t initial_size = data_size + ECMA_ASCII_STRING_HEADER_SIZE; + + ecma_stringbuilder_header_t *header_p = (ecma_stringbuilder_header_t *) jmem_heap_alloc_block (initial_size); + header_p->current_size = initial_size; + + memcpy (ECMA_STRINGBUILDER_STRING_PTR (header_p), data_p, data_size); + + ecma_stringbuilder_t ret = { header_p }; + return ret; +} /* ecma_stringbuilder_create_raw */ + +/** + * Grow the underlying buffer of a string builder + * + * @return pointer to the end of the data in the underlying buffer + */ +static lit_utf8_byte_t * +ecma_stringbuilder_grow (ecma_stringbuilder_t *builder_p, /**< string builder */ + lit_utf8_size_t required_size) /**< required size */ +{ + ecma_stringbuilder_header_t *header_p = builder_p->header_p; + JERRY_ASSERT (header_p != NULL); + + const lit_utf8_size_t new_size = header_p->current_size + required_size; + header_p = (ecma_stringbuilder_header_t *) jmem_heap_realloc_block (header_p, header_p->current_size, new_size); + header_p->current_size = new_size; + builder_p->header_p = header_p; + + return ((lit_utf8_byte_t *) header_p) + header_p->current_size - required_size; +} /* ecma_stringbuilder_grow */ + +/** + * Get the current size of the string in a string builder + * + * @return the size of the string data + */ +lit_utf8_size_t +ecma_stringbuilder_get_size (ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + ecma_stringbuilder_header_t *header_p = builder_p->header_p; + JERRY_ASSERT (header_p != NULL); + + return ECMA_STRINGBUILDER_STRING_SIZE (header_p); +} /* ecma_stringbuilder_get_size */ + +/** + * Get pointer to the raw string data in a string builder + * + * @return pointer to the string data + */ +lit_utf8_byte_t * +ecma_stringbuilder_get_data (ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + ecma_stringbuilder_header_t *header_p = builder_p->header_p; + JERRY_ASSERT (header_p != NULL); + + return ECMA_STRINGBUILDER_STRING_PTR (header_p); +} /* ecma_stringbuilder_get_data */ + +/** + * Revert the string builder to a smaller size + */ +void +ecma_stringbuilder_revert (ecma_stringbuilder_t *builder_p, /**< string builder */ + const lit_utf8_size_t size) /**< new size */ +{ + ecma_stringbuilder_header_t *header_p = builder_p->header_p; + JERRY_ASSERT (header_p != NULL); + + const lit_utf8_size_t new_size = size + ECMA_ASCII_STRING_HEADER_SIZE; + JERRY_ASSERT (new_size <= header_p->current_size); + + header_p = (ecma_stringbuilder_header_t *) jmem_heap_realloc_block (header_p, header_p->current_size, new_size); + header_p->current_size = new_size; + builder_p->header_p = header_p; +} /* ecma_stringbuilder_revert */ + +/** + * Append an ecma_string_t to a string builder + */ +void +ecma_stringbuilder_append (ecma_stringbuilder_t *builder_p, /**< string builder */ + const ecma_string_t *string_p) /**< ecma string */ +{ + const lit_utf8_size_t string_size = ecma_string_get_size (string_p); + lit_utf8_byte_t *dest_p = ecma_stringbuilder_grow (builder_p, string_size); + + ecma_string_to_cesu8_bytes (string_p, dest_p, string_size); +} /* ecma_stringbuilder_append */ + +/** + * Append a magic string to a string builder + */ +void +ecma_stringbuilder_append_magic (ecma_stringbuilder_t *builder_p, /**< string builder */ + const lit_magic_string_id_t id) /**< magic string id */ +{ + const lit_utf8_size_t string_size = lit_get_magic_string_size (id); + lit_utf8_byte_t *dest_p = ecma_stringbuilder_grow (builder_p, string_size); + + const lit_utf8_byte_t *string_data_p = lit_get_magic_string_utf8 (id); + memcpy (dest_p, string_data_p, string_size); +} /* ecma_stringbuilder_append_magic */ + +/** + * Append raw string data to a string builder + */ +void +ecma_stringbuilder_append_raw (ecma_stringbuilder_t *builder_p, /**< string builder */ + const lit_utf8_byte_t *data_p, /**< pointer to data */ + const lit_utf8_size_t data_size) /**< size of the data */ +{ + lit_utf8_byte_t *dest_p = ecma_stringbuilder_grow (builder_p, data_size); + memcpy (dest_p, data_p, data_size); +} /* ecma_stringbuilder_append_raw */ + +/** + * Append a codepoint to a string builder + */ +void +ecma_stringbuilder_append_codepoint (ecma_stringbuilder_t *builder_p, /**< string builder */ + lit_code_point_t cp) /**< code point */ +{ + const lit_utf8_size_t size = (lit_utf8_size_t) lit_code_point_get_cesu8_length (cp); + lit_utf8_byte_t *dest_p = ecma_stringbuilder_grow (builder_p, size); + + lit_code_point_to_cesu8_bytes (dest_p, cp); +} /* ecma_stringbuilder_append_codepoint */ + +/** + * Append an ecma_char_t to a string builder + */ +void +ecma_stringbuilder_append_char (ecma_stringbuilder_t *builder_p, /**< string builder */ + const ecma_char_t c) /**< ecma char */ +{ + ecma_stringbuilder_append_codepoint (builder_p, c); +} /* ecma_stringbuilder_append_char */ + +/** + * Append a single byte to a string builder + */ +void +ecma_stringbuilder_append_byte (ecma_stringbuilder_t *builder_p, /**< string builder */ + const lit_utf8_byte_t byte) /**< byte */ +{ + lit_utf8_byte_t *dest_p = ecma_stringbuilder_grow (builder_p, 1); + *dest_p = byte; +} /* ecma_stringbuilder_append_byte */ + +/** + * Finalize a string builder, returning the created string, and releasing the underlying buffer. + * + * Note: + * The builder should no longer be used. + * + * @return the created string + */ +ecma_string_t * +ecma_stringbuilder_finalize (ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + ecma_stringbuilder_header_t *header_p = builder_p->header_p; + JERRY_ASSERT (header_p != NULL); + + const lit_utf8_size_t string_size = ECMA_STRINGBUILDER_STRING_SIZE (header_p); + lit_utf8_byte_t *string_begin_p = ECMA_STRINGBUILDER_STRING_PTR (header_p); + + ecma_string_t *string_p = ecma_find_special_string (string_begin_p, string_size); + + if (JERRY_UNLIKELY (string_p != NULL)) + { + ecma_stringbuilder_destroy (builder_p); + return string_p; + } + +#ifndef JERRY_NDEBUG + builder_p->header_p = NULL; +#endif /* !defined (JERRY_NDEBUG) */ + + size_t container_size = sizeof (ecma_short_string_t); + const lit_string_hash_t hash = lit_utf8_string_calc_hash (string_begin_p, string_size); + const lit_utf8_size_t length = lit_utf8_string_length (string_begin_p, string_size); + + if (JERRY_LIKELY (string_size <= UINT16_MAX)) + { + if (JERRY_LIKELY (length == string_size) && string_size <= (UINT8_MAX + 1)) + { + string_p = (ecma_string_t *) header_p; + string_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_ASCII_STRING | ECMA_STRING_REF_ONE; + string_p->u.hash = hash; + ECMA_ASCII_STRING_SET_SIZE (string_p, string_size); + + return (ecma_string_t *) string_p; + } + } + else + { + container_size = sizeof (ecma_long_string_t); + } + + const size_t utf8_string_size = string_size + container_size; + header_p = (ecma_stringbuilder_header_t *) jmem_heap_realloc_block (header_p, header_p->current_size, utf8_string_size); + memmove (((lit_utf8_byte_t *) header_p + container_size), ECMA_STRINGBUILDER_STRING_PTR (header_p), string_size); + + if (JERRY_LIKELY (string_size <= UINT16_MAX)) + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) header_p; + + short_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; + short_string_p->header.u.hash = hash; + short_string_p->size = (uint16_t) string_size; + short_string_p->length = (uint16_t) length; + + return (ecma_string_t *) short_string_p; + } + + ecma_long_string_t *long_string_p = (ecma_long_string_t *) header_p; + + long_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING | ECMA_STRING_REF_ONE; + long_string_p->header.u.hash = hash; + long_string_p->string_p = ECMA_LONG_STRING_BUFFER_START (long_string_p); + long_string_p->size = string_size; + long_string_p->length = length; + + return (ecma_string_t *) long_string_p; +} /* ecma_stringbuilder_finalize */ + +/** + * Destroy a string builder that is no longer needed without creating a string from the contents. + */ +void +ecma_stringbuilder_destroy (ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + JERRY_ASSERT (builder_p->header_p != NULL); + const lit_utf8_size_t size = builder_p->header_p->current_size; + jmem_heap_free_block (builder_p->header_p, size); + +#ifndef JERRY_NDEBUG + builder_p->header_p = NULL; +#endif /* !defined (JERRY_NDEBUG) */ + +} /* ecma_stringbuilder_destroy */ + +/** + * AdvanceStringIndex operation + * + * See also: + * ECMA-262 v6.0, 21.2.5.2.3 + * + * @return uint32_t - the proper character index based on the operation + */ +ecma_length_t +ecma_op_advance_string_index (ecma_string_t *str_p, /**< input string */ + ecma_length_t index, /**< given character index */ + bool is_unicode) /**< true - if regexp object's "unicode" flag is set + false - otherwise */ +{ + JERRY_ASSERT ((ecma_number_t) index <= ECMA_NUMBER_MAX_SAFE_INTEGER); + ecma_length_t next_index = index + 1; + + if (!is_unicode) + { + return next_index; + } + + lit_utf8_size_t str_len = ecma_string_get_length (str_p); + + if (next_index >= str_len) + { + return next_index; + } + + JERRY_ASSERT (index < UINT32_MAX); + ecma_char_t first = ecma_string_get_char_at_pos (str_p, (lit_utf8_size_t) index); + + if (!lit_is_code_point_utf16_high_surrogate (first)) + { + return next_index; + } + + ecma_char_t second = ecma_string_get_char_at_pos (str_p, (lit_utf8_size_t) next_index); + + if (!lit_is_code_point_utf16_low_surrogate (second)) + { + return next_index; + } + + return next_index + 1; +} /* ecma_op_advance_string_index */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-value.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-value.cpp new file mode 100644 index 00000000..cf7826b9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-value.cpp @@ -0,0 +1,1257 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" + +#include "jrt-bit-fields.h" +#include "jrt.h" +#include "vm-defines.h" + +JERRY_STATIC_ASSERT (((int)ECMA_TYPE___MAX <= (int)ECMA_VALUE_TYPE_MASK), ecma_types_must_be_less_than_mask); + +JERRY_STATIC_ASSERT (((ECMA_VALUE_TYPE_MASK + 1) == (1 << ECMA_VALUE_SHIFT)), ecma_value_part_must_start_after_flags); + +JERRY_STATIC_ASSERT (((int)ECMA_VALUE_SHIFT <= (int)JMEM_ALIGNMENT_LOG), + ecma_value_shift_must_be_less_than_or_equal_than_mem_alignment_log); + +JERRY_STATIC_ASSERT ((sizeof (jmem_cpointer_t) <= sizeof (ecma_value_t)), + size_of_jmem_cpointer_t_must_be_less_or_equal_to_the_size_of_ecma_value_t); + +JERRY_STATIC_ASSERT ((sizeof (jmem_cpointer_t) <= sizeof (jmem_cpointer_tag_t)), + size_of_jmem_cpointer_t_must_be_less_or_equal_to_the_size_of_jmem_cpointer_tag_t); + +#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + +/* cppcheck-suppress zerodiv */ +JERRY_STATIC_ASSERT (sizeof (uintptr_t) <= sizeof (ecma_value_t), uintptr_t_must_fit_in_ecma_value_t); + +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + +JERRY_STATIC_ASSERT ((sizeof (uintptr_t) > sizeof (ecma_value_t)), uintptr_t_must_not_fit_in_ecma_value_t); + +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + +JERRY_STATIC_ASSERT ((((int)ECMA_VALUE_FALSE | (1 << (int)ECMA_DIRECT_SHIFT)) == (int)ECMA_VALUE_TRUE) + && ECMA_VALUE_FALSE != ECMA_VALUE_TRUE, + only_the_lowest_bit_must_be_different_for_simple_value_true_and_false); + +#if JERRY_BUILTIN_BIGINT + +JERRY_STATIC_ASSERT (ECMA_NULL_POINTER == (ECMA_BIGINT_ZERO & ~(ecma_value_t) ECMA_VALUE_TYPE_MASK), + ecma_bigint_zero_must_be_encoded_as_null_pointer); + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +/** + * Get type field of ecma value + * + * @return type field + */ +ecma_type_t JERRY_ATTR_CONST +ecma_get_value_type_field (ecma_value_t value) /**< ecma value */ +{ + return (ecma_type_t)(((unsigned int) value) & ((unsigned int)ECMA_VALUE_TYPE_MASK)); +} /* ecma_get_value_type_field */ + +/** + * Convert a pointer into an ecma value. + * + * @return ecma value + */ +static inline ecma_value_t JERRY_ATTR_PURE +ecma_pointer_to_ecma_value (const void *ptr) /**< pointer */ +{ +#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + + JERRY_ASSERT (ptr != NULL); + uintptr_t uint_ptr = (uintptr_t) ptr; + JERRY_ASSERT ((uint_ptr & ECMA_VALUE_TYPE_MASK) == 0); + return (ecma_value_t) uint_ptr; + +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + + jmem_cpointer_t ptr_cp; + ECMA_SET_NON_NULL_POINTER (ptr_cp, ptr); + return ((ecma_value_t) ptr_cp) << ECMA_VALUE_SHIFT; + +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ +} /* ecma_pointer_to_ecma_value */ + +/** + * Get a pointer from an ecma value + * + * @return pointer + */ +static inline void *JERRY_ATTR_PURE +ecma_get_pointer_from_ecma_value (ecma_value_t value) /**< value */ +{ +#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + void *ptr = (void *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK); + JERRY_ASSERT (ptr != NULL); + return ptr; +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + return ECMA_GET_NON_NULL_POINTER (void, value >> ECMA_VALUE_SHIFT); +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ +} /* ecma_get_pointer_from_ecma_value */ + +/** + * Check if the value is direct ecma-value. + * + * @return true - if the value is a direct value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_direct (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT); +} /* ecma_is_value_direct */ + +/** + * Check if the value is simple ecma-value. + * + * @return true - if the value is a simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_simple (ecma_value_t value) /**< ecma value */ +{ + return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_SIMPLE_VALUE; +} /* ecma_is_value_simple */ + +/** + * Check whether the value is a given simple value. + * + * @return true - if the value is equal to the given simple value, + * false - otherwise + */ +static inline bool JERRY_ATTR_CONST +ecma_is_value_equal_to_simple_value (ecma_value_t value, /**< ecma value */ + ecma_value_t simple_value) /**< simple value */ +{ + return value == simple_value; +} /* ecma_is_value_equal_to_simple_value */ + +/** + * Check if the value is empty. + * + * @return true - if the value contains implementation-defined empty simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_empty (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_EMPTY); +} /* ecma_is_value_empty */ + +/** + * Check if the value is undefined. + * + * @return true - if the value contains ecma-undefined simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_undefined (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_UNDEFINED); +} /* ecma_is_value_undefined */ + +/** + * Check if the value is null. + * + * @return true - if the value contains ecma-null simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_null (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_NULL); +} /* ecma_is_value_null */ + +/** + * Check if the value is boolean. + * + * @return true - if the value contains ecma-true or ecma-false simple values, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_boolean (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_true (value | (1 << ECMA_DIRECT_SHIFT)); +} /* ecma_is_value_boolean */ + +/** + * Check if the value is true. + * + * @return true - if the value contains ecma-true simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_true (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_TRUE); +} /* ecma_is_value_true */ + +/** + * Check if the value is false. + * + * @return true - if the value contains ecma-false simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_false (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_FALSE); +} /* ecma_is_value_false */ + +/** + * Check if the value is not found. + * + * @return true - if the value contains ecma-not-found simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_found (ecma_value_t value) /**< ecma value */ +{ + return value != ECMA_VALUE_NOT_FOUND; +} /* ecma_is_value_found */ + +/** + * Check if the value is array hole. + * + * @return true - if the value contains ecma-array-hole simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_array_hole (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_ARRAY_HOLE); +} /* ecma_is_value_array_hole */ + +/** + * Check if the value is integer ecma-number. + * + * @return true - if the value contains an integer ecma-number value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_integer_number (ecma_value_t value) /**< ecma value */ +{ + return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE; +} /* ecma_is_value_integer_number */ + +/** + * Check if both values are integer ecma-numbers. + * + * @return true - if both values contain integer ecma-number values, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_are_values_integer_numbers (ecma_value_t first_value, /**< first ecma value */ + ecma_value_t second_value) /**< second ecma value */ +{ + JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_INTEGER_VALUE == 0, ecma_direct_type_integer_value_must_be_zero); + + return ((first_value | second_value) & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE; +} /* ecma_are_values_integer_numbers */ + +/** + * Check if the value is floating-point ecma-number. + * + * @return true - if the value contains a floating-point ecma-number value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_float_number (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT); +} /* ecma_is_value_float_number */ + +/** + * Check if the value is ecma-number. + * + * @return true - if the value contains ecma-number value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_number (ecma_value_t value) /**< ecma value */ +{ + return (ecma_is_value_integer_number (value) || ecma_is_value_float_number (value)); +} /* ecma_is_value_number */ + +JERRY_STATIC_ASSERT (((ECMA_TYPE_STRING | 0x4) == ECMA_TYPE_DIRECT_STRING), + ecma_type_string_and_direct_string_must_have_one_bit_difference); + +/** + * Check if the value is ecma-string. + * + * @return true - if the value contains ecma-string value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_string (ecma_value_t value) /**< ecma value */ +{ + return ((value & (ECMA_VALUE_TYPE_MASK - 0x4)) == ECMA_TYPE_STRING); +} /* ecma_is_value_string */ + +/** + * Check if the value is symbol. + * + * @return true - if the value contains symbol value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_symbol (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_SYMBOL); +} /* ecma_is_value_symbol */ + +/** + * Check if the value is a specific magic string. + * + * @return true - if the value the magic string value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_magic_string (ecma_value_t value, /**< ecma value */ + lit_magic_string_id_t id) /**< magic string id */ +{ + return value == ecma_make_magic_string_value (id); +} /* ecma_is_value_magic_string */ + +/** + * Check if the value is bigint. + * + * @return true - if the value contains bigint value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_bigint (ecma_value_t value) /**< ecma value */ +{ +#if JERRY_BUILTIN_BIGINT + return (ecma_get_value_type_field (value) == ECMA_TYPE_BIGINT); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_BIGINT */ +} /* ecma_is_value_bigint */ + +/** + * Check if the value can be property name. + * + * @return true - if the value can be property name value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_prop_name (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_string (value) || ecma_is_value_symbol (value); +} /* ecma_is_value_prop_name */ + +/** + * Check if the value is direct ecma-string. + * + * @return true - if the value contains direct ecma-string value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_direct_string (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING); +} /* ecma_is_value_direct_string */ + +/** + * Check if the value is non-direct ecma-string. + * + * @return true - if the value contains non-direct ecma-string value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_non_direct_string (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_STRING); +} /* ecma_is_value_non_direct_string */ + +/** + * Check if the value is object. + * + * @return true - if the value contains object value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_object (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT); +} /* ecma_is_value_object */ + +/** + * Check if the value is error reference. + * + * @return true - if the value contains an error reference, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_exception (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR); +} /* ecma_is_value_exception */ + +/** + * Debug assertion that specified value's type is one of ECMA-defined + * script-visible types, i.e.: undefined, null, boolean, number, string, object. + */ +void +ecma_check_value_type_is_spec_defined (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_undefined (value) || ecma_is_value_null (value) || ecma_is_value_boolean (value) + || ecma_is_value_number (value) || ecma_is_value_string (value) || ecma_is_value_bigint (value) + || ecma_is_value_symbol (value) || ecma_is_value_object (value)); +} /* ecma_check_value_type_is_spec_defined */ + +/** + * Checks if the given argument is an array or not. + * + * @return ECMA_VALUE_ERROR- if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether 'arg' is an array object + */ +ecma_value_t +ecma_is_value_array (ecma_value_t arg) /**< argument */ +{ + if (!ecma_is_value_object (arg)) + { + return ECMA_VALUE_FALSE; + } + + ecma_object_t *arg_obj_p = ecma_get_object_from_value (arg); + + if (ecma_get_object_base_type (arg_obj_p) == ECMA_OBJECT_BASE_TYPE_ARRAY) + { + return ECMA_VALUE_TRUE; + } + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (arg_obj_p)) + { + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) arg_obj_p; + + if (proxy_obj_p->handler == ECMA_VALUE_NULL) + { + return ecma_raise_type_error (ECMA_ERR_PROXY_HANDLER_IS_NULL_FOR_ISARRAY_OPERATION); + } + + return ecma_is_value_array (proxy_obj_p->target); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ECMA_VALUE_FALSE; +} /* ecma_is_value_array */ + +/** + * Creates an ecma value from the given raw boolean. + * + * @return boolean ecma_value + */ +ecma_value_t JERRY_ATTR_CONST +ecma_make_boolean_value (bool boolean_value) /**< raw bool value from which the ecma value will be created */ +{ + return boolean_value ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE; +} /* ecma_make_boolean_value */ + +/** + * Encode an integer number into an ecma-value without allocating memory + * + * Note: + * The value must fit into the range of allowed ecma integer values + * + * @return ecma-value + */ +ecma_value_t JERRY_ATTR_CONST +ecma_make_integer_value (ecma_integer_value_t integer_value) /**< integer number to be encoded */ +{ + JERRY_ASSERT (ECMA_IS_INTEGER_NUMBER (integer_value)); + + return (((ecma_value_t) integer_value) << ECMA_DIRECT_SHIFT) | ECMA_DIRECT_TYPE_INTEGER_VALUE; +} /* ecma_make_integer_value */ + +/** + * Allocate and initialize a new float number without checks. + * + * @return ecma-value + */ +static ecma_value_t +ecma_create_float_number (ecma_number_t ecma_number) /**< value of the float number */ +{ + ecma_number_t *ecma_num_p = ecma_alloc_number (); + + *ecma_num_p = ecma_number; + + return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT; +} /* ecma_create_float_number */ + +/** + * Encode float number without checks. + * + * @return ecma-value + */ +ecma_value_t +ecma_make_float_value (ecma_number_t *ecma_num_p) /**< pointer to the float number */ +{ + return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT; +} /* ecma_make_float_value */ + +/** + * Create a new NaN value. + * + * @return ecma-value + */ +ecma_value_t JERRY_ATTR_CONST +ecma_make_nan_value (void) +{ + return ecma_create_float_number (ecma_number_make_nan ()); +} /* ecma_make_nan_value */ + +/** + * Checks whether the passed number is +0.0 + * + * @return true, if it is +0.0, false otherwise + */ +static inline bool JERRY_ATTR_CONST +ecma_is_number_equal_to_positive_zero (ecma_number_t ecma_number) /**< number */ +{ + return ecma_number_to_binary (ecma_number) == ECMA_NUMBER_BINARY_ZERO; +} /* ecma_is_number_equal_to_positive_zero */ + +/** + * Encode a property length number into an ecma-value + * + * @return ecma-value + */ +ecma_value_t +ecma_make_length_value (ecma_length_t number) /**< number to be encoded */ +{ + if (number <= ECMA_INTEGER_NUMBER_MAX) + { + return ecma_make_integer_value ((ecma_integer_value_t) number); + } + + return ecma_create_float_number ((ecma_number_t) number); +} /* ecma_make_length_value */ + +/** + * Encode a number into an ecma-value + * + * @return ecma-value + */ +ecma_value_t +ecma_make_number_value (ecma_number_t ecma_number) /**< number to be encoded */ +{ + ecma_integer_value_t integer_value = (ecma_integer_value_t) ecma_number; + + if ((ecma_number_t) integer_value == ecma_number + && ((integer_value == 0) ? ecma_is_number_equal_to_positive_zero (ecma_number) + : ECMA_IS_INTEGER_NUMBER (integer_value))) + { + return ecma_make_integer_value (integer_value); + } + + return ecma_create_float_number (ecma_number); +} /* ecma_make_number_value */ + +/** + * Encode an int32 number into an ecma-value + * + * @return ecma-value + */ +ecma_value_t +ecma_make_int32_value (int32_t int32_number) /**< int32 number to be encoded */ +{ + if (ECMA_IS_INTEGER_NUMBER (int32_number)) + { + return ecma_make_integer_value ((ecma_integer_value_t) int32_number); + } + + return ecma_create_float_number ((ecma_number_t) int32_number); +} /* ecma_make_int32_value */ + +/** + * Encode an unsigned int32 number into an ecma-value + * + * @return ecma-value + */ +ecma_value_t +ecma_make_uint32_value (uint32_t uint32_number) /**< uint32 number to be encoded */ +{ + if (uint32_number <= ECMA_INTEGER_NUMBER_MAX) + { + return ecma_make_integer_value ((ecma_integer_value_t) uint32_number); + } + + return ecma_create_float_number ((ecma_number_t) uint32_number); +} /* ecma_make_uint32_value */ + +/** + * String value constructor + * + * @return ecma-value representation of the string argument + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to reference in value */ +{ + JERRY_ASSERT (ecma_string_p != NULL); + JERRY_ASSERT (!ecma_prop_name_is_symbol ((ecma_string_t *) ecma_string_p)); + + if ((((uintptr_t) ecma_string_p) & ECMA_VALUE_TYPE_MASK) != 0) + { + return (ecma_value_t) (uintptr_t) ecma_string_p; + } + + return ecma_pointer_to_ecma_value (ecma_string_p) | ECMA_TYPE_STRING; +} /* ecma_make_string_value */ + +/** + * Symbol value constructor + * + * @return ecma-value representation of the string argument + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_symbol_value (const ecma_string_t *ecma_symbol_p) /**< symbol to reference in value */ +{ + JERRY_ASSERT (ecma_symbol_p != NULL); + JERRY_ASSERT (ecma_prop_name_is_symbol ((ecma_string_t *) ecma_symbol_p)); + + return ecma_pointer_to_ecma_value (ecma_symbol_p) | ECMA_TYPE_SYMBOL; +} /* ecma_make_symbol_value */ + +/** + * Property-name value constructor + * + * @return ecma-value representation of a property name argument + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_prop_name_value (const ecma_string_t *ecma_prop_name_p) /**< property name to reference in value */ +{ + JERRY_ASSERT (ecma_prop_name_p != NULL); + + if (ecma_prop_name_is_symbol ((ecma_string_t *) ecma_prop_name_p)) + { + return ecma_make_symbol_value (ecma_prop_name_p); + } + + return ecma_make_string_value (ecma_prop_name_p); +} /* ecma_make_prop_name_value */ + +/** + * String value constructor + * + * @return ecma-value representation of the string argument + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_magic_string_value (lit_magic_string_id_t id) /**< magic string id */ +{ + return (ecma_value_t) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_MAGIC, (uintptr_t) id); +} /* ecma_make_magic_string_value */ + +/** + * Object value constructor + * + * @return ecma-value representation of the object argument + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_object_value (const ecma_object_t *object_p) /**< object to reference in value */ +{ + JERRY_ASSERT (object_p != NULL); + + return ecma_pointer_to_ecma_value (object_p) | ECMA_TYPE_OBJECT; +} /* ecma_make_object_value */ + +/** + * Error reference constructor + * + * @return ecma-value representation of the Error reference + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_extended_primitive_value (const ecma_extended_primitive_t *primitve_p, /**< extended primitve value */ + uint32_t type) /**< ecma type of extended primitve value */ +{ + JERRY_ASSERT (primitve_p != NULL); +#if JERRY_BUILTIN_BIGINT + JERRY_ASSERT (primitve_p != ECMA_BIGINT_POINTER_TO_ZERO); +#endif /* JERRY_BUILTIN_BIGINT */ + JERRY_ASSERT (type == ECMA_TYPE_BIGINT || type == ECMA_TYPE_ERROR); + + return ecma_pointer_to_ecma_value (primitve_p) | type; +} /* ecma_make_extended_primitive_value */ + +/** + * Get integer value from an integer ecma value + * + * @return integer value + */ +ecma_integer_value_t JERRY_ATTR_CONST +ecma_get_integer_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_integer_number (value)); + + return ((ecma_integer_value_t) value) >> ECMA_DIRECT_SHIFT; +} /* ecma_get_integer_from_value */ + +/** + * Get floating point value from an ecma value + * + * @return floating point value + */ +ecma_number_t JERRY_ATTR_PURE +ecma_get_float_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT); + + return *(ecma_number_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_float_from_value */ + +/** + * Get floating point value pointer from an ecma value + * + * @return floating point value + */ +ecma_number_t *JERRY_ATTR_PURE +ecma_get_pointer_from_float_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT); + + return (ecma_number_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_pointer_from_float_value */ + +/** + * Get floating point value from an ecma value + * + * @return floating point value + */ +ecma_number_t JERRY_ATTR_PURE +ecma_get_number_from_value (ecma_value_t value) /**< ecma value */ +{ + if (ecma_is_value_integer_number (value)) + { + return (ecma_number_t) ecma_get_integer_from_value (value); + } + + return ecma_get_float_from_value (value); +} /* ecma_get_number_from_value */ + +/** + * Get pointer to ecma-string from ecma value + * + * @return the string pointer + */ +ecma_string_t *JERRY_ATTR_PURE +ecma_get_string_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_string (value)); + + if ((value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_DIRECT_STRING) + { + return (ecma_string_t *) (uintptr_t) value; + } + + return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_string_from_value */ + +/** + * Get pointer to ecma-string from ecma value + * + * @return the string pointer + */ +ecma_string_t *JERRY_ATTR_PURE +ecma_get_symbol_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_symbol (value)); + + return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_symbol_from_value */ + +/** + * Get pointer to a property name from ecma value + * + * @return the string pointer + */ +ecma_string_t *JERRY_ATTR_PURE +ecma_get_prop_name_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_prop_name (value)); + + if ((value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_DIRECT_STRING) + { + return (ecma_string_t *) (uintptr_t) value; + } + + return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_prop_name_from_value */ + +/** + * Get pointer to ecma-object from ecma value + * + * @return the pointer + */ +ecma_object_t *JERRY_ATTR_PURE +ecma_get_object_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_object (value)); + + return (ecma_object_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_object_from_value */ + +/** + * Get pointer to error reference from ecma value + * + * @return the pointer + */ +ecma_extended_primitive_t *JERRY_ATTR_PURE +ecma_get_extended_primitive_from_value (ecma_value_t value) /**< ecma value */ +{ +#if JERRY_BUILTIN_BIGINT + JERRY_ASSERT (value != ECMA_BIGINT_ZERO); +#endif /* JERRY_BUILTIN_BIGINT */ + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_BIGINT + || ecma_get_value_type_field (value) == ECMA_TYPE_ERROR); + + return (ecma_extended_primitive_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_extended_primitive_from_value */ + +/** + * Invert a boolean value + * + * @return ecma value + */ +ecma_value_t JERRY_ATTR_CONST +ecma_invert_boolean_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_boolean (value)); + + return (value ^ (1 << ECMA_DIRECT_SHIFT)); +} /* ecma_invert_boolean_value */ + +/** + * Copy ecma value. + * + * @return copy of the given value + */ +ecma_value_t +ecma_copy_value (ecma_value_t value) /**< value description */ +{ + switch (ecma_get_value_type_field (value)) + { + case ECMA_TYPE_FLOAT: + { + ecma_number_t *num_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value); + ecma_number_t *new_num_p = ecma_alloc_number (); + + *new_num_p = *num_p; + + return ecma_make_float_value (new_num_p); + } + case ECMA_TYPE_SYMBOL: + case ECMA_TYPE_STRING: + { + ecma_string_t *string_p = (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); + ecma_ref_ecma_string_non_direct (string_p); + return value; + } +#if JERRY_BUILTIN_BIGINT + case ECMA_TYPE_BIGINT: + { + if (value != ECMA_BIGINT_ZERO) + { + ecma_ref_extended_primitive (ecma_get_extended_primitive_from_value (value)); + } + return value; + } +#endif /* JERRY_BUILTIN_BIGINT */ + case ECMA_TYPE_OBJECT: + { + ecma_ref_object_inline (ecma_get_object_from_value (value)); + return value; + } + default: + { + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT + || ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING); + + return value; + } + } +} /* ecma_copy_value */ + +/** + * Copy ecma value. + * + * Note: + * this function is similar to ecma_copy_value, but it is + * faster for direct values since no function call is performed. + * It also increases the binary size so it is recommended for + * critical code paths only. + * + * @return copy of the given value + */ +ecma_value_t +ecma_fast_copy_value (ecma_value_t value) /**< value description */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT) ? value : ecma_copy_value (value); +} /* ecma_fast_copy_value */ + +/** + * Copy the ecma value if not an object + * + * @return copy of the given value + */ +ecma_value_t +ecma_copy_value_if_not_object (ecma_value_t value) /**< value description */ +{ + if (!ecma_is_value_object (value)) + { + return ecma_copy_value (value); + } + + return value; +} /* ecma_copy_value_if_not_object */ + +/** + * Increase reference counter of a value if it is an object. + * + * @return void + */ +void +ecma_ref_if_object (ecma_value_t value) /**< value description */ +{ + if (ecma_is_value_object (value)) + { + ecma_ref_object (ecma_get_object_from_value (value)); + } +} /* ecma_ref_if_object */ + +/** + * Decrease reference counter of a value if it is an object. + * + * @return void + */ +void +ecma_deref_if_object (ecma_value_t value) /**< value description */ +{ + if (ecma_is_value_object (value)) + { + ecma_deref_object (ecma_get_object_from_value (value)); + } +} /* ecma_deref_if_object */ + +/** + * Assign a new value to an ecma-value + * + * Note: + * value previously stored in the property is freed + */ +void +ecma_value_assign_value (ecma_value_t *value_p, /**< [in, out] ecma value */ + ecma_value_t ecma_value) /**< value to assign */ +{ + JERRY_STATIC_ASSERT (ECMA_TYPE_DIRECT == 0, ecma_type_direct_must_be_zero_for_the_next_check); + + if (*value_p == ecma_value) + { + return; + } + + if (ecma_get_value_type_field (ecma_value || *value_p) == ECMA_TYPE_DIRECT) + { + *value_p = ecma_value; + } + else if (ecma_is_value_float_number (ecma_value) && ecma_is_value_float_number (*value_p)) + { + const ecma_number_t *num_src_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (ecma_value); + ecma_number_t *num_dst_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (*value_p); + + *num_dst_p = *num_src_p; + } + else + { + ecma_free_value_if_not_object (*value_p); + *value_p = ecma_copy_value_if_not_object (ecma_value); + } +} /* ecma_value_assign_value */ + +/** + * Update the value of a float number to a new value + * + * Note: + * The original value is destroyed. + * + * @return updated ecma value + */ +ecma_value_t +ecma_update_float_number (ecma_value_t float_value, /**< original float value */ + ecma_number_t new_number) /**< updated number value */ +{ + JERRY_ASSERT (ecma_is_value_float_number (float_value)); + + ecma_integer_value_t integer_number = (ecma_integer_value_t) new_number; + ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (float_value); + + if ((ecma_number_t) integer_number == new_number + && ((integer_number == 0) ? ecma_is_number_equal_to_positive_zero (new_number) + : ECMA_IS_INTEGER_NUMBER (integer_number))) + { + ecma_dealloc_number (number_p); + return ecma_make_integer_value (integer_number); + } + + *number_p = new_number; + return float_value; +} /* ecma_update_float_number */ + +/** + * Assign a float number to an ecma-value + * + * Note: + * value previously stored in the property is freed + */ +static void +ecma_value_assign_float_number (ecma_value_t *value_p, /**< [in, out] ecma value */ + ecma_number_t ecma_number) /**< number to assign */ +{ + if (ecma_is_value_float_number (*value_p)) + { + ecma_number_t *num_dst_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (*value_p); + + *num_dst_p = ecma_number; + return; + } + + if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT + && ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT) + { + ecma_free_value (*value_p); + } + + *value_p = ecma_create_float_number (ecma_number); +} /* ecma_value_assign_float_number */ + +/** + * Assign a number to an ecma-value + * + * Note: + * value previously stored in the property is freed + */ +void +ecma_value_assign_number (ecma_value_t *value_p, /**< [in, out] ecma value */ + ecma_number_t ecma_number) /**< number to assign */ +{ + ecma_integer_value_t integer_value = (ecma_integer_value_t) ecma_number; + + if ((ecma_number_t) integer_value == ecma_number + && ((integer_value == 0) ? ecma_is_number_equal_to_positive_zero (ecma_number) + : ECMA_IS_INTEGER_NUMBER (integer_value))) + { + if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT + && ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT) + { + ecma_free_value (*value_p); + } + *value_p = ecma_make_integer_value (integer_value); + return; + } + + ecma_value_assign_float_number (value_p, ecma_number); +} /* ecma_value_assign_number */ + +/** + * Free the ecma value + */ +void +ecma_free_value (ecma_value_t value) /**< value description */ +{ + switch (ecma_get_value_type_field (value)) + { + case ECMA_TYPE_FLOAT: + { + ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value); + ecma_dealloc_number (number_p); + break; + } + case ECMA_TYPE_SYMBOL: + case ECMA_TYPE_STRING: + { + ecma_string_t *string_p = (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); + ecma_deref_ecma_string_non_direct (string_p); + break; + } + case ECMA_TYPE_OBJECT: + { + ecma_deref_object (ecma_get_object_from_value (value)); + break; + } +#if JERRY_BUILTIN_BIGINT + case ECMA_TYPE_BIGINT: + { + if (value != ECMA_BIGINT_ZERO) + { + ecma_deref_bigint (ecma_get_extended_primitive_from_value (value)); + } + + break; + } +#endif /* JERRY_BUILTIN_BIGINT */ + default: + { + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT + || ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING); + + /* no memory is allocated */ + break; + } + } +} /* ecma_free_value */ + +/** + * Free the ecma value + * + * Note: + * this function is similar to ecma_free_value, but it is + * faster for direct values since no function call is performed. + * It also increases the binary size so it is recommended for + * critical code paths only. + * + * @return void + */ +void +ecma_fast_free_value (ecma_value_t value) /**< value description */ +{ + if (ecma_get_value_type_field (value) != ECMA_TYPE_DIRECT) + { + ecma_free_value (value); + } +} /* ecma_fast_free_value */ + +/** + * Free the ecma value if not an object + */ +void +ecma_free_value_if_not_object (ecma_value_t value) /**< value description */ +{ + if (ecma_get_value_type_field (value) != ECMA_TYPE_OBJECT) + { + ecma_free_value (value); + } +} /* ecma_free_value_if_not_object */ + +/** + * Free an ecma-value object + * + * @return void + */ +void +ecma_free_object (ecma_value_t value) /**< value description */ +{ + ecma_deref_object (ecma_get_object_from_value (value)); +} /* ecma_free_object */ + +/** + * Free an ecma-value number + * + * @return void + */ +void +ecma_free_number (ecma_value_t value) /**< value description */ +{ + JERRY_ASSERT (ecma_is_value_number (value)); + + if (ecma_is_value_float_number (value)) + { + ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value); + ecma_dealloc_number (number_p); + } +} /* ecma_free_number */ + +/** + * Get the literal id associated with the given ecma_value type. + * This operation is equivalent to the JavaScript 'typeof' operator. + * + * @returns one of the following value: + * - LIT_MAGIC_STRING_UNDEFINED + * - LIT_MAGIC_STRING_OBJECT + * - LIT_MAGIC_STRING_BOOLEAN + * - LIT_MAGIC_STRING_NUMBER + * - LIT_MAGIC_STRING_STRING + * - LIT_MAGIC_STRING_FUNCTION + */ +lit_magic_string_id_t +ecma_get_typeof_lit_id (ecma_value_t value) /**< input ecma value */ +{ + lit_magic_string_id_t ret_value = LIT_MAGIC_STRING__EMPTY; + + if (ecma_is_value_undefined (value)) + { + ret_value = LIT_MAGIC_STRING_UNDEFINED; + } + else if (ecma_is_value_null (value)) + { + ret_value = LIT_MAGIC_STRING_OBJECT; + } + else if (ecma_is_value_boolean (value)) + { + ret_value = LIT_MAGIC_STRING_BOOLEAN; + } + else if (ecma_is_value_number (value)) + { + ret_value = LIT_MAGIC_STRING_NUMBER; + } + else if (ecma_is_value_string (value)) + { + ret_value = LIT_MAGIC_STRING_STRING; + } + else if (ecma_is_value_symbol (value)) + { + ret_value = LIT_MAGIC_STRING_SYMBOL; + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (value)) + { + ret_value = LIT_MAGIC_STRING_BIGINT; + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + JERRY_ASSERT (ecma_is_value_object (value)); + + ret_value = ecma_op_is_callable (value) ? LIT_MAGIC_STRING_FUNCTION : LIT_MAGIC_STRING_OBJECT; + } + + JERRY_ASSERT (ret_value != LIT_MAGIC_STRING__EMPTY); + + return ret_value; +} /* ecma_get_typeof_lit_id */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.cpp new file mode 100644 index 00000000..1c994091 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.cpp @@ -0,0 +1,1762 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-helpers.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtins.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-lcache.h" +#include "ecma-line-info.h" +#include "ecma-property-hashmap.h" + +#include "byte-code.h" +#include "jcontext.h" +#include "jrt-bit-fields.h" +#include "re-compiler.h" + + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +JERRY_STATIC_ASSERT (((int)ECMA_OBJECT_TYPE_MASK >= ((int)ECMA_OBJECT_TYPE__MAX) - 1), + ecma_object_types_must_be_lower_than_the_container_mask); + +JERRY_STATIC_ASSERT (((int)ECMA_OBJECT_TYPE_MASK >= (int)ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX), + ecma_lexical_environment_types_must_be_lower_than_the_container_mask); + +JERRY_STATIC_ASSERT (((int)ECMA_OBJECT_FLAG_EXTENSIBLE == ((int)ECMA_OBJECT_TYPE_MASK) + 1), + ecma_extensible_flag_must_follow_the_object_type); + +JERRY_STATIC_ASSERT ((ECMA_OBJECT_REF_ONE == (ECMA_OBJECT_FLAG_EXTENSIBLE << 1)), + ecma_object_ref_one_must_follow_the_extensible_flag); + +JERRY_STATIC_ASSERT (((ECMA_OBJECT_MAX_REF + ECMA_OBJECT_REF_ONE) == ECMA_OBJECT_REF_MASK), + ecma_object_max_ref_does_not_fill_the_remaining_bits); + +JERRY_STATIC_ASSERT (((ECMA_OBJECT_REF_MASK & (ECMA_OBJECT_TYPE_MASK | ECMA_OBJECT_FLAG_EXTENSIBLE)) == 0), + ecma_object_ref_mask_overlaps_with_object_type_or_extensible); + +JERRY_STATIC_ASSERT ((ECMA_PROPERTY_FLAGS_MASK == ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE), + ecma_property_flags_mask_must_use_the_configurable_enumerable_writable_flags); + +/* These checks are needed by ecma_get_object_base_type. */ +JERRY_STATIC_ASSERT (((int) ECMA_OBJECT_TYPE_BUILT_IN_GENERAL == ((int) ECMA_OBJECT_TYPE_GENERAL | 0x1)) + && (((int) ECMA_OBJECT_TYPE_GENERAL & 0x1) == 0), + ecma_object_type_built_in_general_has_unexpected_value); +JERRY_STATIC_ASSERT (((int) ECMA_OBJECT_TYPE_BUILT_IN_CLASS == ((int) ECMA_OBJECT_TYPE_CLASS | 0x1)) + && (((int) ECMA_OBJECT_TYPE_CLASS & 0x1) == 0), + ecma_object_type_built_in_class_has_unexpected_value); +JERRY_STATIC_ASSERT (((int) ECMA_OBJECT_TYPE_BUILT_IN_ARRAY == ((int) ECMA_OBJECT_TYPE_ARRAY | 0x1)) + && (((int) ECMA_OBJECT_TYPE_ARRAY & 0x1) == 0), + ecma_object_type_built_in_array_has_unexpected_value); + +/** + * Create an object with specified prototype object + * (or NULL prototype if there is not prototype for the object) + * and value of 'Extensible' attribute. + * + * Reference counter's value will be set to one. + * + * @return pointer to the object's descriptor + */ +ecma_object_t * +ecma_create_object (ecma_object_t *prototype_object_p, /**< pointer to prototybe of the object (or NULL) */ + size_t ext_object_size, /**< size of extended objects */ + ecma_object_type_t type) /**< object type */ +{ + ecma_object_t *new_object_p; + + if (ext_object_size > 0) + { + new_object_p = (ecma_object_t *) ecma_alloc_extended_object (ext_object_size); + } + else + { + new_object_p = ecma_alloc_object (); + } + + new_object_p->type_flags_refs = (ecma_object_descriptor_t) (type | ECMA_OBJECT_FLAG_EXTENSIBLE); + + ecma_init_gc_info (new_object_p); + + new_object_p->u1.property_list_cp = JMEM_CP_NULL; + + ECMA_SET_POINTER (new_object_p->u2.prototype_cp, prototype_object_p); + + return new_object_p; +} /* ecma_create_object */ + +/** + * Create a declarative lexical environment with specified outer lexical environment + * (or NULL if the environment is not nested). + * + * See also: ECMA-262 v5, 10.2.1.1 + * + * Reference counter's value will be set to one. + * + * @return pointer to the descriptor of lexical environment + */ +ecma_object_t * +ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p) /**< outer lexical environment */ +{ + ecma_object_t *new_lexical_environment_p = ecma_alloc_object (); + + new_lexical_environment_p->type_flags_refs = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE; + + ecma_init_gc_info (new_lexical_environment_p); + + new_lexical_environment_p->u1.property_list_cp = JMEM_CP_NULL; + + ECMA_SET_POINTER (new_lexical_environment_p->u2.outer_reference_cp, outer_lexical_environment_p); + + return new_lexical_environment_p; +} /* ecma_create_decl_lex_env */ + +/** + * Create a object lexical environment with specified outer lexical environment + * (or NULL if the environment is not nested), and binding object. + * + * See also: ECMA-262 v5, 10.2.1.2 + * + * Reference counter's value will be set to one. + * + * @return pointer to the descriptor of lexical environment + */ +ecma_object_t * +ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< outer lexical environment */ + ecma_object_t *binding_obj_p) /**< binding object */ +{ + JERRY_ASSERT (binding_obj_p != NULL && !ecma_is_lexical_environment (binding_obj_p)); + + ecma_object_t *new_lexical_environment_p = ecma_alloc_object (); + + new_lexical_environment_p->type_flags_refs = ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND; + + ecma_init_gc_info (new_lexical_environment_p); + + ECMA_SET_NON_NULL_POINTER (new_lexical_environment_p->u1.bound_object_cp, binding_obj_p); + + ECMA_SET_POINTER (new_lexical_environment_p->u2.outer_reference_cp, outer_lexical_environment_p); + + return new_lexical_environment_p; +} /* ecma_create_object_lex_env */ + +/** + * Create a lexical environment with a specified size. + * + * @return pointer to the descriptor of the lexical environment + */ +ecma_object_t * +ecma_create_lex_env_class (ecma_object_t *outer_lexical_environment_p, /**< outer lexical environment */ + size_t lexical_env_size) /**< size of the lexical environment */ +{ + ecma_object_t *new_lexical_environment_p; + + ecma_object_descriptor_t type_flags_refs = ECMA_LEXICAL_ENVIRONMENT_CLASS; + + if (lexical_env_size > 0) + { + new_lexical_environment_p = (ecma_object_t *) ecma_alloc_extended_object (lexical_env_size); + type_flags_refs |= ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA; + } + else + { + new_lexical_environment_p = ecma_alloc_object (); + } + + new_lexical_environment_p->type_flags_refs = type_flags_refs; + + ecma_init_gc_info (new_lexical_environment_p); + + new_lexical_environment_p->u1.property_list_cp = JMEM_CP_NULL; + + ECMA_SET_POINTER (new_lexical_environment_p->u2.outer_reference_cp, outer_lexical_environment_p); + + return new_lexical_environment_p; +} /* ecma_create_lex_env_class */ + +/** + * Check if the object is lexical environment. + * + * @return true - if object is a lexical environment + * false - otherwise + */ +bool JERRY_ATTR_PURE +ecma_is_lexical_environment (const ecma_object_t *object_p) /**< object or lexical environment */ +{ + JERRY_ASSERT (object_p != NULL); + + return (object_p->type_flags_refs & ECMA_OBJECT_TYPE_MASK) >= ECMA_LEXICAL_ENVIRONMENT_TYPE_START; +} /* ecma_is_lexical_environment */ + +/** + * Set value of [[Extensible]] object's internal property. + */ +void +ecma_op_ordinary_object_set_extensible (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); + + object_p->type_flags_refs |= ECMA_OBJECT_FLAG_EXTENSIBLE; +} /* ecma_op_ordinary_object_set_extensible */ + +/** + * Get the internal type of an object. + * + * @return type of the object (ecma_object_type_t) + */ +ecma_object_type_t JERRY_ATTR_PURE +ecma_get_object_type (const ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); + + return (ecma_object_type_t) (object_p->type_flags_refs & ECMA_OBJECT_TYPE_MASK); +} /* ecma_get_object_type */ + +/** + * Get the internal base type of an object. + * + * @return base type of the object (ecma_object_base_type_t) + */ +ecma_object_base_type_t JERRY_ATTR_PURE +ecma_get_object_base_type (const ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); + + return (ecma_object_base_type_t) (object_p->type_flags_refs & (ECMA_OBJECT_TYPE_MASK - 0x1)); +} /* ecma_get_object_base_type */ + +/** + * Get value of an object if the class matches + * + * @return value of the object if the class matches + * ECMA_VALUE_NOT_FOUND otherwise + */ +bool +ecma_object_class_is (ecma_object_t *object_p, /**< object */ + ecma_object_class_type_t class_id) /**< class id */ +{ + if (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_CLASS) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ext_object_p->u.cls.type == (uint8_t) class_id) + { + return true; + } + } + + return false; +} /* ecma_object_class_is */ + +/** + * Get type of lexical environment. + * + * @return type of the lexical environment (ecma_lexical_environment_type_t) + */ +ecma_lexical_environment_type_t JERRY_ATTR_PURE +ecma_get_lex_env_type (const ecma_object_t *object_p) /**< lexical environment */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (object_p)); + + return (ecma_lexical_environment_type_t) (object_p->type_flags_refs & ECMA_OBJECT_TYPE_MASK); +} /* ecma_get_lex_env_type */ + +/** + * Get lexical environment's bound object. + * + * @return pointer to ecma object + */ +ecma_object_t *JERRY_ATTR_PURE +ecma_get_lex_env_binding_object (const ecma_object_t *object_p) /**< object-bound lexical environment */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND + || (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && !ECMA_LEX_ENV_CLASS_IS_MODULE (object_p))); + + return ECMA_GET_NON_NULL_POINTER (ecma_object_t, object_p->u1.bound_object_cp); +} /* ecma_get_lex_env_binding_object */ + +/** + * Create a new lexical environment with the same property list as the passed lexical environment + * + * @return pointer to the newly created lexical environment + */ +ecma_object_t * +ecma_clone_decl_lexical_environment (ecma_object_t *lex_env_p, /**< declarative lexical environment */ + bool copy_values) /**< copy property values as well */ +{ + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + + ecma_object_t *outer_lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + ecma_object_t *new_lex_env_p = ecma_create_decl_lex_env (outer_lex_env_p); + + jmem_cpointer_t prop_iter_cp = lex_env_p->u1.property_list_cp; + ecma_property_header_t *prop_iter_p; + + JERRY_ASSERT (prop_iter_cp != JMEM_CP_NULL); + +#if JERRY_PROPERTY_HASHMAP + prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + + JERRY_ASSERT (prop_iter_cp != JMEM_CP_NULL); +#endif /* JERRY_PROPERTY_HASHMAP */ + + do + { + prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW_DATA (prop_iter_p->types[i])); + + uint8_t prop_attributes = (uint8_t) (prop_iter_p->types[i] & ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_string_t *name_p = ecma_string_from_property_name (prop_iter_p->types[i], prop_pair_p->names_cp[i]); + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (new_lex_env_p, name_p, prop_attributes, NULL); + + ecma_deref_ecma_string (name_p); + + JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED); + + if (copy_values) + { + property_value_p->value = ecma_copy_value_if_not_object (prop_pair_p->values[i].value); + } + else + { + property_value_p->value = ECMA_VALUE_UNINITIALIZED; + } + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } while (prop_iter_cp != JMEM_CP_NULL); + + ecma_deref_object (lex_env_p); + return new_lex_env_p; +} /* ecma_clone_decl_lexical_environment */ + +/** + * Create a property in an object and link it into + * the object's properties' linked-list (at start of the list). + * + * @return pointer to the newly created property value + */ +static ecma_property_value_t * +ecma_create_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *name_p, /**< property name */ + uint8_t type_and_flags, /**< type and flags, see ecma_property_info_t */ + ecma_property_value_t value, /**< property value */ + ecma_property_t **out_prop_p) /**< [out] the property is also returned + * if this field is non-NULL */ +{ + JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); + JERRY_ASSERT (name_p != NULL); + JERRY_ASSERT (object_p != NULL); + + jmem_cpointer_t *property_list_head_p = &object_p->u1.property_list_cp; + + if (*property_list_head_p != ECMA_NULL_POINTER) + { + /* If the first entry is free (deleted), it is reused. */ + ecma_property_header_t *first_property_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, *property_list_head_p); + +#if JERRY_PROPERTY_HASHMAP + bool has_hashmap = false; + + if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + property_list_head_p = &first_property_p->next_property_cp; + first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, *property_list_head_p); + has_hashmap = true; + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (first_property_p)); + + if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_DELETED) + { + ecma_property_pair_t *first_property_pair_p = (ecma_property_pair_t *) first_property_p; + + ecma_property_t name_type; + first_property_pair_p->names_cp[0] = ecma_string_to_property_name (name_p, &name_type); + first_property_p->types[0] = (ecma_property_t) (type_and_flags | name_type); + + ecma_property_t *property_p = first_property_p->types + 0; + + JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 0); + + if (out_prop_p != NULL) + { + *out_prop_p = property_p; + } + + first_property_pair_p->values[0] = value; + +#if JERRY_PROPERTY_HASHMAP + /* The property must be fully initialized before ecma_property_hashmap_insert + * is called, because the insert operation may reallocate the hashmap, and + * that triggers garbage collection which scans all properties of all objects. + * A not fully initialized but queued property may cause a crash. */ + + if (has_hashmap) + { + ecma_property_hashmap_insert (object_p, name_p, first_property_pair_p, 0); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + return first_property_pair_p->values + 0; + } + } + + /* Otherwise we create a new property pair and use its second value. */ + ecma_property_pair_t *first_property_pair_p = ecma_alloc_property_pair (); + + /* Need to query property_list_head_p again and recheck the existennce + * of property hasmap, because ecma_alloc_property_pair may delete them. */ + property_list_head_p = &object_p->u1.property_list_cp; +#if JERRY_PROPERTY_HASHMAP + bool has_hashmap = false; + + if (*property_list_head_p != ECMA_NULL_POINTER) + { + ecma_property_header_t *first_property_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, *property_list_head_p); + + if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + property_list_head_p = &first_property_p->next_property_cp; + has_hashmap = true; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + /* Just copy the previous value (no need to decompress, compress). */ + first_property_pair_p->header.next_property_cp = *property_list_head_p; + first_property_pair_p->header.types[0] = ECMA_PROPERTY_TYPE_DELETED; + first_property_pair_p->names_cp[0] = LIT_INTERNAL_MAGIC_STRING_DELETED; + + ecma_property_t name_type; + first_property_pair_p->names_cp[1] = ecma_string_to_property_name (name_p, &name_type); + + first_property_pair_p->header.types[1] = (ecma_property_t) (type_and_flags | name_type); + + ECMA_SET_NON_NULL_POINTER (*property_list_head_p, &first_property_pair_p->header); + + ecma_property_t *property_p = first_property_pair_p->header.types + 1; + + JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 1); + + if (out_prop_p != NULL) + { + *out_prop_p = property_p; + } + + first_property_pair_p->values[1] = value; + +#if JERRY_PROPERTY_HASHMAP + /* See the comment before the other ecma_property_hashmap_insert above. */ + + if (has_hashmap) + { + ecma_property_hashmap_insert (object_p, name_p, first_property_pair_p, 1); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + return first_property_pair_p->values + 1; +} /* ecma_create_property */ + +/** + * Create named data property with given name, attributes and undefined value + * in the specified object. + * + * @return pointer to the newly created property value + */ +ecma_property_value_t * +ecma_create_named_data_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *name_p, /**< property name */ + uint8_t prop_attributes, /**< property attributes (See: ecma_property_flags_t) */ + ecma_property_t **out_prop_p) /**< [out] the property is also returned + * if this field is non-NULL */ +{ + JERRY_ASSERT (object_p != NULL && name_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (object_p) || !ecma_op_object_is_fast_array (object_p)); + JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); + JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE_WRITABLE) == 0); + + uint8_t type_and_flags = ECMA_PROPERTY_FLAG_DATA | prop_attributes; + + ecma_property_value_t value; + value.value = ECMA_VALUE_UNDEFINED; + + return ecma_create_property (object_p, name_p, type_and_flags, value, out_prop_p); +} /* ecma_create_named_data_property */ + +/** + * Create named accessor property with given name, attributes, getter and setter. + * + * @return pointer to the newly created property value + */ +ecma_property_value_t * +ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *name_p, /**< property name */ + ecma_object_t *get_p, /**< getter */ + ecma_object_t *set_p, /**< setter */ + uint8_t prop_attributes, /**< property attributes */ + ecma_property_t **out_prop_p) /**< [out] the property is also returned + * if this field is non-NULL */ +{ + JERRY_ASSERT (object_p != NULL && name_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (object_p) || !ecma_op_object_is_fast_array (object_p)); + JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); + JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE) == 0); + + uint8_t type_and_flags = prop_attributes; + + ecma_property_value_t value; +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t)); + ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, get_p); + ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, set_p); + ECMA_SET_NON_NULL_POINTER (value.getter_setter_pair_cp, getter_setter_pair_p); +#else /* !JERRY_CPOINTER_32_BIT */ + ECMA_SET_POINTER (value.getter_setter_pair.getter_cp, get_p); + ECMA_SET_POINTER (value.getter_setter_pair.setter_cp, set_p); +#endif /* JERRY_CPOINTER_32_BIT */ + + return ecma_create_property (object_p, name_p, type_and_flags, value, out_prop_p); +} /* ecma_create_named_accessor_property */ + +#if JERRY_MODULE_SYSTEM +/** + * Create property reference + */ +void +ecma_create_named_reference_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *name_p, /**< property name */ + ecma_value_t reference) /**< property reference */ +{ + JERRY_ASSERT (object_p != NULL && name_p != NULL); + JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); + JERRY_ASSERT ((ecma_is_lexical_environment (object_p) + && ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && ECMA_LEX_ENV_CLASS_IS_MODULE (object_p)) + || ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE_NAMESPACE)); + + uint8_t type_and_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE; + ecma_property_value_t value; + + value.value = reference; + + ecma_create_property (object_p, name_p, type_and_flags, value, NULL); +} /* ecma_create_named_reference_property */ + +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * Find named data property or named accessor property in a specified object. + * + * @return pointer to the property, if it is found, + * NULL - otherwise. + */ +ecma_property_t * +ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in */ + ecma_string_t *name_p) /**< property's name */ +{ + JERRY_ASSERT (obj_p != NULL); + JERRY_ASSERT (name_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (obj_p) || !ecma_op_object_is_fast_array (obj_p)); + +#if JERRY_LCACHE + ecma_property_t *property_p = ecma_lcache_lookup (obj_p, name_p); + if (property_p != NULL) + { + return property_p; + } +#else /* !JERRY_LCACHE */ + ecma_property_t *property_p = NULL; +#endif /* JERRY_LCACHE */ + + jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + jmem_cpointer_t property_real_name_cp; + property_p = ecma_property_hashmap_find ((ecma_property_hashmap_t *) prop_iter_p, name_p, &property_real_name_cp); +#if JERRY_LCACHE + if (property_p != NULL && !ecma_is_property_lcached (property_p)) + { + ecma_lcache_insert (obj_p, property_real_name_cp, property_p); + } +#endif /* JERRY_LCACHE */ + return property_p; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + +#if JERRY_PROPERTY_HASHMAP + uint32_t steps = 0; +#endif /* JERRY_PROPERTY_HASHMAP */ + jmem_cpointer_t property_name_cp = ECMA_NULL_POINTER; + + if (ECMA_IS_DIRECT_STRING (name_p)) + { + ecma_property_t prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (name_p); + property_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (name_p); + + JERRY_ASSERT (prop_name_type > 0); + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (prop_pair_p->names_cp[0] == property_name_cp + && ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[0]) == prop_name_type) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[0])); + + property_p = prop_iter_p->types + 0; + break; + } + + if (prop_pair_p->names_cp[1] == property_name_cp + && ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[1]) == prop_name_type) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[1])); + + property_p = prop_iter_p->types + 1; + break; + } + +#if JERRY_PROPERTY_HASHMAP + steps++; +#endif /* JERRY_PROPERTY_HASHMAP */ + prop_iter_cp = prop_iter_p->next_property_cp; + } + } + else + { + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[0]) == ECMA_DIRECT_STRING_PTR) + { + property_name_cp = prop_pair_p->names_cp[0]; + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_name_cp); + + if (ecma_compare_ecma_non_direct_strings (name_p, prop_name_p)) + { + property_p = prop_iter_p->types + 0; + break; + } + } + + if (ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[1]) == ECMA_DIRECT_STRING_PTR) + { + property_name_cp = prop_pair_p->names_cp[1]; + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_name_cp); + + if (ecma_compare_ecma_non_direct_strings (name_p, prop_name_p)) + { + property_p = prop_iter_p->types + 1; + break; + } + } + +#if JERRY_PROPERTY_HASHMAP + steps++; +#endif /* JERRY_PROPERTY_HASHMAP */ + prop_iter_cp = prop_iter_p->next_property_cp; + } + } + +#if JERRY_PROPERTY_HASHMAP + if (steps >= (ECMA_PROPERTY_HASMAP_MINIMUM_SIZE / 2)) + { + ecma_property_hashmap_create (obj_p); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + +#if JERRY_LCACHE + if (property_p != NULL && !ecma_is_property_lcached (property_p)) + { + ecma_lcache_insert (obj_p, property_name_cp, property_p); + } +#endif /* JERRY_LCACHE */ + + return property_p; +} /* ecma_find_named_property */ + +/** + * Get named data property or named access property in specified object. + * + * Warning: + * the property must exist + * + * @return pointer to the property, if it is found, + * NULL - otherwise. + */ +ecma_property_value_t * +ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property in */ + ecma_string_t *name_p) /**< property's name */ +{ + JERRY_ASSERT (obj_p != NULL); + JERRY_ASSERT (name_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (obj_p) || !ecma_op_object_is_fast_array (obj_p)); + + ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); + + JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*property_p)); + + return ECMA_PROPERTY_VALUE_PTR (property_p); +} /* ecma_get_named_data_property */ + +/** + * Delete the object's property referenced by its value pointer. + * + * Note: specified property must be owned by specified object. + */ +void +ecma_delete_property (ecma_object_t *object_p, /**< object */ + ecma_property_value_t *prop_value_p) /**< property value reference */ +{ + jmem_cpointer_t cur_prop_cp = object_p->u1.property_list_cp; + + ecma_property_header_t *prev_prop_p = NULL; + +#if JERRY_PROPERTY_HASHMAP + ecma_property_hashmap_delete_status hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP; + + if (cur_prop_cp != JMEM_CP_NULL) + { + ecma_property_header_t *cur_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, cur_prop_cp); + + if (cur_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prev_prop_p = cur_prop_p; + cur_prop_cp = cur_prop_p->next_property_cp; + hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (cur_prop_cp != JMEM_CP_NULL) + { + ecma_property_header_t *cur_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, cur_prop_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (cur_prop_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) cur_prop_p; + + for (uint32_t i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if ((prop_pair_p->values + i) == prop_value_p) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (cur_prop_p->types[i])); + +#if JERRY_PROPERTY_HASHMAP + if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP) + { + hashmap_status = ecma_property_hashmap_delete (object_p, prop_pair_p->names_cp[i], cur_prop_p->types + i); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + ecma_gc_free_property (object_p, prop_pair_p, i); + cur_prop_p->types[i] = ECMA_PROPERTY_TYPE_DELETED; + prop_pair_p->names_cp[i] = LIT_INTERNAL_MAGIC_STRING_DELETED; + + JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); + + if (cur_prop_p->types[1 - i] != ECMA_PROPERTY_TYPE_DELETED) + { +#if JERRY_PROPERTY_HASHMAP + /* The other property is still valid. */ + if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP) + { + ecma_property_hashmap_free (object_p); + ecma_property_hashmap_create (object_p); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + return; + } + + JERRY_ASSERT (cur_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED); + + if (prev_prop_p == NULL) + { + object_p->u1.property_list_cp = cur_prop_p->next_property_cp; + } + else + { + prev_prop_p->next_property_cp = cur_prop_p->next_property_cp; + } + + ecma_dealloc_property_pair ((ecma_property_pair_t *) cur_prop_p); + +#if JERRY_PROPERTY_HASHMAP + if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP) + { + ecma_property_hashmap_free (object_p); + ecma_property_hashmap_create (object_p); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + return; + } + } + + prev_prop_p = cur_prop_p; + cur_prop_cp = cur_prop_p->next_property_cp; + } +} /* ecma_delete_property */ + +/** + * Check whether the object contains a property + */ +static void +ecma_assert_object_contains_the_property (const ecma_object_t *object_p, /**< ecma-object */ + const ecma_property_value_t *prop_value_p, /**< property value */ + bool is_data) /**< property should be data property */ +{ +#ifndef JERRY_NDEBUG + jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp; + JERRY_ASSERT (prop_iter_cp != JMEM_CP_NULL); + + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + + while (prop_iter_cp != JMEM_CP_NULL) + { + prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if ((prop_pair_p->values + i) == prop_value_p) + { + JERRY_ASSERT (is_data == ((prop_pair_p->header.types[i] & ECMA_PROPERTY_FLAG_DATA) != 0)); + return; + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } +#else /* JERRY_NDEBUG */ + JERRY_UNUSED (object_p); + JERRY_UNUSED (prop_value_p); + JERRY_UNUSED (is_data); +#endif /* !JERRY_NDEBUG */ +} /* ecma_assert_object_contains_the_property */ + +/** + * Assign value to named data property + * + * Note: + * value previously stored in the property is freed + * + * @return void + */ +void +ecma_named_data_property_assign_value (ecma_object_t *obj_p, /**< object */ + ecma_property_value_t *prop_value_p, /**< property value reference */ + ecma_value_t value) /**< value to assign */ +{ + ecma_assert_object_contains_the_property (obj_p, prop_value_p, true); + + ecma_value_assign_value (&prop_value_p->value, value); +} /* ecma_named_data_property_assign_value */ + +/** + * Get named accessor property getter-setter-pair + * + * @return pointer to object's getter-setter pair + */ +ecma_getter_setter_pointers_t * +ecma_get_named_accessor_property (const ecma_property_value_t *prop_value_p) /**< property value reference */ +{ +#if JERRY_CPOINTER_32_BIT + return ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_value_p->getter_setter_pair_cp); +#else /* !JERRY_CPOINTER_32_BIT */ + return (ecma_getter_setter_pointers_t *) &prop_value_p->getter_setter_pair; +#endif /* JERRY_CPOINTER_32_BIT */ +} /* ecma_get_named_accessor_property */ + +/** + * Set getter of named accessor property + */ +void +ecma_set_named_accessor_property_getter (ecma_object_t *object_p, /**< the property's container */ + ecma_property_value_t *prop_value_p, /**< property value reference */ + ecma_object_t *getter_p) /**< getter object */ +{ + ecma_assert_object_contains_the_property (object_p, prop_value_p, false); + +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_value_p->getter_setter_pair_cp); + ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, getter_p); +#else /* !JERRY_CPOINTER_32_BIT */ + ECMA_SET_POINTER (prop_value_p->getter_setter_pair.getter_cp, getter_p); +#endif /* JERRY_CPOINTER_32_BIT */ +} /* ecma_set_named_accessor_property_getter */ + +/** + * Set setter of named accessor property + */ +void +ecma_set_named_accessor_property_setter (ecma_object_t *object_p, /**< the property's container */ + ecma_property_value_t *prop_value_p, /**< property value reference */ + ecma_object_t *setter_p) /**< setter object */ +{ + ecma_assert_object_contains_the_property (object_p, prop_value_p, false); + +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_value_p->getter_setter_pair_cp); + ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, setter_p); +#else /* !JERRY_CPOINTER_32_BIT */ + ECMA_SET_POINTER (prop_value_p->getter_setter_pair.setter_cp, setter_p); +#endif /* JERRY_CPOINTER_32_BIT */ +} /* ecma_set_named_accessor_property_setter */ + +#if JERRY_MODULE_SYSTEM + +/** + * Construct a reference to a given property + * + * @return property reference + */ +ecma_value_t +ecma_property_to_reference (ecma_property_t *property_p) /**< data or reference property */ +{ + ecma_property_value_t *referenced_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + return referenced_value_p->value; + } + + jmem_cpointer_tag_t offset = (jmem_cpointer_tag_t) (((uintptr_t) property_p) & 0x1); + +#if JERRY_CPOINTER_32_BIT + if (offset != 0) + { + --referenced_value_p; + } +#else /* !JERRY_CPOINTER_32_BIT */ + if (offset == 0) + { + ++referenced_value_p; + } +#endif /* JERRY_CPOINTER_32_BIT */ + + JERRY_ASSERT ((((uintptr_t) referenced_value_p) & (((uintptr_t) 1 << JMEM_ALIGNMENT_LOG) - 1)) == 0); + + ecma_value_t result; + ECMA_SET_NON_NULL_POINTER_TAG (result, referenced_value_p, offset); + return result; +} /* ecma_property_to_reference */ + +/** + * Gets the referenced property value + * + * @return pointer to the value + */ +ecma_property_value_t * +ecma_get_property_value_from_named_reference (ecma_property_value_t *reference_p) /**< data property reference */ +{ + ecma_value_t value = reference_p->value; + reference_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_property_value_t, value); + +#if JERRY_CPOINTER_32_BIT + if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (value)) + { + ++reference_p; + } +#else /* !JERRY_CPOINTER_32_BIT */ + if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (value)) + { + --reference_p; + } +#endif /* JERRY_CPOINTER_32_BIT */ + + return reference_p; +} /* ecma_get_property_value_from_named_reference */ + +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * Get property's 'Writable' attribute value + * + * @return true - property is writable, + * false - otherwise + */ +bool +ecma_is_property_writable (ecma_property_t property) /**< property */ +{ + JERRY_ASSERT (property & ECMA_PROPERTY_FLAG_DATA); + + return (property & ECMA_PROPERTY_FLAG_WRITABLE) != 0; +} /* ecma_is_property_writable */ + +/** + * Set property's 'Writable' attribute value + */ +void +ecma_set_property_writable_attr (ecma_property_t *property_p, /**< [in,out] property */ + bool is_writable) /**< new value for writable flag */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW_DATA (*property_p)); + + if (is_writable) + { + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_WRITABLE); + } + else + { + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_WRITABLE); + } +} /* ecma_set_property_writable_attr */ + +/** + * Get property's 'Enumerable' attribute value + * + * @return true - property is enumerable, + * false - otherwise + */ +bool +ecma_is_property_enumerable (ecma_property_t property) /**< property */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (property)); + + return (property & ECMA_PROPERTY_FLAG_ENUMERABLE) != 0; +} /* ecma_is_property_enumerable */ + +/** + * Set property's 'Enumerable' attribute value + */ +void +ecma_set_property_enumerable_attr (ecma_property_t *property_p, /**< [in,out] property */ + bool is_enumerable) /**< new value for enumerable flag */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + if (is_enumerable) + { + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_ENUMERABLE); + } + else + { + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_ENUMERABLE); + } +} /* ecma_set_property_enumerable_attr */ + +/** + * Get property's 'Configurable' attribute value + * + * @return true - property is configurable, + * false - otherwise + */ +bool +ecma_is_property_configurable (ecma_property_t property) /**< property */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (property)); + + return (property & ECMA_PROPERTY_FLAG_CONFIGURABLE) != 0; +} /* ecma_is_property_configurable */ + +/** + * Set property's 'Configurable' attribute value + */ +void +ecma_set_property_configurable_attr (ecma_property_t *property_p, /**< [in,out] property */ + bool is_configurable) /**< new value for configurable flag */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + if (is_configurable) + { + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_CONFIGURABLE); + } + else + { + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_CONFIGURABLE); + } +} /* ecma_set_property_configurable_attr */ + +#if JERRY_LCACHE + +/** + * Check whether the property is registered in LCache + * + * @return true / false + */ +bool +ecma_is_property_lcached (ecma_property_t *property_p) /**< property */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); + + return (*property_p & ECMA_PROPERTY_FLAG_LCACHED) != 0; +} /* ecma_is_property_lcached */ + +/** + * Set value of flag indicating whether the property is registered in LCache + */ +void +ecma_set_property_lcached (ecma_property_t *property_p, /**< property */ + bool is_lcached) /**< new value for lcached flag */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); + + if (is_lcached) + { + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_LCACHED); + } + else + { + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_LCACHED); + } +} /* ecma_set_property_lcached */ + +#endif /* JERRY_LCACHE */ + +/** + * Construct empty property descriptor, i.e.: + * property descriptor with all is_defined flags set to false and the rest - to default value. + * + * @return empty property descriptor + */ +ecma_property_descriptor_t +ecma_make_empty_property_descriptor (void) +{ + ecma_property_descriptor_t prop_desc; + + prop_desc.flags = 0; + prop_desc.value = ECMA_VALUE_UNDEFINED; + prop_desc.get_p = NULL; + prop_desc.set_p = NULL; + + return prop_desc; +} /* ecma_make_empty_property_descriptor */ + +/** + * Free values contained in the property descriptor + * and make it empty property descriptor + */ +void +ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + ecma_free_value (prop_desc_p->value); + } + + if ((prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) && prop_desc_p->get_p != NULL) + { + ecma_deref_object (prop_desc_p->get_p); + } + + if ((prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) && prop_desc_p->set_p != NULL) + { + ecma_deref_object (prop_desc_p->set_p); + } + + *prop_desc_p = ecma_make_empty_property_descriptor (); +} /* ecma_free_property_descriptor */ + +/** + * Increase ref count of an extended primitve value. + */ +void +ecma_ref_extended_primitive (ecma_extended_primitive_t *primitve_p) /**< extended primitve value */ +{ + if (JERRY_LIKELY (primitve_p->refs_and_type < ECMA_EXTENDED_PRIMITIVE_MAX_REF)) + { + primitve_p->refs_and_type += ECMA_EXTENDED_PRIMITIVE_REF_ONE; + } + else + { + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } +} /* ecma_ref_extended_primitive */ + +/** + * Decrease ref count of an error reference. + */ +void +ecma_deref_exception (ecma_extended_primitive_t *error_ref_p) /**< error reference */ +{ + JERRY_ASSERT (error_ref_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE); + + error_ref_p->refs_and_type -= ECMA_EXTENDED_PRIMITIVE_REF_ONE; + + if (error_ref_p->refs_and_type < ECMA_EXTENDED_PRIMITIVE_REF_ONE) + { + ecma_free_value (error_ref_p->u.value); + jmem_pools_free (error_ref_p, sizeof (ecma_extended_primitive_t)); + } +} /* ecma_deref_exception */ + +#if JERRY_BUILTIN_BIGINT + +/** + * Decrease ref count of a bigint value. + */ +void +ecma_deref_bigint (ecma_extended_primitive_t *bigint_p) /**< bigint value */ +{ + JERRY_ASSERT (bigint_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE); + + bigint_p->refs_and_type -= ECMA_EXTENDED_PRIMITIVE_REF_ONE; + + if (bigint_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE) + { + return; + } + + uint32_t size = ECMA_BIGINT_GET_SIZE (bigint_p); + + JERRY_ASSERT (size > 0); + + size_t mem_size = ECMA_BIGINT_GET_BYTE_SIZE (size) + sizeof (ecma_extended_primitive_t); + jmem_heap_free_block (bigint_p, mem_size); +} /* ecma_deref_bigint */ + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Create an error reference from a given value. + * + * Note: + * Reference of the value is taken. + * + * @return error reference value + */ +ecma_value_t +ecma_create_exception (ecma_value_t value, /**< referenced value */ + uint32_t options) /**< ECMA_ERROR_API_* options */ +{ + ecma_extended_primitive_t *error_ref_p; + error_ref_p = (ecma_extended_primitive_t *) jmem_pools_alloc (sizeof (ecma_extended_primitive_t)); + + error_ref_p->refs_and_type = ECMA_EXTENDED_PRIMITIVE_REF_ONE | options; + error_ref_p->u.value = value; + return ecma_make_extended_primitive_value (error_ref_p, ECMA_TYPE_ERROR); +} /* ecma_create_exception */ + +/** + * Create an error reference from the currently thrown error value. + * + * @return error reference value + */ +ecma_value_t +ecma_create_exception_from_context (void) +{ + uint32_t options = 0; + uint32_t status_flags = JERRY_CONTEXT (status_flags); + + if (status_flags & ECMA_STATUS_ABORT) + { + options |= ECMA_ERROR_API_FLAG_ABORT; + } + +#if JERRY_VM_THROW + if (status_flags & ECMA_STATUS_ERROR_THROWN) + { + options |= ECMA_ERROR_API_FLAG_THROW_CAPTURED; + } +#endif /* JERRY_VM_THROW */ + + return ecma_create_exception (jcontext_take_exception (), options); +} /* ecma_create_exception_from_context */ + +/** + * Create an exception from a given object. + * + * Note: + * Reference of the object is taken. + * + * @return exception value + */ +ecma_value_t +ecma_create_exception_from_object (ecma_object_t *object_p) /**< referenced object */ +{ + return ecma_create_exception (ecma_make_object_value (object_p), 0); +} /* ecma_create_exception_from_object */ + +/** + * Raise a new exception from the argument exception value. + * + * Note: the argument exceptions reference count is decreased + */ +void +ecma_throw_exception (ecma_value_t value) /**< error reference */ +{ + JERRY_ASSERT (!jcontext_has_pending_exception () && !jcontext_has_pending_abort ()); + ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); + + JERRY_ASSERT (error_ref_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE); + + ecma_value_t referenced_value = error_ref_p->u.value; + uint32_t status_flags = JERRY_CONTEXT (status_flags); + + status_flags |= (ECMA_STATUS_EXCEPTION +#if JERRY_VM_THROW + | ECMA_STATUS_ERROR_THROWN +#endif /* JERRY_VM_THROW */ + | ECMA_STATUS_ABORT); + + if (!(error_ref_p->refs_and_type & ECMA_ERROR_API_FLAG_ABORT)) + { + status_flags &= ~(uint32_t) ECMA_STATUS_ABORT; + } + +#if JERRY_VM_THROW + if (!(error_ref_p->refs_and_type & ECMA_ERROR_API_FLAG_THROW_CAPTURED)) + { + status_flags &= ~(uint32_t) ECMA_STATUS_ERROR_THROWN; + } +#endif /* JERRY_VM_THROW */ + + JERRY_CONTEXT (status_flags) = status_flags; + + if (error_ref_p->refs_and_type >= 2 * ECMA_EXTENDED_PRIMITIVE_REF_ONE) + { + error_ref_p->refs_and_type -= ECMA_EXTENDED_PRIMITIVE_REF_ONE; + referenced_value = ecma_copy_value (referenced_value); + } + else + { + jmem_pools_free (error_ref_p, sizeof (ecma_extended_primitive_t)); + } + + JERRY_CONTEXT (error_value) = referenced_value; +} /* ecma_throw_exception */ + +/** + * Decrease the reference counter of a script value. + */ +void +ecma_script_deref (ecma_value_t script_value) /**< script value */ +{ + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + script_p->refs_and_type -= CBC_SCRIPT_REF_ONE; + + if (script_p->refs_and_type >= CBC_SCRIPT_REF_ONE) + { + return; + } + + size_t script_size = sizeof (cbc_script_t); + uint32_t type = script_p->refs_and_type; + + if (type & CBC_SCRIPT_HAS_USER_VALUE) + { + script_size += sizeof (ecma_value_t); + + if (!(type & CBC_SCRIPT_USER_VALUE_IS_OBJECT)) + { + ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p); + + JERRY_ASSERT (!ecma_is_value_object (user_value)); + ecma_free_value (user_value); + } + } + +#if JERRY_SOURCE_NAME + ecma_deref_ecma_string (ecma_get_string_from_value (script_p->source_name)); +#endif /* JERRY_SOURCE_NAME */ + +#if JERRY_MODULE_SYSTEM + if (type & CBC_SCRIPT_HAS_IMPORT_META) + { + JERRY_ASSERT (!(type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)); + JERRY_ASSERT (ecma_is_value_object (CBC_SCRIPT_GET_IMPORT_META (script_p, type))); + + script_size += sizeof (ecma_value_t); + } +#endif /* JERRY_MODULE_SYSTEM */ + +#if JERRY_FUNCTION_TO_STRING + ecma_deref_ecma_string (ecma_get_string_from_value (script_p->source_code)); + + if (type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS) + { + ecma_deref_ecma_string (ecma_get_string_from_value (CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, type))); + script_size += sizeof (ecma_value_t); + } +#endif /* JERRY_FUNCTION_TO_STRING */ + + jmem_heap_free_block (script_p, script_size); +} /* ecma_script_deref */ + +/** + * Increase reference counter of Compact + * Byte Code or regexp byte code. + */ +void +ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ +{ + /* Abort program if maximum reference number is reached. */ + if (bytecode_p->refs >= UINT16_MAX) + { + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } + + bytecode_p->refs++; +} /* ecma_bytecode_ref */ + +/** + * Decrease reference counter of Compact + * Byte Code or regexp byte code. + */ +void +ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ +{ + JERRY_ASSERT (bytecode_p->refs > 0); + JERRY_ASSERT (!CBC_IS_FUNCTION (bytecode_p->status_flags) + || !(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + + bytecode_p->refs--; + + if (bytecode_p->refs > 0) + { + /* Non-zero reference counter. */ + return; + } + + if (CBC_IS_FUNCTION (bytecode_p->status_flags)) + { + ecma_value_t *literal_start_p = NULL; + uint32_t literal_end; + uint32_t const_literal_end; + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_p; + literal_end = args_p->literal_end; + const_literal_end = args_p->const_literal_end; + + literal_start_p = (ecma_value_t *) ((uint8_t *) bytecode_p + sizeof (cbc_uint16_arguments_t)); + literal_start_p -= args_p->register_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_p; + literal_end = args_p->literal_end; + const_literal_end = args_p->const_literal_end; + + literal_start_p = (ecma_value_t *) ((uint8_t *) bytecode_p + sizeof (cbc_uint8_arguments_t)); + literal_start_p -= args_p->register_end; + } + + for (uint32_t i = const_literal_end; i < literal_end; i++) + { + ecma_compiled_code_t *bytecode_literal_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, literal_start_p[i]); + + /* Self references are ignored. */ + if (bytecode_literal_p != bytecode_p) + { + ecma_bytecode_deref (bytecode_literal_p); + } + } + + ecma_script_deref (((cbc_uint8_arguments_t *) bytecode_p)->script_value); + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS) + { + ecma_collection_t *collection_p = ecma_compiled_code_get_tagged_template_collection (bytecode_p); + + /* Since the objects in the tagged template collection are not strong referenced anymore by the compiled code + we can treat them as 'new' objects. */ + JERRY_CONTEXT (ecma_gc_new_objects) += collection_p->item_count * 2; + ecma_collection_free_template_literal (collection_p); + } + +#if JERRY_LINE_INFO + if (bytecode_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO) + { + ecma_line_info_free (ecma_compiled_code_get_line_info (bytecode_p)); + } +#endif /* JERRY_LINE_INFO */ + + } + else + { +#if JERRY_BUILTIN_REGEXP + re_compiled_code_t *re_bytecode_p = (re_compiled_code_t *) bytecode_p; + + ecma_deref_ecma_string (ecma_get_string_from_value (re_bytecode_p->source)); +#endif /* JERRY_BUILTIN_REGEXP */ + } + + jmem_heap_free_block (bytecode_p, ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG); +} /* ecma_bytecode_deref */ + +/** + * Gets the script data asigned to a script / module / function + * + * @return script data - if available, JMEM_CP_NULL - otherwise + */ +ecma_value_t +ecma_script_get_from_value (ecma_value_t value) /**< compiled code */ +{ + if (!ecma_is_value_object (value)) + { + return JMEM_CP_NULL; + } + + ecma_object_t *object_p = ecma_get_object_from_value (value); + const ecma_compiled_code_t *bytecode_p = NULL; + + while (true) + { + switch (ecma_get_object_type (object_p)) + { + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_SCRIPT) + { + bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + break; + } + +#if JERRY_MODULE_SYSTEM + if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_MODULE) + { + ecma_module_t *module_p = (ecma_module_t *) object_p; + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)) + { + bytecode_p = module_p->u.compiled_code_p; + break; + } + } +#endif /* JERRY_MODULE_SYSTEM */ + return JMEM_CP_NULL; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + bytecode_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + object_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_object_p->u.bound_function.target_function); + continue; + } + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + return ((ecma_extended_object_t *) object_p)->u.constructor_function.script_value; + } + default: + { + return JMEM_CP_NULL; + } + } + + JERRY_ASSERT (bytecode_p != NULL); + return ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + } +} /* ecma_script_get_from_value */ + +/** + * Resolve the position of the arguments list start of the compiled code + * + * @return start position of the arguments list start of the compiled code + */ +ecma_value_t * +ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + + uint8_t *byte_p = (uint8_t *) bytecode_header_p; + byte_p += ((size_t) bytecode_header_p->size) << JMEM_ALIGNMENT_LOG; + + if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)) + { + return ((ecma_value_t *) byte_p); + } + + if (JERRY_LIKELY (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS))) + { + return ((ecma_value_t *) byte_p) - ((cbc_uint8_arguments_t *) bytecode_header_p)->argument_end; + } + + return ((ecma_value_t *) byte_p) - ((cbc_uint16_arguments_t *) bytecode_header_p)->argument_end; +} /* ecma_compiled_code_resolve_arguments_start */ + +/** + * Resolve the position of the function name of the compiled code + * + * @return position of the function name of the compiled code + */ +ecma_value_t * +ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + ecma_value_t *base_p = ecma_compiled_code_resolve_arguments_start (bytecode_header_p); + + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR) + { + base_p--; + } + + return base_p; +} /* ecma_compiled_code_resolve_function_name */ + +/** + * Get the tagged template collection of the compiled code + * + * @return pointer to the tagged template collection + */ +ecma_collection_t * +ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS); + + ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p); + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[-1]); +} /* ecma_compiled_code_get_tagged_template_collection */ + +#if JERRY_LINE_INFO + +/** + * Get the line info data from the byte code + * + * @return pointer to the line info data + */ +uint8_t * +ecma_compiled_code_get_line_info (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO); + + ecma_value_t *base_p = ecma_compiled_code_resolve_arguments_start (bytecode_header_p); + + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR) + { + base_p--; + } + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS) + { + base_p--; + } + + return ECMA_GET_INTERNAL_VALUE_POINTER (uint8_t, base_p[-1]); +} /* ecma_compiled_code_get_line_info */ + +#endif /* JERRY_LINE_INFO */ + +/** + * Get the source name of a compiled code. + * + * @return source name value + */ +ecma_value_t +ecma_get_source_name (const ecma_compiled_code_t *bytecode_p) /**< compiled code */ +{ +#if JERRY_SOURCE_NAME +#if JERRY_SNAPSHOT_EXEC + if (JERRY_UNLIKELY (bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_ANON); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + return ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value)->source_name; +#else /* !JERRY_SOURCE_NAME */ + JERRY_UNUSED (bytecode_p); + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_ANON); +#endif /* !JERRY_SOURCE_NAME */ +} /* ecma_get_source_name */ + +#if (JERRY_STACK_LIMIT != 0) +/** + * Check the current stack usage by calculating the difference from the initial stack base. + * + * @return current stack usage in bytes + */ +uintptr_t JERRY_ATTR_NOINLINE +ecma_get_current_stack_usage (void) +{ + volatile int __sp; + return (uintptr_t) (JERRY_CONTEXT (stack_base) - (uintptr_t) &__sp); +} /* ecma_get_current_stack_usage */ + +#endif /* (JERRY_STACK_LIMIT != 0) */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.h new file mode 100644 index 00000000..0e98ea24 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.h @@ -0,0 +1,524 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_HELPERS_H +#define ECMA_HELPERS_H + +#include "ecma-globals.h" + +#include "jmem.h" +#include "lit-strings.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +/** + * Get value of pointer from specified non-null compressed pointer. + */ +#define ECMA_GET_NON_NULL_POINTER(type, field) JMEM_CP_GET_NON_NULL_POINTER (type, field) + +/** + * Extract value of pointer from specified pointer-tag value + */ +#define ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG(type, field) \ + JMEM_CP_GET_NON_NULL_POINTER_FROM_POINTER_TAG (type, field) + +/** + * Get value of pointer from specified compressed pointer. + */ +#define ECMA_GET_POINTER(type, field) JMEM_CP_GET_POINTER (type, field) + +/** + * Set value of non-null compressed pointer so that it will correspond + * to specified non_compressed_pointer. + */ +#define ECMA_SET_NON_NULL_POINTER(field, non_compressed_pointer) \ + JMEM_CP_SET_NON_NULL_POINTER (field, non_compressed_pointer) + +/** + * Set value of pointer-tag value so that it will correspond + * to specified non_compressed_pointer along with tag + */ +#define ECMA_SET_NON_NULL_POINTER_TAG(field, non_compressed_pointer, tag) \ + JMEM_CP_SET_NON_NULL_POINTER_TAG (field, non_compressed_pointer, tag) + +/** + * Set value of compressed pointer so that it will correspond + * to specified non_compressed_pointer. + */ +#define ECMA_SET_POINTER(field, non_compressed_pointer) JMEM_CP_SET_POINTER (field, non_compressed_pointer) + +/** + * Get value of each tag bit from specified pointer-tag value + */ +#define ECMA_GET_FIRST_BIT_FROM_POINTER_TAG(field) \ + JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (field) /**< get first tag bit from jmem_cpointer_tag_t **/ +#define ECMA_GET_SECOND_BIT_FROM_POINTER_TAG(field) \ + JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (field) /**< get second tag bit from jmem_cpointer_tag_t **/ +#define ECMA_GET_THIRD_BIT_FROM_POINTER_TAG(field) \ + JMEM_CP_GET_THIRD_BIT_FROM_POINTER_TAG (field) /**< get third tag bit from jmem_cpointer_tag_t **/ + +/** + * Set value of each tag bit to specified pointer-tag value + */ +#define ECMA_SET_FIRST_BIT_TO_POINTER_TAG(field) \ + JMEM_CP_SET_FIRST_BIT_TO_POINTER_TAG (field) /**< set first tag bit to jmem_cpointer_tag_t **/ +#define ECMA_SET_SECOND_BIT_TO_POINTER_TAG(field) \ + JMEM_CP_SET_SECOND_BIT_TO_POINTER_TAG (field) /**< set second tag bit to jmem_cpointer_tag_t **/ +#define ECMA_SET_THIRD_BIT_TO_POINTER_TAG(field) \ + JMEM_CP_SET_THIRD_BIT_TO_POINTER_TAG (field) /**< set third tag bit to jmem_cpointer_tag_t **/ + +/** + * Status flags for ecma_string_get_chars function + */ +typedef enum +{ + ECMA_STRING_FLAG_EMPTY = 0, /**< No options are provided. */ + ECMA_STRING_FLAG_IS_ASCII = (1 << 0), /**< The string contains only ASCII characters. */ + ECMA_STRING_FLAG_REHASH_NEEDED = (1 << 1), /**< The hash of the string must be recalculated. + * For more details see ecma_append_chars_to_string */ + ECMA_STRING_FLAG_IS_UINT32 = (1 << 2), /**< The string repesents an UINT32 number */ + ECMA_STRING_FLAG_MUST_BE_FREED = (1 << 3), /**< The returned buffer must be freed */ +} ecma_string_flag_t; + +/** + * Underscore is ignored when this option is passed. + */ +#define ECMA_CONVERSION_ALLOW_UNDERSCORE 0x1 + +/** + * Convert ecma-string's contents to a cesu-8 string and put it into a buffer. + */ +#define ECMA_STRING_TO_UTF8_STRING(ecma_str_ptr, /**< ecma string pointer */ \ + utf8_ptr, /**< [out] output buffer pointer */ \ + utf8_str_size) /**< [out] output buffer size */ \ + lit_utf8_size_t utf8_str_size; \ + uint8_t utf8_ptr##flags = ECMA_STRING_FLAG_EMPTY; \ + const lit_utf8_byte_t *utf8_ptr = ecma_string_get_chars (ecma_str_ptr, &utf8_str_size, NULL, NULL, &utf8_ptr##flags); + +/** + * Free the cesu-8 string buffer allocated by 'ECMA_STRING_TO_UTF8_STRING' + */ +#define ECMA_FINALIZE_UTF8_STRING(utf8_ptr, /**< pointer to character buffer */ \ + utf8_str_size) /**< buffer size */ \ + if (utf8_ptr##flags & ECMA_STRING_FLAG_MUST_BE_FREED) \ + { \ + JERRY_ASSERT (utf8_ptr != NULL); \ + jmem_heap_free_block ((void *) utf8_ptr, utf8_str_size); \ + } + +#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + +/** + * Set an internal property value from pointer. + */ +#define ECMA_SET_INTERNAL_VALUE_POINTER(field, pointer) ((field) = ((ecma_value_t) pointer)) + +/** + * Set an internal property value from pointer. Pointer can be NULL. + */ +#define ECMA_SET_INTERNAL_VALUE_ANY_POINTER(field, pointer) ((field) = ((ecma_value_t) pointer)) + +/** + * Convert an internal property value to pointer. + */ +#define ECMA_GET_INTERNAL_VALUE_POINTER(type, field) ((type *) field) + +/** + * Convert an internal property value to pointer. Result can be NULL. + */ +#define ECMA_GET_INTERNAL_VALUE_ANY_POINTER(type, field) ((type *) field) + +/** + * Checks whether an internal property is NULL. + */ +#define ECMA_IS_INTERNAL_VALUE_NULL(field) ((field) == ((ecma_value_t) NULL)) + +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + +/** + * Set an internal property value from pointer. + */ +#define ECMA_SET_INTERNAL_VALUE_POINTER(field, pointer) ECMA_SET_NON_NULL_POINTER (field, pointer) + +/** + * Set an internal property value from pointer. Pointer can be NULL. + */ +#define ECMA_SET_INTERNAL_VALUE_ANY_POINTER(field, pointer) ECMA_SET_POINTER (field, pointer) + +/** + * Convert an internal property value to pointer. + */ +#define ECMA_GET_INTERNAL_VALUE_POINTER(type, field) ECMA_GET_NON_NULL_POINTER (type, field) + +/** + * Convert an internal property value to pointer. Result can be NULL. + */ +#define ECMA_GET_INTERNAL_VALUE_ANY_POINTER(type, field) ECMA_GET_POINTER (type, field) + +/** + * Checks whether an internal property is NULL. + */ +#define ECMA_IS_INTERNAL_VALUE_NULL(field) ((field) == ((ecma_value_t) JMEM_CP_NULL)) + +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + +/** + * Convert boolean to bitfield value. + */ +#define ECMA_BOOL_TO_BITFIELD(x) ((x) ? 1 : 0) + +/** + * Check whether the given type is ECMA_OBJECT_TYPE_PROXY + * + * @param type object type + */ +#define ECMA_OBJECT_TYPE_IS_PROXY(type) (JERRY_UNLIKELY ((type) == ECMA_OBJECT_TYPE_PROXY)) + +/** + * Check whether the given object has [[ProxyHandler]] and [[ProxyTarger]] internal slots + * + * @param obj_p ecma-object + */ +#if JERRY_BUILTIN_PROXY +#define ECMA_OBJECT_IS_PROXY(obj_p) (ECMA_OBJECT_TYPE_IS_PROXY (ecma_get_object_type ((obj_p)))) +#else /* !JERRY_BUILTIN_PROXY */ +#define ECMA_OBJECT_IS_PROXY(obj_p) (false) +#endif /* JERRY_BUILTIN_PROXY */ + +/* ecma-helpers-value.c */ +ecma_type_t JERRY_ATTR_CONST ecma_get_value_type_field (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_direct (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_simple (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_empty (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_undefined (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_null (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_boolean (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_true (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_false (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_found (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_array_hole (ecma_value_t value); + +bool JERRY_ATTR_CONST ecma_is_value_integer_number (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_are_values_integer_numbers (ecma_value_t first_value, ecma_value_t second_value); +bool JERRY_ATTR_CONST ecma_is_value_float_number (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_number (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_string (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_symbol (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_magic_string (ecma_value_t value, lit_magic_string_id_t id); +bool JERRY_ATTR_CONST ecma_is_value_bigint (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_prop_name (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_direct_string (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_non_direct_string (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_object (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_exception (ecma_value_t value); +ecma_value_t ecma_is_value_array (ecma_value_t arg); + +void ecma_check_value_type_is_spec_defined (ecma_value_t value); + +ecma_value_t JERRY_ATTR_CONST ecma_make_boolean_value (bool boolean_value); +ecma_value_t JERRY_ATTR_CONST ecma_make_integer_value (ecma_integer_value_t integer_value); +ecma_value_t ecma_make_nan_value (void); +ecma_value_t ecma_make_float_value (ecma_number_t *ecma_num_p); +ecma_value_t ecma_make_length_value (ecma_length_t length); +ecma_value_t ecma_make_number_value (ecma_number_t ecma_number); +ecma_value_t ecma_make_int32_value (int32_t int32_number); +ecma_value_t ecma_make_uint32_value (uint32_t uint32_number); +ecma_value_t JERRY_ATTR_PURE ecma_make_string_value (const ecma_string_t *ecma_string_p); +ecma_value_t JERRY_ATTR_PURE ecma_make_symbol_value (const ecma_string_t *ecma_symbol_p); +ecma_value_t JERRY_ATTR_PURE ecma_make_prop_name_value (const ecma_string_t *ecma_prop_name_p); +ecma_value_t JERRY_ATTR_PURE ecma_make_magic_string_value (lit_magic_string_id_t id); +ecma_value_t JERRY_ATTR_PURE ecma_make_object_value (const ecma_object_t *object_p); +ecma_value_t JERRY_ATTR_PURE ecma_make_extended_primitive_value (const ecma_extended_primitive_t *primitve_p, + uint32_t type); +ecma_integer_value_t JERRY_ATTR_CONST ecma_get_integer_from_value (ecma_value_t value); +ecma_number_t JERRY_ATTR_PURE ecma_get_float_from_value (ecma_value_t value); +ecma_number_t *ecma_get_pointer_from_float_value (ecma_value_t value); +ecma_number_t JERRY_ATTR_PURE ecma_get_number_from_value (ecma_value_t value); +ecma_string_t JERRY_ATTR_PURE *ecma_get_string_from_value (ecma_value_t value); +ecma_string_t JERRY_ATTR_PURE *ecma_get_symbol_from_value (ecma_value_t value); +ecma_string_t JERRY_ATTR_PURE *ecma_get_prop_name_from_value (ecma_value_t value); +ecma_object_t JERRY_ATTR_PURE *ecma_get_object_from_value (ecma_value_t value); +ecma_extended_primitive_t JERRY_ATTR_PURE *ecma_get_extended_primitive_from_value (ecma_value_t value); +ecma_value_t JERRY_ATTR_CONST ecma_invert_boolean_value (ecma_value_t value); +ecma_value_t ecma_copy_value (ecma_value_t value); +ecma_value_t ecma_fast_copy_value (ecma_value_t value); +ecma_value_t ecma_copy_value_if_not_object (ecma_value_t value); +void ecma_ref_if_object (ecma_value_t value); +void ecma_deref_if_object (ecma_value_t value); +ecma_value_t ecma_update_float_number (ecma_value_t float_value, ecma_number_t new_number); +void ecma_value_assign_value (ecma_value_t *value_p, ecma_value_t ecma_value); +void ecma_value_assign_number (ecma_value_t *value_p, ecma_number_t ecma_number); +void ecma_free_value (ecma_value_t value); +void ecma_fast_free_value (ecma_value_t value); +void ecma_free_value_if_not_object (ecma_value_t value); +void ecma_free_object (ecma_value_t value); +void ecma_free_number (ecma_value_t value); +lit_magic_string_id_t ecma_get_typeof_lit_id (ecma_value_t value); + +/* ecma-helpers-string.c */ +ecma_string_t *ecma_new_symbol_from_descriptor_string (ecma_value_t string_desc); +bool ecma_prop_name_is_symbol (ecma_string_t *string_p); +ecma_length_t ecma_op_advance_string_index (ecma_string_t *str_p, ecma_length_t index_num, bool is_unicode); +#if JERRY_BUILTIN_CONTAINER +ecma_string_t *ecma_new_map_key_string (ecma_value_t value); +bool ecma_prop_name_is_map_key (ecma_string_t *string_p); +#endif /* JERRY_BUILTIN_CONTAINER */ +ecma_string_t *ecma_new_ecma_string_from_ascii (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); +ecma_string_t *ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); +ecma_string_t *ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string_p, + lit_utf8_size_t string_size); +ecma_string_t * +ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size, void *user_p); +ecma_string_t *ecma_new_ecma_string_from_code_unit (ecma_char_t code_unit); +ecma_string_t *ecma_new_ecma_string_from_code_units (ecma_char_t first_code_unit, ecma_char_t second_code_unit); +ecma_string_t *ecma_new_ecma_string_from_length (ecma_length_t index); +ecma_string_t *ecma_new_ecma_string_from_uint32 (uint32_t uint32_number); +ecma_string_t *ecma_new_non_direct_string_from_uint32 (uint32_t uint32_number); +ecma_string_t *ecma_get_ecma_string_from_uint32 (uint32_t uint32_number); +ecma_string_t *ecma_new_ecma_string_from_number (ecma_number_t num); +ecma_string_t *ecma_get_magic_string (lit_magic_string_id_t id); +ecma_string_t *ecma_get_internal_string (lit_magic_string_id_t id); +ecma_string_t *ecma_append_chars_to_string (ecma_string_t *string1_p, + const lit_utf8_byte_t *cesu8_string2_p, + lit_utf8_size_t cesu8_string2_size, + lit_utf8_size_t cesu8_string2_length); +ecma_string_t *ecma_concat_ecma_strings (ecma_string_t *string1_p, ecma_string_t *string2_p); +void ecma_ref_ecma_string (ecma_string_t *string_p); +void ecma_ref_ecma_string_non_direct (ecma_string_t *string_p); +void ecma_deref_ecma_string (ecma_string_t *string_p); +void ecma_deref_ecma_string_non_direct (ecma_string_t *string_p); +void ecma_destroy_ecma_string (ecma_string_t *string_p); +ecma_number_t ecma_string_to_number (const ecma_string_t *str_p); +uint32_t ecma_string_get_array_index (const ecma_string_t *str_p); + +lit_utf8_size_t JERRY_ATTR_WARN_UNUSED_RESULT ecma_string_copy_to_buffer (const ecma_string_t *string_desc_p, + lit_utf8_byte_t *buffer_p, + lit_utf8_size_t buffer_size, + jerry_encoding_t encoding); +void +ecma_string_to_cesu8_bytes (const ecma_string_t *string_desc_p, lit_utf8_byte_t *buffer_p, lit_utf8_size_t buffer_size); +const lit_utf8_byte_t *ecma_string_get_chars (const ecma_string_t *string_p, + lit_utf8_size_t *size_p, + lit_utf8_size_t *length_p, + lit_utf8_byte_t *uint32_buff_p, + uint8_t *flags_p); +bool ecma_compare_ecma_string_to_magic_id (const ecma_string_t *string_p, lit_magic_string_id_t id); +bool ecma_string_is_empty (const ecma_string_t *string_p); +bool ecma_string_is_length (const ecma_string_t *string_p); + +jmem_cpointer_t ecma_string_to_property_name (ecma_string_t *prop_name_p, ecma_property_t *name_type_p); +ecma_string_t *ecma_string_from_property_name (ecma_property_t property, jmem_cpointer_t prop_name_cp); +lit_string_hash_t ecma_string_get_property_name_hash (ecma_property_t property, jmem_cpointer_t prop_name_cp); +uint32_t ecma_string_get_property_index (ecma_property_t property, jmem_cpointer_t prop_name_cp); +bool ecma_string_compare_to_property_name (ecma_property_t property, + jmem_cpointer_t prop_name_cp, + const ecma_string_t *string_p); + +bool ecma_compare_ecma_strings (const ecma_string_t *string1_p, const ecma_string_t *string2_p); +bool ecma_compare_ecma_non_direct_strings (const ecma_string_t *string1_p, const ecma_string_t *string2_p); +bool ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, const ecma_string_t *string2_p); +lit_utf8_size_t ecma_string_get_length (const ecma_string_t *string_p); +lit_utf8_size_t ecma_string_get_utf8_length (const ecma_string_t *string_p); +lit_utf8_size_t ecma_string_get_size (const ecma_string_t *string_p); +lit_utf8_size_t ecma_string_get_utf8_size (const ecma_string_t *string_p); +ecma_char_t ecma_string_get_char_at_pos (const ecma_string_t *string_p, lit_utf8_size_t index); + +lit_magic_string_id_t ecma_get_string_magic (const ecma_string_t *string_p); + +lit_string_hash_t ecma_string_hash (const ecma_string_t *string_p); +ecma_string_t *ecma_string_substr (const ecma_string_t *string_p, lit_utf8_size_t start_pos, lit_utf8_size_t end_pos); +const lit_utf8_byte_t *ecma_string_trim_front (const lit_utf8_byte_t *start_p, const lit_utf8_byte_t *end_p); +const lit_utf8_byte_t *ecma_string_trim_back (const lit_utf8_byte_t *start_p, const lit_utf8_byte_t *end_p); +void ecma_string_trim_helper (const lit_utf8_byte_t **utf8_str_p, lit_utf8_size_t *utf8_str_size); +ecma_string_t *ecma_string_trim (const ecma_string_t *string_p); +ecma_value_t +ecma_string_pad (ecma_value_t original_string_p, ecma_value_t max_length, ecma_value_t fill_string, bool pad_on_start); + +ecma_stringbuilder_t ecma_stringbuilder_create (void); +ecma_stringbuilder_t ecma_stringbuilder_create_from (ecma_string_t *string_p); +ecma_stringbuilder_t ecma_stringbuilder_create_raw (const lit_utf8_byte_t *data_p, const lit_utf8_size_t data_size); +lit_utf8_size_t ecma_stringbuilder_get_size (ecma_stringbuilder_t *builder_p); +lit_utf8_byte_t *ecma_stringbuilder_get_data (ecma_stringbuilder_t *builder_p); +void ecma_stringbuilder_revert (ecma_stringbuilder_t *builder_p, const lit_utf8_size_t size); +void ecma_stringbuilder_append (ecma_stringbuilder_t *builder_p, const ecma_string_t *string_p); +void ecma_stringbuilder_append_magic (ecma_stringbuilder_t *builder_p, const lit_magic_string_id_t id); +void ecma_stringbuilder_append_raw (ecma_stringbuilder_t *builder_p, + const lit_utf8_byte_t *data_p, + const lit_utf8_size_t data_size); +void ecma_stringbuilder_append_codepoint (ecma_stringbuilder_t *builder_p, lit_code_point_t cp); +void ecma_stringbuilder_append_char (ecma_stringbuilder_t *builder_p, const ecma_char_t c); +void ecma_stringbuilder_append_byte (ecma_stringbuilder_t *builder_p, const lit_utf8_byte_t); +ecma_string_t *ecma_stringbuilder_finalize (ecma_stringbuilder_t *builder_p); +void ecma_stringbuilder_destroy (ecma_stringbuilder_t *builder_p); + +/* ecma-helpers-number.c */ +ecma_number_t ecma_number_make_nan (void); +ecma_number_t ecma_number_make_infinity (bool sign); +bool ecma_number_is_nan (ecma_number_t num); +bool ecma_number_is_negative (ecma_number_t num); +bool ecma_number_is_zero (ecma_number_t num); +bool ecma_number_is_infinity (ecma_number_t num); +bool ecma_number_is_finite (ecma_number_t num); +ecma_number_t ecma_number_get_prev (ecma_number_t num); +ecma_number_t ecma_number_get_next (ecma_number_t num); +ecma_number_t ecma_number_trunc (ecma_number_t num); +ecma_number_t ecma_number_remainder (ecma_number_t left_num, ecma_number_t right_num); +ecma_number_t ecma_number_pow (ecma_number_t x, ecma_number_t y); +ecma_value_t +ecma_number_parse_int (const lit_utf8_byte_t *string_buff, lit_utf8_size_t string_buff_size, ecma_value_t radix); +ecma_value_t ecma_number_parse_float (const lit_utf8_byte_t *string_buff, lit_utf8_size_t string_buff_size); +ecma_value_t ecma_integer_multiply (ecma_integer_value_t left_integer, ecma_integer_value_t right_integer); +lit_utf8_size_t ecma_number_to_decimal (ecma_number_t num, lit_utf8_byte_t *out_digits_p, int32_t *out_decimal_exp_p); + +/* ecma-helpers-collection.c */ +ecma_collection_t *ecma_new_collection (void); +void ecma_collection_push_back (ecma_collection_t *collection_p, ecma_value_t value); +void ecma_collection_reserve (ecma_collection_t *collection_p, uint32_t count); +void ecma_collection_append (ecma_collection_t *collection_p, const ecma_value_t *buffer_p, uint32_t count); +void ecma_collection_destroy (ecma_collection_t *collection_p); +void ecma_collection_free (ecma_collection_t *collection_p); +void ecma_collection_free_if_not_object (ecma_collection_t *collection_p); +void ecma_collection_free_objects (ecma_collection_t *collection_p); +void ecma_collection_free_template_literal (ecma_collection_t *collection_p); +bool ecma_collection_check_duplicated_entries (ecma_collection_t *collection_p); +bool ecma_collection_has_string_value (ecma_collection_t *collection_p, ecma_string_t *string_p); + +ecma_value_t *ecma_new_compact_collection (void); +ecma_value_t *ecma_compact_collection_push_back (ecma_value_t *compact_collection_p, ecma_value_t value); +ecma_value_t *ecma_compact_collection_shrink (ecma_value_t *compact_collection_p); +void ecma_compact_collection_free (ecma_value_t *compact_collection_p); +ecma_value_t *ecma_compact_collection_end (ecma_value_t *compact_collection_p); +void ecma_compact_collection_destroy (ecma_value_t *compact_collection_p); + +/* ecma-helpers.c */ +ecma_object_t *ecma_create_object (ecma_object_t *prototype_object_p, size_t ext_object_size, ecma_object_type_t type); +ecma_object_t *ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p); +ecma_object_t *ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, ecma_object_t *binding_obj_p); +ecma_object_t *ecma_create_lex_env_class (ecma_object_t *outer_lexical_environment_p, size_t lexical_env_size); +bool JERRY_ATTR_PURE ecma_is_lexical_environment (const ecma_object_t *object_p); +void ecma_op_ordinary_object_set_extensible (ecma_object_t *object_p); +ecma_object_type_t JERRY_ATTR_PURE ecma_get_object_type (const ecma_object_t *object_p); +ecma_object_base_type_t JERRY_ATTR_PURE ecma_get_object_base_type (const ecma_object_t *object_p); +bool JERRY_ATTR_PURE ecma_object_class_is (ecma_object_t *object_p, ecma_object_class_type_t class_id); +ecma_lexical_environment_type_t JERRY_ATTR_PURE ecma_get_lex_env_type (const ecma_object_t *object_p); +ecma_object_t JERRY_ATTR_PURE *ecma_get_lex_env_binding_object (const ecma_object_t *object_p); +ecma_object_t *ecma_clone_decl_lexical_environment (ecma_object_t *lex_env_p, bool copy_values); + +ecma_property_value_t *ecma_create_named_data_property (ecma_object_t *object_p, + ecma_string_t *name_p, + uint8_t prop_attributes, + ecma_property_t **out_prop_p); +ecma_property_value_t *ecma_create_named_accessor_property (ecma_object_t *object_p, + ecma_string_t *name_p, + ecma_object_t *get_p, + ecma_object_t *set_p, + uint8_t prop_attributes, + ecma_property_t **out_prop_p); +#if JERRY_MODULE_SYSTEM +void ecma_create_named_reference_property (ecma_object_t *object_p, ecma_string_t *name_p, ecma_value_t reference); +#endif /* JERRY_MODULE_SYSTEM */ +ecma_property_t *ecma_find_named_property (ecma_object_t *obj_p, ecma_string_t *name_p); +ecma_property_value_t *ecma_get_named_data_property (ecma_object_t *obj_p, ecma_string_t *name_p); + +void ecma_delete_property (ecma_object_t *object_p, ecma_property_value_t *prop_value_p); + +void +ecma_named_data_property_assign_value (ecma_object_t *obj_p, ecma_property_value_t *prop_value_p, ecma_value_t value); + +ecma_getter_setter_pointers_t *ecma_get_named_accessor_property (const ecma_property_value_t *prop_value_p); +void ecma_set_named_accessor_property_getter (ecma_object_t *object_p, + ecma_property_value_t *prop_value_p, + ecma_object_t *getter_p); +void ecma_set_named_accessor_property_setter (ecma_object_t *object_p, + ecma_property_value_t *prop_value_p, + ecma_object_t *setter_p); +#if JERRY_MODULE_SYSTEM +ecma_value_t ecma_property_to_reference (ecma_property_t *property_p); +ecma_property_value_t *ecma_get_property_value_from_named_reference (ecma_property_value_t *reference_p); +#endif /* JERRY_MODULE_SYSTEM */ +bool ecma_is_property_writable (ecma_property_t property); +void ecma_set_property_writable_attr (ecma_property_t *property_p, bool is_writable); +bool ecma_is_property_enumerable (ecma_property_t property); +void ecma_set_property_enumerable_attr (ecma_property_t *property_p, bool is_enumerable); +bool ecma_is_property_configurable (ecma_property_t property); +void ecma_set_property_configurable_attr (ecma_property_t *property_p, bool is_configurable); + +#if JERRY_LCACHE +bool ecma_is_property_lcached (ecma_property_t *property_p); +void ecma_set_property_lcached (ecma_property_t *property_p, bool is_lcached); +#endif /* JERRY_LCACHE */ + +ecma_property_descriptor_t ecma_make_empty_property_descriptor (void); +void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p); + +void ecma_ref_extended_primitive (ecma_extended_primitive_t *primitve_p); +void ecma_deref_exception (ecma_extended_primitive_t *exception_p); +#if JERRY_BUILTIN_BIGINT +void ecma_deref_bigint (ecma_extended_primitive_t *bigint_p); +#endif /* JERRY_BUILTIN_BIGINT */ + +ecma_value_t ecma_create_exception (ecma_value_t value, uint32_t options); +ecma_value_t ecma_create_exception_from_context (void); +ecma_value_t ecma_create_exception_from_object (ecma_object_t *object_p); +void ecma_throw_exception (ecma_value_t value); + +void ecma_script_deref (ecma_value_t script_value); +void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p); +void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p); +ecma_value_t ecma_script_get_from_value (ecma_value_t value); +ecma_value_t *ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p); +ecma_value_t *ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p); +ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p); +#if JERRY_LINE_INFO +uint8_t *ecma_compiled_code_get_line_info (const ecma_compiled_code_t *bytecode_header_p); +#endif /* JERRY_LINE_INFO */ +ecma_value_t ecma_get_source_name (const ecma_compiled_code_t *bytecode_p); +#if (JERRY_STACK_LIMIT != 0) +uintptr_t ecma_get_current_stack_usage (void); +#endif /* (JERRY_STACK_LIMIT != 0) */ + +/* ecma-helpers-external-pointers.c */ +bool ecma_create_native_pointer_property (ecma_object_t *obj_p, + void *native_p, + const jerry_object_native_info_t *native_info_p); +ecma_native_pointer_t *ecma_get_native_pointer_value (ecma_object_t *obj_p, + const jerry_object_native_info_t *native_info_p); +bool ecma_delete_native_pointer_property (ecma_object_t *obj_p, const jerry_object_native_info_t *native_info_p); + +/* ecma-helpers-conversion.c */ +ecma_number_t ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, lit_utf8_size_t str_size, uint32_t option); +ecma_number_t ecma_utf8_string_to_number_by_radix (const lit_utf8_byte_t *str_p, + lit_utf8_size_t str_size, + uint32_t radix, + uint32_t option); +lit_utf8_size_t ecma_uint32_to_utf8_string (uint32_t value, lit_utf8_byte_t *out_buffer_p, lit_utf8_size_t buffer_size); +uint32_t ecma_number_to_uint32 (ecma_number_t num); +int32_t ecma_number_to_int32 (ecma_number_t num); +lit_utf8_size_t ecma_number_to_utf8_string (ecma_number_t num, lit_utf8_byte_t *buffer_p, lit_utf8_size_t buffer_size); + +/* ecma-helpers-errol.c */ +lit_utf8_size_t ecma_errol0_dtoa (double val, lit_utf8_byte_t *buffer_p, int32_t *exp_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_HELPERS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.cpp new file mode 100644 index 00000000..60a3b2e0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.cpp @@ -0,0 +1,106 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-init-finalize.h" + +#include "ecma-builtins.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-literal-storage.h" + +#include "jcontext.h" +#include "jmem.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmainitfinalize Initialization and finalization of ECMA components + * @{ + */ + +/** + * Maximum number of GC loops on cleanup. + */ +#define JERRY_GC_LOOP_LIMIT 100 + +/** + * Initialize ECMA components + */ +void +ecma_init (void) +{ +#if (JERRY_GC_MARK_LIMIT != 0) + JERRY_CONTEXT (ecma_gc_mark_recursion_limit) = JERRY_GC_MARK_LIMIT; +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + + ecma_init_global_environment (); + +#if JERRY_PROPERTY_HASHMAP + JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) = ECMA_PROP_HASHMAP_ALLOC_ON; + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_HIGH_PRESSURE_GC; +#endif /* JERRY_PROPERTY_HASHMAP */ + +#if (JERRY_STACK_LIMIT != 0) + volatile int sp; + JERRY_CONTEXT (stack_base) = (uintptr_t) &sp; +#endif /* (JERRY_STACK_LIMIT != 0) */ + + ecma_job_queue_init (); + + JERRY_CONTEXT (current_new_target_p) = NULL; + +#if JERRY_BUILTIN_TYPEDARRAY + JERRY_CONTEXT (arraybuffer_compact_allocation_limit) = 256; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* ecma_init */ + +/** + * Finalize ECMA components + */ +void +ecma_finalize (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p) == NULL); + + ecma_finalize_global_environment (); + uint8_t runs = 0; + + do + { + ecma_gc_run (); + if (++runs >= JERRY_GC_LOOP_LIMIT) + { + jerry_fatal (JERRY_FATAL_UNTERMINATED_GC_LOOPS); + } + } while (JERRY_CONTEXT (ecma_gc_new_objects) != 0); + + jmem_cpointer_t *global_symbols_cp = JERRY_CONTEXT (global_symbols_cp); + + for (uint32_t i = 0; i < ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT; i++) + { + if (global_symbols_cp[i] != JMEM_CP_NULL) + { + ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t, global_symbols_cp[i])); + } + } + + ecma_finalize_lit_storage (); +} /* ecma_finalize */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.h new file mode 100644 index 00000000..0e4fda21 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_INIT_FINALIZE_H +#define ECMA_INIT_FINALIZE_H + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmainitfinalize Initialization and finalization of ECMA components + * @{ + */ + +void ecma_init (void); +void ecma_finalize (void); + +/** + * @} + * @} + */ + +#endif /* !ECMA_INIT_FINALIZE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.cpp new file mode 100644 index 00000000..e6a87388 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.cpp @@ -0,0 +1,221 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-lcache.h" + +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalcache Property lookup cache + * @{ + */ + +#if JERRY_LCACHE + +/** + * Bitshift index for calculating hash. + */ +#if JERRY_CPOINTER_32_BIT +#define ECMA_LCACHE_HASH_BITSHIFT_INDEX (2 * JMEM_ALIGNMENT_LOG) +#else /* !JERRY_CPOINTER_32_BIT */ +#define ECMA_LCACHE_HASH_BITSHIFT_INDEX 0 +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Mask for hash bits + */ +#define ECMA_LCACHE_HASH_MASK ((ECMA_LCACHE_HASH_ROWS_COUNT - 1) << ECMA_LCACHE_HASH_BITSHIFT_INDEX) + +/** + * Bitshift index for creating property identifier + */ +#define ECMA_LCACHE_HASH_ENTRY_ID_SHIFT (8 * sizeof (jmem_cpointer_t)) + +/** + * Create property identifier + */ +#define ECMA_LCACHE_CREATE_ID(object_cp, name_cp) \ + (((ecma_lcache_hash_entry_id_t) (object_cp) << ECMA_LCACHE_HASH_ENTRY_ID_SHIFT) | (name_cp)) + +/** + * Invalidate specified LCache entry + */ +static inline void +ecma_lcache_invalidate_entry (ecma_lcache_hash_entry_t *entry_p) /**< entry to invalidate */ +{ + JERRY_ASSERT (entry_p != NULL); + JERRY_ASSERT (entry_p->id != 0); + JERRY_ASSERT (entry_p->prop_p != NULL); + + entry_p->id = 0; + ecma_set_property_lcached (entry_p->prop_p, false); +} /* ecma_lcache_invalidate_entry */ + +/** + * Compute the row index of object / property name pair + * + * @return row index + */ +static inline size_t +ecma_lcache_row_index (jmem_cpointer_t object_cp, /**< compressed pointer to object */ + jmem_cpointer_t name_cp) /**< compressed pointer to property name */ +{ + /* Randomize the property name with the object pointer using a xor operation, + * so properties of different objects with the same name can be cached effectively. */ + return (size_t) (((name_cp ^ object_cp) & ECMA_LCACHE_HASH_MASK) >> ECMA_LCACHE_HASH_BITSHIFT_INDEX); +} /* ecma_lcache_row_index */ + +/** + * Insert an entry into LCache + */ +void +ecma_lcache_insert (const ecma_object_t *object_p, /**< object */ + const jmem_cpointer_t name_cp, /**< property name */ + ecma_property_t *prop_p) /**< property */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (prop_p != NULL && !ecma_is_property_lcached (prop_p)); + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*prop_p)); + + jmem_cpointer_t object_cp; + + ECMA_SET_NON_NULL_POINTER (object_cp, object_p); + + size_t row_index = ecma_lcache_row_index (object_cp, name_cp); + ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache)[row_index]; + ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH; + + do + { + if (entry_p->id == 0) + { + goto insert; + } + + entry_p++; + } while (entry_p < entry_end_p); + + /* Invalidate the last entry. */ + ecma_lcache_invalidate_entry (--entry_p); + + /* Shift other entries towards the end. */ + for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH - 1; i++) + { + entry_p->id = entry_p[-1].id; + entry_p->prop_p = entry_p[-1].prop_p; + entry_p--; + } + +insert: + entry_p->prop_p = prop_p; + entry_p->id = ECMA_LCACHE_CREATE_ID (object_cp, name_cp); + + ecma_set_property_lcached (entry_p->prop_p, true); +} /* ecma_lcache_insert */ + +/** + * Lookup property in the LCache + * + * @return a pointer to an ecma_property_t if the lookup is successful + * NULL otherwise + */ +ecma_property_t * +ecma_lcache_lookup (const ecma_object_t *object_p, /**< object */ + const ecma_string_t *prop_name_p) /**< property's name */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (prop_name_p != NULL); + + jmem_cpointer_t object_cp; + ECMA_SET_NON_NULL_POINTER (object_cp, object_p); + + ecma_property_t prop_name_type = ECMA_DIRECT_STRING_PTR; + jmem_cpointer_t prop_name_cp; + + if (JERRY_UNLIKELY (ECMA_IS_DIRECT_STRING (prop_name_p))) + { + prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (prop_name_p); + prop_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (prop_name_p); + } + else + { + ECMA_SET_NON_NULL_POINTER (prop_name_cp, prop_name_p); + } + + size_t row_index = ecma_lcache_row_index (object_cp, prop_name_cp); + + ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache)[row_index]; + ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH; + ecma_lcache_hash_entry_id_t id = ECMA_LCACHE_CREATE_ID (object_cp, prop_name_cp); + + do + { + if (entry_p->id == id && JERRY_LIKELY (ECMA_PROPERTY_GET_NAME_TYPE (*entry_p->prop_p) == prop_name_type)) + { + JERRY_ASSERT (entry_p->prop_p != NULL && ecma_is_property_lcached (entry_p->prop_p)); + return entry_p->prop_p; + } + entry_p++; + } while (entry_p < entry_end_p); + + return NULL; +} /* ecma_lcache_lookup */ + +/** + * Invalidate LCache entries associated with given object and property name / property + */ +void +ecma_lcache_invalidate (const ecma_object_t *object_p, /**< object */ + const jmem_cpointer_t name_cp, /**< property name */ + ecma_property_t *prop_p) /**< property */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p)); + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*prop_p)); + + jmem_cpointer_t object_cp; + ECMA_SET_NON_NULL_POINTER (object_cp, object_p); + + size_t row_index = ecma_lcache_row_index (object_cp, name_cp); + ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache)[row_index]; + + while (true) + { + /* The property must be present. */ + JERRY_ASSERT (entry_p - JERRY_CONTEXT (lcache)[row_index] < ECMA_LCACHE_HASH_ROW_LENGTH); + + if (entry_p->id != 0 && entry_p->prop_p == prop_p) + { + JERRY_ASSERT (entry_p->id == ECMA_LCACHE_CREATE_ID (object_cp, name_cp)); + + ecma_lcache_invalidate_entry (entry_p); + return; + } + entry_p++; + } +} /* ecma_lcache_invalidate */ + +#endif /* JERRY_LCACHE */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.h new file mode 100644 index 00000000..818e410b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.h @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_LCACHE_H +#define ECMA_LCACHE_H + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalcache Property lookup cache + * @{ + */ + +#include "ecma-globals.h" + +#if JERRY_LCACHE +void ecma_lcache_insert (const ecma_object_t *object_p, const jmem_cpointer_t name_cp, ecma_property_t *prop_p); +ecma_property_t *ecma_lcache_lookup (const ecma_object_t *object_p, const ecma_string_t *prop_name_p); +void ecma_lcache_invalidate (const ecma_object_t *object_p, const jmem_cpointer_t name_cp, ecma_property_t *prop_p); + +#endif /* JERRY_LCACHE */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_LCACHE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.cpp new file mode 100644 index 00000000..48760e84 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.cpp @@ -0,0 +1,271 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-line-info.h" + +#include "ecma-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalineinfo Line info + * @{ + */ + +#if JERRY_LINE_INFO + +/* The layout of the structure is defined in js-parser-line-info-create.c */ + +JERRY_STATIC_ASSERT ((ECMA_LINE_INFO_COLUMN_DEFAULT - 1) == ((ECMA_LINE_INFO_ENCODE_TWO_BYTE >> 1) - 1), + ecma_line_info_column_1_must_be_accessible_with_the_highest_one_byte_negative_value); + +/** + * Decodes an uint32_t number, and updates the buffer position. + * Numbers expected to be larger values. + * + * @return the decoded value + */ +uint32_t +ecma_line_info_decode_vlq (uint8_t **buffer_p) /**< [in/out] target buffer */ +{ + uint8_t *source_p = *buffer_p; + uint32_t value = 0; + + do + { + value = (value << ECMA_LINE_INFO_VLQ_SHIFT) | (*source_p & ECMA_LINE_INFO_VLQ_MASK); + } while (*source_p++ & ECMA_LINE_INFO_VLQ_CONTINUE); + + *buffer_p = source_p; + return value; +} /* ecma_line_info_decode_vlq */ + +/** + * Decodes an uint32_t number, and updates the buffer position. + * Numbers expected to be smaller values. + * + * @return the decoded value + */ +static uint32_t +ecma_line_info_decode_small (uint8_t **buffer_p) /**< [in/out] target buffer */ +{ + uint8_t *source_p = *buffer_p; + uint32_t type = source_p[0]; + + *buffer_p = source_p + 1; + + if (type < ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN) + { + return type; + } + + if (type == ECMA_LINE_INFO_ENCODE_TWO_BYTE) + { + *buffer_p = source_p + 2; + return ((uint32_t) source_p[1]) + ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN; + } + + JERRY_ASSERT (type == ECMA_LINE_INFO_ENCODE_VLQ); + return ecma_line_info_decode_vlq (buffer_p) + ECMA_LINE_INFO_ENCODE_VLQ_MIN; +} /* ecma_line_info_decode_small */ + +/** + * Updates a value using an encoded difference. + * + * @return updated value + */ +uint32_t +ecma_line_info_difference_update (uint32_t current_value, /**< current value */ + uint32_t difference_value) /**< encoded difference */ +{ + if ((difference_value & 0x1) == ECMA_LINE_INFO_INCREASE) + { + return current_value + (difference_value >> 1) + 1; + } + + return current_value - (difference_value >> 1); +} /* ecma_line_info_difference_update */ + +/** + * Release line info data. + */ +void +ecma_line_info_free (uint8_t *line_info_p) /**< line info buffer */ +{ + uint8_t *source_p = line_info_p; + uint32_t total_length = ecma_line_info_decode_vlq (&source_p); + + jmem_heap_free_block (line_info_p, total_length + (uint32_t) (source_p - line_info_p)); +} /* ecma_line_info_free */ + +/** + * Returns the line/column information for a given byte code offset. + */ +void +ecma_line_info_get (uint8_t *line_info_p, /**< line info buffer */ + uint32_t offset, /**< byte code offset */ + jerry_frame_location_t *location_p) /**< [out] location */ +{ + uint32_t line = 1; + uint32_t column = ECMA_LINE_INFO_COLUMN_DEFAULT; + uint32_t end_offset = 0; + uint32_t end_offset_increase; + uint32_t value; + + /* Skip total_length. */ + ecma_line_info_decode_vlq (&line_info_p); + + while (true) + { + value = ecma_line_info_decode_vlq (&line_info_p); + line = ecma_line_info_difference_update (line, value); + + if (*line_info_p == 0) + { + break; + } + + uint8_t *size_p = line_info_p + *line_info_p + (ECMA_LINE_INFO_STREAM_SIZE_MIN + 1); + + uint32_t next_end_offset = end_offset + ecma_line_info_decode_vlq (&size_p); + + if (offset < next_end_offset) + { + break; + } + + end_offset = next_end_offset; + line_info_p = size_p; + } + + line_info_p++; + + do + { + end_offset_increase = ecma_line_info_decode_small (&line_info_p); + + if (end_offset_increase & ECMA_LINE_INFO_HAS_LINE) + { + value = ecma_line_info_decode_small (&line_info_p); + line = ecma_line_info_difference_update (line, value); + column = ECMA_LINE_INFO_COLUMN_DEFAULT; + } + + end_offset_increase >>= 1; + + value = ecma_line_info_decode_small (&line_info_p); + column = ecma_line_info_difference_update (column, value); + + end_offset += end_offset_increase; + } while (end_offset_increase != 0 && end_offset <= offset); + + location_p->line = line; + location_p->column = column; +} /* ecma_line_info_get */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + +/** + * Dumps line info data. + */ +void +ecma_line_info_dump (uint8_t *line_info_p) /**< dumps line info data */ +{ + bool block_last = false; + uint32_t block_line = 1; + uint32_t block_byte_code_offset = 0; + uint32_t value; + + value = ecma_line_info_decode_vlq (&line_info_p); + JERRY_DEBUG_MSG ("\nLine info size: %d bytes\n", (int) value); + + while (true) + { + value = ecma_line_info_decode_vlq (&line_info_p); + block_line = ecma_line_info_difference_update (block_line, value); + + JERRY_DEBUG_MSG ("\nNew block: line: %d", (int) block_line); + + if (*line_info_p == 0) + { + JERRY_DEBUG_MSG (" StreamLength: [last]\n"); + block_last = true; + } + else + { + uint8_t *size_p = line_info_p + *line_info_p + (ECMA_LINE_INFO_STREAM_SIZE_MIN + 1); + + value = ecma_line_info_decode_vlq (&size_p); + + JERRY_DEBUG_MSG (" StreamLength: %d ByteCodeSize: %d\n", + (int) (*line_info_p + ECMA_LINE_INFO_STREAM_SIZE_MIN), + (int) value); + } + + line_info_p++; + + uint32_t stream_line = block_line; + uint32_t stream_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + uint32_t stream_end_offset = block_byte_code_offset; + + while (true) + { + uint32_t stream_end_offset_increase = ecma_line_info_decode_small (&line_info_p); + + if (stream_end_offset_increase & ECMA_LINE_INFO_HAS_LINE) + { + value = ecma_line_info_decode_small (&line_info_p); + stream_line = ecma_line_info_difference_update (stream_line, value); + stream_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + } + + stream_end_offset_increase >>= 1; + + value = ecma_line_info_decode_small (&line_info_p); + stream_column = ecma_line_info_difference_update (stream_column, value); + + if (stream_end_offset_increase == 0) + { + JERRY_DEBUG_MSG (" ByteCodeEndOffset: [unterminated] Line: %d Column: %d\n", + (int) stream_line, + (int) stream_column); + break; + } + + stream_end_offset += stream_end_offset_increase; + + JERRY_DEBUG_MSG (" ByteCodeEndOffset: %d Line: %d Column: %d\n", + (int) stream_end_offset, + (int) stream_line, + (int) stream_column); + } + + if (block_last) + { + break; + } + + block_byte_code_offset += ecma_line_info_decode_vlq (&line_info_p); + } +} /* ecma_line_info_dump */ + +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +#endif /* JERRY_LINE_INFO */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.h new file mode 100644 index 00000000..2e1cbe0e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.h @@ -0,0 +1,114 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_LINE_INFO_H +#define ECMA_LINE_INFO_H + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalineinfo Line info + * @{ + */ + +#ifdef JERRY_LINE_INFO + +#include "ecma-globals.h" + +/** + * Increase the current value of line or column. + */ +#define ECMA_LINE_INFO_INCREASE 0x0 + +/** + * Decrease the current value of line or column. + */ +#define ECMA_LINE_INFO_DECREASE 0x1 + +/** + * Line update is present. + */ +#define ECMA_LINE_INFO_HAS_LINE 0x1 + +/** + * A default value for columns after a line update. + */ +#define ECMA_LINE_INFO_COLUMN_DEFAULT 127 + +/** + * Vlq encoding: flag which is set for all bytes except the last one. + */ +#define ECMA_LINE_INFO_VLQ_CONTINUE 0x80 + +/** + * Vlq encoding: mask to decode the number fragment. + */ +#define ECMA_LINE_INFO_VLQ_MASK 0x7f + +/** + * Vlq encoding: number of bits stored in a byte. + */ +#define ECMA_LINE_INFO_VLQ_SHIFT 7 + +/** + * Small encoding: a value which represents a two byte long number. + */ +#define ECMA_LINE_INFO_ENCODE_TWO_BYTE (UINT8_MAX - 1) + +/** + * Small encoding: minimum value of an encoded two byte long number. + */ +#define ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN (UINT8_MAX - 1) + +/** + * Small encoding: a value which represents a three byte long number. + */ +#define ECMA_LINE_INFO_ENCODE_VLQ UINT8_MAX + +/** + * Small encoding: minimum value of an encoded three byte long number. + */ +#define ECMA_LINE_INFO_ENCODE_VLQ_MIN (ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN + UINT8_MAX + 1) + +/** + * Maximum number of line/column entries stored in a stream. + */ +#define ECMA_LINE_INFO_STREAM_VALUE_COUNT_MAX 48 + +/** + * Minimum size of a stream (except the last one). + */ +#define ECMA_LINE_INFO_STREAM_SIZE_MIN ((2 * ECMA_LINE_INFO_STREAM_VALUE_COUNT_MAX) - 1) + +/* Helper functions for parser/js/js-parser-line-info-create.c. */ +uint32_t ecma_line_info_decode_vlq (uint8_t **buffer_p); +uint32_t ecma_line_info_difference_update (uint32_t current_value, uint32_t difference_value); + +/* General functions. */ +void ecma_line_info_free (uint8_t *line_info_p); +void ecma_line_info_get (uint8_t *line_info_p, uint32_t offset, jerry_frame_location_t *location_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE +void ecma_line_info_dump (uint8_t *line_info_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +#endif /* JERRY_LINE_INFO */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_LINE_INFO_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.cpp new file mode 100644 index 00000000..db086a51 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.cpp @@ -0,0 +1,741 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-literal-storage.h" + +#include "ecma-alloc.h" +#include "ecma-big-uint.h" +#include "ecma-bigint.h" +#include "ecma-helpers.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalitstorage Literal storage + * @{ + */ + +/** + * Free symbol list + */ +static void +ecma_free_symbol_list (jmem_cpointer_t symbol_list_cp) /**< symbol list */ +{ + while (symbol_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *symbol_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, symbol_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (symbol_list_p->values[i] != JMEM_CP_NULL) + { + ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, symbol_list_p->values[i]); + + JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (string_p)); + ecma_deref_ecma_string (string_p); + } + } + + jmem_cpointer_t next_item_cp = symbol_list_p->next_cp; + jmem_pools_free (symbol_list_p, sizeof (ecma_lit_storage_item_t)); + symbol_list_cp = next_item_cp; + } +} /* ecma_free_symbol_list */ + +/** + * Free string list + */ +static void +ecma_free_string_list (jmem_cpointer_t string_list_cp) /**< string list */ +{ + while (string_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *string_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, string_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (string_list_p->values[i] != JMEM_CP_NULL) + { + ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, string_list_p->values[i]); + + JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (string_p)); + ecma_destroy_ecma_string (string_p); + } + } + + jmem_cpointer_t next_item_cp = string_list_p->next_cp; + jmem_pools_free (string_list_p, sizeof (ecma_lit_storage_item_t)); + string_list_cp = next_item_cp; + } +} /* ecma_free_string_list */ + +/** + * Free number list + */ +static void +ecma_free_number_list (jmem_cpointer_t number_list_cp) /**< number list */ +{ + while (number_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *number_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, number_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (number_list_p->values[i] != JMEM_CP_NULL) + { + ecma_dealloc_number (JMEM_CP_GET_NON_NULL_POINTER (ecma_number_t, number_list_p->values[i])); + } + } + + jmem_cpointer_t next_item_cp = number_list_p->next_cp; + jmem_pools_free (number_list_p, sizeof (ecma_lit_storage_item_t)); + number_list_cp = next_item_cp; + } +} /* ecma_free_number_list */ + +#if JERRY_BUILTIN_BIGINT + +/** + * Free bigint list + */ +static void +ecma_free_bigint_list (jmem_cpointer_t bigint_list_cp) /**< bigint list */ +{ + while (bigint_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *bigint_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, bigint_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (bigint_list_p->values[i] != JMEM_CP_NULL) + { + ecma_extended_primitive_t *bigint_p = + JMEM_CP_GET_NON_NULL_POINTER (ecma_extended_primitive_t, bigint_list_p->values[i]); + JERRY_ASSERT (ECMA_EXTENDED_PRIMITIVE_IS_REF_EQUALS_TO_ONE (bigint_p)); + ecma_deref_bigint (bigint_p); + } + } + + jmem_cpointer_t next_item_cp = bigint_list_p->next_cp; + jmem_pools_free (bigint_list_p, sizeof (ecma_lit_storage_item_t)); + bigint_list_cp = next_item_cp; + } +} /* ecma_free_bigint_list */ + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Finalize literal storage + */ +void +ecma_finalize_lit_storage (void) +{ + ecma_free_symbol_list (JERRY_CONTEXT (symbol_list_first_cp)); + ecma_free_string_list (JERRY_CONTEXT (string_list_first_cp)); + ecma_free_number_list (JERRY_CONTEXT (number_list_first_cp)); +#if JERRY_BUILTIN_BIGINT + ecma_free_bigint_list (JERRY_CONTEXT (bigint_list_first_cp)); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* ecma_finalize_lit_storage */ + +/** + * Find or create a literal string. + * + * @return ecma_string_t compressed pointer + */ +ecma_value_t +ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string to be searched */ + lit_utf8_size_t size, /**< size of the string */ + bool is_ascii) /**< encode of the string */ +{ + ecma_string_t *string_p = + (is_ascii ? ecma_new_ecma_string_from_ascii (chars_p, size) : ecma_new_ecma_string_from_utf8 (chars_p, size)); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return ecma_make_string_value (string_p); + } + + jmem_cpointer_t string_list_cp = JERRY_CONTEXT (string_list_first_cp); + jmem_cpointer_t *empty_cpointer_p = NULL; + + while (string_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *string_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, string_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (string_list_p->values[i] == JMEM_CP_NULL) + { + if (empty_cpointer_p == NULL) + { + empty_cpointer_p = string_list_p->values + i; + } + } + else + { + ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, string_list_p->values[i]); + + if (ecma_compare_ecma_strings (string_p, value_p)) + { + /* Return with string if found in the list. */ + ecma_deref_ecma_string (string_p); + return ecma_make_string_value (value_p); + } + } + } + + string_list_cp = string_list_p->next_cp; + } + + ECMA_SET_STRING_AS_STATIC (string_p); + jmem_cpointer_t result; + JMEM_CP_SET_NON_NULL_POINTER (result, string_p); + + if (empty_cpointer_p != NULL) + { + *empty_cpointer_p = result; + return ecma_make_string_value (string_p); + } + + ecma_lit_storage_item_t *new_item_p; + new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); + + new_item_p->values[0] = result; + for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + new_item_p->values[i] = JMEM_CP_NULL; + } + + new_item_p->next_cp = JERRY_CONTEXT (string_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (string_list_first_cp), new_item_p); + + return ecma_make_string_value (string_p); +} /* ecma_find_or_create_literal_string */ + +/** + * Find or create a literal number. + * + * @return ecma value + */ +ecma_value_t +ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be searched */ +{ + ecma_value_t num = ecma_make_number_value (number_arg); + + if (ecma_is_value_integer_number (num)) + { + return num; + } + + JERRY_ASSERT (ecma_is_value_float_number (num)); + + jmem_cpointer_t number_list_cp = JERRY_CONTEXT (number_list_first_cp); + jmem_cpointer_t *empty_cpointer_p = NULL; + + while (number_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *number_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, number_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (number_list_p->values[i] == JMEM_CP_NULL) + { + if (empty_cpointer_p == NULL) + { + empty_cpointer_p = number_list_p->values + i; + } + } + else + { + ecma_number_t *number_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_number_t, number_list_p->values[i]); + + if (*number_p == number_arg) + { + ecma_free_value (num); + return ecma_make_float_value (number_p); + } + } + } + + number_list_cp = number_list_p->next_cp; + } + + jmem_cpointer_t result; + JMEM_CP_SET_NON_NULL_POINTER (result, ecma_get_pointer_from_float_value (num)); + + if (empty_cpointer_p != NULL) + { + *empty_cpointer_p = result; + return num; + } + + ecma_lit_storage_item_t *new_item_p; + new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); + + new_item_p->values[0] = result; + for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + new_item_p->values[i] = JMEM_CP_NULL; + } + + new_item_p->next_cp = JERRY_CONTEXT (number_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (number_list_first_cp), new_item_p); + + return num; +} /* ecma_find_or_create_literal_number */ + +#if JERRY_BUILTIN_BIGINT + +/** + * Find or create a literal BigInt. + * + * @return BigInt value + */ +ecma_value_t +ecma_find_or_create_literal_bigint (ecma_value_t bigint) /**< bigint to be searched */ +{ + JERRY_ASSERT (ecma_is_value_bigint (bigint)); + + if (bigint == ECMA_BIGINT_ZERO) + { + return bigint; + } + + jmem_cpointer_t bigint_list_cp = JERRY_CONTEXT (bigint_list_first_cp); + jmem_cpointer_t *empty_cpointer_p = NULL; + + while (bigint_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *bigint_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, bigint_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (bigint_list_p->values[i] == JMEM_CP_NULL) + { + if (empty_cpointer_p == NULL) + { + empty_cpointer_p = bigint_list_p->values + i; + } + } + else + { + ecma_extended_primitive_t *other_bigint_p = + JMEM_CP_GET_NON_NULL_POINTER (ecma_extended_primitive_t, bigint_list_p->values[i]); + ecma_value_t other_bigint = ecma_make_extended_primitive_value (other_bigint_p, ECMA_TYPE_BIGINT); + + if (ecma_bigint_is_equal_to_bigint (bigint, other_bigint)) + { + ecma_free_value (bigint); + return other_bigint; + } + } + } + + bigint_list_cp = bigint_list_p->next_cp; + } + + jmem_cpointer_t result; + JMEM_CP_SET_NON_NULL_POINTER (result, ecma_get_extended_primitive_from_value (bigint)); + + if (empty_cpointer_p != NULL) + { + *empty_cpointer_p = result; + return bigint; + } + + ecma_lit_storage_item_t *new_item_p; + new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); + + new_item_p->values[0] = result; + for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + new_item_p->values[i] = JMEM_CP_NULL; + } + + new_item_p->next_cp = JERRY_CONTEXT (bigint_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (bigint_list_first_cp), new_item_p); + + return bigint; +} /* ecma_find_or_create_literal_bigint */ + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Log2 of snapshot literal alignment. + */ +#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG 1 + +/** + * Snapshot literal alignment. + */ +#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT (1u << JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG) + +/** + * Literal offset shift. + */ +#define JERRY_SNAPSHOT_LITERAL_SHIFT (ECMA_VALUE_SHIFT + 2) + +/** + * Literal value is number. + */ +#define JERRY_SNAPSHOT_LITERAL_IS_NUMBER (1u << ECMA_VALUE_SHIFT) + +#if JERRY_BUILTIN_BIGINT +/** + * Literal value is BigInt. + */ +#define JERRY_SNAPSHOT_LITERAL_IS_BIGINT (2u << ECMA_VALUE_SHIFT) +#endif /* JERRY_BUILTIN_BIGINT */ + +#if JERRY_SNAPSHOT_SAVE + +/** + * Append the value at the end of the appropriate list if it is not present there. + */ +void +ecma_save_literals_append_value (ecma_value_t value, /**< value to be appended */ + ecma_collection_t *lit_pool_p) /**< list of known values */ +{ + /* Unlike direct numbers, direct strings are converted to character literals. */ + if (!ecma_is_value_string (value) +#if JERRY_BUILTIN_BIGINT + && (!ecma_is_value_bigint (value) || value == ECMA_BIGINT_ZERO) +#endif /* JERRY_BUILTIN_BIGINT */ + && !ecma_is_value_float_number (value)) + { + return; + } + + ecma_value_t *buffer_p = lit_pool_p->buffer_p; + + for (uint32_t i = 0; i < lit_pool_p->item_count; i++) + { + /* Strings / numbers are direct strings or stored in the literal storage. + * Therefore direct comparison is enough to find the same strings / numbers. */ + if (buffer_p[i] == value) + { + return; + } + } + + ecma_collection_push_back (lit_pool_p, value); +} /* ecma_save_literals_append_value */ + +/** + * Add names from a byte-code data to a list. + */ +void +ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_p, /**< byte-code data */ + ecma_collection_t *lit_pool_p) /**< list of known values */ +{ + ecma_value_t *literal_p; + uint32_t argument_end; + uint32_t register_end; + uint32_t const_literal_end; + uint32_t literal_end; + + JERRY_ASSERT (CBC_IS_FUNCTION (compiled_code_p->status_flags)); + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p; + uint8_t *byte_p = (uint8_t *) compiled_code_p; + + literal_p = (ecma_value_t *) (byte_p + sizeof (cbc_uint16_arguments_t)); + register_end = args_p->register_end; + const_literal_end = args_p->const_literal_end - register_end; + literal_end = args_p->literal_end - register_end; + argument_end = args_p->argument_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p; + uint8_t *byte_p = (uint8_t *) compiled_code_p; + + literal_p = (ecma_value_t *) (byte_p + sizeof (cbc_uint8_arguments_t)); + register_end = args_p->register_end; + const_literal_end = args_p->const_literal_end - register_end; + literal_end = args_p->literal_end - register_end; + argument_end = args_p->argument_end; + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + for (uint32_t i = 0; i < argument_end; i++) + { + ecma_save_literals_append_value (literal_p[i], lit_pool_p); + } + } + + for (uint32_t i = 0; i < const_literal_end; i++) + { + ecma_save_literals_append_value (literal_p[i], lit_pool_p); + } + + for (uint32_t i = const_literal_end; i < literal_end; i++) + { + ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, literal_p[i]); + + if (CBC_IS_FUNCTION (bytecode_p->status_flags) && bytecode_p != compiled_code_p) + { + ecma_save_literals_add_compiled_code (bytecode_p, lit_pool_p); + } + } + + uint8_t *byte_p = ((uint8_t *) compiled_code_p) + (((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG); + literal_p = ecma_snapshot_resolve_serializable_values ((ecma_compiled_code_t *) compiled_code_p, byte_p); + + while (literal_p < (ecma_value_t *) byte_p) + { + ecma_save_literals_append_value (*literal_p, lit_pool_p); + literal_p++; + } +} /* ecma_save_literals_add_compiled_code */ + +/** + * Save literals to specified snapshot buffer. + * + * Note: + * Frees 'lit_pool_p' regardless of success. + * + * @return true - if save was performed successfully (i.e. buffer size is sufficient), + * false - otherwise + */ +bool +ecma_save_literals_for_snapshot (ecma_collection_t *lit_pool_p, /**< list of known values */ + uint32_t *buffer_p, /**< [out] output snapshot buffer */ + size_t buffer_size, /**< size of the buffer */ + size_t *in_out_buffer_offset_p, /**< [in,out] write position in the buffer */ + lit_mem_to_snapshot_id_map_entry_t **out_map_p, /**< [out] map from literal identifiers + * to the literal offsets + * in snapshot */ + uint32_t *out_map_len_p) /**< [out] number of literals */ +{ + if (lit_pool_p->item_count == 0) + { + *out_map_p = NULL; + *out_map_len_p = 0; + } + + uint32_t lit_table_size = 0; + size_t max_lit_table_size = buffer_size - *in_out_buffer_offset_p; + + if (max_lit_table_size > (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT)) + { + max_lit_table_size = (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT); + } + + ecma_value_t *lit_buffer_p = lit_pool_p->buffer_p; + + /* Compute the size of the literal pool. */ + for (uint32_t i = 0; i < lit_pool_p->item_count; i++) + { + if (ecma_is_value_float_number (lit_buffer_p[i])) + { + lit_table_size += (uint32_t) sizeof (ecma_number_t); + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (lit_buffer_p[i])) + { + ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (lit_buffer_p[i]); + + lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint32_t) + ECMA_BIGINT_GET_SIZE (bigint_p), + JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + ecma_string_t *string_p = ecma_get_string_from_value (lit_buffer_p[i]); + + lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint16_t) + ecma_string_get_size (string_p), + JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } + + /* Check whether enough space is available and the maximum size is not reached. */ + if (lit_table_size > max_lit_table_size) + { + ecma_collection_destroy (lit_pool_p); + return false; + } + } + + lit_mem_to_snapshot_id_map_entry_t *map_p; + uint32_t total_count = lit_pool_p->item_count; + + map_p = jmem_heap_alloc_block (total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t)); + + /* Set return values (no error is possible from here). */ + JERRY_ASSERT ((*in_out_buffer_offset_p % sizeof (uint32_t)) == 0); + + uint8_t *destination_p = (uint8_t *) (buffer_p + (*in_out_buffer_offset_p / sizeof (uint32_t))); + uint32_t literal_offset = 0; + + *in_out_buffer_offset_p += lit_table_size; + *out_map_p = map_p; + *out_map_len_p = total_count; + + lit_buffer_p = lit_pool_p->buffer_p; + + /* Generate literal pool data. */ + for (uint32_t i = 0; i < lit_pool_p->item_count; i++) + { + map_p->literal_id = lit_buffer_p[i]; + map_p->literal_offset = (literal_offset << JERRY_SNAPSHOT_LITERAL_SHIFT) | ECMA_TYPE_SNAPSHOT_OFFSET; + + lit_utf8_size_t length; + + if (ecma_is_value_float_number (lit_buffer_p[i])) + { + map_p->literal_offset |= JERRY_SNAPSHOT_LITERAL_IS_NUMBER; + + ecma_number_t num = ecma_get_float_from_value (lit_buffer_p[i]); + memcpy (destination_p, &num, sizeof (ecma_number_t)); + + length = JERRY_ALIGNUP (sizeof (ecma_number_t), JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (lit_buffer_p[i])) + { + map_p->literal_offset |= JERRY_SNAPSHOT_LITERAL_IS_BIGINT; + + ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (lit_buffer_p[i]); + uint32_t size = ECMA_BIGINT_GET_SIZE (bigint_p); + + memcpy (destination_p, &bigint_p->u.bigint_sign_and_size, sizeof (uint32_t)); + memcpy (destination_p + sizeof (uint32_t), ECMA_BIGINT_GET_DIGITS (bigint_p, 0), size); + + length = JERRY_ALIGNUP (sizeof (uint32_t) + size, JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + ecma_string_t *string_p = ecma_get_string_from_value (lit_buffer_p[i]); + length = ecma_string_get_size (string_p); + + *(uint16_t *) destination_p = (uint16_t) length; + + ecma_string_to_cesu8_bytes (string_p, destination_p + sizeof (uint16_t), length); + + length = JERRY_ALIGNUP (sizeof (uint16_t) + length, JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } + + JERRY_ASSERT ((length % sizeof (uint16_t)) == 0); + destination_p += length; + literal_offset += length; + + map_p++; + } + + ecma_collection_destroy (lit_pool_p); + return true; +} /* ecma_save_literals_for_snapshot */ + +#endif /* JERRY_SNAPSHOT_SAVE */ + +#if JERRY_SNAPSHOT_EXEC || JERRY_SNAPSHOT_SAVE + +/** + * Get the compressed pointer of a given literal. + * + * @return literal compressed pointer + */ +ecma_value_t +ecma_snapshot_get_literal (const uint8_t *literal_base_p, /**< literal start */ + ecma_value_t literal_value) /**< string / number offset */ +{ + JERRY_ASSERT ((literal_value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET); + + const uint8_t *literal_p = literal_base_p + (literal_value >> JERRY_SNAPSHOT_LITERAL_SHIFT); + + if (literal_value & JERRY_SNAPSHOT_LITERAL_IS_NUMBER) + { + ecma_number_t num; + memcpy (&num, literal_p, sizeof (ecma_number_t)); + return ecma_find_or_create_literal_number (num); + } + +#if JERRY_BUILTIN_BIGINT + if (literal_value & JERRY_SNAPSHOT_LITERAL_IS_BIGINT) + { + uint32_t bigint_sign_and_size = *(uint32_t *) literal_p; + uint32_t size = bigint_sign_and_size & ~(uint32_t) (sizeof (ecma_bigint_digit_t) - 1); + + ecma_extended_primitive_t *bigint_p = ecma_bigint_create (size); + + if (bigint_p == NULL) + { + jerry_fatal (JERRY_FATAL_OUT_OF_MEMORY); + } + + /* Only the sign bit can differ. */ + JERRY_ASSERT (bigint_p->u.bigint_sign_and_size == (bigint_sign_and_size & ~(uint32_t) ECMA_BIGINT_SIGN)); + + bigint_p->u.bigint_sign_and_size = bigint_sign_and_size; + memcpy (ECMA_BIGINT_GET_DIGITS (bigint_p, 0), literal_p + sizeof (uint32_t), size); + return ecma_find_or_create_literal_bigint (ecma_make_extended_primitive_value (bigint_p, ECMA_TYPE_BIGINT)); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + uint16_t length = *(const uint16_t *) literal_p; + + return ecma_find_or_create_literal_string (literal_p + sizeof (uint16_t), length, false); +} /* ecma_snapshot_get_literal */ + +/** + * Compute the start of the serializable ecma-values of the bytecode + * Related values: + * - function argument names, if CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED is present + * - function name, if CBC_CODE_FLAGS_CLASS_CONSTRUCTOR is not present and es.next profile is enabled + * + * @return pointer to the beginning of the serializable ecma-values + */ +ecma_value_t * +ecma_snapshot_resolve_serializable_values (const ecma_compiled_code_t *compiled_code_p, /**< compiled code */ + uint8_t *bytecode_end_p) /**< end of the bytecode */ +{ + ecma_value_t *base_p = (ecma_value_t *) bytecode_end_p; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + uint32_t argument_end; + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + argument_end = ((cbc_uint16_arguments_t *) compiled_code_p)->argument_end; + } + else + { + argument_end = ((cbc_uint8_arguments_t *) compiled_code_p)->argument_end; + } + + base_p -= argument_end; + } + + /* function name */ + if (CBC_FUNCTION_GET_TYPE (compiled_code_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR) + { + base_p--; + } + + return base_p; +} /* ecma_snapshot_resolve_serializable_values */ +#endif /* JERRY_SNAPSHOT_EXEC || JERRY_SNAPSHOT_SAVE */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.h new file mode 100644 index 00000000..6850a868 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.h @@ -0,0 +1,72 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_LIT_STORAGE_H +#define ECMA_LIT_STORAGE_H + +#include "ecma-globals.h" + +#include "jmem.h" +#include "lit-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalitstorage Literal storage + * @{ + */ + +#if JERRY_SNAPSHOT_SAVE +/** + * Snapshot literal - offset map + */ +typedef struct +{ + ecma_value_t literal_id; /**< literal id */ + ecma_value_t literal_offset; /**< literal offset */ +} lit_mem_to_snapshot_id_map_entry_t; +#endif /* JERRY_SNAPSHOT_SAVE */ + +void ecma_finalize_lit_storage (void); + +ecma_value_t ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, lit_utf8_size_t size, bool is_ascii); +ecma_value_t ecma_find_or_create_literal_number (ecma_number_t number_arg); +#if JERRY_BUILTIN_BIGINT +ecma_value_t ecma_find_or_create_literal_bigint (ecma_value_t bigint); +#endif /* JERRY_BUILTIN_BIGINT */ + +#if JERRY_SNAPSHOT_SAVE +void ecma_save_literals_append_value (ecma_value_t value, ecma_collection_t *lit_pool_p); +void ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_p, ecma_collection_t *lit_pool_p); +bool ecma_save_literals_for_snapshot (ecma_collection_t *lit_pool_p, + uint32_t *buffer_p, + size_t buffer_size, + size_t *in_out_buffer_offset_p, + lit_mem_to_snapshot_id_map_entry_t **out_map_p, + uint32_t *out_map_len_p); +#endif /* JERRY_SNAPSHOT_SAVE */ + +#if JERRY_SNAPSHOT_EXEC || JERRY_SNAPSHOT_SAVE +ecma_value_t ecma_snapshot_get_literal (const uint8_t *literal_base_p, ecma_value_t literal_value); +ecma_value_t *ecma_snapshot_resolve_serializable_values (const ecma_compiled_code_t *compiled_code_p, + uint8_t *byte_code_end_p); +#endif /* JERRY_SNAPSHOT_EXEC || JERRY_SNAPSHOT_SAVE */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_LIT_STORAGE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.cpp new file mode 100644 index 00000000..62ac2ae7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.cpp @@ -0,0 +1,1444 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-module.h" + +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "lit-char-helpers.h" +#include "vm.h" + +#if JERRY_MODULE_SYSTEM + +/** + * Type of the result returned by ecma_module_resolve_export. + */ +typedef enum +{ + ECMA_MODULE_RESOLVE_NOT_FOUND, /**< reference not found */ + ECMA_MODULE_RESOLVE_CIRCULAR, /**< only circular references are found */ + ECMA_MODULE_RESOLVE_ERROR, /**< module in error state is encountered */ + ECMA_MODULE_RESOLVE_AMBIGUOUS, /**< reference is ambiguous */ + ECMA_MODULE_RESOLVE_FOUND, /**< reference found */ +} ecma_module_resolve_result_type_t; + +/** + * A record that stores the result of ecma_module_resolve_export. + */ +typedef struct +{ + ecma_module_resolve_result_type_t result_type; /**< result type */ + ecma_value_t result; /**< result value */ +} ecma_module_resolve_result_t; + +/** + * This flag is set in the result if the value is a namespace object. + */ +#define ECMA_MODULE_NAMESPACE_RESULT_FLAG 0x2 + +/** + * Initialize context variables for the root module. + * + * @return new module + */ +ecma_module_t * +ecma_module_create (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (module_current_p) == NULL); + + ecma_object_t *obj_p = ecma_create_object (NULL, sizeof (ecma_module_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_MODULE; + ext_object_p->u.cls.u1.module_state = JERRY_MODULE_STATE_UNLINKED; + ext_object_p->u.cls.u2.module_flags = 0; + + ecma_module_t *module_p = (ecma_module_t *) obj_p; + + module_p->scope_p = NULL; + module_p->namespace_object_p = NULL; + module_p->imports_p = NULL; + module_p->local_exports_p = NULL; + module_p->indirect_exports_p = NULL; + module_p->star_exports_p = NULL; + module_p->u.compiled_code_p = NULL; + + return module_p; +} /* ecma_module_create */ + +/** + * Cleanup context variables for the root module. + */ +void +ecma_module_cleanup_context (void) +{ + ecma_deref_object ((ecma_object_t *) JERRY_CONTEXT (module_current_p)); +#ifndef JERRY_NDEBUG + JERRY_CONTEXT (module_current_p) = NULL; +#endif /* JERRY_NDEBUG */ +} /* ecma_module_cleanup_context */ + +/** + * Sets module state to error. + */ +static void +ecma_module_set_error_state (ecma_module_t *module_p) /**< module */ +{ + module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_ERROR; + + if (JERRY_CONTEXT (module_state_changed_callback_p) != NULL && !jcontext_has_pending_abort ()) + { + jerry_value_t exception = jcontext_take_exception (); + + JERRY_CONTEXT (module_state_changed_callback_p) + (JERRY_MODULE_STATE_ERROR, + ecma_make_object_value (&module_p->header.object), + exception, + JERRY_CONTEXT (module_state_changed_callback_user_p)); + jcontext_raise_exception (exception); + } +} /* ecma_module_set_error_state */ + +/** + * Gets the internal module pointer of a module + * + * @return module pointer + */ +static inline ecma_module_t * +ecma_module_get_from_object (ecma_value_t module_val) /**< module */ +{ + JERRY_ASSERT (ecma_is_value_object (module_val)); + + ecma_object_t *object_p = ecma_get_object_from_value (module_val); + + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE)); + + return (ecma_module_t *) object_p; +} /* ecma_module_get_from_object */ + +/** + * Cleans up a list of module names. + */ +void +ecma_module_release_module_names (ecma_module_names_t *module_name_p) /**< first module name */ +{ + while (module_name_p != NULL) + { + ecma_module_names_t *next_p = module_name_p->next_p; + + ecma_deref_ecma_string (module_name_p->imex_name_p); + ecma_deref_ecma_string (module_name_p->local_name_p); + jmem_heap_free_block (module_name_p, sizeof (ecma_module_names_t)); + + module_name_p = next_p; + } +} /* ecma_module_release_module_names */ + +/** + * Cleans up a list of module nodes. + */ +static void +ecma_module_release_module_nodes (ecma_module_node_t *module_node_p, /**< first module node */ + bool is_import) /**< free path variable */ +{ + while (module_node_p != NULL) + { + ecma_module_node_t *next_p = module_node_p->next_p; + + ecma_module_release_module_names (module_node_p->module_names_p); + + if (is_import && ecma_is_value_string (module_node_p->u.path_or_module)) + { + ecma_deref_ecma_string (ecma_get_string_from_value (module_node_p->u.path_or_module)); + } + + jmem_heap_free_block (module_node_p, sizeof (ecma_module_node_t)); + module_node_p = next_p; + } +} /* ecma_module_release_module_nodes */ + +/** + * Creates a new resolve set item from a {module, export_name} pair. + * + * @return new resolve set item + */ +static ecma_module_resolve_set_t * +ecma_module_resolve_set_create (ecma_module_t *const module_p, /**< module */ + ecma_string_t *const export_name_p) /**< export name */ +{ + ecma_module_resolve_set_t *new_p; + new_p = (ecma_module_resolve_set_t *) jmem_heap_alloc_block (sizeof (ecma_module_resolve_set_t)); + + new_p->next_p = NULL; + new_p->module_p = module_p; + new_p->name_p = export_name_p; + + return new_p; +} /* ecma_module_resolve_set_create */ + +/** + * Appends a {module, export_name} record into a resolve set. + * + * @return true - if the record is appended successfully + * false - otherwise + */ +static bool +ecma_module_resolve_set_append (ecma_module_resolve_set_t *set_p, /**< resolve set */ + ecma_module_t *const module_p, /**< module */ + ecma_string_t *const export_name_p) /**< export name */ +{ + JERRY_ASSERT (set_p != NULL); + ecma_module_resolve_set_t *current_p = set_p; + + while (true) + { + if (current_p->module_p == module_p && ecma_compare_ecma_strings (current_p->name_p, export_name_p)) + { + return false; + } + + ecma_module_resolve_set_t *next_p = current_p->next_p; + + if (next_p == NULL) + { + current_p->next_p = ecma_module_resolve_set_create (module_p, export_name_p); + return true; + } + + current_p = next_p; + } +} /* ecma_module_resolve_set_append */ + +/** + * Cleans up contents of a resolve set. + */ +static void +ecma_module_resolve_set_cleanup (ecma_module_resolve_set_t *set_p) /**< resolve set */ +{ + while (set_p != NULL) + { + ecma_module_resolve_set_t *next_p = set_p->next_p; + jmem_heap_free_block (set_p, sizeof (ecma_module_resolve_set_t)); + set_p = next_p; + } +} /* ecma_module_resolve_set_cleanup */ + +/** + * Throws the appropriate error based on the resolve result + * + * @return error value + */ +static ecma_value_t +ecma_module_resolve_throw (ecma_module_resolve_result_t *resolve_result_p, /**< resolve result */ + ecma_string_t *name_p) /**< referenced value */ +{ +#if JERRY_ERROR_MESSAGES + ecma_value_t name_val = ecma_make_string_value (name_p); + const char *msg_p; + + switch (resolve_result_p->result_type) + { + case ECMA_MODULE_RESOLVE_CIRCULAR: + { + msg_p = "Detected cycle while resolving name '%' (module)"; + break; + } + case ECMA_MODULE_RESOLVE_AMBIGUOUS: + { + msg_p = "Name '%' is ambiguous (module)"; + break; + } + default: + { + JERRY_ASSERT (resolve_result_p->result_type == ECMA_MODULE_RESOLVE_NOT_FOUND + || resolve_result_p->result_type == ECMA_MODULE_RESOLVE_ERROR); + + msg_p = "Name '%' is not found (module)"; + break; + } + } + + return ecma_raise_standard_error_with_format (JERRY_ERROR_SYNTAX, msg_p, name_val); +#else /* JERRY_ERROR_MESSAGES */ + JERRY_UNUSED (resolve_result_p); + JERRY_UNUSED (name_p); + + return ecma_raise_syntax_error (ECMA_ERR_EMPTY); +#endif /* !JERRY_ERROR_MESSAGES */ +} /* ecma_module_resolve_throw */ + +/** + * Updates the resolve record with the passed type/value pair + * + * @return true - if the record is updated successfully + * false - otherwise + */ +static bool +ecma_module_resolve_update (ecma_module_resolve_result_t *resolve_result_p, /**< [in,out] resolve result */ + ecma_value_t result) /**< result value */ +{ + JERRY_ASSERT (resolve_result_p->result_type != ECMA_MODULE_RESOLVE_AMBIGUOUS + && resolve_result_p->result_type != ECMA_MODULE_RESOLVE_ERROR); + + if (resolve_result_p->result_type == ECMA_MODULE_RESOLVE_NOT_FOUND + || resolve_result_p->result_type == ECMA_MODULE_RESOLVE_CIRCULAR) + { + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_FOUND; + resolve_result_p->result = result; + return true; + } + + JERRY_ASSERT (resolve_result_p->result_type == ECMA_MODULE_RESOLVE_FOUND); + + if (resolve_result_p->result == result) + { + return true; + } + + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_AMBIGUOUS; + return false; +} /* ecma_module_resolve_update */ + +/** + * Finds the reference in the imported bindings. + * + * Note: + * This function is needed because the namespace object is created before the imports are connected + * + * @return true - if the record is updated successfully + * false - otherwise + */ +static bool +ecma_module_resolve_import (ecma_module_resolve_result_t *resolve_result_p, /**< [in,out] resolve result */ + ecma_module_resolve_set_t *resolve_set_p, /**< resolve set */ + ecma_module_t *module_p, /**< base module */ + ecma_string_t *local_name_p) /**< local name */ +{ + ecma_module_node_t *import_node_p = module_p->imports_p; + + while (true) + { + JERRY_ASSERT (import_node_p != NULL); + + for (ecma_module_names_t *import_names_p = import_node_p->module_names_p; import_names_p != NULL; + import_names_p = import_names_p->next_p) + { + if (ecma_compare_ecma_strings (local_name_p, import_names_p->local_name_p)) + { + ecma_module_t *imported_module_p = ecma_module_get_from_object (import_node_p->u.path_or_module); + + if (ecma_compare_ecma_string_to_magic_id (import_names_p->imex_name_p, LIT_MAGIC_STRING_ASTERIX_CHAR)) + { + /* Namespace import. */ + ecma_value_t ns = ecma_make_object_value (imported_module_p->namespace_object_p); + + JERRY_ASSERT (ns & ECMA_MODULE_NAMESPACE_RESULT_FLAG); + + return ecma_module_resolve_update (resolve_result_p, ns); + } + + if (!ecma_module_resolve_set_append (resolve_set_p, imported_module_p, import_names_p->imex_name_p) + && resolve_result_p->result_type == ECMA_MODULE_RESOLVE_NOT_FOUND) + { + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_CIRCULAR; + } + + return true; + } + } + + import_node_p = import_node_p->next_p; + } +} /* ecma_module_resolve_import */ + +/** + * Resolves which module satisfies an export based from a specific module in the import tree. + * + * Note: See ES11 15.2.1.17.3 + */ +static void +ecma_module_resolve_export (ecma_module_t *const module_p, /**< base module */ + ecma_string_t *const export_name_p, /**< export name */ + ecma_module_resolve_result_t *resolve_result_p) /**< [out] resolve result */ +{ + ecma_module_resolve_set_t *resolve_set_p = ecma_module_resolve_set_create (module_p, export_name_p); + ecma_module_resolve_set_t *current_set_p = resolve_set_p; + ecma_module_node_t *star_export_p; + + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_NOT_FOUND; + resolve_result_p->result = ECMA_VALUE_UNDEFINED; + + do + { + ecma_module_t *current_module_p = current_set_p->module_p; + ecma_string_t *current_export_name_p = current_set_p->name_p; + + if (current_module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_ERROR) + { + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_ERROR; + goto exit; + } + + if (current_module_p->header.u.cls.u2.module_flags & ECMA_MODULE_HAS_NAMESPACE) + { + ecma_property_t *property_p = + ecma_find_named_property (current_module_p->namespace_object_p, current_export_name_p); + + if (property_p != NULL) + { + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + JERRY_ASSERT ( + (!(*property_p & ECMA_PROPERTY_FLAG_DATA) && !(property_value_p->value & ECMA_MODULE_NAMESPACE_RESULT_FLAG)) + || ((*property_p & ECMA_PROPERTY_FLAG_DATA) && ecma_is_value_object (property_value_p->value) + && ecma_object_class_is (ecma_get_object_from_value (property_value_p->value), + ECMA_OBJECT_CLASS_MODULE_NAMESPACE))); + + if (!ecma_module_resolve_update (resolve_result_p, property_value_p->value)) + { + goto exit; + } + + goto next_iteration; + } + } + else + { + /* 6. */ + ecma_module_names_t *export_names_p = current_module_p->local_exports_p; + + while (export_names_p != NULL) + { + if (ecma_compare_ecma_strings (current_export_name_p, export_names_p->imex_name_p)) + { + ecma_property_t *property_p = + ecma_find_named_property (current_module_p->scope_p, export_names_p->local_name_p); + + if (property_p != NULL) + { + ecma_value_t reference = ecma_property_to_reference (property_p); + + JERRY_ASSERT (!(reference & ECMA_MODULE_NAMESPACE_RESULT_FLAG)); + + if (!ecma_module_resolve_update (resolve_result_p, reference)) + { + goto exit; + } + } + else if (!ecma_module_resolve_import (resolve_result_p, + resolve_set_p, + current_module_p, + export_names_p->local_name_p)) + { + goto exit; + } + + goto next_iteration; + } + + export_names_p = export_names_p->next_p; + } + + /* 7. */ + ecma_module_node_t *indirect_export_p = current_module_p->indirect_exports_p; + + while (indirect_export_p != NULL) + { + export_names_p = indirect_export_p->module_names_p; + + while (export_names_p != NULL) + { + if (ecma_compare_ecma_strings (current_export_name_p, export_names_p->imex_name_p)) + { + ecma_module_t *target_module_p = ecma_module_get_from_object (*indirect_export_p->u.module_object_p); + + if (ecma_compare_ecma_string_to_magic_id (export_names_p->local_name_p, LIT_MAGIC_STRING_ASTERIX_CHAR)) + { + /* Namespace export. */ + ecma_value_t ns = ecma_make_object_value (target_module_p->namespace_object_p); + + JERRY_ASSERT (ns & ECMA_MODULE_NAMESPACE_RESULT_FLAG); + + if (!ecma_module_resolve_update (resolve_result_p, ns)) + { + goto exit; + } + } + else if (!ecma_module_resolve_set_append (resolve_set_p, target_module_p, export_names_p->local_name_p) + && resolve_result_p->result_type == ECMA_MODULE_RESOLVE_NOT_FOUND) + { + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_CIRCULAR; + } + + goto next_iteration; + } + + export_names_p = export_names_p->next_p; + } + + indirect_export_p = indirect_export_p->next_p; + } + } + + /* 8. */ + if (ecma_compare_ecma_string_to_magic_id (current_export_name_p, LIT_MAGIC_STRING_DEFAULT)) + { + goto exit; + } + + /* 10. */ + star_export_p = current_module_p->star_exports_p; + while (star_export_p != NULL) + { + JERRY_ASSERT (star_export_p->module_names_p == NULL); + + ecma_module_t *target_module_p = ecma_module_get_from_object (*star_export_p->u.module_object_p); + + if (!ecma_module_resolve_set_append (resolve_set_p, target_module_p, current_export_name_p) + && resolve_result_p->result_type == ECMA_MODULE_RESOLVE_NOT_FOUND) + { + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_CIRCULAR; + } + + star_export_p = star_export_p->next_p; + } + +next_iteration: + current_set_p = current_set_p->next_p; + } while (current_set_p != NULL); + +exit: + ecma_module_resolve_set_cleanup (resolve_set_p); +} /* ecma_module_resolve_export */ + +/** + * Evaluates an EcmaScript module. + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +ecma_module_evaluate (ecma_module_t *module_p) /**< module */ +{ + if (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_ERROR) + { + return ecma_raise_range_error (ECMA_ERR_MODULE_IS_IN_ERROR_STATE); + } + + if (module_p->header.u.cls.u1.module_state >= JERRY_MODULE_STATE_EVALUATING) + { + return ECMA_VALUE_EMPTY; + } + + JERRY_ASSERT (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKED); + JERRY_ASSERT (module_p->scope_p != NULL); + + module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_EVALUATING; + + ecma_value_t ret_value; + + if (module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) + { + ret_value = ECMA_VALUE_UNDEFINED; + + if (module_p->u.callback) + { + ret_value = module_p->u.callback (ecma_make_object_value (&module_p->header.object)); + + if (JERRY_UNLIKELY (ecma_is_value_exception (ret_value))) + { + ecma_throw_exception (ret_value); + ret_value = ECMA_VALUE_ERROR; + } + } + } + else + { + ret_value = vm_run_module (module_p); + } + + if (JERRY_LIKELY (!ECMA_IS_VALUE_ERROR (ret_value))) + { + module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_EVALUATED; + + if (JERRY_CONTEXT (module_state_changed_callback_p) != NULL) + { + JERRY_CONTEXT (module_state_changed_callback_p) + (JERRY_MODULE_STATE_EVALUATED, + ecma_make_object_value (&module_p->header.object), + ret_value, + JERRY_CONTEXT (module_state_changed_callback_user_p)); + } + } + else + { + ecma_module_set_error_state (module_p); + } + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)) + { + ecma_bytecode_deref (module_p->u.compiled_code_p); + } + + module_p->u.compiled_code_p = NULL; + return ret_value; +} /* ecma_module_evaluate */ + +/** + * Resolves an export and adds it to the modules namespace object, if the export name is not yet handled. + * Note: See 15.2.1.16.2 and 15.2.1.18 + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_EMPTY - otherwise + */ +static ecma_value_t +ecma_module_namespace_object_add_export_if_needed (ecma_collection_t *properties_p, /**< collection of properties */ + ecma_module_t *module_p, /**< module */ + ecma_string_t *export_name_p, /**< export name */ + bool allow_default) /**< allow default export */ +{ + if (!allow_default) + { + if (ecma_compare_ecma_string_to_magic_id (export_name_p, LIT_MAGIC_STRING_DEFAULT)) + { + return ECMA_VALUE_EMPTY; + } + + /* No need to check duplications before star exports are processed. */ + ecma_value_t *buffer_p = properties_p->buffer_p; + ecma_value_t *buffer_end_p = properties_p->buffer_p + properties_p->item_count; + + while (buffer_p < buffer_end_p) + { + if (ecma_compare_ecma_strings (ecma_get_string_from_value (*buffer_p), export_name_p)) + { + return ECMA_VALUE_EMPTY; + } + + buffer_p += 2; + } + } + + ecma_module_resolve_result_t resolve_result; + ecma_module_resolve_export (module_p, export_name_p, &resolve_result); + + if (resolve_result.result_type == ECMA_MODULE_RESOLVE_AMBIGUOUS) + { + return ECMA_VALUE_EMPTY; + } + + if (resolve_result.result_type != ECMA_MODULE_RESOLVE_FOUND) + { + return ecma_module_resolve_throw (&resolve_result, export_name_p); + } + + ecma_collection_push_back (properties_p, ecma_make_string_value (export_name_p)); + ecma_collection_push_back (properties_p, resolve_result.result); + return ECMA_VALUE_EMPTY; +} /* ecma_module_namespace_object_add_export_if_needed */ + +/** + * Helper routine for heapsort algorithm. + */ +static void +ecma_module_heap_sort_shift_down (ecma_value_t *buffer_p, /**< array of items */ + uint32_t item_count, /**< number of items */ + uint32_t item_index) /**< index of updated item */ +{ + while (true) + { + uint32_t highest_index = item_index; + uint32_t current_index = (item_index << 1) + 2; + + if (current_index >= item_count) + { + return; + } + + if (ecma_compare_ecma_strings_relational (ecma_get_string_from_value (buffer_p[highest_index]), + ecma_get_string_from_value (buffer_p[current_index]))) + { + highest_index = current_index; + } + + current_index += 2; + + if (current_index < item_count + && ecma_compare_ecma_strings_relational (ecma_get_string_from_value (buffer_p[highest_index]), + ecma_get_string_from_value (buffer_p[current_index]))) + { + highest_index = current_index; + } + + if (highest_index == item_index) + { + return; + } + + ecma_value_t tmp = buffer_p[highest_index]; + buffer_p[highest_index] = buffer_p[item_index]; + buffer_p[item_index] = tmp; + + tmp = buffer_p[highest_index + 1]; + buffer_p[highest_index + 1] = buffer_p[item_index + 1]; + buffer_p[item_index + 1] = tmp; + + item_index = highest_index; + } +} /* ecma_module_heap_sort_shift_down */ + +/** + * Creates a namespace object for a module. + * Note: See 15.2.1.18 + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_EMPTY - otherwise + */ +static ecma_value_t +ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */ +{ + JERRY_ASSERT (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING); + JERRY_ASSERT (module_p->namespace_object_p != NULL); + JERRY_ASSERT (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_HAS_NAMESPACE)); + + ecma_module_resolve_set_t *resolve_set_p; + resolve_set_p = ecma_module_resolve_set_create (module_p, ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR)); + + /* The properties collection stores name / result item pairs. Name is always + * a string, and result can be a property reference or namespace object. */ + ecma_module_resolve_set_t *current_set_p = resolve_set_p; + ecma_collection_t *properties_p = ecma_new_collection (); + ecma_value_t result = ECMA_VALUE_EMPTY; + bool allow_default = true; + + ecma_value_t *buffer_p; + uint32_t item_count; + ecma_value_t *buffer_end_p; + + do + { + ecma_module_t *current_module_p = current_set_p->module_p; + + if (current_module_p->header.u.cls.u2.module_flags & ECMA_MODULE_HAS_NAMESPACE) + { + JERRY_ASSERT (!allow_default); + + jmem_cpointer_t prop_iter_cp = current_module_p->namespace_object_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (!ECMA_PROPERTY_IS_RAW (prop_iter_p->types[i])) + { + continue; + } + + ecma_string_t *name_p = ecma_string_from_property_name (prop_iter_p->types[i], prop_pair_p->names_cp[i]); + result = ecma_module_namespace_object_add_export_if_needed (properties_p, module_p, name_p, false); + ecma_deref_ecma_string (name_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto exit; + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } + } + else + { + ecma_module_names_t *export_names_p = current_module_p->local_exports_p; + + if (export_names_p != NULL) + { + do + { + result = ecma_module_namespace_object_add_export_if_needed (properties_p, + module_p, + export_names_p->imex_name_p, + allow_default); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto exit; + } + + export_names_p = export_names_p->next_p; + } while (export_names_p != NULL); + } + + ecma_module_node_t *indirect_export_p = current_module_p->indirect_exports_p; + + while (indirect_export_p != NULL) + { + export_names_p = indirect_export_p->module_names_p; + + while (export_names_p != NULL) + { + result = ecma_module_namespace_object_add_export_if_needed (properties_p, + module_p, + export_names_p->imex_name_p, + allow_default); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto exit; + } + + export_names_p = export_names_p->next_p; + } + + indirect_export_p = indirect_export_p->next_p; + } + } + + allow_default = false; + + ecma_module_node_t *star_export_p = current_module_p->star_exports_p; + + while (star_export_p != NULL) + { + JERRY_ASSERT (star_export_p->module_names_p == NULL); + + /* Circular imports are ignored */ + ecma_module_resolve_set_append (resolve_set_p, + ecma_module_get_from_object (*star_export_p->u.module_object_p), + ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR)); + + star_export_p = star_export_p->next_p; + } + + current_set_p = current_set_p->next_p; + } while (current_set_p != NULL); + + buffer_p = properties_p->buffer_p; + item_count = properties_p->item_count; + buffer_end_p = properties_p->buffer_p + item_count; + + if (item_count >= 4) + { + /* Sort items with heapsort if at least two items are stored in the buffer. */ + uint32_t end = (item_count >> 1) & ~(uint32_t) 0x1; + + do + { + end -= 2; + ecma_module_heap_sort_shift_down (buffer_p, item_count, end); + } while (end > 0); + + end = item_count - 2; + + do + { + ecma_value_t tmp = buffer_p[end]; + buffer_p[end] = buffer_p[0]; + buffer_p[0] = tmp; + + tmp = buffer_p[end + 1]; + buffer_p[end + 1] = buffer_p[1]; + buffer_p[1] = tmp; + + ecma_module_heap_sort_shift_down (buffer_p, end, 0); + end -= 2; + } while (end > 0); + } + + buffer_end_p = properties_p->buffer_p + item_count; + + while (buffer_p < buffer_end_p) + { + if (buffer_p[1] & ECMA_MODULE_NAMESPACE_RESULT_FLAG) + { + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (module_p->namespace_object_p, + ecma_get_string_from_value (buffer_p[0]), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE, + NULL); + property_value_p->value = buffer_p[1]; + } + else + { + ecma_create_named_reference_property (module_p->namespace_object_p, + ecma_get_string_from_value (buffer_p[0]), + buffer_p[1]); + } + + buffer_p += 2; + } + + module_p->header.u.cls.u2.module_flags |= ECMA_MODULE_HAS_NAMESPACE; + + ecma_module_release_module_names (module_p->local_exports_p); + module_p->local_exports_p = NULL; + + ecma_module_release_module_nodes (module_p->indirect_exports_p, false); + module_p->indirect_exports_p = NULL; + +exit: + /* Clean up. */ + ecma_module_resolve_set_cleanup (resolve_set_p); + ecma_collection_destroy (properties_p); + return result; +} /* ecma_module_create_namespace_object */ + +/** + * Connects imported values to the current module scope. + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_EMPTY - otherwise + */ +static ecma_value_t +ecma_module_connect_imports (ecma_module_t *module_p) +{ + ecma_object_t *local_env_p = module_p->scope_p; + JERRY_ASSERT (ecma_is_lexical_environment (local_env_p)); + + ecma_module_node_t *import_node_p = module_p->imports_p; + + /* Check that the imported bindings don't exist yet. */ + while (import_node_p != NULL) + { + ecma_module_names_t *import_names_p = import_node_p->module_names_p; + + JERRY_ASSERT (local_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK); + + while (import_names_p != NULL) + { + ecma_property_t *binding_p = ecma_find_named_property (local_env_p, import_names_p->local_name_p); + + if (binding_p != NULL) + { + return ecma_raise_syntax_error (ECMA_ERR_IMPORTED_BINDING_SHADOWS_LOCAL_VARIABLE); + } + + import_names_p = import_names_p->next_p; + } + + import_node_p = import_node_p->next_p; + } + + import_node_p = module_p->imports_p; + + /* Resolve imports and create local bindings. */ + while (import_node_p != NULL) + { + ecma_module_names_t *import_names_p = import_node_p->module_names_p; + ecma_module_t *imported_module_p = ecma_module_get_from_object (import_node_p->u.path_or_module); + + while (import_names_p != NULL) + { + if (ecma_compare_ecma_string_to_magic_id (import_names_p->imex_name_p, LIT_MAGIC_STRING_ASTERIX_CHAR)) + { + /* Namespace import. */ + ecma_property_value_t *value_p; + value_p = + ecma_create_named_data_property (module_p->scope_p, import_names_p->local_name_p, ECMA_PROPERTY_FIXED, NULL); + value_p->value = ecma_make_object_value (imported_module_p->namespace_object_p); + } + else + { + ecma_module_resolve_result_t resolve_result; + ecma_module_resolve_export (imported_module_p, import_names_p->imex_name_p, &resolve_result); + + if (resolve_result.result_type != ECMA_MODULE_RESOLVE_FOUND) + { + return ecma_module_resolve_throw (&resolve_result, import_names_p->imex_name_p); + } + + if (resolve_result.result & ECMA_MODULE_NAMESPACE_RESULT_FLAG) + { + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (module_p->scope_p, + import_names_p->local_name_p, + ECMA_PROPERTY_FIXED, + NULL); + property_value_p->value = resolve_result.result; + } + else + { + ecma_create_named_reference_property (module_p->scope_p, import_names_p->local_name_p, resolve_result.result); + } + } + + import_names_p = import_names_p->next_p; + } + + ecma_module_release_module_names (import_node_p->module_names_p); + import_node_p->module_names_p = NULL; + + import_node_p = import_node_p->next_p; + } + + return ECMA_VALUE_EMPTY; +} /* ecma_module_connect_imports */ + +/** + * Initialize the current module by creating the local binding for the imported variables + * and verifying indirect exports. + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +ecma_module_initialize (ecma_module_t *module_p) /**< module */ +{ + ecma_module_node_t *import_node_p = module_p->imports_p; + + while (import_node_p != NULL) + { + /* Module is evaluated even if it is used only in export-from statements. */ + ecma_value_t result = ecma_module_evaluate (ecma_module_get_from_object (import_node_p->u.path_or_module)); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_free_value (result); + + import_node_p = import_node_p->next_p; + } + + return ECMA_VALUE_EMPTY; +} /* ecma_module_initialize */ + +/** + * Gets the internal module pointer of a module + * + * @return module pointer - if module_val is a valid module, + * NULL - otherwise + */ +ecma_module_t * +ecma_module_get_resolved_module (ecma_value_t module_val) /**< module */ +{ + if (!ecma_is_value_object (module_val)) + { + return NULL; + } + + ecma_object_t *object_p = ecma_get_object_from_value (module_val); + + if (!ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE)) + { + return NULL; + } + + return (ecma_module_t *) object_p; +} /* ecma_module_get_resolved_module */ + +/** + * A module stack for depth-first search + */ +typedef struct ecma_module_stack_item_t +{ + struct ecma_module_stack_item_t *prev_p; /**< prev in the stack */ + struct ecma_module_stack_item_t *parent_p; /**< parent item in the stack */ + ecma_module_t *module_p; /**< currently processed module */ + ecma_module_node_t *node_p; /**< currently processed node */ + uint32_t dfs_index; /**< dfs index (ES2020 15.2.1.16) */ +} ecma_module_stack_item_t; + +/** + * Link module dependencies + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_UNDEFINED - otherwise + */ +ecma_value_t +ecma_module_link (ecma_module_t *module_p, /**< root module */ + jerry_module_resolve_cb_t callback, /**< resolve module callback */ + void *user_p) /**< pointer passed to the resolve callback */ +{ + if (module_p->header.u.cls.u1.module_state != JERRY_MODULE_STATE_UNLINKED) + { + return ecma_raise_type_error (ECMA_ERR_MODULE_MUST_BE_IN_UNLINKED_STATE); + } + + module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_LINKING; + + uint32_t dfs_index = 0; + ecma_module_stack_item_t *last_p; + ecma_module_node_t *node_p; + + last_p = (ecma_module_stack_item_t *) jmem_heap_alloc_block (sizeof (ecma_module_stack_item_t)); + last_p->prev_p = NULL; + last_p->parent_p = NULL; + last_p->module_p = module_p; + last_p->node_p = module_p->imports_p; + last_p->dfs_index = dfs_index; + + module_p->header.u.cls.u3.dfs_ancestor_index = dfs_index; + + ecma_value_t module_val = ecma_make_object_value (&module_p->header.object); + ecma_module_stack_item_t *current_p = last_p; + +restart: + /* Entering into processing new node phase. Resolve dependencies first. */ + node_p = current_p->node_p; + + JERRY_ASSERT (ecma_module_get_from_object (module_val)->imports_p == node_p); + + while (node_p != NULL) + { + ecma_module_t *resolved_module_p; + + if (!ecma_is_value_object (node_p->u.path_or_module)) + { + JERRY_ASSERT (ecma_is_value_string (node_p->u.path_or_module)); + + ecma_value_t resolve_result = callback (node_p->u.path_or_module, module_val, user_p); + + if (JERRY_UNLIKELY (ecma_is_value_exception (resolve_result))) + { + ecma_throw_exception (resolve_result); + goto error; + } + + resolved_module_p = ecma_module_get_resolved_module (resolve_result); + + if (resolved_module_p == NULL) + { + ecma_free_value (resolve_result); + ecma_raise_type_error (ECMA_ERR_CALLBACK_RESULT_NOT_MODULE); + goto error; + } + + ecma_deref_ecma_string (ecma_get_string_from_value (node_p->u.path_or_module)); + node_p->u.path_or_module = resolve_result; + ecma_deref_object (ecma_get_object_from_value (resolve_result)); + } + else + { + resolved_module_p = ecma_module_get_from_object (node_p->u.path_or_module); + } + + if (resolved_module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_ERROR) + { + ecma_raise_type_error (ECMA_ERR_LINK_TO_MODULE_IN_ERROR_STATE); + goto error; + } + + node_p = node_p->next_p; + } + + /* Find next unlinked node, or return to parent */ + while (true) + { + ecma_module_t *current_module_p = current_p->module_p; + node_p = current_p->node_p; + + while (node_p != NULL) + { + module_p = ecma_module_get_from_object (node_p->u.path_or_module); + + if (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_UNLINKED) + { + current_p->node_p = node_p->next_p; + module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_LINKING; + + ecma_module_stack_item_t *item_p; + item_p = (ecma_module_stack_item_t *) jmem_heap_alloc_block (sizeof (ecma_module_stack_item_t)); + + dfs_index++; + + item_p->prev_p = last_p; + item_p->parent_p = current_p; + item_p->module_p = module_p; + item_p->node_p = module_p->imports_p; + item_p->dfs_index = dfs_index; + + module_p->header.u.cls.u3.dfs_ancestor_index = dfs_index; + + last_p = item_p; + current_p = item_p; + module_val = node_p->u.path_or_module; + goto restart; + } + + if (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING) + { + uint32_t dfs_ancestor_index = module_p->header.u.cls.u3.dfs_ancestor_index; + + if (dfs_ancestor_index < current_module_p->header.u.cls.u3.dfs_ancestor_index) + { + current_module_p->header.u.cls.u3.dfs_ancestor_index = dfs_ancestor_index; + } + } + + node_p = node_p->next_p; + } + + if (current_module_p->scope_p == NULL) + { + JERRY_ASSERT (!(current_module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)); + + /* Initialize scope for handling circular references. */ + ecma_value_t result = vm_init_module_scope (current_module_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_module_set_error_state (current_module_p); + goto error; + } + + JERRY_ASSERT (result == ECMA_VALUE_EMPTY); + } + + if (current_module_p->namespace_object_p == NULL) + { + ecma_object_t *namespace_object_p = + ecma_create_object (NULL, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + namespace_object_p->type_flags_refs &= (ecma_object_descriptor_t) ~ECMA_OBJECT_FLAG_EXTENSIBLE; + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) namespace_object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_MODULE_NAMESPACE; + ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.cls.u3.value, module_p); + + current_module_p->namespace_object_p = namespace_object_p; + ecma_deref_object (namespace_object_p); + } + + if (current_module_p->header.u.cls.u3.dfs_ancestor_index != current_p->dfs_index) + { + current_p = current_p->parent_p; + JERRY_ASSERT (current_p != NULL); + + uint32_t dfs_ancestor_index = current_module_p->header.u.cls.u3.dfs_ancestor_index; + + if (dfs_ancestor_index < current_p->module_p->header.u.cls.u3.dfs_ancestor_index) + { + current_p->module_p->header.u.cls.u3.dfs_ancestor_index = dfs_ancestor_index; + } + continue; + } + + ecma_module_stack_item_t *end_p = current_p->prev_p; + current_p = current_p->parent_p; + + ecma_module_stack_item_t *iterator_p = last_p; + + do + { + JERRY_ASSERT (iterator_p->module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING); + + if (ECMA_IS_VALUE_ERROR (ecma_module_create_namespace_object (iterator_p->module_p))) + { + ecma_module_set_error_state (iterator_p->module_p); + goto error; + } + + iterator_p = iterator_p->prev_p; + } while (iterator_p != end_p); + + iterator_p = last_p; + + do + { + JERRY_ASSERT (iterator_p->module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING); + + if (ECMA_IS_VALUE_ERROR (ecma_module_connect_imports (iterator_p->module_p))) + { + ecma_module_set_error_state (iterator_p->module_p); + goto error; + } + + iterator_p = iterator_p->prev_p; + } while (iterator_p != end_p); + + do + { + ecma_module_stack_item_t *prev_p = last_p->prev_p; + + JERRY_ASSERT (last_p->module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING); + last_p->module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_LINKED; + + if (JERRY_CONTEXT (module_state_changed_callback_p) != NULL) + { + JERRY_CONTEXT (module_state_changed_callback_p) + (JERRY_MODULE_STATE_LINKED, + ecma_make_object_value (&last_p->module_p->header.object), + ECMA_VALUE_UNDEFINED, + JERRY_CONTEXT (module_state_changed_callback_user_p)); + } + + jmem_heap_free_block (last_p, sizeof (ecma_module_stack_item_t)); + last_p = prev_p; + } while (last_p != end_p); + + if (current_p == NULL) + { + return ECMA_VALUE_TRUE; + } + } + +error: + JERRY_ASSERT (last_p != NULL); + + do + { + ecma_module_stack_item_t *prev_p = last_p->prev_p; + + if (last_p->module_p->header.u.cls.u1.module_state != JERRY_MODULE_STATE_ERROR) + { + JERRY_ASSERT (last_p->module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING); + last_p->module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_UNLINKED; + } + + jmem_heap_free_block (last_p, sizeof (ecma_module_stack_item_t)); + last_p = prev_p; + } while (last_p != NULL); + + return ECMA_VALUE_ERROR; +} /* ecma_module_link */ + +/** + * Compute the result of 'import()' calls + * + * @return promise object representing the result of the operation + */ +ecma_value_t +ecma_module_import (ecma_value_t specifier, /**< module specifier */ + ecma_value_t user_value) /**< user value assigned to the script */ +{ + ecma_string_t *specifier_p = ecma_op_to_string (specifier); + ecma_module_t *module_p; + + if (JERRY_UNLIKELY (specifier_p == NULL)) + { + goto error; + } + + if (JERRY_CONTEXT (module_import_callback_p) == NULL) + { + ecma_deref_ecma_string (specifier_p); + goto error_module_instantiate; + } + + jerry_value_t result; + result = JERRY_CONTEXT (module_import_callback_p) (ecma_make_string_value (specifier_p), + user_value, + JERRY_CONTEXT (module_import_callback_user_p)); + ecma_deref_ecma_string (specifier_p); + + if (JERRY_UNLIKELY (ecma_is_value_exception (result))) + { + ecma_throw_exception (result); + goto error; + } + + if (ecma_is_value_object (result) && ecma_is_promise (ecma_get_object_from_value (result))) + { + return result; + } + + module_p = ecma_module_get_resolved_module (result); + + if (module_p == NULL) + { + ecma_free_value (result); + goto error_module_instantiate; + } + + if (module_p->header.u.cls.u1.module_state != JERRY_MODULE_STATE_EVALUATED) + { + ecma_deref_object (&module_p->header.object); + goto error_module_instantiate; + } + + result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL); + ecma_fulfill_promise (result, ecma_make_object_value (module_p->namespace_object_p)); + ecma_deref_object (&module_p->header.object); + return result; + +error_module_instantiate: + ecma_raise_range_error (ECMA_ERR_MODULE_CANNOT_BE_INSTANTIATED); + +error: + if (jcontext_has_pending_abort ()) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t exception = jcontext_take_exception (); + + ecma_value_t promise = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL); + ecma_reject_promise (promise, exception); + ecma_free_value (exception); + return promise; +} /* ecma_module_import */ + +/** + * Cleans up and releases a module structure including all referenced modules. + */ +void +ecma_module_release_module (ecma_module_t *module_p) /**< module */ +{ + jerry_module_state_t state = (jerry_module_state_t) module_p->header.u.cls.u1.module_state; + + JERRY_ASSERT (state != JERRY_MODULE_STATE_INVALID); + +#ifndef JERRY_NDEBUG + module_p->scope_p = NULL; + module_p->namespace_object_p = NULL; +#endif /* JERRY_NDEBUG */ + + ecma_module_release_module_names (module_p->local_exports_p); + + if (module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) + { + return; + } + + ecma_module_release_module_nodes (module_p->imports_p, true); + ecma_module_release_module_nodes (module_p->indirect_exports_p, false); + ecma_module_release_module_nodes (module_p->star_exports_p, false); + + if (module_p->u.compiled_code_p != NULL) + { + ecma_bytecode_deref (module_p->u.compiled_code_p); +#ifndef JERRY_NDEBUG + module_p->u.compiled_code_p = NULL; +#endif /* JERRY_NDEBUG */ + } +} /* ecma_module_release_module */ + +#endif /* JERRY_MODULE_SYSTEM */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.h new file mode 100644 index 00000000..ceb47ec6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.h @@ -0,0 +1,132 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_MODULE_H +#define ECMA_MODULE_H + +#include "ecma-globals.h" + +#include "common.h" + +#if JERRY_MODULE_SYSTEM + +#define ECMA_MODULE_MAX_PATH 255u + +/** + * Module status flags. + */ +typedef enum +{ + ECMA_MODULE_IS_NATIVE = (1 << 0), /**< native module */ + ECMA_MODULE_HAS_NAMESPACE = (1 << 1), /**< namespace object has been initialized */ +} ecma_module_flags_t; + +/** + * Imported or exported names, such as "a as b" + * Note: See https://www.ecma-international.org/ecma-262/6.0/#table-39 + * and https://www.ecma-international.org/ecma-262/6.0/#table-41 + */ +typedef struct ecma_module_names +{ + struct ecma_module_names *next_p; /**< next linked list node */ + ecma_string_t *imex_name_p; /**< Import/export name of the item */ + ecma_string_t *local_name_p; /**< Local name of the item */ +} ecma_module_names_t; + +/** + * Module structure storing an instance of a module + * + * Note: + * The imports_p list follows the order of import-from/export-from statements in the source + * code of a module, even if a given module specifier is only used by export-from statements. + */ +typedef struct ecma_module +{ + /* Note: state is stored in header.u.class_prop.extra_info */ + ecma_extended_object_t header; /**< header part */ + /* TODO(dbatyai): These could be compressed pointers */ + ecma_object_t *scope_p; /**< lexical lenvironment of the module */ + ecma_object_t *namespace_object_p; /**< namespace object of the module */ + struct ecma_module_node *imports_p; /**< import requests of the module */ + ecma_module_names_t *local_exports_p; /**< local exports of the module */ + struct ecma_module_node *indirect_exports_p; /**< indirect exports of the module */ + struct ecma_module_node *star_exports_p; /**< star exports of the module */ + + /* Code used for evaluating a module */ + union + { + ecma_compiled_code_t *compiled_code_p; /**< compiled code for the module */ + jerry_native_module_evaluate_cb_t callback; /**< callback for evaluating native modules */ + } u; +} ecma_module_t; + +/** + * Module node to store imports / exports. + * + * Note: + * Only one module node is created for each module specifier: the names are + * concatenated if the same specifier is used multiple times in the source code. + * However, multiple nodes are created for modules with multiple alias + * (for example ./a.mjs and ././a.mjs can refer to the same module). + */ +typedef struct ecma_module_node +{ + struct ecma_module_node *next_p; /**< next linked list node */ + ecma_module_names_t *module_names_p; /**< names of the requested import/export node */ + + union + { + ecma_value_t path_or_module; /**< imports: module specifier (if string) or module reference (if object) */ + ecma_value_t *module_object_p; /**< non-imports: reference to a path_or_module field in the imports */ + } u; +} ecma_module_node_t; + +/** + * A list of module records that can be used to identify circular imports during resolution + */ +typedef struct ecma_module_resolve_set +{ + struct ecma_module_resolve_set *next_p; /**< next in linked list */ + ecma_module_t *module_p; /**< module */ + ecma_string_t *name_p; /**< identifier name */ +} ecma_module_resolve_set_t; + +/** + * A list that is used like a stack to drive the resolution process, instead of recursion. + */ +typedef struct ecma_module_resolve_stack +{ + struct ecma_module_resolve_stack *next_p; /**< next in linked list */ + ecma_module_t *module_p; /**< module request */ + ecma_string_t *export_name_p; /**< export identifier name */ + bool resolving; /**< flag storing wether the current frame started resolving */ +} ecma_module_resolve_stack_t; + +ecma_value_t ecma_module_initialize (ecma_module_t *module_p); +ecma_module_t *ecma_module_get_resolved_module (ecma_value_t module_val); + +ecma_value_t ecma_module_link (ecma_module_t *module_p, jerry_module_resolve_cb_t callback_p, void *user_p); +ecma_value_t ecma_module_evaluate (ecma_module_t *module_p); +ecma_value_t ecma_module_import (ecma_value_t specifier, ecma_value_t user_value); + +ecma_module_t *ecma_module_create (void); +void ecma_module_cleanup_context (void); + +void ecma_module_release_module_names (ecma_module_names_t *module_name_p); +void ecma_module_release_module (ecma_module_t *module_p); + +#endif /* JERRY_MODULE_SYSTEM */ + +#endif /* !ECMA_MODULE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.cpp new file mode 100644 index 00000000..370b1fc7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.cpp @@ -0,0 +1,532 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-property-hashmap.h" + +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "jrt-libc-includes.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmapropertyhashmap Property hashmap + * @{ + */ + +#if JERRY_PROPERTY_HASHMAP + +/** + * Compute the total size of the property hashmap. + */ +#define ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE(max_property_count) \ + (sizeof (ecma_property_hashmap_t) + (max_property_count * sizeof (jmem_cpointer_t)) + (max_property_count >> 3)) + +/** + * Number of items in the stepping table. + */ +#define ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS 8 + +/** + * Stepping values for searching items in the hashmap. + */ +static const uint8_t ecma_property_hashmap_steps[ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS] JERRY_ATTR_CONST_DATA = { + 3, 5, 7, 11, 13, 17, 19, 23 +}; + +/** + * Get the value of a bit in a bitmap. + */ +#define ECMA_PROPERTY_HASHMAP_GET_BIT(byte_p, index) ((byte_p)[(index) >> 3] & (1 << ((index) &0x7))) + +/** + * Clear the value of a bit in a bitmap. + */ +#define ECMA_PROPERTY_HASHMAP_CLEAR_BIT(byte_p, index) \ + ((byte_p)[(index) >> 3] = (uint8_t) ((byte_p)[(index) >> 3] & ~(1 << ((index) &0x7)))) + +/** + * Set the value of a bit in a bitmap. + */ +#define ECMA_PROPERTY_HASHMAP_SET_BIT(byte_p, index) \ + ((byte_p)[(index) >> 3] = (uint8_t) ((byte_p)[(index) >> 3] | (1 << ((index) &0x7)))) + +/** + * Create a new property hashmap for the object. + * The object must not have a property hashmap. + */ +void +ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ +{ + if (JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) != ECMA_PROP_HASHMAP_ALLOC_ON) + { + return; + } + + jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp; + + if (prop_iter_cp == JMEM_CP_NULL) + { + return; + } + + uint32_t named_property_count = 0; + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i])); + named_property_count++; + } + } + prop_iter_cp = prop_iter_p->next_property_cp; + } + + if (named_property_count < (ECMA_PROPERTY_HASMAP_MINIMUM_SIZE / 2)) + { + return; + } + + /* The max_property_count must be power of 2. */ + uint32_t max_property_count = ECMA_PROPERTY_HASMAP_MINIMUM_SIZE; + + /* At least 1/3 items must be NULL. */ + while (max_property_count < (named_property_count + (named_property_count >> 1))) + { + max_property_count <<= 1; + } + + size_t total_size = ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (max_property_count); + + ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) jmem_heap_alloc_block_null_on_error (total_size); + + if (hashmap_p == NULL) + { + return; + } + + memset (hashmap_p, 0, total_size); + + hashmap_p->header.types[0] = ECMA_PROPERTY_TYPE_HASHMAP; + hashmap_p->header.next_property_cp = object_p->u1.property_list_cp; + hashmap_p->max_property_count = max_property_count; + hashmap_p->null_count = max_property_count - named_property_count; + hashmap_p->unused_count = max_property_count - named_property_count; + + jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); + uint8_t *bits_p = (uint8_t *) (pair_list_p + max_property_count); + uint32_t mask = max_property_count - 1; + + prop_iter_cp = object_p->u1.property_list_cp; + ECMA_SET_NON_NULL_POINTER (object_p->u1.property_list_cp, hashmap_p); + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (prop_iter_p->types[i] == ECMA_PROPERTY_TYPE_DELETED) + { + continue; + } + + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i])); + + ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p; + + uint32_t entry_index = ecma_string_get_property_name_hash (prop_iter_p->types[i], property_pair_p->names_cp[i]); + uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; + + entry_index &= mask; +#ifndef JERRY_NDEBUG + /* Because max_property_count (power of 2) and step (a prime + * number) are relative primes, all entries of the hasmap are + * visited exactly once before the start entry index is reached + * again. Furthermore because at least one NULL is present in + * the hashmap, the while loop must be terminated before the + * the starting index is reached again. */ + uint32_t start_entry_index = entry_index; +#endif /* !JERRY_NDEBUG */ + + while (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } + + ECMA_SET_NON_NULL_POINTER (pair_list_p[entry_index], property_pair_p); + + if (i != 0) + { + ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index); + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } +} /* ecma_property_hashmap_create */ + +/** + * Free the hashmap of the object. + * The object must have a property hashmap. + */ +void +ecma_property_hashmap_free (ecma_object_t *object_p) /**< object */ +{ + /* Property hash must be exists and must be the first property. */ + JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); + + ecma_property_header_t *property_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, object_p->u1.property_list_cp); + + JERRY_ASSERT (property_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP); + + ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) property_p; + + object_p->u1.property_list_cp = property_p->next_property_cp; + + jmem_heap_free_block (hashmap_p, ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (hashmap_p->max_property_count)); +} /* ecma_property_hashmap_free */ + +/** + * Insert named property into the hashmap. + */ +void +ecma_property_hashmap_insert (ecma_object_t *object_p, /**< object */ + ecma_string_t *name_p, /**< name of the property */ + ecma_property_pair_t *property_pair_p, /**< property pair */ + int property_index) /**< property index in the pair (0 or 1) */ +{ + JERRY_ASSERT (property_pair_p != NULL); + + ecma_property_hashmap_t *hashmap_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t, object_p->u1.property_list_cp); + + JERRY_ASSERT (hashmap_p->header.types[0] == ECMA_PROPERTY_TYPE_HASHMAP); + + /* The NULLs are reduced below 1/8 of the hashmap. */ + if (hashmap_p->null_count < (hashmap_p->max_property_count >> 3)) + { + ecma_property_hashmap_free (object_p); + ecma_property_hashmap_create (object_p); + return; + } + + JERRY_ASSERT (property_index < ECMA_PROPERTY_PAIR_ITEM_COUNT); + + uint32_t entry_index = ecma_string_hash (name_p); + uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; + uint32_t mask = hashmap_p->max_property_count - 1; + entry_index &= mask; + +#ifndef JERRY_NDEBUG + /* See the comment for this variable in ecma_property_hashmap_create. */ + uint32_t start_entry_index = entry_index; +#endif /* !JERRY_NDEBUG */ + + jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); + + while (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } + + ECMA_SET_NON_NULL_POINTER (pair_list_p[entry_index], property_pair_p); + + uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count); + bits_p += (entry_index >> 3); + mask = (uint32_t) (1 << (entry_index & 0x7)); + + if (!(*bits_p & mask)) + { + /* Deleted entries also has ECMA_NULL_POINTER + * value, but they are not NULL values. */ + hashmap_p->null_count--; + JERRY_ASSERT (hashmap_p->null_count > 0); + } + + hashmap_p->unused_count--; + JERRY_ASSERT (hashmap_p->unused_count > 0); + + if (property_index == 0) + { + *bits_p = (uint8_t) ((*bits_p) & ~mask); + } + else + { + *bits_p = (uint8_t) ((*bits_p) | mask); + } +} /* ecma_property_hashmap_insert */ + +/** + * Delete named property from the hashmap. + * + * @return ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP if hashmap should be recreated + * ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP otherwise + */ +ecma_property_hashmap_delete_status +ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */ + jmem_cpointer_t name_cp, /**< property name */ + ecma_property_t *property_p) /**< property */ +{ + ecma_property_hashmap_t *hashmap_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t, object_p->u1.property_list_cp); + + JERRY_ASSERT (hashmap_p->header.types[0] == ECMA_PROPERTY_TYPE_HASHMAP); + + hashmap_p->unused_count++; + + /* The NULLs are above 3/4 of the hashmap. */ + if (hashmap_p->unused_count > ((hashmap_p->max_property_count * 3) >> 2)) + { + return ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP; + } + + uint32_t entry_index = ecma_string_get_property_name_hash (*property_p, name_cp); + uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; + uint32_t mask = hashmap_p->max_property_count - 1; + jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); + uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count); + + entry_index &= mask; + +#ifndef JERRY_NDEBUG + /* See the comment for this variable in ecma_property_hashmap_create. */ + uint32_t start_entry_index = entry_index; +#endif /* !JERRY_NDEBUG */ + + while (true) + { + if (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + size_t offset = 0; + + if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { + offset = 1; + } + + ecma_property_pair_t *property_pair_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, pair_list_p[entry_index]); + + if ((property_pair_p->header.types + offset) == property_p) + { + JERRY_ASSERT (property_pair_p->names_cp[offset] == name_cp); + + pair_list_p[entry_index] = ECMA_NULL_POINTER; + ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index); + return ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP; + } + } + else + { + /* Must be a deleted entry. */ + JERRY_ASSERT (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)); + } + + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } +} /* ecma_property_hashmap_delete */ + +/** + * Find a named property. + * + * @return pointer to the property if found or NULL otherwise + */ +ecma_property_t * +ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */ + ecma_string_t *name_p, /**< property name */ + jmem_cpointer_t *property_real_name_cp) /**< [out] property real name */ +{ +#ifndef JERRY_NDEBUG + /* A sanity check in debug mode: a named property must be present + * in both the property hashmap and in the property chain, or missing + * from both data collection. The following code checks the property + * chain, and sets the property_found variable. */ + bool property_found = false; + + jmem_cpointer_t prop_iter_cp = hashmap_p->header.next_property_cp; + + while (prop_iter_cp != JMEM_CP_NULL && !property_found) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i])) + { + if (ecma_string_compare_to_property_name (prop_iter_p->types[i], prop_pair_p->names_cp[i], name_p)) + { + /* Property is found */ + property_found = true; + break; + } + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } +#endif /* !JERRY_NDEBUG */ + + uint32_t entry_index = ecma_string_hash (name_p); + uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; + uint32_t mask = hashmap_p->max_property_count - 1; + jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); + uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count); + entry_index &= mask; + +#ifndef JERRY_NDEBUG + /* See the comment for this variable in ecma_property_hashmap_create. */ + uint32_t start_entry_index = entry_index; +#endif /* !JERRY_NDEBUG */ + + if (ECMA_IS_DIRECT_STRING (name_p)) + { + ecma_property_t prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (name_p); + jmem_cpointer_t property_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (name_p); + + JERRY_ASSERT (prop_name_type > 0); + + while (true) + { + if (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + size_t offset = 0; + if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { + offset = 1; + } + + ecma_property_pair_t *property_pair_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, pair_list_p[entry_index]); + + ecma_property_t *property_p = property_pair_p->header.types + offset; + + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); + + if (property_pair_p->names_cp[offset] == property_name_cp + && ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == prop_name_type) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (property_found); +#endif /* !JERRY_NDEBUG */ + + *property_real_name_cp = property_name_cp; + return property_p; + } + } + else + { + if (!ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (!property_found); +#endif /* !JERRY_NDEBUG */ + + return NULL; + } + /* Otherwise it is a deleted entry. */ + } + + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } + } + + while (true) + { + if (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + size_t offset = 0; + if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { + offset = 1; + } + + ecma_property_pair_t *property_pair_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, pair_list_p[entry_index]); + + ecma_property_t *property_p = property_pair_p->header.types + offset; + + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); + + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_PTR) + { + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_pair_p->names_cp[offset]); + + if (ecma_compare_ecma_non_direct_strings (prop_name_p, name_p)) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (property_found); +#endif /* !JERRY_NDEBUG */ + + *property_real_name_cp = property_pair_p->names_cp[offset]; + return property_p; + } + } + } + else + { + if (!ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (!property_found); +#endif /* !JERRY_NDEBUG */ + + return NULL; + } + /* Otherwise it is a deleted entry. */ + } + + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } +} /* ecma_property_hashmap_find */ +#endif /* JERRY_PROPERTY_HASHMAP */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.h new file mode 100644 index 00000000..265075e9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.h @@ -0,0 +1,89 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_PROPERTY_HASHMAP_H +#define ECMA_PROPERTY_HASHMAP_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmapropertyhashmap Property hashmap + * @{ + */ + +/** + * Recommended minimum number of items in a property cache. + */ +#define ECMA_PROPERTY_HASMAP_MINIMUM_SIZE 32 + +/** + * Property hash. + */ +typedef struct +{ + ecma_property_header_t header; /**< header of the property */ + uint32_t max_property_count; /**< maximum property count (power of 2) */ + uint32_t null_count; /**< number of NULLs in the map */ + uint32_t unused_count; /**< number of unused entries in the map */ + + /* + * The hash is followed by max_property_count ecma_cpointer_t + * compressed pointers and (max_property_count + 7) / 8 bytes + * which stores a flag for each compressed pointer. + * + * If the compressed pointer is equal to ECMA_NULL_POINTER + * - flag is cleared if the entry is NULL + * - flag is set if the entry is deleted + * + * If the compressed pointer is not equal to ECMA_NULL_POINTER + * - flag is cleared if the first entry of a property pair is referenced + * - flag is set if the second entry of a property pair is referenced + */ +} ecma_property_hashmap_t; + +#if JERRY_PROPERTY_HASHMAP + +/** + * Simple ecma values + */ +typedef enum +{ + ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP, /**< object has no hashmap */ + ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP, /**< object has hashmap */ + ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP, /**< hashmap should be recreated */ +} ecma_property_hashmap_delete_status; + +void ecma_property_hashmap_create (ecma_object_t *object_p); +void ecma_property_hashmap_free (ecma_object_t *object_p); +void ecma_property_hashmap_insert (ecma_object_t *object_p, + ecma_string_t *name_p, + ecma_property_pair_t *property_pair_p, + int property_index); +ecma_property_hashmap_delete_status +ecma_property_hashmap_delete (ecma_object_t *object_p, jmem_cpointer_t name_cp, ecma_property_t *property_p); + +ecma_property_t *ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, + ecma_string_t *name_p, + jmem_cpointer_t *property_real_name_cp); +#endif /* JERRY_PROPERTY_HASHMAP */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_PROPERTY_HASHMAP_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/meson.build b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/meson.build new file mode 100644 index 00000000..357e887c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/meson.build @@ -0,0 +1,39 @@ +source_file = [ + 'ecma-alloc.h', + 'ecma-error-messages.inc.h', + 'ecma-errors.h', + 'ecma-extended-info.h', + 'ecma-gc.h', + 'ecma-globals.h', + 'ecma-helpers-number.h', + 'ecma-helpers.h', + 'ecma-init-finalize.h', + 'ecma-lcache.h', + 'ecma-line-info.h', + 'ecma-literal-storage.h', + 'ecma-module.h', + 'ecma-property-hashmap.h', + 'ecma-alloc.cpp', + 'ecma-errors.cpp', + 'ecma-extended-info.cpp', + 'ecma-gc.cpp', + 'ecma-helpers-collection.cpp', + 'ecma-helpers-conversion.cpp', + 'ecma-helpers-errol.cpp', + 'ecma-helpers-external-pointers.cpp', + 'ecma-helpers-number.cpp', + 'ecma-helpers-string.cpp', + 'ecma-helpers-value.cpp', + 'ecma-helpers.cpp', + 'ecma-init-finalize.cpp', + 'ecma-lcache.cpp', + 'ecma-line-info.cpp', + 'ecma-literal-storage.cpp', + 'ecma-module.cpp', + 'ecma-property-hashmap.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.cpp new file mode 100644 index 00000000..771fca8e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.cpp @@ -0,0 +1,33 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-aggregateerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID aggregate_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.inc.h new file mode 100644 index 00000000..b5b3a11a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.inc.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * AggregateError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_AGGREGATE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_AGGREGATE_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.cpp new file mode 100644 index 00000000..4313168b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.cpp @@ -0,0 +1,109 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-aggregateerror.inc.h" +#define BUILTIN_UNDERSCORED_ID aggregate_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup aggregateerror ECMA AggregateError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in AggregateError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_aggregate_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + ecma_value_t message_val = ECMA_VALUE_UNDEFINED; + ecma_value_t error_val = ECMA_VALUE_UNDEFINED; + + if (arguments_list_len > 0) + { + error_val = arguments_list_p[0]; + + if (arguments_list_len > 1) + { + message_val = arguments_list_p[1]; + } + } + + return ecma_new_aggregate_error (error_val, message_val); +} /* ecma_builtin_aggregate_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in AggregateError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_aggregate_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_AGGREGATE_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_aggregate_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_aggregate_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.inc.h new file mode 100644 index 00000000..c7f0f6fb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.inc.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * AggregateError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 2, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_AGGREGATE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_AGGREGATE_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.cpp new file mode 100644 index 00000000..c295f7a0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.cpp @@ -0,0 +1,224 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-iterator-object.h" +#include "ecma-typedarray-object.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ARRAY_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_ARRAY_ITERATOR_PROTOTYPE_OBJECT_NEXT, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID array_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %arrayiteratorprototype% ECMA %ArrayIteratorPrototype% object built-in + * @{ + */ + +/** + * The %ArrayIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 22.1.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_array_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + /* 1 - 2. */ + if (!ecma_is_value_object (this_val)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_val); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + /* 3. */ + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARRAY_ITERATOR)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR); + } + + ecma_value_t iterated_value = ext_obj_p->u.cls.u3.iterated_value; + + /* 4 - 5 */ + if (ecma_is_value_empty (iterated_value)) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + ecma_object_t *array_object_p = ecma_get_object_from_value (iterated_value); + + /* 8. */ + ecma_length_t length; + if (ecma_object_is_typedarray (array_object_p)) + { + /* a. */ + ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (array_object_p); + if (ecma_arraybuffer_is_detached (arraybuffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* b. */ + length = ecma_typedarray_get_length (array_object_p); + } + else + { + ecma_value_t len_value = ecma_op_object_get_length (array_object_p, &length); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + return len_value; + } + } + + ecma_length_t index = ext_obj_p->u.cls.u2.iterator_index; + + if (JERRY_UNLIKELY (index == ECMA_ITERATOR_INDEX_LIMIT)) + { + /* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]] + property is stored as an internal property */ + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); + ecma_value_t index_value = ecma_op_object_get (obj_p, prop_name_p); + + if (!ecma_is_value_undefined (index_value)) + { + index = (ecma_length_t) (ecma_get_number_from_value (index_value) + 1); + } + + ecma_value_t put_result = ecma_op_object_put (obj_p, prop_name_p, ecma_make_length_value (index), true); + + JERRY_ASSERT (ecma_is_value_true (put_result)); + + ecma_free_value (index_value); + } + else + { + /* 11. */ + ext_obj_p->u.cls.u2.iterator_index++; + } + + if (index >= length) + { + ext_obj_p->u.cls.u3.iterated_value = ECMA_VALUE_EMPTY; + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + /* 7. */ + uint8_t iterator_kind = ext_obj_p->u.cls.u1.iterator_kind; + + if (iterator_kind == ECMA_ITERATOR_KEYS) + { + /* 12. */ + return ecma_create_iter_result_object (ecma_make_length_value (index), ECMA_VALUE_FALSE); + } + + /* 14. */ + ecma_value_t get_value = ecma_op_object_get_by_index (array_object_p, index); + + /* 15. */ + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + ecma_value_t result; + + /* 16. */ + if (iterator_kind == ECMA_ITERATOR_VALUES) + { + result = ecma_create_iter_result_object (get_value, ECMA_VALUE_FALSE); + } + else + { + /* 17.a */ + JERRY_ASSERT (iterator_kind == ECMA_ITERATOR_ENTRIES); + + /* 17.b */ + ecma_value_t entry_array_value; + entry_array_value = ecma_create_array_from_iter_element (get_value, ecma_make_length_value (index)); + + result = ecma_create_iter_result_object (entry_array_value, ECMA_VALUE_FALSE); + ecma_free_value (entry_array_value); + } + + ecma_free_value (get_value); + + return result; +} /* ecma_builtin_array_iterator_prototype_object_next */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_array_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_ARRAY_ITERATOR_PROTOTYPE_OBJECT_NEXT: + { + return ecma_builtin_array_iterator_prototype_object_next (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_array_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.inc.h new file mode 100644 index 00000000..c74d68da --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %ArrayIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ARRAY_ITERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_ARRAY_ITERATOR_PROTOTYPE_OBJECT_NEXT, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.cpp new file mode 100644 index 00000000..5f67573a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.cpp @@ -0,0 +1,24 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-prototype-unscopables.inc.h" +#define BUILTIN_UNDERSCORED_ID array_prototype_unscopables +#include "ecma-builtin-internal-routines-template.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h new file mode 100644 index 00000000..2cc4bc50 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Array.prototype[@@unscopables] built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +SIMPLE_VALUE (LIT_MAGIC_STRING_AT, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_COPY_WITHIN, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_ENTRIES, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FILL, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FIND, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FIND_INDEX, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FLAT, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FLATMAP, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_INCLUDES, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_KEYS, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_VALUES, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp new file mode 100644 index 00000000..e6243185 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp @@ -0,0 +1,2973 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-comparison.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jcontext.h" +#include "jrt.h" +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_ARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ARRAY_PROTOTYPE_ROUTINE_START = 0, + /* Note: these 2 routine ids must be in this order */ + ECMA_ARRAY_PROTOTYPE_SORT, + ECMA_ARRAY_PROTOTYPE_CONCAT, + ECMA_ARRAY_PROTOTYPE_TO_LOCALE_STRING, + ECMA_ARRAY_PROTOTYPE_JOIN, + ECMA_ARRAY_PROTOTYPE_POP, + ECMA_ARRAY_PROTOTYPE_PUSH, + ECMA_ARRAY_PROTOTYPE_REVERSE, + ECMA_ARRAY_PROTOTYPE_SHIFT, + ECMA_ARRAY_PROTOTYPE_SLICE, + ECMA_ARRAY_PROTOTYPE_SPLICE, + ECMA_ARRAY_PROTOTYPE_UNSHIFT, + ECMA_ARRAY_PROTOTYPE_AT, + ECMA_ARRAY_PROTOTYPE_INDEX_OF, + ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF, + /* Note these 3 routines must be in this order */ + ECMA_ARRAY_PROTOTYPE_EVERY, + ECMA_ARRAY_PROTOTYPE_SOME, + ECMA_ARRAY_PROTOTYPE_FOR_EACH, + ECMA_ARRAY_PROTOTYPE_MAP, + ECMA_ARRAY_PROTOTYPE_FILTER, + /* Note these 2 routines must be in this order */ + ECMA_ARRAY_PROTOTYPE_REDUCE, + ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT, + ECMA_ARRAY_PROTOTYPE_FIND, + ECMA_ARRAY_PROTOTYPE_FIND_INDEX, + ECMA_ARRAY_PROTOTYPE_ENTRIES, + ECMA_ARRAY_PROTOTYPE_KEYS, + ECMA_ARRAY_PROTOTYPE_SYMBOL_ITERATOR, + ECMA_ARRAY_PROTOTYPE_FILL, + ECMA_ARRAY_PROTOTYPE_COPY_WITHIN, + ECMA_ARRAY_PROTOTYPE_INCLUDES, + ECMA_ARRAY_PROTOTYPE_FLAT, + ECMA_ARRAY_PROTOTYPE_FLATMAP, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup arrayprototype ECMA Array.prototype object built-in + * @{ + */ + +/** + * Helper function to set an object's length property + * + * @return ecma value (return value of the [[Put]] method) + * Calling ecma_free_value on the returned value is optional if it is not abrupt completion. + */ +static ecma_value_t +ecma_builtin_array_prototype_helper_set_length (ecma_object_t *object, /**< object*/ + ecma_number_t length) /**< new length */ +{ + ecma_value_t length_value = ecma_make_number_value (length); + ecma_value_t ret_value = + ecma_op_object_put (object, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), length_value, true); + + ecma_free_value (length_value); + + JERRY_ASSERT (ecma_is_value_boolean (ret_value) || ecma_is_value_empty (ret_value) + || ECMA_IS_VALUE_ERROR (ret_value)); + return ret_value; +} /* ecma_builtin_array_prototype_helper_set_length */ + +/** + * The Array.prototype object's 'toLocaleString' routine + * + * See also: + * ECMA-262 v5, 15.4.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_to_locale_string (ecma_object_t *obj_p, /**< object */ + ecma_length_t length) /**< object's length */ +{ + /* 5. */ + if (length == 0) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + /* 7-8. */ + ecma_string_t *first_string_p = ecma_builtin_helper_get_to_locale_string_at_index (obj_p, 0); + + if (JERRY_UNLIKELY (first_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (first_string_p); + ecma_deref_ecma_string (first_string_p); + + /* 9-10. */ + for (ecma_length_t k = 1; k < length; k++) + { + /* 4. Implementation-defined: set the separator to a single comma character. */ + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_COMMA); + + ecma_string_t *next_string_p = ecma_builtin_helper_get_to_locale_string_at_index (obj_p, k); + + if (JERRY_UNLIKELY (next_string_p == NULL)) + { + ecma_stringbuilder_destroy (&builder); + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_append (&builder, next_string_p); + ecma_deref_ecma_string (next_string_p); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_array_prototype_object_to_locale_string */ + +/** + * The Array.prototype object's 'concat' routine + * + * See also: + * ECMA-262 v5, 15.4.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_concat (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p) /**< array object */ +{ + /* 2. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, 0); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + ecma_length_t new_length = 0; + + /* 5.b - 5.c for this_arg */ + ecma_value_t concat_this_value = + ecma_builtin_helper_array_concat_value (new_array_p, &new_length, ecma_make_object_value (obj_p)); + if (ECMA_IS_VALUE_ERROR (concat_this_value)) + { + ecma_deref_object (new_array_p); + return concat_this_value; + } + + JERRY_ASSERT (ecma_is_value_empty (concat_this_value)); + + /* 5. */ + for (uint32_t arg_index = 0; arg_index < args_number; arg_index++) + { + ecma_value_t concat_value = ecma_builtin_helper_array_concat_value (new_array_p, &new_length, args[arg_index]); + + if (ECMA_IS_VALUE_ERROR (concat_value)) + { + ecma_deref_object (new_array_p); + return concat_value; + } + + JERRY_ASSERT (ecma_is_value_empty (concat_value)); + } + + ecma_value_t set_length_value = + ecma_builtin_array_prototype_helper_set_length (new_array_p, ((ecma_number_t) new_length)); + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + ecma_deref_object (new_array_p); + return set_length_value; + } + + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_concat */ + +/** + * The Array.prototype.toString's separator creation routine + * + * See also: + * ECMA-262 v5.1, 15.4.4.2 4th step + * + * @return NULL - if the conversion fails + * ecma_string_t * - otherwise + */ + +static ecma_string_t * +ecma_op_array_get_separator_string (ecma_value_t separator) /**< possible separator */ +{ + if (ecma_is_value_undefined (separator)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR); + } + + return ecma_op_to_string (separator); +} /* ecma_op_array_get_separator_string */ + +/** + * The Array.prototype's 'toString' single element operation routine + * + * See also: + * ECMA-262 v5.1, 15.4.4.2 + * + * @return NULL - if the conversion fails + * ecma_string_t * - otherwise + */ +static ecma_string_t * +ecma_op_array_get_to_string_at_index (ecma_object_t *obj_p, /**< this object */ + ecma_length_t index) /**< array index */ +{ + ecma_value_t index_value = ecma_op_object_get_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (index_value)) + { + return NULL; + } + + if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_string_t *ret_str_p = ecma_op_to_string (index_value); + + ecma_free_value (index_value); + + return ret_str_p; +} /* ecma_op_array_get_to_string_at_index */ + +/** + * The Array.prototype object's 'join' routine + * + * See also: + * ECMA-262 v5, 15.4.4.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_join (ecma_value_t separator_arg, /**< separator argument */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t length) /**< object's length */ +{ + /* 4-5. */ + ecma_string_t *separator_string_p = ecma_op_array_get_separator_string (separator_arg); + + if (JERRY_UNLIKELY (separator_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + if (length == 0) + { + /* 6. */ + ecma_deref_ecma_string (separator_string_p); + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + /* 7-8. */ + ecma_string_t *first_string_p = ecma_op_array_get_to_string_at_index (obj_p, 0); + + if (JERRY_UNLIKELY (first_string_p == NULL)) + { + ecma_deref_ecma_string (separator_string_p); + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (first_string_p); + ecma_deref_ecma_string (first_string_p); + + /* 9-10. */ + for (ecma_length_t k = 1; k < length; k++) + { + /* 10.a */ + ecma_stringbuilder_append (&builder, separator_string_p); + + /* 10.d */ + ecma_string_t *next_string_p = ecma_op_array_get_to_string_at_index (obj_p, k); + + if (JERRY_UNLIKELY (next_string_p == NULL)) + { + ecma_deref_ecma_string (separator_string_p); + ecma_stringbuilder_destroy (&builder); + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_append (&builder, next_string_p); + ecma_deref_ecma_string (next_string_p); + } + + ecma_deref_ecma_string (separator_string_p); + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_array_prototype_join */ + +/** + * The Array.prototype object's 'pop' routine + * + * See also: + * ECMA-262 v5, 15.4.4.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_pop (ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (len == 0) + { + /* 4.a */ + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ECMA_NUMBER_ZERO); + + /* 4.b */ + return ECMA_IS_VALUE_ERROR (set_length_value) ? set_length_value : ECMA_VALUE_UNDEFINED; + } + + /* 5.b */ + len--; + ecma_value_t get_value = ecma_op_object_get_by_index (obj_p, len); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_delete_fast_array_properties (obj_p, (uint32_t) len); + + return get_value; + } + + /* 5.c */ + ecma_value_t del_value = ecma_op_object_delete_by_index (obj_p, len, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + ecma_free_value (get_value); + return del_value; + } + + ecma_free_value (del_value); + + /* 5.d */ + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) len)); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + ecma_free_value (get_value); + return set_length_value; + } + + return get_value; +} /* ecma_builtin_array_prototype_object_pop */ + +/** + * The Array.prototype object's 'push' routine + * + * See also: + * ECMA-262 v5, 15.4.4.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_push (const ecma_value_t *argument_list_p, /**< arguments list */ + uint32_t arguments_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t length) /**< object's length */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + if ((ecma_number_t) (length + arguments_number) > UINT32_MAX) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + } + + if (arguments_number == 0) + { + return ecma_make_uint32_value ((uint32_t) length); + } + + uint32_t new_length = ((uint32_t) length) + arguments_number; + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + ecma_value_t *buffer_p = ecma_fast_array_extend (obj_p, new_length) + length; + + for (uint32_t index = 0; index < arguments_number; index++) + { + buffer_p[index] = ecma_copy_value_if_not_object (argument_list_p[index]); + } + + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE * arguments_number; + + return ecma_make_uint32_value (new_length); + } + + /* 5. */ + if ((ecma_number_t) (length + arguments_number) > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ecma_raise_type_error (ECMA_ERR_PUSHING_TOO_HIGH_ELEMENT); + } + + /* 6. */ + for (ecma_length_t index = 0; index < arguments_number; index++, length++) + { + /* 6.b */ + ecma_value_t put_value = ecma_op_object_put_by_index (obj_p, length, argument_list_p[index], true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + return put_value; + } + } + + /* 6 - 7. */ + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, (ecma_number_t) length); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + return set_length_value; + } + + return ecma_make_length_value (length); +} /* ecma_builtin_array_prototype_object_push */ + +/** + * The Array.prototype object's 'reverse' routine + * + * See also: + * ECMA-262 v5, 15.4.4.8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this argument */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + uint32_t middle = (uint32_t) len / 2; + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && len != 0) + { + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + for (uint32_t i = 0; i < middle; i++) + { + ecma_value_t tmp = buffer_p[i]; + buffer_p[i] = buffer_p[len - 1 - i]; + buffer_p[len - 1 - i] = tmp; + } + + return ecma_copy_value (this_arg); + } + } + + ecma_length_t middle = len / 2; + for (ecma_length_t lower = 0; lower < middle; lower++) + { + ecma_length_t upper = len - lower - 1; + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + ecma_string_t *lower_str_p = ecma_new_ecma_string_from_length (lower); + ecma_string_t *upper_str_p = ecma_new_ecma_string_from_length (upper); + + ecma_value_t lower_value = ECMA_VALUE_EMPTY; + ecma_value_t upper_value = ECMA_VALUE_EMPTY; + + ecma_value_t has_lower = ecma_op_object_has_property (obj_p, lower_str_p); + ecma_value_t has_upper; + + bool upper_exist; + bool lower_exist; + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (has_lower)) + { + goto clean_up; + } +#endif /* JERRY_BUILTIN_PROXY */ + + lower_exist = ecma_is_value_true (has_lower); + + if (lower_exist) + { + lower_value = ecma_op_object_get (obj_p, lower_str_p); + + if (ECMA_IS_VALUE_ERROR (lower_value)) + { + goto clean_up; + } + } + + has_upper = ecma_op_object_has_property (obj_p, upper_str_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (has_upper)) + { + goto clean_up; + } +#endif /* JERRY_BUILTIN_PROXY */ + + upper_exist = ecma_is_value_true (has_upper); + + if (upper_exist) + { + upper_value = ecma_op_object_get (obj_p, upper_str_p); + + if (ECMA_IS_VALUE_ERROR (upper_value)) + { + goto clean_up; + } + } + + if (lower_exist && upper_exist) + { + ecma_value_t outer_put_value = ecma_op_object_put (obj_p, lower_str_p, upper_value, true); + + if (ECMA_IS_VALUE_ERROR (outer_put_value)) + { + goto clean_up; + } + + ecma_value_t inner_put_value = ecma_op_object_put (obj_p, upper_str_p, lower_value, true); + + if (ECMA_IS_VALUE_ERROR (inner_put_value)) + { + goto clean_up; + } + } + else if (!lower_exist && upper_exist) + { + ecma_value_t put_value = ecma_op_object_put (obj_p, lower_str_p, upper_value, true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + goto clean_up; + } + + ecma_value_t del_value = ecma_op_object_delete (obj_p, upper_str_p, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + goto clean_up; + } + } + else if (lower_exist) + { + ecma_value_t del_value = ecma_op_object_delete (obj_p, lower_str_p, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + goto clean_up; + } + + ecma_value_t put_value = ecma_op_object_put (obj_p, upper_str_p, lower_value, true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + goto clean_up; + } + } + + ret_value = ECMA_VALUE_EMPTY; + +clean_up: + ecma_free_value (upper_value); + ecma_free_value (lower_value); + ecma_deref_ecma_string (lower_str_p); + ecma_deref_ecma_string (upper_str_p); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + } + + return ecma_copy_value (this_arg); +} /* ecma_builtin_array_prototype_object_reverse */ + +/** + * The Array.prototype object's 'shift' routine + * + * See also: + * ECMA-262 v5, 15.4.4.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_shift (ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (len == 0) + { + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ECMA_NUMBER_ZERO); + + return ECMA_IS_VALUE_ERROR (set_length_value) ? set_length_value : ECMA_VALUE_UNDEFINED; + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && len != 0) + { + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + ecma_value_t ret_value = buffer_p[0]; + + if (ecma_is_value_object (ret_value)) + { + ecma_ref_object (ecma_get_object_from_value (ret_value)); + } + + memmove (buffer_p, buffer_p + 1, (size_t) (sizeof (ecma_value_t) * (len - 1))); + + buffer_p[len - 1] = ECMA_VALUE_UNDEFINED; + ecma_delete_fast_array_properties (obj_p, (uint32_t) (len - 1)); + + return ret_value; + } + } + + /* 5. */ + ecma_value_t first_value = ecma_op_object_get_by_index (obj_p, 0); + + if (ECMA_IS_VALUE_ERROR (first_value)) + { + return first_value; + } + + /* 6. and 7. */ + for (ecma_length_t k = 1; k < len; k++) + { + /* 7.a - 7.c */ + ecma_value_t curr_value = ecma_op_object_find_by_index (obj_p, k); + + if (ECMA_IS_VALUE_ERROR (curr_value)) + { + ecma_free_value (first_value); + return curr_value; + } + + /* 7.b */ + ecma_length_t to = k - 1; + ecma_value_t operation_value; + + if (ecma_is_value_found (curr_value)) + { + /* 7.d.i, 7.d.ii */ + operation_value = ecma_op_object_put_by_index (obj_p, to, curr_value, true); + ecma_free_value (curr_value); + } + else + { + /* 7.e.i */ + operation_value = ecma_op_object_delete_by_index (obj_p, to, true); + } + + if (ECMA_IS_VALUE_ERROR (operation_value)) + { + ecma_free_value (first_value); + return operation_value; + } + } + + /* 8. */ + ecma_value_t del_value = ecma_op_object_delete_by_index (obj_p, --len, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + ecma_free_value (first_value); + return del_value; + } + + /* 9. */ + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) len)); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + ecma_free_value (first_value); + return set_length_value; + } + + /* 10. */ + return first_value; +} /* ecma_builtin_array_prototype_object_shift */ + +/** + * The Array.prototype object's 'slice' routine + * + * See also: + * ECMA-262 v5, 15.4.4.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_slice (ecma_value_t arg1, /**< start */ + ecma_value_t arg2, /**< end */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + ecma_length_t start = 0, end = len; + + /* 5. 6.*/ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (arg1, len, &start))) + { + return ECMA_VALUE_ERROR; + } + + /* 7. */ + if (ecma_is_value_undefined (arg2)) + { + end = len; + } + else + { + /* 7. part 2, 8.*/ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (arg2, len, &end))) + { + return ECMA_VALUE_ERROR; + } + } + + JERRY_ASSERT (start <= len && end <= len); + + bool use_fast_path = ecma_op_object_is_fast_array (obj_p); + ecma_length_t copied_length = (end > start) ? end - start : 0; + + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, copied_length); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + use_fast_path &= ecma_op_object_is_fast_array (new_array_p); + + if (use_fast_path && copied_length > 0) + { + ecma_extended_object_t *ext_from_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_from_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + { + if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) + { + /** + * Very unlikely case: the buffer copied from is a fast buffer and the property list was deleted. + * There is no need to do any copy. + */ + return ecma_make_object_value (new_array_p); + } + + /* Source array's length could be changed during the start/end normalization. + * If the "end" value is greater than the current length, clamp the value to avoid buffer-overflow. */ + if (ext_from_obj_p->u.array.length < end) + { + end = ext_from_obj_p->u.array.length; + } + + ecma_extended_object_t *ext_to_obj_p = (ecma_extended_object_t *) new_array_p; + + uint32_t target_length = ext_to_obj_p->u.array.length; + ecma_value_t *to_buffer_p; + JERRY_ASSERT (copied_length <= UINT32_MAX); + + if (copied_length == target_length) + { + to_buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, new_array_p->u1.property_list_cp); + } + else if (copied_length > target_length) + { + to_buffer_p = ecma_fast_array_extend (new_array_p, (uint32_t) copied_length); + } + else + { + ecma_delete_fast_array_properties (new_array_p, (uint32_t) copied_length); + to_buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, new_array_p->u1.property_list_cp); + } + + ecma_value_t *from_buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + /* 9. */ + uint32_t n = 0; + + for (uint32_t k = (uint32_t) start; k < (uint32_t) end; k++, n++) + { + ecma_free_value_if_not_object (to_buffer_p[n]); + to_buffer_p[n] = ecma_copy_value_if_not_object (from_buffer_p[k]); + } + + ext_to_obj_p->u.array.length_prop_and_hole_count &= ECMA_FAST_ARRAY_HOLE_ONE - 1; + + return ecma_make_object_value (new_array_p); + } + } + + /* 9. */ + ecma_length_t n = 0; + + /* 10. */ + for (ecma_length_t k = start; k < end; k++, n++) + { + /* 10.c */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, k); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + ecma_deref_object (new_array_p); + return get_value; + } + + if (ecma_is_value_found (get_value)) + { + /* 10.c.ii */ + ecma_value_t put_comp; + put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + n, + get_value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE + | JERRY_PROP_SHOULD_THROW); + ecma_free_value (get_value); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + ecma_deref_object (new_array_p); + return put_comp; + } + } + } + + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (new_array_p, ((ecma_number_t) n)); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + ecma_deref_object (new_array_p); + return set_length_value; + } + + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_slice */ + +/** + * SortCompare abstract method + * + * See also: + * ECMA-262 v5, 15.4.4.11 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_sort_compare_helper (ecma_value_t lhs, /**< left value */ + ecma_value_t rhs, /**< right value */ + ecma_value_t compare_func, /**< compare function */ + ecma_object_t *array_buffer_p) /**< arrayBuffer */ +{ + JERRY_UNUSED (array_buffer_p); + /* + * ECMA-262 v5, 15.4.4.11 NOTE1: Because non-existent property values always + * compare greater than undefined property values, and undefined always + * compares greater than any other value, undefined property values always + * sort to the end of the result, followed by non-existent property values. + */ + bool lhs_is_undef = ecma_is_value_undefined (lhs); + bool rhs_is_undef = ecma_is_value_undefined (rhs); + + if (lhs_is_undef) + { + return ecma_make_integer_value (rhs_is_undef ? 0 : 1); + } + + if (rhs_is_undef) + { + return ecma_make_integer_value (-1); + } + + ecma_number_t result = ECMA_NUMBER_ZERO; + + if (ecma_is_value_undefined (compare_func)) + { + /* Default comparison when no compare_func is passed. */ + ecma_string_t *lhs_str_p = ecma_op_to_string (lhs); + if (JERRY_UNLIKELY (lhs_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_string_t *rhs_str_p = ecma_op_to_string (rhs); + if (JERRY_UNLIKELY (rhs_str_p == NULL)) + { + ecma_deref_ecma_string (lhs_str_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_compare_ecma_strings_relational (lhs_str_p, rhs_str_p)) + { + result = ECMA_NUMBER_MINUS_ONE; + } + else if (!ecma_compare_ecma_strings (lhs_str_p, rhs_str_p)) + { + result = ECMA_NUMBER_ONE; + } + else + { + result = ECMA_NUMBER_ZERO; + } + + ecma_deref_ecma_string (rhs_str_p); + ecma_deref_ecma_string (lhs_str_p); + } + else + { + /* + * compare_func, if not undefined, will always contain a callable function object. + * We checked this previously, before this function was called. + */ + JERRY_ASSERT (ecma_op_is_callable (compare_func)); + ecma_object_t *comparefn_obj_p = ecma_get_object_from_value (compare_func); + + ecma_value_t compare_args[] = { lhs, rhs }; + + ecma_value_t call_value = ecma_op_function_call (comparefn_obj_p, ECMA_VALUE_UNDEFINED, compare_args, 2); + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + if (!ecma_is_value_number (call_value)) + { + ecma_number_t ret_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (call_value, &ret_num))) + { + ecma_free_value (call_value); + return ECMA_VALUE_ERROR; + } + + result = ret_num; + } + else + { + result = ecma_get_number_from_value (call_value); + } + + ecma_free_value (call_value); + } + + return ecma_make_number_value (result); +} /* ecma_builtin_array_prototype_object_sort_compare_helper */ + +/** + * The Array.prototype object's 'sort' routine + * + * See also: + * ECMA-262 v5, 15.4.4.11 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg1, /**< comparefn */ + ecma_object_t *obj_p) /**< object */ +{ + /* Check if the provided compare function is callable. */ + if (!ecma_is_value_undefined (arg1) && !ecma_op_is_callable (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_COMPARE_FUNC_NOT_CALLABLE); + } + + ecma_length_t len; + ecma_value_t len_value = ecma_op_object_get_length (obj_p, &len); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + return len_value; + } + ecma_collection_t *array_index_props_p = ecma_new_collection (); + + for (uint32_t i = 0; i < len; i++) + { + ecma_string_t *prop_name_p = ecma_new_ecma_string_from_uint32 (i); + + ecma_property_descriptor_t prop_desc; + ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (obj_p, prop_name_p, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (get_desc)) + { + ecma_collection_free (array_index_props_p); + ecma_deref_ecma_string (prop_name_p); + return get_desc; + } + + if (ecma_is_value_true (get_desc)) + { + ecma_ref_ecma_string (prop_name_p); + ecma_collection_push_back (array_index_props_p, ecma_make_string_value (prop_name_p)); + ecma_free_property_descriptor (&prop_desc); + continue; + } + } + + uint32_t defined_prop_count = array_index_props_p->item_count; + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + uint32_t copied_num = 0; + JMEM_DEFINE_LOCAL_ARRAY (values_buffer, defined_prop_count, ecma_value_t); + + ecma_value_t *buffer_p = array_index_props_p->buffer_p; + + /* Copy unsorted array into a native c array. */ + for (uint32_t i = 0; i < array_index_props_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]); + + uint32_t index = ecma_string_get_array_index (property_name_p); + JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); + + if (index >= len) + { + break; + } + + ecma_value_t index_value = ecma_op_object_get (obj_p, property_name_p); + + if (ECMA_IS_VALUE_ERROR (index_value)) + { + goto clean_up; + } + + values_buffer[copied_num++] = index_value; + } + + JERRY_ASSERT (copied_num == defined_prop_count); + + /* Sorting. */ + if (copied_num > 1) + { + const ecma_builtin_helper_sort_compare_fn_t sort_cb = &ecma_builtin_array_prototype_object_sort_compare_helper; + ecma_value_t sort_value = + ecma_builtin_helper_array_merge_sort_helper (values_buffer, (uint32_t) (copied_num), arg1, sort_cb, NULL); + if (ECMA_IS_VALUE_ERROR (sort_value)) + { + goto clean_up; + } + + ecma_free_value (sort_value); + } + + /* Put sorted values to the front of the array. */ + for (uint32_t index = 0; index < copied_num; index++) + { + ecma_value_t put_value = ecma_op_object_put_by_index (obj_p, index, values_buffer[index], true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + goto clean_up; + } + } + + ret_value = ECMA_VALUE_EMPTY; + +clean_up: + /* Free values that were copied to the local array. */ + for (uint32_t index = 0; index < copied_num; index++) + { + ecma_free_value (values_buffer[index]); + } + + JMEM_FINALIZE_LOCAL_ARRAY (values_buffer); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_collection_free (array_index_props_p); + return ret_value; + } + + JERRY_ASSERT (ecma_is_value_empty (ret_value)); + + /* Undefined properties should be in the back of the array. */ + ecma_value_t *buffer_p = array_index_props_p->buffer_p; + + for (uint32_t i = 0; i < array_index_props_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]); + + uint32_t index = ecma_string_get_array_index (property_name_p); + JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); + + if (index >= copied_num && index < len) + { + ecma_value_t del_value = ecma_op_object_delete (obj_p, property_name_p, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + ecma_collection_free (array_index_props_p); + return del_value; + } + } + } + + ecma_collection_free (array_index_props_p); + + return ecma_copy_value (this_arg); +} /* ecma_builtin_array_prototype_object_sort */ + +/** + * The Array.prototype object's 'splice' routine + * + * See also: + * ECMA-262 v11, 22.1.3.28 + * ECMA-262 v5, 15.4.4.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_splice (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + ecma_length_t actual_start = 0; + ecma_length_t actual_delete_count = 0; + ecma_length_t insert_count = 0; + + if (args_number > 0) + { + /* ES5.1: 6, ES11: 4. */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[0], len, &actual_start))) + { + return ECMA_VALUE_ERROR; + } + + /* ES11: 6. */ + if (args_number == 1) + { + actual_delete_count = len - actual_start; + } + /* ES11: 7. */ + else + { + insert_count = args_number - 2; + + ecma_number_t delete_num; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &delete_num))) + { + return ECMA_VALUE_ERROR; + } + + /* ES5.1: 7 */ + actual_delete_count = + (ecma_length_t) (JERRY_MIN (JERRY_MAX (delete_num, 0), (ecma_number_t) (len - actual_start))); + } + } + + ecma_length_t new_length = len + insert_count - actual_delete_count; + + /* ES11: 8. */ + if ((ecma_number_t) new_length > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ecma_raise_type_error (ECMA_ERR_INVALID_NEW_ARRAY_LENGTH); + } + + /* ES11: 9. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, actual_delete_count); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* ES5.1: 8, ES11: 10. */ + ecma_length_t k = 0; + + /* ES5.1: 9, ES11: 11. */ + for (; k < actual_delete_count; k++) + { + ecma_length_t from = actual_start + k; + ecma_value_t from_present = ecma_op_object_find_by_index (obj_p, from); + + if (ECMA_IS_VALUE_ERROR (from_present)) + { + ecma_deref_object (new_array_p); + return from_present; + } + + if (ecma_is_value_found (from_present)) + { + ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + k, + from_present, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE + | JERRY_PROP_SHOULD_THROW); + ecma_free_value (from_present); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + ecma_deref_object (new_array_p); + return put_comp; + } + } + } + + /* ES11: 12. */ + ecma_value_t set_length = + ecma_builtin_array_prototype_helper_set_length (new_array_p, ((ecma_number_t) actual_delete_count)); + + if (ECMA_IS_VALUE_ERROR (set_length)) + { + ecma_deref_object (new_array_p); + return set_length; + } + + /* ES5.1: 12, ES11: 15. */ + if (insert_count < actual_delete_count) + { + for (k = actual_start; k < len - actual_delete_count; k++) + { + ecma_length_t from = k + actual_delete_count; + ecma_length_t to = k + insert_count; + + ecma_value_t from_present = ecma_op_object_find_by_index (obj_p, from); + + if (ECMA_IS_VALUE_ERROR (from_present)) + { + ecma_deref_object (new_array_p); + return from_present; + } + + ecma_value_t operation_value; + + if (ecma_is_value_found (from_present)) + { + operation_value = ecma_op_object_put_by_index (obj_p, to, from_present, true); + ecma_free_value (from_present); + } + else + { + operation_value = ecma_op_object_delete_by_index (obj_p, to, true); + } + + if (ECMA_IS_VALUE_ERROR (operation_value)) + { + ecma_deref_object (new_array_p); + return operation_value; + } + } + + k = len; + + for (k = len; k > new_length; k--) + { + ecma_value_t del_value = ecma_op_object_delete_by_index (obj_p, k - 1, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + ecma_deref_object (new_array_p); + return del_value; + } + } + } + /* ES5.1: 13, ES11: 16. */ + else if (insert_count > actual_delete_count) + { + for (k = len - actual_delete_count; k > actual_start; k--) + { + ecma_length_t from = k + actual_delete_count - 1; + ecma_length_t to = k + insert_count - 1; + + ecma_value_t from_present = ecma_op_object_find_by_index (obj_p, from); + + if (ECMA_IS_VALUE_ERROR (from_present)) + { + ecma_deref_object (new_array_p); + return from_present; + } + + ecma_value_t operation_value; + + if (ecma_is_value_found (from_present)) + { + operation_value = ecma_op_object_put_by_index (obj_p, to, from_present, true); + ecma_free_value (from_present); + } + else + { + operation_value = ecma_op_object_delete_by_index (obj_p, to, true); + } + + if (ECMA_IS_VALUE_ERROR (operation_value)) + { + ecma_deref_object (new_array_p); + return operation_value; + } + } + } + + /* ES5.1: 14, ES11: 17. */ + k = actual_start; + + /* ES5.1: 15, ES11: 18. */ + uint32_t idx = 0; + for (uint32_t arg_index = 2; arg_index < args_number; arg_index++, idx++) + { + ecma_value_t put_value = ecma_op_object_put_by_index (obj_p, actual_start + idx, args[arg_index], true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + ecma_deref_object (new_array_p); + return put_value; + } + } + + /* ES5.1: 16, ES11: 19. */ + ecma_value_t set_new_length = ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) new_length)); + + if (ECMA_IS_VALUE_ERROR (set_new_length)) + { + ecma_deref_object (new_array_p); + return set_new_length; + } + + /* ES5.1: 17, ES11: 20. */ + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_splice */ + +/** + * The Array.prototype object's 'unshift' routine + * + * See also: + * ECMA-262 v5, 15.4.4.13 + * ECMA-262 v11, 22.1.3.31 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_unshift (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && len != 0) + { + if (args_number > UINT32_MAX - len) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + } + + if (args_number == 0) + { + return ecma_make_uint32_value ((uint32_t) len); + } + + uint32_t new_length = ((uint32_t) len) + args_number; + ecma_value_t *buffer_p = ecma_fast_array_extend (obj_p, new_length); + memmove (buffer_p + args_number, buffer_p, (size_t) (sizeof (ecma_value_t) * len)); + + uint32_t index = 0; + + while (index < args_number) + { + buffer_p[index] = ecma_copy_value_if_not_object (args[index]); + index++; + } + + ext_obj_p->u.array.length_prop_and_hole_count -= args_number * ECMA_FAST_ARRAY_HOLE_ONE; + + return ecma_make_uint32_value (new_length); + } + } + + if (args_number > 0) + { + /* ES11:4.a. */ + if ((ecma_number_t) (len + args_number) > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ecma_raise_type_error (ECMA_ERR_UNSHIFT_TOO_HIGH); + } + + /* ES5.1:5.,6. ES11: 4.b, 4.c */ + for (ecma_length_t k = len; k > 0; k--) + { + /* ES5.1:6.a, 6.c, ES11:4.c.i., 4.c.iii. */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, k - 1); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + /* ES5.1:6.b, ES11:4.c.ii. */ + ecma_number_t new_idx = ((ecma_number_t) k) + ((ecma_number_t) args_number) - 1; + ecma_string_t *index_str_p = ecma_new_ecma_string_from_number (new_idx); + ecma_value_t operation_value; + + if (ecma_is_value_found (get_value)) + { + /* ES5.1:6.d.i, 6.d.ii, ES11:4.c.iv. */ + operation_value = ecma_op_object_put (obj_p, index_str_p, get_value, true); + ecma_free_value (get_value); + } + else + { + /* ES5.1:6.e.i, ES11:4.c.v. */ + operation_value = ecma_op_object_delete (obj_p, index_str_p, true); + } + + ecma_deref_ecma_string (index_str_p); + + if (ECMA_IS_VALUE_ERROR (operation_value)) + { + return operation_value; + } + } + + for (uint32_t arg_index = 0; arg_index < args_number; arg_index++) + { + /* ES5.1:9.b, ES11:4.f.ii. */ + ecma_value_t put_value = ecma_op_object_put_by_index (obj_p, arg_index, args[arg_index], true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + return put_value; + } + } + } + + /* ES5.1:10., ES11:5. */ + ecma_number_t new_len = ((ecma_number_t) len) + ((ecma_number_t) args_number); + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, new_len); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + return set_length_value; + } + + return ecma_make_number_value (new_len); +} /* ecma_builtin_array_prototype_object_unshift */ + +/** + * The Array.prototype object's 'at' routine + * + * See also: + * ECMA-262 Stage 3 Draft Relative Indexing Method proposal + * from: https://tc39.es/proposal-relative-indexing-method + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_at (const ecma_value_t index, /**< index argument */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + ecma_length_t res_index; + ecma_value_t return_value = ecma_builtin_helper_calculate_index (index, len, &res_index); + + if (return_value != ECMA_VALUE_EMPTY) + { + return return_value; + } + + return ecma_op_object_get_by_index (obj_p, res_index); +} /* ecma_builtin_array_prototype_object_at */ + +/** + * The Array.prototype object's 'indexOf' routine + * + * See also: + * ECMA-262 v5, 15.4.4.14 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_index_of (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (len == 0) + { + return ecma_make_integer_value (-1); + } + + /* 5. */ + ecma_number_t idx = 0; + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &idx))) + { + return ECMA_VALUE_ERROR; + } + } + + /* 6. */ + if (idx >= (ecma_number_t) len) + { + return ecma_make_number_value (-1); + } + + /* 7. */ + ecma_length_t from_idx = (ecma_length_t) idx; + + /* 8. */ + if (idx < 0) + { + from_idx = (ecma_length_t) JERRY_MAX ((ecma_number_t) len + idx, 0); + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + { + if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) + { + return ecma_make_integer_value (-1); + } + + len = JERRY_MIN (ext_obj_p->u.array.length, len); + + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + while (from_idx < len) + { + if (ecma_op_strict_equality_compare (args[0], buffer_p[from_idx])) + { + return ecma_make_uint32_value ((uint32_t) from_idx); + } + + from_idx++; + } + + return ecma_make_integer_value (-1); + } + } + + /* 6. */ + while (from_idx < len) + { + /* 9.a */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, from_idx); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + /* 9.b.i, 9.b.ii */ + if (ecma_is_value_found (get_value) && ecma_op_strict_equality_compare (args[0], get_value)) + { + ecma_free_value (get_value); + return ecma_make_length_value (from_idx); + } + + from_idx++; + + ecma_free_value (get_value); + } + + return ecma_make_integer_value (-1); +} /* ecma_builtin_array_prototype_object_index_of */ + +/** + * The Array.prototype object's 'lastIndexOf' routine + * + * See also: + * ECMA-262 v5, 15.4.4.15 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_last_index_of (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (len == 0) + { + return ecma_make_integer_value (-1); + } + + /* 5. */ + ecma_number_t idx = (ecma_number_t) len - 1; + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &idx))) + { + return ECMA_VALUE_ERROR; + } + } + + ecma_length_t from_idx; + + /* 6 */ + if (idx >= 0) + { + from_idx = (ecma_length_t) (JERRY_MIN (idx, (ecma_number_t) (len - 1))); + } + else + { + ecma_number_t k = (ecma_number_t) len + idx; + if (k < 0) + { + return ecma_make_integer_value (-1); + } + from_idx = (ecma_length_t) k; + } + + ecma_value_t search_element = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED; + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + { + if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) + { + return ecma_make_integer_value (-1); + } + + len = JERRY_MIN (ext_obj_p->u.array.length, len); + + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + while (from_idx < len) + { + if (ecma_op_strict_equality_compare (search_element, buffer_p[from_idx])) + { + return ecma_make_uint32_value ((uint32_t) from_idx); + } + from_idx--; + } + return ecma_make_integer_value (-1); + } + } + + /* 8. */ + while (from_idx < len) + { + /* 8.a */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, from_idx); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + /* 8.b.i, 8.b.ii */ + if (ecma_is_value_found (get_value) && ecma_op_strict_equality_compare (search_element, get_value)) + { + ecma_free_value (get_value); + return ecma_make_length_value (from_idx); + } + + from_idx--; + + ecma_free_value (get_value); + } + + return ecma_make_integer_value (-1); +} /* ecma_builtin_array_prototype_object_last_index_of */ + +/** + * Type of array routine. + */ +typedef enum +{ + ARRAY_ROUTINE_EVERY, /**< Array.every: ECMA-262 v5, 15.4.4.16 */ + ARRAY_ROUTINE_SOME, /**< Array.some: ECMA-262 v5, 15.4.4.17 */ + ARRAY_ROUTINE_FOREACH, /**< Array.forEach: ECMA-262 v5, 15.4.4.18 */ + ARRAY_ROUTINE__COUNT /**< count of the modes */ +} array_routine_mode; + +/** + * Applies the provided function to each element of the array as long as + * the return value stays empty. The common function for 'every', 'some' + * and 'forEach' of the Array prototype. + * + * See also: + * ECMA-262 v5, 15.4.4.16 + * ECMA-262 v5, 15.4.4.17 + * ECMA-262 v5, 15.4.4.18 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_apply (ecma_value_t arg1, /**< callbackfn */ + ecma_value_t arg2, /**< thisArg */ + array_routine_mode mode, /**< array routine mode */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ + +{ + JERRY_ASSERT (mode < ARRAY_ROUTINE__COUNT); + + /* 4. */ + if (!ecma_op_is_callable (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* We already checked that arg1 is callable */ + ecma_object_t *func_object_p = ecma_get_object_from_value (arg1); + ecma_value_t current_index; + + /* 7. */ + for (ecma_length_t index = 0; index < len; index++) + { + /* 7.a - 7.c */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + if (ecma_is_value_found (get_value)) + { + /* 7.c.i */ + current_index = ecma_make_length_value (index); + + ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; + /* 7.c.ii */ + ecma_value_t call_value = ecma_op_function_call (func_object_p, arg2, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ecma_free_value (get_value); + return call_value; + } + + bool to_boolean = ecma_op_to_boolean (call_value); + + ecma_free_value (call_value); + ecma_free_value (get_value); + + /* 7.c.iii */ + if (mode == ARRAY_ROUTINE_EVERY && !to_boolean) + { + return ECMA_VALUE_FALSE; + } + else if (mode == ARRAY_ROUTINE_SOME && to_boolean) + { + return ECMA_VALUE_TRUE; + } + } + } + + /* 8. */ + + if (mode == ARRAY_ROUTINE_EVERY) + { + return ECMA_VALUE_TRUE; + } + else if (mode == ARRAY_ROUTINE_SOME) + { + return ECMA_VALUE_FALSE; + } + + JERRY_ASSERT (mode == ARRAY_ROUTINE_FOREACH); + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_array_apply */ + +/** + * The Array.prototype object's 'map' routine + * + * See also: + * ECMA-262 v5, 15.4.4.19 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_map (ecma_value_t arg1, /**< callbackfn */ + ecma_value_t arg2, /**< thisArg */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (!ecma_op_is_callable (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* 6. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, len); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + JERRY_ASSERT (ecma_is_value_object (arg1)); + ecma_object_t *func_object_p = ecma_get_object_from_value (arg1); + + /* 7-8. */ + ecma_value_t current_index; + + for (ecma_length_t index = 0; index < len; index++) + { + /* 8.a - 8.b */ + ecma_value_t current_value = ecma_op_object_find_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (current_value)) + { + ecma_deref_object (new_array_p); + return current_value; + } + + if (ecma_is_value_found (current_value)) + { + /* 8.c.i, 8.c.ii */ + current_index = ecma_make_length_value (index); + ecma_value_t call_args[] = { current_value, current_index, ecma_make_object_value (obj_p) }; + + ecma_value_t mapped_value = ecma_op_function_call (func_object_p, arg2, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (mapped_value)) + { + ecma_free_value (current_value); + ecma_deref_object (new_array_p); + return mapped_value; + } + + /* 8.c.iii */ + ecma_value_t put_comp; + put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + index, + mapped_value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE + | JERRY_PROP_SHOULD_THROW); + + ecma_free_value (mapped_value); + ecma_free_value (current_value); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + ecma_deref_object (new_array_p); + return put_comp; + } + } + } + + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_map */ + +/** + * The Array.prototype object's 'filter' routine + * + * See also: + * ECMA-262 v5, 15.4.4.20 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_filter (ecma_value_t arg1, /**< callbackfn */ + ecma_value_t arg2, /**< thisArg */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (!ecma_op_is_callable (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* 6. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, 0); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* ES11: 22.1.3.7. 7.c.iii.1 */ + const uint32_t prop_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + + /* We already checked that arg1 is callable, so it will always be an object. */ + JERRY_ASSERT (ecma_is_value_object (arg1)); + ecma_object_t *func_object_p = ecma_get_object_from_value (arg1); + + /* 8. */ + ecma_length_t new_array_index = 0; + ecma_value_t current_index; + + /* 9. */ + for (ecma_length_t index = 0; index < len; index++) + { + /* 9.a - 9.c */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + ecma_deref_object (new_array_p); + return get_value; + } + + if (ecma_is_value_found (get_value)) + { + /* 9.c.i */ + current_index = ecma_make_length_value (index); + + ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; + /* 9.c.ii */ + ecma_value_t call_value = ecma_op_function_call (func_object_p, arg2, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ecma_free_value (get_value); + ecma_deref_object (new_array_p); + return call_value; + } + + /* 9.c.iii */ + if (ecma_op_to_boolean (call_value)) + { + ecma_value_t put_comp; + put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, new_array_index, get_value, prop_flags); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + ecma_free_value (call_value); + ecma_free_value (get_value); + ecma_deref_object (new_array_p); + + return put_comp; + } + + new_array_index++; + } + + ecma_free_value (call_value); + ecma_free_value (get_value); + } + } + + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_filter */ + +/** + * The Array.prototype object's 'reduce' and 'reduceRight' routine + * + * See also: + * ECMA-262 v5, 15.4.4.21 + * ECMA-262 v5, 15.4.4.22 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_reduce_from (const ecma_value_t args_p[], /**< routine's arguments */ + uint32_t args_number, /**< arguments list length */ + bool start_from_left, /**< whether the reduce starts from left or right */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (!ecma_op_is_callable (args_p[0])) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* 5. */ + if (len == 0 && args_number == 1) + { + return ecma_raise_type_error (ECMA_ERR_REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE); + } + + JERRY_ASSERT (ecma_is_value_object (args_p[0])); + ecma_object_t *func_object_p = ecma_get_object_from_value (args_p[0]); + + ecma_value_t accumulator = ECMA_VALUE_UNDEFINED; + + /* 6. */ + ecma_length_t index = 0; + const ecma_length_t last_index = len - 1; + + /* 7.a */ + if (args_number > 1) + { + accumulator = ecma_copy_value (args_p[1]); + } + else + { + /* 8.a */ + bool k_present = false; + + /* 8.b */ + while (!k_present && index < len) + { + /* 8.b.i */ + k_present = true; + + /* 8.b.ii-iii */ + ecma_value_t current_value = ecma_op_object_find_by_index (obj_p, start_from_left ? index : last_index - index); + + if (ECMA_IS_VALUE_ERROR (current_value)) + { + return current_value; + } + + if (ecma_is_value_found (current_value)) + { + accumulator = current_value; + } + else + { + k_present = false; + } + + /* 8.b.iv */ + index++; + } + + /* 8.c */ + if (!k_present) + { + return ecma_raise_type_error (ECMA_ERR_MISSING_ARRAY_ELEMENT); + } + } + /* 9. */ + ecma_value_t current_index; + + for (; index < len; index++) + { + const ecma_length_t corrected_index = start_from_left ? index : last_index - index; + + /* 9.a - 9.b */ + ecma_value_t current_value = ecma_op_object_find_by_index (obj_p, corrected_index); + + if (ECMA_IS_VALUE_ERROR (current_value)) + { + ecma_free_value (accumulator); + return current_value; + } + + if (ecma_is_value_found (current_value)) + { + /* 9.c.i, 9.c.ii */ + current_index = ecma_make_length_value (corrected_index); + ecma_value_t call_args[] = { accumulator, current_value, current_index, ecma_make_object_value (obj_p) }; + + ecma_value_t call_value = ecma_op_function_call (func_object_p, ECMA_VALUE_UNDEFINED, call_args, 4); + ecma_free_value (current_index); + ecma_free_value (accumulator); + ecma_free_value (current_value); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + accumulator = call_value; + } + } + + return accumulator; +} /* ecma_builtin_array_reduce_from */ + +/** + * The Array.prototype object's 'fill' routine + * + * Note: this method only supports length up to uint32, instead of max_safe_integer + * + * See also: + * ECMA-262 v6, 22.1.3.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_fill (ecma_value_t value, /**< value */ + ecma_value_t start_val, /**< start value */ + ecma_value_t end_val, /**< end value */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + ecma_length_t k, final; + + /* 5. 6. 7. */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (start_val, len, &k))) + { + return ECMA_VALUE_ERROR; + } + + /* 8. */ + if (ecma_is_value_undefined (end_val)) + { + final = len; + } + else + { + /* 8 part 2, 9, 10 */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (end_val, len, &final))) + { + return ECMA_VALUE_ERROR; + } + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + { + if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) + { + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); + } + + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + while (k < final) + { + ecma_free_value_if_not_object (buffer_p[k]); + buffer_p[k] = ecma_copy_value_if_not_object (value); + k++; + } + + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); + } + } + + /* 11. */ + while (k < final) + { + /* 11.a - 11.b */ + ecma_value_t put_val = ecma_op_object_put_by_index (obj_p, k, value, true); + + /* 11. c */ + if (ECMA_IS_VALUE_ERROR (put_val)) + { + return put_val; + } + + /* 11.d */ + k++; + } + + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); +} /* ecma_builtin_array_prototype_fill */ + +/** + * The Array.prototype object's 'find' and 'findIndex' routine + * + * See also: + * ECMA-262 v6, 22.1.3.8 + * ECMA-262 v6, 22.1.3.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_find (ecma_value_t predicate, /**< callback function */ + ecma_value_t predicate_this_arg, /**< this argument for + * invoke predicate */ + bool is_find, /**< true - find routine + * false - findIndex routine */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 5. */ + if (!ecma_op_is_callable (predicate)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* We already checked that predicate is callable, so it will always be an object. */ + JERRY_ASSERT (ecma_is_value_object (predicate)); + ecma_object_t *func_object_p = ecma_get_object_from_value (predicate); + + /* 7 - 8. */ + for (ecma_length_t index = 0; index < len; index++) + { + /* 8.a - 8.c */ + ecma_value_t get_value = ecma_op_object_get_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + /* 8.d - 8.e */ + ecma_value_t current_index = ecma_make_length_value (index); + + ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; + + ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ecma_free_value (get_value); + return call_value; + } + + bool call_value_to_bool = ecma_op_to_boolean (call_value); + + ecma_free_value (call_value); + + if (call_value_to_bool) + { + /* 8.f */ + if (is_find) + { + ecma_free_value (current_index); + return get_value; + } + + ecma_free_value (get_value); + return current_index; + } + + ecma_free_value (get_value); + ecma_free_value (current_index); + } + + /* 9. */ + return is_find ? ECMA_VALUE_UNDEFINED : ecma_make_integer_value (-1); +} /* ecma_builtin_array_prototype_object_find */ + +/** + * The Array.prototype object's 'copyWithin' routine + * + * See also: + * ECMA-262 v6, 22.1.3.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_copy_within (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + if (args_number == 0) + { + return ecma_copy_value (ecma_make_object_value (obj_p)); + } + + /* 5 - 7 */ + ecma_length_t target; + + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[0], len, &target))) + { + return ECMA_VALUE_ERROR; + } + + ecma_length_t start = 0; + ecma_length_t end = len; + + if (args_number > 1) + { + /* 8 - 10 */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[1], len, &start))) + { + return ECMA_VALUE_ERROR; + } + + if (args_number > 2) + { + /* 11 */ + if (ecma_is_value_undefined (args[2])) + { + end = len; + } + else + { + /* 11 part 2, 12, 13 */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[2], len, &end))) + { + return ECMA_VALUE_ERROR; + } + } + } + } + + ecma_length_t count = JERRY_MIN (end - start, len - target); + if (end <= start || len <= target) /* count <= 0 check, but variables are unsigned */ + { + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); + } + + bool forward = true; + + if (start < target && target < start + count) + { + start = start + count - 1; + target = target + count - 1; + forward = false; + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + const uint32_t actual_length = ext_obj_p->u.array.length; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE + && ((forward && (target + count - 1 < actual_length)) || (!forward && (target < actual_length)))) + { + if (obj_p->u1.property_list_cp != JMEM_CP_NULL) + { + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + for (; count > 0; count--) + { + ecma_value_t copy_value = ecma_copy_value_if_not_object (buffer_p[start]); + + ecma_free_value_if_not_object (buffer_p[target]); + + buffer_p[target] = copy_value; + + if (forward) + { + start++; + target++; + } + else + { + start--; + target--; + } + } + } + + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); + } + } + + while (count > 0) + { + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, start); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + ecma_value_t op_value; + + if (ecma_is_value_found (get_value)) + { + op_value = ecma_op_object_put_by_index (obj_p, target, get_value, true); + } + else + { + op_value = ecma_op_object_delete_by_index (obj_p, target, true); + } + + ecma_free_value (get_value); + + if (ECMA_IS_VALUE_ERROR (op_value)) + { + return op_value; + } + + ecma_free_value (op_value); + + if (forward) + { + start++; + target++; + } + else + { + start--; + target--; + } + + count--; + } + + return ecma_copy_value (ecma_make_object_value (obj_p)); +} /* ecma_builtin_array_prototype_object_copy_within */ + +/** + * The Array.prototype object's 'includes' routine + * + * See also: + * ECMA-262 v11, 22.1.3.13 + * + * @return ECMA_VALUE_ERROR -if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the search element is in the array or not + */ +static ecma_value_t +ecma_builtin_array_prototype_includes (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 3. */ + if (len == 0) + { + return ECMA_VALUE_FALSE; + } + + ecma_length_t from_index = 0; + + /* 4-7. */ + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[1], len, &from_index))) + { + return ECMA_VALUE_ERROR; + } + } + + /* Fast array path */ + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + { + if (obj_p->u1.property_list_cp != JMEM_CP_NULL) + { + len = JERRY_MIN (ext_obj_p->u.array.length, len); + + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + while (from_index < len) + { + if (ecma_op_same_value_zero (buffer_p[from_index], args[0], false)) + { + return ECMA_VALUE_TRUE; + } + + from_index++; + } + } + + return ECMA_VALUE_FALSE; + } + } + + /* 8. */ + while (from_index < len) + { + ecma_value_t element = ecma_op_object_get_by_index (obj_p, from_index); + + if (ECMA_IS_VALUE_ERROR (element)) + { + return element; + } + + if (ecma_op_same_value_zero (element, args[0], false)) + { + ecma_free_value (element); + return ECMA_VALUE_TRUE; + } + + ecma_free_value (element); + from_index++; + } + + /* 9. */ + return ECMA_VALUE_FALSE; +} /* ecma_builtin_array_prototype_includes */ + +/** + * Abstract operation: FlattenIntoArray + * + * See also: + * ECMA-262 v10, 22.1.3.10.1 + * + * @return ECMA_VALUE_ERROR -if the operation fails + * ecma value which contains target_index + */ +static ecma_value_t +ecma_builtin_array_flatten_into_array (ecma_value_t target, /**< target will contains source's elements */ + ecma_object_t *source, /**< source object */ + ecma_length_t source_len, /**< source object length */ + ecma_length_t start, /**< remaining recursion depth */ + ecma_number_t depth, /**< start index offset */ + ecma_value_t mapped_value, /**< mapped value */ + ecma_value_t thisArg) /**< this arg */ +{ + ECMA_CHECK_STACK_USAGE (); + + /* 7. */ + ecma_length_t target_index = start; + + /* 9. */ + for (ecma_length_t source_index = 0; source_index < source_len; source_index++) + { + /* a. */ + ecma_value_t element = ecma_op_object_find_by_index (source, source_index); + + if (ECMA_IS_VALUE_ERROR (element)) + { + return element; + } + + if (!ecma_is_value_found (element)) + { + continue; + } + + /* b-c. */ + if (!ecma_is_value_undefined (mapped_value)) + { + /* i-ii. */ + ecma_value_t source_val = ecma_make_length_value (source_index); + ecma_value_t args[] = { element, source_val, ecma_make_object_value (source) }; + ecma_value_t temp_element = ecma_op_function_call (ecma_get_object_from_value (mapped_value), thisArg, args, 3); + + ecma_free_value (element); + ecma_free_value (source_val); + + if (ECMA_IS_VALUE_ERROR (temp_element)) + { + return temp_element; + } + + element = temp_element; + } + + /* iv-v. */ + if (depth > 0) + { + ecma_value_t is_array = ecma_is_value_array (element); + + if (ECMA_IS_VALUE_ERROR (is_array)) + { + ecma_free_value (element); + return is_array; + } + + if (ecma_is_value_true (is_array)) + { + ecma_object_t *element_obj = ecma_get_object_from_value (element); + ecma_length_t element_len; + ecma_value_t len_value = ecma_op_object_get_length (element_obj, &element_len); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (element_obj); + return len_value; + } + + ecma_value_t target_index_val = ecma_builtin_array_flatten_into_array (target, + element_obj, + element_len, + target_index, + depth - 1, + ECMA_VALUE_UNDEFINED, + ECMA_VALUE_UNDEFINED); + + ecma_deref_object (element_obj); + + if (ECMA_IS_VALUE_ERROR (target_index_val)) + { + return target_index_val; + } + + target_index = (ecma_length_t) ecma_get_number_from_value (target_index_val); + continue; + } + } + + /* vi. */ + const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + ecma_value_t element_temp = + ecma_builtin_helper_def_prop_by_index (ecma_get_object_from_value (target), target_index, element, flags); + + ecma_free_value (element); + + if (ECMA_IS_VALUE_ERROR (element_temp)) + { + return element_temp; + } + + target_index++; + } + /* 10. */ + return ecma_make_length_value (target_index); +} /* ecma_builtin_array_flatten_into_array */ + +/** + * The Array.prototype object's 'flat' routine + * + * See also: + * ECMA-262 v10, 22.1.3.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_flat (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< array object */ + ecma_length_t len) /**< array object's length */ +{ + /* 3. */ + ecma_number_t depth_num = 1; + + /* 4. */ + if (args_number > 0 && ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[0], &depth_num))) + { + return ECMA_VALUE_ERROR; + } + + /* 5. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, 0); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 6. */ + ecma_value_t flatten_val = ecma_builtin_array_flatten_into_array (ecma_make_object_value (new_array_p), + obj_p, + len, + 0, + depth_num, + ECMA_VALUE_UNDEFINED, + ECMA_VALUE_UNDEFINED); + + if (ECMA_IS_VALUE_ERROR (flatten_val)) + { + ecma_deref_object (new_array_p); + return flatten_val; + } + + /* 7. */ + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_flat */ + +/** + * The Array.prototype object's 'flatMap' routine + * + * See also: + * ECMA-262 v10, 22.1.3.11 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_flat_map (ecma_value_t callback, /**< callbackFn */ + ecma_value_t this_arg, /**< thisArg */ + ecma_object_t *obj_p, /**< array object */ + ecma_length_t len) /**< array object's length */ +{ + if (!ecma_op_is_callable (callback)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* 4. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, 0); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 5. */ + ecma_value_t flatten_val = + ecma_builtin_array_flatten_into_array (ecma_make_object_value (new_array_p), obj_p, len, 0, 1, callback, this_arg); + if (ECMA_IS_VALUE_ERROR (flatten_val)) + { + ecma_deref_object (new_array_p); + return flatten_val; + } + + /* 6. */ + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_flat_map */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_array_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + ecma_value_t obj_this = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (obj_this)) + { + return obj_this; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); + + if (JERRY_UNLIKELY (builtin_routine_id <= ECMA_ARRAY_PROTOTYPE_CONCAT)) + { + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_SORT) + { + ret_value = ecma_builtin_array_prototype_object_sort (this_arg, arguments_list_p[0], obj_p); + } + else if (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_CONCAT) + { + ret_value = ecma_builtin_array_prototype_object_concat (arguments_list_p, arguments_number, obj_p); + } + + ecma_deref_object (obj_p); + return ret_value; + } + + if (JERRY_UNLIKELY (builtin_routine_id >= ECMA_ARRAY_PROTOTYPE_ENTRIES + && builtin_routine_id <= ECMA_ARRAY_PROTOTYPE_KEYS)) + { + ecma_value_t ret_value; + + if (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_ENTRIES) + { + ret_value = ecma_op_create_array_iterator (obj_p, ECMA_ITERATOR_ENTRIES); + } + else + { + JERRY_ASSERT (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_KEYS); + ret_value = ecma_op_create_array_iterator (obj_p, ECMA_ITERATOR_KEYS); + } + + ecma_deref_object (obj_p); + return ret_value; + } + + ecma_length_t length; + ecma_value_t len_value = ecma_op_object_get_length (obj_p, &length); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (obj_p); + return len_value; + } + + ecma_value_t ret_value; + + switch (builtin_routine_id) + { + case ECMA_ARRAY_PROTOTYPE_TO_LOCALE_STRING: + { + ret_value = ecma_builtin_array_prototype_object_to_locale_string (obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_JOIN: + { + ret_value = ecma_builtin_array_prototype_join (arguments_list_p[0], obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_POP: + { + ret_value = ecma_builtin_array_prototype_object_pop (obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_PUSH: + { + ret_value = ecma_builtin_array_prototype_object_push (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_REVERSE: + { + ret_value = ecma_builtin_array_prototype_object_reverse (this_arg, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_SHIFT: + { + ret_value = ecma_builtin_array_prototype_object_shift (obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_SLICE: + { + ret_value = ecma_builtin_array_prototype_object_slice (arguments_list_p[0], arguments_list_p[1], obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_SPLICE: + { + ret_value = ecma_builtin_array_prototype_object_splice (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_UNSHIFT: + { + ret_value = ecma_builtin_array_prototype_object_unshift (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_AT: + { + ret_value = ecma_builtin_array_prototype_object_at (arguments_list_p[0], obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_INDEX_OF: + { + ret_value = ecma_builtin_array_prototype_object_index_of (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF: + { + ret_value = ecma_builtin_array_prototype_object_last_index_of (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_EVERY: + case ECMA_ARRAY_PROTOTYPE_SOME: + case ECMA_ARRAY_PROTOTYPE_FOR_EACH: + { + ret_value = ecma_builtin_array_apply (arguments_list_p[0], + arguments_list_p[1], + (array_routine_mode) (builtin_routine_id - (uint8_t) ECMA_ARRAY_PROTOTYPE_EVERY), + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_MAP: + { + ret_value = ecma_builtin_array_prototype_object_map (arguments_list_p[0], arguments_list_p[1], obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_REDUCE: + case ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT: + { + ret_value = ecma_builtin_array_reduce_from (arguments_list_p, + arguments_number, + builtin_routine_id == ECMA_ARRAY_PROTOTYPE_REDUCE, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_COPY_WITHIN: + { + ret_value = ecma_builtin_array_prototype_object_copy_within (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_FIND: + case ECMA_ARRAY_PROTOTYPE_FIND_INDEX: + { + ret_value = ecma_builtin_array_prototype_object_find (arguments_list_p[0], + arguments_list_p[1], + builtin_routine_id == ECMA_ARRAY_PROTOTYPE_FIND, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_FILL: + { + ret_value = ecma_builtin_array_prototype_fill (arguments_list_p[0], + arguments_list_p[1], + arguments_list_p[2], + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_INCLUDES: + { + ret_value = ecma_builtin_array_prototype_includes (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_FLAT: + { + ret_value = ecma_builtin_array_prototype_object_flat (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_FLATMAP: + { + ret_value = + ecma_builtin_array_prototype_object_flat_map (arguments_list_p[0], arguments_list_p[1], obj_p, length); + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_FILTER); + + ret_value = ecma_builtin_array_prototype_object_filter (arguments_list_p[0], arguments_list_p[1], obj_p, length); + break; + } + } + + ecma_free_value (len_value); + ecma_deref_object (obj_p); + + return ret_value; +} /* ecma_builtin_array_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h new file mode 100644 index 00000000..19110f78 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h @@ -0,0 +1,85 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Array.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ARRAY + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.4.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 22.1.3.31 */ +OBJECT_VALUE (LIT_GLOBAL_SYMBOL_UNSCOPABLES, + ECMA_BUILTIN_ID_ARRAY_PROTOTYPE_UNSCOPABLES, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Number properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.4.4 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_WRITABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_ARRAY_PROTOTYPE_TO_LOCALE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_CONCAT, ECMA_ARRAY_PROTOTYPE_CONCAT, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_JOIN, ECMA_ARRAY_PROTOTYPE_JOIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_POP, ECMA_ARRAY_PROTOTYPE_POP, 0, 0) +ROUTINE (LIT_MAGIC_STRING_PUSH, ECMA_ARRAY_PROTOTYPE_PUSH, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_REVERSE, ECMA_ARRAY_PROTOTYPE_REVERSE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SHIFT, ECMA_ARRAY_PROTOTYPE_SHIFT, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SLICE, ECMA_ARRAY_PROTOTYPE_SLICE, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SORT, ECMA_ARRAY_PROTOTYPE_SORT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_AT, ECMA_ARRAY_PROTOTYPE_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SPLICE, ECMA_ARRAY_PROTOTYPE_SPLICE, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_UNSHIFT, ECMA_ARRAY_PROTOTYPE_UNSHIFT, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_ARRAY_PROTOTYPE_INDEX_OF, 2, 1) +ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF, NON_FIXED, 1) +/* Note these 3 routines must be in this order */ +ROUTINE (LIT_MAGIC_STRING_EVERY, ECMA_ARRAY_PROTOTYPE_EVERY, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SOME, ECMA_ARRAY_PROTOTYPE_SOME, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_ARRAY_PROTOTYPE_FOR_EACH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_MAP, ECMA_ARRAY_PROTOTYPE_MAP, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FILTER, ECMA_ARRAY_PROTOTYPE_FILTER, 2, 1) +/* Note these 2 routines must be in this order */ +ROUTINE (LIT_MAGIC_STRING_REDUCE, ECMA_ARRAY_PROTOTYPE_REDUCE, 2, 1) +ROUTINE (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FIND, ECMA_ARRAY_PROTOTYPE_FIND, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FIND_INDEX, ECMA_ARRAY_PROTOTYPE_FIND_INDEX, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FILL, ECMA_ARRAY_PROTOTYPE_FILL, 3, 1) +ROUTINE (LIT_MAGIC_STRING_COPY_WITHIN, ECMA_ARRAY_PROTOTYPE_COPY_WITHIN, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_ARRAY_PROTOTYPE_ENTRIES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_ARRAY_PROTOTYPE_KEYS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_INCLUDES, ECMA_ARRAY_PROTOTYPE_INCLUDES, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_FLAT, ECMA_ARRAY_PROTOTYPE_FLAT, 1, 0) +ROUTINE (LIT_MAGIC_STRING_FLATMAP, ECMA_ARRAY_PROTOTYPE_FLATMAP, 2, 1) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_STRING_UL, LIT_MAGIC_STRING_TO_STRING_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_VALUES, + LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_GLOBAL_SYMBOL_ITERATOR, + LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ARRAY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp new file mode 100644 index 00000000..0d88411f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp @@ -0,0 +1,569 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ARRAY_ROUTINE_START = 0, + ECMA_ARRAY_ROUTINE_IS_ARRAY, + ECMA_ARRAY_ROUTINE_FROM, + ECMA_ARRAY_ROUTINE_OF, + ECMA_ARRAY_ROUTINE_SPECIES_GET +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array.inc.h" +#define BUILTIN_UNDERSCORED_ID array +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup array ECMA Array object built-in + * @{ + */ + +/** + * The Array object's 'from' routine + * + * See also: + * ECMA-262 v6, 22.1.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + /* 1. */ + ecma_value_t constructor = this_arg; + ecma_value_t call_this_arg = ECMA_VALUE_UNDEFINED; + ecma_value_t items = arguments_list_p[0]; + ecma_value_t mapfn = (arguments_list_len > 1) ? arguments_list_p[1] : ECMA_VALUE_UNDEFINED; + ecma_length_t k = 0; + ecma_value_t set_status; + + /* 2. */ + ecma_object_t *mapfn_obj_p = NULL; + + /* 3. */ + if (!ecma_is_value_undefined (mapfn)) + { + /* 3.a */ + if (!ecma_op_is_callable (mapfn)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* 3.b */ + if (arguments_list_len > 2) + { + call_this_arg = arguments_list_p[2]; + } + + /* 3.c */ + mapfn_obj_p = ecma_get_object_from_value (mapfn); + } + + /* 4. */ + ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (items, LIT_GLOBAL_SYMBOL_ITERATOR); + + /* 5. */ + if (ECMA_IS_VALUE_ERROR (using_iterator)) + { + return using_iterator; + } + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + /* 6. */ + if (!ecma_is_value_undefined (using_iterator)) + { + ecma_object_t *array_obj_p; + + /* 6.a */ + if (ecma_is_constructor (constructor)) + { + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); + + ecma_value_t array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, NULL, 0); + + if (ecma_is_value_undefined (array) || ecma_is_value_null (array)) + { + ecma_free_value (using_iterator); + return ecma_raise_type_error (ECMA_ERR_CANNOT_CONVERT_TO_OBJECT); + } + + /* 6.c */ + if (ECMA_IS_VALUE_ERROR (array)) + { + ecma_free_value (using_iterator); + return array; + } + + array_obj_p = ecma_get_object_from_value (array); + } + else + { + /* 6.b */ + array_obj_p = ecma_op_new_array_object (0); + } + + /* 6.d */ + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (items, using_iterator, &next_method); + ecma_free_value (using_iterator); + + /* 6.e */ + if (ECMA_IS_VALUE_ERROR (iterator)) + { + ecma_deref_object (array_obj_p); + return iterator; + } + + /* 6.f */ + uint32_t k = 0; + + /* 6.g */ + while (true) + { + /* 6.g.ii */ + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + + /* 6.g.iii */ + if (ECMA_IS_VALUE_ERROR (next)) + { + goto iterator_cleanup; + } + + /* 6.g.iii */ + if (ecma_is_value_false (next)) + { + /* 6.g.iv.1 */ + ecma_value_t len_value = ecma_make_uint32_value (k); + ecma_value_t set_status = + ecma_op_object_put (array_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), len_value, true); + ecma_free_value (len_value); + + /* 6.g.iv.2 */ + if (ECMA_IS_VALUE_ERROR (set_status)) + { + goto iterator_cleanup; + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + /* 6.g.iv.3 */ + return ecma_make_object_value (array_obj_p); + } + + /* 6.g.v */ + ecma_value_t next_value = ecma_op_iterator_value (next); + + ecma_free_value (next); + + /* 6.g.vi */ + if (ECMA_IS_VALUE_ERROR (next_value)) + { + goto iterator_cleanup; + } + + ecma_value_t mapped_value; + /* 6.g.vii */ + if (mapfn_obj_p != NULL) + { + /* 6.g.vii.1 */ + ecma_value_t args_p[2] = { next_value, ecma_make_uint32_value (k) }; + /* 6.g.vii.3 */ + mapped_value = ecma_op_function_call (mapfn_obj_p, call_this_arg, args_p, 2); + ecma_free_value (args_p[1]); + ecma_free_value (next_value); + + /* 6.g.vii.2 */ + if (ECMA_IS_VALUE_ERROR (mapped_value)) + { + ecma_op_iterator_close (iterator); + goto iterator_cleanup; + } + } + else + { + /* 6.g.viii */ + mapped_value = next_value; + } + + /* 6.g.ix */ + const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + ecma_value_t set_status = ecma_builtin_helper_def_prop_by_index (array_obj_p, k, mapped_value, flags); + + ecma_free_value (mapped_value); + + /* 6.g.x */ + if (ECMA_IS_VALUE_ERROR (set_status)) + { + ecma_op_iterator_close (iterator); + goto iterator_cleanup; + } + + /* 6.g.xi */ + k++; + } + +iterator_cleanup: + ecma_free_value (iterator); + ecma_free_value (next_method); + ecma_deref_object (array_obj_p); + + return ret_value; + } + + /* 8. */ + ecma_value_t array_like = ecma_op_to_object (items); + + /* 9. */ + if (ECMA_IS_VALUE_ERROR (array_like)) + { + return array_like; + } + + ecma_object_t *array_like_obj_p = ecma_get_object_from_value (array_like); + + /* 10. */ + ecma_length_t len; + ecma_value_t len_value = ecma_op_object_get_length (array_like_obj_p, &len); + + /* 11. */ + if (ECMA_IS_VALUE_ERROR (len_value)) + { + goto cleanup; + } + + /* 12. */ + ecma_object_t *array_obj_p; + + /* 12.a */ + if (ecma_is_constructor (constructor)) + { + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); + + len_value = ecma_make_length_value (len); + ecma_value_t array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &len_value, 1); + ecma_free_value (len_value); + + if (ecma_is_value_undefined (array) || ecma_is_value_null (array)) + { + ecma_raise_type_error (ECMA_ERR_CANNOT_CONVERT_TO_OBJECT); + goto cleanup; + } + + /* 14. */ + if (ECMA_IS_VALUE_ERROR (array)) + { + goto cleanup; + } + + array_obj_p = ecma_get_object_from_value (array); + } + else + { + /* 13.a */ + array_obj_p = ecma_op_new_array_object_from_length (len); + + if (JERRY_UNLIKELY (array_obj_p == NULL)) + { + goto cleanup; + } + } + + /* 15. */ + k = 0; + + /* 16. */ + while (k < len) + { + /* 16.b */ + ecma_value_t k_value = ecma_op_object_get_by_index (array_like_obj_p, k); + + /* 16.c */ + if (ECMA_IS_VALUE_ERROR (k_value)) + { + goto construct_cleanup; + } + + ecma_value_t mapped_value; + /* 16.d */ + if (mapfn_obj_p != NULL) + { + /* 16.d.i */ + ecma_value_t args_p[2] = { k_value, ecma_make_length_value (k) }; + mapped_value = ecma_op_function_call (mapfn_obj_p, call_this_arg, args_p, 2); + ecma_free_value (args_p[1]); + ecma_free_value (k_value); + + /* 16.d.ii */ + if (ECMA_IS_VALUE_ERROR (mapped_value)) + { + goto construct_cleanup; + } + } + else + { + /* 16.e */ + mapped_value = k_value; + } + + /* 16.f */ + const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + ecma_value_t set_status = ecma_builtin_helper_def_prop_by_index (array_obj_p, k, mapped_value, flags); + + ecma_free_value (mapped_value); + + /* 16.g */ + if (ECMA_IS_VALUE_ERROR (set_status)) + { + goto construct_cleanup; + } + + /* 16.h */ + k++; + } + + /* 17. */ + len_value = ecma_make_length_value (k); + set_status = ecma_op_object_put (array_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), len_value, true); + ecma_free_value (len_value); + + /* 18. */ + if (ECMA_IS_VALUE_ERROR (set_status)) + { + goto construct_cleanup; + } + + /* 19. */ + ecma_deref_object (array_like_obj_p); + return ecma_make_object_value (array_obj_p); + +construct_cleanup: + ecma_deref_object (array_obj_p); +cleanup: + ecma_deref_object (array_like_obj_p); + return ret_value; +} /* ecma_builtin_array_object_from */ + +/** + * The Array object's 'of' routine + * + * See also: + * ECMA-262 v6, 22.1.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_object_of (ecma_value_t this_arg, /**< 'this' argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + if (!ecma_is_constructor (this_arg)) + { + return ecma_op_new_array_object_from_buffer (arguments_list_p, arguments_list_len); + } + + ecma_value_t len = ecma_make_uint32_value (arguments_list_len); + + ecma_value_t ret_val = + ecma_op_function_construct (ecma_get_object_from_value (this_arg), ecma_get_object_from_value (this_arg), &len, 1); + + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + ecma_free_value (len); + return ret_val; + } + + uint32_t k = 0; + ecma_object_t *obj_p = ecma_get_object_from_value (ret_val); + const uint32_t prop_status_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + + while (k < arguments_list_len) + { + ecma_value_t define_status = + ecma_builtin_helper_def_prop_by_index (obj_p, k, arguments_list_p[k], prop_status_flags); + + if (ECMA_IS_VALUE_ERROR (define_status)) + { + ecma_free_value (len); + ecma_deref_object (obj_p); + return define_status; + } + + k++; + } + + ret_val = ecma_op_object_put (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), len, true); + + ecma_free_value (len); + + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + ecma_deref_object (obj_p); + return ret_val; + } + + return ecma_make_object_value (obj_p); +} /* ecma_builtin_array_object_of */ + +/** + * Handle calling [[Call]] of built-in Array object + * + * @return ECMA_VALUE_ERROR - if the array construction fails + * constructed array object - otherwise + */ +ecma_value_t +ecma_builtin_array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len != 1 || !ecma_is_value_number (arguments_list_p[0])) + { + return ecma_op_new_array_object_from_buffer (arguments_list_p, arguments_list_len); + } + + ecma_number_t num = ecma_get_number_from_value (arguments_list_p[0]); + uint32_t num_uint32 = ecma_number_to_uint32 (num); + + if (num != ((ecma_number_t) num_uint32)) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + } + + return ecma_make_object_value (ecma_op_new_array_object (num_uint32)); +} /* ecma_builtin_array_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Array object + * + * @return ECMA_VALUE_ERROR - if the array construction fails + * constructed array object - otherwise + */ +ecma_value_t +ecma_builtin_array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_ARRAY_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_array_dispatch_call (arguments_list_p, arguments_list_len); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (proto_p); + return result; + } + + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + ecma_deref_object (proto_p); + return result; +} /* ecma_builtin_array_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_array_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + switch (builtin_routine_id) + { + case ECMA_ARRAY_ROUTINE_IS_ARRAY: + { + JERRY_UNUSED (this_arg); + + return ecma_is_value_array (arguments_list_p[0]); + } + case ECMA_ARRAY_ROUTINE_FROM: + { + return ecma_builtin_array_object_from (this_arg, arguments_list_p, arguments_number); + } + case ECMA_ARRAY_ROUTINE_OF: + { + return ecma_builtin_array_object_of (this_arg, arguments_list_p, arguments_number); + } + case ECMA_ARRAY_ROUTINE_SPECIES_GET: + { + return ecma_copy_value (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_array_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h new file mode 100644 index 00000000..bf43da90 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h @@ -0,0 +1,47 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Array description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ARRAY + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.4.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ARRAY_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* Number properties: + * (property name, object pointer getter) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ARRAY_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_IS_ARRAY_UL, ECMA_ARRAY_ROUTINE_IS_ARRAY, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FROM, ECMA_ARRAY_ROUTINE_FROM, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_OF, ECMA_ARRAY_ROUTINE_OF, NON_FIXED, 0) + +/* ECMA-262 v6, 22.1.2.5 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ECMA_ARRAY_ROUTINE_SPECIES_GET, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* !(JERRY_BUILTIN_ARRAY) */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.cpp new file mode 100644 index 00000000..3e47e068 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.cpp @@ -0,0 +1,116 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jrt-libc-includes.h" +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-arraybuffer-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID arraybuffer_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup arraybufferprototype ECMA ArrayBuffer.prototype object built-in + * @{ + */ + +/** + * The ArrayBuffer.prototype.bytelength accessor + * + * See also: + * ES2015, 24.1.4.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_arraybuffer_prototype_bytelength_getter (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)) + { + if (ecma_arraybuffer_is_detached (object_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + uint32_t len = ecma_arraybuffer_get_length (object_p); + + return ecma_make_uint32_value (len); + } + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ARRAY_BUFFER_OBJECT); +} /* ecma_builtin_arraybuffer_prototype_bytelength_getter */ + +/** + * The ArrayBuffer.prototype object's 'slice' routine + * + * See also: + * ECMA-262 v11, 24.1.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< this argument */ + const ecma_value_t *argument_list_p, /**< arguments list */ + uint32_t arguments_number) /**< number of arguments */ +{ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + /* 2. */ + if (!ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ARRAY_BUFFER_OBJECT); + } + + return ecma_builtin_arraybuffer_slice (this_arg, argument_list_p, arguments_number); +} /* ecma_builtin_arraybuffer_prototype_object_slice */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h new file mode 100644 index 00000000..80463446 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ArrayBuffer.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ARRAYBUFFER, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Readonly accessor properties */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL, + ecma_builtin_arraybuffer_prototype_bytelength_getter, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 24.1.4.4 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ARRAY_BUFFER_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_SLICE, ecma_builtin_arraybuffer_prototype_object_slice, NON_FIXED, 2) + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.cpp new file mode 100644 index 00000000..cb26f0a9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.cpp @@ -0,0 +1,114 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtins.h" +#include "ecma-dataview-object.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-arraybuffer.inc.h" +#define BUILTIN_UNDERSCORED_ID arraybuffer +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup arraybuffer ECMA ArrayBuffer object built-in + * @{ + */ + +/** + * The ArrayBuffer object's 'isView' routine + * + * See also: + * ES2015 24.1.3.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_arraybuffer_object_is_view (ecma_value_t this_arg, /**< 'this' argument */ + ecma_value_t arg) /**< argument 1 */ +{ + JERRY_UNUSED (this_arg); + + return ecma_make_boolean_value (ecma_is_typedarray (arg) || ecma_is_dataview (arg)); +} /* ecma_builtin_arraybuffer_object_is_view */ + +/** + * Handle calling [[Call]] of built-in ArrayBuffer object + * + * ES2015 24.1.2 ArrayBuffer is not intended to be called as + * a function and will throw an exception when called in + * that manner. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_arraybuffer_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_ARRAYBUFFER_REQUIRES_NEW); +} /* ecma_builtin_arraybuffer_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in ArrayBuffer object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_arraybuffer_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_arraybuffer_object (arguments_list_p, arguments_list_len); +} /* ecma_builtin_arraybuffer_dispatch_construct */ + +/** + * 24.1.3.3 get ArrayBuffer [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_arraybuffer_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_arraybuffer_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h new file mode 100644 index 00000000..6fe1a936 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h @@ -0,0 +1,47 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ArrayBuffer built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ARRAY_BUFFER_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ + +/* ES2015 24.1.3.1 */ +ROUTINE (LIT_MAGIC_STRING_IS_VIEW_UL, ecma_builtin_arraybuffer_object_is_view, 1, 1) + +/* ES2015 24.1.3.3 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_arraybuffer_species_get, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.cpp new file mode 100644 index 00000000..8f1b10e0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.cpp @@ -0,0 +1,355 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jerryscript-types.h" + +#include "ecma-builtin-handlers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" +#include "jrt.h" +#include "lit-magic-strings.h" +#include "lit-strings.h" +#include "opcodes.h" +#include "vm-defines.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_START = 0, /**< buitlin routine start id */ + ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_NEXT, /**< 'next' routine v11, 25.1.4.2.1 */ + ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_RETURN, /**< 'return' routine v11, 25.1.4.2.2 */ + ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_THROW /**< 'throw' routine v11, 25.1.4.2.3 */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-from-sync-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID async_from_sync_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncfromsynciteratorprototype ECMA %AsyncFromSyncIteratorPrototype% object built-in + * @{ + */ + +/** + * AsyncFromSyncIteratorContinuation operation + * + * See also: + * ECMAScript v11, 25.1.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_op_async_from_sync_iterator_prototype_continuation (ecma_value_t result, /**< routine's 'result' argument */ + ecma_object_t *capability_obj_p) /**< promise capability */ +{ + /* 1. */ + ecma_value_t done = ecma_op_iterator_complete (result); + + /* 2. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&done, capability_obj_p))) + { + return done; + } + + uint16_t done_flag = ecma_is_value_false (done) ? 0 : (1 << ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT); + ecma_free_value (done); + + /* 3. */ + ecma_value_t value = ecma_op_iterator_value (result); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&value, capability_obj_p))) + { + return value; + } + + /* 5. */ + ecma_value_t builtin_promise = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE)); + ecma_value_t value_wrapper = ecma_promise_reject_or_resolve (builtin_promise, value, true); + ecma_free_value (value); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&value_wrapper, capability_obj_p))) + { + return value_wrapper; + } + + /* 8 - 9. */ + ecma_object_t *on_fullfilled = ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_ASYNC_FROM_SYNC_ITERATOR_UNWRAP, + sizeof (ecma_extended_object_t)); + ((ecma_extended_object_t *) on_fullfilled)->u.built_in.u2.routine_flags = (uint8_t) done_flag; + + /* 10. */ + ecma_value_t then_result = ecma_promise_perform_then (value_wrapper, + ecma_make_object_value (on_fullfilled), + ECMA_VALUE_UNDEFINED, + capability_obj_p); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (then_result)); + ecma_deref_object (on_fullfilled); + ecma_free_value (value_wrapper); + + /* 11. */ + return then_result; +} /* ecma_op_async_from_sync_iterator_prototype_continuation */ + +/** + * The %AsyncFromSyncIteratorPrototype% object's 'next' routine + * + * See also: + * ECMAScript v11, 25.1.4.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_async_from_sync_iterator_prototype_next (ecma_async_from_sync_iterator_object_t *iter_p, /**< iterator + * record*/ + ecma_object_t *capability_p, /**< promise capability */ + ecma_value_t value) /**< routine's 'value' argument */ +{ + /* 5. */ + ecma_value_t next_result = + ecma_op_iterator_next (iter_p->header.u.cls.u3.sync_iterator, iter_p->sync_next_method, value); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&next_result, capability_p))) + { + return next_result; + } + + /* 7. */ + ecma_value_t result = ecma_op_async_from_sync_iterator_prototype_continuation (next_result, capability_p); + ecma_free_value (next_result); + + return result; +} /* ecma_builtin_async_from_sync_iterator_prototype_next */ + +/** + * The %AsyncFromSyncIteratorPrototype% object's 'return' and 'throw' routines + * + * See also: + * ECMAScript v11, 25.1.4.2.2 + * ECMAScript v11, 25.1.4.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_async_from_sync_iterator_prototype_do (ecma_async_from_sync_iterator_object_t *iter_p, /**< iterator + * record*/ + ecma_object_t *capability_obj_p, /**< promise capability */ + ecma_value_t value, /**< routine's 'value' argument */ + lit_magic_string_id_t method_id) /**< method id */ +{ + /* 5. */ + ecma_value_t sync_iterator = iter_p->header.u.cls.u3.sync_iterator; + ecma_value_t method = ecma_op_get_method_by_magic_id (sync_iterator, method_id); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&method, capability_obj_p))) + { + return method; + } + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + + ecma_value_t call_arg; + uint32_t arg_size; + + if (ecma_is_value_empty (value)) + { + arg_size = 0; + call_arg = ECMA_VALUE_UNDEFINED; + } + else + { + arg_size = 1; + call_arg = value; + } + + /* 7. */ + if (ecma_is_value_undefined (method)) + { + ecma_value_t func_obj; + + if (method_id == LIT_MAGIC_STRING_RETURN) + { + /* 7.a. */ + call_arg = ecma_create_iter_result_object (call_arg, ECMA_VALUE_TRUE); + arg_size = 1; + func_obj = capability_p->resolve; + } + else + { + func_obj = capability_p->reject; + } + + /* 7.b. */ + ecma_value_t resolve = + ecma_op_function_call (ecma_get_object_from_value (func_obj), ECMA_VALUE_UNDEFINED, &call_arg, arg_size); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (resolve)); + ecma_free_value (resolve); + + if (method_id == LIT_MAGIC_STRING_RETURN) + { + ecma_free_value (call_arg); + } + + /* 7.c. */ + return ecma_copy_value (capability_p->header.u.cls.u3.promise); + } + + /* 8. */ + ecma_value_t call_result = ecma_op_function_validated_call (method, sync_iterator, &call_arg, arg_size); + ecma_free_value (method); + + /* 9. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&call_result, capability_obj_p))) + { + return call_result; + } + + /* 10. */ + if (!ecma_is_value_object (call_result)) + { + ecma_free_value (call_result); + +#if JERRY_ERROR_MESSAGES + const lit_utf8_byte_t *msg_p = (lit_utf8_byte_t *) ecma_get_error_msg (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + lit_utf8_size_t msg_size = ecma_get_error_size (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + ecma_string_t *error_msg_p = ecma_new_ecma_string_from_ascii (msg_p, msg_size); +#else /* !JERRY_ERROR_MESSAGES */ + ecma_string_t *error_msg_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + + ecma_object_t *type_error_obj_p = ecma_new_standard_error (JERRY_ERROR_TYPE, error_msg_p); + +#if JERRY_ERROR_MESSAGES + ecma_deref_ecma_string (error_msg_p); +#endif /* JERRY_ERROR_MESSAGES */ + + ecma_value_t type_error = ecma_make_object_value (type_error_obj_p); + + /* 10.a. */ + ecma_value_t reject = + ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &type_error, 1); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (reject)); + ecma_deref_object (type_error_obj_p); + ecma_free_value (reject); + + /* 10.b. */ + return ecma_copy_value (capability_p->header.u.cls.u3.promise); + } + + ecma_value_t result = ecma_op_async_from_sync_iterator_prototype_continuation (call_result, capability_obj_p); + ecma_free_value (call_result); + + return result; +} /* ecma_builtin_async_from_sync_iterator_prototype_do */ + +/** + * Dispatcher of the %AsyncFromSyncIteratorPrototype% built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_async_from_sync_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of + * arguments + * passed to + * routine */ + uint32_t arguments_number) /**< length of + * arguments' list */ +{ + JERRY_UNUSED (arguments_number); + JERRY_ASSERT (ecma_is_value_object (this_arg)); + + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); + + JERRY_ASSERT (ecma_object_class_is (this_obj_p, ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR)); + + ecma_async_from_sync_iterator_object_t *iter_p = (ecma_async_from_sync_iterator_object_t *) this_obj_p; + + ecma_value_t builtin_promise = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE)); + ecma_object_t *capability_p = ecma_promise_new_capability (builtin_promise, ECMA_VALUE_UNDEFINED); + JERRY_ASSERT (capability_p != NULL); + + ecma_value_t result; + ecma_value_t arg = (arguments_number == 0 ? ECMA_VALUE_EMPTY : arguments_list_p[0]); + + switch (builtin_routine_id) + { + case ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_NEXT: + { + result = ecma_builtin_async_from_sync_iterator_prototype_next (iter_p, capability_p, arg); + break; + } + case ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_RETURN: + { + result = ecma_builtin_async_from_sync_iterator_prototype_do (iter_p, capability_p, arg, LIT_MAGIC_STRING_RETURN); + break; + } + case ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_THROW: + { + result = ecma_builtin_async_from_sync_iterator_prototype_do (iter_p, capability_p, arg, LIT_MAGIC_STRING_THROW); + break; + } + default: + { + JERRY_UNREACHABLE (); + break; + } + } + + ecma_deref_object (capability_p); + + return result; +} /* ecma_builtin_async_from_sync_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.inc.h new file mode 100644 index 00000000..7c5e9c39 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncFromSyncIteratorPrototype% built-in description (AsyncFunction.prototype) + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_NEXT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_RETURN, ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_RETURN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_THROW, ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_THROW, 1, 1) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.cpp new file mode 100644 index 00000000..6be0c162 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.cpp @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-function-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID async_function_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncfunctionprototype ECMA AsyncFunction.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.inc.h new file mode 100644 index 00000000..e4388d3c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncFunctionPrototype% built-in description (AsyncFunction.prototype) + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v11, 25.7.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ASYNC_FUNCTION, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v11, 25.7.3.2 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ASYNC_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.cpp new file mode 100644 index 00000000..de1a7dbc --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.cpp @@ -0,0 +1,68 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" +#include "ecma-function-object.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-function.inc.h" +#define BUILTIN_UNDERSCORED_ID async_function +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncfunction ECMA AsyncFunction object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in AsyncFunction object + * + * @return constructed async function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_async_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_dynamic_function (arguments_list_p, arguments_list_len, ECMA_PARSE_ASYNC_FUNCTION); +} /* ecma_builtin_async_function_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in AsyncFunction object + * + * @return constructed async function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_async_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_async_function_dispatch_call (arguments_list_p, arguments_list_len); +} /* ecma_builtin_async_function_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.inc.h new file mode 100644 index 00000000..0fe50ae2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.inc.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncFunction% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v11, 25.7.2 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ASYNC_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v11, 25.7.2.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v10, 25.7.2.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v11, 25.7.3.2 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ASYNC_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.cpp new file mode 100644 index 00000000..18ad25ef --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.cpp @@ -0,0 +1,70 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" +#include "ecma-function-object.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-generator-function.inc.h" +#define BUILTIN_UNDERSCORED_ID async_generator_function +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncgeneratorfunction ECMA AsyncGeneratorFunction object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in AsyncGeneratorFunction object + * + * @return constructed async generator function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_async_generator_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_dynamic_function (arguments_list_p, + arguments_list_len, + (ecma_parse_opts_t)(((unsigned int) ECMA_PARSE_GENERATOR_FUNCTION) | ((unsigned int) ECMA_PARSE_ASYNC_FUNCTION))); +} /* ecma_builtin_async_generator_function_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in AsyncGeneratorFunction object + * + * @return constructed async generator function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_async_generator_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_async_generator_function_dispatch_call (arguments_list_p, arguments_list_len); +} /* ecma_builtin_async_generator_function_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.inc.h new file mode 100644 index 00000000..edc88c71 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.inc.h @@ -0,0 +1,31 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncGeneratorFunction% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v10, 25.3.2 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ASYNC_GENERATOR_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v10, 25.3.2.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.3.2.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ASYNC_GENERATOR, ECMA_PROPERTY_FIXED) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.cpp new file mode 100644 index 00000000..3ea9dea0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.cpp @@ -0,0 +1,147 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-async-generator-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" +#include "opcodes.h" +#include "vm-defines.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_NEXT, + ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_THROW, + ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_RETURN +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-generator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID async_generator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncgeneratorprototype ECMA AsyncGenerator.prototype object built-in + * @{ + */ + +/** + * Convert routine type to operation type. + */ +#define ECMA_ASYNC_GENERATOR_ROUTINE_TO_OPERATION(type) \ + ((ecma_async_generator_operation_type_t) ((type) -ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_NEXT)) + +JERRY_STATIC_ASSERT ((ECMA_ASYNC_GENERATOR_ROUTINE_TO_OPERATION (ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_NEXT) == ECMA_ASYNC_GENERATOR_DO_NEXT), + convert_ecma_async_generator_routine_next_to_ecma_async_generator_do_next_failed); + +JERRY_STATIC_ASSERT ((ECMA_ASYNC_GENERATOR_ROUTINE_TO_OPERATION (ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_THROW) == ECMA_ASYNC_GENERATOR_DO_THROW), + convert_ecma_async_generator_routine_throw_to_ecma_async_generator_do_throw_failed); + +JERRY_STATIC_ASSERT ((ECMA_ASYNC_GENERATOR_ROUTINE_TO_OPERATION (ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_RETURN) == ECMA_ASYNC_GENERATOR_DO_RETURN), + convert_ecma_async_generator_routine_return_to_ecma_async_generator_do_return_failed); + +/** + * Dispatcher of the Generator built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_async_generator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to + * routine */ + uint32_t arguments_number) /**< length of arguments' + * list */ +{ + JERRY_UNUSED (arguments_number); + + vm_executable_object_t *executable_object_p = NULL; + + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ASYNC_GENERATOR)) + { + executable_object_p = (vm_executable_object_t *) object_p; + } + } + + if (executable_object_p == NULL) + { + const char *msg_p = ecma_get_error_msg (ECMA_ERR_ARGUMENT_THIS_NOT_ASYNC_GENERATOR); + lit_utf8_size_t msg_size = ecma_get_error_size (ECMA_ERR_ARGUMENT_THIS_NOT_ASYNC_GENERATOR); + ecma_string_t *error_msg_p = ecma_new_ecma_string_from_ascii ((const lit_utf8_byte_t *) msg_p, msg_size); + + ecma_object_t *type_error_obj_p = ecma_new_standard_error (JERRY_ERROR_TYPE, error_msg_p); + ecma_deref_ecma_string (error_msg_p); + + ecma_value_t promise = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL); + ecma_reject_promise (promise, ecma_make_object_value (type_error_obj_p)); + ecma_deref_object (type_error_obj_p); + + return promise; + } + + if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_COMPLETED) + { + ecma_value_t promise = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE)); + + if (JERRY_UNLIKELY (builtin_routine_id == ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_THROW)) + { + return ecma_promise_reject_or_resolve (promise, arguments_list_p[0], false); + } + + ecma_value_t iter_result = ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + ecma_value_t result = ecma_promise_reject_or_resolve (promise, iter_result, true); + ecma_free_value (iter_result); + return result; + } + + return ecma_async_generator_enqueue (executable_object_p, + ECMA_ASYNC_GENERATOR_ROUTINE_TO_OPERATION (builtin_routine_id), + arguments_list_p[0]); +} /* ecma_builtin_async_generator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.inc.h new file mode 100644 index 00000000..dcad1c62 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * AsyncGenerator.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 25.3.1.5 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ASYNC_GENERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ASYNC_GENERATOR, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_NEXT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_RETURN, ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_RETURN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_THROW, ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_THROW, 1, 1) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.cpp new file mode 100644 index 00000000..46937420 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.cpp @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-generator.inc.h" +#define BUILTIN_UNDERSCORED_ID async_generator +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncgenerator ECMA AsyncGenerator object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.inc.h new file mode 100644 index 00000000..a856cbbe --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.inc.h @@ -0,0 +1,33 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncGenerator% built-in description (AsyncGeneratorFunction.prototype) + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v6, 25.3.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ASYNC_GENERATOR_FUNCTION, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.3.2.3.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.3.2.3.3 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, + LIT_MAGIC_STRING_ASYNC_GENERATOR_FUNCTION_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.cpp new file mode 100644 index 00000000..28579fee --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.cpp @@ -0,0 +1,103 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-iterator-object.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_ASYNC_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_BUILTIN_ASYNC_ITERATOR_PROTOTYPE_OBJECT_ASYNC_ITERATOR, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID async_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %asynciteratorprototype% ECMA %AsyncIteratorPrototype% object built-in + * @{ + */ + +/** + * The %AsyncIteratorPrototype% object's '@@asyncIterator' routine + * + * See also: + * ECMA-262 v10, 25.1.3.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return the given this value + */ +static ecma_value_t +ecma_builtin_async_iterator_prototype_object_async_iterator (ecma_value_t this_val) /**< this argument */ +{ + /* 1. */ + return ecma_copy_value (this_val); +} /* ecma_builtin_async_iterator_prototype_object_async_iterator */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_async_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< + * list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_ASYNC_ITERATOR_PROTOTYPE_OBJECT_ASYNC_ITERATOR: + { + return ecma_builtin_async_iterator_prototype_object_async_iterator (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_async_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.inc.h new file mode 100644 index 00000000..53d43d00 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, ECMA_BUILTIN_ASYNC_ITERATOR_PROTOTYPE_OBJECT_ASYNC_ITERATOR, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.cpp new file mode 100644 index 00000000..c7d1847c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.cpp @@ -0,0 +1,260 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-atomics-object.h" +#include "ecma-builtins.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ATOMICS + +#define ECMA_BUILTINS_INTERNAL + +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ATOMICS_ROUTINE_START = 0, /**< Special value, should be ignored */ + ECMA_ATOMICS_ROUTINE_ADD, /**< Atomics add routine */ + ECMA_ATOMICS_ROUTINE_AND, /**< Atomics and routine */ + ECMA_ATOMICS_ROUTINE_COMPAREEXCHANGE, /**< Atomics compare exchange routine */ + ECMA_ATOMICS_ROUTINE_EXCHANGE, /**< Atomics exchange routine */ + ECMA_ATOMICS_ROUTINE_ISLOCKFREE, /**< Atomics is lock free routine */ + ECMA_ATOMICS_ROUTINE_LOAD, /**< Atomics load routine */ + ECMA_ATOMICS_ROUTINE_OR, /**< Atomics or routine */ + ECMA_ATOMICS_ROUTINE_STORE, /**< Atomics store routine */ + ECMA_ATOMICS_ROUTINE_SUB, /**< Atomics sub routine */ + ECMA_ATOMICS_ROUTINE_WAIT, /**< Atomics wait routine */ + ECMA_ATOMICS_ROUTINE_NOTIFY, /**< Atomics notify routine */ + ECMA_ATOMICS_ROUTINE_XOR, /**< Atomics xor routine */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-atomics.inc.h" +#define BUILTIN_UNDERSCORED_ID atomics + +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup atomics ECMA Atomics object built-in + * @{ + */ + +/** + * The Atomics object's 'compareExchange' routine + * + * See also: ES11 24.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_atomics_compare_exchange (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index, /**< index argument */ + ecma_value_t expected_value, /**< expectedValue argument */ + ecma_value_t replacement_value) /**< replacementValue argument*/ +{ + JERRY_UNUSED (typedarray); + JERRY_UNUSED (index); + JERRY_UNUSED (expected_value); + JERRY_UNUSED (replacement_value); + + return ecma_make_uint32_value (0); +} /* ecma_builtin_atomics_compare_exchange */ + +/** + * The Atomics object's 'isLockFree' routine + * + * See also: ES11 24.4.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_atomics_is_lock_free (ecma_value_t size) /**< size argument */ +{ + JERRY_UNUSED (size); + + return ECMA_VALUE_FALSE; +} /* ecma_builtin_atomics_is_lock_free */ + +/** + * The Atomics object's 'store' routine + * + * See also: ES11 24.4.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_atomics_store (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index, /**< index argument */ + ecma_value_t value) /**< value argument */ +{ + JERRY_UNUSED (typedarray); + JERRY_UNUSED (index); + JERRY_UNUSED (value); + + return ecma_make_uint32_value (0); +} /* ecma_builtin_atomics_store */ + +/** + * The Atomics object's 'wait' routine + * + * See also: ES11 24.4.11 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_atomics_wait (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index, /**< index argument */ + ecma_value_t value, /**< value argument */ + ecma_value_t timeout) /**< timeout argument */ +{ + JERRY_UNUSED (typedarray); + JERRY_UNUSED (index); + JERRY_UNUSED (value); + JERRY_UNUSED (timeout); + + return ecma_make_uint32_value (0); +} /* ecma_builtin_atomics_wait */ + +/** + * The Atomics object's 'notify' routine + * + * See also: ES11 24.4.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_atomics_notify (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index, /**< index argument */ + ecma_value_t count) /**< count argument */ +{ + JERRY_UNUSED (typedarray); + JERRY_UNUSED (index); + JERRY_UNUSED (count); + + return ecma_make_uint32_value (0); +} /* ecma_builtin_atomics_notify */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_atomics_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (this_arg); + ecma_value_t arg1 = arguments_list_p[0]; + ecma_value_t arg2 = arguments_list_p[1]; + ecma_value_t arg3 = arguments_list_p[2]; + ecma_value_t arg4 = (arguments_number > 3) ? arguments_list_p[3] : ECMA_VALUE_UNDEFINED; + + ecma_atomics_op_t type; + + switch (builtin_routine_id) + { + case ECMA_ATOMICS_ROUTINE_ADD: + { + type = ECMA_ATOMICS_ADD; + break; + } + case ECMA_ATOMICS_ROUTINE_AND: + { + type = ECMA_ATOMICS_AND; + break; + } + case ECMA_ATOMICS_ROUTINE_COMPAREEXCHANGE: + { + return ecma_builtin_atomics_compare_exchange (arg1, arg2, arg3, arg4); + } + case ECMA_ATOMICS_ROUTINE_EXCHANGE: + { + type = ECMA_ATOMICS_EXCHANGE; + break; + } + case ECMA_ATOMICS_ROUTINE_ISLOCKFREE: + { + return ecma_builtin_atomics_is_lock_free (arg1); + } + case ECMA_ATOMICS_ROUTINE_LOAD: + { + return ecma_atomic_load (arg1, arg2); + } + case ECMA_ATOMICS_ROUTINE_OR: + { + type = ECMA_ATOMICS_OR; + break; + } + case ECMA_ATOMICS_ROUTINE_STORE: + { + return ecma_builtin_atomics_store (arg1, arg2, arg3); + } + case ECMA_ATOMICS_ROUTINE_SUB: + { + type = ECMA_ATOMICS_SUBTRACT; + break; + } + case ECMA_ATOMICS_ROUTINE_WAIT: + { + return ecma_builtin_atomics_wait (arg1, arg2, arg3, arg4); + } + case ECMA_ATOMICS_ROUTINE_NOTIFY: + { + return ecma_builtin_atomics_notify (arg1, arg2, arg3); + } + case ECMA_ATOMICS_ROUTINE_XOR: + { + type = ECMA_ATOMICS_XOR; + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + return ecma_atomic_read_modify_write (arg1, arg2, arg3, type); +} /* ecma_builtin_atomics_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ATOMICS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.inc.h new file mode 100644 index 00000000..a11b4518 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.inc.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Atomics built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ATOMICS + +/* ECMA-262 v11, 24.4.14 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ATOMICS_U, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_ADD, ECMA_ATOMICS_ROUTINE_ADD, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_AND, ECMA_ATOMICS_ROUTINE_AND, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_COMPAREEXCHANGE, ECMA_ATOMICS_ROUTINE_COMPAREEXCHANGE, 4, 4) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_EXCHANGE, ECMA_ATOMICS_ROUTINE_EXCHANGE, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_ISLOCKFREE, ECMA_ATOMICS_ROUTINE_ISLOCKFREE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_LOAD, ECMA_ATOMICS_ROUTINE_LOAD, 2, 2) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_OR, ECMA_ATOMICS_ROUTINE_OR, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_STORE, ECMA_ATOMICS_ROUTINE_STORE, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_SUB, ECMA_ATOMICS_ROUTINE_SUB, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_WAIT, ECMA_ATOMICS_ROUTINE_WAIT, 4, 4) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_NOTIFY, ECMA_ATOMICS_ROUTINE_NOTIFY, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_XOR, ECMA_ATOMICS_ROUTINE_XOR, 3, 3) + +#endif /* JERRY_BUILTIN_ATOMICS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.cpp new file mode 100644 index 00000000..4e6ad9bf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.cpp @@ -0,0 +1,186 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-bigint.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BIGINT_PROTOTYPE_ROUTINE_START = 0, + ECMA_BIGINT_PROTOTYPE_VALUE_OF, + ECMA_BIGINT_PROTOTYPE_TO_STRING, + ECMA_BIGINT_PROTOTYPE_TO_LOCALE_STRING, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-bigint-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID bigint_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup bigint ECMA BigInt object built-in + * @{ + */ + +/** + * The BigInt.prototype object's 'valueOf' routine + * + * See also: + * ECMA-262 v11, 20.2.3.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_bigint_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_bigint (this_arg)) + { + return ecma_copy_value (this_arg); + } + + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_BIGINT)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (ecma_is_value_bigint (ext_object_p->u.cls.u3.value)); + + return ecma_copy_value (ext_object_p->u.cls.u3.value); + } + } + + return ecma_raise_type_error (ECMA_ERR_BIGINT_VALUE_EXCPECTED); +} /* ecma_builtin_bigint_prototype_object_value_of */ + +/** + * The BigInt.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v11, 20.2.3.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_bigint_prototype_object_to_string (ecma_value_t this_arg, /**< this argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + uint32_t radix = 10; + + if (arguments_list_len > 0 && !ecma_is_value_undefined (arguments_list_p[0])) + { + ecma_number_t arg_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arguments_list_p[0], &arg_num))) + { + return ECMA_VALUE_ERROR; + } + + if (arg_num < 2 || arg_num > 36) + { + return ecma_raise_range_error (ECMA_ERR_RADIX_IS_OUT_OF_RANGE); + } + + radix = (uint32_t) arg_num; + } + + ecma_string_t *string_p = ecma_bigint_to_string (this_arg, radix); + + if (string_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + return ecma_make_string_value (string_p); +} /* ecma_builtin_bigint_prototype_object_to_string */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_bigint_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + ecma_value_t this_value = ecma_builtin_bigint_prototype_object_value_of (this_arg); + ecma_value_t ret_val; + + if (ECMA_IS_VALUE_ERROR (this_value)) + { + return this_value; + } + + switch (builtin_routine_id) + { + case ECMA_BIGINT_PROTOTYPE_VALUE_OF: + { + ret_val = this_value; + break; + } + case ECMA_BIGINT_PROTOTYPE_TO_STRING: + { + ret_val = ecma_builtin_bigint_prototype_object_to_string (this_value, arguments_list_p, arguments_number); + ecma_free_value (this_value); + break; + } + case ECMA_BIGINT_PROTOTYPE_TO_LOCALE_STRING: + { + ret_val = ecma_builtin_bigint_prototype_object_to_string (this_value, 0, 0); + ecma_free_value (this_value); + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + return ret_val; +} /* ecma_builtin_bigint_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.inc.h new file mode 100644 index 00000000..1dc916b0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigInt.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_BIGINT + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v11, 20.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_BIGINT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v11, 20.2.3.5 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_BIGINT_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_BIGINT_PROTOTYPE_TO_STRING, NON_FIXED, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_BIGINT_PROTOTYPE_VALUE_OF, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_BIGINT_PROTOTYPE_TO_LOCALE_STRING, 0, 0) + +#endif /* JERRY_BUILTIN_BIGINT */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.cpp new file mode 100644 index 00000000..b349db16 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.cpp @@ -0,0 +1,80 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-bigint.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-bigint.inc.h" +#define BUILTIN_UNDERSCORED_ID bigint +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup bigint ECMA BigInt object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in BigInt object + * + * See also: + * ECMA-262 v11, 20.2.1.1 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_bigint_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t value = (arguments_list_len == 0) ? ECMA_VALUE_UNDEFINED : arguments_list_p[0]; + return ecma_bigint_to_bigint (value, true); +} /* ecma_builtin_bigint_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in BigInt object + * + * See also: + * ECMA-262 v11, 20.2.1 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_bigint_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_BIGINT_FUNCTION_NOT_CONSTRUCTOR); +} /* ecma_builtin_bigint_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.inc.h new file mode 100644 index 00000000..d8b216ab --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigInt built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_BIGINT + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v11, 20.2.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v11, 20.2.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_BIGINT_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v11, 20.2.2.3 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_BIGINT_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_BIGINT */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp new file mode 100644 index 00000000..0d71a067 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp @@ -0,0 +1,140 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_BOOLEAN + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BOOLEAN_PROTOTYPE_ROUTINE_START = 0, + ECMA_BOOLEAN_PROTOTYPE_ROUTINE_TO_STRING, + ECMA_BOOLEAN_PROTOTYPE_ROUTINE_VALUE_OF +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-boolean-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID boolean_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup booleanprototype ECMA Boolean.prototype object built-in + * @{ + */ + +/** + * The Boolean.prototype object's 'valueOf' routine + * + * See also: + * ECMA-262 v5, 15.6.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_boolean_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_boolean (this_arg)) + { + return this_arg; + } + else if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_BOOLEAN)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (ecma_is_value_boolean (ext_object_p->u.cls.u3.value)); + + return ext_object_p->u.cls.u3.value; + } + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_BOOLEAN_OBJECT); +} /* ecma_builtin_boolean_prototype_object_value_of */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_boolean_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_number, arguments_list_p); + + ecma_value_t value_of_ret = ecma_builtin_boolean_prototype_object_value_of (this_arg); + if (builtin_routine_id == ECMA_BOOLEAN_PROTOTYPE_ROUTINE_VALUE_OF) + { + return value_of_ret; + } + + JERRY_ASSERT (builtin_routine_id == ECMA_BOOLEAN_PROTOTYPE_ROUTINE_TO_STRING); + + if (ECMA_IS_VALUE_ERROR (value_of_ret)) + { + return value_of_ret; + } + + if (ecma_is_value_true (value_of_ret)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_TRUE); + } + + JERRY_ASSERT (ecma_is_value_false (value_of_ret)); + + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FALSE); +} /* ecma_builtin_boolean_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BOOLEAN */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.inc.h new file mode 100644 index 00000000..82ef75f9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Boolean.prototype description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_BOOLEAN + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.6.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_BOOLEAN, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_BOOLEAN_PROTOTYPE_ROUTINE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_BOOLEAN_PROTOTYPE_ROUTINE_VALUE_OF, 0, 0) + +#endif /* JERRY_BUILTIN_BOOLEAN */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.cpp new file mode 100644 index 00000000..603d6104 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.cpp @@ -0,0 +1,99 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-boolean-object.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_BOOLEAN + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-boolean.inc.h" +#define BUILTIN_UNDERSCORED_ID boolean +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup boolean ECMA Boolean object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Boolean object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_boolean_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t arg_value; + + if (arguments_list_len == 0) + { + arg_value = ECMA_VALUE_UNDEFINED; + } + else + { + arg_value = arguments_list_p[0]; + } + + return ecma_make_boolean_value (ecma_op_to_boolean (arg_value)); +} /* ecma_builtin_boolean_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Boolean object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_boolean_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len == 0) + { + return ecma_op_create_boolean_object (ECMA_VALUE_FALSE); + } + else + { + return ecma_op_create_boolean_object (arguments_list_p[0]); + } +} /* ecma_builtin_boolean_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BOOLEAN */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.inc.h new file mode 100644 index 00000000..36f68455 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Boolean description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_BOOLEAN + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.6.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* Number properties: + * (property name, object pointer getter) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_BOOLEAN_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_BOOLEAN */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.cpp new file mode 100644 index 00000000..6cb9ba3a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.cpp @@ -0,0 +1,238 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-dataview-object.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" + +#if JERRY_BUILTIN_DATAVIEW + +#if !JERRY_BUILTIN_TYPEDARRAY +#error "DataView builtin requires ES2015 TypedArray builtin" +#endif /* !JERRY_BUILTIN_TYPEDARRAY */ + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_DATAVIEW_PROTOTYPE_ROUTINE_START = 0, + ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER, + ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER, + ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER, + ECMA_DATAVIEW_PROTOTYPE_GET_INT8, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT8, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT8_CLAMPED, /* unused value */ + ECMA_DATAVIEW_PROTOTYPE_GET_INT16, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT16, + ECMA_DATAVIEW_PROTOTYPE_GET_INT32, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT32, + ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT32, +#if JERRY_NUMBER_TYPE_FLOAT64 + ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT64, +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + ECMA_DATAVIEW_PROTOTYPE_GET_BIGINT64, + ECMA_DATAVIEW_PROTOTYPE_GET_BIGUINT64, +#endif /* JERRY_BUILTIN_BIGINT */ + ECMA_DATAVIEW_PROTOTYPE_SET_INT8, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT8, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT8_CLAMPED, /* unused value */ + ECMA_DATAVIEW_PROTOTYPE_SET_INT16, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT16, + ECMA_DATAVIEW_PROTOTYPE_SET_INT32, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT32, + ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT32, +#if JERRY_NUMBER_TYPE_FLOAT64 + ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT64, +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + ECMA_DATAVIEW_PROTOTYPE_SET_BIGINT64, + ECMA_DATAVIEW_PROTOTYPE_SET_BIGUINT64, +#endif /* JERRY_BUILTIN_BIGINT */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-dataview-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID dataview_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup dataviewprototype ECMA DataView.prototype object built-in + * @{ + */ + +/** + * The DataView.prototype object's {buffer, byteOffset, byteLength} getters + * + * See also: + * ECMA-262 v6, 24.2.4.1 + * ECMA-262 v6, 24.2.4.2 + * ECMA-262 v6, 24.2.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_dataview_prototype_object_getters (ecma_value_t this_arg, /**< this argument */ + uint16_t builtin_routine_id) /**< built-in wide routine identifier */ +{ + ecma_dataview_object_t *obj_p = ecma_op_dataview_get_object (this_arg); + + if (JERRY_UNLIKELY (obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + switch (builtin_routine_id) + { + case ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER: + { + ecma_object_t *buffer_p = obj_p->buffer_p; + ecma_ref_object (buffer_p); + + return ecma_make_object_value (buffer_p); + } + case ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER: + { + if (ecma_arraybuffer_is_detached (obj_p->buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + return ecma_make_uint32_value (obj_p->header.u.cls.u3.length); + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER); + + if (ecma_arraybuffer_is_detached (obj_p->buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + return ecma_make_uint32_value (obj_p->byte_offset); + } + } +} /* ecma_builtin_dataview_prototype_object_getters */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_dataview_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + switch (builtin_routine_id) + { + case ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER: + case ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER: + case ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER: + { + return ecma_builtin_dataview_prototype_object_getters (this_arg, builtin_routine_id); + } + case ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT32: +#if JERRY_NUMBER_TYPE_FLOAT64 + case ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT64: +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + case ECMA_DATAVIEW_PROTOTYPE_GET_INT16: + case ECMA_DATAVIEW_PROTOTYPE_GET_INT32: + case ECMA_DATAVIEW_PROTOTYPE_GET_UINT16: + case ECMA_DATAVIEW_PROTOTYPE_GET_UINT32: +#if JERRY_BUILTIN_BIGINT + case ECMA_DATAVIEW_PROTOTYPE_GET_BIGINT64: + case ECMA_DATAVIEW_PROTOTYPE_GET_BIGUINT64: +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_typedarray_type_t id = (ecma_typedarray_type_t) (builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_GET_INT8); + + return ecma_op_dataview_get_set_view_value (this_arg, + arguments_list_p[0], + arguments_list_p[1], + ECMA_VALUE_EMPTY, + id); + } + case ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT32: +#if JERRY_NUMBER_TYPE_FLOAT64 + case ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT64: +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + case ECMA_DATAVIEW_PROTOTYPE_SET_INT16: + case ECMA_DATAVIEW_PROTOTYPE_SET_INT32: + case ECMA_DATAVIEW_PROTOTYPE_SET_UINT16: + case ECMA_DATAVIEW_PROTOTYPE_SET_UINT32: +#if JERRY_BUILTIN_BIGINT + case ECMA_DATAVIEW_PROTOTYPE_SET_BIGINT64: + case ECMA_DATAVIEW_PROTOTYPE_SET_BIGUINT64: +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_typedarray_type_t id = (ecma_typedarray_type_t) (builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_SET_INT8); + + return ecma_op_dataview_get_set_view_value (this_arg, + arguments_list_p[0], + arguments_list_p[2], + arguments_list_p[1], + id); + } + case ECMA_DATAVIEW_PROTOTYPE_GET_INT8: + case ECMA_DATAVIEW_PROTOTYPE_GET_UINT8: + { + ecma_typedarray_type_t id = (ecma_typedarray_type_t) (builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_GET_INT8); + + return ecma_op_dataview_get_set_view_value (this_arg, + arguments_list_p[0], + ECMA_VALUE_FALSE, + ECMA_VALUE_EMPTY, + id); + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATAVIEW_PROTOTYPE_SET_INT8 + || builtin_routine_id == ECMA_DATAVIEW_PROTOTYPE_SET_UINT8); + ecma_typedarray_type_t id = (ecma_typedarray_type_t) (builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_SET_INT8); + + return ecma_op_dataview_get_set_view_value (this_arg, + arguments_list_p[0], + ECMA_VALUE_FALSE, + arguments_list_p[1], + id); + } + } +} /* ecma_builtin_dataview_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATAVIEW */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h new file mode 100644 index 00000000..82ef26b1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * DataView.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_DATAVIEW + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 24.2.3 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_DATAVIEW, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.2.4.21 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_DATAVIEW_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_GET_FLOAT_32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT32, 2, 1) +#if JERRY_NUMBER_TYPE_FLOAT64 +ROUTINE (LIT_MAGIC_STRING_GET_FLOAT_64_UL, ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT64, 2, 1) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +ROUTINE (LIT_MAGIC_STRING_GET_INT8_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT8, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET_INT16_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT16, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_INT32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT32, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_UINT8_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT8, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_UINT16_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT16, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_UINT32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT32, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SET_FLOAT_32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT32, 2, 2) +#if JERRY_NUMBER_TYPE_FLOAT64 +ROUTINE (LIT_MAGIC_STRING_SET_FLOAT_64_UL, ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT64, 2, 2) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +ROUTINE (LIT_MAGIC_STRING_SET_INT8_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT8, 1, 2) +ROUTINE (LIT_MAGIC_STRING_SET_INT16_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT16, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_INT32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT32, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_UINT8_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT8, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_UINT16_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT16, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_UINT32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT32, 2, 2) +#if JERRY_BUILTIN_BIGINT +ROUTINE (LIT_MAGIC_STRING_GET_BIGINT64, ECMA_DATAVIEW_PROTOTYPE_GET_BIGINT64, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_BIGUINT64, ECMA_DATAVIEW_PROTOTYPE_GET_BIGUINT64, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SET_BIGINT64, ECMA_DATAVIEW_PROTOTYPE_SET_BIGINT64, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_BIGUINT64, ECMA_DATAVIEW_PROTOTYPE_SET_BIGUINT64, 2, 2) +#endif /* JERRY_BUILTIN_BIGINT */ + +/* ECMA-262 v6, 24.2.4.1 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BUFFER, ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 24.2.4.2 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL, + ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 24.2.4.3 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_OFFSET_UL, + ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_DATAVIEW */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.cpp new file mode 100644 index 00000000..bfdb33f0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.cpp @@ -0,0 +1,71 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-dataview-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_DATAVIEW + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-dataview.inc.h" +#define BUILTIN_UNDERSCORED_ID dataview +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup dataview ECMA DataView object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in DataView object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_dataview_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_DATAVIEW_REQUIRES_NEW); +} /* ecma_builtin_dataview_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in DataView object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_dataview_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_dataview_create (arguments_list_p, arguments_list_len); +} /* ecma_builtin_dataview_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATAVIEW */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.inc.h new file mode 100644 index 00000000..9b1027cc --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * DataView built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_DATAVIEW + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.1.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_DATAVIEW_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.1.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_DATAVIEW */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp new file mode 100644 index 00000000..5ad4f2d8 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp @@ -0,0 +1,722 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#if JERRY_BUILTIN_DATE + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * Checks whether the function uses UTC time zone. + */ +#define BUILTIN_DATE_FUNCTION_IS_UTC(builtin_routine_id) \ + (((builtin_routine_id) -ECMA_DATE_PROTOTYPE_GET_FULL_YEAR) & 0x1) + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_DATE_PROTOTYPE_ROUTINE_START = 0, + + ECMA_DATE_PROTOTYPE_GET_FULL_YEAR, /* ECMA-262 v5 15.9.5.10 */ + ECMA_DATE_PROTOTYPE_GET_UTC_FULL_YEAR, /* ECMA-262 v5 15.9.5.11 */ +#if JERRY_BUILTIN_ANNEXB + ECMA_DATE_PROTOTYPE_GET_YEAR, /* ECMA-262 v5, AnnexB.B.2.4 */ + ECMA_DATE_PROTOTYPE_GET_UTC_YEAR, /* has no UTC variant */ +#endif /* JERRY_BUILTIN_ANNEXB */ + ECMA_DATE_PROTOTYPE_GET_MONTH, /* ECMA-262 v5 15.9.5.12 */ + ECMA_DATE_PROTOTYPE_GET_UTC_MONTH, /* ECMA-262 v5 15.9.5.13 */ + ECMA_DATE_PROTOTYPE_GET_DATE, /* ECMA-262 v5 15.9.5.14 */ + ECMA_DATE_PROTOTYPE_GET_UTC_DATE, /* ECMA-262 v5 15.9.5.15 */ + ECMA_DATE_PROTOTYPE_GET_DAY, /* ECMA-262 v5 15.9.5.16 */ + ECMA_DATE_PROTOTYPE_GET_UTC_DAY, /* ECMA-262 v5 15.9.5.17 */ + ECMA_DATE_PROTOTYPE_GET_HOURS, /* ECMA-262 v5 15.9.5.18 */ + ECMA_DATE_PROTOTYPE_GET_UTC_HOURS, /* ECMA-262 v5 15.9.5.19 */ + ECMA_DATE_PROTOTYPE_GET_MINUTES, /* ECMA-262 v5 15.9.5.20 */ + ECMA_DATE_PROTOTYPE_GET_UTC_MINUTES, /* ECMA-262 v5 15.9.5.21 */ + ECMA_DATE_PROTOTYPE_GET_SECONDS, /* ECMA-262 v5 15.9.5.22 */ + ECMA_DATE_PROTOTYPE_GET_UTC_SECONDS, /* ECMA-262 v5 15.9.5.23 */ + ECMA_DATE_PROTOTYPE_GET_MILLISECONDS, /* ECMA-262 v5 15.9.5.24 */ + ECMA_DATE_PROTOTYPE_GET_UTC_MILLISECONDS, /* ECMA-262 v5 15.9.5.25 */ + ECMA_DATE_PROTOTYPE_GET_TIMEZONE_OFFSET, /* has no local time zone variant */ + ECMA_DATE_PROTOTYPE_GET_UTC_TIMEZONE_OFFSET, /* ECMA-262 v5 15.9.5.26 */ + + ECMA_DATE_PROTOTYPE_SET_FULL_YEAR, /* ECMA-262 v5, 15.9.5.40 */ + ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR, /* ECMA-262 v5, 15.9.5.41 */ +#if JERRY_BUILTIN_ANNEXB + ECMA_DATE_PROTOTYPE_SET_YEAR, /* ECMA-262 v5, ECMA-262 v5, AnnexB.B.2.5 */ + ECMA_DATE_PROTOTYPE_SET_UTC_YEAR, /* has no UTC variant */ +#endif /* JERRY_BUILTIN_ANNEXB */ + ECMA_DATE_PROTOTYPE_SET_MONTH, /* ECMA-262 v5, 15.9.5.38 */ + ECMA_DATE_PROTOTYPE_SET_UTC_MONTH, /* ECMA-262 v5, 15.9.5.39 */ + ECMA_DATE_PROTOTYPE_SET_DATE, /* ECMA-262 v5, 15.9.5.36 */ + ECMA_DATE_PROTOTYPE_SET_UTC_DATE, /* ECMA-262 v5, 15.9.5.37 */ + ECMA_DATE_PROTOTYPE_SET_HOURS, /* ECMA-262 v5, 15.9.5.34 */ + ECMA_DATE_PROTOTYPE_SET_UTC_HOURS, /* ECMA-262 v5, 15.9.5.35 */ + ECMA_DATE_PROTOTYPE_SET_MINUTES, /* ECMA-262 v5, 15.9.5.32 */ + ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES, /* ECMA-262 v5, 15.9.5.33 */ + ECMA_DATE_PROTOTYPE_SET_SECONDS, /* ECMA-262 v5, 15.9.5.30 */ + ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS, /* ECMA-262 v5, 15.9.5.31 */ + ECMA_DATE_PROTOTYPE_SET_MILLISECONDS, /* ECMA-262 v5, 15.9.5.28 */ + ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS, /* ECMA-262 v5, 15.9.5.29 */ + + ECMA_DATE_PROTOTYPE_TO_STRING, /* ECMA-262 v5, 15.9.5.2 */ + ECMA_DATE_PROTOTYPE_TO_DATE_STRING, /* ECMA-262 v5, 15.9.5.3 */ + ECMA_DATE_PROTOTYPE_TO_TIME_STRING, /* ECMA-262 v5, 15.9.5.4 */ + ECMA_DATE_PROTOTYPE_TO_ISO_STRING, /* ECMA-262 v5, 15.9.5.43 */ + + ECMA_DATE_PROTOTYPE_GET_TIME, /* ECMA-262 v5, 15.9.5.9 */ + ECMA_DATE_PROTOTYPE_SET_TIME, /* ECMA-262 v5, 15.9.5.27 */ + ECMA_DATE_PROTOTYPE_TO_JSON, /* ECMA-262 v5, 15.9.5.44 */ + + ECMA_DATE_PROTOTYPE_TO_PRIMITIVE, /* ECMA-262 v6 20.3.4.45 */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-date-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID date_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup dateprototype ECMA Date.prototype object built-in + * @{ + */ + +/** + * The Date.prototype object's 'toJSON' routine + * + * See also: + * ECMA-262 v5, 15.9.5.44 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_date_prototype_to_json (ecma_value_t this_arg) /**< this argument */ +{ + /* 1. */ + ecma_value_t obj = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (obj)) + { + return obj; + } + + /* 2. */ + ecma_value_t tv = ecma_op_to_primitive (obj, ECMA_PREFERRED_TYPE_NUMBER); + + if (ECMA_IS_VALUE_ERROR (tv)) + { + ecma_free_value (obj); + return tv; + } + + /* 3. */ + if (ecma_is_value_number (tv)) + { + ecma_number_t num_value = ecma_get_number_from_value (tv); + + ecma_free_value (tv); + + if (ecma_number_is_nan (num_value) || ecma_number_is_infinity (num_value)) + { + ecma_free_value (obj); + return ECMA_VALUE_NULL; + } + } + else + { + ecma_free_value (tv); + } + + ecma_object_t *value_obj_p = ecma_get_object_from_value (obj); + + /* 4. */ + ecma_value_t ret_value = ecma_op_invoke_by_magic_id (obj, LIT_MAGIC_STRING_TO_ISO_STRING_UL, NULL, 0); + + ecma_deref_object (value_obj_p); + + return ret_value; +} /* ecma_builtin_date_prototype_to_json */ + +/** + * The Date.prototype object's toPrimitive routine + * + * See also: + * ECMA-262 v6, 20.3.4.45 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_date_prototype_to_primitive (ecma_value_t this_arg, /**< this argument */ + ecma_value_t hint_arg) /**< {"default", "number", "string"} */ +{ + if (ecma_is_value_object (this_arg) && ecma_is_value_string (hint_arg)) + { + ecma_string_t *hint_str_p = ecma_get_string_from_value (hint_arg); + + ecma_preferred_type_hint_t hint = ECMA_PREFERRED_TYPE_NO; + + if (hint_str_p == ecma_get_magic_string (LIT_MAGIC_STRING_STRING) + || hint_str_p == ecma_get_magic_string (LIT_MAGIC_STRING_DEFAULT)) + { + hint = ECMA_PREFERRED_TYPE_STRING; + } + else if (hint_str_p == ecma_get_magic_string (LIT_MAGIC_STRING_NUMBER)) + { + hint = ECMA_PREFERRED_TYPE_NUMBER; + } + + if (hint != ECMA_PREFERRED_TYPE_NO) + { + return ecma_op_general_object_ordinary_value (ecma_get_object_from_value (this_arg), hint); + } + } + + return ecma_raise_type_error (ECMA_ERR_INVALID_ARGUMENT_TYPE_IN_TOPRIMITIVE); +} /* ecma_builtin_date_prototype_to_primitive */ + +/** + * Dispatch get date functions + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_date_prototype_dispatch_get (uint16_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_number_t date_value) /**< date converted to number */ +{ + if (ecma_number_is_nan (date_value)) + { + return ecma_make_nan_value (); + } + + int32_t result; + + switch (builtin_routine_id) + { + case ECMA_DATE_PROTOTYPE_GET_FULL_YEAR: + case ECMA_DATE_PROTOTYPE_GET_UTC_FULL_YEAR: + { + result = ecma_date_year_from_time (date_value); + break; + } +#if JERRY_BUILTIN_ANNEXB + case ECMA_DATE_PROTOTYPE_GET_YEAR: + { + result = (ecma_date_year_from_time (date_value) - 1900); + break; + } +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_DATE_PROTOTYPE_GET_MONTH: + case ECMA_DATE_PROTOTYPE_GET_UTC_MONTH: + { + result = ecma_date_month_from_time (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_DATE: + case ECMA_DATE_PROTOTYPE_GET_UTC_DATE: + { + result = ecma_date_date_from_time (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_DAY: + case ECMA_DATE_PROTOTYPE_GET_UTC_DAY: + { + result = ecma_date_week_day (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_HOURS: + case ECMA_DATE_PROTOTYPE_GET_UTC_HOURS: + { + result = ecma_date_hour_from_time (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_MINUTES: + case ECMA_DATE_PROTOTYPE_GET_UTC_MINUTES: + { + result = ecma_date_min_from_time (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_SECONDS: + case ECMA_DATE_PROTOTYPE_GET_UTC_SECONDS: + { + result = ecma_date_sec_from_time (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_MILLISECONDS: + case ECMA_DATE_PROTOTYPE_GET_UTC_MILLISECONDS: + { + result = ecma_date_ms_from_time (date_value); + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_GET_UTC_TIMEZONE_OFFSET); + + result = -ecma_date_local_time_zone_adjustment (date_value) / ECMA_DATE_MS_PER_MINUTE; + break; + } + } + + return ecma_make_int32_value (result); +} /* ecma_builtin_date_prototype_dispatch_get */ + +#if JERRY_BUILTIN_ANNEXB + +/** + * Returns true, if the built-in id sets a year. + */ +#define ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE(builtin_routine_id) \ + ((builtin_routine_id) == ECMA_DATE_PROTOTYPE_SET_FULL_YEAR \ + || (builtin_routine_id) == ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR \ + || (builtin_routine_id) == ECMA_DATE_PROTOTYPE_SET_YEAR) + +#else /* !JERRY_BUILTIN_ANNEXB */ + +/** + * Returns true, if the built-in id sets a year. + */ +#define ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE(builtin_routine_id) \ + ((builtin_routine_id) == ECMA_DATE_PROTOTYPE_SET_FULL_YEAR \ + || (builtin_routine_id) == ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR) + +#endif /* JERRY_BUILTIN_ANNEXB */ + +/** + * Dispatch set date functions + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_date_prototype_dispatch_set (uint16_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_object_t *object_p, /**< date object */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + ecma_number_t converted_number[4]; + uint32_t conversions = 0; + + /* If the first argument is not specified, it is always converted to NaN. */ + converted_number[0] = ecma_number_make_nan (); + + switch (builtin_routine_id) + { +#if JERRY_BUILTIN_ANNEXB + case ECMA_DATE_PROTOTYPE_SET_YEAR: +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_DATE_PROTOTYPE_SET_DATE: + case ECMA_DATE_PROTOTYPE_SET_UTC_DATE: + case ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS: + case ECMA_DATE_PROTOTYPE_SET_MILLISECONDS: + { + conversions = 1; + break; + } + case ECMA_DATE_PROTOTYPE_SET_MONTH: + case ECMA_DATE_PROTOTYPE_SET_UTC_MONTH: + case ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS: + case ECMA_DATE_PROTOTYPE_SET_SECONDS: + { + conversions = 2; + break; + } + case ECMA_DATE_PROTOTYPE_SET_FULL_YEAR: + case ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR: + case ECMA_DATE_PROTOTYPE_SET_MINUTES: + case ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES: + { + conversions = 3; + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_HOURS + || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_HOURS); + + conversions = 4; + break; + } + } + + if (conversions > arguments_number) + { + conversions = arguments_number; + } + + for (uint32_t i = 0; i < conversions; i++) + { + ecma_value_t value = ecma_op_to_number (arguments_list[i], &converted_number[i]); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + } + + ecma_date_object_t *date_object_p = (ecma_date_object_t *) object_p; + ecma_number_t *date_value_p = &date_object_p->date_value; + ecma_number_t date_value = *date_value_p; + + if (!BUILTIN_DATE_FUNCTION_IS_UTC (builtin_routine_id)) + { + ecma_number_t local_tza; + + if (date_object_p->header.u.cls.u1.date_flags & ECMA_DATE_TZA_SET) + { + local_tza = date_object_p->header.u.cls.u3.tza; + JERRY_ASSERT (local_tza == ecma_date_local_time_zone_adjustment (date_value)); + } + else + { + local_tza = ecma_date_local_time_zone_adjustment (date_value); + } + + date_value += local_tza; + } + + ecma_number_t day_part; + ecma_number_t time_part; + + if (builtin_routine_id <= ECMA_DATE_PROTOTYPE_SET_UTC_DATE) + { + if (ecma_number_is_nan (date_value)) + { + if (!ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE (builtin_routine_id)) + { + return ecma_make_number_value (date_value); + } + + date_value = ECMA_NUMBER_ZERO; + } + + time_part = ecma_date_time_in_day_from_time (date_value); + + ecma_number_t year = ecma_date_year_from_time (date_value); + ecma_number_t month = ecma_date_month_from_time (date_value); + ecma_number_t day = ecma_date_date_from_time (date_value); + + switch (builtin_routine_id) + { + case ECMA_DATE_PROTOTYPE_SET_FULL_YEAR: + case ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR: + { + year = converted_number[0]; + if (conversions >= 2) + { + month = converted_number[1]; + } + if (conversions >= 3) + { + day = converted_number[2]; + } + break; + } +#if JERRY_BUILTIN_ANNEXB + case ECMA_DATE_PROTOTYPE_SET_YEAR: + { + if (ecma_number_is_nan (converted_number[0])) + { + *date_value_p = converted_number[0]; + date_object_p->header.u.cls.u1.date_flags &= (uint8_t) ~ECMA_DATE_TZA_SET; + return ecma_make_number_value (converted_number[0]); + } + + year = ecma_number_trunc (converted_number[0]); + if (year >= 0 && year <= 99) + { + year += 1900; + } + break; + } +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_DATE_PROTOTYPE_SET_MONTH: + case ECMA_DATE_PROTOTYPE_SET_UTC_MONTH: + { + month = converted_number[0]; + if (conversions >= 2) + { + day = converted_number[1]; + } + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_DATE + || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_DATE); + + day = converted_number[0]; + break; + } + } + + day_part = ecma_date_make_day (year, month, day); + +#if JERRY_BUILTIN_ANNEXB + if (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_YEAR) + { + if (ecma_number_is_nan (converted_number[0])) + { + day_part = 0; + time_part = converted_number[0]; + } + } +#endif /* JERRY_BUILTIN_ANNEXB */ + } + else + { + if (ecma_number_is_nan (date_value)) + { + return ecma_make_number_value (date_value); + } + + day_part = ecma_date_day_from_time (date_value) * (ecma_number_t) ECMA_DATE_MS_PER_DAY; + + ecma_number_t hour = ecma_date_hour_from_time (date_value); + ecma_number_t min = ecma_date_min_from_time (date_value); + ecma_number_t sec = ecma_date_sec_from_time (date_value); + ecma_number_t ms = ecma_date_ms_from_time (date_value); + + switch (builtin_routine_id) + { + case ECMA_DATE_PROTOTYPE_SET_HOURS: + case ECMA_DATE_PROTOTYPE_SET_UTC_HOURS: + { + hour = converted_number[0]; + if (conversions >= 2) + { + min = converted_number[1]; + } + if (conversions >= 3) + { + sec = converted_number[2]; + } + if (conversions >= 4) + { + ms = converted_number[3]; + } + break; + } + case ECMA_DATE_PROTOTYPE_SET_MINUTES: + case ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES: + { + min = converted_number[0]; + if (conversions >= 2) + { + sec = converted_number[1]; + } + if (conversions >= 3) + { + ms = converted_number[2]; + } + break; + } + case ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS: + case ECMA_DATE_PROTOTYPE_SET_SECONDS: + { + sec = converted_number[0]; + if (conversions >= 2) + { + ms = converted_number[1]; + } + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS + || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_MILLISECONDS); + + ms = converted_number[0]; + break; + } + } + + time_part = ecma_date_make_time (hour, min, sec, ms); + } + + bool is_utc = BUILTIN_DATE_FUNCTION_IS_UTC (builtin_routine_id); + + ecma_number_t full_date = ecma_date_make_date (day_part, time_part); + + if (!is_utc) + { + full_date = ecma_date_utc (full_date); + } + + full_date = ecma_date_time_clip (full_date); + + *date_value_p = full_date; + + date_object_p->header.u.cls.u1.date_flags &= (uint8_t) ~ECMA_DATE_TZA_SET; + + return ecma_make_number_value (full_date); +} /* ecma_builtin_date_prototype_dispatch_set */ + +#undef ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_date_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + if (JERRY_UNLIKELY (builtin_routine_id == ECMA_DATE_PROTOTYPE_TO_JSON)) + { + return ecma_builtin_date_prototype_to_json (this_arg); + } + + if (JERRY_UNLIKELY (builtin_routine_id == ECMA_DATE_PROTOTYPE_TO_PRIMITIVE)) + { + return ecma_builtin_date_prototype_to_primitive (this_arg, arguments_list[0]); + } + + if (!ecma_is_value_object (this_arg) + || !ecma_object_class_is (ecma_get_object_from_value (this_arg), ECMA_OBJECT_CLASS_DATE)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_DATE_OBJECT); + } + + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); + + ecma_date_object_t *date_object_p = (ecma_date_object_t *) this_obj_p; + ecma_number_t *date_value_p = &date_object_p->date_value; + ecma_number_t date_value = *date_value_p; + + if (builtin_routine_id == ECMA_DATE_PROTOTYPE_GET_TIME) + { + return ecma_make_number_value (date_value); + } + + if (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_TIME) + { + ecma_number_t time_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (arguments_list[0], &time_num))) + { + return ECMA_VALUE_ERROR; + } + + *date_value_p = ecma_date_time_clip (time_num); + date_object_p->header.u.cls.u1.date_flags &= (uint8_t) ~ECMA_DATE_TZA_SET; + + return ecma_make_number_value (*date_value_p); + } + + if (builtin_routine_id <= ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS) + { + if (builtin_routine_id <= ECMA_DATE_PROTOTYPE_GET_UTC_TIMEZONE_OFFSET) + { + if (!BUILTIN_DATE_FUNCTION_IS_UTC (builtin_routine_id)) + { + ecma_number_t local_tza; + + if (date_object_p->header.u.cls.u1.date_flags & ECMA_DATE_TZA_SET) + { + local_tza = date_object_p->header.u.cls.u3.tza; + JERRY_ASSERT (local_tza == ecma_date_local_time_zone_adjustment (date_value)); + } + else + { + local_tza = ecma_date_local_time_zone_adjustment (date_value); + JERRY_ASSERT (local_tza <= INT32_MAX && local_tza >= INT32_MIN); + date_object_p->header.u.cls.u3.tza = (int32_t) local_tza; + date_object_p->header.u.cls.u1.date_flags |= ECMA_DATE_TZA_SET; + } + + date_value += local_tza; + } + + return ecma_builtin_date_prototype_dispatch_get (builtin_routine_id, date_value); + } + + return ecma_builtin_date_prototype_dispatch_set (builtin_routine_id, this_obj_p, arguments_list, arguments_number); + } + + if (builtin_routine_id == ECMA_DATE_PROTOTYPE_TO_ISO_STRING) + { + if (ecma_number_is_nan (date_value)) + { + return ecma_raise_range_error (ECMA_ERR_DATE_MUST_BE_A_FINITE_NUMBER); + } + + return ecma_date_value_to_iso_string (date_value); + } + + if (ecma_number_is_nan (date_value)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_INVALID_DATE_UL); + } + + switch (builtin_routine_id) + { + case ECMA_DATE_PROTOTYPE_TO_STRING: + { + return ecma_date_value_to_string (date_value); + } + case ECMA_DATE_PROTOTYPE_TO_DATE_STRING: + { + return ecma_date_value_to_date_string (date_value); + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_TO_TIME_STRING); + + return ecma_date_value_to_time_string (date_value); + } + } +} /* ecma_builtin_date_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATE */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.inc.h new file mode 100644 index 00000000..a960cc45 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.inc.h @@ -0,0 +1,83 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Date.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_DATE + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_DATE, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_DATE_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_DATE_STRING_UL, ECMA_DATE_PROTOTYPE_TO_DATE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_TIME_STRING_UL, ECMA_DATE_PROTOTYPE_TO_TIME_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_DATE_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_DATE_STRING_UL, ECMA_DATE_PROTOTYPE_TO_DATE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_TIME_STRING_UL, ECMA_DATE_PROTOTYPE_TO_TIME_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_DATE_PROTOTYPE_GET_TIME, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_TIME_UL, ECMA_DATE_PROTOTYPE_GET_TIME, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_FULL_YEAR_UL, ECMA_DATE_PROTOTYPE_GET_FULL_YEAR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_FULL_YEAR_UL, ECMA_DATE_PROTOTYPE_GET_UTC_FULL_YEAR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_MONTH_UL, ECMA_DATE_PROTOTYPE_GET_MONTH, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_MONTH_UL, ECMA_DATE_PROTOTYPE_GET_UTC_MONTH, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_DATE_UL, ECMA_DATE_PROTOTYPE_GET_DATE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_DATE_UL, ECMA_DATE_PROTOTYPE_GET_UTC_DATE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_DAY_UL, ECMA_DATE_PROTOTYPE_GET_DAY, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_DAY_UL, ECMA_DATE_PROTOTYPE_GET_UTC_DAY, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_HOURS_UL, ECMA_DATE_PROTOTYPE_GET_HOURS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_HOURS_UL, ECMA_DATE_PROTOTYPE_GET_UTC_HOURS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_MINUTES_UL, ECMA_DATE_PROTOTYPE_GET_MINUTES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_MINUTES_UL, ECMA_DATE_PROTOTYPE_GET_UTC_MINUTES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_SECONDS_UL, ECMA_DATE_PROTOTYPE_GET_SECONDS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_SECONDS_UL, ECMA_DATE_PROTOTYPE_GET_UTC_SECONDS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_MILLISECONDS_UL, ECMA_DATE_PROTOTYPE_GET_MILLISECONDS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_MILLISECONDS_UL, ECMA_DATE_PROTOTYPE_GET_UTC_MILLISECONDS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_TIMEZONE_OFFSET_UL, ECMA_DATE_PROTOTYPE_GET_UTC_TIMEZONE_OFFSET, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SET_TIME_UL, ECMA_DATE_PROTOTYPE_SET_TIME, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_MILLISECONDS_UL, ECMA_DATE_PROTOTYPE_SET_MILLISECONDS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_MILLISECONDS_UL, ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_SECONDS_UL, ECMA_DATE_PROTOTYPE_SET_SECONDS, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_SECONDS_UL, ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_MINUTES_UL, ECMA_DATE_PROTOTYPE_SET_MINUTES, NON_FIXED, 3) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_MINUTES_UL, ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES, NON_FIXED, 3) +ROUTINE (LIT_MAGIC_STRING_SET_HOURS_UL, ECMA_DATE_PROTOTYPE_SET_HOURS, NON_FIXED, 4) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_HOURS_UL, ECMA_DATE_PROTOTYPE_SET_UTC_HOURS, NON_FIXED, 4) +ROUTINE (LIT_MAGIC_STRING_SET_DATE_UL, ECMA_DATE_PROTOTYPE_SET_DATE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_DATE_UL, ECMA_DATE_PROTOTYPE_SET_UTC_DATE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_MONTH_UL, ECMA_DATE_PROTOTYPE_SET_MONTH, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_MONTH_UL, ECMA_DATE_PROTOTYPE_SET_UTC_MONTH, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_FULL_YEAR_UL, ECMA_DATE_PROTOTYPE_SET_FULL_YEAR, NON_FIXED, 3) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_FULL_YEAR_UL, ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR, NON_FIXED, 3) +ROUTINE (LIT_MAGIC_STRING_TO_ISO_STRING_UL, ECMA_DATE_PROTOTYPE_TO_ISO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_JSON_UL, ECMA_DATE_PROTOTYPE_TO_JSON, 1, 1) +ROUTINE_CONFIGURABLE_ONLY (LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, ECMA_DATE_PROTOTYPE_TO_PRIMITIVE, 1, 1) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_UTC_STRING_UL, + LIT_MAGIC_STRING_TO_UTC_STRING_UL, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#if JERRY_BUILTIN_ANNEXB +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_GMT_STRING_UL, + LIT_MAGIC_STRING_TO_UTC_STRING_UL, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +ROUTINE (LIT_MAGIC_STRING_GET_YEAR_UL, ECMA_DATE_PROTOTYPE_GET_YEAR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SET_YEAR_UL, ECMA_DATE_PROTOTYPE_SET_YEAR, 1, 1) + +#endif /* JERRY_BUILTIN_ANNEXB */ + +#endif /* JERRY_BUILTIN_DATE */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp new file mode 100644 index 00000000..c9b0d5de --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp @@ -0,0 +1,874 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_DATE + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_DATE_ROUTINE_START = 0, + ECMA_DATE_ROUTINE_PARSE, + ECMA_DATE_ROUTINE_UTC, + ECMA_DATE_ROUTINE_NOW, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-date.inc.h" +#define BUILTIN_UNDERSCORED_ID date +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup date ECMA Date object built-in + * @{ + */ + +/** + * Encode minimum/maximum limits + * + * See: ecma_date_parse_date_chars + * + * @param min: 8 bits unsigned number + * @param max: 24 bits unsigned number + */ +#define ECMA_DATE_LIMIT(min, max) (min << 24 | max) + +/** + * Decode the minimum value from the encoded limit + */ +#define ECMA_DATE_LIMIT_MIN(limit) (limit >> 24) + +/** + * Decode the maximum value from the encoded limit + */ +#define ECMA_DATE_LIMIT_MAX(limit) (limit & ((1 << 24) - 1)) + +/** + * Helper function to try to parse a part of a date string + * + * @return NaN if cannot read from string, ToNumber() otherwise + */ +static ecma_number_t +ecma_date_parse_date_chars (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p, /**< pointer to the end of the string */ + uint32_t num_of_chars, /**< number of characters to read and convert */ + uint32_t limit) /**< minimum/maximum valid value */ +{ + JERRY_ASSERT (num_of_chars > 0 && num_of_chars <= 6); + + if (*str_p + num_of_chars > str_end_p) + { + return ecma_number_make_nan (); + } + + str_end_p = *str_p + num_of_chars; + + uint32_t num = 0; + + while (num_of_chars--) + { + lit_utf8_byte_t c = **str_p; + if (!lit_char_is_decimal_digit (c)) + { + return ecma_number_make_nan (); + } + + num = (num * 10) + (uint32_t) ((c - LIT_CHAR_0)); + (*str_p)++; + } + + if (num >= ECMA_DATE_LIMIT_MIN (limit) && num <= ECMA_DATE_LIMIT_MAX (limit)) + { + return (ecma_number_t) num; + } + + return ecma_number_make_nan (); +} /* ecma_date_parse_date_chars */ + +/** + * Helper function to try to parse a special chracter (+,-,T,Z,:,.) in a date string + * + * @return true if the first character is same as the expected, false otherwise + */ +static bool +ecma_date_parse_special_char (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p, /**< pointer to the end of the string */ + ecma_char_t expected_char) /**< expected character */ +{ + if ((*str_p < str_end_p) && (**str_p == expected_char)) + { + (*str_p)++; + return true; + } + + return false; +} /* ecma_date_parse_special_char */ + +static inline bool +ecma_date_check_two_chars (const lit_utf8_byte_t *str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p, /**< pointer to the end of the string */ + ecma_char_t expected_char1, /**< first expected character */ + ecma_char_t expected_char2) /**< second expected character */ +{ + return (str_p < str_end_p && (*str_p == expected_char1 || *str_p == expected_char2)); +} /* ecma_date_check_two_chars */ + +/** + * Helper function to try to parse a 4-5-6 digit year with optional negative sign in a date string + * + * Date.prototype.toString() and Date.prototype.toUTCString() emits year + * in this format and Date.parse() should parse this format too. + * + * @return the parsed year or NaN. + */ +static ecma_number_t +ecma_date_parse_year (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p) /**< pointer to the end of the string */ +{ + bool is_year_sign_negative = ecma_date_parse_special_char (str_p, str_end_p, LIT_CHAR_MINUS); + const lit_utf8_byte_t *str_start_p = *str_p; + int32_t parsed_year = 0; + + while ((str_start_p - *str_p < 6) && (str_start_p < str_end_p) && lit_char_is_decimal_digit (*str_start_p)) + { + parsed_year = 10 * parsed_year + *str_start_p - LIT_CHAR_0; + str_start_p++; + } + + if (str_start_p - *str_p >= 4) + { + *str_p = str_start_p; + return is_year_sign_negative ? -parsed_year : parsed_year; + } + + return ecma_number_make_nan (); +} /* ecma_date_parse_year */ + +/** + * Helper function to try to parse a day name in a date string + * Valid day names: Sun, Mon, Tue, Wed, Thu, Fri, Sat + * See also: + * ECMA-262 v9, 20.3.4.41.2 Table 46 + * + * @return true if the string starts with a valid day name, false otherwise + */ +static bool +ecma_date_parse_day_name (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p) /**< pointer to the end of the string */ +{ + if (*str_p + 3 < str_end_p) + { + for (uint32_t i = 0; i < 7; i++) + { + if (!memcmp (day_names_p[i], *str_p, 3)) + { + (*str_p) += 3; + return true; + } + } + } + return false; +} /* ecma_date_parse_day_name */ + +/** + * Helper function to try to parse a month name in a date string + * Valid month names: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec + * See also: + * ECMA-262 v9, 20.3.4.41.2 Table 47 + * + * @return number of the month if the string starts with a valid month name, 0 otherwise + */ +static uint32_t +ecma_date_parse_month_name (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p) /**< pointer to the end of the string */ +{ + if (*str_p + 3 < str_end_p) + { + for (uint32_t i = 0; i < 12; i++) + { + if (!memcmp (month_names_p[i], *str_p, 3)) + { + (*str_p) += 3; + return (i + 1); + } + } + } + return 0; +} /* ecma_date_parse_month_name */ + +/** + * Calculate MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)) for Date constructor and UTC + * + * See also: + * ECMA-262 v11, 20.4.3.4 + * + * @return false - if the operation fails + * true - otherwise + */ +static bool +ecma_date_construct_helper (const ecma_value_t *args, /**< arguments passed to the Date constructor */ + uint32_t args_len, /**< number of arguments */ + ecma_number_t *tv_p) /**< [out] time value */ +{ + ecma_number_t date_nums[7] = { + ECMA_NUMBER_ZERO, /* year */ + ECMA_NUMBER_ZERO, /* month */ + ECMA_NUMBER_ONE, /* date */ + ECMA_NUMBER_ZERO, /* hours */ + ECMA_NUMBER_ZERO, /* minutes */ + ECMA_NUMBER_ZERO, /* seconds */ + ECMA_NUMBER_ZERO /* miliseconds */ + }; + + args_len = JERRY_MIN (args_len, sizeof (date_nums) / sizeof (date_nums[0])); + + /* 1-7. */ + for (uint32_t i = 0; i < args_len; i++) + { + ecma_value_t status = ecma_op_to_number (args[i], date_nums + i); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return false; + } + } + + /* 8. */ + if (!ecma_number_is_nan (date_nums[0])) + { + /* 9.a */ + ecma_number_t yi = ecma_number_trunc (date_nums[0]); + + /* 9.b */ + if (yi >= 0 && yi <= 99) + { + date_nums[0] = 1900 + yi; + } + } + + /* 10. */ + *tv_p = ecma_date_make_date (ecma_date_make_day (date_nums[0], date_nums[1], date_nums[2]), + ecma_date_make_time (date_nums[3], date_nums[4], date_nums[5], date_nums[6])); + return true; +} /* ecma_date_construct_helper */ + +/** + * Helper function used by ecma_builtin_date_parse + * + * See also: + * ECMA-262 v5, 15.9.4.2 Date.parse (string) + * ECMA-262 v5, 15.9.1.15 Date Time String Format + * + * @return the parsed date as ecma_number_t or NaN otherwise + */ +static ecma_number_t +ecma_builtin_date_parse_basic (const lit_utf8_byte_t *date_str_curr_p, /**< date string start */ + const lit_utf8_byte_t *date_str_end_p) /**< date string end */ +{ + /* 1. read year */ + + uint32_t year_digits = 4; + uint32_t year_limit = 9999; + + bool is_year_sign_negative = false; + + if (ecma_date_check_two_chars (date_str_curr_p, date_str_end_p, LIT_CHAR_MINUS, LIT_CHAR_PLUS)) + { + is_year_sign_negative = (*date_str_curr_p++ == LIT_CHAR_MINUS); + year_digits = 6; + year_limit = 999999; + } + + ecma_number_t year = + ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, year_digits, ECMA_DATE_LIMIT (0, year_limit)); + if (is_year_sign_negative) + { + year = -year; + } + + if (ecma_number_is_nan (year)) + { + return year; + } + + ecma_number_t month = ECMA_NUMBER_ONE; + ecma_number_t day = ECMA_NUMBER_ONE; + ecma_number_t time = ECMA_NUMBER_ZERO; + + /* 2. read month if any */ + if (ecma_date_check_two_chars (date_str_curr_p, date_str_end_p, LIT_CHAR_MINUS, LIT_CHAR_SLASH)) + { + lit_utf8_byte_t separator = *date_str_curr_p++; + month = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (1, 12)); + + /* 3. read day if any */ + if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, separator)) + { + day = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (1, 31)); + } + } + + bool is_utc = true; + /* 4. read time if any */ + if (ecma_date_check_two_chars (date_str_curr_p, date_str_end_p, LIT_CHAR_UPPERCASE_T, LIT_CHAR_SP)) + { + date_str_curr_p++; + + ecma_number_t hours = ECMA_NUMBER_ZERO; + ecma_number_t minutes = ECMA_NUMBER_ZERO; + ecma_number_t seconds = ECMA_NUMBER_ZERO; + ecma_number_t milliseconds = ECMA_NUMBER_ZERO; + + /* 'HH:mm' must present */ + if (date_str_end_p - date_str_curr_p < 5) + { + return ecma_number_make_nan (); + } + + /* 4.1 read hours and minutes */ + hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 24)); + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COLON)) + { + return ecma_number_make_nan (); + } + + minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + + /* 4.2 read seconds if any */ + if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COLON)) + { + seconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + + /* 4.3 read milliseconds if any */ + if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_DOT)) + { + milliseconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 3, ECMA_DATE_LIMIT (0, 999)); + } + } + + if (hours == 24 && (minutes != 0 || seconds != 0 || milliseconds != 0)) + { + return ecma_number_make_nan (); + } + + time = ecma_date_make_time (hours, minutes, seconds, milliseconds); + + if (ecma_number_is_nan (time)) + { + return time; + } + + /* 4.4 read timezone if any */ + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_UPPERCASE_Z)) + { + if ((date_str_end_p - date_str_curr_p) == 6 + && (*date_str_curr_p == LIT_CHAR_MINUS || *date_str_curr_p == LIT_CHAR_PLUS)) + { + bool is_timezone_sign_negative = (*date_str_curr_p++ == LIT_CHAR_MINUS); + /* read hours and minutes */ + hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 24)); + + if (hours == 24) + { + hours = ECMA_NUMBER_ZERO; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COLON)) + { + return ecma_number_make_nan (); + } + + minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + ecma_number_t timezone_offset = ecma_date_make_time (hours, minutes, ECMA_NUMBER_ZERO, ECMA_NUMBER_ZERO); + time += is_timezone_sign_negative ? timezone_offset : -timezone_offset; + } + else + { + is_utc = false; + } + } + } + + if (date_str_curr_p < date_str_end_p) + { + return ecma_number_make_nan (); + } + + ecma_number_t date = ecma_date_make_day (year, month - 1, day); + ecma_number_t result_date = ecma_date_make_date (date, time); + + if (!is_utc) + { + result_date = ecma_date_utc (result_date); + } + + return result_date; +} /* ecma_builtin_date_parse_basic */ + +/** + * Helper function used by ecma_builtin_date_parse + * + * See also: + * ECMA-262 v5, 15.9.4.2 Date.parse (string) + * ECMA-262 v9, 20.3.4.41 Date.prototype.toString () + * ECMA-262 v9, 20.3.4.43 Date.prototype.toUTCString () + * + * Used by: ecma_builtin_date_parse + * + * @return the parsed date as ecma_number_t or NaN otherwise + */ +static ecma_number_t +ecma_builtin_date_parse_toString_formats (const lit_utf8_byte_t *date_str_curr_p, const lit_utf8_byte_t *date_str_end_p) +{ + const ecma_number_t nan = ecma_number_make_nan (); + + if (!ecma_date_parse_day_name (&date_str_curr_p, date_str_end_p)) + { + return nan; + } + + const bool is_toUTCString_format = ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COMMA); + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_SP)) + { + return nan; + } + + ecma_number_t month = 0; + ecma_number_t day = 0; + if (is_toUTCString_format) + { + day = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 31)); + + if (ecma_number_is_nan (day)) + { + return nan; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_SP)) + { + return nan; + } + + month = ecma_date_parse_month_name (&date_str_curr_p, date_str_end_p); + + if (month == 0) + { + return ecma_number_make_nan (); + } + } + else + { + month = ecma_date_parse_month_name (&date_str_curr_p, date_str_end_p); + + if (month == 0) + { + return nan; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_SP)) + { + return nan; + } + + day = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 31)); + + if (ecma_number_is_nan (day)) + { + return nan; + } + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_SP)) + { + return nan; + } + + ecma_number_t year = ecma_date_parse_year (&date_str_curr_p, date_str_end_p); + + if (ecma_number_is_nan (year)) + { + return nan; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_SP)) + { + return nan; + } + + ecma_number_t hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 24)); + + if (ecma_number_is_nan (hours)) + { + return nan; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COLON)) + { + return nan; + } + + ecma_number_t minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + + if (ecma_number_is_nan (minutes)) + { + return nan; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COLON)) + { + return nan; + } + + ecma_number_t seconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + + if (ecma_number_is_nan (seconds)) + { + return nan; + } + + if (hours == 24 && (minutes != 0 || seconds != 0)) + { + return nan; + } + + const char gmt_p[] = " GMT"; + if (date_str_end_p - date_str_curr_p < 4 || memcmp (date_str_curr_p, gmt_p, 4) != 0) + { + return nan; + } + + date_str_curr_p += 4; + + ecma_number_t time = ecma_date_make_time (hours, minutes, seconds, 0); + + if (!is_toUTCString_format) + { + if (!ecma_date_check_two_chars (date_str_curr_p, date_str_end_p, LIT_CHAR_MINUS, LIT_CHAR_PLUS)) + { + return nan; + } + + bool is_timezone_sign_negative = (*date_str_curr_p++ == LIT_CHAR_MINUS); + + hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 24)); + + if (ecma_number_is_nan (hours)) + { + return nan; + } + + if (hours == 24) + { + hours = ECMA_NUMBER_ZERO; + } + + minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + + if (ecma_number_is_nan (minutes)) + { + return nan; + } + + ecma_number_t timezone_offset = ecma_date_make_time (hours, minutes, ECMA_NUMBER_ZERO, ECMA_NUMBER_ZERO); + + time += is_timezone_sign_negative ? timezone_offset : -timezone_offset; + } + + if (date_str_curr_p < date_str_end_p) + { + return nan; + } + + ecma_number_t date = ecma_date_make_day (year, month - 1, day); + return ecma_date_make_date (date, time); +} /* ecma_builtin_date_parse_toString_formats */ + +/** + * The Date object's 'parse' routine + * + * See also: + * ECMA-262 v5, 15.9.4.2 Date.parse (string) + * ECMA-262 v5, 15.9.1.15 Date Time String Format + * ECMA-262 v9, 20.3.4.41 Date.prototype.toString () + * ECMA-262 v9, 20.3.4.43 Date.prototype.toUTCString () + * + * @return parsed time + */ +static ecma_number_t +ecma_builtin_date_parse (ecma_string_t *string_p) /**< string */ +{ + ECMA_STRING_TO_UTF8_STRING (string_p, str_p, str_size); + const lit_utf8_byte_t *date_str_curr_p = str_p; + const lit_utf8_byte_t *date_str_end_p = str_p + str_size; + + /* try to parse date string as ISO string - ECMA-262 v5, 15.9.1.15 */ + ecma_number_t tv = ecma_builtin_date_parse_basic (date_str_curr_p, date_str_end_p); + + if (ecma_number_is_nan (tv)) + { + /* try to parse date string in Date.prototype.toString() or toUTCString() format */ + tv = ecma_builtin_date_parse_toString_formats (date_str_curr_p, date_str_end_p); + } + + ECMA_FINALIZE_UTF8_STRING (str_p, str_size); + + return tv; +} /* ecma_builtin_date_parse */ + +/** + * The Date object's 'UTC' routine + * + * See also: + * ECMA-262 v5, 15.9.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_date_utc (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (args_number < 1) + { + return ecma_make_nan_value (); + } + + ecma_number_t tv; + + if (!ecma_date_construct_helper (args, args_number, &tv)) + { + return ECMA_VALUE_ERROR; + } + + return ecma_make_number_value ((ecma_number_t) ecma_date_time_clip (tv)); +} /* ecma_builtin_date_utc */ + +/** + * Helper method to get the current time + * + * @return ecma_number_t + */ +static ecma_number_t +ecma_builtin_date_now_helper (void) +{ + return floor (DOUBLE_TO_ECMA_NUMBER_T (jerry_port_current_time ())); +} /* ecma_builtin_date_now_helper */ + +/** + * Construct a date object with the given [[DateValue]] + * + * Note: New target must be a valid object + * + * @return ECMA_VALUE_ERROR - if the operation fails + * constructed date object - otherwise + */ +static ecma_value_t +ecma_builtin_date_create (ecma_number_t tv) +{ + JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p) != NULL); + + ecma_object_t *prototype_obj_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_DATE_PROTOTYPE); + + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, sizeof (ecma_date_object_t), ECMA_OBJECT_TYPE_CLASS); + ecma_deref_object (prototype_obj_p); + + ecma_date_object_t *date_object_p = (ecma_date_object_t *) obj_p; + date_object_p->header.u.cls.type = ECMA_OBJECT_CLASS_DATE; + date_object_p->header.u.cls.u1.date_flags = ECMA_DATE_TZA_NONE; + date_object_p->header.u.cls.u3.tza = 0; + date_object_p->date_value = tv; + + return ecma_make_object_value (obj_p); +} /* ecma_builtin_date_create */ + +/** + * Handle calling [[Call]] of built-in Date object + * + * See also: + * ECMA-262 v5, 15.9.2.1 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_date_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_UNUSED (arguments_list_p); + JERRY_UNUSED (arguments_list_len); + + return ecma_date_value_to_string (ecma_builtin_date_now_helper ()); +} /* ecma_builtin_date_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Date object + * + * See also: + * ECMA-262 v5, 15.9.3.1 + * ECMA-262 v11, 20.4.2 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_date_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + /* 20.4.2.3 */ + if (arguments_list_len == 0) + { + return ecma_builtin_date_create (ecma_builtin_date_now_helper ()); + } + + ecma_number_t tv; + /* 20.4.2.2 */ + if (arguments_list_len == 1) + { + ecma_value_t argument = arguments_list_p[0]; + + /* 4.a */ + if (ecma_is_value_object (argument) + && ecma_object_class_is (ecma_get_object_from_value (argument), ECMA_OBJECT_CLASS_DATE)) + { + return ecma_builtin_date_create (((ecma_date_object_t *) ecma_get_object_from_value (argument))->date_value); + } + /* 4.b */ + ecma_value_t primitive = ecma_op_to_primitive (argument, ECMA_PREFERRED_TYPE_NO); + + if (ECMA_IS_VALUE_ERROR (primitive)) + { + return primitive; + } + + if (ecma_is_value_string (primitive)) + { + ecma_string_t *prim_str_p = ecma_get_string_from_value (primitive); + tv = ecma_builtin_date_parse (prim_str_p); + ecma_deref_ecma_string (prim_str_p); + } + else + { + ecma_value_t prim_value = ecma_op_to_number (primitive, &tv); + ecma_free_value (primitive); + + if (ECMA_IS_VALUE_ERROR (prim_value)) + { + return prim_value; + } + } + } + /* 20.4.2.1 */ + else if (ecma_date_construct_helper (arguments_list_p, arguments_list_len, &tv)) + { + tv = ecma_date_utc (tv); + } + else + { + return ECMA_VALUE_ERROR; + } + + return ecma_builtin_date_create (ecma_date_time_clip (tv)); +} /* ecma_builtin_date_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_date_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (this_arg); + + switch (builtin_routine_id) + { + case ECMA_DATE_ROUTINE_NOW: + { + return ecma_make_number_value (ecma_builtin_date_now_helper ()); + } + case ECMA_DATE_ROUTINE_UTC: + { + return ecma_builtin_date_utc (arguments_list_p, arguments_number); + } + case ECMA_DATE_ROUTINE_PARSE: + { + if (arguments_number < 1) + { + return ecma_make_nan_value (); + } + + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_make_number_value (ecma_date_time_clip (ecma_builtin_date_parse (str_p))); + ecma_deref_ecma_string (str_p); + + return result; + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_date_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATE */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h new file mode 100644 index 00000000..a50ac00f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Date built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_DATE + +/* ECMA-262 v5, 15.9.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_DATE_PROTOTYPE, ECMA_PROPERTY_FIXED) + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 7, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +ROUTINE (LIT_MAGIC_STRING_PARSE, ECMA_DATE_ROUTINE_PARSE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_UTC_U, ECMA_DATE_ROUTINE_UTC, NON_FIXED, 7) +ROUTINE (LIT_MAGIC_STRING_NOW, ECMA_DATE_ROUTINE_NOW, 0, 0) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_DATE_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_DATE */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.cpp new file mode 100644 index 00000000..db69f1b9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.cpp @@ -0,0 +1,180 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" +#include "lit-char-helpers.h" +#include "lit-magic-strings.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ERROR_PROTOTYPE_ROUTINE_START = 0, + ECMA_ERROR_PROTOTYPE_ROUTINE_TO_STRING, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-error-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup errorprototype ECMA Error.prototype object built-in + * @{ + */ + +/** + * Helper method to get a property value from an error object + * + * @return ecma_string_t + */ +static ecma_string_t * +ecma_builtin_error_prototype_object_to_string_helper (ecma_object_t *obj_p, /**< error object */ + lit_magic_string_id_t property_id, /**< property id */ + lit_magic_string_id_t default_value) /**< default prop value */ +{ + ecma_value_t prop_value = ecma_op_object_get_by_magic_id (obj_p, property_id); + + if (ECMA_IS_VALUE_ERROR (prop_value)) + { + return NULL; + } + + if (ecma_is_value_undefined (prop_value)) + { + return ecma_get_magic_string (default_value); + } + + ecma_string_t *ret_str_p = ecma_op_to_string (prop_value); + ecma_free_value (prop_value); + + return ret_str_p; +} /* ecma_builtin_error_prototype_object_to_string_helper */ + +/** + * The Error.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v5, 15.11.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_error_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ +{ + /* 2. */ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); + + ecma_string_t *name_string_p = + ecma_builtin_error_prototype_object_to_string_helper (obj_p, LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ERROR_UL); + + if (JERRY_UNLIKELY (name_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_string_t *msg_string_p = + ecma_builtin_error_prototype_object_to_string_helper (obj_p, LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY); + + if (JERRY_UNLIKELY (msg_string_p == NULL)) + { + ecma_deref_ecma_string (name_string_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_string_is_empty (name_string_p)) + { + return ecma_make_string_value (msg_string_p); + } + + if (ecma_string_is_empty (msg_string_p)) + { + return ecma_make_string_value (name_string_p); + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (name_string_p); + + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) ": ", 2); + ecma_stringbuilder_append (&builder, msg_string_p); + + ecma_deref_ecma_string (name_string_p); + ecma_deref_ecma_string (msg_string_p); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_error_prototype_object_to_string */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_error_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments passed to + * routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_number, arguments_list_p); + + switch (builtin_routine_id) + { + case ECMA_ERROR_PROTOTYPE_ROUTINE_TO_STRING: + { + return ecma_builtin_error_prototype_object_to_string (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_error_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.inc.h new file mode 100644 index 00000000..751094ca --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Error.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.4.2 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.4.3 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_ERROR_PROTOTYPE_ROUTINE_TO_STRING, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.cpp new file mode 100644 index 00000000..846186a1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.cpp @@ -0,0 +1,93 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-error.inc.h" +#define BUILTIN_UNDERSCORED_ID error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup error ECMA Error object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Error object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_COMMON, arguments_list_p, arguments_list_len); +} /* ecma_builtin_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Error object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h new file mode 100644 index 00000000..d8cff1bd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Error built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.7.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.cpp new file mode 100644 index 00000000..37588033 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-evalerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID eval_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.inc.h new file mode 100644 index 00000000..1f13dd2f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * EvalError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_EVAL_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_EVAL_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.cpp new file mode 100644 index 00000000..341d179b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-evalerror.inc.h" +#define BUILTIN_UNDERSCORED_ID eval_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup evalerror ECMA EvalError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in EvalError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_eval_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_EVAL, arguments_list_p, arguments_list_len); +} /* ecma_builtin_eval_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in EvalError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_eval_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_eval_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_eval_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h new file mode 100644 index 00000000..29c8f966 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * EvalError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_EVAL_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.cpp new file mode 100644 index 00000000..555f5f3d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.cpp @@ -0,0 +1,550 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-function-prototype.h" + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-extended-info.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" + +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_FUNCTION_PROTOTYPE_ROUTINE_START = 0, + ECMA_FUNCTION_PROTOTYPE_TO_STRING, + ECMA_FUNCTION_PROTOTYPE_CALL, + ECMA_FUNCTION_PROTOTYPE_APPLY, + ECMA_FUNCTION_PROTOTYPE_BIND, + ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-function-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID function_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup functionprototype ECMA Function.prototype object built-in + * @{ + */ + +/** + * Maximum number of arguments for an apply function. + */ +#define ECMA_FUNCTION_APPLY_ARGUMENT_COUNT_LIMIT 65535 + +/** + * The Function.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v5, 15.3.4.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_function_prototype_object_to_string (ecma_object_t *func_obj_p) /**< this argument object */ +{ + if (ecma_get_object_type (func_obj_p) != ECMA_OBJECT_TYPE_FUNCTION) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE); + } + +#if JERRY_FUNCTION_TO_STRING + const ecma_compiled_code_t *bytecode_p; + bytecode_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) func_obj_p); + + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) + { + uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (bytecode_p); + uint8_t extended_info = *extended_info_p; + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE) + { + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) + { + ecma_extended_info_decode_vlq (&extended_info_p); + } + + uint32_t range_start = ecma_extended_info_decode_vlq (&extended_info_p); + uint32_t range_size = ecma_extended_info_decode_vlq (&extended_info_p); + ecma_value_t source_code; + + if (!(extended_info & CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS)) + { + source_code = script_p->source_code; +#if JERRY_SNAPSHOT_EXEC + if (ecma_is_value_magic_string (source_code, LIT_MAGIC_STRING__EMPTY)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + } + else + { +#if JERRY_SNAPSHOT_EXEC + if (!(script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA); + } +#else /* !JERRY_SNAPSHOT_EXEC */ + JERRY_ASSERT (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS); +#endif /* JERRY_SNAPSHOT_EXEC */ + + source_code = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, script_p->refs_and_type); + } + + ecma_string_t *result_string_p; + + ECMA_STRING_TO_UTF8_STRING (ecma_get_string_from_value (source_code), source_p, source_size); + result_string_p = ecma_new_ecma_string_from_utf8 (source_p + range_start, range_size); + ECMA_FINALIZE_UTF8_STRING (source_p, source_size); + + return ecma_make_string_value (result_string_p); + } + } + +#if JERRY_SNAPSHOT_EXEC + if (!(script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA); + } +#else /* !JERRY_SNAPSHOT_EXEC */ + JERRY_ASSERT (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS); +#endif /* JERRY_SNAPSHOT_EXEC */ + + lit_magic_string_id_t header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON; + + switch (CBC_FUNCTION_GET_TYPE (bytecode_p->status_flags)) + { + case CBC_FUNCTION_GENERATOR: + { + header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_GENERATOR; + break; + } + case CBC_FUNCTION_ASYNC_GENERATOR: + { + header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR; + break; + } + case CBC_FUNCTION_ASYNC: + { + header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC; + break; + } + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (ecma_get_magic_string (header_id)); + ecma_value_t function_arguments = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, script_p->refs_and_type); + + ecma_stringbuilder_append (&builder, ecma_get_string_from_value (function_arguments)); + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\n) {\n", 5); + ecma_stringbuilder_append (&builder, ecma_get_string_from_value (script_p->source_code)); + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\n}", 2); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +#else /* !JERRY_FUNCTION_TO_STRING */ + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA); +#endif /* JERRY_FUNCTION_TO_STRING */ +} /* ecma_builtin_function_prototype_object_to_string */ + +/** + * The Function.prototype object's 'apply' routine + * + * See also: + * ECMA-262 v5, 15.3.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_function_prototype_object_apply (ecma_object_t *func_obj_p, /**< this argument object */ + ecma_value_t arg1, /**< first argument */ + ecma_value_t arg2) /**< second argument */ +{ + /* 2. */ + if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2)) + { + return ecma_op_function_call (func_obj_p, arg1, NULL, 0); + } + + /* 3. */ + if (!ecma_is_value_object (arg2)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arg2); + + /* 4-5. */ + ecma_length_t length; + ecma_value_t len_value = ecma_op_object_get_length (obj_p, &length); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + return len_value; + } + + if (length >= ECMA_FUNCTION_APPLY_ARGUMENT_COUNT_LIMIT) + { + return ecma_raise_range_error (ECMA_ERR_TOO_MANY_ARGUMENTS_DECLARED_FOR_FUNCTION_APPLY); + } + + /* 6. */ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + JMEM_DEFINE_LOCAL_ARRAY (arguments_list_p, length, ecma_value_t); + ecma_length_t index = 0; + + /* 7. */ + for (index = 0; index < length; index++) + { + ecma_value_t get_value = ecma_op_object_get_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + ret_value = get_value; + break; + } + + arguments_list_p[index] = get_value; + } + + if (ecma_is_value_empty (ret_value)) + { + JERRY_ASSERT (index == length); + ret_value = ecma_op_function_call (func_obj_p, arg1, arguments_list_p, (uint32_t) length); + } + + for (uint32_t remove_index = 0; remove_index < index; remove_index++) + { + ecma_free_value (arguments_list_p[remove_index]); + } + + JMEM_FINALIZE_LOCAL_ARRAY (arguments_list_p); + + return ret_value; +} /* ecma_builtin_function_prototype_object_apply */ + +/** + * The Function.prototype object's 'call' routine + * + * See also: + * ECMA-262 v5, 15.3.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_function_prototype_object_call (ecma_object_t *func_obj_p, /**< this argument object */ + const ecma_value_t *arguments_list_p, /**< list of arguments */ + uint32_t arguments_number) /**< number of arguments */ +{ + if (arguments_number == 0) + { + /* Even a 'this' argument is missing. */ + return ecma_op_function_call (func_obj_p, ECMA_VALUE_UNDEFINED, NULL, 0); + } + + return ecma_op_function_call (func_obj_p, + arguments_list_p[0], + arguments_list_p + 1, + (uint32_t) (arguments_number - 1u)); +} /* ecma_builtin_function_prototype_object_call */ + +/** + * The Function.prototype object's 'bind' routine + * + * See also: + * ECMA-262 v5, 15.3.4.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_function_prototype_object_bind (ecma_object_t *this_arg_obj_p, /**< this argument object */ + const ecma_value_t *arguments_list_p, /**< list of arguments */ + uint32_t arguments_number) /**< number of arguments */ +{ + /* 4. 11. 18. */ + ecma_object_t *prototype_obj_p; + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (this_arg_obj_p)) + { + ecma_value_t proto = ecma_proxy_object_get_prototype_of (this_arg_obj_p); + + if (ECMA_IS_VALUE_ERROR (proto)) + { + return proto; + } + prototype_obj_p = ecma_is_value_null (proto) ? NULL : ecma_get_object_from_value (proto); + } + else + { +#endif /* JERRY_BUILTIN_PROXY */ + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (this_arg_obj_p); + if (proto_cp != JMEM_CP_NULL) + { + prototype_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + ecma_ref_object (prototype_obj_p); + } + else + { + prototype_obj_p = NULL; + } +#if JERRY_BUILTIN_PROXY + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_object_t *function_p; + ecma_bound_function_t *bound_func_p; + + if (arguments_number == 0 || (arguments_number == 1 && !ecma_is_value_integer_number (arguments_list_p[0]))) + { + function_p = ecma_create_object (prototype_obj_p, sizeof (ecma_bound_function_t), ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + /* 8. */ + bound_func_p = (ecma_bound_function_t *) function_p; + ECMA_SET_NON_NULL_POINTER_TAG (bound_func_p->header.u.bound_function.target_function, this_arg_obj_p, 0); + + bound_func_p->header.u.bound_function.args_len_or_this = ECMA_VALUE_UNDEFINED; + + if (arguments_number != 0) + { + bound_func_p->header.u.bound_function.args_len_or_this = ecma_copy_value_if_not_object (arguments_list_p[0]); + } + } + else + { + JERRY_ASSERT (arguments_number > 0); + + size_t obj_size = sizeof (ecma_bound_function_t) + (arguments_number * sizeof (ecma_value_t)); + + function_p = ecma_create_object (prototype_obj_p, obj_size, ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + /* 8. */ + bound_func_p = (ecma_bound_function_t *) function_p; + ECMA_SET_NON_NULL_POINTER_TAG (bound_func_p->header.u.bound_function.target_function, this_arg_obj_p, 0); + + /* NOTE: This solution provides temporary false data about the object's size + but prevents GC from freeing it until it's not fully initialized. */ + bound_func_p->header.u.bound_function.args_len_or_this = ECMA_VALUE_UNDEFINED; + ecma_value_t *args_p = (ecma_value_t *) (bound_func_p + 1); + + for (uint32_t i = 0; i < arguments_number; i++) + { + *args_p++ = ecma_copy_value_if_not_object (arguments_list_p[i]); + } + + ecma_value_t args_len_or_this = ecma_make_integer_value ((ecma_integer_value_t) arguments_number); + bound_func_p->header.u.bound_function.args_len_or_this = args_len_or_this; + } + + if (prototype_obj_p != NULL) + { + ecma_deref_object (prototype_obj_p); + } + + bound_func_p->target_length = ecma_make_integer_value (0); + + ecma_string_t *len_string = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (this_arg_obj_p, len_string, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_deref_object (function_p); + return status; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (status)) + { + ecma_free_property_descriptor (&prop_desc); + ecma_value_t len_value = ecma_op_object_get (this_arg_obj_p, len_string); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (function_p); + return len_value; + } + + if (ecma_is_value_number (len_value)) + { + ecma_number_t len_num; + ecma_op_to_integer (len_value, &len_num); + bound_func_p->target_length = ecma_make_number_value (len_num); + } + ecma_free_value (len_value); + } + + /* 12. */ + ecma_value_t name_value = ecma_op_object_get_by_magic_id (this_arg_obj_p, LIT_MAGIC_STRING_NAME); + if (ECMA_IS_VALUE_ERROR (name_value)) + { + ecma_deref_object (function_p); + return name_value; + } + + ecma_string_t *name_p; + + if (ecma_is_value_string (name_value)) + { + name_p = ecma_get_string_from_value (name_value); + } + else + { + ecma_free_value (name_value); + name_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_value_t bound_function_name = ecma_op_function_form_name (name_p, (char*)"bound ", 6); + + ecma_deref_ecma_string (name_p); + + ecma_property_value_t *name_prop_value_p; + name_prop_value_p = ecma_create_named_data_property (function_p, + ecma_get_magic_string (LIT_MAGIC_STRING_NAME), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + + name_prop_value_p->value = bound_function_name; + + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. + * + * See also: ecma_object_get_class_name + */ + + /* 22. */ + return ecma_make_object_value (function_p); +} /* ecma_builtin_function_prototype_object_bind */ + +/** + * Handle calling [[Call]] of built-in Function.prototype object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_function_prototype_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_function_prototype_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Function.prototype object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_function_prototype_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_FUNCTION_PROTOTYPE_NOT_A_CONSTRUCTOR); +} /* ecma_builtin_function_prototype_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_function_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + if (!ecma_op_is_callable (this_arg)) + { + if (JERRY_UNLIKELY (builtin_routine_id == ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE)) + { + return ECMA_VALUE_FALSE; + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_FUNCTION); + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); + + switch (builtin_routine_id) + { + case ECMA_FUNCTION_PROTOTYPE_TO_STRING: + { + return ecma_builtin_function_prototype_object_to_string (func_obj_p); + } + case ECMA_FUNCTION_PROTOTYPE_APPLY: + { + return ecma_builtin_function_prototype_object_apply (func_obj_p, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_FUNCTION_PROTOTYPE_CALL: + { + return ecma_builtin_function_prototype_object_call (func_obj_p, arguments_list_p, arguments_number); + } + case ECMA_FUNCTION_PROTOTYPE_BIND: + { + return ecma_builtin_function_prototype_object_bind (func_obj_p, arguments_list_p, arguments_number); + } + case ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE: + { + return ecma_op_object_has_instance (func_obj_p, arguments_list_p[0]); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_function_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.h new file mode 100644 index 00000000..363681f5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.h @@ -0,0 +1,24 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BUILTIN_FUNCTION_PROTOTYPE_H +#define ECMA_BUILTIN_FUNCTION_PROTOTYPE_H + +#include "ecma-globals.h" + +ecma_value_t +ecma_builtin_function_prototype_object_apply (ecma_object_t *func_obj_p, ecma_value_t arg1, ecma_value_t arg2); + +#endif /* !ECMA_BUILTIN_FUNCTION_PROTOTYPE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h new file mode 100644 index 00000000..8bab444f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h @@ -0,0 +1,55 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Function.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.3.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_FUNCTION, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Number properties: + * (property name, object pointer getter) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_FUNCTION_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_APPLY, ECMA_FUNCTION_PROTOTYPE_APPLY, 2, 2) +ROUTINE (LIT_MAGIC_STRING_CALL, ECMA_FUNCTION_PROTOTYPE_CALL, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_BIND, ECMA_FUNCTION_PROTOTYPE_BIND, NON_FIXED, 1) + +/** + * ECMA-262 v6.0 19.2.3.6 @@hasInstance + * the property attributes are: { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. + */ +ROUTINE_WITH_FLAGS (LIT_GLOBAL_SYMBOL_HAS_INSTANCE, ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE, 1, 1, 0 /* flags */) +ACCESSOR_BUILTIN_FUNCTION (LIT_MAGIC_STRING_ARGUMENTS, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +ACCESSOR_BUILTIN_FUNCTION (LIT_MAGIC_STRING_CALLER, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp new file mode 100644 index 00000000..7c8e1dfd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-conversion.h" +#include "ecma-eval.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-lex-env.h" + +#include "js-parser.h" +#include "lit-magic-strings.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-function.inc.h" +#define BUILTIN_UNDERSCORED_ID function +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup function ECMA Function object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Function object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_builtin_function_dispatch_construct (arguments_list_p, arguments_list_len); +} /* ecma_builtin_function_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Function object + * + * See also: + * ECMA-262 v5, 15.3. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_create_dynamic_function (arguments_list_p, arguments_list_len, ECMA_PARSE_NO_OPTS); +} /* ecma_builtin_function_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h new file mode 100644 index 00000000..92e50eda --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Function built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.3.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* Number properties: + * (property name, object pointer getter) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.cpp new file mode 100644 index 00000000..acb25eec --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.cpp @@ -0,0 +1,68 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" +#include "ecma-function-object.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-generator-function.inc.h" +#define BUILTIN_UNDERSCORED_ID generator_function +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup generatorfunction ECMA GeneratorFunction object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in GeneratorFunction object + * + * @return constructed generator function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_generator_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_dynamic_function (arguments_list_p, arguments_list_len, ECMA_PARSE_GENERATOR_FUNCTION); +} /* ecma_builtin_generator_function_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in GeneratorFunction object + * + * @return constructed generator function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_generator_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_generator_function_dispatch_call (arguments_list_p, arguments_list_len); +} /* ecma_builtin_generator_function_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.inc.h new file mode 100644 index 00000000..39416a91 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.inc.h @@ -0,0 +1,31 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %GeneratorFunction% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v6, 25.2.2 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.2.2.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.2.2.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_GENERATOR, ECMA_PROPERTY_FIXED) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.cpp new file mode 100644 index 00000000..da6269de --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.cpp @@ -0,0 +1,258 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" + +#include "jcontext.h" +#include "opcodes.h" +#include "vm-defines.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_GENERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_GENERATOR_PROTOTYPE_ROUTINE_NEXT, + ECMA_GENERATOR_PROTOTYPE_ROUTINE_THROW, + ECMA_GENERATOR_PROTOTYPE_ROUTINE_RETURN +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-generator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID generator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup generatorprototype ECMA Generator.prototype object built-in + * @{ + */ + +/** + * Convert routine type to operation type. + */ +#define ECMA_GENERATOR_ROUTINE_TO_OPERATION(type) \ + ((ecma_iterator_command_type_t) ((type) -ECMA_GENERATOR_PROTOTYPE_ROUTINE_NEXT)) + +JERRY_STATIC_ASSERT ((ECMA_GENERATOR_ROUTINE_TO_OPERATION (ECMA_GENERATOR_PROTOTYPE_ROUTINE_NEXT) == ECMA_ITERATOR_NEXT), + convert_ecma_generator_routine_next_to_ecma_iterator_next_failed); + +JERRY_STATIC_ASSERT ((ECMA_GENERATOR_ROUTINE_TO_OPERATION (ECMA_GENERATOR_PROTOTYPE_ROUTINE_THROW) == ECMA_ITERATOR_THROW), + convert_ecma_generator_routine_throw_to_ecma_iterator_throw_failed); + +JERRY_STATIC_ASSERT ((ECMA_GENERATOR_ROUTINE_TO_OPERATION (ECMA_GENERATOR_PROTOTYPE_ROUTINE_RETURN) == ECMA_ITERATOR_RETURN), + convert_ecma_generator_routine_return_to_ecma_iterator_return_failed); + +/** + * Helper function for next / return / throw + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_generator_prototype_object_do (vm_executable_object_t *generator_object_p, /**< generator object */ + ecma_value_t arg, /**< argument */ + ecma_iterator_command_type_t resume_mode) /**< resume mode */ +{ + arg = ecma_copy_value (arg); + + while (true) + { + if (generator_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + { + if (generator_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_RUNNING) + { + return ecma_raise_type_error (ECMA_ERR_GENERATOR_IS_CURRENTLY_UNDER_EXECUTION); + } + + ecma_value_t iterator = generator_object_p->iterator; + ecma_value_t next_method = generator_object_p->frame_ctx.stack_top_p[-1]; + + bool done = false; + + generator_object_p->extended_object.u.cls.u2.executable_obj_flags |= ECMA_EXECUTABLE_OBJECT_RUNNING; + ecma_value_t result = ecma_op_iterator_do (resume_mode, iterator, next_method, arg, &done); + ecma_free_value (arg); + generator_object_p->extended_object.u.cls.u2.executable_obj_flags &= (uint8_t) ~ECMA_EXECUTABLE_OBJECT_RUNNING; + + if (ECMA_IS_VALUE_ERROR (result)) + { + arg = result; + } + else if (done) + { + arg = ecma_op_iterator_value (result); + ecma_free_value (result); + + if (resume_mode == ECMA_ITERATOR_THROW) + { + resume_mode = ECMA_ITERATOR_NEXT; + } + } + else + { + return result; + } + + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (generator_object_p); + generator_object_p->iterator = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (generator_object_p->frame_ctx.stack_top_p[-1] == ECMA_VALUE_UNDEFINED + || ecma_is_value_object (generator_object_p->frame_ctx.stack_top_p[-1])); + generator_object_p->frame_ctx.stack_top_p--; + + if (ECMA_IS_VALUE_ERROR (arg)) + { + arg = jcontext_take_exception (); + resume_mode = ECMA_ITERATOR_THROW; + } + } + + if (resume_mode == ECMA_ITERATOR_RETURN) + { + generator_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_return; + } + else if (resume_mode == ECMA_ITERATOR_THROW) + { + generator_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + } + + ecma_value_t value = opfunc_resume_executable_object (generator_object_p, arg); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + bool done; + done = (generator_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_COMPLETED); + + if (!done) + { + const uint8_t *byte_code_p = generator_object_p->frame_ctx.byte_code_p; + + JERRY_ASSERT (byte_code_p[-2] == CBC_EXT_OPCODE + && (byte_code_p[-1] == CBC_EXT_YIELD || byte_code_p[-1] == CBC_EXT_YIELD_ITERATOR)); + + if (byte_code_p[-1] == CBC_EXT_YIELD_ITERATOR) + { + ecma_value_t iterator = + ecma_op_get_iterator (value, ECMA_VALUE_SYNC_ITERATOR, generator_object_p->frame_ctx.stack_top_p); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (iterator)) + { + resume_mode = ECMA_ITERATOR_THROW; + arg = jcontext_take_exception (); + continue; + } + + ecma_deref_object (ecma_get_object_from_value (iterator)); + generator_object_p->extended_object.u.cls.u2.executable_obj_flags |= ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD; + generator_object_p->iterator = iterator; + + if (generator_object_p->frame_ctx.stack_top_p[0] != ECMA_VALUE_UNDEFINED) + { + ecma_deref_object (ecma_get_object_from_value (generator_object_p->frame_ctx.stack_top_p[0])); + } + + generator_object_p->frame_ctx.stack_top_p++; + arg = ECMA_VALUE_UNDEFINED; + continue; + } + } + + ecma_value_t result = ecma_create_iter_result_object (value, ecma_make_boolean_value (done)); + ecma_fast_free_value (value); + return result; + } +} /* ecma_builtin_generator_prototype_object_do */ + +/** + * Dispatcher of the Generator built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_generator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + vm_executable_object_t *executable_object_p = NULL; + + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_GENERATOR)) + { + executable_object_p = (vm_executable_object_t *) object_p; + } + } + + if (executable_object_p == NULL) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_GENERATOR_OBJECT); + } + + if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_RUNNING) + { + return ecma_raise_type_error (ECMA_ERR_GENERATOR_IS_CURRENTLY_UNDER_EXECUTION); + } + + if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_COMPLETED) + { + if (builtin_routine_id != ECMA_GENERATOR_PROTOTYPE_ROUTINE_THROW) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + jcontext_raise_exception (ecma_copy_value (arguments_list_p[0])); + return ECMA_VALUE_ERROR; + } + + return ecma_builtin_generator_prototype_object_do (executable_object_p, + arguments_list_p[0], + ECMA_GENERATOR_ROUTINE_TO_OPERATION (builtin_routine_id)); +} /* ecma_builtin_generator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.inc.h new file mode 100644 index 00000000..07086dbd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Generator.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 25.3.1.5 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_GENERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_GENERATOR, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_GENERATOR_PROTOTYPE_ROUTINE_NEXT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_RETURN, ECMA_GENERATOR_PROTOTYPE_ROUTINE_RETURN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_THROW, ECMA_GENERATOR_PROTOTYPE_ROUTINE_THROW, 1, 1) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.cpp new file mode 100644 index 00000000..6d822933 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.cpp @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-generator.inc.h" +#define BUILTIN_UNDERSCORED_ID generator +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup generator ECMA Generator object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.inc.h new file mode 100644 index 00000000..b45bd937 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.inc.h @@ -0,0 +1,31 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %Generator% built-in description (GeneratorFunction.prototype) + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v6, 25.3.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_GENERATOR_FUNCTION, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.3.2.3.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.3.2.3.3 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.cpp new file mode 100644 index 00000000..d9ccc8ff --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.cpp @@ -0,0 +1,700 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-eval.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "jrt-bit-fields.h" +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "lit-char-helpers.h" +#include "lit-magic-strings.h" +#include "lit-strings.h" +#include "vm.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_GLOBAL_ROUTINE_START = 0, + /* Note: these 5 routine ids must be in this order */ + ECMA_GLOBAL_IS_NAN, + ECMA_GLOBAL_IS_FINITE, + ECMA_GLOBAL_EVAL, + ECMA_GLOBAL_PARSE_INT, + ECMA_GLOBAL_PARSE_FLOAT, + ECMA_GLOBAL_DECODE_URI, + ECMA_GLOBAL_DECODE_URI_COMPONENT, + ECMA_GLOBAL_ENCODE_URI, + ECMA_GLOBAL_ENCODE_URI_COMPONENT, + ECMA_GLOBAL_ESCAPE, + ECMA_GLOBAL_UNESCAPE, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-global.inc.h" +#define BUILTIN_UNDERSCORED_ID global +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup global ECMA Global object built-in + * @{ + */ + +/** + * The Global object's 'eval' routine + * + * See also: + * ECMA-262 v5, 15.1.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_eval (ecma_value_t x) /**< routine's first argument */ +{ + if (JERRY_UNLIKELY (!ecma_is_value_string (x))) + { + /* step 1 */ + return ecma_copy_value (x); + } + + uint32_t parse_opts = vm_is_direct_eval_form_call () ? ECMA_PARSE_DIRECT_EVAL : ECMA_PARSE_NO_OPTS; + + /* See also: ECMA-262 v5, 10.1.1 */ + if (parse_opts && vm_is_strict_mode ()) + { + JERRY_ASSERT (parse_opts & ECMA_PARSE_DIRECT_EVAL); + parse_opts |= ECMA_PARSE_STRICT_MODE; + } + + if (vm_is_direct_eval_form_call ()) + { + parse_opts |= ECMA_GET_LOCAL_PARSE_OPTS (); + } + + /* steps 2 to 8 */ + return ecma_op_eval (x, parse_opts); +} /* ecma_builtin_global_object_eval */ + +/** + * The Global object's 'isNaN' routine + * + * See also: + * ECMA-262 v5, 15.1.2.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_is_nan (ecma_number_t arg_num) /**< routine's first argument */ +{ + return ecma_make_boolean_value (ecma_number_is_nan (arg_num)); +} /* ecma_builtin_global_object_is_nan */ + +/** + * The Global object's 'isFinite' routine + * + * See also: + * ECMA-262 v5, 15.1.2.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_is_finite (ecma_number_t arg_num) /**< routine's first argument */ +{ + bool is_finite = !(ecma_number_is_nan (arg_num) || ecma_number_is_infinity (arg_num)); + + return ecma_make_boolean_value (is_finite); +} /* ecma_builtin_global_object_is_finite */ + +/** + * Helper function to check whether a character is in a character bitset. + * + * @return true if the character is in the character bitset. + */ +static bool +ecma_builtin_global_object_character_is_in (uint32_t character, /**< character */ + const uint8_t *bitset) /**< character set */ +{ + JERRY_ASSERT (character < 128); + return (bitset[character >> 3] & (1u << (character & 0x7))) != 0; +} /* ecma_builtin_global_object_character_is_in */ + +/** + * Unescaped URI characters bitset: + * One bit for each character between 0 - 127. + * Bit is set if the character is in the unescaped URI set. + */ +static const uint8_t unescaped_uri_set[16] = { 0x0, 0x0, 0x0, 0x0, 0xda, 0xff, 0xff, 0xaf, + 0xff, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x47 }; + +/** + * Unescaped URI component characters bitset: + * One bit for each character between 0 - 127. + * Bit is set if the character is in the unescaped component URI set. + */ +static const uint8_t unescaped_uri_component_set[16] = { 0x0, 0x0, 0x0, 0x0, 0x82, 0x67, 0xff, 0x3, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x47 }; + +/** + * Format is a percent sign followed by two hex digits. + */ +#define URI_ENCODED_BYTE_SIZE (3) + +/** + * The Global object's 'decodeURI' and 'decodeURIComponent' routines + * + * See also: + * ECMA-262 v5, 15.1.3.1 + * ECMA-262 v5, 15.1.3.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_decode_uri_helper (lit_utf8_byte_t *input_start_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t input_size, /**< routine's first argument's + * string buffer's size */ + const uint8_t *reserved_uri_bitset) /**< reserved characters bitset */ +{ + lit_utf8_byte_t *input_char_p = input_start_p; + lit_utf8_byte_t *input_end_p = input_start_p + input_size; + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + while (input_char_p < input_end_p) + { + if (*input_char_p != '%') + { + ecma_stringbuilder_append_byte (&builder, *input_char_p++); + continue; + } + + uint32_t hex_value = lit_char_hex_lookup (input_char_p + 1, input_end_p, 2); + if (hex_value == UINT32_MAX) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_INVALID_HEXADECIMAL_VALUE); + } + + ecma_char_t decoded_byte = (ecma_char_t) hex_value; + input_char_p += URI_ENCODED_BYTE_SIZE; + + if (decoded_byte <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + if (ecma_builtin_global_object_character_is_in (decoded_byte, reserved_uri_bitset) + && !ecma_builtin_global_object_character_is_in (decoded_byte, unescaped_uri_component_set)) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_PERCENT); + input_char_p -= 2; + } + else + { + ecma_stringbuilder_append_byte (&builder, (lit_utf8_byte_t) decoded_byte); + } + } + else + { + uint32_t bytes_count; + + if ((decoded_byte & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + bytes_count = 2; + } + else if ((decoded_byte & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER) + { + bytes_count = 3; + } + else if ((decoded_byte & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER) + { + bytes_count = 4; + } + else + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_INVALID_UTF8_CHARACTER); + } + + lit_utf8_byte_t octets[LIT_UTF8_MAX_BYTES_IN_CODE_POINT]; + octets[0] = (lit_utf8_byte_t) decoded_byte; + bool is_valid = true; + + for (uint32_t i = 1; i < bytes_count; i++) + { + if (input_char_p >= input_end_p || *input_char_p != '%') + { + is_valid = false; + break; + } + else + { + hex_value = lit_char_hex_lookup (input_char_p + 1, input_end_p, 2); + + if (hex_value == UINT32_MAX || (hex_value & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) + { + is_valid = false; + break; + } + + input_char_p += URI_ENCODED_BYTE_SIZE; + octets[i] = (lit_utf8_byte_t) hex_value; + } + } + + if (!is_valid || !lit_is_valid_utf8_string (octets, bytes_count, true)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_INVALID_UTF8_STRING); + } + + lit_code_point_t cp; + lit_read_code_point_from_utf8 (octets, bytes_count, &cp); + + if (lit_is_code_point_utf16_high_surrogate (cp) || lit_is_code_point_utf16_low_surrogate (cp)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_INVALID_UTF8_CODEPOINT); + } + + lit_utf8_byte_t result_chars[LIT_CESU8_MAX_BYTES_IN_CODE_POINT]; + lit_utf8_size_t cp_size = lit_code_point_to_cesu8 (cp, result_chars); + ecma_stringbuilder_append_raw (&builder, result_chars, cp_size); + } + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_global_object_decode_uri_helper */ + +/** + * Helper function to encode byte as hexadecimal values. + */ +static void +ecma_builtin_global_object_byte_to_hex (lit_utf8_byte_t *dest_p, /**< destination pointer */ + uint32_t byte) /**< value */ +{ + JERRY_ASSERT (byte < 256); + + dest_p[0] = LIT_CHAR_PERCENT; + ecma_char_t hex_digit = (ecma_char_t) (byte >> 4); + dest_p[1] = (lit_utf8_byte_t) ((hex_digit > 9) ? (hex_digit + ('A' - 10)) : (hex_digit + '0')); + hex_digit = (lit_utf8_byte_t) (byte & 0xf); + dest_p[2] = (lit_utf8_byte_t) ((hex_digit > 9) ? (hex_digit + ('A' - 10)) : (hex_digit + '0')); +} /* ecma_builtin_global_object_byte_to_hex */ + +/** + * The Global object's 'encodeURI' and 'encodeURIComponent' routines + * + * See also: + * ECMA-262 v5, 15.1.3.3 + * ECMA-262 v5, 15.1.3.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_encode_uri_helper (lit_utf8_byte_t *input_start_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t input_size, /**< routine's first argument's + * string buffer's size */ + const uint8_t *unescaped_uri_bitset_p) /**< unescaped bitset */ +{ + lit_utf8_byte_t *input_char_p = input_start_p; + const lit_utf8_byte_t *input_end_p = input_start_p + input_size; + ecma_char_t ch; + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + lit_utf8_byte_t octets[LIT_UTF8_MAX_BYTES_IN_CODE_POINT]; + memset (octets, LIT_BYTE_NULL, LIT_UTF8_MAX_BYTES_IN_CODE_POINT); + + while (input_char_p < input_end_p) + { + input_char_p += lit_read_code_unit_from_cesu8 (input_char_p, &ch); + + if (lit_is_code_point_utf16_low_surrogate (ch)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_UNICODE_SURROGATE_PAIR_MISSING); + } + + lit_code_point_t cp = ch; + + if (lit_is_code_point_utf16_high_surrogate (ch)) + { + if (input_char_p == input_end_p) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_UNICODE_SURROGATE_PAIR_MISSING); + } + + ecma_char_t next_ch; + lit_utf8_size_t read_size = lit_read_code_unit_from_cesu8 (input_char_p, &next_ch); + + if (lit_is_code_point_utf16_low_surrogate (next_ch)) + { + cp = lit_convert_surrogate_pair_to_code_point (ch, next_ch); + input_char_p += read_size; + } + else + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_UNICODE_SURROGATE_PAIR_MISSING); + } + } + + lit_utf8_size_t utf_size = lit_code_point_to_utf8 (cp, octets); + lit_utf8_byte_t result_chars[URI_ENCODED_BYTE_SIZE]; + + if (utf_size == 1) + { + if (ecma_builtin_global_object_character_is_in (octets[0], unescaped_uri_bitset_p)) + { + ecma_stringbuilder_append_byte (&builder, octets[0]); + } + else + { + ecma_builtin_global_object_byte_to_hex (result_chars, octets[0]); + ecma_stringbuilder_append_raw (&builder, result_chars, URI_ENCODED_BYTE_SIZE); + } + } + else + { + for (uint32_t i = 0; i < utf_size; i++) + { + JERRY_ASSERT (utf_size <= LIT_UTF8_MAX_BYTES_IN_CODE_POINT); + ecma_builtin_global_object_byte_to_hex (result_chars, octets[i]); + ecma_stringbuilder_append_raw (&builder, result_chars, URI_ENCODED_BYTE_SIZE); + } + } + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_global_object_encode_uri_helper */ + +#if JERRY_BUILTIN_ANNEXB + +/** + * Maximum value of a byte. + */ +#define ECMA_ESCAPE_MAXIMUM_BYTE_VALUE (255) + +/** + * Format is a percent sign followed by lowercase u and four hex digits. + */ +#define ECMA_ESCAPE_ENCODED_UNICODE_CHARACTER_SIZE (6) + +/** + * Escape characters bitset: + * One bit for each character between 0 - 127. + * Bit is set if the character does not need to be converted to %xx form. + * These characters are: a-z A-Z 0-9 @ * _ + - . / + */ +static const uint8_t ecma_escape_set[16] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0xec, 0xff, 0x3, + 0xff, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x7 }; + +/** + * The Global object's 'escape' routine + * + * See also: + * ECMA-262 v5, B.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_escape (lit_utf8_byte_t *input_start_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t input_size) /**< routine's first argument's + * string buffer's size */ +{ + const lit_utf8_byte_t *input_curr_p = input_start_p; + const lit_utf8_byte_t *input_end_p = input_start_p + input_size; + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + lit_utf8_byte_t result_chars[URI_ENCODED_BYTE_SIZE]; + + while (input_curr_p < input_end_p) + { + ecma_char_t chr = lit_cesu8_read_next (&input_curr_p); + + if (chr <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + if (ecma_builtin_global_object_character_is_in ((uint32_t) chr, ecma_escape_set)) + { + ecma_stringbuilder_append_char (&builder, chr); + } + else + { + ecma_builtin_global_object_byte_to_hex (result_chars, chr); + ecma_stringbuilder_append_raw (&builder, result_chars, URI_ENCODED_BYTE_SIZE); + } + } + else if (chr > ECMA_ESCAPE_MAXIMUM_BYTE_VALUE) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_PERCENT); + ecma_stringbuilder_append_char (&builder, LIT_CHAR_LOWERCASE_U); + + ecma_builtin_global_object_byte_to_hex (result_chars, (chr >> JERRY_BITSINBYTE)); + ecma_stringbuilder_append_raw (&builder, result_chars + 1, 2); + + ecma_builtin_global_object_byte_to_hex (result_chars, (chr & 0xff)); + ecma_stringbuilder_append_raw (&builder, result_chars + 1, 2); + } + else + { + ecma_builtin_global_object_byte_to_hex (result_chars, chr); + ecma_stringbuilder_append_raw (&builder, result_chars, URI_ENCODED_BYTE_SIZE); + } + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_global_object_escape */ + +/** + * Utility method to resolve character sequences for the 'unescape' method. + * + * Expected formats: %uxxxx or %yy + * + * @return number of characters processed during the escape resolve + */ +static uint8_t +ecma_builtin_global_object_unescape_resolve_escape (const lit_utf8_byte_t *buffer_p, /**< character buffer */ + bool unicode_sequence, /**< true if unescaping unicode sequence */ + ecma_char_t *out_result_p) /**< [out] resolved character */ +{ + JERRY_ASSERT (buffer_p != NULL); + JERRY_ASSERT (out_result_p != NULL); + + ecma_char_t unescaped_chr = 0; + uint8_t sequence_length = unicode_sequence ? 5 : 2; + uint8_t start = unicode_sequence ? 1 : 0; + + for (uint8_t i = start; i < sequence_length; i++) + { + const lit_utf8_byte_t current_char = buffer_p[i]; + + if (!lit_char_is_hex_digit (current_char)) + { + /* This was not an escape sequence, skip processing */ + return 0; + } + + unescaped_chr = (ecma_char_t) ((unescaped_chr << 4) + (ecma_char_t) lit_char_hex_to_int (current_char)); + } + + *out_result_p = unescaped_chr; + + return sequence_length; +} /* ecma_builtin_global_object_unescape_resolve_escape */ + +/** + * The Global object's 'unescape' routine + * + * See also: + * ECMA-262 v5, B.2.2 + * ECMA-262 v11, B.2.1.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_unescape (lit_utf8_byte_t *input_start_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t input_size) /**< routine's first argument's + * string buffer's size */ +{ + if (input_size == 0) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + const lit_utf8_byte_t *input_curr_p = input_start_p; + const lit_utf8_byte_t *input_end_p = input_start_p + input_size; + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + while (input_curr_p < input_end_p) + { + ecma_char_t chr = lit_cesu8_read_next (&input_curr_p); + + // potential pattern + if (chr == LIT_CHAR_PERCENT) + { + const lit_utf8_size_t chars_leftover = (lit_utf8_size_t) (input_end_p - input_curr_p); + + // potential unicode sequence + if (chars_leftover >= 5 && input_curr_p[0] == LIT_CHAR_LOWERCASE_U) + { + input_curr_p += ecma_builtin_global_object_unescape_resolve_escape (input_curr_p, true, &chr); + } + // potential two hexa sequence + else if (chars_leftover >= 2) + { + input_curr_p += ecma_builtin_global_object_unescape_resolve_escape (input_curr_p, false, &chr); + } + } + + ecma_stringbuilder_append_char (&builder, chr); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_global_object_unescape */ + +#endif /* JERRY_BUILTIN_ANNEXB */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_global_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (this_arg, arguments_number); + + ecma_value_t routine_arg_1 = arguments_list_p[0]; + + if (builtin_routine_id == ECMA_GLOBAL_EVAL) + { + return ecma_builtin_global_object_eval (routine_arg_1); + } + + if (builtin_routine_id <= ECMA_GLOBAL_IS_FINITE) + { + ecma_number_t arg_num; + + routine_arg_1 = ecma_op_to_number (routine_arg_1, &arg_num); + + if (!ecma_is_value_empty (routine_arg_1)) + { + return routine_arg_1; + } + + if (builtin_routine_id == ECMA_GLOBAL_IS_NAN) + { + return ecma_builtin_global_object_is_nan (arg_num); + } + + JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_IS_FINITE); + + return ecma_builtin_global_object_is_finite (arg_num); + } + + ecma_string_t *str_p = ecma_op_to_string (routine_arg_1); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value; + + if (builtin_routine_id <= ECMA_GLOBAL_PARSE_FLOAT) + { + ECMA_STRING_TO_UTF8_STRING (str_p, string_buff, string_buff_size); + + if (builtin_routine_id == ECMA_GLOBAL_PARSE_INT) + { + ret_value = ecma_number_parse_int (string_buff, string_buff_size, arguments_list_p[1]); + } + else + { + JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_PARSE_FLOAT); + ret_value = ecma_number_parse_float (string_buff, string_buff_size); + } + + ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size); + ecma_deref_ecma_string (str_p); + return ret_value; + } + + lit_utf8_size_t input_size = ecma_string_get_size (str_p); + + JMEM_DEFINE_LOCAL_ARRAY (input_start_p, input_size + 1, lit_utf8_byte_t); + + ecma_string_to_cesu8_bytes (str_p, input_start_p, input_size); + + input_start_p[input_size] = LIT_BYTE_NULL; + + switch (builtin_routine_id) + { +#if JERRY_BUILTIN_ANNEXB + case ECMA_GLOBAL_ESCAPE: + { + ret_value = ecma_builtin_global_object_escape (input_start_p, input_size); + break; + } + case ECMA_GLOBAL_UNESCAPE: + { + ret_value = ecma_builtin_global_object_unescape (input_start_p, input_size); + break; + } +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_GLOBAL_DECODE_URI: + case ECMA_GLOBAL_DECODE_URI_COMPONENT: + { + const uint8_t *uri_set = + (builtin_routine_id == ECMA_GLOBAL_DECODE_URI ? unescaped_uri_set : unescaped_uri_component_set); + + ret_value = ecma_builtin_global_object_decode_uri_helper (input_start_p, input_size, uri_set); + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_ENCODE_URI + || builtin_routine_id == ECMA_GLOBAL_ENCODE_URI_COMPONENT); + + const uint8_t *uri_set = + (builtin_routine_id == ECMA_GLOBAL_ENCODE_URI ? unescaped_uri_set : unescaped_uri_component_set); + + ret_value = ecma_builtin_global_object_encode_uri_helper (input_start_p, input_size, uri_set); + break; + } + } + + JMEM_FINALIZE_LOCAL_ARRAY (input_start_p); + + ecma_deref_ecma_string (str_p); + return ret_value; +} /* ecma_builtin_global_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h new file mode 100644 index 00000000..dafcdaba --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h @@ -0,0 +1,217 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Global built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Simple value properties: + * (property name, simple value, writable, enumerable, configurable) */ + +/* ECMA-262 v5, 15.1.1.3 */ +SIMPLE_VALUE (LIT_MAGIC_STRING_UNDEFINED, ECMA_VALUE_UNDEFINED, ECMA_PROPERTY_FIXED) + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v5, 15.1.1.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_NAN, ECMA_BUILTIN_NUMBER_NAN, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.1.1.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_INFINITY_UL, ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY, ECMA_PROPERTY_FIXED) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.1.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_OBJECT_UL, ECMA_BUILTIN_ID_OBJECT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_FUNCTION_UL, ECMA_BUILTIN_ID_FUNCTION, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.3 */ +#if JERRY_BUILTIN_ARRAY +OBJECT_VALUE (LIT_MAGIC_STRING_ARRAY_UL, ECMA_BUILTIN_ID_ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_ARRAY */ + +#if JERRY_BUILTIN_STRING +/* ECMA-262 v5, 15.1.4.4 */ +OBJECT_VALUE (LIT_MAGIC_STRING_STRING_UL, ECMA_BUILTIN_ID_STRING, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_STRING */ + +#if JERRY_BUILTIN_BOOLEAN +/* ECMA-262 v5, 15.1.4.5 */ +OBJECT_VALUE (LIT_MAGIC_STRING_BOOLEAN_UL, ECMA_BUILTIN_ID_BOOLEAN, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_BOOLEAN */ + +#if JERRY_BUILTIN_NUMBER +/* ECMA-262 v5, 15.1.4.6 */ +OBJECT_VALUE (LIT_MAGIC_STRING_NUMBER_UL, ECMA_BUILTIN_ID_NUMBER, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_NUMBER */ + +#if JERRY_BUILTIN_DATE +/* ECMA-262 v5, 15.1.4.7 */ +OBJECT_VALUE (LIT_MAGIC_STRING_DATE_UL, ECMA_BUILTIN_ID_DATE, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_DATE */ + +#if JERRY_BUILTIN_REGEXP +/* ECMA-262 v5, 15.1.4.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_REGEXP_UL, ECMA_BUILTIN_ID_REGEXP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_REGEXP */ + +/* ECMA-262 v5, 15.1.4.9 */ +OBJECT_VALUE (LIT_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if JERRY_BUILTIN_ERRORS + +/* ECMA-262 v5, 15.1.4.10 */ +OBJECT_VALUE (LIT_MAGIC_STRING_EVAL_ERROR_UL, ECMA_BUILTIN_ID_EVAL_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.11 */ +OBJECT_VALUE (LIT_MAGIC_STRING_RANGE_ERROR_UL, ECMA_BUILTIN_ID_RANGE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.12 */ +OBJECT_VALUE (LIT_MAGIC_STRING_REFERENCE_ERROR_UL, ECMA_BUILTIN_ID_REFERENCE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.13 */ +OBJECT_VALUE (LIT_MAGIC_STRING_SYNTAX_ERROR_UL, ECMA_BUILTIN_ID_SYNTAX_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.14 */ +OBJECT_VALUE (LIT_MAGIC_STRING_TYPE_ERROR_UL, ECMA_BUILTIN_ID_TYPE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.15 */ +OBJECT_VALUE (LIT_MAGIC_STRING_URI_ERROR_UL, ECMA_BUILTIN_ID_URI_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_ERRORS */ + +#if JERRY_BUILTIN_MATH +/* ECMA-262 v5, 15.1.5.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_MATH_UL, ECMA_BUILTIN_ID_MATH, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_REFLECT +/* ECMA-262 v6, 26.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_REFLECT_UL, ECMA_BUILTIN_ID_REFLECT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_REFLECT */ + +#if JERRY_BUILTIN_ATOMICS +/* ECMA-262 v5, 15.1.5.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_ATOMICS_U, ECMA_BUILTIN_ID_ATOMICS, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_ATOMICS */ + +#if JERRY_BUILTIN_TYPEDARRAY +OBJECT_VALUE (LIT_MAGIC_STRING_ARRAY_BUFFER_UL, ECMA_BUILTIN_ID_ARRAYBUFFER, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +OBJECT_VALUE (LIT_MAGIC_STRING_SHARED_ARRAY_BUFFER_UL, + ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + +OBJECT_VALUE (LIT_MAGIC_STRING_INT8_ARRAY_UL, ECMA_BUILTIN_ID_INT8ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_UINT8_ARRAY_UL, ECMA_BUILTIN_ID_UINT8ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_INT16_ARRAY_UL, ECMA_BUILTIN_ID_INT16ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_UINT16_ARRAY_UL, ECMA_BUILTIN_ID_UINT16ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_INT32_ARRAY_UL, ECMA_BUILTIN_ID_INT32ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_UINT32_ARRAY_UL, ECMA_BUILTIN_ID_UINT32ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_FLOAT32_ARRAY_UL, ECMA_BUILTIN_ID_FLOAT32ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if JERRY_NUMBER_TYPE_FLOAT64 +OBJECT_VALUE (LIT_MAGIC_STRING_FLOAT64_ARRAY_UL, ECMA_BUILTIN_ID_FLOAT64ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +#if JERRY_BUILTIN_BIGINT +OBJECT_VALUE (LIT_MAGIC_STRING_BIGINT64_ARRAY_UL, ECMA_BUILTIN_ID_BIGINT64ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_BIGUINT64_ARRAY_UL, ECMA_BUILTIN_ID_BIGUINT64ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_BIGINT */ + +OBJECT_VALUE (LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL, + ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#if JERRY_BUILTIN_CONTAINER +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_WEAKSET_UL, ECMA_BUILTIN_ID_WEAKSET, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_MAP_UL, ECMA_BUILTIN_ID_MAP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_SET_UL, ECMA_BUILTIN_ID_SET, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_WEAKMAP_UL, ECMA_BUILTIN_ID_WEAKMAP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_CONTAINER */ + +#if JERRY_BUILTIN_WEAKREF +OBJECT_VALUE (LIT_MAGIC_STRING_WEAKREF_UL, ECMA_BUILTIN_ID_WEAKREF, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_WEAKREF */ + +OBJECT_VALUE (LIT_MAGIC_STRING_AGGREGATE_ERROR_UL, ECMA_BUILTIN_ID_AGGREGATE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_PROMISE_UL, ECMA_BUILTIN_ID_PROMISE, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 19.4.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_SYMBOL_UL, ECMA_BUILTIN_ID_SYMBOL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if JERRY_BUILTIN_GLOBAL_THIS +/* ECMA-262 v11, 18.1.1 */ +SIMPLE_VALUE (LIT_MAGIC_STRING_GLOBAL_THIS_UL, ECMA_VALUE_GLOBAL_THIS, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_GLOBAL_THIS */ + +#if JERRY_BUILTIN_DATAVIEW +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_DATAVIEW_UL, ECMA_BUILTIN_ID_DATAVIEW, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_DATAVIEW */ + +#if JERRY_BUILTIN_PROXY +/* ECMA-262 v6, 26.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROXY_UL, ECMA_BUILTIN_ID_PROXY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_PROXY */ + +#if JERRY_BUILTIN_BIGINT +/* ECMA-262 v11, 20.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_BIGINT_UL, ECMA_BUILTIN_ID_BIGINT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_BIGINT */ + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ + +ROUTINE (LIT_MAGIC_STRING_EVAL, ECMA_GLOBAL_EVAL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_NAN, ECMA_GLOBAL_IS_NAN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_FINITE, ECMA_GLOBAL_IS_FINITE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_DECODE_URI, ECMA_GLOBAL_DECODE_URI, 1, 1) +ROUTINE (LIT_MAGIC_STRING_DECODE_URI_COMPONENT, ECMA_GLOBAL_DECODE_URI_COMPONENT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ENCODE_URI, ECMA_GLOBAL_ENCODE_URI, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ENCODE_URI_COMPONENT, ECMA_GLOBAL_ENCODE_URI_COMPONENT, 1, 1) + +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_FLOAT, LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_INT, LIT_MAGIC_STRING_PARSE_INT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if JERRY_BUILTIN_ANNEXB +ROUTINE (LIT_MAGIC_STRING_ESCAPE, ECMA_GLOBAL_ESCAPE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_UNESCAPE, ECMA_GLOBAL_UNESCAPE, 1, 1) +#endif /* JERRY_BUILTIN_ANNEXB */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.cpp new file mode 100644 index 00000000..3a048d22 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.cpp @@ -0,0 +1,60 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-handlers.h" + +#include "ecma-globals.h" +#include "ecma-iterator-object.h" +#include "ecma-promise-object.h" + +static const ecma_builtin_handler_t ecma_native_handlers[] = { +/** @cond doxygen_suppress */ +#define ECMA_NATIVE_HANDLER(id, handler, length) handler, +#include "ecma-builtin-handlers.inc.h" +#undef ECMA_NATIVE_HANDLER + /** @endcond */ +}; + +static const uint8_t ecma_native_handler_lengths[] = { +/** @cond doxygen_suppress */ +#define ECMA_NATIVE_HANDLER(id, handler, length) length, +#include "ecma-builtin-handlers.inc.h" +#undef ECMA_NATIVE_HANDLER + /** @endcond */ +}; + +/** + * Get the native handler of a built-in handler type. + * + * return Function pointer of the handler + */ +ecma_builtin_handler_t +ecma_builtin_handler_get (ecma_native_handler_id_t id) /**< handler id */ +{ + JERRY_ASSERT (id != ECMA_NATIVE_HANDLER_START && id < ECMA_NATIVE_HANDLER__COUNT); + return ecma_native_handlers[id - 1]; +} /* ecma_builtin_handler_get */ + +/** + * Get the initial 'length' value of a built-in handler type. + * + * return 'length' value of the handler + */ +uint8_t +ecma_builtin_handler_get_length (ecma_native_handler_id_t id) /**< handler id */ +{ + JERRY_ASSERT (id != ECMA_NATIVE_HANDLER_START && id < ECMA_NATIVE_HANDLER__COUNT); + return ecma_native_handler_lengths[id - 1]; +} /* ecma_builtin_handler_get_length */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.h new file mode 100644 index 00000000..01434739 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.h @@ -0,0 +1,51 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BUILTIN_HANDLERS_H +#define ECMA_BUILTIN_HANDLERS_H + +#include "ecma-builtins.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-promise-object.h" +#include "ecma-proxy-object.h" + +typedef enum +{ + /** @cond doxygen_suppress */ + ECMA_NATIVE_HANDLER_START = 0, +#define ECMA_NATIVE_HANDLER(id, handler, length) id, +#include "ecma-builtin-handlers.inc.h" +#undef ECMA_NATIVE_HANDLER + ECMA_NATIVE_HANDLER__COUNT + /** @endcond */ +} ecma_native_handler_id_t; + +typedef enum +{ + ECMA_NATIVE_HANDLER_FLAGS_NONE = 0, + ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED = (1 << 0), + ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED = (1 << 1), +} ecma_native_handler_flags_t; + +/** + * Shift for Promise helper handler function. + */ +#define ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT 2 + +ecma_builtin_handler_t ecma_builtin_handler_get (ecma_native_handler_id_t id); +uint8_t ecma_builtin_handler_get_length (ecma_native_handler_id_t id); + +#endif /* !ECMA_BUILTIN_HANDLERS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.inc.h new file mode 100644 index 00000000..b5b7a60e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_RESOLVE, ecma_promise_resolve_handler, 1) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_REJECT, ecma_promise_reject_handler, 1) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_THEN_FINALLY, ecma_promise_then_finally_cb, 1) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_CATCH_FINALLY, ecma_promise_catch_finally_cb, 1) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER, ecma_promise_all_or_all_settled_handler_cb, 1) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_CAPABILITY_EXECUTOR, ecma_op_get_capabilities_executor_cb, 2) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_ASYNC_FROM_SYNC_ITERATOR_UNWRAP, ecma_async_from_sync_iterator_unwrap_cb, 1) +#if JERRY_BUILTIN_PROXY +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROXY_REVOKE, ecma_proxy_revoke_cb, 0) +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_VALUE_THUNK, ecma_value_thunk_helper_cb, 0) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_VALUE_THROWER, ecma_value_thunk_thrower_cb, 0) diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp new file mode 100644 index 00000000..84b2596c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp @@ -0,0 +1,766 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-exceptions.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_DATE + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltinhelpers ECMA builtin helper operations + * @{ + */ + +/** + * Day names + */ +const char* day_names_p[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + +/** + * Month names + */ +const char* month_names_p[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +/** + * Calculate the elapsed days since Unix Epoch + * + * @return elapsed days since Unix Epoch + */ +int32_t +ecma_date_day_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + if (time < 0) + { + time -= ECMA_DATE_MS_PER_DAY - 1; + } + + return (int32_t) (time / ECMA_DATE_MS_PER_DAY); +} /* ecma_date_day_from_time */ + +/** + * Abstract operation: DayFromYear + * + * See also: + * ECMA-262 v11, 20.4.1.3 + * + * @return first of day in the given year + */ +static int32_t +ecma_date_day_from_year (int32_t year) /**< year value */ +{ + if (JERRY_LIKELY (year >= 1970)) + { + return (int32_t) (365 * (year - 1970) + ((year - 1969) / 4) - ((year - 1901) / 100) + ((year - 1601) / 400)); + } + + return (int32_t) (365 * (year - 1970) + floor ((year - 1969) / 4.0) - floor ((year - 1901) / 100.0) + + floor ((year - 1601) / 400.0)); +} /* ecma_date_day_from_year */ + +/** + * Abstract operation: DaysInYear + * + * See also: + * ECMA-262 v11, 20.4.1.3 + * + * @return number of days in the given year + */ +static int +ecma_date_days_in_year (int32_t year) /**< year */ +{ + if (year % 4 != 0 || (year % 100 == 0 && (year % 400 != 0))) + { + return ECMA_DATE_DAYS_IN_YEAR; + } + + return ECMA_DATE_DAYS_IN_LEAP_YEAR; +} /* ecma_date_days_in_year */ + +/** + * Abstract operation: InLeapYear + * + * See also: + * ECMA-262 v11, 20.4.1.3 + * + * @return 1 - if the year is leap + * 0 - otherwise + */ +static int32_t +ecma_date_in_leap_year (int32_t year) /**< time value */ +{ + return ecma_date_days_in_year (year) - ECMA_DATE_DAYS_IN_YEAR; +} /* ecma_date_in_leap_year */ + +/** + * First days of months in normal and leap years + */ +static const uint16_t first_day_in_month[2][12] = { { + 0, + 31, + 59, + 90, + 120, + 151, + 181, + 212, + 243, + 273, + 304, + 334, /* normal year */ + }, + { + 0, + 31, + 60, + 91, + 121, + 152, + 182, + 213, + 244, + 274, + 305, + 335 /* leap year */ + } }; + +/** + * Abstract operation: YearFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.3 + * + * @return year corresponds to the given time + */ +int32_t +ecma_date_year_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t approx = (int32_t) (floor (time / ECMA_DATE_MS_PER_DAY / 365.2425) + 1970); + int64_t year_ms = ecma_date_day_from_year (approx) * ((int64_t) ECMA_DATE_MS_PER_DAY); + + if ((ecma_number_t) year_ms > time) + { + approx--; + } + + if ((ecma_number_t) (year_ms + ecma_date_days_in_year (approx) * ((int64_t) ECMA_DATE_MS_PER_DAY)) <= time) + { + approx++; + } + + return approx; +} /* ecma_date_year_from_time */ + +/** + * Abstract operation: MonthFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.4 + * + * @return month corresponds to the given time + */ +int32_t +ecma_date_month_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t year = ecma_date_year_from_time (time); + int32_t day_within_year = ecma_date_day_from_time (time) - ecma_date_day_from_year (year); + + JERRY_ASSERT (day_within_year >= 0 && day_within_year < ECMA_DATE_DAYS_IN_LEAP_YEAR); + + int32_t in_leap_year = ecma_date_in_leap_year (year); + + for (int i = 1; i < 12; i++) + { + if (day_within_year < first_day_in_month[in_leap_year][i]) + { + return i - 1; + } + } + + return 11; +} /* ecma_date_month_from_time */ + +/** + * Abstract operation: DateFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.4 + * + * @return date corresponds to the given time + */ +int32_t +ecma_date_date_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t year = ecma_date_year_from_time (time); + int32_t day_within_year = ecma_date_day_from_time (time) - ecma_date_day_from_year (year); + + JERRY_ASSERT (day_within_year >= 0 && day_within_year < ECMA_DATE_DAYS_IN_LEAP_YEAR); + + int32_t in_leap_year = ecma_date_in_leap_year (year); + + int32_t month = 11; + + for (int i = 1; i < 12; i++) + { + if (day_within_year < first_day_in_month[in_leap_year][i]) + { + month = i - 1; + break; + } + } + + return day_within_year + 1 - first_day_in_month[in_leap_year][month]; +} /* ecma_date_date_from_time */ + +/** + * Abstract operation: WeekDay + * + * See also: + * ECMA-262 v11, 20.4.1.4 + * + * @return weekday corresponds to the given time + */ +int32_t +ecma_date_week_day (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t day = ecma_date_day_from_time (time); + + int week_day = (day + 4) % 7; + + return week_day >= 0 ? week_day : week_day + 7; +} /* ecma_date_week_day */ + +/** + * Abstract operation: LocalTZA + * + * See also: + * ECMA-262 v11, 20.4.1.7 + * + * @return local time zone adjustment + */ +int32_t +ecma_date_local_time_zone_adjustment (ecma_number_t time) /**< time value */ +{ + return jerry_port_local_tza (time); +} /* ecma_date_local_time_zone_adjustment */ + +/** + * Abstract operation: UTC + * + * See also: + * ECMA-262 v11, 20.4.1.9 + * + * @return UTC time + */ +ecma_number_t +ecma_date_utc (ecma_number_t time) /**< time value */ +{ + return time - jerry_port_local_tza (time); +} /* ecma_date_utc */ + +/** + * Calculate the time component from the given time + * + * @return time component of the given time + */ +int32_t +ecma_date_time_in_day_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + ecma_number_t day = ecma_date_day_from_time (time); + + return (int32_t) (time - (day * ECMA_DATE_MS_PER_DAY)); +} /* ecma_date_time_in_day_from_time */ + +/** + * Abstract operation: HourFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.10 + * + * @return hours component of the given time + */ +int32_t +ecma_date_hour_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t time_in_day = ecma_date_time_in_day_from_time (time); + + return (int32_t) (time_in_day / ECMA_DATE_MS_PER_HOUR); +} /* ecma_date_hour_from_time */ + +/** + * Abstract operation: HourFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.10 + * + * @return minutes component of the given time + */ +int32_t +ecma_date_min_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t time_in_day = ecma_date_time_in_day_from_time (time); + + return ((int32_t) (time_in_day / ECMA_DATE_MS_PER_MINUTE)) % ECMA_DATE_MINUTES_PER_HOUR; +} /* ecma_date_min_from_time */ + +/** + * Abstract operation: HourFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.10 + * + * @return seconds component of the given time + */ +int32_t +ecma_date_sec_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t time_in_day = ecma_date_time_in_day_from_time (time); + + return ((int32_t) (time_in_day / ECMA_DATE_MS_PER_SECOND)) % ECMA_DATE_SECONDS_PER_MINUTE; +} /* ecma_date_sec_from_time */ + +/** + * Abstract operation: HourFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.10 + * + * @return milliseconds component of the given time + */ +int32_t +ecma_date_ms_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t time_in_day = ecma_date_time_in_day_from_time (time); + + return (int32_t) (time_in_day % ECMA_DATE_MS_PER_SECOND); +} /* ecma_date_ms_from_time */ + +/** + * Abstract operation: MakeTime + * + * See also: + * ECMA-262 v11, 20.4.1.11 + * + * @return constructed time in milliseconds + */ +ecma_number_t +ecma_date_make_time (ecma_number_t hour, /**< hour value */ + ecma_number_t min, /**< minute value */ + ecma_number_t sec, /**< second value */ + ecma_number_t ms) /**< millisecond value */ +{ + if (!ecma_number_is_finite (hour) || !ecma_number_is_finite (min) || !ecma_number_is_finite (sec) + || !ecma_number_is_finite (ms)) + { + return ecma_number_make_nan (); + } + + ecma_number_t h = ecma_number_trunc (hour); + ecma_number_t m = ecma_number_trunc (min); + ecma_number_t s = ecma_number_trunc (sec); + ecma_number_t milli = ecma_number_trunc (ms); + + return h * ECMA_DATE_MS_PER_HOUR + m * ECMA_DATE_MS_PER_MINUTE + s * ECMA_DATE_MS_PER_SECOND + milli; +} /* ecma_date_make_time */ + +/** + * Abstract operation: MakeDay + * + * See also: + * ECMA-262 v11, 20.4.1.12 + * + * @return elpased number of days since Unix Epoch + */ +ecma_number_t +ecma_date_make_day (ecma_number_t year, /**< year value */ + ecma_number_t month, /**< month value */ + ecma_number_t date) /**< date value */ +{ + /* 1. */ + if (!ecma_number_is_finite (year) || !ecma_number_is_finite (month) || !ecma_number_is_finite (date) + || fabs (year) > INT32_MAX) + { + return ecma_number_make_nan (); + } + + /* 2., 3., 4. */ + int32_t y = (int32_t) (year); + ecma_number_t m = ecma_number_trunc (month); + ecma_number_t dt = ecma_number_trunc (date); + + /* 5. */ + int32_t ym = y + (int32_t) (floor (m / 12)); + + /* 6. */ + int32_t mn = (int32_t) fmod (m, 12); + + if (mn < 0) + { + mn += 12; + } + + /* 7. */ + ecma_number_t days = (ecma_date_day_from_year (ym) + first_day_in_month[ecma_date_in_leap_year (ym)][mn] + (dt - 1)); + return days * ECMA_DATE_MS_PER_DAY; +} /* ecma_date_make_day */ + +/** + * Abstract operation: MakeTime + * + * See also: + * ECMA-262 v11, 20.4.1.13 + * + * @return elpased number of milliceconds since Unix Epoch + */ +ecma_number_t +ecma_date_make_date (ecma_number_t day, /**< day value */ + ecma_number_t time) /**< time value */ +{ + if (!ecma_number_is_finite (day) || !ecma_number_is_finite (time)) + { + return ecma_number_make_nan (); + } + + return day + time; +} /* ecma_date_make_date */ + +/** + * Abstract operation: TimeClip + * + * See also: + * ECMA-262 v11, 20.4.1.14 + * + * @return elpased number of milliceconds since Unix Epoch + */ +ecma_number_t +ecma_date_time_clip (ecma_number_t time) /**< time value */ +{ + if (!ecma_number_is_finite (time) || fabs (time) > ECMA_DATE_MAX_VALUE) + { + return ecma_number_make_nan (); + } + + return ecma_number_trunc (time); +} /* ecma_date_time_clip */ + +/** + * Common function to convert date to string. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_date_to_string_format (ecma_number_t datetime_number, /**< datetime */ + const char *format_p) /**< format buffer */ +{ + const uint32_t date_buffer_length = 37; + JERRY_VLA (lit_utf8_byte_t, date_buffer, date_buffer_length); + + lit_utf8_byte_t *dest_p = date_buffer; + + while (*format_p != LIT_CHAR_NULL) + { + if (*format_p != LIT_CHAR_DOLLAR_SIGN) + { + *dest_p++ = (lit_utf8_byte_t) *format_p++; + continue; + } + + format_p++; + + const char *str_p = NULL; + int32_t number = 0; + int32_t number_length = 0; + + switch (*format_p) + { + case LIT_CHAR_UPPERCASE_Y: /* Year. */ + { + number = ecma_date_year_from_time (datetime_number); + + if (number >= 100000 || number <= -100000) + { + number_length = 6; + } + else if (number >= 10000 || number <= -10000) + { + number_length = 5; + } + else + { + number_length = 4; + } + break; + } + case LIT_CHAR_LOWERCASE_Y: /* ISO Year: -000001, 0000, 0001, 9999, +012345 */ + { + number = ecma_date_year_from_time (datetime_number); + if (0 <= number && number <= 9999) + { + number_length = 4; + } + else + { + number_length = 6; + } + break; + } + case LIT_CHAR_UPPERCASE_M: /* Month. */ + { + int32_t month = ecma_date_month_from_time (datetime_number); + + JERRY_ASSERT (month >= 0 && month <= 11); + + str_p = month_names_p[month]; + break; + } + case LIT_CHAR_UPPERCASE_O: /* Month as number. */ + { + /* The 'ecma_date_month_from_time' (ECMA 262 v5, 15.9.1.4) returns a + * number from 0 to 11, but we have to print the month from 1 to 12 + * for ISO 8601 standard (ECMA 262 v5, 15.9.1.15). */ + number = ecma_date_month_from_time (datetime_number) + 1; + number_length = 2; + break; + } + case LIT_CHAR_UPPERCASE_D: /* Day. */ + { + number = ecma_date_date_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_UPPERCASE_W: /* Day of week. */ + { + int32_t day = ecma_date_week_day (datetime_number); + + JERRY_ASSERT (day >= 0 && day <= 6); + + str_p = day_names_p[day]; + break; + } + case LIT_CHAR_LOWERCASE_H: /* Hour. */ + { + number = ecma_date_hour_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_LOWERCASE_M: /* Minutes. */ + { + number = ecma_date_min_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_LOWERCASE_S: /* Seconds. */ + { + number = ecma_date_sec_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_LOWERCASE_I: /* Milliseconds. */ + { + number = ecma_date_ms_from_time (datetime_number); + number_length = 3; + break; + } + case LIT_CHAR_LOWERCASE_Z: /* Time zone hours part. */ + { + int32_t time_zone = ecma_date_local_time_zone_adjustment (datetime_number); + + if (time_zone >= 0) + { + *dest_p++ = LIT_CHAR_PLUS; + } + else + { + *dest_p++ = LIT_CHAR_MINUS; + time_zone = -time_zone; + } + + number = time_zone / ECMA_DATE_MS_PER_HOUR; + number_length = 2; + break; + } + default: + { + JERRY_ASSERT (*format_p == LIT_CHAR_UPPERCASE_Z); /* Time zone minutes part. */ + + int32_t time_zone = ecma_date_local_time_zone_adjustment (datetime_number); + + if (time_zone < 0) + { + time_zone = -time_zone; + } + + number = (time_zone % ECMA_DATE_MS_PER_HOUR) / ECMA_DATE_MS_PER_MINUTE; + number_length = 2; + break; + } + } + + format_p++; + + if (str_p != NULL) + { + /* Print string values: month or day name which is always 3 characters */ + memcpy (dest_p, str_p, 3); + dest_p += 3; + continue; + } + + /* Print right aligned number values. */ + JERRY_ASSERT (number_length > 0); + + if (number < 0) + { + number = -number; + *dest_p++ = '-'; + } + else if (*(format_p - 1) == LIT_CHAR_LOWERCASE_Y && number_length == 6) + { + /* positive sign is compulsory for extended years */ + *dest_p++ = '+'; + } + + dest_p += number_length; + lit_utf8_byte_t *buffer_p = dest_p; + + do + { + buffer_p--; + *buffer_p = (lit_utf8_byte_t) ((number % 10) + (int32_t) LIT_CHAR_0); + number /= 10; + } while (--number_length); + } + + JERRY_ASSERT (dest_p <= date_buffer + date_buffer_length); + + return ecma_make_string_value ( + ecma_new_ecma_string_from_ascii (date_buffer, (lit_utf8_size_t) (dest_p - date_buffer))); +} /* ecma_date_to_string_format */ + +/** + * Common function to create a time zone specific string from a numeric value. + * + * Used by: + * - The Date routine. + * - The Date.prototype.toString routine. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_date_value_to_string (ecma_number_t datetime_number) /**< datetime */ +{ + datetime_number += ecma_date_local_time_zone_adjustment (datetime_number); + return ecma_date_to_string_format (datetime_number, "$W $M $D $Y $h:$m:$s GMT$z$Z"); +} /* ecma_date_value_to_string */ + +/** + * Common function to create a time zone specific string from a numeric value. + * + * Used by: + * - The Date.prototype.toUTCString routine. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_date_value_to_utc_string (ecma_number_t datetime_number) /**< datetime */ +{ + return ecma_date_to_string_format (datetime_number, "$W, $D $M $Y $h:$m:$s GMT"); +} /* ecma_date_value_to_utc_string */ + +/** + * Common function to create a ISO specific string from a numeric value. + * + * Used by: + * - The Date.prototype.toISOString routine. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_date_value_to_iso_string (ecma_number_t datetime_number) /** source_array_p [left_idx : right_idx - 1] + * Second -> source_array_p [right_idx : end_idx - 1] + * Output -> output_array_p + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_helper_array_merge_sort_bottom_up (ecma_value_t *source_array_p, /**< arrays to merge */ + uint32_t left_idx, /**< first array begin */ + uint32_t right_idx, /**< first array end */ + uint32_t end_idx, /**< second array end */ + ecma_value_t *output_array_p, /**< output array */ + ecma_value_t compare_func, /**< compare function */ + const ecma_builtin_helper_sort_compare_fn_t sort_cb, /**< sorting cb */ + ecma_object_t *array_buffer_p) /* array_buffer_p */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + uint32_t i = left_idx, j = right_idx; + + for (uint32_t k = left_idx; k < end_idx; k++) + { + ecma_value_t compare_value = ecma_make_number_value (ECMA_NUMBER_ZERO); + + if (i < right_idx && j < end_idx) + { + compare_value = sort_cb (source_array_p[i], source_array_p[j], compare_func, array_buffer_p); + if (ECMA_IS_VALUE_ERROR (compare_value)) + { + ret_value = ECMA_VALUE_ERROR; + break; + } + } + + if (i < right_idx && ecma_get_number_from_value (compare_value) <= ECMA_NUMBER_ZERO) + { + output_array_p[k] = source_array_p[i]; + i++; + } + else + { + output_array_p[k] = source_array_p[j]; + j++; + } + ecma_free_value (compare_value); + } + + return ret_value; +} /* ecma_builtin_helper_array_merge_sort_bottom_up */ + +/** + * Mergesort function + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_helper_array_merge_sort_helper (ecma_value_t *array_p, /**< array to sort */ + uint32_t length, /**< length */ + ecma_value_t compare_func, /**< compare function */ + const ecma_builtin_helper_sort_compare_fn_t sort_cb, /**< sorting cb */ + ecma_object_t *array_buffer_p) /**< arrayBuffer */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + JMEM_DEFINE_LOCAL_ARRAY (dest_array_p, length, ecma_value_t); + + ecma_value_t *temp_p; + ecma_value_t *base_array_p = array_p; + uint32_t r, e; + + for (uint32_t w = 1; w < length; w = 2 * w) + { + for (uint32_t i = 0; i < length; i = i + 2 * w) + { + // End of first array + r = i + w; + if (r > length) + { + r = length; + } + + // End of second array + e = i + 2 * w; + if (e > length) + { + e = length; + } + + // Merge two arrays + ret_value = ecma_builtin_helper_array_merge_sort_bottom_up (array_p, + i, + r, + e, + dest_array_p, + compare_func, + sort_cb, + array_buffer_p); + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + break; + } + } + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + break; + } + + // Swap arrays + temp_p = dest_array_p; + dest_array_p = array_p; + array_p = temp_p; + } + + // Sorted array is in dest_array_p - there was uneven number of arrays swaps + if (dest_array_p == base_array_p) + { + uint32_t index = 0; + temp_p = dest_array_p; + dest_array_p = array_p; + array_p = temp_p; + + while (index < length) + { + array_p[index] = dest_array_p[index]; + index++; + } + JERRY_ASSERT (index == length); + } + + JMEM_FINALIZE_LOCAL_ARRAY (dest_array_p); + + return ret_value; +} /* ecma_builtin_helper_array_merge_sort_helper */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp new file mode 100644 index 00000000..f4916101 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp @@ -0,0 +1,1039 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jmem.h" +#include "lit-char-helpers.h" +#include "lit-magic-strings.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltinhelpers ECMA builtin helper operations + * @{ + */ + +/** + * Helper function for Object.prototype.toString routine when + * the @@toStringTag property is present + * + * See also: + * ECMA-262 v6, 19.1.3.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_helper_object_to_string_tag_helper (ecma_value_t tag_value) /**< string tag */ +{ + JERRY_ASSERT (ecma_is_value_string (tag_value)); + + ecma_string_t *tag_str_p = ecma_get_string_from_value (tag_value); + lit_utf8_size_t tag_str_size = ecma_string_get_size (tag_str_p); + ecma_string_t *ret_string_p; + + /* Building string "[object #@@toStringTag#]" + The string size will be size("[object ") + size(#@@toStringTag#) + size ("]"). */ + const lit_utf8_size_t buffer_size = 9 + tag_str_size; + JMEM_DEFINE_LOCAL_ARRAY (str_buffer, buffer_size, lit_utf8_byte_t); + + lit_utf8_byte_t *buffer_ptr = str_buffer; + + const lit_magic_string_id_t magic_string_ids[] = { + LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, + LIT_MAGIC_STRING_OBJECT, + LIT_MAGIC_STRING_SPACE_CHAR, + }; + + /* Copy to buffer the "[object " string */ + for (uint32_t i = 0; i < sizeof (magic_string_ids) / sizeof (lit_magic_string_id_t); ++i) + { + buffer_ptr = lit_copy_magic_string_to_buffer (magic_string_ids[i], + buffer_ptr, + (lit_utf8_size_t) ((str_buffer + buffer_size) - buffer_ptr)); + + JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); + } + + /* Copy to buffer the #@@toStringTag# string */ + ecma_string_to_cesu8_bytes (tag_str_p, buffer_ptr, tag_str_size); + buffer_ptr += tag_str_size; + + JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); + + /* Copy to buffer the "]" string */ + buffer_ptr = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR, + buffer_ptr, + (lit_utf8_size_t) ((str_buffer + buffer_size) - buffer_ptr)); + + JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); + + ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_ptr - str_buffer)); + + JMEM_FINALIZE_LOCAL_ARRAY (str_buffer); + ecma_deref_ecma_string (tag_str_p); + + return ecma_make_string_value (ret_string_p); +} /* ecma_builtin_helper_object_to_string_tag_helper */ + +/** + * Common implementation of the Object.prototype.toString routine + * + * See also: + * ECMA-262 v5, 15.2.4.2 + * + * Used by: + * - The Object.prototype.toString routine. + * - The Array.prototype.toString routine as fallback. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ + +ecma_value_t +ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this argument */ +{ + lit_magic_string_id_t builtin_tag; + + if (ecma_is_value_undefined (this_arg)) + { + builtin_tag = LIT_MAGIC_STRING_UNDEFINED_UL; + } + else if (ecma_is_value_null (this_arg)) + { + builtin_tag = LIT_MAGIC_STRING_NULL_UL; + } + else + { + ecma_value_t obj_this = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (obj_this)) + { + return obj_this; + } + + JERRY_ASSERT (ecma_is_value_object (obj_this)); + + ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); + + builtin_tag = ecma_object_get_class_name (obj_p); + + ecma_value_t is_array = ecma_is_value_array (obj_this); + + if (ECMA_IS_VALUE_ERROR (is_array)) + { + ecma_deref_object (obj_p); + return is_array; + } + + if (ecma_is_value_true (is_array)) + { + builtin_tag = LIT_MAGIC_STRING_ARRAY_UL; + } + + ecma_value_t tag = ecma_op_object_get_by_symbol_id (obj_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG); + + if (ECMA_IS_VALUE_ERROR (tag)) + { + ecma_deref_object (obj_p); + return tag; + } + + if (ecma_is_value_string (tag)) + { + ecma_deref_object (obj_p); + return ecma_builtin_helper_object_to_string_tag_helper (tag); + } + else if (builtin_tag != LIT_MAGIC_STRING_ARGUMENTS_UL && builtin_tag != LIT_MAGIC_STRING_FUNCTION_UL + && builtin_tag != LIT_MAGIC_STRING_ERROR_UL && builtin_tag != LIT_MAGIC_STRING_BOOLEAN_UL + && builtin_tag != LIT_MAGIC_STRING_NUMBER_UL && builtin_tag != LIT_MAGIC_STRING_STRING_UL + && builtin_tag != LIT_MAGIC_STRING_DATE_UL && builtin_tag != LIT_MAGIC_STRING_REGEXP_UL + && builtin_tag != LIT_MAGIC_STRING_ARRAY_UL) + { + builtin_tag = LIT_MAGIC_STRING_OBJECT_UL; + } + + ecma_free_value (tag); + ecma_deref_object (obj_p); + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + ecma_stringbuilder_append_magic (&builder, LIT_MAGIC_STRING_OBJECT_TO_STRING_UL); + ecma_stringbuilder_append_magic (&builder, builtin_tag); + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_RIGHT_SQUARE); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_helper_object_to_string */ + +/** + * The Array.prototype's 'toLocaleString' single element operation routine + * + * See also: + * ECMA-262 v5, 15.4.4.3 steps 6-8 and 10.b-d + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_string_t * +ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /**< this object */ + ecma_length_t index) /**< array index */ +{ + ecma_value_t index_value = ecma_op_object_get_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (index_value)) + { + return NULL; + } + + if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_value_t call_value = ecma_op_invoke_by_magic_id (index_value, LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, NULL, 0); + + ecma_free_value (index_value); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return NULL; + } + + ecma_string_t *ret_string_p = ecma_op_to_string (call_value); + + ecma_free_value (call_value); + + return ret_string_p; +} /* ecma_builtin_helper_get_to_locale_string_at_index */ + +/** + * Helper function to normalizing an array index + * + * See also: + * ECMA-262 v5, 15.4.4.10 steps 5, 6, 7 part 2, 8 + * ECMA-262 v5, 15.4.4.12 steps 5, 6 + * + * ECMA-262 v6, 22.1.3.6 steps 5 - 7, 8 part 2, 9, 10 + * ECMA-262 v6, 22.1.3.3 steps 5 - 10, 11 part 2, 12, 13 + * + * Used by: + * - The Array.prototype.slice routine. + * - The Array.prototype.splice routine. + * - The Array.prototype.fill routine. + * - The Array.prototype.copyWithin routine. + * + * @return ECMA_VALUE_EMPTY if successful + * conversion error otherwise + */ +ecma_value_t +ecma_builtin_helper_array_index_normalize (ecma_value_t arg, /**< index */ + ecma_length_t length, /**< array's length */ + ecma_length_t *number_p) /**< [out] ecma_length_t */ +{ + ecma_number_t to_int; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg, &to_int))) + { + return ECMA_VALUE_ERROR; + } + + *number_p = ((to_int < 0) ? (ecma_length_t) JERRY_MAX (((ecma_number_t) length + to_int), 0) + : (ecma_length_t) JERRY_MIN (to_int, (ecma_number_t) length)); + + return ECMA_VALUE_EMPTY; +} /* ecma_builtin_helper_array_index_normalize */ + +/** + * Helper function to normalizing an uint32 index + * + * See also: + * ECMA-262 v5, 15.5.4.13 steps 4 - 7 + * ECMA-262 v6, 22.2.3.5 steps 5 - 10, 11 part 2, 12, 13 + * ECMA-262 v6, 22.2.3.23 steps 5 - 10 + * ECMA-262 v6, 24.1.4.3 steps 6 - 8, 9 part 2, 10, 11 + * ECMA-262 v6, 22.2.3.26 steps 7 - 9, 10 part 2, 11, 12 + * ECMA-262 v6, 22.2.3.8 steps 5 - 7, 8 part 2, 9, 10 + * + * Used by: + * - The String.prototype.slice routine. + * - The Array.prototype.copyWithin routine. + * - The TypedArray.prototype.copyWithin routine. + * - The TypedArray.prototype.slice routine. + * - The ArrayBuffer.prototype.slice routine. + * - The TypedArray.prototype.subarray routine. + * - The TypedArray.prototype.fill routine. + * + * @return ECMA_VALUE_EMPTY if successful + * conversion error otherwise + */ +ecma_value_t +ecma_builtin_helper_uint32_index_normalize (ecma_value_t arg, /**< index */ + uint32_t length, /**< array's length */ + uint32_t *number_p) /**< [out] uint32_t number */ +{ + ecma_number_t to_int; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg, &to_int))) + { + return ECMA_VALUE_ERROR; + } + + *number_p = ((to_int < 0) ? (uint32_t) JERRY_MAX ((ecma_number_t) length + to_int, 0) + : (uint32_t) JERRY_MIN (to_int, (ecma_number_t) length)); + + return ECMA_VALUE_EMPTY; +} /* ecma_builtin_helper_uint32_index_normalize */ + +/** + * Helper function for concatenating an ecma_value_t to an Array. + * + * See also: + * ECMA-262 v5, 15.4.4.4 steps 5.b - 5.c + * + * Used by: + * - The Array.prototype.concat routine. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_helper_array_concat_value (ecma_object_t *array_obj_p, /**< array */ + ecma_length_t *length_p, /**< [in,out] array's length */ + ecma_value_t value) /**< value to concat */ +{ + /* 5.b */ + ecma_value_t is_spreadable = ecma_op_is_concat_spreadable (value); + + if (ECMA_IS_VALUE_ERROR (is_spreadable)) + { + return is_spreadable; + } + + bool spread_object = is_spreadable == ECMA_VALUE_TRUE; + /* ES11: 22.1.3.1.5.c.iv.3.b */ + const uint32_t prop_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + + if (spread_object) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + ecma_length_t arg_len; + ecma_value_t error = ecma_op_object_get_length (obj_p, &arg_len); + + if (ECMA_IS_VALUE_ERROR (error)) + { + return error; + } + + /* 4 . */ + if ((ecma_number_t) (*length_p + arg_len) > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ecma_raise_type_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + } + + /* 5.b.iii */ + for (ecma_length_t array_index = 0; array_index < arg_len; array_index++) + { + /* 5.b.iii.2 */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, array_index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + if (!ecma_is_value_found (get_value)) + { + continue; + } + + /* 5.b.iii.3.b */ + /* This will always be a simple value since 'is_throw' is false, so no need to free. */ + ecma_value_t put_comp = + ecma_builtin_helper_def_prop_by_index (array_obj_p, *length_p + array_index, get_value, prop_flags); + ecma_free_value (get_value); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + return put_comp; + } + } + + *length_p += arg_len; + return ECMA_VALUE_EMPTY; + } + + /* 5.c.i */ + /* This will always be a simple value since 'is_throw' is false, so no need to free. */ + ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p, (*length_p)++, value, prop_flags); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + return put_comp; + } + + return ECMA_VALUE_EMPTY; +} /* ecma_builtin_helper_array_concat_value */ + +/** + * Helper function to normalizing a string index + * + * This function clamps the given index to the [0, length] range. + * If the index is negative, 0 value is used. + * If the index is greater than the length of the string, the normalized index will be the length of the string. + * NaN is mapped to zero or length depending on the nan_to_zero parameter. + * + * See also: + * ECMA-262 v5, 15.5.4.15 + * + * Used by: + * - The String.prototype.substring routine. + * - The ecma_builtin_helper_string_prototype_object_index_of helper routine. + * + * @return lit_utf8_size_t - the normalized value of the index + */ +lit_utf8_size_t +ecma_builtin_helper_string_index_normalize (ecma_number_t index, /**< index */ + lit_utf8_size_t length, /**< string's length */ + bool nan_to_zero) /**< whether NaN is mapped to zero (t) or length (f) */ +{ + uint32_t norm_index = 0; + + if (ecma_number_is_nan (index)) + { + if (!nan_to_zero) + { + norm_index = length; + } + } + else if (!ecma_number_is_negative (index)) + { + if (ecma_number_is_infinity (index)) + { + norm_index = length; + } + else + { + norm_index = ecma_number_to_uint32 (index); + + if (norm_index > length) + { + norm_index = length; + } + } + } + + return norm_index; +} /* ecma_builtin_helper_string_index_normalize */ + +/** + * Helper function for finding lastindex of a search string + * + * This function clamps the given index to the [0, length] range. + * If the index is negative, 0 value is used. + * If the index is greater than the length of the string, the normalized index will be the length of the string. + * + * See also: + * ECMA-262 v6, 21.1.3.9 + * + * Used by: + * - The ecma_builtin_helper_string_prototype_object_index_of helper routine. + * - The ecma_builtin_string_prototype_object_replace_match helper routine. + * + * @return uint32_t - whether there is a match for the search string + */ +static uint32_t +ecma_builtin_helper_string_find_last_index (ecma_string_t *original_str_p, /**< original string */ + ecma_string_t *search_str_p, /**< search string */ + uint32_t position) /**< start_position */ +{ + if (ecma_string_is_empty (search_str_p)) + { + return position; + } + + uint32_t original_length = ecma_string_get_length (original_str_p); + + ECMA_STRING_TO_UTF8_STRING (search_str_p, search_str_utf8_p, search_str_size); + ECMA_STRING_TO_UTF8_STRING (original_str_p, original_str_utf8_p, original_str_size); + + uint32_t ret_value = UINT32_MAX; + + if (original_str_size >= search_str_size) + { + const lit_utf8_byte_t *end_p = original_str_utf8_p + original_str_size; + const lit_utf8_byte_t *current_p = end_p; + + for (ecma_number_t i = original_length; i > position; i--) + { + lit_utf8_decr (¤t_p); + } + + while (current_p + search_str_size > end_p) + { + lit_utf8_decr (¤t_p); + position--; + } + + while (true) + { + if (memcmp (current_p, search_str_utf8_p, search_str_size) == 0) + { + ret_value = position; + break; + } + + if (position == 0) + { + break; + } + + lit_utf8_decr (¤t_p); + position--; + } + } + ECMA_FINALIZE_UTF8_STRING (original_str_utf8_p, original_str_size); + ECMA_FINALIZE_UTF8_STRING (search_str_utf8_p, search_str_size); + + return ret_value; +} /* ecma_builtin_helper_string_find_last_index */ + +/** + * Helper function for string indexOf, lastIndexOf, startsWith, includes, endsWith functions + * + * See also: + * ECMA-262 v5, 15.5.4.7 + * ECMA-262 v5, 15.5.4.8 + * ECMA-262 v6, 21.1.3.6 + * ECMA-262 v6, 21.1.3.7 + * ECMA-262 v6, 21.1.3.18 + * + * Used by: + * - The String.prototype.indexOf routine. + * - The String.prototype.lastIndexOf routine. + * - The String.prototype.startsWith routine. + * - The String.prototype.includes routine. + * - The String.prototype.endsWith routine. + * + * @return ecma_value_t - Returns index (last index) or a + * boolean value + */ +ecma_value_t +ecma_builtin_helper_string_prototype_object_index_of (ecma_string_t *original_str_p, /**< this argument */ + ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2, /**< routine's second argument */ + ecma_string_index_of_mode_t mode) /**< routine's mode */ +{ + /* 5 (indexOf) -- 6 (lastIndexOf) */ + const lit_utf8_size_t original_len = ecma_string_get_length (original_str_p); + + /* 4, 6 (startsWith, includes, endsWith) */ + if (mode >= ECMA_STRING_STARTS_WITH) + { + ecma_value_t regexp = ecma_op_is_regexp (arg1); + + if (ECMA_IS_VALUE_ERROR (regexp)) + { + return regexp; + } + + if (regexp == ECMA_VALUE_TRUE) + { + JERRY_ASSERT (ECMA_STRING_LAST_INDEX_OF < mode && mode <= ECMA_STRING_ENDS_WITH); + return ecma_raise_type_error (ECMA_ERR_SEARCH_STRING_CANNOT_BE_OF_TYPE_REGEXP); + } + } + + /* 7, 8 */ + ecma_string_t *search_str_p = ecma_op_to_string (arg1); + + if (JERRY_UNLIKELY (search_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value; + + /* 4 (indexOf, lastIndexOf), 9 (startsWith, includes), 10 (endsWith) */ + ecma_number_t pos_num; + + if (mode > ECMA_STRING_LAST_INDEX_OF) + { + ret_value = ecma_op_to_integer (arg2, &pos_num); + } + else + { + ret_value = ecma_op_to_number (arg2, &pos_num); + } + + /* 10 (startsWith, includes), 11 (endsWith) */ + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_ecma_string (search_str_p); + return ret_value; + } + + bool use_first_index = mode != ECMA_STRING_LAST_INDEX_OF; + + /* 4b, 6 (indexOf) - 4b, 5, 7 (lastIndexOf) */ + lit_utf8_size_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, use_first_index); + + ecma_number_t ret_num = ECMA_NUMBER_MINUS_ONE; + + ret_value = ECMA_VALUE_FALSE; + + switch (mode) + { + case ECMA_STRING_STARTS_WITH: + { + if (start > original_len) + { + break; + } + /* 15, 16 (startsWith) */ + uint32_t index = ecma_builtin_helper_string_find_index (original_str_p, search_str_p, start); + ret_value = ecma_make_boolean_value (index == start); + break; + } + case ECMA_STRING_INCLUDES: + { + if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, start) != UINT32_MAX) + { + ret_value = ECMA_VALUE_TRUE; + } + break; + } + case ECMA_STRING_ENDS_WITH: + { + if (start == 0) + { + start = original_len; + } + + lit_utf8_size_t search_str_len = ecma_string_get_length (search_str_p); + + if (search_str_len == 0) + { + ret_value = ECMA_VALUE_TRUE; + break; + } + + int32_t start_ends_with = (int32_t) (start - search_str_len); + + if (start_ends_with < 0) + { + break; + } + uint32_t index = ecma_builtin_helper_string_find_index (original_str_p, search_str_p, (uint32_t) start_ends_with); + ret_value = ecma_make_boolean_value (index == (uint32_t) start_ends_with); + break; + } + case ECMA_STRING_INDEX_OF: + { + /* 8 (indexOf) -- 9 (lastIndexOf) */ + ecma_value_t find_index = ecma_builtin_helper_string_find_index (original_str_p, search_str_p, start); + + if (find_index != UINT32_MAX) + { + ret_num = ((ecma_number_t) find_index); + } + ret_value = ecma_make_number_value (ret_num); + break; + } + + case ECMA_STRING_LAST_INDEX_OF: + { + uint32_t index = ecma_builtin_helper_string_find_last_index (original_str_p, search_str_p, start); + + if (index != UINT32_MAX) + { + ret_num = ((ecma_number_t) index); + } + ret_value = ecma_make_number_value (ret_num); + break; + } + + default: + { + JERRY_UNREACHABLE (); + } + } + + ecma_deref_ecma_string (search_str_p); + + return ret_value; +} /* ecma_builtin_helper_string_prototype_object_index_of */ + +/** + * Helper function for finding index of a search string + * + * This function clamps the given index to the [0, length] range. + * If the index is negative, 0 value is used. + * If the index is greater than the length of the string, the normalized index will be the length of the string. + * + * See also: + * ECMA-262 v6, 21.1.3.8 + * + * Used by: + * - The ecma_builtin_helper_string_prototype_object_index_of helper routine. + * - The ecma_builtin_string_prototype_object_replace_match helper routine. + * + * @return uint32_t - whether there is a match for the search string + */ +uint32_t +ecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, /**< index */ + ecma_string_t *search_str_p, /**< string's length */ + uint32_t start_pos) /**< start position */ +{ + uint32_t match_found = UINT32_MAX; + + if (ecma_string_is_empty (search_str_p)) + { + return start_pos; + } + + ECMA_STRING_TO_UTF8_STRING (search_str_p, search_str_utf8_p, search_str_size); + ECMA_STRING_TO_UTF8_STRING (original_str_p, original_str_utf8_p, original_str_size); + + const lit_utf8_byte_t *str_current_p = original_str_utf8_p; + + for (ecma_number_t i = 0; i < start_pos; i++) + { + lit_utf8_incr (&str_current_p); + } + + const lit_utf8_byte_t *original_end_p = original_str_utf8_p + original_str_size; + + while (!((size_t) (original_end_p - str_current_p) < search_str_size)) + { + if (memcmp (str_current_p, search_str_utf8_p, search_str_size) == 0) + { + match_found = start_pos; + break; + } + + lit_utf8_incr (&str_current_p); + start_pos++; + } + + ECMA_FINALIZE_UTF8_STRING (original_str_utf8_p, original_str_size); + ECMA_FINALIZE_UTF8_STRING (search_str_utf8_p, search_str_size); + + return match_found; +} /* ecma_builtin_helper_string_find_index */ + +/** + * Helper function for using [[DefineOwnProperty]] specialized for indexed property names + * + * Note: this method falls back to the general ecma_builtin_helper_def_prop + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_helper_def_prop_by_index (ecma_object_t *obj_p, /**< object */ + ecma_length_t index, /**< property index */ + ecma_value_t value, /**< value */ + uint32_t opts) /**< any combination of ecma_property_flag_t bits */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_builtin_helper_def_prop (obj_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), value, opts); + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_builtin_helper_def_prop (obj_p, index_str_p, value, opts); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_builtin_helper_def_prop_by_index */ + +/** + * Helper function for at() functions. + * + * See also: + * ECMA-262 Stage 3 Draft Relative Indexing Method proposal 3. 4. 5. 6. + * + * Used by: + * - The Array.prototype.at routine. + * - The String.prototype.at routine. + * - The TypedArray.prototype.at routine. + * + * @return ECMA_VALUE_ERROR - on conversion error + * ECMA_VALUE_UNDEFINED - if the requested index is not exist + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +ecma_builtin_helper_calculate_index (ecma_value_t index, /**< relative index argument */ + ecma_length_t length, /**< object's length */ + ecma_length_t *out_index) /**< calculated index */ +{ + JERRY_ASSERT (out_index != NULL); + + ecma_number_t relative_index; + ecma_value_t conversion_result = ecma_op_to_integer (index, &relative_index); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (conversion_result)) + { + return ECMA_VALUE_ERROR; + } + + /* 5. 6. */ + ecma_number_t k; + + if (relative_index >= 0) + { + k = relative_index; + } + else + { + k = ((ecma_number_t) length + relative_index); + } + + /* 7. */ + if (k < 0 || k >= ((ecma_number_t) length)) + { + return ECMA_VALUE_UNDEFINED; + } + + *out_index = (ecma_length_t) k; + + return ECMA_VALUE_EMPTY; +} /* ecma_builtin_helper_calculate_index */ + +/** + * Helper function for using [[DefineOwnProperty]]. + * + * See also: + * ECMA-262 v5, 8.12.9 + * ECMA-262 v5, 15.4.5.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_helper_def_prop (ecma_object_t *obj_p, /**< object */ + ecma_string_t *name_p, /**< name string */ + ecma_value_t value, /**< value */ + uint32_t opts) /**< any combination of ecma_property_descriptor_status_flags_t bits */ +{ + ecma_property_descriptor_t prop_desc; + + prop_desc.flags = (uint16_t) (ECMA_NAME_DATA_PROPERTY_DESCRIPTOR_BITS | opts); + + prop_desc.value = value; + + return ecma_op_object_define_own_property (obj_p, name_p, &prop_desc); +} /* ecma_builtin_helper_def_prop */ + +/** + * GetSubstitution abstract operation + * + * See: + * ECMA-262 v6.0 21.1.3.14.1 + */ +void +ecma_builtin_replace_substitute (ecma_replace_context_t *ctx_p) /**< replace context */ +{ + JERRY_ASSERT (ctx_p->string_p != NULL); + JERRY_ASSERT (ctx_p->matched_p == NULL + || (ctx_p->matched_p >= ctx_p->string_p && ctx_p->matched_p <= ctx_p->string_p + ctx_p->string_size)); + + lit_utf8_size_t replace_size; + uint8_t replace_flags = ECMA_STRING_FLAG_IS_ASCII; + const lit_utf8_byte_t *replace_buf_p = + ecma_string_get_chars (ctx_p->replace_str_p, &replace_size, NULL, NULL, &replace_flags); + + const lit_utf8_byte_t *const replace_end_p = replace_buf_p + replace_size; + const lit_utf8_byte_t *curr_p = replace_buf_p; + const lit_utf8_byte_t *last_inserted_end_p = replace_buf_p; + + while (curr_p < replace_end_p) + { + if (*curr_p++ == LIT_CHAR_DOLLAR_SIGN) + { + ecma_stringbuilder_append_raw (&(ctx_p->builder), + last_inserted_end_p, + (lit_utf8_size_t) (curr_p - last_inserted_end_p - 1)); + if (curr_p >= replace_end_p) + { + last_inserted_end_p = curr_p - 1; + break; + } + + const lit_utf8_byte_t c = *curr_p++; + + switch (c) + { + case LIT_CHAR_DOLLAR_SIGN: + { + ecma_stringbuilder_append_byte (&(ctx_p->builder), LIT_CHAR_DOLLAR_SIGN); + break; + } + case LIT_CHAR_AMPERSAND: + { + if (JERRY_UNLIKELY (ctx_p->matched_p == NULL)) + { + JERRY_ASSERT (ctx_p->capture_count == 0); + JERRY_ASSERT (ctx_p->u.collection_p != NULL); + JERRY_ASSERT (ctx_p->u.collection_p->item_count > 0); + const ecma_value_t match_value = ctx_p->u.collection_p->buffer_p[0]; + + JERRY_ASSERT (ecma_is_value_string (match_value)); + ecma_stringbuilder_append (&(ctx_p->builder), ecma_get_string_from_value (match_value)); + break; + } + + JERRY_ASSERT (ctx_p->matched_p != NULL); + ecma_stringbuilder_append_raw (&(ctx_p->builder), ctx_p->matched_p, ctx_p->matched_size); + break; + } + case LIT_CHAR_GRAVE_ACCENT: + { + ecma_stringbuilder_append_raw (&(ctx_p->builder), ctx_p->string_p, ctx_p->match_byte_pos); + break; + } + case LIT_CHAR_SINGLE_QUOTE: + { + if (JERRY_UNLIKELY (ctx_p->matched_p == NULL)) + { + JERRY_ASSERT (ctx_p->capture_count == 0); + JERRY_ASSERT (ctx_p->u.collection_p != NULL); + JERRY_ASSERT (ctx_p->u.collection_p->item_count > 0); + const ecma_value_t match_value = ctx_p->u.collection_p->buffer_p[0]; + + JERRY_ASSERT (ecma_is_value_string (match_value)); + const ecma_string_t *const matched_p = ecma_get_string_from_value (match_value); + const lit_utf8_size_t match_size = ecma_string_get_size (matched_p); + const lit_utf8_byte_t *const begin_p = ctx_p->string_p + ctx_p->match_byte_pos + match_size; + + ecma_stringbuilder_append_raw (&(ctx_p->builder), + begin_p, + (lit_utf8_size_t) (ctx_p->string_p + ctx_p->string_size - begin_p)); + break; + } + + JERRY_ASSERT (ctx_p->matched_p != NULL); + ecma_stringbuilder_append_raw (&(ctx_p->builder), + ctx_p->matched_p + ctx_p->matched_size, + ctx_p->string_size - ctx_p->match_byte_pos - ctx_p->matched_size); + break; + } + default: + { + const lit_utf8_byte_t *const number_begin_p = curr_p - 1; + + if (lit_char_is_decimal_digit (c)) + { + uint32_t capture_count = ctx_p->capture_count; + + if (capture_count == 0 && ctx_p->u.collection_p != NULL) + { + capture_count = ctx_p->u.collection_p->item_count; + } + + uint8_t idx = (uint8_t) (c - LIT_CHAR_0); + if (curr_p < replace_end_p && lit_char_is_decimal_digit (*(curr_p))) + { + uint8_t two_digit_index = (uint8_t) (idx * 10 + (uint8_t) (*(curr_p) -LIT_CHAR_0)); + if (two_digit_index < capture_count) + { + idx = two_digit_index; + curr_p++; + } + } + + if (idx > 0 && idx < capture_count) + { + if (ctx_p->capture_count > 0) + { +#if JERRY_BUILTIN_REGEXP + JERRY_ASSERT (ctx_p->u.captures_p != NULL); + const ecma_regexp_capture_t *const capture_p = ctx_p->u.captures_p + idx; + + if (ECMA_RE_IS_CAPTURE_DEFINED (capture_p)) + { + ecma_stringbuilder_append_raw (&(ctx_p->builder), + capture_p->begin_p, + (lit_utf8_size_t) (capture_p->end_p - capture_p->begin_p)); + } + + break; +#endif /* JERRY_BUILTIN_REGEXP */ + } + else if (ctx_p->u.collection_p != NULL) + { + const ecma_value_t capture_value = ctx_p->u.collection_p->buffer_p[idx]; + if (!ecma_is_value_undefined (capture_value)) + { + ecma_stringbuilder_append (&(ctx_p->builder), ecma_get_string_from_value (capture_value)); + } + + break; + } + } + } + + ecma_stringbuilder_append_byte (&(ctx_p->builder), LIT_CHAR_DOLLAR_SIGN); + curr_p = number_begin_p; + break; + } + } + + last_inserted_end_p = curr_p; + } + } + + ecma_stringbuilder_append_raw (&(ctx_p->builder), + last_inserted_end_p, + (lit_utf8_size_t) (replace_end_p - last_inserted_end_p)); + + if (replace_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) replace_buf_p, replace_size); + } +} /* ecma_builtin_replace_substitute */ + +/** + * Helper function to determine if method is the builtin exec method + * + * @return true, if function is the builtin exec method + * false, otherwise + */ +bool +ecma_builtin_is_regexp_exec (ecma_extended_object_t *obj_p) /**< function object */ +{ + return (ecma_get_object_type (&obj_p->object) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + && obj_p->u.built_in.routine_id == ECMA_REGEXP_PROTOTYPE_ROUTINE_EXEC); +} /* ecma_builtin_is_regexp_exec */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h new file mode 100644 index 00000000..2910e9df --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h @@ -0,0 +1,232 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BUILTIN_HELPERS_H +#define ECMA_BUILTIN_HELPERS_H + +#include "ecma-exceptions.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-regexp-object.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltinhelpers ECMA builtin helper operations + * @{ + */ + +/** + * List of built-in routine identifiers. + */ +enum +{ + /** These routines must be in this order */ + ECMA_REGEXP_PROTOTYPE_ROUTINE_START = 0, + ECMA_REGEXP_PROTOTYPE_ROUTINE_EXEC, +#if JERRY_BUILTIN_ANNEXB + ECMA_REGEXP_PROTOTYPE_ROUTINE_COMPILE, +#endif /* JERRY_BUILTIN_ANNEXB */ + + ECMA_REGEXP_PROTOTYPE_ROUTINE_TEST, + ECMA_REGEXP_PROTOTYPE_ROUTINE_TO_STRING, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_SOURCE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_FLAGS, + + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_GLOBAL, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_IGNORE_CASE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_MULTILINE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_STICKY, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_UNICODE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_DOT_ALL, + + ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SEARCH, + ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH, + ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_REPLACE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SPLIT, + ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH_ALL, +}; + +/** + * Mode of string index routine. + */ +typedef enum +{ + /** These routines must be in this order */ + ECMA_STRING_LAST_INDEX_OF, /**< String.lastIndexOf: ECMA-262 v5, 15.5.4.8 */ + ECMA_STRING_INDEX_OF, /**< String.indexOf: ECMA-262 v5, 15.5.4.7 */ + ECMA_STRING_STARTS_WITH, /**< String.startsWith: ECMA-262 v6, 21.1.3.18 */ + ECMA_STRING_INCLUDES, /**< String.includes: ECMA-262 v6, 21.1.3.7 */ + ECMA_STRING_ENDS_WITH /**< String.includes: ECMA-262 v6, 21.1.3.6 */ +} ecma_string_index_of_mode_t; + +ecma_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg); +ecma_string_t *ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, ecma_length_t index); +ecma_value_t ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, ecma_length_t *length_p, ecma_value_t value); +ecma_value_t ecma_builtin_helper_uint32_index_normalize (ecma_value_t arg, uint32_t length, uint32_t *number_p); +ecma_value_t +ecma_builtin_helper_array_index_normalize (ecma_value_t arg, ecma_length_t length, ecma_length_t *number_p); +ecma_value_t ecma_builtin_helper_string_index_normalize (ecma_number_t index, uint32_t length, bool nan_to_zero); +ecma_value_t ecma_builtin_helper_string_prototype_object_index_of (ecma_string_t *original_str_p, + ecma_value_t arg1, + ecma_value_t arg2, + ecma_string_index_of_mode_t mode); +uint32_t +ecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, ecma_string_t *search_str_p, uint32_t start_pos); +ecma_value_t +ecma_builtin_helper_def_prop (ecma_object_t *obj_p, ecma_string_t *name_p, ecma_value_t value, uint32_t opts); + +ecma_value_t +ecma_builtin_helper_def_prop_by_index (ecma_object_t *obj_p, ecma_length_t index, ecma_value_t value, uint32_t opts); +ecma_value_t ecma_builtin_helper_calculate_index (ecma_value_t index, ecma_length_t length, ecma_length_t *out_index); + +/** + * Context for replace substitutions + */ +typedef struct +{ + ecma_stringbuilder_t builder; /**< result string builder */ + const lit_utf8_byte_t *string_p; /**< source string */ + lit_utf8_size_t string_size; /**< source string size */ + const lit_utf8_byte_t *matched_p; /**< matched string */ + lit_utf8_size_t matched_size; /**< matcehd string size */ + lit_utf8_size_t match_byte_pos; /**< byte position of the match in the source string */ + uint16_t flags; /**< replace flags */ + + /** + * Capture results + */ + union + { +#if JERRY_BUILTIN_REGEXP + const ecma_regexp_capture_t *captures_p; /**< array of regexp capturing groups */ +#endif /* JERRY_BUILTIN_REGEXP */ + const ecma_collection_t *collection_p; /**< collection of captured substrings */ + } u; + + uint32_t capture_count; /**< number of captures in the capturing group array */ + ecma_string_t *replace_str_p; /**< replacement string */ +} ecma_replace_context_t; + +void ecma_builtin_replace_substitute (ecma_replace_context_t *ctx_p); +bool ecma_builtin_is_regexp_exec (ecma_extended_object_t *obj_p); + +#if JERRY_BUILTIN_DATE + +/** + * Time range defines for helper functions. + * + * See also: + * ECMA-262 v5, 15.9.1.1, 15.9.1.10 + */ + +/** Hours in a day. */ +#define ECMA_DATE_HOURS_PER_DAY (24) + +/** Minutes in an hour. */ +#define ECMA_DATE_MINUTES_PER_HOUR (60) + +/** Seconds in a minute. */ +#define ECMA_DATE_SECONDS_PER_MINUTE (60) + +/** Milliseconds in a second. */ +#define ECMA_DATE_MS_PER_SECOND (1000) + +/** ECMA_DATE_MS_PER_MINUTE == 60000 */ +#define ECMA_DATE_MS_PER_MINUTE (ECMA_DATE_MS_PER_SECOND * ECMA_DATE_SECONDS_PER_MINUTE) + +/** ECMA_DATE_MS_PER_HOUR == 3600000 */ +#define ECMA_DATE_MS_PER_HOUR (ECMA_DATE_MS_PER_MINUTE * ECMA_DATE_MINUTES_PER_HOUR) + +/** ECMA_DATE_MS_PER_DAY == 86400000 */ +#define ECMA_DATE_MS_PER_DAY ((ECMA_DATE_MS_PER_HOUR * ECMA_DATE_HOURS_PER_DAY)) + +#define ECMA_DATE_DAYS_IN_YEAR (365) + +#define ECMA_DATE_DAYS_IN_LEAP_YEAR (366) + +/** + * This gives a range of 8,640,000,000,000,000 milliseconds + * to either side of 01 January, 1970 UTC. + */ +#define ECMA_DATE_MAX_VALUE 8.64e15 + +/** + * Timezone type. + */ +typedef enum +{ + ECMA_DATE_UTC, /**< date vaule is in UTC */ + ECMA_DATE_LOCAL /**< date vaule is in local time */ +} ecma_date_timezone_t; + +/* ecma-builtin-helpers-date.c */ +extern const char* day_names_p[7]; +extern const char* month_names_p[12]; + +int32_t ecma_date_day_from_time (ecma_number_t time); +int32_t ecma_date_year_from_time (ecma_number_t time); +int32_t ecma_date_month_from_time (ecma_number_t time); +int32_t ecma_date_date_from_time (ecma_number_t time); +int32_t ecma_date_week_day (ecma_number_t time); +int32_t ecma_date_hour_from_time (ecma_number_t time); +int32_t ecma_date_min_from_time (ecma_number_t time); +int32_t ecma_date_sec_from_time (ecma_number_t time); +int32_t ecma_date_ms_from_time (ecma_number_t time); +int32_t ecma_date_time_in_day_from_time (ecma_number_t time); + +int32_t ecma_date_local_time_zone_adjustment (ecma_number_t time); +ecma_number_t ecma_date_utc (ecma_number_t time); +ecma_number_t ecma_date_make_time (ecma_number_t hour, ecma_number_t min, ecma_number_t sec, ecma_number_t ms); +ecma_number_t ecma_date_make_day (ecma_number_t year, ecma_number_t month, ecma_number_t date); +ecma_number_t ecma_date_make_date (ecma_number_t day, ecma_number_t time); +ecma_number_t ecma_date_time_clip (ecma_number_t time); + +ecma_value_t ecma_date_value_to_string (ecma_number_t datetime_number); +ecma_value_t ecma_date_value_to_utc_string (ecma_number_t datetime_number); +ecma_value_t ecma_date_value_to_iso_string (ecma_number_t datetime_number); +ecma_value_t ecma_date_value_to_date_string (ecma_number_t datetime_number); +ecma_value_t ecma_date_value_to_time_string (ecma_number_t datetime_number); + +#endif /* JERRY_BUILTIN_DATE */ + +/* ecma-builtin-helper-error.c */ + +ecma_value_t ecma_builtin_helper_error_dispatch_call (jerry_error_t error_type, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +/* ecma-builtin-helpers-sort.c */ + +/** + * Comparison callback function header for sorting helper routines. + */ +typedef ecma_value_t (*ecma_builtin_helper_sort_compare_fn_t) (ecma_value_t lhs, /**< left value */ + ecma_value_t rhs, /**< right value */ + ecma_value_t compare_func, /**< compare function */ + ecma_object_t *array_buffer_p /**< arrayBuffer */); + +ecma_value_t ecma_builtin_helper_array_merge_sort_helper (ecma_value_t *array_p, + uint32_t length, + ecma_value_t compare_func, + const ecma_builtin_helper_sort_compare_fn_t sort_cb, + ecma_object_t *array_buffer_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_BUILTIN_HELPERS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h new file mode 100644 index 00000000..3755f612 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h @@ -0,0 +1,241 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BUILTIN_UNDERSCORED_ID +#error "Please, define BUILTIN_UNDERSCORED_ID" +#endif /* !BUILTIN_UNDERSCORED_ID */ + +#ifndef BUILTIN_INC_HEADER_NAME +#error "Please, define BUILTIN_INC_HEADER_NAME" +#endif /* !BUILTIN_INC_HEADER_NAME */ + +#include "ecma-objects.h" + +#define PASTE__(x, y) x##y +#define PASTE_(x, y) PASTE__ (x, y) +#define PASTE(x, y) PASTE_ (x, y) + +#define PROPERTY_DESCRIPTOR_LIST_NAME PASTE (PASTE (ecma_builtin_, BUILTIN_UNDERSCORED_ID), _property_descriptor_list) +#define DISPATCH_ROUTINE_ROUTINE_NAME PASTE (PASTE (ecma_builtin_, BUILTIN_UNDERSCORED_ID), _dispatch_routine) + +#ifndef BUILTIN_CUSTOM_DISPATCH + +#define ROUTINE_ARG(n) , ecma_value_t arg##n +#define ROUTINE_ARG_LIST_0 ecma_value_t this_arg +#define ROUTINE_ARG_LIST_1 ROUTINE_ARG_LIST_0 ROUTINE_ARG (1) +#define ROUTINE_ARG_LIST_2 ROUTINE_ARG_LIST_1 ROUTINE_ARG (2) +#define ROUTINE_ARG_LIST_3 ROUTINE_ARG_LIST_2 ROUTINE_ARG (3) +#define ROUTINE_ARG_LIST_NON_FIXED ROUTINE_ARG_LIST_0, const ecma_value_t *arguments_list_p, uint32_t arguments_list_len +#define ROUTINE(name, c_function_name, args_number, length_prop_value) \ + static ecma_value_t c_function_name (ROUTINE_ARG_LIST_##args_number); +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + static ecma_value_t c_function_name (ROUTINE_ARG_LIST_##args_number); +#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \ + static ecma_value_t c_function_name (ROUTINE_ARG_LIST_##args_number); +#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ + static ecma_value_t c_getter_func_name (ROUTINE_ARG_LIST_0); \ + static ecma_value_t c_setter_func_name (ROUTINE_ARG_LIST_1); +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ + static ecma_value_t c_getter_func_name (ROUTINE_ARG_LIST_0); +#include BUILTIN_INC_HEADER_NAME +#undef ROUTINE_ARG_LIST_NON_FIXED +#undef ROUTINE_ARG_LIST_3 +#undef ROUTINE_ARG_LIST_2 +#undef ROUTINE_ARG_LIST_1 +#undef ROUTINE_ARG_LIST_0 +#undef ROUTINE_ARG + +/** + * List of built-in routine identifiers. + */ +enum +{ + PASTE (ECMA_ROUTINE_START_, BUILTIN_UNDERSCORED_ID) = 0, +#define ROUTINE(name, c_function_name, args_number, length_prop_value) ECMA_ROUTINE_##name##c_function_name, +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + ECMA_ROUTINE_##name##c_function_name, +#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \ + ECMA_ROUTINE_##name##c_function_name, +#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ + ECMA_ACCESSOR_##name##c_getter_func_name, ECMA_ACCESSOR_##name##c_setter_func_name, +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) ECMA_ACCESSOR_##name##c_getter_func_name, +#include BUILTIN_INC_HEADER_NAME +}; + +#endif /* !BUILTIN_CUSTOM_DISPATCH */ + +/** + * Built-in property list of the built-in object. + */ +const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] = { +#ifndef BUILTIN_CUSTOM_DISPATCH +#define ROUTINE(name, c_function_name, args_number, length_prop_value) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, \ + ECMA_ROUTINE_VALUE (ECMA_ROUTINE_##name##c_function_name, length_prop_value) }, +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, \ + ECMA_ROUTINE_VALUE (ECMA_ROUTINE_##name##c_function_name, length_prop_value) }, +#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ROUTINE_VALUE (ECMA_ROUTINE_##name##c_function_name, length_prop_value) }, +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ACCESSOR_##name##c_getter_func_name }, +#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ACCESSOR_READ_WRITE (ECMA_ACCESSOR_##name##c_getter_func_name, ECMA_ACCESSOR_##name##c_setter_func_name) }, +#else /* BUILTIN_CUSTOM_DISPATCH */ +#define ROUTINE(name, c_function_name, args_number, length_prop_value) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, \ + ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) }, +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, \ + ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) }, +#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) }, +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + c_getter_func_name }, +#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ACCESSOR_READ_WRITE (c_getter_func_name, c_setter_func_name) }, +#endif /* !BUILTIN_CUSTOM_DISPATCH */ +#define OBJECT_VALUE(name, obj_builtin_id, prop_attributes) \ + { name, ECMA_BUILTIN_PROPERTY_OBJECT, (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, obj_builtin_id }, +#define SIMPLE_VALUE(name, simple_value, prop_attributes) \ + { name, ECMA_BUILTIN_PROPERTY_SIMPLE, (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, simple_value }, +#define NUMBER_VALUE(name, number_value, prop_attributes) \ + { name, ECMA_BUILTIN_PROPERTY_NUMBER, (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, number_value }, +#define STRING_VALUE(name, magic_string_id, prop_attributes) \ + { name, ECMA_BUILTIN_PROPERTY_STRING, (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, magic_string_id }, +#define SYMBOL_VALUE(name, symbol) { name, ECMA_BUILTIN_PROPERTY_SYMBOL, ECMA_PROPERTY_BUILT_IN_FIXED, symbol }, +#define INTRINSIC_PROPERTY(name, magic_string_id, prop_attributes) \ + { name, ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY, (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, magic_string_id }, +#define ACCESSOR_BUILTIN_FUNCTION(name, getter_builtin_id, setter_builtin_id, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ACCESSOR_READ_WRITE (getter_builtin_id, setter_builtin_id) }, +#include BUILTIN_INC_HEADER_NAME + { LIT_MAGIC_STRING__COUNT, ECMA_BUILTIN_PROPERTY_END, 0, 0 } +}; + +#ifndef BUILTIN_CUSTOM_DISPATCH + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +DISPATCH_ROUTINE_ROUTINE_NAME (uint8_t builtin_routine_id, /**< built-in wide routine + identifier */ + ecma_value_t this_arg_value, /**< 'this' argument + value */ + const ecma_value_t arguments_list[], /**< list of arguments + passed to routine */ + uint32_t arguments_number) /**< length of + * arguments' list */ +{ + /* the arguments may be unused for some built-ins */ + JERRY_UNUSED (this_arg_value); + JERRY_UNUSED (arguments_list); + JERRY_UNUSED (arguments_number); + + switch (builtin_routine_id) + { +#define ROUTINE_ARG(n) (arguments_list[n - 1]) +#define ROUTINE_ARG_LIST_0 +#define ROUTINE_ARG_LIST_1 , ROUTINE_ARG (1) +#define ROUTINE_ARG_LIST_2 ROUTINE_ARG_LIST_1, ROUTINE_ARG (2) +#define ROUTINE_ARG_LIST_3 ROUTINE_ARG_LIST_2, ROUTINE_ARG (3) +#define ROUTINE_ARG_LIST_NON_FIXED , arguments_list, arguments_number +#define ROUTINE(name, c_function_name, args_number, length_prop_value) \ + case ECMA_ROUTINE_##name##c_function_name: \ + { \ + return c_function_name (this_arg_value ROUTINE_ARG_LIST_##args_number); \ + } +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + case ECMA_ROUTINE_##name##c_function_name: \ + { \ + return c_function_name (this_arg_value ROUTINE_ARG_LIST_##args_number); \ + } +#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \ + case ECMA_ROUTINE_##name##c_function_name: \ + { \ + return c_function_name (this_arg_value ROUTINE_ARG_LIST_##args_number); \ + } +#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ + case ECMA_ACCESSOR_##name##c_getter_func_name: \ + { \ + return c_getter_func_name (this_arg_value); \ + } \ + case ECMA_ACCESSOR_##name##c_setter_func_name: \ + { \ + return c_setter_func_name (this_arg_value ROUTINE_ARG_LIST_1); \ + } +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ + case ECMA_ACCESSOR_##name##c_getter_func_name: \ + { \ + return c_getter_func_name (this_arg_value); \ + } +#include BUILTIN_INC_HEADER_NAME +#undef ROUTINE_ARG +#undef ROUTINE_ARG_LIST_0 +#undef ROUTINE_ARG_LIST_1 +#undef ROUTINE_ARG_LIST_2 +#undef ROUTINE_ARG_LIST_3 +#undef ROUTINE_ARG_LIST_NON_FIXED + + default: + { + JERRY_UNREACHABLE (); + } + } +} /* DISPATCH_ROUTINE_ROUTINE_NAME */ + +#endif /* !BUILTIN_CUSTOM_DISPATCH */ + +#undef BUILTIN_INC_HEADER_NAME +#undef BUILTIN_CUSTOM_DISPATCH +#undef BUILTIN_UNDERSCORED_ID +#undef DISPATCH_ROUTINE_ROUTINE_NAME +#undef ECMA_BUILTIN_PROPERTY_NAME_INDEX +#undef PASTE__ +#undef PASTE_ +#undef PASTE +#undef PROPERTY_DESCRIPTOR_LIST_NAME diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.cpp new file mode 100644 index 00000000..66519dcd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.cpp @@ -0,0 +1,305 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-array-object.h" +#include "ecma-arraybuffer-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-container-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-string-object.h" +#include "ecma-typedarray-object.h" + +#include "lit-char-helpers.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_INTRINSIC_ROUTINE_START = 0, + ECMA_INTRINSIC_ARRAY_PROTOTYPE_VALUES, + ECMA_INTRINSIC_TYPEDARRAY_PROTOTYPE_VALUES, + ECMA_INTRINSIC_MAP_PROTOTYPE_ENTRIES, + ECMA_INTRINSIC_SET_PROTOTYPE_VALUES, + ECMA_INTRINSIC_ARRAY_TO_STRING, + ECMA_INTRINSIC_DATE_TO_UTC_STRING, + ECMA_INTRINSIC_PARSE_FLOAT, + ECMA_INTRINSIC_PARSE_INT, + ECMA_INTRINSIC_STRING_TRIM_START, + ECMA_INTRINSIC_STRING_TRIM_END, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-intrinsic.inc.h" +#define BUILTIN_UNDERSCORED_ID intrinsic +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup intrinsic ECMA Intrinsic object built-in + * @{ + */ + +/** + * The %ArrayProto_values% intrinsic routine + * + * See also: + * ECMA-262 v5, 15.4.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_intrinsic_array_prototype_values (ecma_value_t this_value) /**< this argument */ +{ + ecma_value_t this_obj = ecma_op_to_object (this_value); + + if (ECMA_IS_VALUE_ERROR (this_obj)) + { + return this_obj; + } + + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_obj); + + ecma_value_t ret_value = ecma_op_create_array_iterator (this_obj_p, ECMA_ITERATOR_VALUES); + + ecma_deref_object (this_obj_p); + + return ret_value; +} /* ecma_builtin_intrinsic_array_prototype_values */ + +/** + * The Map.prototype entries and [@@iterator] routines + * + * See also: + * ECMA-262 v6, 23.1.3.4 + * ECMA-262 v6, 23.1.3.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_intrinsic_map_prototype_entries (ecma_value_t this_value) /**< this value */ +{ + ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_value, LIT_MAGIC_STRING_MAP_UL); + + if (map_object_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + return ecma_op_container_create_iterator (this_value, + ECMA_BUILTIN_ID_MAP_ITERATOR_PROTOTYPE, + ECMA_OBJECT_CLASS_MAP_ITERATOR, + ECMA_ITERATOR_ENTRIES); +} /* ecma_builtin_intrinsic_map_prototype_entries */ + +/** + * The Set.prototype values, keys and [@@iterator] routines + * + * See also: + * ECMA-262 v6, 23.2.3.8 + * ECMA-262 v6, 23.2.3.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_intrinsic_set_prototype_values (ecma_value_t this_value) /**< this value */ +{ + ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_value, LIT_MAGIC_STRING_SET_UL); + + if (map_object_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + return ecma_op_container_create_iterator (this_value, + ECMA_BUILTIN_ID_SET_ITERATOR_PROTOTYPE, + ECMA_OBJECT_CLASS_SET_ITERATOR, + ECMA_ITERATOR_VALUES); +} /* ecma_builtin_intrinsic_set_prototype_values */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_intrinsic_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + switch (builtin_routine_id) + { +#if JERRY_BUILTIN_ARRAY + case ECMA_INTRINSIC_ARRAY_PROTOTYPE_VALUES: + { + return ecma_builtin_intrinsic_array_prototype_values (this_arg); + } + case ECMA_INTRINSIC_ARRAY_TO_STRING: + { + ecma_value_t this_obj = ecma_op_to_object (this_arg); + if (ECMA_IS_VALUE_ERROR (this_obj)) + { + return this_obj; + } + + ecma_value_t result = ecma_array_object_to_string (this_obj); + ecma_deref_object (ecma_get_object_from_value (this_obj)); + + return result; + } +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY + case ECMA_INTRINSIC_TYPEDARRAY_PROTOTYPE_VALUES: + { + if (!ecma_is_typedarray (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY); + } + + if (ecma_arraybuffer_is_detached (ecma_typedarray_get_arraybuffer (ecma_get_object_from_value (this_arg)))) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + return ecma_typedarray_iterators_helper (this_arg, ECMA_ITERATOR_VALUES); + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_CONTAINER + case ECMA_INTRINSIC_SET_PROTOTYPE_VALUES: + { + return ecma_builtin_intrinsic_set_prototype_values (this_arg); + } + case ECMA_INTRINSIC_MAP_PROTOTYPE_ENTRIES: + { + return ecma_builtin_intrinsic_map_prototype_entries (this_arg); + } +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_DATE + case ECMA_INTRINSIC_DATE_TO_UTC_STRING: + { + if (!ecma_is_value_object (this_arg) + || !ecma_object_class_is (ecma_get_object_from_value (this_arg), ECMA_OBJECT_CLASS_DATE)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_DATE_OBJECT); + } + + ecma_number_t *date_value_p = &((ecma_date_object_t *) ecma_get_object_from_value (this_arg))->date_value; + + if (ecma_number_is_nan (*date_value_p)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_INVALID_DATE_UL); + } + + return ecma_date_value_to_utc_string (*date_value_p); + } +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_STRING + case ECMA_INTRINSIC_STRING_TRIM_START: + case ECMA_INTRINSIC_STRING_TRIM_END: + { + if (!ecma_op_require_object_coercible (this_arg)) + { + return ECMA_VALUE_ERROR; + } + + ecma_string_t *to_str_p = ecma_op_to_string (this_arg); + if (to_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ECMA_STRING_TO_UTF8_STRING (to_str_p, start_p, input_start_size); + + lit_utf8_size_t size; + const lit_utf8_byte_t *input_start_p = start_p; + const lit_utf8_byte_t *input_str_end_p = start_p + input_start_size; + + ecma_string_t *ret_str_p; + if (builtin_routine_id == ECMA_INTRINSIC_STRING_TRIM_START) + { + const lit_utf8_byte_t *new_start_p = ecma_string_trim_front (input_start_p, input_str_end_p); + size = (lit_utf8_size_t) (input_str_end_p - new_start_p); + ret_str_p = ecma_new_ecma_string_from_utf8 (new_start_p, size); + } + else + { + const lit_utf8_byte_t *new_end_p = ecma_string_trim_back (input_start_p, input_str_end_p); + size = (lit_utf8_size_t) (new_end_p - input_start_p); + ret_str_p = ecma_new_ecma_string_from_utf8 (input_start_p, size); + } + + ECMA_FINALIZE_UTF8_STRING (start_p, input_start_size); + ecma_value_t result = ecma_make_string_value (ret_str_p); + ecma_deref_ecma_string (to_str_p); + return result; + } +#endif /* JERRY_BUILTIN_STRING */ + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_INTRINSIC_PARSE_INT || builtin_routine_id == ECMA_INTRINSIC_PARSE_FLOAT); + + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result; + ECMA_STRING_TO_UTF8_STRING (str_p, string_buff, string_buff_size); + + if (builtin_routine_id == ECMA_INTRINSIC_PARSE_INT) + { + result = ecma_number_parse_int (string_buff, string_buff_size, arguments_list_p[1]); + } + else + { + JERRY_ASSERT (builtin_routine_id == ECMA_INTRINSIC_PARSE_FLOAT); + result = ecma_number_parse_float (string_buff, string_buff_size); + } + + ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size); + ecma_deref_ecma_string (str_p); + return result; + } + } +} /* ecma_builtin_intrinsic_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h new file mode 100644 index 00000000..54c82c4d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Intrinsic built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, ECMA_INTRINSIC_ARRAY_PROTOTYPE_VALUES, 0, 0) +ROUTINE (LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES, ECMA_INTRINSIC_TYPEDARRAY_PROTOTYPE_VALUES, 0, 0) +ROUTINE (LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, ECMA_INTRINSIC_SET_PROTOTYPE_VALUES, 0, 0) +ROUTINE (LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES, ECMA_INTRINSIC_MAP_PROTOTYPE_ENTRIES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TRIM_START, ECMA_INTRINSIC_STRING_TRIM_START, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TRIM_END, ECMA_INTRINSIC_STRING_TRIM_END, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_INTRINSIC_ARRAY_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_UTC_STRING_UL, ECMA_INTRINSIC_DATE_TO_UTC_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_INTRINSIC_PARSE_FLOAT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PARSE_INT, ECMA_INTRINSIC_PARSE_INT, 2, 2) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.cpp new file mode 100644 index 00000000..ca991d66 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.cpp @@ -0,0 +1,102 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-iterator-object.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_BUILTIN_ITERATOR_PROTOTYPE_OBJECT_ITERATOR, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %iteratorprototype% ECMA %IteratorPrototype% object built-in + * @{ + */ + +/** + * The %IteratorPrototype% object's '@@iterator' routine + * + * See also: + * ECMA-262 v6, 22.1.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return the given this value + */ +static ecma_value_t +ecma_builtin_iterator_prototype_object_iterator (ecma_value_t this_val) /**< this argument */ +{ + /* 1. */ + return ecma_copy_value (this_val); +} /* ecma_builtin_iterator_prototype_object_iterator */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< + * list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_ITERATOR_PROTOTYPE_OBJECT_ITERATOR: + { + return ecma_builtin_iterator_prototype_object_iterator (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_iterator_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.inc.h new file mode 100644 index 00000000..4054eb40 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %IteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_GLOBAL_SYMBOL_ITERATOR, ECMA_BUILTIN_ITERATOR_PROTOTYPE_OBJECT_ITERATOR, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.cpp new file mode 100644 index 00000000..9471a450 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.cpp @@ -0,0 +1,106 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_MAP_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_BUILTIN_MAP_ITERATOR_PROTOTYPE_ROUTINE_OBJECT_NEXT, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-map-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID map_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %mapiteratorprototype% ECMA %MapIteratorPrototype% object built-in + * @{ + */ + +/** + * The %MapIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 23.1.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_map_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + return ecma_op_container_iterator_next (this_val, ECMA_OBJECT_CLASS_MAP_ITERATOR); +} /* ecma_builtin_map_iterator_prototype_object_next */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_map_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_MAP_ITERATOR_PROTOTYPE_ROUTINE_OBJECT_NEXT: + { + return ecma_builtin_map_iterator_prototype_object_next (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_map_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.inc.h new file mode 100644 index 00000000..fe2b8187 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.inc.h @@ -0,0 +1,32 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %MapIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_MAP_ITERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_BUILTIN_MAP_ITERATOR_PROTOTYPE_ROUTINE_OBJECT_NEXT, 0, 0) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.cpp new file mode 100644 index 00000000..d7a10cc9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.cpp @@ -0,0 +1,66 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-map-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID map_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup map ECMA Map object built-in + * @{ + */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_map_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + return ecma_builtin_container_dispatch_routine (builtin_routine_id, + this_arg, + arguments_list_p, + LIT_MAGIC_STRING_MAP_UL); +} /* ecma_builtin_map_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.inc.h new file mode 100644 index 00000000..65d91d69 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.inc.h @@ -0,0 +1,55 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Map.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.1.3.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_MAP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.3.13 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_MAP_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_CLEAR, ECMA_CONTAINER_ROUTINE_CLEAR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_DELETE, ECMA_CONTAINER_ROUTINE_DELETE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_CONTAINER_ROUTINE_FOREACH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET, ECMA_CONTAINER_ROUTINE_GET, 1, 1) +ROUTINE (LIT_MAGIC_STRING_HAS, ECMA_CONTAINER_ROUTINE_HAS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET, ECMA_CONTAINER_ROUTINE_SET, 2, 2) +ROUTINE (LIT_MAGIC_STRING_VALUES, ECMA_CONTAINER_ROUTINE_VALUES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_CONTAINER_ROUTINE_KEYS, 0, 0) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_ENTRIES, + LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_GLOBAL_SYMBOL_ITERATOR, + LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.3.10 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_SIZE, ECMA_CONTAINER_ROUTINE_SIZE_GETTER, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.cpp new file mode 100644 index 00000000..817b5f94 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.cpp @@ -0,0 +1,86 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-container-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-map.inc.h" +#define BUILTIN_UNDERSCORED_ID map +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup map ECMA Map object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Map object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_map_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_MAP_REQUIRES_NEW); +} /* ecma_builtin_map_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Map object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_map_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_container_create (arguments_list_p, + arguments_list_len, + LIT_MAGIC_STRING_MAP_UL, + ECMA_BUILTIN_ID_MAP_PROTOTYPE); +} /* ecma_builtin_map_dispatch_construct */ + +/** + * 23.1.2.2 get Map [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_map_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_map_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.inc.h new file mode 100644 index 00000000..e1ff9c00 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.inc.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Map built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.1.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_MAP_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.1.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_MAP_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 23.1.2.2 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_map_species_get, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp new file mode 100644 index 00000000..33a9bc23 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp @@ -0,0 +1,561 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jrt-libc-includes.h" +#include "jrt.h" + +#if defined(_WIN32) +#include +#endif /* defined(_WIN32) */ + +#if JERRY_BUILTIN_MATH + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_MATH_OBJECT_ROUTINE_START = 0, + + ECMA_MATH_OBJECT_ABS, /* ECMA-262 v5, 15.8.2.1 */ + ECMA_MATH_OBJECT_ACOS, /* ECMA-262 v5, 15.8.2.2 */ + ECMA_MATH_OBJECT_ASIN, /* ECMA-262 v5, 15.8.2.3 */ + ECMA_MATH_OBJECT_ATAN, /* ECMA-262 v5, 15.8.2.4 */ + ECMA_MATH_OBJECT_CEIL, /* ECMA-262 v5, 15.8.2.6 */ + ECMA_MATH_OBJECT_COS, /* ECMA-262 v5, 15.8.2.7 */ + ECMA_MATH_OBJECT_EXP, /* ECMA-262 v5, 15.8.2.8 */ + ECMA_MATH_OBJECT_FLOOR, /* ECMA-262 v5, 15.8.2.9 */ + ECMA_MATH_OBJECT_LOG, /* ECMA-262 v5, 15.8.2.10 */ + ECMA_MATH_OBJECT_ROUND, /* ECMA-262 v5, 15.8.2.15 */ + ECMA_MATH_OBJECT_SIN, /* ECMA-262 v5, 15.8.2.16 */ + ECMA_MATH_OBJECT_SQRT, /* ECMA-262 v5, 15.8.2.17 */ + ECMA_MATH_OBJECT_TAN, /* ECMA-262 v5, 15.8.2.18 */ + ECMA_MATH_OBJECT_ACOSH, /* ECMA-262 v6, 20.2.2.3 */ + ECMA_MATH_OBJECT_ASINH, /* ECMA-262 v6, 20.2.2.5 */ + ECMA_MATH_OBJECT_ATANH, /* ECMA-262 v6, 20.2.2.7 */ + ECMA_MATH_OBJECT_CBRT, /* ECMA-262 v6, 20.2.2.9 */ + ECMA_MATH_OBJECT_CLZ32, /* ECMA-262 v6, 20.2.2.11 */ + ECMA_MATH_OBJECT_COSH, /* ECMA-262 v6, 20.2.2.13 */ + ECMA_MATH_OBJECT_EXPM1, /* ECMA-262 v6, 20.2.2.15 */ + ECMA_MATH_OBJECT_FROUND, /* ECMA-262 v6, 20.2.2.17 */ + ECMA_MATH_OBJECT_LOG1P, /* ECMA-262 v6, 20.2.2.21 */ + ECMA_MATH_OBJECT_LOG10, /* ECMA-262 v6, 20.2.2.22 */ + ECMA_MATH_OBJECT_LOG2, /* ECMA-262 v6, 20.2.2.23 */ + ECMA_MATH_OBJECT_SIGN, /* ECMA-262 v6, 20.2.2.29 */ + ECMA_MATH_OBJECT_SINH, /* ECMA-262 v6, 20.2.2.31 */ + ECMA_MATH_OBJECT_TANH, /* ECMA-262 v6, 20.2.2.34 */ + ECMA_MATH_OBJECT_TRUNC, /* ECMA-262 v6, 20.2.2.35 */ + ECMA_MATH_OBJECT_ATAN2, + /* ECMA-262 v5, 15.8.2.5 */ /* first routine with 2 arguments */ + ECMA_MATH_OBJECT_IMUL, /* ECMA-262 v6, 20.2.2.19 */ + ECMA_MATH_OBJECT_POW, + /* ECMA-262 v5, 15.8.2.13 */ /* last routine with 1 or 2 arguments*/ + ECMA_MATH_OBJECT_MAX, /* ECMA-262 v5, 15.8.2.11 */ + ECMA_MATH_OBJECT_MIN, /* ECMA-262 v5, 15.8.2.12 */ + ECMA_MATH_OBJECT_HYPOT, /* ECMA-262 v6, 20.2.2.18 */ + ECMA_MATH_OBJECT_RANDOM, /* ECMA-262 v5, 15.8.2.14 */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-math.inc.h" +#define BUILTIN_UNDERSCORED_ID math +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup object ECMA Object object built-in + * @{ + */ + +/** + * The Math object's 'max' 'min' routines. + * + * See also: + * ECMA-262 v5, 15.8.2.11 + * ECMA-262 v5, 15.8.2.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_math_object_max_min (bool is_max, /**< 'max' or 'min' operation */ + const ecma_value_t *arg, /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + ecma_number_t result_num = ecma_number_make_infinity (is_max); + + while (args_number > 0) + { + ecma_number_t arg_num; + ecma_value_t value = ecma_op_to_number (*arg, &arg_num); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + arg++; + args_number--; + + if (ecma_number_is_nan (arg_num)) + { + result_num = arg_num; + } + + if (ecma_number_is_zero (arg_num) && ecma_number_is_zero (result_num)) + { + bool is_negative = ecma_number_is_negative (arg_num); + + if (is_max ? !is_negative : is_negative) + { + result_num = arg_num; + } + } + else + { + if (is_max ? (arg_num > result_num) : (arg_num < result_num)) + { + result_num = arg_num; + } + } + } + + return ecma_make_number_value (result_num); +} /* ecma_builtin_math_object_max_min */ + +/** + * The Math object's 'hypot' routine + * + * See also: + * ECMA-262 v6, 20.2.2.18 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_math_object_hypot (const ecma_value_t *arg, /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (args_number == 0) + { + return ecma_make_number_value (0.0); + } + + ecma_number_t result_num = 0; + bool inf = false; + + while (args_number > 0) + { + ecma_number_t arg_num; + ecma_value_t value = ecma_op_to_number (*arg, &arg_num); + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + arg++; + args_number--; + + if (ecma_number_is_nan (arg_num) && !inf) + { + result_num = arg_num; + continue; + } + + if (ecma_number_is_infinity (arg_num)) + { + inf = true; + result_num = ecma_number_make_infinity (false); + continue; + } + + result_num += arg_num * arg_num; + } + + return ecma_make_number_value (sqrt (result_num)); +} /* ecma_builtin_math_object_hypot */ + +/** + * The Math object's 'trunc' routine + * + * See also: + * ECMA-262 v6, 20.2.2.35 + * + * @return ecma number + */ +static ecma_number_t +ecma_builtin_math_object_trunc (ecma_number_t arg) +{ + if (ecma_number_is_nan (arg) || ecma_number_is_infinity (arg) || ecma_number_is_zero (arg)) + { + return arg; + } + + if ((arg > 0) && (arg < 1)) + { + return (ecma_number_t) 0.0; + } + + if ((arg < 0) && (arg > -1)) + { + return (ecma_number_t) -0.0; + } + + return (ecma_number_t) arg - fmod (arg, 1); +} /* ecma_builtin_math_object_trunc */ + +/** + * The Math object's 'sign' routine + * + * See also: + * ECMA-262 v6, 20.2.2.29 + * + * @return ecma number + */ +static ecma_number_t +ecma_builtin_math_object_sign (ecma_number_t arg) +{ + if (ecma_number_is_nan (arg) || ecma_number_is_zero (arg)) + { + return arg; + } + + if (ecma_number_is_negative (arg)) + { + return (ecma_number_t) -1.0; + } + + return (ecma_number_t) 1.0; +} /* ecma_builtin_math_object_sign */ + +/** + * The Math object's 'random' routine. + * + * See also: + * ECMA-262 v5, 15.8.2.14 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_math_object_random (void) +{ + const ecma_number_t rand_max = (ecma_number_t) RAND_MAX; + const ecma_number_t rand_max_min_1 = (ecma_number_t) (RAND_MAX - 1); + + return ecma_make_number_value (((ecma_number_t) rand ()) / rand_max * rand_max_min_1 / rand_max); +} /* ecma_builtin_math_object_random */ + +/** + * Dispatcher for the built-in's routines. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_math_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (this_arg); + + if (builtin_routine_id <= ECMA_MATH_OBJECT_POW) + { + ecma_number_t x = ecma_number_make_nan (); + ecma_number_t y = ecma_number_make_nan (); + + if (arguments_number >= 1) + { + ecma_value_t value = ecma_op_to_number (arguments_list[0], &x); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + } + + if (builtin_routine_id >= ECMA_MATH_OBJECT_ATAN2 && arguments_number >= 2) + { + if (ecma_is_value_number (arguments_list[1])) + { + y = ecma_get_number_from_value (arguments_list[1]); + } + else + { + ecma_value_t value = ecma_op_to_number (arguments_list[1], &y); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + } + } + + switch (builtin_routine_id) + { + case ECMA_MATH_OBJECT_ABS: + { + x = DOUBLE_TO_ECMA_NUMBER_T (fabs (x)); + break; + } + case ECMA_MATH_OBJECT_ACOS: + { + x = DOUBLE_TO_ECMA_NUMBER_T (acos (x)); + break; + } + case ECMA_MATH_OBJECT_ASIN: + { + x = DOUBLE_TO_ECMA_NUMBER_T (asin (x)); + break; + } + case ECMA_MATH_OBJECT_ATAN: + { + x = DOUBLE_TO_ECMA_NUMBER_T (atan (x)); + break; + } + case ECMA_MATH_OBJECT_CEIL: + { + x = DOUBLE_TO_ECMA_NUMBER_T (ceil (x)); + break; + } + case ECMA_MATH_OBJECT_COS: + { + x = DOUBLE_TO_ECMA_NUMBER_T (cos (x)); + break; + } + case ECMA_MATH_OBJECT_EXP: + { + x = DOUBLE_TO_ECMA_NUMBER_T (exp (x)); + break; + } + case ECMA_MATH_OBJECT_FLOOR: + { + x = DOUBLE_TO_ECMA_NUMBER_T (floor (x)); + break; + } + case ECMA_MATH_OBJECT_LOG: + { + x = DOUBLE_TO_ECMA_NUMBER_T (log (x)); + break; + } + case ECMA_MATH_OBJECT_TRUNC: + { + x = ecma_builtin_math_object_trunc (x); + break; + } + case ECMA_MATH_OBJECT_SIGN: + { + x = ecma_builtin_math_object_sign (x); + break; + } + case ECMA_MATH_OBJECT_ROUND: + { + if (ecma_number_is_nan (x) || ecma_number_is_zero (x) || ecma_number_is_infinity (x)) + { + break; + } + + ecma_number_t fraction = fmod (x, ECMA_NUMBER_ONE); + + if (ecma_number_is_zero (fraction)) + { + break; + } + + if (ecma_number_is_negative (x)) + { + if (x >= -ECMA_NUMBER_HALF) + { + x = -ECMA_NUMBER_ZERO; + break; + } + + if (fraction < -ECMA_NUMBER_HALF) + { + x -= ECMA_NUMBER_HALF; + } + } + else if (fraction >= ECMA_NUMBER_HALF) + { + x += ECMA_NUMBER_HALF; + } + + x = ecma_number_trunc (x); + break; + } + case ECMA_MATH_OBJECT_SIN: + { + x = DOUBLE_TO_ECMA_NUMBER_T (sin (x)); + break; + } + case ECMA_MATH_OBJECT_SQRT: + { + x = DOUBLE_TO_ECMA_NUMBER_T (sqrt (x)); + break; + } + case ECMA_MATH_OBJECT_TAN: + { + x = DOUBLE_TO_ECMA_NUMBER_T (tan (x)); + break; + } + case ECMA_MATH_OBJECT_ATAN2: + { + x = DOUBLE_TO_ECMA_NUMBER_T (atan2 (x, y)); + break; + } + case ECMA_MATH_OBJECT_POW: + { + x = ecma_number_pow (x, y); + break; + } + case ECMA_MATH_OBJECT_ACOSH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (acosh (x)); + break; + } + case ECMA_MATH_OBJECT_ASINH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (asinh (x)); + break; + } + case ECMA_MATH_OBJECT_ATANH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (atanh (x)); + break; + } + case ECMA_MATH_OBJECT_CBRT: + { + x = DOUBLE_TO_ECMA_NUMBER_T (cbrt (x)); + break; + } + case ECMA_MATH_OBJECT_COSH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (cosh (x)); + break; + } + case ECMA_MATH_OBJECT_EXPM1: + { + x = DOUBLE_TO_ECMA_NUMBER_T (expm1 (x)); + break; + } + case ECMA_MATH_OBJECT_LOG1P: + { + x = DOUBLE_TO_ECMA_NUMBER_T (log1p (x)); + break; + } + case ECMA_MATH_OBJECT_LOG10: + { + x = DOUBLE_TO_ECMA_NUMBER_T (log10 (x)); + break; + } + case ECMA_MATH_OBJECT_LOG2: + { + x = DOUBLE_TO_ECMA_NUMBER_T (log2 (x)); + break; + } + case ECMA_MATH_OBJECT_SINH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (sinh (x)); + break; + } + case ECMA_MATH_OBJECT_TANH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (tanh (x)); + break; + } + case ECMA_MATH_OBJECT_CLZ32: + { + uint32_t n = ecma_number_to_uint32 (x); +#if defined(__GNUC__) || defined(__clang__) + x = n ? __builtin_clz (n) : 32; +#elif defined(_WIN32) + unsigned long ret; + x = _BitScanReverse (&ret, n) ? 31 - ret : 32; +#else /* !(defined(__GNUC__) || defined(__clang__) || defined(_WIN32)) */ + x = 32; + for (int i = 31; i >= 0; i--) + { + if (n >> i) + { + x = 31 - i; + break; + } + } +#endif /* defined (__GNUC__) || defined (__clang__) */ + break; + } + case ECMA_MATH_OBJECT_FROUND: + { + x = (float) x; + break; + } + case ECMA_MATH_OBJECT_IMUL: + { + x = (int32_t) (ecma_number_to_uint32 (x) * ecma_number_to_uint32 (y)); + break; + } + } + return ecma_make_number_value (x); + } /* if (builtin_routine_id <= ECMA_MATH_OBJECT_POW) */ + + if (builtin_routine_id <= ECMA_MATH_OBJECT_MIN) + { + return ecma_builtin_math_object_max_min (builtin_routine_id == ECMA_MATH_OBJECT_MAX, + arguments_list, + arguments_number); + } + + if (builtin_routine_id == ECMA_MATH_OBJECT_HYPOT) + { + return ecma_builtin_math_object_hypot (arguments_list, arguments_number); + } + + JERRY_ASSERT (builtin_routine_id == ECMA_MATH_OBJECT_RANDOM); + + return ecma_builtin_math_object_random (); +} /* ecma_builtin_math_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_MATH */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h new file mode 100644 index 00000000..c30ad25d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h @@ -0,0 +1,94 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Math built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_MATH + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v5, 15.8.1.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_E_U, ECMA_BUILTIN_NUMBER_E, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LN10_U, ECMA_BUILTIN_NUMBER_LN10, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.3 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LN2_U, ECMA_BUILTIN_NUMBER_LN2, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.4 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LOG2E_U, ECMA_BUILTIN_NUMBER_LOG2E, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.5 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LOG10E_U, ECMA_BUILTIN_NUMBER_LOG10E, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.6 */ +NUMBER_VALUE (LIT_MAGIC_STRING_PI_U, ECMA_BUILTIN_NUMBER_PI, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.7 */ +NUMBER_VALUE (LIT_MAGIC_STRING_SQRT1_2_U, ECMA_BUILTIN_NUMBER_SQRT_1_2, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.8 */ +NUMBER_VALUE (LIT_MAGIC_STRING_SQRT2_U, ECMA_BUILTIN_NUMBER_SQRT2, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 20.2.1.9 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_MATH_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_ABS, ECMA_MATH_OBJECT_ABS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ACOS, ECMA_MATH_OBJECT_ACOS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ASIN, ECMA_MATH_OBJECT_ASIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ATAN, ECMA_MATH_OBJECT_ATAN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ATAN2, ECMA_MATH_OBJECT_ATAN2, 2, 2) +ROUTINE (LIT_MAGIC_STRING_CEIL, ECMA_MATH_OBJECT_CEIL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_COS, ECMA_MATH_OBJECT_COS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_EXP, ECMA_MATH_OBJECT_EXP, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FLOOR, ECMA_MATH_OBJECT_FLOOR, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOG, ECMA_MATH_OBJECT_LOG, 1, 1) +ROUTINE (LIT_MAGIC_STRING_MAX, ECMA_MATH_OBJECT_MAX, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_MIN, ECMA_MATH_OBJECT_MIN, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_POW, ECMA_MATH_OBJECT_POW, 2, 2) +ROUTINE (LIT_MAGIC_STRING_RANDOM, ECMA_MATH_OBJECT_RANDOM, 0, 0) +ROUTINE (LIT_MAGIC_STRING_ROUND, ECMA_MATH_OBJECT_ROUND, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SIN, ECMA_MATH_OBJECT_SIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SQRT, ECMA_MATH_OBJECT_SQRT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TAN, ECMA_MATH_OBJECT_TAN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ACOSH, ECMA_MATH_OBJECT_ACOSH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ASINH, ECMA_MATH_OBJECT_ASINH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ATANH, ECMA_MATH_OBJECT_ATANH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_CBRT, ECMA_MATH_OBJECT_CBRT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_CLZ32, ECMA_MATH_OBJECT_CLZ32, 1, 1) +ROUTINE (LIT_MAGIC_STRING_COSH, ECMA_MATH_OBJECT_COSH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_EXPM1, ECMA_MATH_OBJECT_EXPM1, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FROUND, ECMA_MATH_OBJECT_FROUND, 1, 1) +ROUTINE (LIT_MAGIC_STRING_HYPOT, ECMA_MATH_OBJECT_HYPOT, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_IMUL, ECMA_MATH_OBJECT_IMUL, 2, 2) +ROUTINE (LIT_MAGIC_STRING_LOG1P, ECMA_MATH_OBJECT_LOG1P, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOG10, ECMA_MATH_OBJECT_LOG10, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOG2, ECMA_MATH_OBJECT_LOG2, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SIGN, ECMA_MATH_OBJECT_SIGN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SINH, ECMA_MATH_OBJECT_SINH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TANH, ECMA_MATH_OBJECT_TANH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TRUNC, ECMA_MATH_OBJECT_TRUNC, 1, 1) + +#endif /* JERRY_BUILTIN_MATH */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp new file mode 100644 index 00000000..456f7b64 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp @@ -0,0 +1,673 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_NUMBER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_NUMBER_PROTOTYPE_ROUTINE_START = 0, + ECMA_NUMBER_PROTOTYPE_VALUE_OF, + ECMA_NUMBER_PROTOTYPE_TO_STRING, + ECMA_NUMBER_PROTOTYPE_TO_LOCALE_STRING, + ECMA_NUMBER_PROTOTYPE_TO_FIXED, + ECMA_NUMBER_PROTOTYPE_TO_EXPONENTIAL, + ECMA_NUMBER_PROTOTYPE_TO_PRECISION, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-number-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID number_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup numberprototype ECMA Number.prototype object built-in + * @{ + */ + +/** + * Helper for rounding numbers + * + * @return rounded number + */ +static inline lit_utf8_size_t +ecma_builtin_number_prototype_helper_round (lit_utf8_byte_t *digits_p, /**< [in,out] number as a string in decimal + * form */ + lit_utf8_size_t num_digits, /**< length of the string representation */ + int32_t round_num, /**< number of digits to keep */ + int32_t *exponent_p, /**< [in, out] decimal exponent */ + bool zero) /**< true if digits_p represents zero */ +{ + if (round_num == 0 && *exponent_p == 0) + { + if (digits_p[0] >= 5) + { + digits_p[0] = '1'; + } + else + { + digits_p[0] = '0'; + } + + return 1; + } + + if (round_num < 1) + { + return 0; + } + + if ((lit_utf8_size_t) round_num >= num_digits || zero) + { + return num_digits; + } + + if (digits_p[round_num] >= '5') + { + digits_p[round_num] = '0'; + + int i = 1; + + /* Handle carry number. */ + for (; i <= round_num; i++) + { + if (++digits_p[round_num - i] <= '9') + { + break; + } + digits_p[round_num - i] = '0'; + } + + /* Prepend highest digit */ + if (i > round_num) + { + memmove (digits_p + 1, digits_p, num_digits); + digits_p[0] = '1'; + *exponent_p += 1; + } + } + + return (lit_utf8_size_t) round_num; +} /* ecma_builtin_number_prototype_helper_round */ + +/** + * Size of Number toString digit buffers. + */ +#define NUMBER_TO_STRING_MAX_DIGIT_COUNT 64u + +/** + * The Number.prototype object's 'toString' and 'toLocaleString' routines + * + * See also: + * ECMA-262 v5, 15.7.4.2 + * ECMA-262 v5, 15.7.4.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_number_prototype_object_to_string (ecma_number_t this_arg_number, /**< this argument number */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + static const lit_utf8_byte_t digit_chars[36] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + + uint32_t radix = 10; + if (arguments_list_len > 0 && !ecma_is_value_undefined (arguments_list_p[0])) + { + ecma_number_t arg_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arguments_list_p[0], &arg_num))) + { + return ECMA_VALUE_ERROR; + } + + radix = ecma_number_to_uint32 (arg_num); + + if (radix < 2 || radix > 36) + { + return ecma_raise_range_error (ECMA_ERR_RADIX_IS_OUT_OF_RANGE); + } + } + + if (ecma_number_is_nan (this_arg_number) || ecma_number_is_infinity (this_arg_number) + || ecma_number_is_zero (this_arg_number) || radix == 10) + { + ecma_string_t *ret_str_p = ecma_new_ecma_string_from_number (this_arg_number); + return ecma_make_string_value (ret_str_p); + } + + uint8_t integer_digits[NUMBER_TO_STRING_MAX_DIGIT_COUNT]; + uint8_t fraction_digits[NUMBER_TO_STRING_MAX_DIGIT_COUNT]; + uint32_t integer_zeros = 0; + uint32_t fraction_zeros = 0; + bool is_number_negative = false; + + if (ecma_number_is_negative (this_arg_number)) + { + this_arg_number = -this_arg_number; + is_number_negative = true; + } + + ecma_number_t integer_part = floor (this_arg_number); + ecma_number_t fraction_part = this_arg_number - integer_part; + + uint8_t *integer_cursor_p = integer_digits + NUMBER_TO_STRING_MAX_DIGIT_COUNT; + uint8_t *fraction_cursor_p = fraction_digits; + + if (fraction_part > 0.0) + { + uint8_t digit; + ecma_number_t precision = (ecma_number_get_next (this_arg_number) - this_arg_number) * 0.5f; + precision = JERRY_MAX (precision, ECMA_NUMBER_MIN_VALUE); + + do + { + fraction_part *= radix; + precision *= radix; + + digit = (uint8_t) floor (fraction_part); + + if (digit == 0 && fraction_cursor_p == fraction_digits) + { + fraction_zeros++; + continue; + } + + JERRY_ASSERT (fraction_cursor_p < fraction_digits + NUMBER_TO_STRING_MAX_DIGIT_COUNT); + *fraction_cursor_p++ = digit; + fraction_part -= (ecma_number_t) digit; + } while (fraction_part >= precision); + + /* Round to even */ + if (fraction_part > 0.5 || (fraction_part == 0.5 && (digit & 1) != 0)) + { + /* Add carry and remove overflowing trailing digits */ + while (true) + { + (*(--fraction_cursor_p))++; + + if (*fraction_cursor_p < radix) + { + /* Re-adjust cursor to point after the last significant digit */ + fraction_cursor_p++; + break; + } + + if (fraction_cursor_p == fraction_digits) + { + /* Carry overflowed to integer part */ + integer_part += 1; + break; + } + } + } + + /* Convert fraction digits to characters. */ + for (uint8_t *digit_p = fraction_digits; digit_p < fraction_cursor_p; digit_p++) + { + *digit_p = digit_chars[*digit_p]; + } + } + + while (ecma_number_biased_exp (ecma_number_to_binary (integer_part / radix)) + > ECMA_NUMBER_EXPONENT_BIAS + ECMA_NUMBER_FRACTION_WIDTH) + { + integer_zeros++; + integer_part /= radix; + } + + uint64_t integer_u64 = (uint64_t) integer_part; + + do + { + uint64_t remainder = integer_u64 % radix; + *(--integer_cursor_p) = (uint8_t) digit_chars[remainder]; + + integer_u64 /= radix; + } while (integer_u64 > 0); + + const uint32_t integer_digit_count = + (uint32_t) (integer_digits + NUMBER_TO_STRING_MAX_DIGIT_COUNT - integer_cursor_p); + JERRY_ASSERT (integer_digit_count > 0); + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + if (is_number_negative) + { + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_MINUS); + } + + ecma_stringbuilder_append_raw (&builder, integer_cursor_p, integer_digit_count); + + while (integer_zeros--) + { + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_0); + } + + if (fraction_cursor_p != fraction_digits) + { + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_DOT); + + while (fraction_zeros--) + { + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_0); + } + + const uint32_t fraction_digit_count = (uint32_t) (fraction_cursor_p - fraction_digits); + JERRY_ASSERT (fraction_digit_count > 0); + + ecma_stringbuilder_append_raw (&builder, fraction_digits, fraction_digit_count); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_number_prototype_object_to_string */ + +/** + * The Number.prototype object's 'valueOf' routine + * + * See also: + * ECMA-262 v5, 15.7.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_number_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_number (this_arg)) + { + return this_arg; + } + else if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_NUMBER)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (ecma_is_value_number (ext_object_p->u.cls.u3.value)); + + return ext_object_p->u.cls.u3.value; + } + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_NUMBER); +} /* ecma_builtin_number_prototype_object_value_of */ + +/** + * Type of number routine + */ +typedef enum +{ + NUMBER_ROUTINE_TO_FIXED, /**< Number.prototype.toFixed: ECMA-262 v11, 20.1.3.3 */ + NUMBER_ROUTINE_TO_EXPONENTIAL, /**< Number.prototype.toExponential: ECMA-262 v11, 20.1.3.2 */ + NUMBER_ROUTINE_TO_PRECISION, /**< Number.prototype.toPrecision: ECMA-262 v11, 20.1.3.5 */ + NUMBER_ROUTINE__COUNT, /**< count of the modes */ +} number_routine_mode_t; + +/** + * Helper method to convert a number based on the given routine. + */ +static ecma_value_t +ecma_builtin_number_prototype_object_to_number_convert (ecma_number_t this_num, /**< this argument number */ + ecma_value_t arg, /**< routine's argument */ + number_routine_mode_t mode) /**< number routine mode */ +{ + if (ecma_is_value_undefined (arg) && mode == NUMBER_ROUTINE_TO_PRECISION) + { + return ecma_builtin_number_prototype_object_to_string (this_num, NULL, 0); + } + + ecma_number_t arg_num; + ecma_value_t to_integer = ecma_op_to_integer (arg, &arg_num); + + if (ECMA_IS_VALUE_ERROR (to_integer)) + { + return to_integer; + } + + /* Argument boundary check for toFixed method */ + if (mode == NUMBER_ROUTINE_TO_FIXED && (arg_num <= -1 || arg_num >= 101)) + { + return ecma_raise_range_error (ECMA_ERR_FRACTION_DIGITS_OUT_OF_RANGE); + } + + /* Handle NaN separately */ + if (ecma_number_is_nan (this_num)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_NAN); + } + + /* Get the parameters of the number */ + lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; + lit_utf8_size_t num_of_digits; + int32_t exponent; + int32_t arg_int = ecma_number_to_int32 (arg_num); + bool is_zero = ecma_number_is_zero (this_num); + bool is_negative = ecma_number_is_negative (this_num); + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + if (is_negative) + { + if (!is_zero) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_MINUS); + } + + this_num *= -1; + } + + /* Handle zero separately */ + if (is_zero) + { + if (mode == NUMBER_ROUTINE_TO_PRECISION) + { + arg_int--; + } + + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + + if (arg_int > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_DOT); + } + + for (int32_t i = 0; i < arg_int; i++) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + } + + if (mode == NUMBER_ROUTINE_TO_EXPONENTIAL) + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "e+0", 3); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + } + + /* Handle infinity separately */ + if (ecma_number_is_infinity (this_num)) + { + ecma_stringbuilder_append_magic (&builder, LIT_MAGIC_STRING_INFINITY_UL); + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + } + + /* Argument boundary check for toExponential and toPrecision methods */ + if (mode == NUMBER_ROUTINE_TO_EXPONENTIAL && (arg_num <= -1 || arg_num >= 101)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_range_error (ECMA_ERR_FRACTION_DIGITS_OUT_OF_RANGE); + } + else if (mode == NUMBER_ROUTINE_TO_PRECISION && (arg_num < 1 || arg_num > 100)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_range_error (ECMA_ERR_PRECISION_DIGITS_MUST_BE_BETWEEN_IN_RANGE); + } + + num_of_digits = ecma_number_to_decimal (this_num, digits, &exponent); + + /* Handle undefined argument */ + if (ecma_is_value_undefined (arg) && mode == NUMBER_ROUTINE_TO_EXPONENTIAL) + { + arg_int = (int32_t) num_of_digits - 1; + } + + if (mode == NUMBER_ROUTINE_TO_FIXED && exponent > 21) + { + ecma_stringbuilder_destroy (&builder); + + if (is_negative) + { + this_num *= -1; + } + + return ecma_builtin_number_prototype_object_to_string (this_num, NULL, 0); + } + + int32_t digits_to_keep = arg_int; + + if (mode == NUMBER_ROUTINE_TO_FIXED) + { + digits_to_keep += exponent; + } + else if (mode == NUMBER_ROUTINE_TO_EXPONENTIAL) + { + digits_to_keep += 1; + } + + num_of_digits = ecma_builtin_number_prototype_helper_round (digits, num_of_digits, digits_to_keep, &exponent, false); + + /* toExponent routine and toPrecision cases where the exponent > precision or exponent < -5 */ + if (mode == NUMBER_ROUTINE_TO_EXPONENTIAL + || (mode == NUMBER_ROUTINE_TO_PRECISION && (exponent < -5 || exponent > arg_int))) + { + /* Append first digit */ + ecma_stringbuilder_append_byte (&builder, *digits); + + if (mode == NUMBER_ROUTINE_TO_PRECISION) + { + arg_int--; + } + + if (arg_int > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_DOT); + } + + /* Append significant fraction digits */ + ecma_stringbuilder_append_raw (&builder, digits + 1, num_of_digits - 1); + + /* Append leading zeros */ + for (int32_t i = (int32_t) (num_of_digits); i < arg_int + 1; i++) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + } + + ecma_stringbuilder_append_char (&builder, LIT_CHAR_LOWERCASE_E); + + if (exponent <= 0) + { + exponent = (-exponent) + 1; + ecma_stringbuilder_append_char (&builder, LIT_CHAR_MINUS); + } + else + { + exponent -= 1; + ecma_stringbuilder_append_char (&builder, LIT_CHAR_PLUS); + } + + /* Append exponent part */ + lit_utf8_size_t exp_size = ecma_uint32_to_utf8_string ((uint32_t) exponent, digits, 3); + ecma_stringbuilder_append_raw (&builder, digits, exp_size); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + } + + /* toFixed routine and toPrecision cases where the exponent <= precision and exponent >= -5 */ + lit_utf8_size_t result_digits; + + if (mode == NUMBER_ROUTINE_TO_FIXED) + { + result_digits = ((exponent > 0) ? (lit_utf8_size_t) (exponent + arg_int) : (lit_utf8_size_t) (arg_int + 1)); + } + else + { + result_digits = ((exponent <= 0) ? (lit_utf8_size_t) (1 - exponent + arg_int) : (lit_utf8_size_t) arg_int); + } + + /* Number of digits we copied from digits array */ + lit_utf8_size_t copied_digits = 0; + + if (exponent == 0 && digits_to_keep == 0) + { + ecma_stringbuilder_append_char (&builder, *digits); + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + } + + if (exponent <= 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + result_digits--; + + if (result_digits > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_DOT); + + /* Append leading zeros to the fraction part */ + for (int32_t i = 0; i < -exponent && result_digits > 0; i++) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + result_digits--; + } + } + } + else + { + /* Append significant digits of integer part */ + copied_digits = JERRY_MIN (JERRY_MIN (num_of_digits, result_digits), (lit_utf8_size_t) exponent); + ecma_stringbuilder_append_raw (&builder, digits, copied_digits); + + result_digits -= copied_digits; + num_of_digits -= copied_digits; + exponent -= (int32_t) copied_digits; + + /* Append zeros before decimal point */ + while (exponent > 0 && result_digits > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + result_digits--; + exponent--; + } + + if (result_digits > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_DOT); + } + } + + if (result_digits > 0) + { + /* Append significant digits to the fraction part */ + lit_utf8_size_t to_copy = JERRY_MIN (num_of_digits, result_digits); + ecma_stringbuilder_append_raw (&builder, digits + copied_digits, to_copy); + result_digits -= to_copy; + + /* Append leading zeros */ + while (result_digits > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + result_digits--; + } + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_number_prototype_object_to_number_convert */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_number_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + ecma_value_t this_value = ecma_builtin_number_prototype_object_value_of (this_arg); + + if (ECMA_IS_VALUE_ERROR (this_value)) + { + return this_value; + } + + if (builtin_routine_id == ECMA_NUMBER_PROTOTYPE_VALUE_OF) + { + return ecma_copy_value (this_value); + } + + ecma_number_t this_arg_number = ecma_get_number_from_value (this_value); + + switch (builtin_routine_id) + { + case ECMA_NUMBER_PROTOTYPE_TO_STRING: + { + return ecma_builtin_number_prototype_object_to_string (this_arg_number, arguments_list_p, arguments_number); + } + case ECMA_NUMBER_PROTOTYPE_TO_LOCALE_STRING: + { + return ecma_builtin_number_prototype_object_to_string (this_arg_number, NULL, 0); + } + case ECMA_NUMBER_PROTOTYPE_TO_FIXED: + case ECMA_NUMBER_PROTOTYPE_TO_EXPONENTIAL: + case ECMA_NUMBER_PROTOTYPE_TO_PRECISION: + { + const int option = NUMBER_ROUTINE_TO_FIXED + (builtin_routine_id - ECMA_NUMBER_PROTOTYPE_TO_FIXED); + return ecma_builtin_number_prototype_object_to_number_convert (this_arg_number, + arguments_list_p[0], + (number_routine_mode_t) option); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_number_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_NUMBER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.inc.h new file mode 100644 index 00000000..e5ac7dd1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Number.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_NUMBER + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.7.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_NUMBER, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_NUMBER_PROTOTYPE_TO_STRING, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_NUMBER_PROTOTYPE_VALUE_OF, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_NUMBER_PROTOTYPE_TO_LOCALE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_FIXED_UL, ECMA_NUMBER_PROTOTYPE_TO_FIXED, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TO_EXPONENTIAL_UL, ECMA_NUMBER_PROTOTYPE_TO_EXPONENTIAL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TO_PRECISION_UL, ECMA_NUMBER_PROTOTYPE_TO_PRECISION, 1, 1) + +#endif /* JERRY_BUILTIN_NUMBER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.cpp new file mode 100644 index 00000000..89fa1ab9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.cpp @@ -0,0 +1,246 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-bigint.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-number-object.h" +#include "ecma-objects.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_NUMBER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_NUMBER_OBJECT_ROUTINE_START = 0, + ECMA_NUMBER_OBJECT_ROUTINE_IS_FINITE, + ECMA_NUMBER_OBJECT_ROUTINE_IS_NAN, + ECMA_NUMBER_OBJECT_ROUTINE_IS_INTEGER, + ECMA_NUMBER_OBJECT_ROUTINE_IS_SAFE_INTEGER +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-number.inc.h" +#define BUILTIN_UNDERSCORED_ID number +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup number ECMA Number object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Number object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_number_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if (arguments_list_len == 0) + { + ret_value = ecma_make_integer_value (0); + } + else + { + ecma_number_t num; + ret_value = ecma_op_to_numeric (arguments_list_p[0], &num, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (ret_value)) + { + ecma_value_t bigint = ret_value; + ret_value = ecma_bigint_to_number (bigint); + ecma_free_value (bigint); + } + else +#endif /* JERRY_BUILTIN_BIGINT */ + { + ret_value = ecma_make_number_value (num); + } + } + + return ret_value; +} /* ecma_builtin_number_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Number object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_number_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len == 0) + { + return ecma_op_create_number_object (ecma_make_integer_value (0)); + } + +#if JERRY_BUILTIN_BIGINT + ecma_number_t num; + ecma_value_t value = ecma_op_to_numeric (arguments_list_p[0], &num, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + if (ecma_is_value_bigint (value)) + { + ecma_value_t bigint = value; + value = ecma_bigint_to_number (bigint); + ecma_free_value (bigint); + } + else + { + value = ecma_make_number_value (num); + } + + ecma_value_t result = ecma_op_create_number_object (value); + ecma_free_value (value); + return result; +#else /* !JERRY_BUILTIN_BIGINT */ + return ecma_op_create_number_object (arguments_list_p[0]); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* ecma_builtin_number_dispatch_construct */ + +/** + * The Number object 'isInteger' and 'isSafeInteger' routine + * + * See also: + * ECMA-262 v6, 20.1.2.3 + * ECMA-262 v6, 20.1.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_number_object_is_integer_helper (ecma_value_t arg, /**< routine's argument */ + ecma_number_t num, /**< this number */ + bool is_safe) /**< is the number safe */ +{ + if (ecma_number_is_nan (num) || ecma_number_is_infinity (num)) + { + return ECMA_VALUE_FALSE; + } + + ecma_number_t int_num; + + if (is_safe) + { + int_num = ecma_number_trunc (num); + + if (fabs (int_num) > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ECMA_VALUE_FALSE; + } + } + else + { + ecma_op_to_integer (arg, &int_num); + } + + return (int_num == num) ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE; +} /* ecma_builtin_number_object_is_integer_helper */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_number_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (this_arg, arguments_number); + + if (!ecma_is_value_number (arguments_list_p[0])) + { + return ECMA_VALUE_FALSE; + } + + ecma_number_t num = ecma_get_number_from_value (arguments_list_p[0]); + + switch (builtin_routine_id) + { + case ECMA_NUMBER_OBJECT_ROUTINE_IS_FINITE: + { + return ecma_make_boolean_value (!(ecma_number_is_nan (num) || ecma_number_is_infinity (num))); + } + case ECMA_NUMBER_OBJECT_ROUTINE_IS_NAN: + { + return ecma_make_boolean_value (ecma_number_is_nan (num)); + } + case ECMA_NUMBER_OBJECT_ROUTINE_IS_INTEGER: + case ECMA_NUMBER_OBJECT_ROUTINE_IS_SAFE_INTEGER: + { + bool is_safe = (builtin_routine_id == ECMA_NUMBER_OBJECT_ROUTINE_IS_SAFE_INTEGER); + return ecma_builtin_number_object_is_integer_helper (arguments_list_p[0], num, is_safe); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_number_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_NUMBER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h new file mode 100644 index 00000000..5a30cbf0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h @@ -0,0 +1,72 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Number built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_NUMBER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* ECMA-262 v5, 15.7.3.4 */ +NUMBER_VALUE (LIT_MAGIC_STRING_NAN, ECMA_BUILTIN_NUMBER_NAN, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.7.3.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_MAX_VALUE_U, ECMA_BUILTIN_NUMBER_MAX, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.7.3.3 */ +NUMBER_VALUE (LIT_MAGIC_STRING_MIN_VALUE_U, ECMA_BUILTIN_NUMBER_MIN, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.7.3.5 */ +NUMBER_VALUE (LIT_MAGIC_STRING_POSITIVE_INFINITY_U, ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.7.3.6 */ +NUMBER_VALUE (LIT_MAGIC_STRING_NEGATIVE_INFINITY_U, ECMA_BUILTIN_NUMBER_NEGATIVE_INFINITY, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 20.1.2.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_EPSILON_U, ECMA_BUILTIN_NUMBER_EPSILON, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 20.1.2.6 */ +NUMBER_VALUE (LIT_MAGIC_STRING_MAX_SAFE_INTEGER_U, ECMA_BUILTIN_NUMBER_MAX_SAFE_INTEGER, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 20.1.2.8 */ +NUMBER_VALUE (LIT_MAGIC_STRING_MIN_SAFE_INTEGER_U, ECMA_BUILTIN_NUMBER_MIN_SAFE_INTEGER, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_NUMBER_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.7.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_NUMBER_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_NUMBER */ + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_IS_FINITE, ECMA_NUMBER_OBJECT_ROUTINE_IS_FINITE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_NAN, ECMA_NUMBER_OBJECT_ROUTINE_IS_NAN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_INTEGER, ECMA_NUMBER_OBJECT_ROUTINE_IS_INTEGER, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_SAFE_INTEGER, ECMA_NUMBER_OBJECT_ROUTINE_IS_SAFE_INTEGER, 1, 1) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_FLOAT, LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_INT, LIT_MAGIC_STRING_PARSE_INT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.cpp new file mode 100644 index 00000000..28abfbb4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.cpp @@ -0,0 +1,513 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtin-object.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + /* Note: these 6 routines must be in this order */ + ECMA_OBJECT_PROTOTYPE_ROUTINE_START = 0, + ECMA_OBJECT_PROTOTYPE_TO_STRING, + ECMA_OBJECT_PROTOTYPE_VALUE_OF, + ECMA_OBJECT_PROTOTYPE_TO_LOCALE_STRING, + ECMA_OBJECT_PROTOTYPE_GET_PROTO, + ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF, + ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY, + ECMA_OBJECT_PROTOTYPE_PROPERTY_IS_ENUMERABLE, + ECMA_OBJECT_PROTOTYPE_SET_PROTO, +#if JERRY_BUILTIN_ANNEXB + ECMA_OBJECT_PROTOTYPE_DEFINE_GETTER, + ECMA_OBJECT_PROTOTYPE_DEFINE_SETTER, + ECMA_OBJECT_PROTOTYPE_LOOKUP_GETTER, + ECMA_OBJECT_PROTOTYPE_LOOKUP_SETTER, +#endif /* JERRY_BUILTIN_ANNEXB */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-object-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID object_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup objectprototype ECMA Object.prototype object built-in + * @{ + */ + +/** + * The Object.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v5, 15.2.4.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ +{ + return ecma_builtin_helper_object_to_string (this_arg); +} /* ecma_builtin_object_prototype_object_to_string */ + +/** + * The Object.prototype object's 'valueOf' routine + * + * See also: + * ECMA-262 v5, 15.2.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ +{ + return ecma_op_to_object (this_arg); +} /* ecma_builtin_object_prototype_object_value_of */ + +/** + * The Object.prototype object's 'toLocaleString' routine + * + * See also: + * ECMA-262 v5, 15.2.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_to_locale_string (ecma_value_t this_arg) /**< this argument */ +{ + return ecma_op_invoke_by_magic_id (this_arg, LIT_MAGIC_STRING_TO_STRING_UL, &this_arg, 1); +} /* ecma_builtin_object_prototype_object_to_locale_string */ + +/** + * The Object.prototype object's 'hasOwnProperty' routine + * + * See also: + * ECMA-262 v5, 15.2.4.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_has_own_property (ecma_object_t *obj_p, /**< this argument */ + ecma_string_t *prop_name_p) /**< first argument */ +{ + return ecma_op_object_has_own_property (obj_p, prop_name_p); +} /* ecma_builtin_object_prototype_object_has_own_property */ + +/** + * The Object.prototype object's 'isPrototypeOf' routine + * + * See also: + * ECMA-262 v5, 15.2.4.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_is_prototype_of (ecma_object_t *obj_p, /**< this argument */ + ecma_value_t arg) /**< routine's first argument */ +{ + /* 3. Compare prototype to object */ + ecma_value_t v_obj_value = ecma_op_to_object (arg); + + if (ECMA_IS_VALUE_ERROR (v_obj_value)) + { + return v_obj_value; + } + + ecma_object_t *v_obj_p = ecma_get_object_from_value (v_obj_value); + + ecma_value_t ret_value = ecma_op_object_is_prototype_of (obj_p, v_obj_p); + + ecma_deref_object (v_obj_p); + + return ret_value; +} /* ecma_builtin_object_prototype_object_is_prototype_of */ + +/** + * The Object.prototype object's 'propertyIsEnumerable' routine + * + * See also: + * ECMA-262 v5, 15.2.4.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_property_is_enumerable (ecma_object_t *obj_p, /**< this argument */ + ecma_string_t *prop_name_p) /**< first argument */ +{ + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, prop_name_p, &prop_desc); + + if (!ecma_is_value_true (status)) + { + return status; + } + + bool is_enumerable = (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE); + + ecma_free_property_descriptor (&prop_desc); + + return ecma_make_boolean_value (is_enumerable); +} /* ecma_builtin_object_prototype_object_property_is_enumerable */ + +#if JERRY_BUILTIN_ANNEXB +/** + * The Object.prototype object's '__defineGetter__' and '__defineSetter__' routine + * + * See also: + * ECMA-262 v11, B.2.2.2 + * ECMA-262 v11, B.2.2.3 + * + * @return ECMA_VALUE_ERROR - if the operation fails, + * ECMA_VALUE_UNDEFINED - otherwise + */ +static ecma_value_t +ecma_builtin_object_prototype_define_getter_setter (ecma_value_t this_arg, /**< this argument */ + ecma_value_t prop, /**< property */ + ecma_value_t accessor, /**< getter/setter function */ + bool define_getter) /**< true - defineGetter method + false - defineSetter method */ +{ + /* 1. */ + ecma_value_t to_obj = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (to_obj)) + { + return to_obj; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (to_obj); + + /* 2. */ + if (!ecma_op_is_callable (accessor)) + { + ecma_deref_object (obj_p); + return ecma_raise_type_error (ECMA_ERR_GETTER_IS_NOT_CALLABLE); + } + + ecma_object_t *accessor_obj_p = ecma_get_object_from_value (accessor); + + /* 3. */ + ecma_property_descriptor_t desc = ecma_make_empty_property_descriptor (); + desc.flags |= (JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE_DEFINED + | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_SHOULD_THROW); + + if (define_getter) + { + desc.get_p = accessor_obj_p; + desc.flags |= JERRY_PROP_IS_GET_DEFINED; + } + else + { + desc.set_p = accessor_obj_p; + desc.flags |= JERRY_PROP_IS_SET_DEFINED; + } + + /* 4. */ + ecma_string_t *prop_name_p = ecma_op_to_property_key (prop); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + ecma_deref_object (obj_p); + return ECMA_VALUE_ERROR; + } + + /* 5. */ + ecma_value_t define_prop = ecma_op_object_define_own_property (obj_p, prop_name_p, &desc); + + ecma_deref_object (obj_p); + ecma_deref_ecma_string (prop_name_p); + + if (ECMA_IS_VALUE_ERROR (define_prop)) + { + return define_prop; + } + + /* 6. */ + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_object_prototype_define_getter_setter */ + +/** + * The Object.prototype object's '__lookupGetter__' and '__lookupSetter__' routine + * + * See also: + * ECMA-262 v11, B.2.2.4 + * ECMA-262 v11, B.2.2.5 + * + * @return ECMA_VALUE_ERROR - if the operation fails, + * ECMA_VALUE_UNDEFINED - if the property was not found + * Accessor property - otherwise + */ +static ecma_value_t +ecma_builtin_object_prototype_lookup_getter_setter (ecma_value_t this_arg, /**< this argument */ + ecma_value_t prop, /**< property */ + bool lookup_getter) /**< true - lookupGetter method + false - lookupSetter method */ +{ + /* 1. */ + ecma_value_t to_obj = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (to_obj)) + { + return to_obj; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (to_obj); + + /* 2. */ + ecma_string_t *prop_name_p = ecma_op_to_property_key (prop); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + ecma_deref_object (obj_p); + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value = ECMA_VALUE_UNDEFINED; + + ecma_ref_object (obj_p); + + /* 3. */ + while (true) + { + /* 3.a */ + ecma_property_descriptor_t desc; + ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (obj_p, prop_name_p, &desc); + + if (ECMA_IS_VALUE_ERROR (get_desc)) + { + ret_value = get_desc; + ecma_deref_object (obj_p); + break; + } + + /* 3.b */ + if (ecma_is_value_true (get_desc)) + { + if ((desc.flags & JERRY_PROP_IS_SET_DEFINED) || (desc.flags & JERRY_PROP_IS_GET_DEFINED)) + { + if (lookup_getter && desc.get_p != NULL) + { + ecma_ref_object (desc.get_p); + ret_value = ecma_make_object_value (desc.get_p); + } + else if (!lookup_getter && desc.set_p != NULL) + { + ecma_ref_object (desc.set_p); + ret_value = ecma_make_object_value (desc.set_p); + } + } + + ecma_free_property_descriptor (&desc); + ecma_deref_object (obj_p); + break; + } + + /* 3.c */ + ecma_object_t *proto_p = ecma_op_object_get_prototype_of (obj_p); + ecma_deref_object (obj_p); + + if (proto_p == NULL) + { + break; + } + else if (JERRY_UNLIKELY (proto_p == ECMA_OBJECT_POINTER_ERROR)) + { + ret_value = ECMA_VALUE_ERROR; + break; + } + + /* Advance up on prototype chain. */ + obj_p = proto_p; + } + + ecma_free_value (to_obj); + ecma_deref_ecma_string (prop_name_p); + + return ret_value; +} /* ecma_builtin_object_prototype_lookup_getter_setter */ +#endif /* JERRY_BUILTIN_ANNEXB */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + /* no specialization */ + if (builtin_routine_id <= ECMA_OBJECT_PROTOTYPE_VALUE_OF) + { + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_TO_STRING) + { + return ecma_builtin_object_prototype_object_to_string (this_arg); + } + + JERRY_ASSERT (builtin_routine_id <= ECMA_OBJECT_PROTOTYPE_VALUE_OF); + + return ecma_builtin_object_prototype_object_value_of (this_arg); + } + + if (builtin_routine_id <= ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF) + { + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF) + { + /* 15.2.4.6.1. */ + if (!ecma_is_value_object (arguments_list_p[0])) + { + return ECMA_VALUE_FALSE; + } + } + + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_TO_LOCALE_STRING) + { + return ecma_builtin_object_prototype_object_to_locale_string (this_arg); + } + + ecma_value_t to_object = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (to_object)) + { + return to_object; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (to_object); + + ecma_value_t ret_value; + + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_GET_PROTO) + { + ret_value = ecma_builtin_object_object_get_prototype_of (obj_p); + } + else + { + ret_value = ecma_builtin_object_prototype_object_is_prototype_of (obj_p, arguments_list_p[0]); + } + + ecma_deref_object (obj_p); + + return ret_value; + } + + JERRY_ASSERT (builtin_routine_id >= ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY); + + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_SET_PROTO) + { + return ecma_builtin_object_object_set_proto (this_arg, arguments_list_p[0]); + } +#if JERRY_BUILTIN_ANNEXB + else if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_LOOKUP_GETTER) + { + return ecma_builtin_object_prototype_lookup_getter_setter (this_arg, arguments_list_p[0], true); + } + else if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_LOOKUP_SETTER) + { + return ecma_builtin_object_prototype_lookup_getter_setter (this_arg, arguments_list_p[0], false); + } + else if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_DEFINE_GETTER) + { + return ecma_builtin_object_prototype_define_getter_setter (this_arg, + arguments_list_p[0], + arguments_list_p[1], + true); + } + else if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_DEFINE_SETTER) + { + return ecma_builtin_object_prototype_define_getter_setter (this_arg, + arguments_list_p[0], + arguments_list_p[1], + false); + } +#endif /* JERRY_BUILTIN_ANNEXB */ + + ecma_string_t *prop_name_p = ecma_op_to_property_key (arguments_list_p[0]); + + if (prop_name_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t to_object = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (to_object)) + { + ecma_deref_ecma_string (prop_name_p); + return to_object; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (to_object); + + ecma_value_t ret_value; + + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY) + { + ret_value = ecma_builtin_object_prototype_object_has_own_property (obj_p, prop_name_p); + } + else + { + ret_value = ecma_builtin_object_prototype_object_property_is_enumerable (obj_p, prop_name_p); + } + + ecma_deref_ecma_string (prop_name_p); + ecma_deref_object (obj_p); + + return ret_value; +} /* ecma_builtin_object_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.inc.h new file mode 100644 index 00000000..b218eda5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.inc.h @@ -0,0 +1,49 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Object.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.2.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_OBJECT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +ACCESSOR_READ_WRITE (LIT_MAGIC_STRING__PROTO__, + ECMA_OBJECT_PROTOTYPE_GET_PROTO, + ECMA_OBJECT_PROTOTYPE_SET_PROTO, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_OBJECT_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_OBJECT_PROTOTYPE_VALUE_OF, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_OBJECT_PROTOTYPE_TO_LOCALE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_HAS_OWN_PROPERTY_UL, ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_PROTOTYPE_OF_UL, ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL, ECMA_OBJECT_PROTOTYPE_PROPERTY_IS_ENUMERABLE, 1, 1) + +#if JERRY_BUILTIN_ANNEXB +ROUTINE (LIT_MAGIC_STRING_DEFINE_GETTER, ECMA_OBJECT_PROTOTYPE_DEFINE_GETTER, 2, 2) +ROUTINE (LIT_MAGIC_STRING_DEFINE_SETTER, ECMA_OBJECT_PROTOTYPE_DEFINE_SETTER, 2, 2) +ROUTINE (LIT_MAGIC_STRING_LOOKUP_GETTER, ECMA_OBJECT_PROTOTYPE_LOOKUP_GETTER, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOOKUP_SETTER, ECMA_OBJECT_PROTOTYPE_LOOKUP_SETTER, 1, 1) +#endif /* JERRY_BUILTIN_ANNEXB*/ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp new file mode 100644 index 00000000..ecadb696 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp @@ -0,0 +1,1555 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" + +#include "jcontext.h" +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_OBJECT_ROUTINE_START = 0, + + ECMA_OBJECT_ROUTINE_CREATE, + ECMA_OBJECT_ROUTINE_IS, + ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY, + ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_ASSIGN, + ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR, + ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTORS, + ECMA_OBJECT_ROUTINE_HAS_OWN, + ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF, + ECMA_OBJECT_ROUTINE_FROM_ENTRIES, + ECMA_OBJECT_ROUTINE_KEYS, + ECMA_OBJECT_ROUTINE_VALUES, + ECMA_OBJECT_ROUTINE_ENTRIES, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES, + ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_FREEZE, + ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS, + ECMA_OBJECT_ROUTINE_SEAL, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE, + ECMA_OBJECT_ROUTINE_IS_FROZEN, + ECMA_OBJECT_ROUTINE_IS_SEALED, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-object.inc.h" +#define BUILTIN_UNDERSCORED_ID object +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup object ECMA Object object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Object object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_object_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + if (arguments_list_len == 0 || ecma_is_value_undefined (arguments_list_p[0]) + || ecma_is_value_null (arguments_list_p[0])) + { + return ecma_make_object_value (ecma_op_create_object_object_noarg ()); + } + + return ecma_op_to_object (arguments_list_p[0]); +} /* ecma_builtin_object_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Object object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_object_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + if (JERRY_CONTEXT (current_new_target_p) != ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT)) + { + ecma_object_t *prototype_obj_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *object_p = ecma_create_object (prototype_obj_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (prototype_obj_p); + + return ecma_make_object_value (object_p); + } + + return ecma_builtin_object_dispatch_call (arguments_list_p, arguments_list_len); +} /* ecma_builtin_object_dispatch_construct */ + +/** + * The Object object's 'getPrototypeOf' routine + * + * See also: + * ECMA-262 v5, 15.2.3.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_get_prototype_of (ecma_object_t *obj_p) /**< routine's argument */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_get_prototype_of (obj_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (obj_p); + + if (proto_cp != JMEM_CP_NULL) + { + ecma_object_t *prototype_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + ecma_ref_object (prototype_p); + return ecma_make_object_value (prototype_p); + } + + return ECMA_VALUE_NULL; +} /* ecma_builtin_object_object_get_prototype_of */ + +/** + * The Object object's 'setPrototypeOf' routine + * + * See also: + * ES2015 19.1.2.18 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_set_prototype_of (ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + /* 1., 2. */ + if (!ecma_op_require_object_coercible (arg1)) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + if (!ecma_is_value_object (arg2) && !ecma_is_value_null (arg2)) + { + return ecma_raise_type_error (ECMA_ERR_PROTOTYPE_IS_NEITHER_OBJECT_NOR_NULL); + } + + /* 4. */ + if (!ecma_is_value_object (arg1)) + { + return ecma_copy_value (arg1); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arg1); + ecma_value_t status; + + /* 5. */ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + status = ecma_proxy_object_set_prototype_of (obj_p, arg2); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + } + else + { +#endif /* JERRY_BUILTIN_PROXY */ + status = ecma_op_ordinary_object_set_prototype_of (obj_p, arg2); +#if JERRY_BUILTIN_PROXY + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (status)) + { + return ecma_raise_type_error (ECMA_ERR_SET_PROTOTYPE); + } + + JERRY_ASSERT (ecma_is_value_true (status)); + ecma_ref_object (obj_p); + + return arg1; +} /* ecma_builtin_object_object_set_prototype_of */ + +/** + * The Object object's set __proto__ routine + * + * See also: + * ECMA-262 v6, B.2.2.1.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_set_proto (ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + /* 1., 2. */ + if (!ecma_op_require_object_coercible (arg1)) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + if (!ecma_is_value_object (arg2) && !ecma_is_value_null (arg2)) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 4. */ + if (!ecma_is_value_object (arg1)) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arg1); + ecma_value_t status; + + /* 5. */ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + status = ecma_proxy_object_set_prototype_of (obj_p, arg2); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + } + else + { +#endif /* JERRY_BUILTIN_PROXY */ + status = ecma_op_ordinary_object_set_prototype_of (obj_p, arg2); +#if JERRY_BUILTIN_PROXY + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (status)) + { + return ecma_raise_type_error (ECMA_ERR_SET_PROTOTYPE); + } + + JERRY_ASSERT (ecma_is_value_true (status)); + + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_object_object_set_proto */ + +/** + * SetIntegrityLevel operation + * + * See also: + * ECMA-262 v6, 7.3.14 + * + * @return ECMA_VALUE_ERROR - if the operation raised an error + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the integrity level has been set successfully + */ +static ecma_value_t +ecma_builtin_object_set_integrity_level (ecma_object_t *obj_p, /**< object */ + bool is_seal) /**< true - set "sealed" + * false - set "frozen" */ +{ + /* 3. */ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + ecma_value_t status = ecma_proxy_object_prevent_extensions (obj_p); + + if (!ecma_is_value_true (status)) + { + return status; + } + } + else +#endif /* JERRY_BUILTIN_PROXY */ + { + ecma_op_ordinary_object_prevent_extensions (obj_p); + } + + /* 6. */ + ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (props_p == NULL) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *buffer_p = props_p->buffer_p; + + if (is_seal) + { + /* 8.a */ + for (uint32_t i = 0; i < props_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]); + + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_free (props_p); + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (status)) + { + continue; + } + + prop_desc.flags &= (uint16_t) ~JERRY_PROP_IS_CONFIGURABLE; + prop_desc.flags |= JERRY_PROP_SHOULD_THROW; + + /* 8.a.i */ + ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, property_name_p, &prop_desc); + + ecma_free_property_descriptor (&prop_desc); + + /* 8.a.ii */ + if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) + { + ecma_collection_free (props_p); + return define_own_prop_ret; + } + + ecma_free_value (define_own_prop_ret); + } + } + else + { + /* 9.a */ + for (uint32_t i = 0; i < props_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]); + + /* 9.1 */ + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_free (props_p); + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (status)) + { + continue; + } + + /* 9.2 */ + if ((prop_desc.flags & (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)) + == (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)) + { + prop_desc.flags &= (uint16_t) ~JERRY_PROP_IS_WRITABLE; + } + + prop_desc.flags &= (uint16_t) ~JERRY_PROP_IS_CONFIGURABLE; + prop_desc.flags |= JERRY_PROP_SHOULD_THROW; + + /* 9.3 */ + ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, property_name_p, &prop_desc); + + ecma_free_property_descriptor (&prop_desc); + + /* 9.4 */ + if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) + { + ecma_collection_free (props_p); + return define_own_prop_ret; + } + + ecma_free_value (define_own_prop_ret); + } + } + + ecma_collection_free (props_p); + + return ECMA_VALUE_TRUE; +} /* ecma_builtin_object_set_integrity_level */ + +/** + * The Object object's 'seal' routine + * + * See also: + * ECMA-262 v5, 15.2.3.8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_seal (ecma_object_t *obj_p) /**< routine's argument */ +{ + ecma_value_t status = ecma_builtin_object_set_integrity_level (obj_p, true); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + +#if JERRY_BUILTIN_PROXY + if (ecma_is_value_false (status)) + { + return ecma_raise_type_error (ECMA_ERR_OBJECT_CANNOT_BE_SEALED); + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 4. */ + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); +} /* ecma_builtin_object_object_seal */ + +/** + * The Object object's 'freeze' routine + * + * See also: + * ECMA-262 v5, 15.2.3.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_freeze (ecma_object_t *obj_p) /**< routine's argument */ +{ + ecma_value_t status = ecma_builtin_object_set_integrity_level (obj_p, false); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + +#if JERRY_BUILTIN_PROXY + if (ecma_is_value_false (status)) + { + return ecma_raise_type_error (ECMA_ERR_OBJECT_CANNOT_BE_FROZEN); + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 4. */ + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); +} /* ecma_builtin_object_object_freeze */ + +/** + * The Object object's 'preventExtensions' routine + * + * See also: + * ECMA-262 v5, 15.2.3.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_prevent_extensions (ecma_object_t *obj_p) /**< routine's argument */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + ecma_value_t status = ecma_proxy_object_prevent_extensions (obj_p); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + if (ecma_is_value_false (status)) + { + return ecma_raise_type_error (ECMA_ERR_SET_EXTENSIBLE_PROPERTY); + } + + JERRY_ASSERT (ecma_is_value_true (status)); + } + else + { +#endif /* JERRY_BUILTIN_PROXY */ + ecma_op_ordinary_object_prevent_extensions (obj_p); +#if JERRY_BUILTIN_PROXY + } +#endif /* JERRY_BUILTIN_PROXY */ + ecma_ref_object (obj_p); + + return ecma_make_object_value (obj_p); +} /* ecma_builtin_object_object_prevent_extensions */ + +/** + * The Object object's 'isSealed' and 'isFrozen' routines + * + * See also: + * ECMA-262 v5, 15.2.3.11 + * ECMA-262 v5, 15.2.3.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_test_integrity_level (ecma_object_t *obj_p, /**< routine's argument */ + int mode) /**< routine mode */ +{ + JERRY_ASSERT (mode == ECMA_OBJECT_ROUTINE_IS_FROZEN || mode == ECMA_OBJECT_ROUTINE_IS_SEALED); + + /* 3. */ + bool is_extensible; +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + ecma_value_t status = ecma_proxy_object_is_extensible (obj_p); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + is_extensible = ecma_is_value_true (status); + } + else +#endif /* JERRY_BUILTIN_PROXY */ + { + is_extensible = ecma_op_ordinary_object_is_extensible (obj_p); + } + + if (is_extensible) + { + return ECMA_VALUE_FALSE; + } + + /* the value can be updated in the loop below */ + ecma_value_t ret_value = ECMA_VALUE_TRUE; + + /* 2. */ + ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (props_p == NULL) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *buffer_p = props_p->buffer_p; + + for (uint32_t i = 0; i < props_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]); + + /* 2.a */ + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ret_value = status; + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (status)) + { + continue; + } + + bool is_writable_data = ((prop_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE)) + == (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE)); + bool is_configurable = (prop_desc.flags & JERRY_PROP_IS_CONFIGURABLE); + + ecma_free_property_descriptor (&prop_desc); + + /* 2.b for isFrozen */ + /* 2.b for isSealed, 2.c for isFrozen */ + if ((mode == ECMA_OBJECT_ROUTINE_IS_FROZEN && is_writable_data) || is_configurable) + { + ret_value = ECMA_VALUE_FALSE; + break; + } + } + + ecma_collection_free (props_p); + + return ret_value; +} /* ecma_builtin_object_test_integrity_level */ + +/** + * The Object object's 'isExtensible' routine + * + * See also: + * ECMA-262 v5, 15.2.3.13 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_is_extensible (ecma_object_t *obj_p) /**< routine's argument */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_is_extensible (obj_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ecma_make_boolean_value (ecma_op_ordinary_object_is_extensible (obj_p)); +} /* ecma_builtin_object_object_is_extensible */ + +/** + * Common implementation of the Object object's 'keys', 'values', 'entries' routines + * + * See also: + * ECMA-262 v11, 19.1.2.17 + * ECMA-262 v11, 19.1.2.22 + * ECMA-262 v11, 19.1.2.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_keys_values_helper (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_enumerable_property_names_options_t option) /**< listing option */ +{ + /* 2. */ + ecma_collection_t *props_p = ecma_op_object_get_enumerable_property_names (obj_p, option); + + if (props_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + return ecma_op_new_array_object_from_collection (props_p, option != ECMA_ENUMERABLE_PROPERTY_KEYS); +} /* ecma_builtin_object_object_keys_values_helper */ + +/** + * The Object object's 'getOwnPropertyDescriptor' routine + * + * See also: + * ECMA-262 v5, 15.2.3.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_get_own_property_descriptor (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_string_t *name_str_p) /**< routine's second argument */ +{ + /* 3. */ + ecma_property_descriptor_t prop_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, name_str_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (status)) + { + /* 4. */ + ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); + + ecma_free_property_descriptor (&prop_desc); + + return ecma_make_object_value (desc_obj_p); + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_object_object_get_own_property_descriptor */ + +/** + * The Object object's 'getOwnPropertyDescriptors' routine + * + * See also: + * ECMA-262 v11, 19.1.2.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_get_own_property_descriptors (ecma_object_t *obj_p) /**< routine's first argument */ +{ + /* 2 */ + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (prop_names_p == NULL) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *names_buffer_p = prop_names_p->buffer_p; + + /* 3 */ + ecma_object_t *object_prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + ecma_object_t *descriptors_p = ecma_create_object (object_prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + + /* 4 */ + for (uint32_t i = 0; i < prop_names_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (names_buffer_p[i]); + + /* 4.a */ + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_deref_object (descriptors_p); + ecma_collection_free (prop_names_p); + + return status; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (status)) + { + /* 4.b */ + ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); + /* 4.c */ + ecma_property_value_t *value_p = ecma_create_named_data_property (descriptors_p, + property_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + value_p->value = ecma_make_object_value (desc_obj_p); + + ecma_deref_object (desc_obj_p); + ecma_free_property_descriptor (&prop_desc); + } + } + + ecma_collection_free (prop_names_p); + + return ecma_make_object_value (descriptors_p); +} /* ecma_builtin_object_object_get_own_property_descriptors */ + +/** + * The Object object's 'defineProperties' routine + * + * See also: + * ECMA-262 v5, 15.2.3.7 + * ECMA-262 v11, 19.1.2.3.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + /* 2. */ + ecma_value_t props = ecma_op_to_object (arg2); + + if (ECMA_IS_VALUE_ERROR (props)) + { + return props; + } + + ecma_object_t *props_p = ecma_get_object_from_value (props); + + /* 3. */ + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (props_p, JERRY_PROPERTY_FILTER_ALL); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + +#if JERRY_BUILTIN_PROXY + if (prop_names_p == NULL) + { + ecma_deref_object (props_p); + return ret_value; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *buffer_p = prop_names_p->buffer_p; + + /* 4. */ + JMEM_DEFINE_LOCAL_ARRAY (property_descriptors, prop_names_p->item_count, ecma_property_descriptor_t); + uint32_t property_descriptor_number = 0; + ecma_collection_t *enum_prop_names = ecma_new_collection (); + + /* 5. */ + for (uint32_t i = 0; i < prop_names_p->item_count; i++) + { + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (buffer_p[i]); + + ecma_property_descriptor_t prop_desc; + ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (props_p, prop_name_p, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (get_desc)) + { + goto cleanup; + } + + if (ecma_is_value_true (get_desc)) + { + if (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) + { + ecma_value_t desc_obj = ecma_op_object_get (props_p, prop_name_p); + + if (ECMA_IS_VALUE_ERROR (desc_obj)) + { + ecma_free_property_descriptor (&prop_desc); + goto cleanup; + } + + ecma_value_t conv_result = + ecma_op_to_property_descriptor (desc_obj, &property_descriptors[property_descriptor_number]); + + property_descriptors[property_descriptor_number].flags |= JERRY_PROP_SHOULD_THROW; + + ecma_free_value (desc_obj); + + if (ECMA_IS_VALUE_ERROR (conv_result)) + { + ecma_free_property_descriptor (&prop_desc); + goto cleanup; + } + + property_descriptor_number++; + ecma_free_value (conv_result); + ecma_ref_ecma_string (prop_name_p); + ecma_collection_push_back (enum_prop_names, buffer_p[i]); + } + + ecma_free_property_descriptor (&prop_desc); + } + } + + /* 6. */ + for (uint32_t i = 0; i < enum_prop_names->item_count; i++) + { + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (enum_prop_names->buffer_p[i]); + + ecma_value_t define_own_prop_ret = + ecma_op_object_define_own_property (obj_p, prop_name_p, &property_descriptors[i]); + if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) + { + goto cleanup; + } + + ecma_free_value (define_own_prop_ret); + } + + ecma_ref_object (obj_p); + ret_value = ecma_make_object_value (obj_p); + +cleanup: + /* Clean up. */ + for (uint32_t index = 0; index < property_descriptor_number; index++) + { + ecma_free_property_descriptor (&property_descriptors[index]); + } + + ecma_collection_free (enum_prop_names); + + JMEM_FINALIZE_LOCAL_ARRAY (property_descriptors); + + ecma_collection_free (prop_names_p); + + ecma_deref_object (props_p); + + return ret_value; +} /* ecma_builtin_object_object_define_properties */ + +/** + * The Object object's 'create' routine + * + * See also: + * ECMA-262 v5, 15.2.3.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_create (ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + /* 1. */ + if (!ecma_is_value_object (arg1) && !ecma_is_value_null (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + ecma_object_t *obj_p = NULL; + + if (!ecma_is_value_null (arg1)) + { + obj_p = ecma_get_object_from_value (arg1); + } + /* 2-3. */ + ecma_object_t *result_obj_p = ecma_op_create_object_object_noarg_and_set_prototype (obj_p); + + /* 4. */ + if (!ecma_is_value_undefined (arg2)) + { + ecma_value_t obj = ecma_builtin_object_object_define_properties (result_obj_p, arg2); + + if (ECMA_IS_VALUE_ERROR (obj)) + { + ecma_deref_object (result_obj_p); + return obj; + } + + ecma_free_value (obj); + } + + /* 5. */ + return ecma_make_object_value (result_obj_p); +} /* ecma_builtin_object_object_create */ + +/** + * The Object object's 'defineProperty' routine + * + * See also: + * ECMA-262 v5, 15.2.3.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_define_property (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_string_t *name_str_p, /**< routine's second argument */ + ecma_value_t arg3) /**< routine's third argument */ +{ + ecma_property_descriptor_t prop_desc; + + ecma_value_t conv_result = ecma_op_to_property_descriptor (arg3, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (conv_result)) + { + return conv_result; + } + + prop_desc.flags |= JERRY_PROP_SHOULD_THROW; + + ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, name_str_p, &prop_desc); + + ecma_free_property_descriptor (&prop_desc); + ecma_free_value (conv_result); + + if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) + { + return define_own_prop_ret; + } + + if (ecma_is_value_false (define_own_prop_ret)) + { + return ecma_raise_type_error (ECMA_ERR_THE_REQUESTED_PROPERTY_UPDATE_CANNOT_BE_PERFORMED); + } + + JERRY_ASSERT (ecma_is_value_true (define_own_prop_ret)); + + ecma_ref_object (obj_p); + ecma_free_value (define_own_prop_ret); + + return ecma_make_object_value (obj_p); +} /* ecma_builtin_object_object_define_property */ + +/** + * The Object object's 'assign' routine + * + * See also: + * ECMA-262 v6, 19.1.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_assign (ecma_object_t *target_p, /**< target object */ + const ecma_value_t arguments_list_p[], /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 4-5. */ + for (uint32_t i = 0; i < arguments_list_len && ecma_is_value_empty (ret_value); i++) + { + ecma_value_t next_source = arguments_list_p[i]; + + /* 5.a */ + if (ecma_is_value_undefined (next_source) || ecma_is_value_null (next_source)) + { + continue; + } + + /* 5.b.i */ + ecma_value_t from_value = ecma_op_to_object (next_source); + /* null and undefied cases are handled above, so this must be a valid object */ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (from_value)); + + ecma_object_t *from_obj_p = ecma_get_object_from_value (from_value); + + /* 5.b.iii */ + ecma_collection_t *props_p = ecma_op_object_own_property_keys (from_obj_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (props_p == NULL) + { + ecma_deref_object (from_obj_p); + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *buffer_p = props_p->buffer_p; + + for (uint32_t j = 0; (j < props_p->item_count) && ecma_is_value_empty (ret_value); j++) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[j]); + + /* 5.c.i-ii */ + ecma_property_descriptor_t prop_desc; + ecma_value_t desc_status = ecma_op_object_get_own_property_descriptor (from_obj_p, property_name_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (desc_status)) + { + ret_value = desc_status; + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (desc_status)) + { + continue; + } + + /* 5.c.iii */ + if (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) + { + /* 5.c.iii.1 */ + ecma_value_t prop_value = ecma_op_object_get (from_obj_p, property_name_p); + + /* 5.c.iii.2 */ + if (ECMA_IS_VALUE_ERROR (prop_value)) + { + ret_value = prop_value; + } + else + { + /* 5.c.iii.3 */ + ecma_value_t status = ecma_op_object_put (target_p, property_name_p, prop_value, true); + + /* 5.c.iii.4 */ + if (ECMA_IS_VALUE_ERROR (status)) + { + ret_value = status; + } + } + + ecma_free_value (prop_value); + } + + ecma_free_property_descriptor (&prop_desc); + } + + ecma_deref_object (from_obj_p); + ecma_collection_free (props_p); + } + + /* 6. */ + if (ecma_is_value_empty (ret_value)) + { + ecma_ref_object (target_p); + return ecma_make_object_value (target_p); + } + + return ret_value; +} /* ecma_builtin_object_object_assign */ + +/** + * The Object object's 'is' routine + * + * See also: + * ECMA-262 v6, 19.1.2.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_is (ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + return ecma_op_same_value (arg1, arg2) ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE; +} /* ecma_builtin_object_object_is */ + +/** + * The Object object's 'fromEntries' routine + * + * See also: + * ECMA-262 v10, 19.1.2.7 + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_from_entries (ecma_value_t iterator) /**< object's iterator */ +{ + JERRY_ASSERT (ecma_op_require_object_coercible (iterator)); + /* 2 */ + ecma_object_t *object_prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + ecma_object_t *obj_p = ecma_create_object (object_prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + + /* 6.a */ + ecma_value_t next_method; + ecma_value_t result = ecma_op_get_iterator (iterator, ECMA_VALUE_SYNC_ITERATOR, &next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (obj_p); + return result; + } + + const ecma_value_t original_iterator = result; + + /* 6.b */ + while (true) + { + /* 6.a.i */ + result = ecma_op_iterator_step (original_iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_iterator; + } + + /* 6.a.ii */ + if (ecma_is_value_false (result)) + { + break; + } + + /* 6.a.iii */ + const ecma_value_t next = result; + result = ecma_op_iterator_value (next); + ecma_free_value (next); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_iterator; + } + + /* 6.a.iv */ + if (!ecma_is_value_object (result)) + { + ecma_free_value (result); + ecma_raise_type_error (ECMA_ERR_ITERATOR_VALUE_IS_NOT_AN_OBJECT); + result = ecma_op_iterator_close (original_iterator); + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result)); + goto cleanup_iterator; + } + + /* 6.a.v-vi */ + ecma_object_t *next_object_p = ecma_get_object_from_value (result); + + result = ecma_op_object_get_by_index (next_object_p, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (next_object_p); + ecma_op_iterator_close (original_iterator); + goto cleanup_iterator; + } + + const ecma_value_t key = result; + + result = ecma_op_object_get_by_index (next_object_p, 1); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (next_object_p); + ecma_free_value (key); + ecma_op_iterator_close (original_iterator); + goto cleanup_iterator; + } + + /* 6.a.vii */ + const ecma_value_t value = result; + ecma_string_t *property_key = ecma_op_to_property_key (key); + + if (property_key == NULL) + { + ecma_deref_object (next_object_p); + ecma_free_value (key); + ecma_op_iterator_close (original_iterator); + result = ECMA_VALUE_ERROR; + goto cleanup_iterator; + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, property_key); + + if (property_p == NULL) + { + ecma_property_value_t *prop; + prop = + ecma_create_named_data_property (obj_p, property_key, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + prop->value = ecma_copy_value_if_not_object (value); + } + else + { + ecma_named_data_property_assign_value (obj_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); + } + + ecma_deref_ecma_string (property_key); + ecma_free_value (key); + ecma_free_value (value); + ecma_deref_object (next_object_p); + } + + ecma_ref_object (obj_p); + result = ecma_make_object_value (obj_p); + +cleanup_iterator: + ecma_free_value (original_iterator); + ecma_free_value (next_method); + ecma_deref_object (obj_p); + + return result; +} /* ecma_builtin_object_from_entries */ + +/** + * GetOwnPropertyKeys abstract method + * + * See also: + * ECMA-262 v11, 19.1.2.11.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_op_object_get_own_property_keys (ecma_value_t this_arg, /**< this argument */ + uint16_t type) /**< routine type */ +{ + /* 1. */ + ecma_value_t object = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (object)) + { + return object; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + + /* 2. */ + jerry_property_filter_t filter = JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS; + + if (type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS) + { + filter = (jerry_property_filter_t) ((unsigned int) JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS | (unsigned int) JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES); + } + + ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, filter); + + if (props_p == NULL) + { + ecma_deref_object (obj_p); + return ECMA_VALUE_ERROR; + } + + /* 3. */ + ecma_collection_t *name_list_p = ecma_new_collection (); + + /* 4. */ + for (uint32_t i = 0; i < props_p->item_count; i++) + { + ecma_value_t prop_name = props_p->buffer_p[i]; + ecma_string_t *name_p = ecma_get_prop_name_from_value (prop_name); + + if ((ecma_prop_name_is_symbol (name_p) && type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS) + || (ecma_is_value_string (prop_name) && type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES)) + { + ecma_ref_ecma_string (name_p); + ecma_collection_push_back (name_list_p, prop_name); + } + } + + ecma_value_t result_array = ecma_op_new_array_object_from_collection (name_list_p, false); + + ecma_deref_object (obj_p); + ecma_collection_free (props_p); + + return result_array; +} /* ecma_op_object_get_own_property_keys */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (this_arg, arguments_number); + + ecma_value_t arg1 = arguments_list_p[0]; + ecma_value_t arg2 = arguments_list_p[1]; + + /* No specialization for the arguments */ + switch (builtin_routine_id) + { + case ECMA_OBJECT_ROUTINE_CREATE: + { + return ecma_builtin_object_object_create (arg1, arg2); + } + case ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF: + { + return ecma_builtin_object_object_set_prototype_of (arg1, arg2); + } + case ECMA_OBJECT_ROUTINE_IS: + { + return ecma_builtin_object_object_is (arg1, arg2); + } + default: + { + break; + } + } + + ecma_object_t *obj_p; + + if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES) + { + if (!ecma_is_value_object (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + obj_p = ecma_get_object_from_value (arg1); + + if (builtin_routine_id == ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY) + { + ecma_string_t *prop_name_p = ecma_op_to_property_key (arg2); + + if (prop_name_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_object_object_define_property (obj_p, prop_name_p, arguments_list_p[2]); + + ecma_deref_ecma_string (prop_name_p); + return result; + } + + JERRY_ASSERT (builtin_routine_id == ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES); + return ecma_builtin_object_object_define_properties (obj_p, arg2); + } + else if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_ENTRIES) + { + ecma_value_t object = ecma_op_to_object (arg1); + if (ECMA_IS_VALUE_ERROR (object)) + { + return object; + } + + obj_p = ecma_get_object_from_value (object); + + ecma_value_t result; + switch (builtin_routine_id) + { + case ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF: + { + result = ecma_builtin_object_object_get_prototype_of (obj_p); + break; + } + case ECMA_OBJECT_ROUTINE_ASSIGN: + { + result = ecma_builtin_object_object_assign (obj_p, arguments_list_p + 1, arguments_number - 1); + break; + } + case ECMA_OBJECT_ROUTINE_ENTRIES: + case ECMA_OBJECT_ROUTINE_VALUES: + case ECMA_OBJECT_ROUTINE_KEYS: + { + JERRY_ASSERT (builtin_routine_id - ECMA_OBJECT_ROUTINE_KEYS < ECMA_ENUMERABLE_PROPERTY__COUNT); + + const int option = builtin_routine_id - ECMA_OBJECT_ROUTINE_KEYS; + result = + ecma_builtin_object_object_keys_values_helper (obj_p, (ecma_enumerable_property_names_options_t) option); + break; + } + case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR: + { + ecma_string_t *prop_name_p = ecma_op_to_property_key (arg2); + + if (prop_name_p == NULL) + { + result = ECMA_VALUE_ERROR; + break; + } + + result = ecma_builtin_object_object_get_own_property_descriptor (obj_p, prop_name_p); + ecma_deref_ecma_string (prop_name_p); + break; + } + case ECMA_OBJECT_ROUTINE_HAS_OWN: + { + ecma_string_t *prop_name_p = ecma_op_to_property_key (arg2); + + if (prop_name_p == NULL) + { + result = ECMA_VALUE_ERROR; + break; + } + + result = ecma_op_object_has_own_property (obj_p, prop_name_p); + ecma_deref_ecma_string (prop_name_p); + break; + } + case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTORS: + { + result = ecma_builtin_object_object_get_own_property_descriptors (obj_p); + break; + } + case ECMA_OBJECT_ROUTINE_FROM_ENTRIES: + { + result = ecma_builtin_object_from_entries (arg1); + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + + ecma_deref_object (obj_p); + return result; + } + else if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS) + { + return ecma_op_object_get_own_property_keys (arg1, builtin_routine_id); + } + else if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_SEAL) + { + if (!ecma_is_value_object (arg1)) + { + return ecma_copy_value (arg1); + } + + obj_p = ecma_get_object_from_value (arg1); + switch (builtin_routine_id) + { + case ECMA_OBJECT_ROUTINE_SEAL: + { + return ecma_builtin_object_object_seal (obj_p); + } + case ECMA_OBJECT_ROUTINE_FREEZE: + { + return ecma_builtin_object_object_freeze (obj_p); + } + case ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS: + { + return ecma_builtin_object_object_prevent_extensions (obj_p); + } + default: + { + JERRY_UNREACHABLE (); + } + } + } + else + { + JERRY_ASSERT (builtin_routine_id <= ECMA_OBJECT_ROUTINE_IS_SEALED); + + if (!ecma_is_value_object (arg1)) + { + return ecma_make_boolean_value (builtin_routine_id != ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE); + } + + obj_p = ecma_get_object_from_value (arg1); + switch (builtin_routine_id) + { + case ECMA_OBJECT_ROUTINE_IS_SEALED: + case ECMA_OBJECT_ROUTINE_IS_FROZEN: + { + return ecma_builtin_object_test_integrity_level (obj_p, builtin_routine_id); + } + case ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE: + { + return ecma_builtin_object_object_is_extensible (obj_p); + } + default: + { + JERRY_UNREACHABLE (); + } + } + } +} /* ecma_builtin_object_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.h new file mode 100644 index 00000000..f31b2617 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ECMA_BUILTIN_OBJECT_H +#define ECMA_BUILTIN_OBJECT_H + +#include "ecma-globals.h" + +ecma_value_t ecma_builtin_object_object_get_prototype_of (ecma_object_t *obj_p); + +ecma_value_t ecma_builtin_object_object_set_prototype_of (ecma_value_t arg1, ecma_value_t arg2); + +ecma_value_t ecma_builtin_object_object_set_proto (ecma_value_t arg1, ecma_value_t arg2); + +ecma_value_t ecma_builtin_object_object_prevent_extensions (ecma_object_t *obj_p); + +ecma_value_t ecma_builtin_object_object_is_extensible (ecma_object_t *obj_p); + +ecma_value_t ecma_builtin_object_object_get_own_property_descriptor (ecma_object_t *obj_p, ecma_string_t *name_str_p); +ecma_value_t +ecma_builtin_object_object_define_property (ecma_object_t *obj_p, ecma_string_t *name_str_p, ecma_value_t arg3); + +#endif /* !ECMA_BUILTIN_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h new file mode 100644 index 00000000..ee02ad62 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h @@ -0,0 +1,59 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Object built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_OBJECT_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_GET_PROTOTYPE_OF_UL, ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SEAL, ECMA_OBJECT_ROUTINE_SEAL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FREEZE, ECMA_OBJECT_ROUTINE_FREEZE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL, ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_SEALED_UL, ECMA_OBJECT_ROUTINE_IS_SEALED, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_FROZEN_UL, ECMA_OBJECT_ROUTINE_IS_FROZEN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_EXTENSIBLE, ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_OBJECT_ROUTINE_ENTRIES, 1, 1) +ROUTINE (LIT_MAGIC_STRING_VALUES, ECMA_OBJECT_ROUTINE_VALUES, 1, 1) +ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_OBJECT_ROUTINE_KEYS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR, 2, 2) +ROUTINE (LIT_MAGIC_STRING_HAS_OWN_UL, ECMA_OBJECT_ROUTINE_HAS_OWN, 2, 2) +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTORS_UL, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTORS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_OBJECT_FROM_ENTRIES, ECMA_OBJECT_ROUTINE_FROM_ENTRIES, 1, 1) +ROUTINE (LIT_MAGIC_STRING_CREATE, ECMA_OBJECT_ROUTINE_CREATE, 2, 2) +ROUTINE (LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL, ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES, 2, 2) +ROUTINE (LIT_MAGIC_STRING_DEFINE_PROPERTY_UL, ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY, 3, 3) +ROUTINE (LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL, ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF, 2, 2) +ROUTINE (LIT_MAGIC_STRING_ASSIGN, ECMA_OBJECT_ROUTINE_ASSIGN, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_IS, ECMA_OBJECT_ROUTINE_IS, 2, 2) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.cpp new file mode 100644 index 00000000..b24f6d5b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.cpp @@ -0,0 +1,93 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" +#include "ecma-promise-object.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_PROMISE_PROTOTYPE_ROUTINE_START = 0, + ECMA_PROMISE_PROTOTYPE_ROUTINE_THEN, + ECMA_PROMISE_PROTOTYPE_ROUTINE_CATCH, + ECMA_PROMISE_PROTOTYPE_ROUTINE_FINALLY +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-promise-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID promise_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup promiseprototype ECMA Promise.prototype object built-in + * @{ + */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_promise_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + switch (builtin_routine_id) + { + case ECMA_PROMISE_PROTOTYPE_ROUTINE_THEN: + { + return ecma_promise_then (this_arg, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_PROMISE_PROTOTYPE_ROUTINE_CATCH: + { + ecma_value_t args[] = { ECMA_VALUE_UNDEFINED, arguments_list_p[0] }; + return ecma_op_invoke_by_magic_id (this_arg, LIT_MAGIC_STRING_THEN, args, 2); + } + case ECMA_PROMISE_PROTOTYPE_ROUTINE_FINALLY: + { + return ecma_promise_finally (this_arg, arguments_list_p[0]); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_promise_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.inc.h new file mode 100644 index 00000000..76ee6fda --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.inc.h @@ -0,0 +1,30 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_PROMISE, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 25.4.5.4 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_PROMISE_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ROUTINE (LIT_MAGIC_STRING_THEN, ECMA_PROMISE_PROTOTYPE_ROUTINE_THEN, 2, 2) +ROUTINE (LIT_MAGIC_STRING_CATCH, ECMA_PROMISE_PROTOTYPE_ROUTINE_CATCH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FINALLY, ECMA_PROMISE_PROTOTYPE_ROUTINE_FINALLY, 1, 1) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.cpp new file mode 100644 index 00000000..02f600c5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.cpp @@ -0,0 +1,527 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-handlers.h" +#include "ecma-builtin-helpers.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-iterator-object.h" +#include "ecma-number-object.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_PROMISE_ROUTINE_START = 0, + ECMA_PROMISE_ROUTINE_REJECT, + ECMA_PROMISE_ROUTINE_RESOLVE, + ECMA_PROMISE_ROUTINE_RACE, + ECMA_PROMISE_ROUTINE_ALL, + ECMA_PROMISE_ROUTINE_ALLSETTLED, + ECMA_PROMISE_ROUTINE_ANY, + ECMA_PROMISE_ROUTINE_SPECIES_GET +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-promise.inc.h" +#define BUILTIN_UNDERSCORED_ID promise +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup promise ECMA Promise object built-in + * @{ + */ + +/** + * Runtime Semantics: PerformPromiseRace. + * + * See also: + * ES2020 25.6.4.4.1 + * + * @return ecma value of the new promise. + * Returned value must be freed with ecma_free_value. + */ +static inline ecma_value_t +ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for race */ + ecma_value_t next_method, /**< next method */ + ecma_object_t *capability_obj_p, /**< PromiseCapability record */ + ecma_value_t ctor, /**< Constructor value */ + bool *done_p) /**< [out] iteratorRecord[[done]] */ +{ + JERRY_ASSERT (ecma_is_value_object (iterator)); + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + JERRY_ASSERT (ecma_is_constructor (ctor)); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + + ecma_value_t resolve = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (ctor), LIT_MAGIC_STRING_RESOLVE); + + if (ECMA_IS_VALUE_ERROR (resolve)) + { + return resolve; + } + + if (!ecma_op_is_callable (resolve)) + { + ecma_free_value (resolve); + return ecma_raise_type_error (ECMA_ERR_RESOLVE_METHOD_MUST_BE_CALLABLE); + } + + ecma_object_t *resolve_func_p = ecma_get_object_from_value (resolve); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + /* 5. */ + while (true) + { + /* a. */ + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + /* b, c. */ + if (ECMA_IS_VALUE_ERROR (next)) + { + goto done; + } + + /* d. */ + if (ecma_is_value_false (next)) + { + /* ii. */ + ret_value = ecma_copy_value (capability_p->header.u.cls.u3.promise); + goto done; + } + + /* e. */ + ecma_value_t next_val = ecma_op_iterator_value (next); + ecma_free_value (next); + + /* f, g. */ + if (ECMA_IS_VALUE_ERROR (next_val)) + { + goto done; + } + + /* h. */ + ecma_value_t next_promise = ecma_op_function_call (resolve_func_p, ctor, &next_val, 1); + ecma_free_value (next_val); + + if (ECMA_IS_VALUE_ERROR (next_promise)) + { + goto exit; + } + + /* i. */ + ecma_value_t args[2] = { capability_p->resolve, capability_p->reject }; + ecma_value_t result = ecma_op_invoke_by_magic_id (next_promise, LIT_MAGIC_STRING_THEN, args, 2); + ecma_free_value (next_promise); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto exit; + } + + ecma_free_value (result); + } + +done: + *done_p = true; +exit: + ecma_deref_object (resolve_func_p); + + return ret_value; +} /* ecma_builtin_promise_perform_race */ + +/** + * Runtime Semantics: Perform Promise all, allSettled or any. + * + * See also: + * ES2020 25.6.4.1.1 + * + * @return ecma value of the new promise. + * Returned value must be freed with ecma_free_value. + */ +static inline ecma_value_t +ecma_builtin_promise_perform (ecma_value_t iterator, /**< iteratorRecord */ + ecma_value_t next_method, /**< next method */ + ecma_object_t *capability_obj_p, /**< PromiseCapability record */ + ecma_value_t ctor, /**< the caller of Promise.all */ + uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + bool *done_p) /**< [out] iteratorRecord[[done]] */ +{ + /* 1. - 2. */ + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + JERRY_ASSERT (ecma_is_constructor (ctor)); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + + ecma_value_t resolve = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (ctor), LIT_MAGIC_STRING_RESOLVE); + + if (ECMA_IS_VALUE_ERROR (resolve)) + { + return resolve; + } + + if (!ecma_op_is_callable (resolve)) + { + ecma_free_value (resolve); + return ecma_raise_type_error (ECMA_ERR_RESOLVE_METHOD_MUST_BE_CALLABLE); + } + + ecma_object_t *resolve_func_p = ecma_get_object_from_value (resolve); + + /* 3. */ + ecma_object_t *values_array_obj_p = ecma_op_new_array_object (0); + ecma_value_t values_array = ecma_make_object_value (values_array_obj_p); + /* 4. */ + ecma_value_t remaining = ecma_op_create_number_object (ecma_make_integer_value (1)); + /* 5. */ + uint32_t idx = 0; + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + /* 6. */ + while (true) + { + /* a. */ + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + /* b. - c. */ + if (ECMA_IS_VALUE_ERROR (next)) + { + goto done; + } + + /* d. */ + if (ecma_is_value_false (next)) + { + /* ii. - iii. */ + if (ecma_promise_remaining_inc_or_dec (remaining, false) == 0) + { + if (builtin_routine_id == ECMA_PROMISE_ROUTINE_ANY) + { + ret_value = ecma_raise_aggregate_error (values_array, ECMA_VALUE_UNDEFINED); + goto done; + } + + /* 2. */ + ecma_value_t resolve_result = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), + ECMA_VALUE_UNDEFINED, + &values_array, + 1); + /* 3. */ + if (ECMA_IS_VALUE_ERROR (resolve_result)) + { + goto done; + } + + ecma_free_value (resolve_result); + } + + /* iv. */ + ret_value = ecma_copy_value (capability_p->header.u.cls.u3.promise); + goto done; + } + + /* e. */ + ecma_value_t next_value = ecma_op_iterator_value (next); + ecma_free_value (next); + + /* f. - g. */ + if (ECMA_IS_VALUE_ERROR (next_value)) + { + goto done; + } + + /* h. */ + ecma_builtin_helper_def_prop_by_index (values_array_obj_p, + idx, + ECMA_VALUE_UNDEFINED, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + /* i. */ + ecma_value_t next_promise = ecma_op_function_call (resolve_func_p, ctor, &next_value, 1); + ecma_free_value (next_value); + + /* j. */ + if (ECMA_IS_VALUE_ERROR (next_promise)) + { + goto exit; + } + + if (JERRY_UNLIKELY (idx == UINT32_MAX - 1)) + { + ecma_raise_range_error (ECMA_ERR_PROMISE_ALL_REMAINING_ELEMENTS_LIMIT_REACHED); + goto exit; + } + + idx++; + ecma_value_t args[2]; + ecma_object_t *executor_func_p = NULL; + + if (builtin_routine_id != ECMA_PROMISE_ROUTINE_ANY) + { + /* k. */ + executor_func_p = + ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER, sizeof (ecma_promise_all_executor_t)); + + ecma_promise_all_executor_t *executor_p = (ecma_promise_all_executor_t *) executor_func_p; + + /* m. + t. */ + executor_p->index = idx; + + /* n. */ + executor_p->values = values_array; + + /* o. */ + executor_p->capability = ecma_make_object_value (capability_obj_p); + + /* p. */ + executor_p->remaining_elements = remaining; + + uint8_t executor_type = ECMA_PROMISE_ALL_RESOLVE << ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT; + + if (builtin_routine_id == ECMA_PROMISE_ROUTINE_ALLSETTLED) + { + executor_type = ECMA_PROMISE_ALLSETTLED_RESOLVE << ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT; + } + + executor_p->header.u.built_in.u2.routine_flags |= executor_type; + + args[0] = ecma_make_object_value (executor_func_p); + } + else + { + args[0] = capability_p->resolve; + } + + /* q. */ + ecma_promise_remaining_inc_or_dec (remaining, true); + ecma_value_t result; + + if (builtin_routine_id != ECMA_PROMISE_ROUTINE_ALL) + { + uint8_t executor_type = ECMA_PROMISE_ALLSETTLED_REJECT << ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT; + + if (builtin_routine_id == ECMA_PROMISE_ROUTINE_ANY) + { + executor_type = ECMA_PROMISE_ANY_REJECT << ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT; + } + + ecma_object_t *reject_func_p = + ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER, sizeof (ecma_promise_all_executor_t)); + + ecma_promise_all_executor_t *reject_p = (ecma_promise_all_executor_t *) reject_func_p; + reject_p->index = idx; + reject_p->values = values_array; + reject_p->capability = ecma_make_object_value (capability_obj_p); + reject_p->remaining_elements = remaining; + reject_p->header.u.built_in.u2.routine_flags |= executor_type; + args[1] = ecma_make_object_value (reject_func_p); + result = ecma_op_invoke_by_magic_id (next_promise, LIT_MAGIC_STRING_THEN, args, 2); + ecma_deref_object (reject_func_p); + } + else + { + args[1] = capability_p->reject; + result = ecma_op_invoke_by_magic_id (next_promise, LIT_MAGIC_STRING_THEN, args, 2); + } + + ecma_free_value (next_promise); + + if (builtin_routine_id != ECMA_PROMISE_ROUTINE_ANY) + { + ecma_deref_object (executor_func_p); + } + + /* s. */ + if (ECMA_IS_VALUE_ERROR (result)) + { + goto exit; + } + + ecma_free_value (result); + } + +done: + *done_p = true; +exit: + ecma_free_value (remaining); + ecma_deref_object (values_array_obj_p); + ecma_deref_object (resolve_func_p); + + return ret_value; +} /* ecma_builtin_promise_perform */ + +/** + * The common function for Promise.race, Promise.all, Promise.any and Promise.allSettled. + * + * @return ecma value of the new promise. + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_promise_helper (ecma_value_t this_arg, /**< 'this' argument */ + ecma_value_t iterable, /**< the items to be resolved */ + uint8_t builtin_routine_id) /**< built-in wide routine identifier */ +{ + ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg, ECMA_VALUE_UNDEFINED); + + if (JERRY_UNLIKELY (capability_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, &next_method); + ecma_value_t ret = ECMA_VALUE_ERROR; + + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&iterator, capability_obj_p))) + { + ecma_free_value (next_method); + ecma_deref_object (capability_obj_p); + return iterator; + } + + bool is_done = false; + + if (builtin_routine_id == ECMA_PROMISE_ROUTINE_RACE) + { + ret = ecma_builtin_promise_perform_race (iterator, next_method, capability_obj_p, this_arg, &is_done); + } + else + { + ret = + ecma_builtin_promise_perform (iterator, next_method, capability_obj_p, this_arg, builtin_routine_id, &is_done); + } + + if (ECMA_IS_VALUE_ERROR (ret)) + { + if (!is_done) + { + ret = ecma_op_iterator_close (iterator); + } + + ecma_op_if_abrupt_reject_promise (&ret, capability_obj_p); + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + ecma_deref_object (capability_obj_p); + + return ret; +} /* ecma_builtin_promise_helper */ + +/** + * Handle calling [[Call]] of built-in Promise object. + * + * ES2015 25.4.3 Promise is not intended to be called + * as a function and will throw an exception when called + * in that manner. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_promise_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_PROMISE_REQUIRES_NEW); +} /* ecma_builtin_promise_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Promise object. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_promise_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len == 0 || !ecma_op_is_callable (arguments_list_p[0])) + { + return ecma_raise_type_error (ECMA_ERR_FIRST_PARAMETER_MUST_BE_CALLABLE); + } + + return ecma_op_create_promise_object (arguments_list_p[0], + ECMA_VALUE_UNDEFINED, + JERRY_CONTEXT (current_new_target_p)); +} /* ecma_builtin_promise_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_promise_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + switch (builtin_routine_id) + { + case ECMA_PROMISE_ROUTINE_REJECT: + case ECMA_PROMISE_ROUTINE_RESOLVE: + { + bool is_resolve = (builtin_routine_id == ECMA_PROMISE_ROUTINE_RESOLVE); + return ecma_promise_reject_or_resolve (this_arg, arguments_list_p[0], is_resolve); + } + case ECMA_PROMISE_ROUTINE_RACE: + case ECMA_PROMISE_ROUTINE_ALL: + case ECMA_PROMISE_ROUTINE_ALLSETTLED: + case ECMA_PROMISE_ROUTINE_ANY: + { + return ecma_builtin_promise_helper (this_arg, arguments_list_p[0], builtin_routine_id); + } + case ECMA_PROMISE_ROUTINE_SPECIES_GET: + { + return ecma_copy_value (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_promise_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h new file mode 100644 index 00000000..6c697539 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h @@ -0,0 +1,46 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Promose built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_PROMISE_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_PROMISE_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_REJECT, ECMA_PROMISE_ROUTINE_REJECT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_RESOLVE, ECMA_PROMISE_ROUTINE_RESOLVE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_RACE, ECMA_PROMISE_ROUTINE_RACE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ALL, ECMA_PROMISE_ROUTINE_ALL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ALLSETTLED, ECMA_PROMISE_ROUTINE_ALLSETTLED, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ANY, ECMA_PROMISE_ROUTINE_ANY, 1, 1) + +/* ES2015 25.4.4.6 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ECMA_PROMISE_ROUTINE_SPECIES_GET, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.cpp new file mode 100644 index 00000000..2a2097d3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.cpp @@ -0,0 +1,160 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-proxy-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_PROXY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_PROXY_OBJECT_ROUTINE_START = 0, + ECMA_BUILTIN_PROXY_OBJECT_REVOCABLE, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-proxy.inc.h" +#define BUILTIN_UNDERSCORED_ID proxy +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup proxy ECMA Proxy object built-in + * @{ + */ + +/** + * The Proxy object's 'revocable' routine + * + * See also: + * ES2015 26.2.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_proxy_object_revocable (ecma_value_t target, /**< target argument */ + ecma_value_t handler) /**< handler argument */ +{ + ecma_object_t *rev_proxy_p = ecma_proxy_create_revocable (target, handler); + + if (JERRY_UNLIKELY (rev_proxy_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + return ecma_make_object_value (rev_proxy_p); +} /* ecma_builtin_proxy_object_revocable */ + +/** + * Handle calling [[Call]] of built-in Proxy object + * + * See also: + * ES2015 26.2.2 + * + * @return raised error + */ +ecma_value_t +ecma_builtin_proxy_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + /* 1. */ + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_PROXY_REQUIRES_NEW); +} /* ecma_builtin_proxy_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in proxy object + * + * See also: + * ES2015 26.2.2 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * new proxy object - otherwise + */ +ecma_value_t +ecma_builtin_proxy_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + /* 2. */ + ecma_object_t *proxy_p = ecma_proxy_create (arguments_list_len > 0 ? arguments_list_p[0] : ECMA_VALUE_UNDEFINED, + arguments_list_len > 1 ? arguments_list_p[1] : ECMA_VALUE_UNDEFINED, + 0); + + if (JERRY_UNLIKELY (proxy_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + return ecma_make_object_value (proxy_p); +} /* ecma_builtin_proxy_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_proxy_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (this_arg, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_PROXY_OBJECT_REVOCABLE: + { + return ecma_builtin_proxy_object_revocable (arguments_list_p[0], arguments_list_p[1]); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_proxy_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_PROXY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h new file mode 100644 index 00000000..32670616 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Proxy object built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_PROXY + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 2, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_PROXY_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ + +ROUTINE (LIT_MAGIC_STRING_REVOCABLE, ECMA_BUILTIN_PROXY_OBJECT_REVOCABLE, 2, 2) + +#endif /* JERRY_BUILTIN_PROXY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.cpp new file mode 100644 index 00000000..f72ac2c2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-rangeerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID range_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.inc.h new file mode 100644 index 00000000..1307e4a0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * RangeError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_RANGE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_RANGE_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.cpp new file mode 100644 index 00000000..c17a2369 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-rangeerror.inc.h" +#define BUILTIN_UNDERSCORED_ID range_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup rangeerror ECMA RangeError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in RangeError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_range_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_RANGE, arguments_list_p, arguments_list_len); +} /* ecma_builtin_range_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in RangeError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_range_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_range_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_range_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.inc.h new file mode 100644 index 00000000..6891fa5b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * RangeError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_RANGE_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.cpp new file mode 100644 index 00000000..5212d6bf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-referenceerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID reference_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.inc.h new file mode 100644 index 00000000..caa9e0e3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ReferenceError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_REFERENCE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_REFERENCE_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.cpp new file mode 100644 index 00000000..2a3f2da5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-referenceerror.inc.h" +#define BUILTIN_UNDERSCORED_ID reference_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup referenceerror ECMA ReferenceError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in ReferenceError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_reference_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_REFERENCE, arguments_list_p, arguments_list_len); +} /* ecma_builtin_reference_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in ReferenceError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_reference_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_reference_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_reference_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h new file mode 100644 index 00000000..b28ada19 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ReferenceError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_REFERENCE_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.cpp new file mode 100644 index 00000000..056a6b5f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.cpp @@ -0,0 +1,344 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-array-object.h" +#include "ecma-builtin-function-prototype.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtin-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-iterator-object.h" +#include "ecma-proxy-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_REFLECT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_REFLECT_OBJECT_ROUTINE_START = 0, + ECMA_REFLECT_OBJECT_GET, /* ECMA-262 v6, 26.1.6 */ + ECMA_REFLECT_OBJECT_SET, /* ECMA-262 v6, 26.1.13 */ + ECMA_REFLECT_OBJECT_HAS, /* ECMA-262 v6, 26.1.9 */ + ECMA_REFLECT_OBJECT_DELETE_PROPERTY, /* ECMA-262 v6, 26.1.4 */ + ECMA_REFLECT_OBJECT_CONSTRUCT, /* ECMA-262, 26.1.2 */ + ECMA_REFLECT_OBJECT_OWN_KEYS, /* ECMA-262 v6, 26.1.11 */ + ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF, /* ECMA-262 v6, 26.1.8 */ + ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF, /* ECMA-262 v6, 26.1.14 */ + ECMA_REFLECT_OBJECT_APPLY, /* ECMA-262 v6, 26.1.1 */ + ECMA_REFLECT_OBJECT_DEFINE_PROPERTY, /* ECMA-262 v6, 26.1.3 */ + ECMA_REFLECT_OBJECT_GET_OWN_PROPERTY_DESCRIPTOR, /* ECMA-262 v6, 26.1.7 */ + ECMA_REFLECT_OBJECT_IS_EXTENSIBLE, /* ECMA-262 v6, 26.1.10 */ + ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS, /* ECMA-262 v6, 26.1.12 */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-reflect.inc.h" +#define BUILTIN_UNDERSCORED_ID reflect +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup object ECMA Reflect object built-in + * @{ + */ + +/** + * Dispatcher for the built-in's routines. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (this_arg); + + if (builtin_routine_id < ECMA_REFLECT_OBJECT_CONSTRUCT) + { + /* 1. */ + if (arguments_number == 0 || !ecma_is_value_object (arguments_list[0])) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + /* 2. */ + ecma_string_t *name_str_p = ecma_op_to_property_key (arguments_list[1]); + + /* 3. */ + if (name_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value; + ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]); + switch (builtin_routine_id) + { + case ECMA_REFLECT_OBJECT_GET: + { + ecma_value_t receiver = arguments_list[0]; + + /* 4. */ + if (arguments_number > 2) + { + receiver = arguments_list[2]; + } + + ret_value = ecma_op_object_get_with_receiver (target_p, name_str_p, receiver); + break; + } + + case ECMA_REFLECT_OBJECT_HAS: + { + ret_value = ecma_op_object_has_property (target_p, name_str_p); + break; + } + + case ECMA_REFLECT_OBJECT_DELETE_PROPERTY: + { + ret_value = ecma_op_object_delete (target_p, name_str_p, false); + break; + } + + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_REFLECT_OBJECT_SET); + + ecma_value_t receiver = arguments_list[0]; + + if (arguments_number > 3) + { + receiver = arguments_list[3]; + } + + ret_value = ecma_op_object_put_with_receiver (target_p, name_str_p, arguments_list[2], receiver, false); + break; + } + } + + ecma_deref_ecma_string (name_str_p); + return ret_value; + } + + if (builtin_routine_id == ECMA_REFLECT_OBJECT_OWN_KEYS) + { + /* 1. */ + if (arguments_number == 0 || !ecma_is_value_object (arguments_list[0])) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]); + + /* 2. */ + ecma_collection_t *prop_names = ecma_op_object_own_property_keys (target_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (prop_names == NULL) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 3. */ + return ecma_op_new_array_object_from_collection (prop_names, false); + } + + if (builtin_routine_id == ECMA_REFLECT_OBJECT_CONSTRUCT) + { + /* 1. */ + if (arguments_number < 1 || !ecma_is_constructor (arguments_list[0])) + { + return ecma_raise_type_error (ECMA_ERR_TARGET_IS_NOT_A_CONSTRUCTOR); + } + + ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]); + + /* 2. */ + ecma_object_t *new_target_p = target_p; + + if (arguments_number > 2) + { + /* 3. */ + if (!ecma_is_constructor (arguments_list[2])) + { + return ecma_raise_type_error (ECMA_ERR_TARGET_IS_NOT_A_CONSTRUCTOR); + } + + new_target_p = ecma_get_object_from_value (arguments_list[2]); + } + + /* 4. */ + if (arguments_number < 2) + { + return ecma_raise_type_error (ECMA_ERR_REFLECT_EXPECTS_AN_OBJECT_AS_SECOND_ARGUMENT); + } + + ecma_collection_t *coll_p = ecma_op_create_list_from_array_like (arguments_list[1], false); + + if (coll_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value = ecma_op_function_construct (target_p, new_target_p, coll_p->buffer_p, coll_p->item_count); + + ecma_collection_free (coll_p); + return ret_value; + } + + if (!ecma_is_value_object (arguments_list[0])) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + switch (builtin_routine_id) + { + case ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF: + { + return ecma_builtin_object_object_get_prototype_of (ecma_get_object_from_value (arguments_list[0])); + } + case ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF: + { + if (!ecma_is_value_object (arguments_list[1]) && !ecma_is_value_null (arguments_list[1])) + { + return ecma_raise_type_error (ECMA_ERR_PROTOTYPE_IS_NEITHER_OBJECT_NOR_NULL); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); + ecma_value_t status; + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + status = ecma_proxy_object_set_prototype_of (obj_p, arguments_list[1]); + } + else +#endif /* JERRY_BUILTIN_PROXY */ + { + status = ecma_op_ordinary_object_set_prototype_of (obj_p, arguments_list[1]); + } + + return status; + } + case ECMA_REFLECT_OBJECT_APPLY: + { + if (!ecma_op_is_callable (arguments_list[0])) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_FUNCTION); + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (arguments_list[0]); + return ecma_builtin_function_prototype_object_apply (func_obj_p, arguments_list[1], arguments_list[2]); + } + case ECMA_REFLECT_OBJECT_DEFINE_PROPERTY: + { + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); + ecma_string_t *name_str_p = ecma_op_to_property_key (arguments_list[1]); + + if (name_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_property_descriptor_t prop_desc; + ecma_value_t conv_result = ecma_op_to_property_descriptor (arguments_list[2], &prop_desc); + + if (ECMA_IS_VALUE_ERROR (conv_result)) + { + ecma_deref_ecma_string (name_str_p); + return conv_result; + } + + ecma_value_t result = ecma_op_object_define_own_property (obj_p, name_str_p, &prop_desc); + + ecma_deref_ecma_string (name_str_p); + ecma_free_property_descriptor (&prop_desc); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + bool boolean_result = ecma_op_to_boolean (result); + + return ecma_make_boolean_value (boolean_result); + } + case ECMA_REFLECT_OBJECT_GET_OWN_PROPERTY_DESCRIPTOR: + { + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); + ecma_string_t *name_str_p = ecma_op_to_property_key (arguments_list[1]); + + if (name_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_val = ecma_builtin_object_object_get_own_property_descriptor (obj_p, name_str_p); + ecma_deref_ecma_string (name_str_p); + return ret_val; + } + case ECMA_REFLECT_OBJECT_IS_EXTENSIBLE: + { + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); + return ecma_builtin_object_object_is_extensible (obj_p); + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS); + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_prevent_extensions (obj_p); + } +#endif /* !JERRY_BUILTIN_PROXY */ + + ecma_op_ordinary_object_prevent_extensions (obj_p); + + return ECMA_VALUE_TRUE; + } + } +} /* ecma_builtin_reflect_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REFLECT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.inc.h new file mode 100644 index 00000000..4f4c824a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_REFLECT + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_APPLY, ECMA_REFLECT_OBJECT_APPLY, 3, 3) +ROUTINE (LIT_MAGIC_STRING_DEFINE_PROPERTY_UL, ECMA_REFLECT_OBJECT_DEFINE_PROPERTY, 3, 3) +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL, ECMA_REFLECT_OBJECT_GET_OWN_PROPERTY_DESCRIPTOR, 2, 2) +ROUTINE (LIT_MAGIC_STRING_GET, ECMA_REFLECT_OBJECT_GET, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_SET, ECMA_REFLECT_OBJECT_SET, NON_FIXED, 3) +ROUTINE (LIT_MAGIC_STRING_HAS, ECMA_REFLECT_OBJECT_HAS, 2, 2) +ROUTINE (LIT_MAGIC_STRING_DELETE_PROPERTY_UL, ECMA_REFLECT_OBJECT_DELETE_PROPERTY, 2, 2) +ROUTINE (LIT_MAGIC_STRING_OWN_KEYS_UL, ECMA_REFLECT_OBJECT_OWN_KEYS, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_CONSTRUCT, ECMA_REFLECT_OBJECT_CONSTRUCT, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_GET_PROTOTYPE_OF_UL, ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_EXTENSIBLE, ECMA_REFLECT_OBJECT_IS_EXTENSIBLE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL, ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL, ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF, 2, 2) + +#endif /* JERRY_BUILTIN_REFLECT */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp new file mode 100644 index 00000000..94c0384d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp @@ -0,0 +1,659 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-regexp-object.h" + +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_REGEXP +#include "ecma-regexp-object.h" + +#include "re-compiler.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-regexp-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID regexp_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup regexpprototype ECMA RegExp.prototype object built-in + * @{ + */ + +/** + * Helper function to retrieve the flags associated with a RegExp object + * + * @return ECMA_VALUE_{TRUE,FALSE} depends on whether the given flag is present. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_flags_helper (ecma_extended_object_t *re_obj_p, /**< this object */ + uint16_t builtin_routine_id) /**< id of the flag */ +{ + re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, re_obj_p->u.cls.u3.value); + + uint16_t flags = bc_p->header.status_flags; + + static const uint8_t re_flags[] = { + RE_FLAG_GLOBAL, RE_FLAG_IGNORE_CASE, RE_FLAG_MULTILINE, RE_FLAG_STICKY, RE_FLAG_UNICODE, RE_FLAG_DOTALL, + }; + + uint16_t offset = (uint16_t) (builtin_routine_id - ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_GLOBAL); + return ecma_make_boolean_value ((flags & re_flags[offset]) != 0); +} /* ecma_builtin_regexp_prototype_flags_helper */ + +/** + * The RegExp.prototype object's 'flags' accessor property + * + * See also: + * ECMA-262 v6, 21.2.5.3 + * + * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object + * string value - otherwise + * + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_get_flags (ecma_object_t *object_p) /**< this object */ +{ + static const lit_magic_string_id_t flag_lit_ids[] = { LIT_MAGIC_STRING_GLOBAL, LIT_MAGIC_STRING_IGNORECASE_UL, + LIT_MAGIC_STRING_MULTILINE, LIT_MAGIC_STRING_DOTALL, + LIT_MAGIC_STRING_UNICODE, LIT_MAGIC_STRING_STICKY }; + + static const lit_utf8_byte_t flag_chars[] = { LIT_CHAR_LOWERCASE_G, LIT_CHAR_LOWERCASE_I, LIT_CHAR_LOWERCASE_M, + LIT_CHAR_LOWERCASE_S, LIT_CHAR_LOWERCASE_U, LIT_CHAR_LOWERCASE_Y }; + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + for (uint32_t i = 0; i < sizeof (flag_lit_ids) / sizeof (lit_magic_string_id_t); i++) + { + ecma_value_t result = ecma_op_object_get_by_magic_id (object_p, flag_lit_ids[i]); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_stringbuilder_destroy (&builder); + return result; + } + + if (ecma_op_to_boolean (result)) + { + ecma_stringbuilder_append_byte (&builder, flag_chars[i]); + } + + ecma_free_value (result); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_regexp_prototype_get_flags */ + +/** + * The EscapeRegExpPattern method. + * + * See also: + * ECMA-262 v6, 21.2.3.2.4 + * + * @return ecma_value_t + */ +static ecma_value_t +ecma_op_escape_regexp_pattern (ecma_string_t *pattern_str_p) /**< RegExp pattern */ +{ + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + ECMA_STRING_TO_UTF8_STRING (pattern_str_p, pattern_start_p, pattern_start_size); + + const lit_utf8_byte_t *pattern_str_curr_p = pattern_start_p; + const lit_utf8_byte_t *pattern_str_end_p = pattern_start_p + pattern_start_size; + + while (pattern_str_curr_p < pattern_str_end_p) + { + ecma_char_t c = lit_cesu8_read_next (&pattern_str_curr_p); + + switch (c) + { + case LIT_CHAR_SLASH: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\/", 2); + break; + } + case LIT_CHAR_LF: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\n", 2); + break; + } + case LIT_CHAR_CR: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\r", 2); + break; + } + case LIT_CHAR_LS: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\u2028", 6); + break; + } + case LIT_CHAR_PS: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\u2029", 6); + break; + } + case LIT_CHAR_BACKSLASH: + { + JERRY_ASSERT (pattern_str_curr_p < pattern_str_end_p); + ecma_stringbuilder_append_char (&builder, LIT_CHAR_BACKSLASH); + ecma_stringbuilder_append_char (&builder, lit_cesu8_read_next (&pattern_str_curr_p)); + break; + } + default: + { + ecma_stringbuilder_append_char (&builder, c); + break; + } + } + } + + ECMA_FINALIZE_UTF8_STRING (pattern_start_p, pattern_start_size); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_op_escape_regexp_pattern */ + +/** + * The RegExp.prototype object's 'source' accessor property + * + * See also: + * ECMA-262 v6, 21.2.5.10 + * + * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object + * string value - otherwise + * + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_get_source (ecma_extended_object_t *re_obj_p) /**< this argument */ +{ + re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, re_obj_p->u.cls.u3.value); + + return ecma_op_escape_regexp_pattern (ecma_get_string_from_value (bc_p->source)); +} /* ecma_builtin_regexp_prototype_get_source */ + +#if JERRY_BUILTIN_ANNEXB +/** + * The RegExp.prototype object's 'compile' routine + * + * See also: + * ECMA-262 v11, B.2.5.1 + * + * @return undefined - if compiled successfully + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this */ + ecma_value_t pattern_arg, /**< pattern or RegExp object */ + ecma_value_t flags_arg) /**< flags */ +{ + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); + ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) this_obj_p; + re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, re_obj_p->u.cls.u3.value); + + ecma_value_t ret_value; + + if (ecma_object_is_regexp_object (pattern_arg)) + { + if (!ecma_is_value_undefined (flags_arg)) + { + return ecma_raise_type_error (ECMA_ERR_INVALID_ARGUMENT); + } + + ecma_extended_object_t *pattern_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (pattern_arg); + re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, pattern_obj_p->u.cls.u3.value); + + ret_value = ecma_op_create_regexp_from_bytecode (this_obj_p, bc_p); + } + else + { + ret_value = ecma_op_create_regexp_from_pattern (this_obj_p, pattern_arg, flags_arg); + } + + if (!ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_value_t status = ecma_builtin_helper_def_prop (this_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + ECMA_PROPERTY_FLAG_WRITABLE | JERRY_PROP_SHOULD_THROW); + + ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + ecma_ref_object (this_obj_p); + } + + return ret_value; +} /* ecma_builtin_regexp_prototype_compile */ + +#endif /* JERRY_BUILTIN_ANNEXB */ + +/** + * The RegExp.prototype object's 'exec' routine + * + * See also: + * ECMA-262 v5, 15.10.6.2 + * + * @return array object containing the results - if the matched + * null - otherwise + * + * May raise error, so returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_exec (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg) /**< routine's argument */ +{ + ecma_value_t obj_this = ecma_op_to_object (this_arg); + if (ECMA_IS_VALUE_ERROR (obj_this)) + { + return obj_this; + } + + ecma_string_t *input_str_p = ecma_op_to_string (arg); + if (JERRY_UNLIKELY (input_str_p == NULL)) + { + ecma_free_value (obj_this); + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value = ecma_regexp_exec_helper (ecma_get_object_from_value (obj_this), input_str_p); + + ecma_free_value (obj_this); + ecma_deref_ecma_string (input_str_p); + + return ret_value; +} /* ecma_builtin_regexp_prototype_exec */ + +/** + * The RegExp.prototype object's 'test' routine + * + * See also: + * ECMA-262 v5, 15.10.6.3 + * ECMA-262 v6, 21.2.5.13 + * + * @return true - if match is not null + * false - otherwise + * + * May raise error, so returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_test (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg) /**< routine's argument */ +{ + ecma_string_t *arg_str_p = ecma_op_to_string (arg); + + if (JERRY_UNLIKELY (arg_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_op_regexp_exec (this_arg, arg_str_p); + + ecma_deref_ecma_string (arg_str_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_value_t ret_value = ecma_make_boolean_value (!ecma_is_value_null (result)); + ecma_free_value (result); + + return ret_value; +} /* ecma_builtin_regexp_prototype_test */ + +/** + * The RegExp.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v5, 15.10.6.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_to_string (ecma_object_t *object_p) /**< this object */ +{ + ecma_value_t result = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_SOURCE); + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_string_t *source_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (source_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + result = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_FLAGS); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_ecma_string (source_p); + return result; + } + + ecma_string_t *flags_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (flags_p == NULL) + { + ecma_deref_ecma_string (source_p); + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_SLASH); + ecma_stringbuilder_append (&builder, source_p); + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_SLASH); + ecma_stringbuilder_append (&builder, flags_p); + + ecma_deref_ecma_string (source_p); + ecma_deref_ecma_string (flags_p); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_regexp_prototype_to_string */ + +/** + * The RegExp.prototype object's 'matchAll' routine + * + * See also: + * ECMA-262 v11, 21.2.5.8 + * + * @return ecma_value_t + */ +static ecma_value_t +ecma_builtin_regexp_prototype_match_all (ecma_object_t *regexp_obj_p, /**< this argument */ + ecma_value_t string_arg) /**< source string */ +{ + /* 3. */ + ecma_string_t *str_p = ecma_op_to_string (string_arg); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 4. */ + ecma_value_t constructor = ecma_op_species_constructor (regexp_obj_p, ECMA_BUILTIN_ID_REGEXP); + + if (ECMA_IS_VALUE_ERROR (constructor)) + { + ecma_deref_ecma_string (str_p); + return constructor; + } + + /* 5. */ + ecma_value_t get_flag = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_FLAGS); + + if (ECMA_IS_VALUE_ERROR (get_flag)) + { + ecma_deref_ecma_string (str_p); + ecma_free_value (constructor); + return get_flag; + } + + ecma_string_t *flags = ecma_op_to_string (get_flag); + + ecma_free_value (get_flag); + + if (JERRY_UNLIKELY (flags == NULL)) + { + ecma_deref_ecma_string (str_p); + ecma_free_value (constructor); + return ECMA_VALUE_ERROR; + } + + /* 6. */ + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); + ecma_value_t flags_value = ecma_make_string_value (flags); + ecma_value_t match_args[] = { ecma_make_object_value (regexp_obj_p), flags_value }; + ecma_value_t matcher = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, match_args, 2); + + ecma_deref_object (constructor_obj_p); + + if (ECMA_IS_VALUE_ERROR (matcher)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_ecma_string (flags); + return matcher; + } + + /* 7. */ + ecma_value_t get_last_index = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); + + if (ECMA_IS_VALUE_ERROR (get_last_index)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_ecma_string (flags); + ecma_free_value (matcher); + return get_last_index; + } + + ecma_length_t last_index; + ecma_value_t to_len = ecma_op_to_length (get_last_index, &last_index); + + ecma_free_value (get_last_index); + + if (ECMA_IS_VALUE_ERROR (to_len)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_ecma_string (flags); + ecma_free_value (matcher); + return to_len; + } + + /* 8. */ + ecma_object_t *matcher_obj_p = ecma_get_object_from_value (matcher); + ecma_value_t last_index_value = ecma_make_length_value (last_index); + ecma_value_t set = + ecma_op_object_put (matcher_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), last_index_value, true); + + ecma_free_value (last_index_value); + + if (ECMA_IS_VALUE_ERROR (set)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_ecma_string (flags); + ecma_deref_object (matcher_obj_p); + } + + uint16_t parsed_flag; + ecma_value_t flag_parse = ecma_regexp_parse_flags (flags, &parsed_flag); + + ecma_deref_ecma_string (flags); + + if (ECMA_IS_VALUE_ERROR (flag_parse)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_object (matcher_obj_p); + return flag_parse; + } + + /* 13. */ + ecma_object_t *result_obj; + ecma_object_t *proto_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_STRING_ITERATOR_PROTOTYPE); + result_obj = ecma_create_object (proto_p, sizeof (ecma_regexp_string_iterator_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) result_obj; + ext_obj_p->u.cls.type = ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR; + ext_obj_p->u.cls.u1.regexp_string_iterator_flags = (uint8_t) (parsed_flag & (RE_FLAG_GLOBAL | RE_FLAG_UNICODE)); + + ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) result_obj; + + regexp_string_iterator_obj->iterating_regexp = matcher; + regexp_string_iterator_obj->iterated_string = ecma_make_string_value (str_p); + + ecma_deref_object (matcher_obj_p); + + return ecma_make_object_value (result_obj); +} /* ecma_builtin_regexp_prototype_match_all */ + +/** + * Dispatcher of the Regexp built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_regexp_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + ecma_object_t *obj_p = NULL; + + /* 1. && 2. */ + if (ecma_is_value_object (this_arg)) + { + obj_p = ecma_get_object_from_value (this_arg); + + if (builtin_routine_id < ECMA_REGEXP_PROTOTYPE_ROUTINE_TEST + && !ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_REGEXP)) + { + obj_p = NULL; + } + } + + if (obj_p == NULL) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + switch (builtin_routine_id) + { +#if JERRY_BUILTIN_ANNEXB + case ECMA_REGEXP_PROTOTYPE_ROUTINE_COMPILE: + { + return ecma_builtin_regexp_prototype_compile (this_arg, arguments_list_p[0], arguments_list_p[1]); + } +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_REGEXP_PROTOTYPE_ROUTINE_TEST: + { + return ecma_builtin_regexp_prototype_test (this_arg, arguments_list_p[0]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_EXEC: + { + return ecma_builtin_regexp_prototype_exec (this_arg, arguments_list_p[0]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_TO_STRING: + { + return ecma_builtin_regexp_prototype_to_string (obj_p); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SEARCH: + { + return ecma_regexp_search_helper (this_arg, arguments_list_p[0]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH: + { + return ecma_regexp_match_helper (this_arg, arguments_list_p[0]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH_ALL: + { + return ecma_builtin_regexp_prototype_match_all (obj_p, arguments_list_p[0]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_REPLACE: + { + return ecma_regexp_replace_helper (this_arg, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SPLIT: + { + return ecma_regexp_split_helper (this_arg, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_FLAGS: + { + return ecma_builtin_regexp_prototype_get_flags (obj_p); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_SOURCE: + { + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_REGEXP)) + { + if (obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_REGEXP); + } + + ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) obj_p; + return ecma_builtin_regexp_prototype_get_source (re_obj_p); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_GLOBAL: + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_IGNORE_CASE: + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_MULTILINE: + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_STICKY: + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_UNICODE: + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_DOT_ALL: + { + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_REGEXP)) + { + if (obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE)) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_REGEXP); + } + + ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) obj_p; + return ecma_builtin_regexp_prototype_flags_helper (re_obj_p, builtin_routine_id); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_regexp_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.inc.h new file mode 100644 index 00000000..51486e9f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.inc.h @@ -0,0 +1,64 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * RegExp.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_REGEXP + +/* ECMA-262 v5, 15.10.6.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_REGEXP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_FLAGS, ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_FLAGS, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_SOURCE, ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_SOURCE, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_GLOBAL, ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_GLOBAL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_IGNORECASE_UL, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_IGNORE_CASE, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_DOTALL, ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_DOT_ALL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_MULTILINE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_MULTILINE, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_UNICODE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_UNICODE, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_STICKY, ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_STICKY, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ROUTINE (LIT_GLOBAL_SYMBOL_REPLACE, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_REPLACE, 2, 2) +ROUTINE (LIT_GLOBAL_SYMBOL_SEARCH, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SEARCH, 1, 1) +ROUTINE (LIT_GLOBAL_SYMBOL_SPLIT, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SPLIT, 2, 2) +ROUTINE (LIT_GLOBAL_SYMBOL_MATCH, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH, 1, 1) +ROUTINE (LIT_GLOBAL_SYMBOL_MATCH_ALL, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH_ALL, 1, 1) + +#if JERRY_BUILTIN_ANNEXB +ROUTINE (LIT_MAGIC_STRING_COMPILE, ECMA_REGEXP_PROTOTYPE_ROUTINE_COMPILE, 2, 2) +#endif /* JERRY_BUILTIN_ANNEXB */ +ROUTINE (LIT_MAGIC_STRING_EXEC, ECMA_REGEXP_PROTOTYPE_ROUTINE_EXEC, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TEST, ECMA_REGEXP_PROTOTYPE_ROUTINE_TEST, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_REGEXP_PROTOTYPE_ROUTINE_TO_STRING, 0, 0) + +#endif /* JERRY_BUILTIN_REGEXP */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.cpp new file mode 100644 index 00000000..5a1d554d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.cpp @@ -0,0 +1,184 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-gc.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-regexp-string-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID regexp_string_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %regexpstringiteratorprototype% ECMA %ArrayIteratorPrototype% object built-in + * @{ + */ + +/** + * The %RegExpStringIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v11, 21.2.7.1.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_regexp_string_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + /* 2. */ + if (!ecma_is_value_object (this_val)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_val); + + /* 3. */ + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR); + } + + ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) obj_p; + + /* 4. */ + if (ecma_is_value_empty (regexp_string_iterator_obj->iterated_string)) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + /* 5. */ + ecma_value_t regexp = regexp_string_iterator_obj->iterating_regexp; + + /* 6. */ + ecma_value_t matcher_str_value = regexp_string_iterator_obj->iterated_string; + ecma_string_t *matcher_str_p = ecma_get_string_from_value (matcher_str_value); + + /* 9. */ + ecma_value_t match = ecma_op_regexp_exec (regexp, matcher_str_p); + + if (ECMA_IS_VALUE_ERROR (match)) + { + return match; + } + + /* 10. */ + if (ecma_is_value_null (match)) + { + ecma_free_value (regexp_string_iterator_obj->iterated_string); + regexp_string_iterator_obj->iterated_string = ECMA_VALUE_EMPTY; + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + ecma_object_t *match_result_array_p = ecma_get_object_from_value (match); + + ecma_value_t result = ECMA_VALUE_ERROR; + + /* 11. */ + if (regexp_string_iterator_obj->header.u.cls.u1.regexp_string_iterator_flags & RE_FLAG_GLOBAL) + { + ecma_value_t matched_str_value = ecma_op_object_get_by_index (match_result_array_p, 0); + + if (ECMA_IS_VALUE_ERROR (matched_str_value)) + { + goto free_variables; + } + + ecma_string_t *matched_str_p = ecma_op_to_string (matched_str_value); + + ecma_free_value (matched_str_value); + + if (JERRY_UNLIKELY (matched_str_p == NULL)) + { + goto free_variables; + } + + if (ecma_string_is_empty (matched_str_p)) + { + ecma_object_t *regexp_obj_p = ecma_get_object_from_value (regexp); + + ecma_value_t get_last_index = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); + + if (ECMA_IS_VALUE_ERROR (get_last_index)) + { + goto free_variables; + } + + ecma_length_t this_index; + ecma_value_t to_len = ecma_op_to_length (get_last_index, &this_index); + + ecma_free_value (get_last_index); + + if (ECMA_IS_VALUE_ERROR (to_len)) + { + goto free_variables; + } + + uint8_t flags = regexp_string_iterator_obj->header.u.cls.u1.regexp_string_iterator_flags; + ecma_length_t next_index = + ecma_op_advance_string_index (matcher_str_p, this_index, (flags & RE_FLAG_UNICODE) != 0); + + ecma_value_t next_index_value = ecma_make_length_value (next_index); + ecma_value_t set = ecma_op_object_put (regexp_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + next_index_value, + true); + + ecma_free_value (next_index_value); + + if (ECMA_IS_VALUE_ERROR (set)) + { + goto free_variables; + } + } + else + { + ecma_deref_ecma_string (matched_str_p); + } + } + else + { + ecma_free_value (regexp_string_iterator_obj->iterated_string); + regexp_string_iterator_obj->iterated_string = ECMA_VALUE_EMPTY; + } + + result = ecma_create_iter_result_object (match, ECMA_VALUE_FALSE); + +free_variables: + ecma_deref_object (match_result_array_p); + + return result; +} /* ecma_builtin_regexp_string_iterator_prototype_object_next */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.inc.h new file mode 100644 index 00000000..612bf697 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.inc.h @@ -0,0 +1,30 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %RegExpStringIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, + LIT_MAGIC_STRING_REGEXP_STRING_ITERATOR_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ecma_builtin_regexp_string_iterator_prototype_object_next, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.cpp new file mode 100644 index 00000000..0b3cfe58 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.cpp @@ -0,0 +1,217 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-regexp-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_REGEXP + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-regexp.inc.h" +#define BUILTIN_UNDERSCORED_ID regexp +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup regexp ECMA RegExp object built-in + * @{ + */ + +static ecma_value_t +ecma_builtin_regexp_dispatch_helper (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_value_t pattern_value = ECMA_VALUE_UNDEFINED; + ecma_value_t flags_value = ECMA_VALUE_UNDEFINED; + bool create_regexp_from_bc = false; + bool free_arguments = false; + ecma_object_t *new_target_p = JERRY_CONTEXT (current_new_target_p); + + if (arguments_list_len > 0) + { + /* pattern string or RegExp object */ + pattern_value = arguments_list_p[0]; + + if (arguments_list_len > 1) + { + flags_value = arguments_list_p[1]; + } + } + + ecma_value_t regexp_value = ecma_op_is_regexp (pattern_value); + + if (ECMA_IS_VALUE_ERROR (regexp_value)) + { + return regexp_value; + } + + bool pattern_is_regexp = regexp_value == ECMA_VALUE_TRUE; + re_compiled_code_t *bc_p = NULL; + + if (new_target_p == NULL) + { + new_target_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP); + + if (pattern_is_regexp && ecma_is_value_undefined (flags_value)) + { + ecma_object_t *pattern_obj_p = ecma_get_object_from_value (pattern_value); + + ecma_value_t pattern_constructor = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_CONSTRUCTOR); + + if (ECMA_IS_VALUE_ERROR (pattern_constructor)) + { + return pattern_constructor; + } + + bool is_same = ecma_op_same_value (ecma_make_object_value (new_target_p), pattern_constructor); + ecma_free_value (pattern_constructor); + + if (is_same) + { + return ecma_copy_value (pattern_value); + } + } + } + + if (ecma_object_is_regexp_object (pattern_value)) + { + ecma_extended_object_t *pattern_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (pattern_value); + bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, pattern_obj_p->u.cls.u3.value); + + create_regexp_from_bc = ecma_is_value_undefined (flags_value); + + if (!create_regexp_from_bc) + { + pattern_value = bc_p->source; + } + } + else if (pattern_is_regexp) + { + ecma_object_t *pattern_obj_p = ecma_get_object_from_value (pattern_value); + + pattern_value = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_SOURCE); + + if (ECMA_IS_VALUE_ERROR (pattern_value)) + { + return pattern_value; + } + + if (ecma_is_value_undefined (flags_value)) + { + flags_value = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_FLAGS); + + if (ECMA_IS_VALUE_ERROR (flags_value)) + { + ecma_free_value (pattern_value); + return flags_value; + } + } + else + { + flags_value = ecma_copy_value (flags_value); + } + + free_arguments = true; + } + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + ecma_object_t *new_target_obj_p = ecma_op_regexp_alloc (new_target_p); + + if (JERRY_LIKELY (new_target_obj_p != NULL)) + { + if (create_regexp_from_bc) + { + ret_value = ecma_op_create_regexp_from_bytecode (new_target_obj_p, bc_p); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (ret_value)); + } + else + { + ret_value = ecma_op_create_regexp_from_pattern (new_target_obj_p, pattern_value, flags_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_object (new_target_obj_p); + } + } + } + + if (free_arguments) + { + ecma_free_value (pattern_value); + ecma_free_value (flags_value); + } + + return ret_value; +} /* ecma_builtin_regexp_dispatch_helper */ + +/** + * Handle calling [[Call]] of built-in RegExp object + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_regexp_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_regexp_dispatch_helper (arguments_list_p, arguments_list_len); +} /* ecma_builtin_regexp_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in RegExp object + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_regexp_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_regexp_dispatch_helper (arguments_list_p, arguments_list_len); +} /* ecma_builtin_regexp_dispatch_construct */ + +/** + * 21.2.4.2 get RegExp [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_regexp_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_regexp_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h new file mode 100644 index 00000000..a9fa8922 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * RegExp built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_REGEXP + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 2, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* ECMA-262 v5, 15.10.5.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_REGEXP_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_REGEXP_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 21.2.4.2 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_regexp_species_get, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_REGEXP */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.cpp new file mode 100644 index 00000000..e435626b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.cpp @@ -0,0 +1,106 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_SET_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_BUILTIN_SET_ITERATOR_PROTOTYPE_OBJECT_NEXT, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-set-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID set_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %setiteratorprototype% ECMA %SetIteratorPrototype% object built-in + * @{ + */ + +/** + * The %SetIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 23.2.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_set_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + return ecma_op_container_iterator_next (this_val, ECMA_OBJECT_CLASS_SET_ITERATOR); +} /* ecma_builtin_set_iterator_prototype_object_next */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_set_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + *routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_SET_ITERATOR_PROTOTYPE_OBJECT_NEXT: + { + return ecma_builtin_set_iterator_prototype_object_next (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_set_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.inc.h new file mode 100644 index 00000000..4704236a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.inc.h @@ -0,0 +1,32 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %SetIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_SET_ITERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_BUILTIN_SET_ITERATOR_PROTOTYPE_OBJECT_NEXT, 0, 0) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.cpp new file mode 100644 index 00000000..8ff2687c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.cpp @@ -0,0 +1,65 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-set-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID set_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup set ECMA Set object built-in + * @{ + */ +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_set_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + return ecma_builtin_container_dispatch_routine (builtin_routine_id, + this_arg, + arguments_list_p, + LIT_MAGIC_STRING_SET_UL); +} /* ecma_builtin_set_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.inc.h new file mode 100644 index 00000000..8c6f874b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.inc.h @@ -0,0 +1,55 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Set.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.2.3.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_SET, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.3.13 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_SET_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_CLEAR, ECMA_CONTAINER_ROUTINE_CLEAR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_ADD, ECMA_CONTAINER_ROUTINE_ADD, 1, 1) +ROUTINE (LIT_MAGIC_STRING_DELETE, ECMA_CONTAINER_ROUTINE_DELETE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_CONTAINER_ROUTINE_FOREACH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_HAS, ECMA_CONTAINER_ROUTINE_HAS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_CONTAINER_ROUTINE_ENTRIES, 0, 0) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_VALUES, + LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_GLOBAL_SYMBOL_ITERATOR, + LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_KEYS, + LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_SIZE, ECMA_CONTAINER_ROUTINE_SIZE_GETTER, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.cpp new file mode 100644 index 00000000..d875fdaf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.cpp @@ -0,0 +1,86 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-container-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-set.inc.h" +#define BUILTIN_UNDERSCORED_ID set +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup set ECMA Set object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Set object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_set_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_SET_REQUIRES_NEW); +} /* ecma_builtin_set_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Map object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_set_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_container_create (arguments_list_p, + arguments_list_len, + LIT_MAGIC_STRING_SET_UL, + ECMA_BUILTIN_ID_SET_PROTOTYPE); +} /* ecma_builtin_set_dispatch_construct */ + +/** + * 23.2.2.2 get Set [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_set_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_set_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.inc.h new file mode 100644 index 00000000..559b4ccb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.inc.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Set built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.2.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_SET_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.2.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_SET_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 23.2.2.2 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_set_species_get, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.cpp new file mode 100644 index 00000000..321c2c82 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.cpp @@ -0,0 +1,113 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-shared-arraybuffer-object.h" + +#include "jrt-libc-includes.h" +#include "jrt.h" + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-shared-arraybuffer-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID shared_arraybuffer_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup sharedarraybufferprototype ECMA SharedArrayBuffer.prototype object built-in + * @{ + */ + +/** + * The SharedArrayBuffer.prototype.bytelength accessor + * + * See also: + * ES11, 24.2.4.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_shared_arraybuffer_prototype_bytelength_getter (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER)) + { + uint32_t len = ecma_arraybuffer_get_length (object_p); + + return ecma_make_uint32_value (len); + } + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER); +} /* ecma_builtin_shared_arraybuffer_prototype_bytelength_getter */ + +/** + * The SharedArrayBuffer.prototype object's 'slice' routine + * + * See also: + * ECMA-262 v11, 24.2.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_shared_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< this argument */ + const ecma_value_t *argument_list_p, /**< arguments list */ + uint32_t arguments_number) /**< number of arguments */ +{ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + /* 2. */ + if (!ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER_OBJECT); + } + + return ecma_builtin_arraybuffer_slice (this_arg, argument_list_p, arguments_number); +} /* ecma_builtin_shared_arraybuffer_prototype_object_slice */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.inc.h new file mode 100644 index 00000000..c7b0b9eb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.inc.h @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * SharedArrayBuffer.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Readonly accessor properties */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL, + ecma_builtin_shared_arraybuffer_prototype_bytelength_getter, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v11, 24.2.4.4 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_SHARED_ARRAY_BUFFER_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_SLICE, ecma_builtin_shared_arraybuffer_prototype_object_slice, NON_FIXED, 2) + +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.cpp new file mode 100644 index 00000000..38fc8f12 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.cpp @@ -0,0 +1,96 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-dataview-object.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-shared-arraybuffer-object.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-shared-arraybuffer.inc.h" +#define BUILTIN_UNDERSCORED_ID shared_arraybuffer +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup sharedarraybuffer ECMA SharedArrayBuffer object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in SharedArrayBuffer object + * + * ES11 24.2.2 SharedArrayBuffer is not intended to be called as + * a function and will throw an exception when called in + * that manner. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_shared_arraybuffer_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_SHAREDARRAYBUFFER_REQUIRES_NEW); +} /* ecma_builtin_shared_arraybuffer_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in SharedArrayBuffer object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_shared_arraybuffer_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_shared_arraybuffer_object (arguments_list_p, arguments_list_len); +} /* ecma_builtin_shared_arraybuffer_dispatch_construct */ + +/** + * 24.2.3.2 get SharedArrayBuffer [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_shared_arraybuffer_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_shared_arraybuffer_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.inc.h new file mode 100644 index 00000000..8a7c73a7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.inc.h @@ -0,0 +1,46 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * SharedArrayBuffer built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_SHARED_ARRAY_BUFFER_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ + +/* ES11 24.1.3.3 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, + ecma_builtin_shared_arraybuffer_species_get, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.cpp new file mode 100644 index 00000000..5f2158cf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.cpp @@ -0,0 +1,205 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-iterator-object.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_STRING_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_BUILTIN_STRING_ITERATOR_PROTOTYPE_OBJECT_NEXT, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-string-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID string_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %stringiteratorprototype% ECMA %ArrayIteratorPrototype% object built-in + * @{ + */ + +/** + * The %StringIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 22.1.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_string_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + /* 1 - 2. */ + if (!ecma_is_value_object (this_val)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_val); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + /* 3. */ + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_STRING_ITERATOR)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR); + } + + ecma_value_t iterated_value = ext_obj_p->u.cls.u3.iterated_value; + + /* 4 - 5 */ + if (ecma_is_value_empty (iterated_value)) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + JERRY_ASSERT (ecma_is_value_string (iterated_value)); + + ecma_string_t *string_p = ecma_get_string_from_value (iterated_value); + + /* 6. */ + lit_utf8_size_t position = ext_obj_p->u.cls.u2.iterator_index; + + if (JERRY_UNLIKELY (position == ECMA_ITERATOR_INDEX_LIMIT)) + { + /* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]] + property is stored as an internal property */ + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); + ecma_value_t position_value = ecma_op_object_get (obj_p, prop_name_p); + + position = (lit_utf8_size_t) (ecma_get_number_from_value (position_value)); + ecma_free_value (position_value); + } + + /* 7. */ + lit_utf8_size_t len = ecma_string_get_length (string_p); + + /* 8. */ + if (position >= len) + { + ecma_deref_ecma_string (string_p); + ext_obj_p->u.cls.u3.iterated_value = ECMA_VALUE_EMPTY; + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + /* 9. */ + ecma_char_t first = ecma_string_get_char_at_pos (string_p, position); + + ecma_string_t *result_str_p; + lit_utf8_size_t result_size = 1; + + /* 10. */ + if (first < LIT_UTF16_HIGH_SURROGATE_MIN || first > LIT_UTF16_HIGH_SURROGATE_MAX || (position + 1 == len)) + { + result_str_p = ecma_new_ecma_string_from_code_unit (first); + } + /* 11. */ + else + { + /* 11.a */ + ecma_char_t second = ecma_string_get_char_at_pos (string_p, position + 1); + + /* 11.b */ + if (second < LIT_UTF16_LOW_SURROGATE_MIN || second > LIT_UTF16_LOW_SURROGATE_MAX) + { + result_str_p = ecma_new_ecma_string_from_code_unit (first); + } + /* 11.c */ + else + { + result_str_p = ecma_new_ecma_string_from_code_units (first, second); + result_size = 2; + } + } + + /* 13. */ + if (position + result_size < ECMA_ITERATOR_INDEX_LIMIT) + { + ext_obj_p->u.cls.u2.iterator_index = (uint16_t) (position + result_size); + } + else + { + ext_obj_p->u.cls.u2.iterator_index = ECMA_ITERATOR_INDEX_LIMIT; + + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); + ecma_value_t put_result = + ecma_op_object_put (obj_p, prop_name_p, ecma_make_length_value (position + result_size), true); + + JERRY_ASSERT (ecma_is_value_true (put_result)); + } + + /* 14. */ + ecma_value_t result = ecma_create_iter_result_object (ecma_make_string_value (result_str_p), ECMA_VALUE_FALSE); + ecma_deref_ecma_string (result_str_p); + + return result; +} /* ecma_builtin_string_iterator_prototype_object_next */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_string_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< + * list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_STRING_ITERATOR_PROTOTYPE_OBJECT_NEXT: + { + return ecma_builtin_string_iterator_prototype_object_next (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_string_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h new file mode 100644 index 00000000..adc799d1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %StringIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_STRING_ITERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_BUILTIN_STRING_ITERATOR_PROTOTYPE_OBJECT_NEXT, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp new file mode 100644 index 00000000..f60cd005 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp @@ -0,0 +1,1560 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtin-regexp.inc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jcontext.h" +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "lit-char-helpers.h" +#include "lit-strings.h" + +#if JERRY_BUILTIN_REGEXP +#include "ecma-regexp-object.h" +#endif /* JERRY_BUILTIN_REGEXP */ + +#if JERRY_BUILTIN_STRING + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_STRING_PROTOTYPE_ROUTINE_START = 0, + /* Note: These 4 routines MUST be in this order */ + ECMA_STRING_PROTOTYPE_TO_STRING, + ECMA_STRING_PROTOTYPE_VALUE_OF, + ECMA_STRING_PROTOTYPE_CHAR_AT, + ECMA_STRING_PROTOTYPE_CHAR_CODE_AT, + + ECMA_STRING_PROTOTYPE_CONCAT, + ECMA_STRING_PROTOTYPE_SLICE, + ECMA_STRING_PROTOTYPE_AT, + + ECMA_STRING_PROTOTYPE_LOCALE_COMPARE, + + ECMA_STRING_PROTOTYPE_MATCH, + ECMA_STRING_PROTOTYPE_REPLACE, + ECMA_STRING_PROTOTYPE_SEARCH, + + ECMA_STRING_PROTOTYPE_SPLIT, + ECMA_STRING_PROTOTYPE_SUBSTRING, + ECMA_STRING_PROTOTYPE_TO_LOWER_CASE, + ECMA_STRING_PROTOTYPE_TO_LOCAL_LOWER_CASE, + ECMA_STRING_PROTOTYPE_TO_UPPER_CASE, + ECMA_STRING_PROTOTYPE_TO_LOCAL_UPPER_CASE, + ECMA_STRING_PROTOTYPE_TRIM, + + ECMA_STRING_PROTOTYPE_SUBSTR, + + ECMA_STRING_PROTOTYPE_REPEAT, + ECMA_STRING_PROTOTYPE_CODE_POINT_AT, + ECMA_STRING_PROTOTYPE_PAD_START, + ECMA_STRING_PROTOTYPE_PAD_END, + /* Note: These 5 routines MUST be in this order */ + ECMA_STRING_PROTOTYPE_LAST_INDEX_OF, + ECMA_STRING_PROTOTYPE_INDEX_OF, + ECMA_STRING_PROTOTYPE_STARTS_WITH, + ECMA_STRING_PROTOTYPE_INCLUDES, + ECMA_STRING_PROTOTYPE_ENDS_WITH, + + ECMA_STRING_PROTOTYPE_ITERATOR, + ECMA_STRING_PROTOTYPE_REPLACE_ALL, + ECMA_STRING_PROTOTYPE_MATCH_ALL, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-string-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID string_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup stringprototype ECMA String.prototype object built-in + * @{ + */ + +/** + * The String.prototype object's 'toString' and 'valueOf' routines + * + * See also: + * ECMA-262 v5, 15.5.4.2 + * ECMA-262 v5, 15.5.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_string (this_arg)) + { + return ecma_copy_value (this_arg); + } + + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_STRING)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (ecma_is_value_string (ext_object_p->u.cls.u3.value)); + + return ecma_copy_value (ext_object_p->u.cls.u3.value); + } + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_STRING_OBJECT); +} /* ecma_builtin_string_prototype_object_to_string */ + +/** + * Helper function for the String.prototype object's 'charAt' and charCodeAt' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_char_at_helper (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg, /**< routine's argument */ + bool charcode_mode) /**< routine mode */ +{ + /* 3 */ + ecma_number_t index_num; + ecma_value_t to_num_result = ecma_op_to_integer (arg, &index_num); + + if (JERRY_UNLIKELY (!ecma_is_value_empty (to_num_result))) + { + return to_num_result; + } + + /* 2 */ + ecma_string_t *original_string_p = ecma_op_to_string (this_arg); + if (JERRY_UNLIKELY (original_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 4 */ + const lit_utf8_size_t len = ecma_string_get_length (original_string_p); + + /* 5 */ + // When index_num is NaN, then the first two comparisons are false + if (index_num < 0 || index_num >= len || (ecma_number_is_nan (index_num) && len == 0)) + { + ecma_deref_ecma_string (original_string_p); + return (charcode_mode ? ecma_make_nan_value () : ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY)); + } + + /* 6 */ + /* + * String length is currently uint32_t, but index_num may be bigger, + * ToInteger performs floor, while ToUInt32 performs modulo 2^32, + * hence after the check 0 <= index_num < len we assume to_uint32 can be used. + * We assume to_uint32 (NaN) is 0. + */ + JERRY_ASSERT (ecma_number_is_nan (index_num) || ecma_number_to_uint32 (index_num) == ecma_number_trunc (index_num)); + + ecma_char_t new_ecma_char = ecma_string_get_char_at_pos (original_string_p, ecma_number_to_uint32 (index_num)); + ecma_deref_ecma_string (original_string_p); + + return (charcode_mode ? ecma_make_uint32_value (new_ecma_char) + : ecma_make_string_value (ecma_new_ecma_string_from_code_unit (new_ecma_char))); +} /* ecma_builtin_string_prototype_char_at_helper */ + +/** + * The String.prototype object's 'concat' routine + * + * See also: + * ECMA-262 v5, 15.5.4.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_concat (ecma_string_t *this_string_p, /**< this argument */ + const ecma_value_t *argument_list_p, /**< arguments list */ + uint32_t arguments_number) /**< number of arguments */ +{ + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (this_string_p); + + /* 5 */ + for (uint32_t arg_index = 0; arg_index < arguments_number; ++arg_index) + { + /* 5a, b */ + ecma_string_t *get_arg_string_p = ecma_op_to_string (argument_list_p[arg_index]); + + if (JERRY_UNLIKELY (get_arg_string_p == NULL)) + { + ecma_stringbuilder_destroy (&builder); + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_append (&builder, get_arg_string_p); + + ecma_deref_ecma_string (get_arg_string_p); + } + + /* 6 */ + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_string_prototype_object_concat */ + +/** + * The String.prototype object's 'localeCompare' routine + * + * See also: + * ECMA-262 v5, 15.5.4.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_locale_compare (ecma_string_t *this_string_p, /**< this argument */ + ecma_value_t arg) /**< routine's argument */ +{ + /* 3. */ + ecma_string_t *arg_string_p = ecma_op_to_string (arg); + + if (JERRY_UNLIKELY (arg_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t result = ECMA_NUMBER_ZERO; + + if (ecma_compare_ecma_strings_relational (this_string_p, arg_string_p)) + { + result = ECMA_NUMBER_MINUS_ONE; + } + else if (!ecma_compare_ecma_strings (this_string_p, arg_string_p)) + { + result = ECMA_NUMBER_ONE; + } + else + { + result = ECMA_NUMBER_ZERO; + } + + ecma_deref_ecma_string (arg_string_p); + + return ecma_make_number_value (result); +} /* ecma_builtin_string_prototype_object_locale_compare */ + +#if JERRY_BUILTIN_REGEXP +/** + * The String.prototype object's 'match' routine + * + * See also: + * ECMA-262 v5, 15.5.4.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_match (ecma_value_t this_argument, /**< this argument */ + ecma_value_t regexp_arg) /**< routine's argument */ +{ + /* 3. */ + if (!(ecma_is_value_undefined (regexp_arg) || ecma_is_value_null (regexp_arg))) + { + /* 3.a */ + ecma_value_t matcher = ecma_op_get_method_by_symbol_id (regexp_arg, LIT_GLOBAL_SYMBOL_MATCH); + + /* 3.b */ + if (ECMA_IS_VALUE_ERROR (matcher)) + { + return matcher; + } + + /* 3.c */ + if (!ecma_is_value_undefined (matcher)) + { + /* 3.c.i */ + ecma_object_t *matcher_method = ecma_get_object_from_value (matcher); + ecma_value_t result = ecma_op_function_call (matcher_method, regexp_arg, &this_argument, 1); + ecma_deref_object (matcher_method); + return result; + } + } + + /* 4. */ + ecma_string_t *this_str_p = ecma_op_to_string (this_argument); + + /* 5. */ + if (JERRY_UNLIKELY (this_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 6. */ + ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL); + + if (JERRY_UNLIKELY (regexp_obj_p == NULL)) + { + ecma_deref_ecma_string (this_str_p); + return ECMA_VALUE_ERROR; + } + + ecma_value_t new_regexp = ecma_op_create_regexp_from_pattern (regexp_obj_p, regexp_arg, ECMA_VALUE_UNDEFINED); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (new_regexp)) + { + ecma_deref_object (regexp_obj_p); + ecma_deref_ecma_string (this_str_p); + return new_regexp; + } + ecma_value_t this_str_value = ecma_make_string_value (this_str_p); + + /* 8. */ + ecma_value_t ret_value = ecma_op_invoke_by_symbol_id (new_regexp, LIT_GLOBAL_SYMBOL_MATCH, &this_str_value, 1); + + ecma_deref_ecma_string (this_str_p); + ecma_free_value (new_regexp); + + return ret_value; +} /* ecma_builtin_string_prototype_object_match */ + +/** + * The String.prototype object's 'matchAll' routine + * + * See also: + * ECMA-262 v11, 21.1.3.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_match_all (ecma_value_t this_argument, /**< this argument */ + ecma_value_t regexp_arg) /**< routine's argument */ +{ + /* 2. */ + if (!ecma_is_value_null (regexp_arg) && !ecma_is_value_undefined (regexp_arg)) + { + /* 2.a */ + ecma_value_t is_regexp = ecma_op_is_regexp (regexp_arg); + + if (ECMA_IS_VALUE_ERROR (is_regexp)) + { + return is_regexp; + } + + /* 2.b */ + if (ecma_is_value_true (is_regexp)) + { + /* 2.b.i */ + ecma_object_t *regexp_obj_p = ecma_get_object_from_value (regexp_arg); + ecma_value_t get_flags = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_FLAGS); + + if (ECMA_IS_VALUE_ERROR (get_flags)) + { + return get_flags; + } + + /* 2.b.ii */ + if (!ecma_op_require_object_coercible (get_flags)) + { + ecma_free_value (get_flags); + return ECMA_VALUE_ERROR; + } + + /* 2.b.iii */ + ecma_string_t *flags = ecma_op_to_string (get_flags); + + ecma_free_value (get_flags); + + if (JERRY_UNLIKELY (flags == NULL)) + { + return ECMA_VALUE_ERROR; + } + + uint16_t parsed_flag; + ecma_value_t flag_parse = ecma_regexp_parse_flags (flags, &parsed_flag); + + ecma_deref_ecma_string (flags); + + if (ECMA_IS_VALUE_ERROR (flag_parse)) + { + return flag_parse; + } + + if (!(parsed_flag & RE_FLAG_GLOBAL)) + { + return ecma_raise_type_error (ECMA_ERR_REGEXP_ARGUMENT_SHOULD_HAVE_GLOBAL_FLAG); + } + } + + /* 2.c */ + ecma_value_t matcher = ecma_op_get_method_by_symbol_id (regexp_arg, LIT_GLOBAL_SYMBOL_MATCH_ALL); + + if (ECMA_IS_VALUE_ERROR (matcher)) + { + return matcher; + } + + /* 2.d */ + if (!ecma_is_value_undefined (matcher)) + { + /* 2.d.i */ + ecma_object_t *matcher_method = ecma_get_object_from_value (matcher); + ecma_value_t result = ecma_op_function_call (matcher_method, regexp_arg, &this_argument, 1); + ecma_deref_object (matcher_method); + return result; + } + } + + /* 3. */ + ecma_string_t *str_p = ecma_op_to_string (this_argument); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 4. */ + ecma_object_t *new_regexp_obj_p = ecma_op_regexp_alloc (NULL); + + if (JERRY_UNLIKELY (new_regexp_obj_p == NULL)) + { + ecma_deref_ecma_string (str_p); + return ECMA_VALUE_ERROR; + } + + ecma_value_t new_regexp = ecma_op_create_regexp_from_pattern (new_regexp_obj_p, regexp_arg, ECMA_VALUE_UNDEFINED); + + if (ECMA_IS_VALUE_ERROR (new_regexp)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_object (new_regexp_obj_p); + return new_regexp; + } + + /* 5. */ + ecma_value_t string_arg = ecma_make_string_value (str_p); + ecma_value_t ret_value = ecma_op_invoke_by_symbol_id (new_regexp, LIT_GLOBAL_SYMBOL_MATCH_ALL, &string_arg, 1); + + ecma_deref_ecma_string (str_p); + ecma_free_value (new_regexp); + + return ret_value; +} /* ecma_builtin_string_prototype_object_match_all */ + +/** + * The String.prototype object's 'replace' and 'replaceAll' routine + * + * See also: + * ECMA-262 v5, 15.5.4.11 (replace ES5) + * ECMA-262 v6, 21.1.3.14 (replace ES6) + * ECMA-262 v12, 21.1.3.18 (replaceAll) + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_replace_helper (ecma_value_t this_value, /**< this argument */ + ecma_value_t search_value, /**< routine's first argument */ + ecma_value_t replace_value, /**< routine's second argument */ + bool replace_all) +{ + ecma_string_t *result_string_p; + lit_utf8_byte_t *search_buf_p; + uint8_t search_flags; + uint8_t input_flags; + + if (!(ecma_is_value_undefined (search_value) || ecma_is_value_null (search_value))) + { + if (replace_all) + { + ecma_value_t is_regexp = ecma_op_is_regexp (search_value); + + if (ECMA_IS_VALUE_ERROR (is_regexp)) + { + return is_regexp; + } + + if (ecma_is_value_true (is_regexp)) + { + ecma_object_t *regexp_obj_p = ecma_get_object_from_value (search_value); + ecma_value_t get_flags = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_FLAGS); + + if (ECMA_IS_VALUE_ERROR (get_flags)) + { + return get_flags; + } + + if (!ecma_op_require_object_coercible (get_flags)) + { + ecma_free_value (get_flags); + return ECMA_VALUE_ERROR; + } + + ecma_string_t *flags = ecma_op_to_string (get_flags); + + ecma_free_value (get_flags); + + if (JERRY_UNLIKELY (flags == NULL)) + { + return ECMA_VALUE_ERROR; + } + + bool have_global_flag = lit_find_char_in_string (flags, LIT_CHAR_LOWERCASE_G); + + ecma_deref_ecma_string (flags); + + if (!have_global_flag) + { + return ecma_raise_type_error (ECMA_ERR_REGEXP_ARGUMENT_SHOULD_HAVE_GLOBAL_FLAG); + } + } + } + + ecma_object_t *obj_p = ecma_get_object_from_value (ecma_op_to_object (search_value)); + ecma_value_t replace_symbol = ecma_op_object_get_by_symbol_id (obj_p, LIT_GLOBAL_SYMBOL_REPLACE); + ecma_deref_object (obj_p); + + if (ECMA_IS_VALUE_ERROR (replace_symbol)) + { + return replace_symbol; + } + + if (!ecma_is_value_undefined (replace_symbol) && !ecma_is_value_null (replace_symbol)) + { + ecma_value_t arguments[] = { this_value, replace_value }; + ecma_value_t replace_result = ecma_op_function_validated_call (replace_symbol, search_value, arguments, 2); + ecma_free_value (replace_symbol); + + return replace_result; + } + } + + ecma_string_t *input_str_p = ecma_op_to_string (this_value); + + if (input_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ECMA_VALUE_ERROR; + + ecma_string_t *search_str_p = ecma_op_to_string (search_value); + if (search_str_p == NULL) + { + ecma_deref_ecma_string (input_str_p); + return result; + } + + ecma_replace_context_t replace_ctx; + replace_ctx.capture_count = 0; + replace_ctx.u.captures_p = NULL; + + replace_ctx.replace_str_p = NULL; + if (!ecma_op_is_callable (replace_value)) + { + replace_ctx.replace_str_p = ecma_op_to_string (replace_value); + if (replace_ctx.replace_str_p == NULL) + { + goto cleanup_search; + } + } + + input_flags = ECMA_STRING_FLAG_IS_ASCII; + replace_ctx.string_p = ecma_string_get_chars (input_str_p, &(replace_ctx.string_size), NULL, NULL, &input_flags); + + lit_utf8_size_t search_size; + lit_utf8_size_t search_length; + search_flags = ECMA_STRING_FLAG_IS_ASCII; + search_buf_p = (lit_utf8_byte_t *) ecma_string_get_chars (search_str_p, &search_size, &search_length, NULL, &search_flags); + + result_string_p = NULL; + + if (replace_ctx.string_size >= search_size) + { + replace_ctx.builder = ecma_stringbuilder_create (); + replace_ctx.matched_size = search_size; + const lit_utf8_byte_t *const input_end_p = replace_ctx.string_p + replace_ctx.string_size; + const lit_utf8_byte_t *const loop_end_p = input_end_p - search_size; + const lit_utf8_byte_t *last_match_end_p = replace_ctx.string_p; + const lit_utf8_byte_t *curr_p = replace_ctx.string_p; + + lit_utf8_size_t pos = 0; + while (curr_p <= loop_end_p) + { + if (!memcmp (curr_p, search_buf_p, search_size)) + { + const lit_utf8_size_t prefix_size = (lit_utf8_size_t) (curr_p - last_match_end_p); + ecma_stringbuilder_append_raw (&replace_ctx.builder, last_match_end_p, prefix_size); + + last_match_end_p = curr_p + search_size; + + if (replace_ctx.replace_str_p == NULL) + { + ecma_object_t *function_p = ecma_get_object_from_value (replace_value); + + ecma_value_t args[] = { ecma_make_string_value (search_str_p), + ecma_make_uint32_value (pos), + ecma_make_string_value (input_str_p) }; + + result = ecma_op_function_call (function_p, ECMA_VALUE_UNDEFINED, args, 3); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_stringbuilder_destroy (&replace_ctx.builder); + goto cleanup_replace; + } + + ecma_string_t *const result_str_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (result_str_p == NULL) + { + ecma_stringbuilder_destroy (&replace_ctx.builder); + result = ECMA_VALUE_ERROR; + goto cleanup_replace; + } + + ecma_stringbuilder_append (&replace_ctx.builder, result_str_p); + ecma_deref_ecma_string (result_str_p); + } + else + { + replace_ctx.matched_p = curr_p; + replace_ctx.match_byte_pos = (lit_utf8_size_t) (curr_p - replace_ctx.string_p); + + ecma_builtin_replace_substitute (&replace_ctx); + } + + if (!replace_all || last_match_end_p == input_end_p) + { + break; + } + + if (search_size != 0) + { + curr_p = last_match_end_p; + pos += search_length; + continue; + } + } + + pos++; + lit_utf8_incr (&curr_p); + } + + ecma_stringbuilder_append_raw (&replace_ctx.builder, + last_match_end_p, + (lit_utf8_size_t) (input_end_p - last_match_end_p)); + result_string_p = ecma_stringbuilder_finalize (&replace_ctx.builder); + } + + if (result_string_p == NULL) + { + ecma_ref_ecma_string (input_str_p); + result_string_p = input_str_p; + } + + result = ecma_make_string_value (result_string_p); + +cleanup_replace: + if (input_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) replace_ctx.string_p, replace_ctx.string_size); + } + + if (search_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) search_buf_p, search_size); + } + + if (replace_ctx.replace_str_p != NULL) + { + ecma_deref_ecma_string (replace_ctx.replace_str_p); + } + +cleanup_search: + ecma_deref_ecma_string (search_str_p); + ecma_deref_ecma_string (input_str_p); + + return result; +} /* ecma_builtin_string_prototype_object_replace_helper */ + +/** + * The String.prototype object's 'search' routine + * + * See also: + * ECMA-262 v5, 15.5.4.12 + * ECMA-262 v6, 21.1.3.15 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_search (ecma_value_t this_value, /**< this argument */ + ecma_value_t regexp_value) /**< routine's argument */ +{ + if (!(ecma_is_value_undefined (regexp_value) || ecma_is_value_null (regexp_value))) + { + ecma_object_t *obj_p = ecma_get_object_from_value (ecma_op_to_object (regexp_value)); + ecma_value_t search_symbol = ecma_op_object_get_by_symbol_id (obj_p, LIT_GLOBAL_SYMBOL_SEARCH); + ecma_deref_object (obj_p); + + if (ECMA_IS_VALUE_ERROR (search_symbol)) + { + return search_symbol; + } + + if (!ecma_is_value_undefined (search_symbol) && !ecma_is_value_null (search_symbol)) + { + ecma_value_t search_result = ecma_op_function_validated_call (search_symbol, regexp_value, &this_value, 1); + ecma_free_value (search_symbol); + return search_result; + } + } + + ecma_value_t result = ECMA_VALUE_ERROR; + + ecma_string_t *string_p = ecma_op_to_string (this_value); + if (string_p == NULL) + { + return result; + } + + ecma_string_t *pattern_p = ecma_regexp_read_pattern_str_helper (regexp_value); + if (pattern_p == NULL) + { + ecma_deref_ecma_string (string_p); + return result; + } + + ecma_object_t *new_regexp_obj_p = ecma_op_regexp_alloc (NULL); + + if (JERRY_UNLIKELY (new_regexp_obj_p == NULL)) + { + ecma_deref_ecma_string (string_p); + ecma_deref_ecma_string (pattern_p); + return result; + } + + ecma_value_t new_regexp = + ecma_op_create_regexp_from_pattern (new_regexp_obj_p, ecma_make_string_value (pattern_p), ECMA_VALUE_UNDEFINED); + + ecma_deref_ecma_string (pattern_p); + + if (ECMA_IS_VALUE_ERROR (new_regexp)) + { + ecma_deref_ecma_string (string_p); + ecma_deref_object (new_regexp_obj_p); + return result; + } + + ecma_object_t *regexp_obj_p = ecma_get_object_from_value (new_regexp); + ecma_value_t this_str_value = ecma_make_string_value (string_p); + result = ecma_op_invoke_by_symbol_id (new_regexp, LIT_GLOBAL_SYMBOL_SEARCH, &this_str_value, 1); + ecma_deref_object (regexp_obj_p); + ecma_deref_ecma_string (string_p); + + return result; +} /* ecma_builtin_string_prototype_object_search */ + +#endif /* JERRY_BUILTIN_REGEXP */ + +/** + * The String.prototype object's 'slice' routine + * + * See also: + * ECMA-262 v5, 15.5.4.13 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_slice (ecma_string_t *get_string_val, /**< this argument */ + ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + const lit_utf8_size_t len = ecma_string_get_length (get_string_val); + + /* 4. 6. */ + lit_utf8_size_t start = 0, end = len; + + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (arg1, len, &start))) + { + return ECMA_VALUE_ERROR; + } + + /* 5. 7. */ + if (ecma_is_value_undefined (arg2)) + { + end = len; + } + else + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (arg2, len, &end))) + { + return ECMA_VALUE_ERROR; + } + } + + JERRY_ASSERT (start <= len && end <= len); + + /* 8-9. */ + ecma_string_t *new_str_p = ecma_string_substr (get_string_val, start, end); + + return ecma_make_string_value (new_str_p); +} /* ecma_builtin_string_prototype_object_slice */ + +/** + * The String.prototype object's 'at' routine + * + * See also: + * ECMA-262 Stage 3 Draft Relative Indexing Method proposal + * from: https://tc39.es/proposal-relative-indexing-method + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_at (ecma_string_t *string_val, /**< this argument */ + const ecma_value_t index) /**< index argument */ +{ + ecma_length_t len = (ecma_length_t) ecma_string_get_length (string_val); + ecma_length_t res_index; + ecma_value_t return_value = ecma_builtin_helper_calculate_index (index, len, &res_index); + + if (return_value != ECMA_VALUE_EMPTY) + { + return return_value; + } + + ecma_char_t character = ecma_string_get_char_at_pos (string_val, (lit_utf8_size_t) res_index); + + return ecma_make_string_value (ecma_new_ecma_string_from_code_unit (character)); +} /* ecma_builtin_string_prototype_object_at */ + +/** + * The String.prototype object's 'split' routine + * + * See also: + * ECMA-262 v5, 15.5.4.14 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_split (ecma_value_t this_value, /**< this argument */ + ecma_value_t separator_value, /**< separator */ + ecma_value_t limit_value) /**< limit */ +{ + if (!(ecma_is_value_undefined (separator_value) || ecma_is_value_null (separator_value))) + { + ecma_object_t *obj_p = ecma_get_object_from_value (ecma_op_to_object (separator_value)); + ecma_value_t split_symbol = ecma_op_object_get_by_symbol_id (obj_p, LIT_GLOBAL_SYMBOL_SPLIT); + ecma_deref_object (obj_p); + + if (ECMA_IS_VALUE_ERROR (split_symbol)) + { + return split_symbol; + } + + if (!ecma_is_value_undefined (split_symbol) && !ecma_is_value_null (split_symbol)) + { + ecma_value_t arguments[] = { this_value, limit_value }; + ecma_value_t split_result = ecma_op_function_validated_call (split_symbol, separator_value, arguments, 2); + ecma_free_value (split_symbol); + + return split_result; + } + } + + ecma_value_t result = ECMA_VALUE_ERROR; + ecma_string_t *end_substr_p; + ecma_value_t put_result; + + lit_utf8_size_t string_size; + uint8_t string_flags; + lit_utf8_byte_t *string_buffer_p; + lit_utf8_size_t separator_size; + uint8_t separator_flags; + lit_utf8_byte_t *separator_buffer_p; + + lit_utf8_byte_t *string_end_p; + lit_utf8_byte_t *compare_end_p; + const lit_utf8_byte_t *current_p; + const lit_utf8_byte_t *last_str_begin_p; + + lit_utf8_size_t array_length; + + uint32_t limit; + + ecma_string_t *separator_p; + ecma_object_t *array_p; + + /* 4. */ + ecma_string_t *string_p = ecma_op_to_string (this_value); + if (string_p == NULL) + { + return result; + } + + /* 8. */ + limit = UINT32_MAX - 1; + + if (!ecma_is_value_undefined (limit_value)) + { + /* ECMA-262 v11, 21.1.3.20 6 */ + ecma_number_t num; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (limit_value, &num))) + { + goto cleanup_string; + } + limit = ecma_number_to_uint32 (num); + } + + /* 12. */ + separator_p = ecma_op_to_string (separator_value); + if (separator_p == NULL) + { + goto cleanup_string; + } + + /* 6. */ + array_p = ecma_op_new_array_object (0); + result = ecma_make_object_value (array_p); + + /* 14. */ + if (limit == 0) + { + goto cleanup_separator; + } + + /* 6. */ + array_length = 0; + + /* 15. */ + if (ecma_is_value_undefined (separator_value)) + { + ecma_value_t put_result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length, + ecma_make_string_value (string_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (put_result == ECMA_VALUE_TRUE); + goto cleanup_separator; + } + + /* 16. */ + if (ecma_string_is_empty (string_p)) + { + if (!ecma_string_is_empty (separator_p)) + { + ecma_value_t put_result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length, + ecma_make_string_value (string_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (put_result == ECMA_VALUE_TRUE); + } + + goto cleanup_separator; + } + + string_flags = ECMA_STRING_FLAG_IS_ASCII; + string_buffer_p = (lit_utf8_byte_t *) ecma_string_get_chars (string_p, &string_size, NULL, NULL, &string_flags); + separator_flags = ECMA_STRING_FLAG_IS_ASCII; + separator_buffer_p = (lit_utf8_byte_t *) ecma_string_get_chars (separator_p, &separator_size, NULL, NULL, &separator_flags); + + string_end_p = string_buffer_p + string_size; + compare_end_p = JERRY_MIN (string_end_p - separator_size + 1, string_end_p); + current_p = string_buffer_p; + last_str_begin_p = string_buffer_p; + + while (current_p < compare_end_p) + { + if (!memcmp (current_p, separator_buffer_p, separator_size) && (last_str_begin_p != current_p + separator_size)) + { + ecma_string_t *substr_p = + ecma_new_ecma_string_from_utf8 (last_str_begin_p, (lit_utf8_size_t) (current_p - last_str_begin_p)); + ecma_value_t put_result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length++, + ecma_make_string_value (substr_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (put_result == ECMA_VALUE_TRUE); + ecma_deref_ecma_string (substr_p); + + if (array_length >= limit) + { + goto cleanup_buffers; + } + + current_p += separator_size; + last_str_begin_p = current_p; + continue; + } + + lit_utf8_incr (¤t_p); + } + + end_substr_p = ecma_new_ecma_string_from_utf8 (last_str_begin_p, (lit_utf8_size_t) (string_end_p - last_str_begin_p)); + put_result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length, + ecma_make_string_value (end_substr_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (put_result == ECMA_VALUE_TRUE); + ecma_deref_ecma_string (end_substr_p); + +cleanup_buffers: + if (string_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) string_buffer_p, string_size); + } + + if (separator_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) separator_buffer_p, separator_size); + } + +cleanup_separator: + ecma_deref_ecma_string (separator_p); +cleanup_string: + ecma_deref_ecma_string (string_p); + return result; +} /* ecma_builtin_string_prototype_object_split */ + +/** + * The String.prototype object's 'substring' routine + * + * See also: + * ECMA-262 v5, 15.5.4.15 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_substring (ecma_string_t *original_string_p, /**< this argument */ + ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + /* 3 */ + const lit_utf8_size_t len = ecma_string_get_length (original_string_p); + lit_utf8_size_t start = 0, end = len; + + /* 4 */ + ecma_number_t start_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg1, &start_num))) + { + return ECMA_VALUE_ERROR; + } + + /* 6 */ + start = (uint32_t) JERRY_MIN (JERRY_MAX (start_num, 0), len); + + /* 5 */ + if (ecma_is_value_undefined (arg2)) + { + end = len; + } + else + { + /* 5 part 2 */ + ecma_number_t end_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg2, &end_num))) + { + return ECMA_VALUE_ERROR; + } + /* 7 */ + end = (uint32_t) JERRY_MIN (JERRY_MAX (end_num, 0), len); + } + + JERRY_ASSERT (start <= len && end <= len); + + /* 8 */ + uint32_t from = start < end ? start : end; + + /* 9 */ + uint32_t to = start > end ? start : end; + + /* 10 */ + ecma_string_t *new_str_p = ecma_string_substr (original_string_p, from, to); + return ecma_make_string_value (new_str_p); +} /* ecma_builtin_string_prototype_object_substring */ + +/** + * The common implementation of the String.prototype object's + * 'toLowerCase', 'toLocaleLowerCase', 'toUpperCase', 'toLocalUpperCase' routines + * + * See also: + * ECMA-262 v5, 15.5.4.16 + * ECMA-262 v5, 15.5.4.17 + * ECMA-262 v5, 15.5.4.18 + * ECMA-262 v5, 15.5.4.19 + * + * Helper function to convert a string to upper or lower case. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_conversion_helper (ecma_string_t *input_string_p, /**< this argument */ + bool lower_case) /**< convert to lower (true) + * or upper (false) case */ +{ + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + ECMA_STRING_TO_UTF8_STRING (input_string_p, input_start_p, input_start_size); + + const lit_utf8_byte_t *input_curr_p = input_start_p; + const lit_utf8_byte_t *input_str_end_p = input_start_p + input_start_size; + + while (input_curr_p < input_str_end_p) + { + lit_code_point_t cp = lit_cesu8_read_next (&input_curr_p); + + if (lit_is_code_point_utf16_high_surrogate (cp) && input_curr_p < input_str_end_p) + { + const ecma_char_t next_ch = lit_cesu8_peek_next (input_curr_p); + if (lit_is_code_point_utf16_low_surrogate (next_ch)) + { + cp = lit_convert_surrogate_pair_to_code_point ((ecma_char_t) cp, next_ch); + input_curr_p += LIT_UTF8_MAX_BYTES_IN_CODE_UNIT; + } + } + + if (lower_case) + { + lit_char_to_lower_case (cp, &builder); + } + else + { + lit_char_to_upper_case (cp, &builder); + } + } + + ECMA_FINALIZE_UTF8_STRING (input_start_p, input_start_size); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_string_prototype_object_conversion_helper */ + +/** + * The String.prototype object's 'trim' routine + * + * See also: + * ECMA-262 v5, 15.5.4.20 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_trim (ecma_string_t *original_string_p) /**< this argument */ +{ + ecma_string_t *trimmed_string_p = ecma_string_trim (original_string_p); + + return ecma_make_string_value (trimmed_string_p); +} /* ecma_builtin_string_prototype_object_trim */ + +/** + * The String.prototype object's 'repeat' routine + * + * See also: + * ECMA-262 v6, 21.1.3.13 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_repeat (ecma_string_t *original_string_p, /**< this argument */ + ecma_value_t repeat) /**< times to repeat */ +{ + ecma_string_t *ret_string_p; + + /* 4 */ + ecma_number_t count_number; + ecma_value_t count_value = ecma_op_to_integer (repeat, &count_number); + + /* 5 */ + if (ECMA_IS_VALUE_ERROR (count_value)) + { + return count_value; + } + + int32_t repeat_count = ecma_number_to_int32 (count_number); + + bool isNan = ecma_number_is_nan (count_number); + + /* 6, 7 */ + if (count_number < 0 || (!isNan && ecma_number_is_infinity (count_number))) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_COUNT_VALUE); + } + + lit_utf8_size_t size = ecma_string_get_size (original_string_p); + + if (repeat_count == 0 || size == 0 || isNan) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + if ((uint32_t) repeat_count >= (ECMA_STRING_SIZE_LIMIT / size)) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_STRING_); + } + + lit_utf8_size_t total_size = size * (lit_utf8_size_t) repeat_count; + + JMEM_DEFINE_LOCAL_ARRAY (str_buffer, total_size, lit_utf8_byte_t); + + ecma_string_to_cesu8_bytes (original_string_p, str_buffer, size); + lit_utf8_byte_t *buffer_ptr = str_buffer + size; + + for (int32_t n = 1; n < repeat_count; n++) + { + memcpy (buffer_ptr, str_buffer, size); + buffer_ptr += size; + } + + ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_ptr - str_buffer)); + JMEM_FINALIZE_LOCAL_ARRAY (str_buffer); + + return ecma_make_string_value (ret_string_p); +} /* ecma_builtin_string_prototype_object_repeat */ + +/** + * The String.prototype object's 'codePointAt' routine + * + * See also: + * ECMA-262 v6, 21.1.3.3 + * + * @return lit_code_point_t + */ +static ecma_value_t +ecma_builtin_string_prototype_object_code_point_at (ecma_string_t *this_string_p, /**< this argument */ + ecma_value_t pos) /**< given position */ +{ + ecma_number_t pos_num; + ecma_value_t error = ecma_op_to_integer (pos, &pos_num); + + if (ECMA_IS_VALUE_ERROR (error)) + { + return error; + } + + lit_utf8_size_t length = ecma_string_get_length (this_string_p); + + if (pos_num < 0 || pos_num >= length) + { + return ECMA_VALUE_UNDEFINED; + } + + uint32_t index = (uint32_t) pos_num; + + ecma_char_t first = ecma_string_get_char_at_pos (this_string_p, index); + + if (first < LIT_UTF16_HIGH_SURROGATE_MIN || first > LIT_UTF16_HIGH_SURROGATE_MAX || index + 1 == length) + { + return ecma_make_uint32_value (first); + } + + ecma_char_t second = ecma_string_get_char_at_pos (this_string_p, index + 1); + + if (second < LIT_UTF16_LOW_SURROGATE_MARKER || second > LIT_UTF16_LOW_SURROGATE_MAX) + { + return ecma_make_uint32_value (first); + } + + return ecma_make_uint32_value (lit_convert_surrogate_pair_to_code_point (first, second)); +} /* ecma_builtin_string_prototype_object_code_point_at */ + +#if JERRY_BUILTIN_ANNEXB + +/** + * The String.prototype object's 'substr' routine + * + * See also: + * ECMA-262 v5, B.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_substr (ecma_string_t *this_string_p, /**< this argument */ + ecma_value_t start, /**< routine's first argument */ + ecma_value_t length) /**< routine's second argument */ +{ + /* 2. */ + ecma_number_t start_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (start, &start_num))) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + ecma_number_t length_num = ecma_number_make_infinity (false); + + if (!ecma_is_value_undefined (length)) + { + ecma_number_t len; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (length, &len))) + { + return ECMA_VALUE_ERROR; + } + + length_num = ecma_number_is_nan (len) ? 0 : len; + } + + /* 4. */ + lit_utf8_size_t this_len = ecma_string_get_length (this_string_p); + + /* 5. */ + uint32_t from = (uint32_t) ((start_num < 0) ? JERRY_MAX (this_len + start_num, 0) : start_num); + + if (from > this_len) + { + from = this_len; + } + + /* 6. */ + ecma_number_t to_num = JERRY_MIN (JERRY_MAX (length_num, 0), this_len - from); + + /* 7. */ + uint32_t to = from + (uint32_t) to_num; + + /* 8. */ + ecma_string_t *new_str_p = ecma_string_substr (this_string_p, from, to); + return ecma_make_string_value (new_str_p); +} /* ecma_builtin_string_prototype_object_substr */ + +#endif /* JERRY_BUILTIN_ANNEXB */ + +/** + * The String.prototype object's @@iterator routine + * + * See also: + * ECMA-262 v6, 21.1.3.27 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_iterator (ecma_value_t to_string) /**< this argument */ +{ + return ecma_op_create_iterator_object (ecma_copy_value (to_string), + ecma_builtin_get (ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE), + ECMA_OBJECT_CLASS_STRING_ITERATOR, + ECMA_ITERATOR_VALUES); +} /* ecma_builtin_string_prototype_object_iterator */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_string_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + if (builtin_routine_id <= ECMA_STRING_PROTOTYPE_VALUE_OF) + { + return ecma_builtin_string_prototype_object_to_string (this_arg); + } + + if (!ecma_op_require_object_coercible (this_arg)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t arg1 = arguments_list_p[0]; + ecma_value_t arg2 = arguments_list_p[1]; + +#if JERRY_BUILTIN_REGEXP + if (builtin_routine_id == ECMA_STRING_PROTOTYPE_MATCH) + { + return ecma_builtin_string_prototype_object_match (this_arg, arg1); + } + + if (builtin_routine_id == ECMA_STRING_PROTOTYPE_MATCH_ALL) + { + return ecma_builtin_string_prototype_object_match_all (this_arg, arg1); + } +#endif /* JERRY_BUILTIN_REGEXP */ + + if (builtin_routine_id <= ECMA_STRING_PROTOTYPE_CHAR_CODE_AT) + { + return ecma_builtin_string_prototype_char_at_helper (this_arg, + arg1, + builtin_routine_id == ECMA_STRING_PROTOTYPE_CHAR_CODE_AT); + } + +#if JERRY_BUILTIN_REGEXP + if (builtin_routine_id == ECMA_STRING_PROTOTYPE_REPLACE) + { + return ecma_builtin_string_prototype_object_replace_helper (this_arg, arg1, arg2, false); + } + + else if (builtin_routine_id == ECMA_STRING_PROTOTYPE_REPLACE_ALL) + { + return ecma_builtin_string_prototype_object_replace_helper (this_arg, arg1, arg2, true); + } +#endif /* JERRY_BUILTIN_REGEXP */ + + ecma_string_t *string_p = ecma_op_to_string (this_arg); + + if (JERRY_UNLIKELY (string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t to_string_val = ecma_make_string_value (string_p); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + switch (builtin_routine_id) + { + case ECMA_STRING_PROTOTYPE_CONCAT: + { + ret_value = ecma_builtin_string_prototype_object_concat (string_p, arguments_list_p, arguments_number); + break; + } + case ECMA_STRING_PROTOTYPE_SLICE: + { + ret_value = ecma_builtin_string_prototype_object_slice (string_p, arg1, arg2); + break; + } + case ECMA_STRING_PROTOTYPE_AT: + { + ret_value = ecma_builtin_string_prototype_object_at (string_p, arg1); + break; + } + case ECMA_STRING_PROTOTYPE_LAST_INDEX_OF: + case ECMA_STRING_PROTOTYPE_INDEX_OF: + case ECMA_STRING_PROTOTYPE_STARTS_WITH: + case ECMA_STRING_PROTOTYPE_INCLUDES: + case ECMA_STRING_PROTOTYPE_ENDS_WITH: + { + ecma_string_index_of_mode_t mode; + mode = (ecma_string_index_of_mode_t) (builtin_routine_id - ECMA_STRING_PROTOTYPE_LAST_INDEX_OF); + ret_value = ecma_builtin_helper_string_prototype_object_index_of (string_p, arg1, arg2, mode); + break; + } + case ECMA_STRING_PROTOTYPE_LOCALE_COMPARE: + { + ret_value = ecma_builtin_string_prototype_object_locale_compare (string_p, arg1); + break; + } +#if JERRY_BUILTIN_REGEXP + case ECMA_STRING_PROTOTYPE_SEARCH: + { + ret_value = ecma_builtin_string_prototype_object_search (to_string_val, arg1); + break; + } +#endif /* JERRY_BUILTIN_REGEXP */ + case ECMA_STRING_PROTOTYPE_SPLIT: + { + ret_value = ecma_builtin_string_prototype_object_split (to_string_val, arg1, arg2); + break; + } + case ECMA_STRING_PROTOTYPE_SUBSTRING: + { + ret_value = ecma_builtin_string_prototype_object_substring (string_p, arg1, arg2); + break; + } + case ECMA_STRING_PROTOTYPE_TO_LOWER_CASE: + case ECMA_STRING_PROTOTYPE_TO_LOCAL_LOWER_CASE: + case ECMA_STRING_PROTOTYPE_TO_UPPER_CASE: + case ECMA_STRING_PROTOTYPE_TO_LOCAL_UPPER_CASE: + { + bool is_lower_case = builtin_routine_id <= ECMA_STRING_PROTOTYPE_TO_LOCAL_LOWER_CASE; + ret_value = ecma_builtin_string_prototype_object_conversion_helper (string_p, is_lower_case); + break; + } + case ECMA_STRING_PROTOTYPE_TRIM: + { + ret_value = ecma_builtin_string_prototype_object_trim (string_p); + break; + } +#if JERRY_BUILTIN_ANNEXB + case ECMA_STRING_PROTOTYPE_SUBSTR: + { + ret_value = ecma_builtin_string_prototype_object_substr (string_p, arg1, arg2); + break; + } +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_STRING_PROTOTYPE_REPEAT: + { + ret_value = ecma_builtin_string_prototype_object_repeat (string_p, arg1); + break; + } + case ECMA_STRING_PROTOTYPE_CODE_POINT_AT: + { + ret_value = ecma_builtin_string_prototype_object_code_point_at (string_p, arg1); + break; + } + case ECMA_STRING_PROTOTYPE_ITERATOR: + { + ret_value = ecma_builtin_string_prototype_object_iterator (to_string_val); + break; + } + case ECMA_STRING_PROTOTYPE_PAD_END: + case ECMA_STRING_PROTOTYPE_PAD_START: + { + ret_value = ecma_string_pad (to_string_val, arg1, arg2, builtin_routine_id == ECMA_STRING_PROTOTYPE_PAD_START); + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + + ecma_deref_ecma_string (string_p); + + return ret_value; +} /* ecma_builtin_string_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_STRING */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h new file mode 100644 index 00000000..3e54d262 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h @@ -0,0 +1,85 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * String.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_STRING + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.5.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_STRING, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Number properties: + * (property name, number value) */ + +/* ECMA-262 v5, 15.5.4 (String.prototype is itself a String object whose value is an empty String), 15.5.5.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FIXED) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_STRING_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_STRING_PROTOTYPE_VALUE_OF, 0, 0) +ROUTINE (LIT_MAGIC_STRING_CONCAT, ECMA_STRING_PROTOTYPE_CONCAT, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_SLICE, ECMA_STRING_PROTOTYPE_SLICE, 2, 2) +ROUTINE (LIT_MAGIC_STRING_AT, ECMA_STRING_PROTOTYPE_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_STRING_PROTOTYPE_INDEX_OF, 2, 1) +ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ECMA_STRING_PROTOTYPE_LAST_INDEX_OF, 2, 1) +ROUTINE (LIT_MAGIC_STRING_CHAR_AT_UL, ECMA_STRING_PROTOTYPE_CHAR_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_CHAR_CODE_AT_UL, ECMA_STRING_PROTOTYPE_CHAR_CODE_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOCALE_COMPARE_UL, ECMA_STRING_PROTOTYPE_LOCALE_COMPARE, 1, 1) + +#if JERRY_BUILTIN_REGEXP +ROUTINE (LIT_MAGIC_STRING_MATCH, ECMA_STRING_PROTOTYPE_MATCH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_REPLACE, ECMA_STRING_PROTOTYPE_REPLACE, 2, 2) +ROUTINE (LIT_MAGIC_STRING_REPLACE_ALL, ECMA_STRING_PROTOTYPE_REPLACE_ALL, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SEARCH, ECMA_STRING_PROTOTYPE_SEARCH, 1, 1) +#endif /* JERRY_BUILTIN_REGEXP */ + +ROUTINE (LIT_MAGIC_STRING_SPLIT, ECMA_STRING_PROTOTYPE_SPLIT, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SUBSTRING, ECMA_STRING_PROTOTYPE_SUBSTRING, 2, 2) +ROUTINE (LIT_MAGIC_STRING_TO_LOWER_CASE_UL, ECMA_STRING_PROTOTYPE_TO_LOWER_CASE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_LOWER_CASE_UL, ECMA_STRING_PROTOTYPE_TO_LOCAL_LOWER_CASE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_UPPER_CASE_UL, ECMA_STRING_PROTOTYPE_TO_UPPER_CASE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_UPPER_CASE_UL, ECMA_STRING_PROTOTYPE_TO_LOCAL_UPPER_CASE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TRIM, ECMA_STRING_PROTOTYPE_TRIM, 0, 0) + +#if JERRY_BUILTIN_ANNEXB +ROUTINE (LIT_MAGIC_STRING_SUBSTR, ECMA_STRING_PROTOTYPE_SUBSTR, 2, 2) +#endif /* JERRY_BUILTIN_ANNEXB */ + +ROUTINE (LIT_MAGIC_STRING_REPEAT, ECMA_STRING_PROTOTYPE_REPEAT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_STARTS_WITH, ECMA_STRING_PROTOTYPE_STARTS_WITH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_INCLUDES, ECMA_STRING_PROTOTYPE_INCLUDES, 2, 1) +ROUTINE (LIT_MAGIC_STRING_ENDS_WITH, ECMA_STRING_PROTOTYPE_ENDS_WITH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_CODE_POINT_AT, ECMA_STRING_PROTOTYPE_CODE_POINT_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PAD_START, ECMA_STRING_PROTOTYPE_PAD_START, 2, 1) +ROUTINE (LIT_MAGIC_STRING_PAD_END, ECMA_STRING_PROTOTYPE_PAD_END, 2, 1) +ROUTINE (LIT_GLOBAL_SYMBOL_ITERATOR, ECMA_STRING_PROTOTYPE_ITERATOR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_MATCH_ALL, ECMA_STRING_PROTOTYPE_MATCH_ALL, 1, 1) + +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_START, LIT_MAGIC_STRING_TRIM_START, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_LEFT, LIT_MAGIC_STRING_TRIM_START, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_END, LIT_MAGIC_STRING_TRIM_END, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_RIGHT, LIT_MAGIC_STRING_TRIM_END, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_STRING */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.cpp new file mode 100644 index 00000000..0da8ee1e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.cpp @@ -0,0 +1,430 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" +#include "ecma-symbol-object.h" + +#include "jrt.h" +#include "lit-strings.h" + +#if JERRY_BUILTIN_STRING + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_STRING_ROUTINE_START = 0, + ECMA_BUILTIN_STRING_OBJECT_FROM_CHAR_CODE, + ECMA_BUILTIN_STRING_OBJECT_FROM_CODE_POINT, + ECMA_BUILTIN_STRING_OBJECT_RAW, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-string.inc.h" +#define BUILTIN_UNDERSCORED_ID string +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup string ECMA String object built-in + * @{ + */ + +/** + * The String object's 'fromCharCode' routine + * + * See also: + * ECMA-262 v5, 15.5.3.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_object_from_char_code (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (args_number == 0) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + lit_utf8_size_t utf8_buf_size = args_number * LIT_CESU8_MAX_BYTES_IN_CODE_UNIT; + ecma_string_t *ret_string_p = NULL; + bool isError = false; + + JMEM_DEFINE_LOCAL_ARRAY (utf8_buf_p, utf8_buf_size, lit_utf8_byte_t); + + lit_utf8_size_t utf8_buf_used = 0; + + for (uint32_t arg_index = 0; arg_index < args_number; arg_index++) + { + ecma_number_t arg_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (args[arg_index], &arg_num))) + { + isError = true; + break; + } + + uint32_t uint32_char_code = ecma_number_to_uint32 (arg_num); + ecma_char_t code_unit = (uint16_t) uint32_char_code; + + JERRY_ASSERT (utf8_buf_used <= utf8_buf_size - LIT_UTF8_MAX_BYTES_IN_CODE_UNIT); + utf8_buf_used += lit_code_unit_to_utf8 (code_unit, utf8_buf_p + utf8_buf_used); + JERRY_ASSERT (utf8_buf_used <= utf8_buf_size); + } + + if (!isError) + { + ret_string_p = ecma_new_ecma_string_from_utf8 (utf8_buf_p, utf8_buf_used); + } + + JMEM_FINALIZE_LOCAL_ARRAY (utf8_buf_p); + + return isError ? ECMA_VALUE_ERROR : ecma_make_string_value (ret_string_p); +} /* ecma_builtin_string_object_from_char_code */ + +/** + * The String object's 'raw' routine + * + * See also: + * ECMA-262 v6, 21.1.2.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_object_raw (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + /* 1 - 2. */ + const ecma_value_t *substitutions; + uint32_t number_of_substitutions; + ecma_length_t next_index; + ecma_stringbuilder_t builder; + + if (args_number > 1) + { + substitutions = args + 1; + number_of_substitutions = args_number - 1; + } + else + { + substitutions = NULL; + number_of_substitutions = 0; + } + + /* 3. */ + ecma_value_t templated = args_number > 0 ? args[0] : ECMA_VALUE_UNDEFINED; + + ecma_value_t cooked = ecma_op_to_object (templated); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (cooked)) + { + return cooked; + } + + ecma_object_t *cooked_obj_p = ecma_get_object_from_value (cooked); + + /* 5. */ + ecma_value_t raw = ecma_op_object_get_by_magic_id (cooked_obj_p, LIT_MAGIC_STRING_RAW); + + ecma_deref_object (cooked_obj_p); + + if (ECMA_IS_VALUE_ERROR (raw)) + { + return raw; + } + + ecma_value_t raw_obj = ecma_op_to_object (raw); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (raw_obj)) + { + ecma_free_value (raw); + return raw_obj; + } + + ecma_object_t *raw_obj_p = ecma_get_object_from_value (raw_obj); + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + /* 7 - 8. */ + ecma_length_t literal_segments; + if (ECMA_IS_VALUE_ERROR (ecma_op_object_get_length (raw_obj_p, &literal_segments))) + { + goto cleanup; + } + + /* 9. */ + if (literal_segments == 0) + { + ret_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + goto cleanup; + } + + /* 10. */ + builder = ecma_stringbuilder_create (); + + /* 11. */ + next_index = 0; + + /* 12. */ + while (true) + { + /* 12.a,b */ + ecma_value_t next_seg = ecma_op_object_get_by_index (raw_obj_p, next_index); + + if (ECMA_IS_VALUE_ERROR (next_seg)) + { + goto builder_cleanup; + } + + ecma_string_t *next_seg_srt_p = ecma_op_to_string (next_seg); + + /* 12.c */ + if (JERRY_UNLIKELY (next_seg_srt_p == NULL)) + { + ecma_free_value (next_seg); + goto builder_cleanup; + } + + /* 12.d */ + ecma_stringbuilder_append (&builder, next_seg_srt_p); + + ecma_deref_ecma_string (next_seg_srt_p); + ecma_free_value (next_seg); + + /* 12.e */ + if (next_index + 1 == literal_segments) + { + ret_value = ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + goto cleanup; + } + + /* 12.f-g */ + if (next_index >= number_of_substitutions) + { + next_index++; + continue; + } + + /* 12.h */ + ecma_string_t *next_sub_p = ecma_op_to_string (substitutions[next_index]); + + /* 12.i */ + if (JERRY_UNLIKELY (next_sub_p == NULL)) + { + goto builder_cleanup; + } + + /* 12.j */ + ecma_stringbuilder_append (&builder, next_sub_p); + ecma_deref_ecma_string (next_sub_p); + + /* 12.k */ + next_index++; + } + +builder_cleanup: + ecma_stringbuilder_destroy (&builder); + +cleanup: + ecma_deref_object (raw_obj_p); + ecma_free_value (raw); + + return ret_value; +} /* ecma_builtin_string_object_raw */ + +/** + * The String object's 'fromCodePoint' routine + * + * See also: + * ECMA-262 v6, 21.1.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_object_from_code_point (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (args_number == 0) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + for (uint32_t index = 0; index < args_number; index++) + { + ecma_number_t to_number_num; + ecma_value_t to_number_value = ecma_op_to_number (args[index], &to_number_num); + + if (ECMA_IS_VALUE_ERROR (to_number_value)) + { + ecma_stringbuilder_destroy (&builder); + return to_number_value; + } + + if (!ecma_op_is_integer (to_number_num)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_range_error (ECMA_ERR_INVALID_CODE_POINT_ERROR); + } + + ecma_free_value (to_number_value); + + if (to_number_num < 0 || to_number_num > LIT_UNICODE_CODE_POINT_MAX) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_range_error (ECMA_ERR_INVALID_CODE_POINT); + } + + lit_code_point_t code_point = (lit_code_point_t) to_number_num; + + ecma_char_t converted_cp[2]; + uint8_t encoded_size = lit_utf16_encode_code_point (code_point, converted_cp); + + for (uint8_t i = 0; i < encoded_size; i++) + { + ecma_stringbuilder_append_char (&builder, converted_cp[i]); + } + } + + ecma_string_t *ret_str_p = ecma_stringbuilder_finalize (&builder); + + return ecma_make_string_value (ret_str_p); +} /* ecma_builtin_string_object_from_code_point */ + +/** + * Handle calling [[Call]] of built-in String object + * + * See also: + * ECMA-262 v6, 21.1.1.1 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_string_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 1. */ + if (arguments_list_len == 0) + { + ret_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + /* 2.a */ + else if (ecma_is_value_symbol (arguments_list_p[0])) + { + ret_value = ecma_get_symbol_descriptive_string (arguments_list_p[0]); + } + /* 2.b */ + else + { + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ret_value = ecma_make_string_value (str_p); + } + + return ret_value; +} /* ecma_builtin_string_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in String object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_string_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_string_object (arguments_list_p, arguments_list_len); +} /* ecma_builtin_string_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_string_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (this_arg); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_STRING_OBJECT_FROM_CHAR_CODE: + { + return ecma_builtin_string_object_from_char_code (arguments_list_p, arguments_number); + } + case ECMA_BUILTIN_STRING_OBJECT_FROM_CODE_POINT: + { + return ecma_builtin_string_object_from_code_point (arguments_list_p, arguments_number); + } + case ECMA_BUILTIN_STRING_OBJECT_RAW: + { + return ecma_builtin_string_object_raw (arguments_list_p, arguments_number); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_string_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_STRING */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h new file mode 100644 index 00000000..2178acf1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * String built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_STRING + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.7.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_STRING_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_STRING_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_FROM_CHAR_CODE_UL, ECMA_BUILTIN_STRING_OBJECT_FROM_CHAR_CODE, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_FROM_CODE_POINT_UL, ECMA_BUILTIN_STRING_OBJECT_FROM_CODE_POINT, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_RAW, ECMA_BUILTIN_STRING_OBJECT_RAW, NON_FIXED, 1) + +#endif /* JERRY_BUILTIN_STRING */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.cpp new file mode 100644 index 00000000..df4c9d5f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.cpp @@ -0,0 +1,111 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-symbol-object.h" + +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_SYMBOL_PROTOTYPE_ROUTINE_START = 0, + ECMA_SYMBOL_PROTOTYPE_VALUE_OF, /**< ECMA-262 v11, 19.4.3.4 */ + ECMA_SYMBOL_PROTOTYPE_TO_PRIMITIVE, /**< ECMA-262 v11, 19.4.3.5 */ + ECMA_SYMBOL_PROTOTYPE_TO_STRING, /**< ECMA-262 v11, 19.4.3.3 */ + ECMA_SYMBOL_PROTOTYPE_DESCRIPTION, /**< ECMA-262 v11, 19.4.3.2 */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-symbol-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID symbol_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup symbolprototype ECMA Symbol prototype object built-in + * @{ + */ + +/** + * Dispatcher of the Symbol built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_symbol_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list, arguments_number); + + ecma_value_t sym = ecma_symbol_this_value (this_arg); + + if (ECMA_IS_VALUE_ERROR (sym)) + { + return sym; + } + + if (builtin_routine_id < ECMA_SYMBOL_PROTOTYPE_TO_STRING) + { + return ecma_copy_value (sym); + } + + if (builtin_routine_id == ECMA_SYMBOL_PROTOTYPE_TO_STRING) + { + return ecma_get_symbol_descriptive_string (sym); + } + + JERRY_ASSERT (builtin_routine_id == ECMA_SYMBOL_PROTOTYPE_DESCRIPTION); + ecma_string_t *symbol_p = ecma_get_symbol_from_value (sym); + ecma_value_t desc = ecma_get_symbol_description (symbol_p); + if (ecma_is_value_undefined (desc)) + { + return desc; + } + + ecma_string_t *desc_p = ecma_get_string_from_value (desc); + ecma_ref_ecma_string (desc_p); + return desc; +} /* ecma_builtin_symbol_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h new file mode 100644 index 00000000..9b0daa0c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Symbol prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_SYMBOL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_SYMBOL_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_SYMBOL_PROTOTYPE_VALUE_OF, 0, 0) +ROUTINE_CONFIGURABLE_ONLY (LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, ECMA_SYMBOL_PROTOTYPE_TO_PRIMITIVE, 0, 1) + +/* ECMA-262 v6, 19.4.3.4 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_SYMBOL_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262, v11, 19.4.3.2 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_DESCRIPTION, ECMA_SYMBOL_PROTOTYPE_DESCRIPTION, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.cpp new file mode 100644 index 00000000..3ce75f9b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.cpp @@ -0,0 +1,253 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-literal-storage.h" +#include "ecma-objects.h" +#include "ecma-symbol-object.h" + +#include "jcontext.h" +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-symbol.inc.h" +#define BUILTIN_UNDERSCORED_ID symbol +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup symbol ECMA Symbol object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Symbol object. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_symbol_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_symbol (arguments_list_p, arguments_list_len); +} /* ecma_builtin_symbol_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Symbol object. + * + * Symbol constructor is not intended to be used + * with the new operator or to be subclassed. + * + * See also: + * ECMA-262 v6, 19.4.1 + * @return ecma value + */ +ecma_value_t +ecma_builtin_symbol_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_SYMBOL_IS_NOT_A_CONSTRUCTOR); +} /* ecma_builtin_symbol_dispatch_construct */ + +/** + * Helper function for Symbol object's 'for' and `keyFor` + * routines common parts + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_for_helper (ecma_value_t value_to_find) /**< symbol or ecma-string */ +{ + ecma_string_t *string_p; + + bool is_for = ecma_is_value_string (value_to_find); + + if (is_for) + { + string_p = ecma_get_string_from_value (value_to_find); + } + else + { + string_p = ecma_get_symbol_from_value (value_to_find); + } + + jmem_cpointer_t symbol_list_cp = JERRY_CONTEXT (symbol_list_first_cp); + jmem_cpointer_t *empty_cpointer_p = NULL; + + while (symbol_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *symbol_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, symbol_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (symbol_list_p->values[i] != JMEM_CP_NULL) + { + ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, symbol_list_p->values[i]); + + if (is_for) + { + ecma_value_t symbol_desc = ecma_get_symbol_description (value_p); + + if (ecma_is_value_undefined (symbol_desc)) + { + ecma_ref_ecma_string (value_p); + return ecma_make_symbol_value (value_p); + } + + ecma_string_t *symbol_desc_p = ecma_get_string_from_value (symbol_desc); + + if (ecma_compare_ecma_strings (symbol_desc_p, string_p)) + { + /* The current symbol's descriptor matches with the value_to_find, + so the value is no longer needed. */ + ecma_deref_ecma_string (string_p); + return ecma_copy_value (ecma_make_symbol_value (value_p)); + } + } + else + { + if (string_p == value_p) + { + ecma_value_t symbol_desc = ecma_get_symbol_description (string_p); + + if (ecma_is_value_undefined (symbol_desc)) + { + return symbol_desc; + } + + ecma_string_t *symbol_desc_p = ecma_get_string_from_value (symbol_desc); + ecma_ref_ecma_string (symbol_desc_p); + return symbol_desc; + } + } + } + else + { + if (empty_cpointer_p == NULL) + { + empty_cpointer_p = symbol_list_p->values + i; + } + } + } + + symbol_list_cp = symbol_list_p->next_cp; + } + + if (!is_for) + { + return ECMA_VALUE_UNDEFINED; + } + + /* There was no matching, sp a new symbol should be added the the global symbol list. The symbol creation requires + an extra reference to the descriptor string, but this reference has already been added. */ + ecma_string_t *new_symbol_p = ecma_new_symbol_from_descriptor_string (value_to_find); + + jmem_cpointer_t result; + JMEM_CP_SET_NON_NULL_POINTER (result, new_symbol_p); + + if (empty_cpointer_p != NULL) + { + *empty_cpointer_p = result; + return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); + } + + ecma_lit_storage_item_t *new_item_p; + new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); + + new_item_p->values[0] = result; + for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + new_item_p->values[i] = JMEM_CP_NULL; + } + + new_item_p->next_cp = JERRY_CONTEXT (symbol_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (symbol_list_first_cp), new_item_p); + + return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); +} /* ecma_builtin_symbol_for_helper */ + +/** + * The Symbol object's 'for' routine + * + * See also: + * ECMA-262 v6, 19.4.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_for (ecma_value_t this_arg, /**< this argument */ + ecma_value_t key) /**< key string */ +{ + JERRY_UNUSED (this_arg); + ecma_string_t *string_desc_p = ecma_op_to_string (key); + + /* 1. */ + if (JERRY_UNLIKELY (string_desc_p == NULL)) + { + /* 2. */ + return ECMA_VALUE_ERROR; + } + + return ecma_builtin_symbol_for_helper (ecma_make_string_value (string_desc_p)); +} /* ecma_builtin_symbol_for */ + +/** + * The Symbol object's 'keyFor' routine + * + * See also: + * ECMA-262 v6, 19.4.2. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_key_for (ecma_value_t this_arg, /**< this argument */ + ecma_value_t symbol) /**< symbol */ +{ + JERRY_UNUSED (this_arg); + + /* 1. */ + if (!ecma_is_value_symbol (symbol)) + { + return ecma_raise_type_error (ECMA_ERR_THE_GIVEN_ARGUMENT_IS_NOT_A_SYMBOL); + } + + /* 2-4. */ + return ecma_builtin_symbol_for_helper (symbol); +} /* ecma_builtin_symbol_key_for */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h new file mode 100644 index 00000000..9fecbd4f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h @@ -0,0 +1,80 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Symbol built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 19.4.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_SYMBOL_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 19.4.2.7 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v10, 19.4.2.1 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_ASYNC_ITERATOR, LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR) + +/* ECMA-262 v6, 19.4.2.2 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_HAS_INSTANCE, LIT_GLOBAL_SYMBOL_HAS_INSTANCE) + +/* ECMA-262 v6, 19.4.2.3 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE) + +/* ECMA-262 v6, 19.4.2.4 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_ITERATOR, LIT_GLOBAL_SYMBOL_ITERATOR) + +/* ECMA-262 v6, 19.4.2.6 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_MATCH, LIT_GLOBAL_SYMBOL_MATCH) + +/* ECMA-262 v6, 19.4.2.8 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_REPLACE, LIT_GLOBAL_SYMBOL_REPLACE) + +/* ECMA-262 v6, 19.4.2.9 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_SEARCH, LIT_GLOBAL_SYMBOL_SEARCH) + +/* ECMA-262 v6, 19.4.2.10 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_SPECIES, LIT_GLOBAL_SYMBOL_SPECIES) + +/* ECMA-262 v6, 19.4.2.11 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_SPLIT, LIT_GLOBAL_SYMBOL_SPLIT) + +/* ECMA-262 v6, 19.4.2.12 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_TO_PRIMITIVE, LIT_GLOBAL_SYMBOL_TO_PRIMITIVE) + +/* ECMA-262 v6, 19.4.2.13 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_TO_STRING_TAG, LIT_GLOBAL_SYMBOL_TO_STRING_TAG) + +/* ECMA-262 v6, 19.4.2.14 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_UNSCOPABLES, LIT_GLOBAL_SYMBOL_UNSCOPABLES) + +/* ECMA-262 v11, 19.4.2.8 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_MATCH_ALL, LIT_GLOBAL_SYMBOL_MATCH_ALL) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_FOR, ecma_builtin_symbol_for, 1, 1) +ROUTINE (LIT_MAGIC_STRING_KEY_FOR, ecma_builtin_symbol_key_for, 1, 1) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.cpp new file mode 100644 index 00000000..2e5e7b8c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-syntaxerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID syntax_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.inc.h new file mode 100644 index 00000000..670efc1d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * SyntaxError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_SYNTAX_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_SYNTAX_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.cpp new file mode 100644 index 00000000..449c0db6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-syntaxerror.inc.h" +#define BUILTIN_UNDERSCORED_ID syntax_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup syntaxerror ECMA SyntaxError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in SyntaxError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_syntax_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_SYNTAX, arguments_list_p, arguments_list_len); +} /* ecma_builtin_syntax_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in SyntaxError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_syntax_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_syntax_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_syntax_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h new file mode 100644 index 00000000..bee730cf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * SyntaxError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_SYNTAX_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.cpp new file mode 100644 index 00000000..253a8deb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.cpp @@ -0,0 +1,82 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-type-error-thrower.inc.h" +#define BUILTIN_UNDERSCORED_ID type_error_thrower +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup type_error_thrower ECMA [[ThrowTypeError]] object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in [[ThrowTypeError]] object + * + * See also: + * ECMA-262 v5, 13.2.3 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_type_error_thrower_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CANNOT_ACCESS_CALLER_CALLE_ARGUMENTS); +} /* ecma_builtin_type_error_thrower_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in [[ThrowTypeError]] object + * + * See also: + * ECMA-262 v5, 13.2.3 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_type_error_thrower_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_builtin_type_error_thrower_dispatch_call (arguments_list_p, arguments_list_len); +} /* ecma_builtin_type_error_thrower_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.inc.h new file mode 100644 index 00000000..e44c8aba --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.inc.h @@ -0,0 +1,31 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * [[ThrowTypeError]] description + * + * See also: ECMA-262 v5, 13.2.3 + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_FIXED) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.cpp new file mode 100644 index 00000000..9e9971a1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-typeerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID type_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.inc.h new file mode 100644 index 00000000..4d0b4f28 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * TypeError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_TYPE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_TYPE_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.cpp new file mode 100644 index 00000000..c18cdaad --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-typeerror.inc.h" +#define BUILTIN_UNDERSCORED_ID type_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup typeerror ECMA TypeError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in TypeError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_type_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_TYPE, arguments_list_p, arguments_list_len); +} /* ecma_builtin_type_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in TypeError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_type_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_type_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_type_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h new file mode 100644 index 00000000..d2bb8e33 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * TypeError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_TYPE_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.cpp new file mode 100644 index 00000000..26acbaba --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-urierror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID uri_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.inc.h new file mode 100644 index 00000000..2b6fd89c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * UriError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_URI_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_URI_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.cpp new file mode 100644 index 00000000..1c7333e9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-urierror.inc.h" +#define BUILTIN_UNDERSCORED_ID uri_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup urierror ECMA UriError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in UriError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uri_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_URI, arguments_list_p, arguments_list_len); +} /* ecma_builtin_uri_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in UriError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uri_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_uri_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_uri_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h new file mode 100644 index 00000000..ed1d3d5a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * UriError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_URI_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.cpp new file mode 100644 index 00000000..2a8d6768 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.cpp @@ -0,0 +1,65 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakmap-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID weakmap_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakmap ECMA WeakMap object built-in + * @{ + */ +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_weakmap_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + return ecma_builtin_container_dispatch_routine (builtin_routine_id, + this_arg, + arguments_list_p, + LIT_MAGIC_STRING_WEAKMAP_UL); +} /* ecma_builtin_weakmap_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.inc.h new file mode 100644 index 00000000..75d61770 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.inc.h @@ -0,0 +1,42 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakMap.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.3.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_WEAKMAP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.3.3.6 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_WEAKMAP_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_DELETE, ECMA_CONTAINER_ROUTINE_DELETE_WEAK, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET, ECMA_CONTAINER_ROUTINE_GET, 1, 1) +ROUTINE (LIT_MAGIC_STRING_HAS, ECMA_CONTAINER_ROUTINE_HAS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET, ECMA_CONTAINER_ROUTINE_SET, 2, 2) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.cpp new file mode 100644 index 00000000..afc2f667 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.cpp @@ -0,0 +1,74 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-container-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakmap.inc.h" +#define BUILTIN_UNDERSCORED_ID weakmap +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakmap ECMA WeakMap object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in WeakMap object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakmap_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_WEAKMAP_REQUIRES_NEW); +} /* ecma_builtin_weakmap_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in WeakMap object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakmap_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_container_create (arguments_list_p, + arguments_list_len, + LIT_MAGIC_STRING_WEAKMAP_UL, + ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE); +} /* ecma_builtin_weakmap_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.inc.h new file mode 100644 index 00000000..8bf9843f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakMap built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.3.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_WEAKMAP_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.3.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.cpp new file mode 100644 index 00000000..4b4caf26 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.cpp @@ -0,0 +1,114 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-container-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_WEAKREF + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_WEAKREF_PROTOTYPE_OBJECT_ROUTINE_START = 0, + ECMA_BUILTIN_WEAKREF_PROTOTYPE_OBJECT_DEREF +}; + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakref-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID weakref_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakref ECMA WeakRef object built-in + * @{ + */ + +/** + * Deref checks weakRef target + * + * @return weakRef target + * error - otherwise + */ +static ecma_value_t +ecma_builtin_weakref_prototype_object_deref (ecma_value_t this_arg) /**< this argument */ +{ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_TARGET_IS_NOT_OBJECT); + } + + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + ecma_extended_object_t *this_ext_obj = (ecma_extended_object_t *) object_p; + + if (!ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_WEAKREF)) + { + return ecma_raise_type_error (ECMA_ERR_TARGET_IS_NOT_WEAKREF); + } + + return ecma_copy_value (this_ext_obj->u.cls.u3.target); +} /* ecma_builtin_weakref_prototype_object_deref */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_weakref_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_WEAKREF_PROTOTYPE_OBJECT_DEREF: + { + return ecma_builtin_weakref_prototype_object_deref (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_weakref_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_WEAKREF */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.inc.h new file mode 100644 index 00000000..533d3956 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakSet.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_WEAKREF + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_WEAKREF, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_WEAKREF_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_DEREF, ECMA_BUILTIN_WEAKREF_PROTOTYPE_OBJECT_DEREF, 0, 0) + +#endif /* JERRY_BUILTIN_WEAKREF */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.cpp new file mode 100644 index 00000000..bf15aae1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.cpp @@ -0,0 +1,96 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_WEAKREF + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakref.inc.h" +#define BUILTIN_UNDERSCORED_ID weakref +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakref ECMA WeakRef object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in WeakRef object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakref_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_WEAKREF_REQUIRES_NEW); +} /* ecma_builtin_weakref_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in WeakRef object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakref_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + if (arguments_list_len == 0 || !ecma_is_value_object (arguments_list_p[0])) + { + return ecma_raise_type_error (ECMA_ERR_WEAKREF_TARGET_MUST_BE_AN_OBJECT); + } + + JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p) != NULL); + + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_WEAKREF_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *object_p = ecma_create_object (proto_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + ecma_deref_object (proto_p); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.cls.type = ECMA_OBJECT_CLASS_WEAKREF; + ext_obj_p->u.cls.u3.target = arguments_list_p[0]; + ecma_op_object_set_weak (ecma_get_object_from_value (arguments_list_p[0]), object_p); + + return ecma_make_object_value (object_p); +} /* ecma_builtin_weakref_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_WEAKREF */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.inc.h new file mode 100644 index 00000000..d4e6e5b5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakRef built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_WEAKREF + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_WEAKREF_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_WEAKREF_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_WEAKREF */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.cpp new file mode 100644 index 00000000..370c5047 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.cpp @@ -0,0 +1,67 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakset-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID weakset_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakset ECMA WeakSet object built-in + * @{ + */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_weakset_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + return ecma_builtin_container_dispatch_routine (builtin_routine_id, + this_arg, + arguments_list_p, + LIT_MAGIC_STRING_WEAKSET_UL); +} /* ecma_builtin_weakset_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.inc.h new file mode 100644 index 00000000..6221f895 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakSet.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.4.3.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_WEAKSET, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.4.3.5 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_WEAKSET_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_ADD, ECMA_CONTAINER_ROUTINE_ADD, 1, 1) +ROUTINE (LIT_MAGIC_STRING_DELETE, ECMA_CONTAINER_ROUTINE_DELETE_WEAK, 1, 1) +ROUTINE (LIT_MAGIC_STRING_HAS, ECMA_CONTAINER_ROUTINE_HAS, 1, 1) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.cpp new file mode 100644 index 00000000..f30c6c25 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.cpp @@ -0,0 +1,74 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-container-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakset.inc.h" +#define BUILTIN_UNDERSCORED_ID weakset +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakset ECMA WeakSet object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in WeakSet object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakset_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_WEAKSET_REQUIRES_NEW); +} /* ecma_builtin_weakset_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in WeakSet object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakset_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_container_create (arguments_list_p, + arguments_list_len, + LIT_MAGIC_STRING_WEAKSET_UL, + ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE); +} /* ecma_builtin_weakset_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.inc.h new file mode 100644 index 00000000..8aa16c84 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakSet built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.4.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.4 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_WEAKSET_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.4.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h new file mode 100644 index 00000000..5695e2d8 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h @@ -0,0 +1,98 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BUILTINS_INTERNAL_H +#define ECMA_BUILTINS_INTERNAL_H + +#ifndef ECMA_BUILTINS_INTERNAL +#error "!ECMA_BUILTINS_INTERNAL" +#endif /* !ECMA_BUILTINS_INTERNAL */ + +#include "ecma-builtins.h" +#include "ecma-globals.h" + +/** + * Type of built-in properties. + */ +typedef enum +{ + ECMA_BUILTIN_PROPERTY_SIMPLE, /**< simple value property */ + ECMA_BUILTIN_PROPERTY_NUMBER, /**< number value property */ + ECMA_BUILTIN_PROPERTY_STRING, /**< string value property */ + ECMA_BUILTIN_PROPERTY_SYMBOL, /**< symbol value property */ + ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY, /**< intrinsic routine property */ + ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION, /**< full accessor property with builtin function object + getter/setter pair */ + ECMA_BUILTIN_PROPERTY_OBJECT, /**< builtin object property */ + ECMA_BUILTIN_PROPERTY_ROUTINE, /**< routine property */ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE, /**< full accessor property */ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY, /**< read-only accessor property */ + ECMA_BUILTIN_PROPERTY_END, /**< last property */ +} ecma_builtin_property_type_t; + +/** + * Type of symbolic built-in number types (starting from 256). + */ +typedef enum +{ + ECMA_BUILTIN_NUMBER_MAX = 256, /**< value of ECMA_NUMBER_MAX_VALUE */ + ECMA_BUILTIN_NUMBER_MIN, /**< value of ECMA_NUMBER_MIN_VALUE */ + ECMA_BUILTIN_NUMBER_EPSILON, /**< value of ECMA_NUMBER_EPSILON */ + ECMA_BUILTIN_NUMBER_MAX_SAFE_INTEGER, /**< value of ECMA_NUMBER_MAX_SAFE_INTEGER */ + ECMA_BUILTIN_NUMBER_MIN_SAFE_INTEGER, /**< value of ECMA_NUMBER_MIN_SAFE_INTEGER */ + ECMA_BUILTIN_NUMBER_E, /**< value of ECMA_NUMBER_E */ + ECMA_BUILTIN_NUMBER_PI, /**< value of ECMA_NUMBER_PI */ + ECMA_BUILTIN_NUMBER_LN10, /**< value of ECMA_NUMBER_LN10 */ + ECMA_BUILTIN_NUMBER_LN2, /**< value of ECMA_NUMBER_LN2 */ + ECMA_BUILTIN_NUMBER_LOG2E, /**< value of ECMA_NUMBER_LOG2E */ + ECMA_BUILTIN_NUMBER_LOG10E, /**< value of ECMA_NUMBER_LOG10E */ + ECMA_BUILTIN_NUMBER_SQRT2, /**< value of ECMA_NUMBER_SQRT2 */ + ECMA_BUILTIN_NUMBER_SQRT_1_2, /**< value of ECMA_NUMBER_SQRT_1_2 */ + ECMA_BUILTIN_NUMBER_NAN, /**< result of ecma_number_make_nan () */ + ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY, /**< result of ecma_number_make_infinity (false) */ + ECMA_BUILTIN_NUMBER_NEGATIVE_INFINITY, /**< result of ecma_number_make_infinity (true) */ +} ecma_builtin_number_type_t; + +/** + * Description of built-in properties. + */ +typedef struct +{ + uint16_t magic_string_id; /**< name of the property */ + uint8_t type; /**< type of the property */ + uint8_t attributes; /**< attributes of the property */ + uint16_t value; /**< value of the property */ +} ecma_builtin_property_descriptor_t; + +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + extern const ecma_builtin_property_descriptor_t ecma_builtin_##lowercase_name##_property_descriptor_list[]; \ + ecma_value_t ecma_builtin_##lowercase_name##_dispatch_call (const ecma_value_t *, uint32_t); \ + ecma_value_t ecma_builtin_##lowercase_name##_dispatch_construct (const ecma_value_t *, uint32_t); \ + ecma_value_t ecma_builtin_##lowercase_name##_dispatch_routine (uint8_t builtin_routine_id, \ + ecma_value_t this_arg_value, \ + const ecma_value_t[], \ + uint32_t); +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + extern const ecma_builtin_property_descriptor_t ecma_builtin_##lowercase_name##_property_descriptor_list[]; \ + ecma_value_t ecma_builtin_##lowercase_name##_dispatch_routine (uint8_t builtin_routine_id, \ + ecma_value_t this_arg_value, \ + const ecma_value_t[], \ + uint32_t); +#include "ecma-builtins.inc.h" + +#undef BUILTIN_ROUTINE +#undef BUILTIN + +#endif /* !ECMA_BUILTINS_INTERNAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.cpp new file mode 100644 index 00000000..cae35ad8 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.cpp @@ -0,0 +1,1524 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#include "ecma-alloc.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt-bit-fields.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + */ + +JERRY_STATIC_ASSERT ((((int)ECMA_BUILTIN_ID_GLOBAL) == ((int)ECMA_BUILTIN_OBJECTS_COUNT)), + ecma_builtin_id_global_must_be_the_last_builtin_id); + +/** + * Checks whether the built-in is an ecma_extended_built_in_object_t + */ +#define ECMA_BUILTIN_IS_EXTENDED_BUILT_IN(object_type) \ + ((object_type) == ECMA_OBJECT_TYPE_BUILT_IN_CLASS || (object_type) == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY) + +/** + * Helper definition for ecma_builtin_property_list_references. + */ +typedef const ecma_builtin_property_descriptor_t *ecma_builtin_property_list_reference_t; + +/** + * Definition of built-in dispatch routine function pointer. + */ +typedef ecma_value_t (*ecma_builtin_dispatch_routine_t) (uint8_t builtin_routine_id, + ecma_value_t this_arg, + const ecma_value_t arguments_list[], + uint32_t arguments_number); +/** + * Definition of built-in dispatch call function pointer. + */ +typedef ecma_value_t (*ecma_builtin_dispatch_call_t) (const ecma_value_t arguments_list[], uint32_t arguments_number); +/** + * Definition of a builtin descriptor which contains the builtin object's: + * - prototype objects's id (13-bits) + * - type (3-bits) + * + * Layout: + * + * |----------------------|---------------| + * prototype_id(12) obj_type(4) + */ +typedef uint16_t ecma_builtin_descriptor_t; + +/** + * Bitshift index for get the prototype object's id from a builtin descriptor + */ +#define ECMA_BUILTIN_PROTOTYPE_ID_SHIFT 4 + +/** + * Bitmask for get the object's type from a builtin descriptor + */ +#define ECMA_BUILTIN_OBJECT_TYPE_MASK ((1 << ECMA_BUILTIN_PROTOTYPE_ID_SHIFT) - 1) + +/** + * Create a builtin descriptor value + */ +#define ECMA_MAKE_BUILTIN_DESCRIPTOR(type, proto_id) (((proto_id) << ECMA_BUILTIN_PROTOTYPE_ID_SHIFT) | (type)) + +/** + * List of the built-in descriptors. + */ +static const ecma_builtin_descriptor_t ecma_builtin_descriptors[] = { +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ECMA_MAKE_BUILTIN_DESCRIPTOR (object_type, object_prototype_builtin_id), +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE +#define BUILTIN_ROUTINE(a, b, c, d, e) +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ECMA_MAKE_BUILTIN_DESCRIPTOR (object_type, object_prototype_builtin_id), +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE + /** @endcond */ +}; + +#ifndef JERRY_NDEBUG +/** @cond doxygen_suppress */ +enum +{ + ECMA_BUILTIN_EXTENSIBLE_CHECK = +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + (is_extensible != 0 || builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER) && +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE +#define BUILTIN_ROUTINE(a, b, c, d, e) +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + (is_extensible != 0 || builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER) && +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE + true +}; +/** @endcond */ + +/** + * All the builtin object must be extensible except the ThrowTypeError object. + */ +JERRY_STATIC_ASSERT (ECMA_BUILTIN_EXTENSIBLE_CHECK == true, + ecma_builtin_must_be_extensible_except_the_builtin_thorw_type_error_object); +#endif /* !JERRY_NDEBUG */ + +/** + * List of the built-in routines. + */ +static const ecma_builtin_dispatch_routine_t ecma_builtin_routines[] = { +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_dispatch_routine, +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE +#define BUILTIN_ROUTINE(a, b, c, d, e) +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_dispatch_routine, +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE + /** @endcond */ +}; + +/** + * List of the built-in call functions. + */ +static const ecma_builtin_dispatch_call_t ecma_builtin_call_functions[] = { +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_dispatch_call, +#include "ecma-builtins.inc.h" +#undef BUILTIN_ROUTINE +#undef BUILTIN + /** @endcond */ +}; + +/** + * List of the built-in construct functions. + */ +static const ecma_builtin_dispatch_call_t ecma_builtin_construct_functions[] = { +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_dispatch_construct, +#include "ecma-builtins.inc.h" +#undef BUILTIN_ROUTINE +#undef BUILTIN + /** @endcond */ +}; + +/** + * Property descriptor lists for all built-ins. + */ +static const ecma_builtin_property_list_reference_t ecma_builtin_property_list_references[] = { +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_property_descriptor_list, +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE +#define BUILTIN_ROUTINE(a, b, c, d, e) +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_property_descriptor_list, +#include "ecma-builtins.inc.h" +#undef BUILTIN_ROUTINE +#undef BUILTIN + /** @endcond */ +}; + +/** + * Get the number of properties of a built-in object. + * + * @return the number of properties + */ +static size_t +ecma_builtin_get_property_count (ecma_builtin_id_t builtin_id) /**< built-in ID */ +{ + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; + + const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; + + while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) + { + curr_property_p++; + } + + return (size_t) (curr_property_p - property_list_p); +} /* ecma_builtin_get_property_count */ + +/** + * Check if passed object is a global built-in. + * + * @return true - if the object is a global built-in + * false - otherwise + */ +bool +ecma_builtin_is_global (ecma_object_t *object_p) /**< pointer to an object */ +{ + return (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL + && ((ecma_extended_object_t *) object_p)->u.built_in.id == ECMA_BUILTIN_ID_GLOBAL); +} /* ecma_builtin_is_global */ + +/** + * Get reference to the global object + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to the global object + */ +ecma_object_t * +ecma_builtin_get_global (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (global_object_p) != NULL); + + return (ecma_object_t *) JERRY_CONTEXT (global_object_p); +} /* ecma_builtin_get_global */ + +/** + * Checks whether the given function is a built-in routine + * + * @return true - if the function object is a built-in routine + * false - otherwise + */ +bool +ecma_builtin_function_is_routine (ecma_object_t *func_obj_p) /**< function object */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + return (ext_func_obj_p->u.built_in.routine_id != 0); +} /* ecma_builtin_function_is_routine */ + +#if JERRY_BUILTIN_REALMS + +/** + * Get reference to the realm provided by another built-in object + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to the global object + */ +static ecma_global_object_t * +ecma_builtin_get_realm (ecma_object_t *builtin_object_p) /**< built-in object */ +{ + ecma_object_type_t object_type = ecma_get_object_type (builtin_object_p); + ecma_value_t realm_value; + + JERRY_ASSERT (object_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL || object_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS + || object_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY || object_type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type)) + { + realm_value = ((ecma_extended_built_in_object_t *) builtin_object_p)->built_in.realm_value; + } + else + { + realm_value = ((ecma_extended_object_t *) builtin_object_p)->u.built_in.realm_value; + } + + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value); +} /* ecma_builtin_get_realm */ + +#endif /* JERRY_BUILTIN_REALMS */ + +/** + * Instantiate specified ECMA built-in object + * + * @return the newly instantiated built-in + */ +static ecma_object_t * +ecma_instantiate_builtin (ecma_global_object_t *global_object_p, /**< global object */ + ecma_builtin_id_t obj_builtin_id) /**< built-in id */ +{ + jmem_cpointer_t *builtin_objects = global_object_p->builtin_objects; + + JERRY_ASSERT (obj_builtin_id < ECMA_BUILTIN_OBJECTS_COUNT); + JERRY_ASSERT (builtin_objects[obj_builtin_id] == JMEM_CP_NULL); + + ecma_builtin_descriptor_t builtin_desc = ecma_builtin_descriptors[obj_builtin_id]; + ecma_builtin_id_t object_prototype_builtin_id = (ecma_builtin_id_t) (builtin_desc >> ECMA_BUILTIN_PROTOTYPE_ID_SHIFT); + + ecma_object_t *prototype_obj_p; + + if (JERRY_UNLIKELY (object_prototype_builtin_id == ECMA_BUILTIN_ID__COUNT)) + { + prototype_obj_p = NULL; + } + else + { + if (builtin_objects[object_prototype_builtin_id] == JMEM_CP_NULL) + { + ecma_instantiate_builtin (global_object_p, object_prototype_builtin_id); + } + prototype_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, builtin_objects[object_prototype_builtin_id]); + JERRY_ASSERT (prototype_obj_p != NULL); + } + + ecma_object_type_t obj_type = (ecma_object_type_t) (builtin_desc & ECMA_BUILTIN_OBJECT_TYPE_MASK); + + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL || obj_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS + || obj_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY || obj_type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + bool is_extended_built_in = ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (obj_type); + + size_t ext_object_size = + (is_extended_built_in ? sizeof (ecma_extended_built_in_object_t) : sizeof (ecma_extended_object_t)); + + size_t property_count = ecma_builtin_get_property_count (obj_builtin_id); + + if (property_count > ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE) + { + /* Only 64 extra properties supported at the moment. + * This can be extended to 256 later. */ + JERRY_ASSERT (property_count <= (ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE + 64)); + + ext_object_size += sizeof (uint64_t); + } + + ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, ext_object_size, obj_type); + + if (JERRY_UNLIKELY (obj_builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER)) + { + ecma_op_ordinary_object_prevent_extensions (obj_p); + } + else + { + ecma_op_ordinary_object_set_extensible (obj_p); + } + + /* + * [[Class]] property of built-in object is not stored explicitly. + * + * See also: ecma_object_get_class_name + */ + + ecma_built_in_props_t *built_in_props_p; + + if (is_extended_built_in) + { + built_in_props_p = &((ecma_extended_built_in_object_t *) obj_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) obj_p)->u.built_in; + } + + built_in_props_p->id = (uint8_t) obj_builtin_id; + built_in_props_p->routine_id = 0; + built_in_props_p->u.length_and_bitset_size = 0; + built_in_props_p->u2.instantiated_bitset[0] = 0; +#if JERRY_BUILTIN_REALMS + ECMA_SET_INTERNAL_VALUE_POINTER (built_in_props_p->realm_value, global_object_p); +#else /* !JERRY_BUILTIN_REALMS */ + built_in_props_p->continue_instantiated_bitset[0] = 0; +#endif /* JERRY_BUILTIN_REALMS */ + + if (property_count > ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE) + { + built_in_props_p->u.length_and_bitset_size = 1 << ECMA_BUILT_IN_BITSET_SHIFT; + + uint32_t *instantiated_bitset_p = (uint32_t *) (built_in_props_p + 1); + instantiated_bitset_p[0] = 0; + instantiated_bitset_p[1] = 0; + } + + /** Initializing [[PrimitiveValue]] properties of built-in prototype objects */ + switch (obj_builtin_id) + { +#if JERRY_BUILTIN_ARRAY + case ECMA_BUILTIN_ID_ARRAY_PROTOTYPE: + { + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + ext_object_p->u.array.length = 0; + ext_object_p->u.array.length_prop_and_hole_count = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_VIRTUAL; + break; + } +#endif /* JERRY_BUILTIN_ARRAY */ + +#if JERRY_BUILTIN_STRING + case ECMA_BUILTIN_ID_STRING_PROTOTYPE: + { + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_STRING; + ext_object_p->u.cls.u3.value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + break; + } +#endif /* JERRY_BUILTIN_STRING */ + +#if JERRY_BUILTIN_NUMBER + case ECMA_BUILTIN_ID_NUMBER_PROTOTYPE: + { + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_NUMBER; + ext_object_p->u.cls.u3.value = ecma_make_integer_value (0); + break; + } +#endif /* JERRY_BUILTIN_NUMBER */ + +#if JERRY_BUILTIN_BOOLEAN + case ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE: + { + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_BOOLEAN; + ext_object_p->u.cls.u3.value = ECMA_VALUE_FALSE; + break; + } +#endif /* JERRY_BUILTIN_BOOLEAN */ + + default: + { + JERRY_ASSERT (obj_type != ECMA_OBJECT_TYPE_BUILT_IN_CLASS); + break; + } + } + + ECMA_SET_NON_NULL_POINTER (builtin_objects[obj_builtin_id], obj_p); + ecma_deref_object (obj_p); + return obj_p; +} /* ecma_instantiate_builtin */ + +/** + * Create a global object + * + * @return a new global object + */ +ecma_global_object_t * +ecma_builtin_create_global_object (void) +{ + ecma_builtin_descriptor_t builtin_desc = ecma_builtin_descriptors[ECMA_BUILTIN_ID_GLOBAL]; + ecma_builtin_id_t prototype_builtin_id = (ecma_builtin_id_t) (builtin_desc >> ECMA_BUILTIN_PROTOTYPE_ID_SHIFT); + ecma_object_type_t obj_type = (ecma_object_type_t) (builtin_desc & ECMA_BUILTIN_OBJECT_TYPE_MASK); + size_t property_count = ecma_builtin_get_property_count (ECMA_BUILTIN_ID_GLOBAL); + + JERRY_ASSERT (prototype_builtin_id != ECMA_BUILTIN_ID__COUNT); + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL); + + /* Whenever this assertion fails, the size of extra_instantiated_bitset in ecma_global_object_t + * must be increased and 32 must be added to these constants. Furthermore the new uint32 item + * must be set to zero. */ +#if JERRY_BUILTIN_REALMS + JERRY_ASSERT (property_count <= ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE + 64); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_ASSERT (property_count <= ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE + 32); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *object_p = ecma_create_object (NULL, sizeof (ecma_global_object_t), obj_type); + + ecma_op_ordinary_object_set_extensible (object_p); + + ecma_global_object_t *global_object_p = (ecma_global_object_t *) object_p; + + global_object_p->extended_object.u.built_in.id = (uint8_t) ECMA_BUILTIN_ID_GLOBAL; + global_object_p->extended_object.u.built_in.routine_id = 0; + /* Bitset size is ignored by the gc. */ + global_object_p->extended_object.u.built_in.u.length_and_bitset_size = 0; + global_object_p->extended_object.u.built_in.u2.instantiated_bitset[0] = 0; + global_object_p->extra_instantiated_bitset[0] = 0; +#if JERRY_BUILTIN_REALMS + ECMA_SET_INTERNAL_VALUE_POINTER (global_object_p->extended_object.u.built_in.realm_value, global_object_p); + global_object_p->extra_realms_bitset = 0; + global_object_p->this_binding = ecma_make_object_value (object_p); +#else /* !JERRY_BUILTIN_REALMS */ + global_object_p->extended_object.u.built_in.continue_instantiated_bitset[0] = 0; +#endif /* JERRY_BUILTIN_REALMS */ + + memset (global_object_p->builtin_objects, 0, (sizeof (jmem_cpointer_t) * ECMA_BUILTIN_OBJECTS_COUNT)); + + /* Temporary self reference for GC mark. */ + ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, object_p); + global_object_p->global_scope_cp = global_object_p->global_env_cp; + + ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL, object_p); + + ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, global_lex_env_p); + global_object_p->global_scope_cp = global_object_p->global_env_cp; + + ecma_deref_object (global_lex_env_p); + + ecma_object_t *prototype_object_p; + prototype_object_p = ecma_instantiate_builtin (global_object_p, prototype_builtin_id); + JERRY_ASSERT (prototype_object_p != NULL); + + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, prototype_object_p); + + return global_object_p; +} /* ecma_builtin_create_global_object */ + +/** + * Get reference to specified built-in object + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to the object's instance + */ +ecma_object_t * +ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on */ +{ + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_OBJECTS_COUNT); + + ecma_global_object_t *global_object_p = (ecma_global_object_t *) ecma_builtin_get_global (); + jmem_cpointer_t *builtin_p = global_object_p->builtin_objects + builtin_id; + + if (JERRY_UNLIKELY (*builtin_p == JMEM_CP_NULL)) + { + return ecma_instantiate_builtin (global_object_p, builtin_id); + } + + return ECMA_GET_NON_NULL_POINTER (ecma_object_t, *builtin_p); +} /* ecma_builtin_get */ + +#if JERRY_BUILTIN_REALMS + +/** + * Get reference to specified built-in object using the realm provided by another built-in object + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to the object's instance + */ +ecma_object_t * +ecma_builtin_get_from_realm (ecma_global_object_t *global_object_p, /**< global object */ + ecma_builtin_id_t builtin_id) /**< id of built-in to check on */ +{ + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_OBJECTS_COUNT); + + jmem_cpointer_t *builtin_p = global_object_p->builtin_objects + builtin_id; + + if (JERRY_UNLIKELY (*builtin_p == JMEM_CP_NULL)) + { + return ecma_instantiate_builtin (global_object_p, builtin_id); + } + + return ECMA_GET_NON_NULL_POINTER (ecma_object_t, *builtin_p); +} /* ecma_builtin_get_from_realm */ + +#endif /* JERRY_BUILTIN_REALMS */ + +/** + * Get reference to specified built-in object using the realm provided by another built-in object + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to the object's instance + */ +static inline ecma_object_t * +ecma_builtin_get_from_builtin (ecma_object_t *builtin_object_p, /**< built-in object */ + ecma_builtin_id_t builtin_id) /**< id of built-in to check on */ +{ + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_OBJECTS_COUNT); + +#if JERRY_BUILTIN_REALMS + return ecma_builtin_get_from_realm (ecma_builtin_get_realm (builtin_object_p), builtin_id); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_UNUSED (builtin_object_p); + return ecma_builtin_get (builtin_id); +#endif /* JERRY_BUILTIN_REALMS */ +} /* ecma_builtin_get_from_builtin */ + +/** + * Construct a Function object for specified built-in routine + * + * See also: ECMA-262 v5, 15 + * + * @return pointer to constructed Function object + */ +static ecma_object_t * +ecma_builtin_make_function_object_for_routine (ecma_object_t *builtin_object_p, /**< builtin object */ + uint8_t routine_id, /**< builtin-wide identifier of the built-in + * object's routine property */ + uint32_t routine_index, /**< property descriptor index of routine */ + uint8_t flags) /**< see also: ecma_builtin_routine_flags */ +{ + ecma_object_t *prototype_obj_p = ecma_builtin_get_from_builtin (builtin_object_p, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + + size_t ext_object_size = sizeof (ecma_extended_object_t); + + ecma_object_t *func_obj_p = ecma_create_object (prototype_obj_p, ext_object_size, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + JERRY_ASSERT (routine_id > 0); + JERRY_ASSERT (routine_index <= UINT8_MAX); + + ecma_built_in_props_t *built_in_props_p; + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (ecma_get_object_type (builtin_object_p))) + { + built_in_props_p = &((ecma_extended_built_in_object_t *) builtin_object_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) builtin_object_p)->u.built_in; + } + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + ext_func_obj_p->u.built_in.id = built_in_props_p->id; + ext_func_obj_p->u.built_in.routine_id = routine_id; + ext_func_obj_p->u.built_in.u.routine_index = (uint8_t) routine_index; + ext_func_obj_p->u.built_in.u2.routine_flags = flags; + +#if JERRY_BUILTIN_REALMS + ext_func_obj_p->u.built_in.realm_value = built_in_props_p->realm_value; +#endif /* JERRY_BUILTIN_REALMS */ + + return func_obj_p; +} /* ecma_builtin_make_function_object_for_routine */ + +/** + * Construct a Function object for specified built-in accessor getter + * + * @return pointer to constructed accessor getter Function object + */ +static ecma_object_t * +ecma_builtin_make_function_object_for_getter_accessor (ecma_object_t *builtin_object_p, /**< builtin object */ + uint8_t routine_id, /**< builtin-wide id of the built-in + * object's routine property */ + uint32_t routine_index) /**< property descriptor index + * of routine */ +{ + return ecma_builtin_make_function_object_for_routine (builtin_object_p, + routine_id, + routine_index, + ECMA_BUILTIN_ROUTINE_GETTER); +} /* ecma_builtin_make_function_object_for_getter_accessor */ + +/** + * Construct a Function object for specified built-in accessor setter + * + * @return pointer to constructed accessor getter Function object + */ +static ecma_object_t * +ecma_builtin_make_function_object_for_setter_accessor (ecma_object_t *builtin_object_p, /**< builtin object */ + uint8_t routine_id, /**< builtin-wide id of the built-in + * object's routine property */ + uint32_t routine_index) /**< property descriptor index + * of routine */ +{ + return ecma_builtin_make_function_object_for_routine (builtin_object_p, + routine_id, + routine_index, + ECMA_BUILTIN_ROUTINE_SETTER); +} /* ecma_builtin_make_function_object_for_setter_accessor */ + +/** + * Create specification defined properties for built-in native handlers. + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +static ecma_property_t * +ecma_builtin_native_handler_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ecma_property_t *prop_p = NULL; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)) + { + if ((ext_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED) == 0) + { + ecma_property_value_t *value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &prop_p); + + value_p->value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + } + else if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + if ((ext_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED) == 0) + { + ecma_property_value_t *value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &prop_p); + + const uint8_t length = ecma_builtin_handler_get_length ((ecma_native_handler_id_t) ext_obj_p->u.built_in.routine_id); + value_p->value = ecma_make_integer_value (length); + } + } + + return prop_p; +} /* ecma_builtin_native_handler_try_to_instantiate_property */ + +/** + * Lazy instantiation of builtin routine property of builtin object + * + * If the property is not instantiated yet, instantiate the property and + * return pointer to the instantiated property. + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + && ecma_builtin_function_is_routine (object_p)); + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (JERRY_UNLIKELY (ext_func_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + { + return ecma_builtin_native_handler_try_to_instantiate_property (object_p, property_name_p); + } + + if (ecma_string_is_length (property_name_p)) + { + /* + * Lazy instantiation of 'length' property + */ + ecma_property_t *len_prop_p; + + uint8_t *bitset_p = &ext_func_p->u.built_in.u2.routine_flags; + + if (*bitset_p & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED) + { + /* length property was already instantiated */ + return NULL; + } + + /* We mark that the property was lazily instantiated, + * as it is configurable and so can be deleted (ECMA-262 v6, 19.2.4.1) */ + ecma_property_value_t *len_prop_value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &len_prop_p); + + uint8_t length = 0; + + if (ext_func_p->u.built_in.u2.routine_flags & ECMA_BUILTIN_ROUTINE_SETTER) + { + length = 1; + } + else if (!(ext_func_p->u.built_in.u2.routine_flags & ECMA_BUILTIN_ROUTINE_GETTER)) + { + uint8_t routine_index = ext_func_p->u.built_in.u.routine_index; + const ecma_builtin_property_descriptor_t *property_list_p; + + property_list_p = ecma_builtin_property_list_references[ext_func_p->u.built_in.id]; + + JERRY_ASSERT (property_list_p[routine_index].type == ECMA_BUILTIN_PROPERTY_ROUTINE); + + length = ECMA_GET_ROUTINE_LENGTH (property_list_p[routine_index].value); + } + + len_prop_value_p->value = ecma_make_integer_value (length); + return len_prop_p; + } + + /* + * Lazy instantiation of 'name' property + */ + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)) + { + uint8_t *bitset_p = &ext_func_p->u.built_in.u2.routine_flags; + + if (*bitset_p & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED) + { + /* name property was already instantiated */ + return NULL; + } + + /* We mark that the property was lazily instantiated */ + ecma_property_t *name_prop_p; + ecma_property_value_t *name_prop_value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &name_prop_p); + + uint8_t routine_index = ext_func_p->u.built_in.u.routine_index; + const ecma_builtin_property_descriptor_t *property_list_p; + + property_list_p = ecma_builtin_property_list_references[ext_func_p->u.built_in.id]; + + JERRY_ASSERT (property_list_p[routine_index].type == ECMA_BUILTIN_PROPERTY_ROUTINE + || property_list_p[routine_index].type == ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE + || property_list_p[routine_index].type == ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY); + + lit_magic_string_id_t name_id = (lit_magic_string_id_t) property_list_p[routine_index].magic_string_id; + ecma_string_t *name_p; + + if (JERRY_UNLIKELY (name_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT)) + { + /* Note: Whenever new intrinsic routine is being added this mapping should be updated as well! */ + if (JERRY_UNLIKELY (name_id == LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES) + || JERRY_UNLIKELY (name_id == LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES) + || JERRY_UNLIKELY (name_id == LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES)) + { + name_p = ecma_get_magic_string (LIT_MAGIC_STRING_VALUES); + } + else if (JERRY_UNLIKELY (name_id == LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES)) + { + name_p = ecma_get_magic_string (LIT_MAGIC_STRING_ENTRIES); + } + else + { + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (name_id)); + name_p = ecma_op_get_global_symbol (name_id); + } + } + else + { + name_p = ecma_get_magic_string (name_id); + } + + const char *prefix_p = NULL; + lit_utf8_size_t prefix_size = 0; + + if (*bitset_p & (ECMA_BUILTIN_ROUTINE_GETTER | ECMA_BUILTIN_ROUTINE_SETTER)) + { + prefix_size = 4; + prefix_p = (*bitset_p & ECMA_BUILTIN_ROUTINE_GETTER) ? "get " : "set "; + } + + name_prop_value_p->value = ecma_op_function_form_name (name_p, (char*)prefix_p, prefix_size); + + if (JERRY_UNLIKELY (name_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT)) + { + ecma_deref_ecma_string (name_p); + } + + return name_prop_p; + } + + return NULL; +} /* ecma_builtin_routine_try_to_instantiate_property */ + +/** + * If the property's name is one of built-in properties of the object + * that is not instantiated yet, instantiate the property and + * return pointer to the instantiated property. + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + lit_magic_string_id_t magic_string_id = ecma_get_string_magic (property_name_p); + + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p)) && property_name_p->u.hash & ECMA_SYMBOL_FLAG_GLOBAL) + { + magic_string_id = (lit_magic_string_id_t) ((int) property_name_p->u.hash >> (int) ECMA_SYMBOL_FLAGS_SHIFT); + } + + if (magic_string_id == LIT_MAGIC_STRING__COUNT) + { + return NULL; + } + + ecma_built_in_props_t *built_in_props_p; + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + JERRY_ASSERT (object_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL || object_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS + || object_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY + || (object_type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION && !ecma_builtin_function_is_routine (object_p))); + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type)) + { + built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in; + } + + ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id; + + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + + const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; + const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; + + while (curr_property_p->magic_string_id != magic_string_id) + { + if (curr_property_p->magic_string_id == LIT_MAGIC_STRING__COUNT) + { + return NULL; + } + curr_property_p++; + } + + uint32_t index = (uint32_t) (curr_property_p - property_list_p); + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + (index >> 3); + +#if JERRY_BUILTIN_REALMS + if (index >= 8 * sizeof (uint8_t)) + { + bitset_p += sizeof (ecma_value_t); + } +#endif /* JERRY_BUILTIN_REALMS */ + + uint8_t bit_for_index = (uint8_t) (1u << (index & 0x7)); + + if (*bitset_p & bit_for_index) + { + /* This property was instantiated before. */ + return NULL; + } + + ecma_value_t value = ECMA_VALUE_EMPTY; + bool is_accessor = false; + ecma_object_t *getter_p = NULL; + ecma_object_t *setter_p = NULL; + + switch (curr_property_p->type) + { + case ECMA_BUILTIN_PROPERTY_SIMPLE: + { + value = curr_property_p->value; + +#if JERRY_BUILTIN_GLOBAL_THIS + if (value == ECMA_VALUE_GLOBAL_THIS) + { + /* Only the global object has globalThis property. */ + JERRY_ASSERT (ecma_builtin_is_global (object_p)); + ecma_ref_object (object_p); + value = ecma_make_object_value (object_p); + } +#endif /* JERRY_BUILTIN_GLOBAL_THIS */ + break; + } + case ECMA_BUILTIN_PROPERTY_NUMBER: + { + ecma_number_t num = 0.0; + + if (curr_property_p->value < ECMA_BUILTIN_NUMBER_MAX) + { + num = curr_property_p->value; + } + else if (curr_property_p->value < ECMA_BUILTIN_NUMBER_NAN) + { + static const ecma_number_t builtin_number_list[] = { + ECMA_NUMBER_MAX_VALUE, + ECMA_NUMBER_MIN_VALUE, + ECMA_NUMBER_EPSILON, + ECMA_NUMBER_MAX_SAFE_INTEGER, + ECMA_NUMBER_MIN_SAFE_INTEGER, + ECMA_NUMBER_E, + ECMA_NUMBER_PI, + ECMA_NUMBER_LN10, + ECMA_NUMBER_LN2, + ECMA_NUMBER_LOG2E, + ECMA_NUMBER_LOG10E, + ECMA_NUMBER_SQRT2, + ECMA_NUMBER_SQRT_1_2, + }; + + num = builtin_number_list[curr_property_p->value - ECMA_BUILTIN_NUMBER_MAX]; + } + else + { + switch (curr_property_p->value) + { + case ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY: + { + num = ecma_number_make_infinity (false); + break; + } + case ECMA_BUILTIN_NUMBER_NEGATIVE_INFINITY: + { + num = ecma_number_make_infinity (true); + break; + } + default: + { + JERRY_ASSERT (curr_property_p->value == ECMA_BUILTIN_NUMBER_NAN); + + num = ecma_number_make_nan (); + break; + } + } + } + + value = ecma_make_number_value (num); + break; + } + case ECMA_BUILTIN_PROPERTY_STRING: + { + value = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->value); + break; + } + case ECMA_BUILTIN_PROPERTY_SYMBOL: + { + lit_magic_string_id_t symbol_id = (lit_magic_string_id_t) curr_property_p->value; + + value = ecma_make_symbol_value (ecma_op_get_global_symbol (symbol_id)); + break; + } + case ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY: + { + ecma_object_t *intrinsic_object_p = ecma_builtin_get_from_builtin (object_p, ECMA_BUILTIN_ID_INTRINSIC_OBJECT); + value = ecma_op_object_get_by_magic_id (intrinsic_object_p, (lit_magic_string_id_t) curr_property_p->value); + break; + } + case ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION: + { + is_accessor = true; + uint16_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value); + uint16_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value); + getter_p = ecma_builtin_get_from_builtin (object_p, (ecma_builtin_id_t) getter_id); + setter_p = ecma_builtin_get_from_builtin (object_p, (ecma_builtin_id_t) setter_id); + ecma_ref_object (getter_p); + ecma_ref_object (setter_p); + break; + } + case ECMA_BUILTIN_PROPERTY_OBJECT: + { + ecma_object_t *builtin_object_p; + builtin_object_p = ecma_builtin_get_from_builtin (object_p, (ecma_builtin_id_t) curr_property_p->value); + ecma_ref_object (builtin_object_p); + value = ecma_make_object_value (builtin_object_p); + break; + } + case ECMA_BUILTIN_PROPERTY_ROUTINE: + { + ecma_object_t *func_obj_p; + func_obj_p = ecma_builtin_make_function_object_for_routine (object_p, + ECMA_GET_ROUTINE_ID (curr_property_p->value), + index, + ECMA_BUILTIN_ROUTINE_NO_OPTS); + value = ecma_make_object_value (func_obj_p); + break; + } + case ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE: + { + is_accessor = true; + uint8_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value); + uint8_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value); + getter_p = ecma_builtin_make_function_object_for_getter_accessor (object_p, getter_id, index); + setter_p = ecma_builtin_make_function_object_for_setter_accessor (object_p, setter_id, index); + break; + } + default: + { + JERRY_ASSERT (curr_property_p->type == ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY); + + is_accessor = true; + uint8_t getter_id = (uint8_t) curr_property_p->value; + getter_p = ecma_builtin_make_function_object_for_getter_accessor (object_p, getter_id, index); + break; + } + } + + ecma_property_t *prop_p; + + JERRY_ASSERT (curr_property_p->attributes & ECMA_PROPERTY_FLAG_BUILT_IN); + + if (is_accessor) + { + ecma_create_named_accessor_property (object_p, + property_name_p, + getter_p, + setter_p, + curr_property_p->attributes, + &prop_p); + + if (setter_p) + { + ecma_deref_object (setter_p); + } + if (getter_p) + { + ecma_deref_object (getter_p); + } + } + else + { + ecma_property_value_t *prop_value_p = + ecma_create_named_data_property (object_p, property_name_p, curr_property_p->attributes, &prop_p); + prop_value_p->value = value; + + /* Reference count of objects must be decreased. */ + ecma_deref_if_object (value); + } + + return prop_p; +} /* ecma_builtin_try_to_instantiate_property */ + +/** + * Delete configurable properties of native handlers. + */ +static void +ecma_builtin_native_handler_delete_built_in_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_extended_object_t *extended_obj_p = (ecma_extended_object_t *) object_p; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!(extended_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED)); + + extended_obj_p->u.built_in.u2.routine_flags |= ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED; + return; + } + + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); + JERRY_ASSERT (!(extended_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED)); + + extended_obj_p->u.built_in.u2.routine_flags |= ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED; +} /* ecma_builtin_native_handler_delete_built_in_property */ + +/** + * Delete configurable properties of built-in routines. + */ +void +ecma_builtin_routine_delete_built_in_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + && ecma_builtin_function_is_routine (object_p)); + + ecma_extended_object_t *extended_obj_p = (ecma_extended_object_t *) object_p; + + if (JERRY_UNLIKELY (extended_obj_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + { + ecma_builtin_native_handler_delete_built_in_property (object_p, property_name_p); + return; + } + + uint8_t *bitset_p = &extended_obj_p->u.built_in.u2.routine_flags; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!(*bitset_p & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED)); + + *bitset_p |= ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED; + return; + } + + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); + JERRY_ASSERT (!(*bitset_p & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED)); + + *bitset_p |= ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED; +} /* ecma_builtin_routine_delete_built_in_property */ + +/** + * Delete configurable properties of built-ins. + */ +void +ecma_builtin_delete_built_in_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + lit_magic_string_id_t magic_string_id = ecma_get_string_magic (property_name_p); + + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + if (property_name_p->u.hash & ECMA_SYMBOL_FLAG_GLOBAL) + { + magic_string_id = (lit_magic_string_id_t ) ((int) property_name_p->u.hash >> ECMA_SYMBOL_FLAGS_SHIFT); + } + } + + ecma_built_in_props_t *built_in_props_p; + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + JERRY_ASSERT (object_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL || object_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS + || object_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY + || (object_type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION && !ecma_builtin_function_is_routine (object_p))); + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type)) + { + built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in; + } + + ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id; + + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + + const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; + const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; + + while (curr_property_p->magic_string_id != magic_string_id) + { + JERRY_ASSERT (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT); + curr_property_p++; + } + + uint32_t index = (uint32_t) (curr_property_p - property_list_p); + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + (index >> 3); + +#if JERRY_BUILTIN_REALMS + if (index >= 8 * sizeof (uint8_t)) + { + bitset_p += sizeof (ecma_value_t); + } +#endif /* JERRY_BUILTIN_REALMS */ + + uint8_t bit_for_index = (uint8_t) (1u << (index & 0x7)); + JERRY_ASSERT (!(*bitset_p & bit_for_index)); + + *bitset_p |= bit_for_index; +} /* ecma_builtin_delete_built_in_property */ + +/** + * List names of an Built-in native handler object's lazy instantiated properties, + * adding them to corresponding string collections + */ +static void +ecma_builtin_native_handler_list_lazy_property_names (ecma_object_t *object_p, /**< function object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p) /**< prop counter */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + + if ((ext_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED) == 0) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_NAME)); + prop_counter_p->string_named_props++; + } + + if ((ext_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED) == 0) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } +} /* ecma_builtin_native_handler_list_lazy_property_names */ + +/** + * List names of a built-in function's lazy instantiated properties + * + * See also: + * ecma_builtin_routine_try_to_instantiate_property + */ +void +ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + JERRY_ASSERT (ecma_builtin_function_is_routine (object_p)); + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + return; + } + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (JERRY_UNLIKELY (ext_func_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + { + ecma_builtin_native_handler_list_lazy_property_names (object_p, prop_names_p, prop_counter_p); + return; + } + + if (!(ext_func_p->u.built_in.u2.routine_flags & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED)) + { + /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + if (!(ext_func_p->u.built_in.u2.routine_flags & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED)) + { + /* Unintialized 'name' property is non-enumerable (ECMA-262 v6, 19.2.4.2) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_NAME)); + prop_counter_p->string_named_props++; + } +} /* ecma_builtin_routine_list_lazy_property_names */ + +/** + * List names of a built-in object's lazy instantiated properties + * + * See also: + * ecma_builtin_try_to_instantiate_property + */ +void +ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + || !ecma_builtin_function_is_routine (object_p)); + + ecma_built_in_props_t *built_in_props_p; + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type)) + { + built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in; + } + + ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id; + + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + +#if JERRY_BUILTIN_REALMS + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1 + sizeof (ecma_value_t); +#else /* !JERRY_BUILTIN_REALMS */ + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1; +#endif /* JERRY_BUILTIN_REALMS */ + + uint8_t *symbol_bitset_p = bitset_p; + bool has_symbol = true; + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id]; + uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0]; + uint32_t index = 0; + + has_symbol = false; + + while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) + { + if (index == 8) + { + bitset = *bitset_p++; + index = 0; + } + + uint32_t bit_for_index = (uint32_t) 1u << index; + + if (!(bitset & bit_for_index)) + { + if (JERRY_LIKELY (curr_property_p->magic_string_id < LIT_NON_INTERNAL_MAGIC_STRING__COUNT)) + { + ecma_value_t name = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->magic_string_id); + ecma_collection_push_back (prop_names_p, name); + prop_counter_p->string_named_props++; + } + else + { + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (curr_property_p->magic_string_id)); + has_symbol = true; + } + } + + curr_property_p++; + index++; + } + } + + if (has_symbol && !(filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS)) + { + const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id]; + uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0]; + uint32_t index = 0; + + while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) + { + if (index == 8) + { + bitset = *symbol_bitset_p++; + index = 0; + } + + uint32_t bit_for_index = (uint32_t) 1u << index; + + if (curr_property_p->magic_string_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT && !(bitset & bit_for_index)) + { + ecma_string_t *name_p = ecma_op_get_global_symbol ((lit_magic_string_id_t ) curr_property_p->magic_string_id); + ecma_collection_push_back (prop_names_p, ecma_make_symbol_value (name_p)); + prop_counter_p->symbol_named_props++; + } + + curr_property_p++; + index++; + } + } +} /* ecma_builtin_list_lazy_property_names */ + +/** + * Dispatcher of built-in routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_dispatch_routine (ecma_extended_object_t *func_obj_p, /**< builtin object */ + ecma_value_t this_arg_value, /**< 'this' argument value */ + const ecma_value_t *arguments_list_p, /**< list of arguments passed to routine */ + uint32_t arguments_list_len) /**< length of arguments' list */ +{ + JERRY_ASSERT (ecma_builtin_function_is_routine ((ecma_object_t *) func_obj_p)); + + ecma_value_t padded_arguments_list_p[3] = { ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED }; + + if (arguments_list_len <= 2) + { + switch (arguments_list_len) + { + case 2: + { + padded_arguments_list_p[1] = arguments_list_p[1]; + /* FALLTHRU */ + } + case 1: + { + padded_arguments_list_p[0] = arguments_list_p[0]; + break; + } + default: + { + JERRY_ASSERT (arguments_list_len == 0); + } + } + + arguments_list_p = padded_arguments_list_p; + } + + return ecma_builtin_routines[func_obj_p->u.built_in.id](func_obj_p->u.built_in.routine_id, + this_arg_value, + arguments_list_p, + arguments_list_len); +} /* ecma_builtin_dispatch_routine */ + +/** + * Handle calling [[Call]] of built-in object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */ + ecma_value_t this_arg_value, /**< 'this' argument value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< arguments list length */ +{ + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ecma_builtin_function_is_routine (obj_p)) + { + if (JERRY_UNLIKELY (ext_obj_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + { + ecma_builtin_handler_t handler = ecma_builtin_handler_get ((ecma_native_handler_id_t ) ext_obj_p->u.built_in.routine_id); + return handler (obj_p, arguments_list_p, arguments_list_len); + } + + return ecma_builtin_dispatch_routine (ext_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + } + + ecma_builtin_id_t builtin_object_id = (ecma_builtin_id_t) ext_obj_p->u.built_in.id; + JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_call_functions) / sizeof (ecma_builtin_dispatch_call_t)); + return ecma_builtin_call_functions[builtin_object_id](arguments_list_p, arguments_list_len); +} /* ecma_builtin_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< arguments list length */ +{ + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + if (ecma_builtin_function_is_routine (obj_p)) + { + return ecma_raise_type_error (ECMA_ERR_BULTIN_ROUTINES_HAVE_NO_CONSTRUCTOR); + } + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + ecma_builtin_id_t builtin_object_id = (ecma_builtin_id_t) ext_obj_p->u.built_in.id; + JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_construct_functions) / sizeof (ecma_builtin_dispatch_call_t)); + + return ecma_builtin_construct_functions[builtin_object_id](arguments_list_p, arguments_list_len); +} /* ecma_builtin_dispatch_construct */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.h new file mode 100644 index 00000000..82761cdc --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.h @@ -0,0 +1,136 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BUILTINS_H +#define ECMA_BUILTINS_H + +#include "ecma-globals.h" + +/** + * A built-in object's identifier + */ +typedef enum +{ +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) builtin_id, +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE +#define BUILTIN_ROUTINE(a, b, c, d, e) +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) builtin_id, +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE + /** @endcond */ + ECMA_BUILTIN_ID__COUNT /**< number of built-in objects */ +} ecma_builtin_id_t; + +/** + * Special id for handlers (handlers are not regular built-ins, but + * they use the same ecma_built_in_props_t structure as other built-ins) + */ +#define ECMA_BUILTIN_ID_HANDLER ECMA_BUILTIN_ID__COUNT + +/** + * Number of global symbols + */ +#define ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT (LIT_GLOBAL_SYMBOL__LAST - LIT_GLOBAL_SYMBOL__FIRST + 1) + +/** + * Construct a routine value + */ +#define ECMA_ROUTINE_VALUE(id, length) (((id) << 4) | length) + +/** + * Get routine length + */ +#define ECMA_GET_ROUTINE_LENGTH(value) ((uint8_t) ((value) &0xf)) + +/** + * Get routine ID + */ +#define ECMA_GET_ROUTINE_ID(value) ((uint8_t) ((value) >> 4)) + +/** + * Construct a fully accessor value + */ +#define ECMA_ACCESSOR_READ_WRITE(getter, setter) (((getter) << 8) | (setter)) + +/** + * Get accessor setter ID + */ +#define ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID(value) ((uint8_t) ((value) &0xff)) + +/** + * Get accessor getter ID + */ +#define ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID(value) ((uint8_t) ((value) >> 8)) + +/** + * Number ob built-in objects excluding global object + */ +#define ECMA_BUILTIN_OBJECTS_COUNT (ECMA_BUILTIN_ID__COUNT - 1) + +/** + * Description of built-in global ECMA-object. + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + uint32_t extra_instantiated_bitset[1]; /**< extra bit set for instantiated properties */ +#if JERRY_BUILTIN_REALMS + uint32_t extra_realms_bitset; /**< extra bit set for instantiated properties when realms is enabled */ + ecma_value_t this_binding; /**< 'this' binding of this global object */ +#endif /* JERRY_BUILTIN_REALMS */ + jmem_cpointer_t global_env_cp; /**< global lexical environment */ + jmem_cpointer_t global_scope_cp; /**< global lexical scope */ + jmem_cpointer_t builtin_objects[ECMA_BUILTIN_OBJECTS_COUNT]; /**< pointer to instances of built-in objects */ +} ecma_global_object_t; + +/* ecma-builtins.c */ + +ecma_global_object_t *ecma_builtin_create_global_object (void); + +ecma_value_t ecma_builtin_dispatch_call (ecma_object_t *obj_p, + ecma_value_t this_arg_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +ecma_value_t ecma_builtin_dispatch_construct (ecma_object_t *obj_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +ecma_property_t *ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, + ecma_string_t *property_name_p); +ecma_property_t *ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +void ecma_builtin_routine_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +void ecma_builtin_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +void ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +void ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +bool ecma_builtin_is_global (ecma_object_t *object_p); +ecma_object_t *ecma_builtin_get (ecma_builtin_id_t builtin_id); +ecma_object_t *ecma_builtin_get_global (void); +bool ecma_builtin_function_is_routine (ecma_object_t *func_obj_p); + +#if JERRY_BUILTIN_REALMS +ecma_object_t *ecma_builtin_get_from_realm (ecma_global_object_t *global_object_p, ecma_builtin_id_t builtin_id); +#endif /* JERRY_BUILTIN_REALMS */ + +#endif /* !ECMA_BUILTINS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h new file mode 100644 index 00000000..9cbfae26 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h @@ -0,0 +1,747 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Description of built-in objects + in format (ECMA_BUILTIN_ID_id, object_type, prototype_id, is_extensible, is_static, underscored_id) */ + +/* The Object.prototype object (15.2.4) */ +BUILTIN (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID__COUNT /* no prototype */, + true, + object_prototype) + +/* The Object object (15.2.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_OBJECT, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + object) + +#if JERRY_BUILTIN_ARRAY +/* The Array.prototype object (15.4.4) */ +BUILTIN (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_ARRAY, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + array_prototype) + +/* The Array object (15.4.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + array) +#endif /* JERRY_BUILTIN_ARRAY */ + +#if JERRY_BUILTIN_DATE +/* The Date.prototype object (20.3.4) */ +BUILTIN (ECMA_BUILTIN_ID_DATE_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + date_prototype) +#endif /* JERRY_BUILTIN_DATE */ + +#if JERRY_BUILTIN_REGEXP +/* The RegExp.prototype object (21.2.5) */ +BUILTIN (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + regexp_prototype) +#endif /* JERRY_BUILTIN_REGEXP */ + +#if JERRY_BUILTIN_STRING +/* The String.prototype object (15.5.4) */ +BUILTIN (ECMA_BUILTIN_ID_STRING_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_CLASS, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + string_prototype) + +/* The String object (15.5.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_STRING, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + string) +#endif /* JERRY_BUILTIN_STRING */ + +#if JERRY_BUILTIN_BOOLEAN +/* The Boolean.prototype object (15.6.4) */ +BUILTIN (ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_CLASS, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + boolean_prototype) + +/* The Boolean object (15.6.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BOOLEAN, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + boolean) +#endif /* JERRY_BUILTIN_BOOLEAN */ + +#if JERRY_BUILTIN_NUMBER +/* The Number.prototype object (15.7.4) */ +BUILTIN (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_CLASS, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + number_prototype) + +/* The Number object (15.7.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_NUMBER, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + number) +#endif /* JERRY_BUILTIN_NUMBER */ + +/* The Function.prototype object (15.3.4) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + function_prototype) + +/* The Function object (15.3.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_FUNCTION, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + function) + +#if JERRY_BUILTIN_MATH +/* The Math object (15.8) */ +BUILTIN (ECMA_BUILTIN_ID_MATH, ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, math) +#endif /* JERRY_BUILTIN_MATH */ + +#if JERRY_BUILTIN_REFLECT + +/* The Reflect object (26.1) */ +BUILTIN (ECMA_BUILTIN_ID_REFLECT, ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, reflect) +#endif /* JERRY_BUILTIN_REFLECT */ + +#if JERRY_BUILTIN_ATOMICS +/* The Atomics object (24.4) */ +BUILTIN (ECMA_BUILTIN_ID_ATOMICS, ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, atomics) +#endif /* JERRY_BUILTIN_ATOMICS */ + +#if JERRY_BUILTIN_DATE +/* The Date object (15.9.3) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_DATE, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + date) +#endif /* JERRY_BUILTIN_DATE */ + +#if JERRY_BUILTIN_REGEXP +/* The RegExp object (15.10) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_REGEXP, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + regexp) +#endif /* JERRY_BUILTIN_REGEXP */ + +#define ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID ECMA_BUILTIN_ID_ERROR + +/* The Error object (15.11.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + error) + +/* The Error.prototype object (15.11.4) */ +BUILTIN (ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + error_prototype) + +#if JERRY_BUILTIN_ERRORS +/* The EvalError.prototype object (15.11.6.1) */ +BUILTIN (ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + eval_error_prototype) + +/* The EvalError object (15.11.6.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_EVAL_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + eval_error) + +/* The RangeError.prototype object (15.11.6.2) */ +BUILTIN (ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + range_error_prototype) + +/* The RangeError object (15.11.6.2) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_RANGE_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + range_error) + +/* The ReferenceError.prototype object (15.11.6.3) */ +BUILTIN (ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + reference_error_prototype) + +/* The ReferenceError object (15.11.6.3) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_REFERENCE_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + reference_error) + +/* The SyntaxError.prototype object (15.11.6.4) */ +BUILTIN (ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + syntax_error_prototype) + +/* The SyntaxError object (15.11.6.4) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_SYNTAX_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + syntax_error) + +/* The TypeError.prototype object (15.11.6.5) */ +BUILTIN (ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + type_error_prototype) + +/* The TypeError object (15.11.6.5) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_TYPE_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + type_error) + +/* The AggregateError.prototype object (15.11.6.5) */ +BUILTIN (ECMA_BUILTIN_ID_AGGREGATE_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + aggregate_error_prototype) + +/* The AggregateError object (15.11.6.5) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_AGGREGATE_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + aggregate_error) + +/* The URIError.prototype object (15.11.6.6) */ +BUILTIN (ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + uri_error_prototype) + +/* The URIError object (15.11.6.6) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_URI_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + uri_error) +#endif /* JERRY_BUILTIN_ERRORS */ + +/**< The [[ThrowTypeError]] object (13.2.3) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + false, + type_error_thrower) + +#if JERRY_BUILTIN_TYPEDARRAY + +/* The ArrayBuffer.prototype object (ES2015 24.1.4) */ +BUILTIN (ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + arraybuffer_prototype) + +/* The ArrayBuffer object (ES2015 24.1.2) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ARRAYBUFFER, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + arraybuffer) + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +/* The SharedArrayBuffer.prototype object (ES2015 24.2.4) */ +BUILTIN (ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + shared_arraybuffer_prototype) + +/* The SharedArrayBuffer object (ES2015 24.2.2) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + shared_arraybuffer) +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + +/* The %TypedArrayPrototype% object (ES2015 24.2.3) */ +BUILTIN (ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + typedarray_prototype) + +/* The %TypedArray% intrinsic object (ES2015 22.2.1) + Note: The routines must be in this order. */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_TYPEDARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + typedarray) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_INT8ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + int8array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_UINT8ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + uint8array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + uint8clampedarray) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_INT16ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + int16array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_UINT16ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + uint16array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_INT32ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + int32array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_UINT32ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + uint32array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_FLOAT32ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + float32array) + +#if JERRY_NUMBER_TYPE_FLOAT64 +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_FLOAT64ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + float64array) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +#if JERRY_BUILTIN_BIGINT +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BIGINT64ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + bigint64array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BIGUINT64ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + biguint64array) +#endif /* JERRY_BUILTIN_BIGINT */ + +BUILTIN (ECMA_BUILTIN_ID_INT8ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + int8array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_UINT8ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + uint8array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + uint8clampedarray_prototype) + +BUILTIN (ECMA_BUILTIN_ID_INT16ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + int16array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_UINT16ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + uint16array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_INT32ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + int32array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_UINT32ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + uint32array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_FLOAT32ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + float32array_prototype) + +#if JERRY_NUMBER_TYPE_FLOAT64 +BUILTIN (ECMA_BUILTIN_ID_FLOAT64ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + float64array_prototype) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +#if JERRY_BUILTIN_BIGINT +BUILTIN (ECMA_BUILTIN_ID_BIGINT64ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + bigint64array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_BIGUINT64ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + biguint64array_prototype) +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +BUILTIN (ECMA_BUILTIN_ID_PROMISE_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + promise_prototype) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_PROMISE, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + promise) + +#if JERRY_BUILTIN_CONTAINER + +/* The Map prototype object (23.1.3) */ +BUILTIN (ECMA_BUILTIN_ID_MAP_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + map_prototype) + +/* The Map routine (ECMA-262 v6, 23.1.1.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_MAP, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, true, map) + +/* The Set prototype object (23.1.3) */ +BUILTIN (ECMA_BUILTIN_ID_SET_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + set_prototype) + +/* The Set routine (ECMA-262 v6, 23.1.1.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_SET, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, true, set) + +/* The WeakMap prototype object (23.1.3) */ +BUILTIN (ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + weakmap_prototype) + +/* The WeakMap routine (ECMA-262 v6, 23.1.1.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_WEAKMAP, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + weakmap) + +/* The WeakSet prototype object (23.1.3) */ +BUILTIN (ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + weakset_prototype) + +/* The WeakSet routine (ECMA-262 v6, 23.1.1.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_WEAKSET, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + weakset) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#if JERRY_BUILTIN_WEAKREF + +/* The WeakRef prototype object */ +BUILTIN (ECMA_BUILTIN_ID_WEAKREF_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + weakref_prototype) + +/* The WeakRef routine */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_WEAKREF, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + weakref) + +#endif /* JERRY_BUILTIN_WEAKREF */ + +#if (JERRY_BUILTIN_PROXY) +/* The Proxy routine (ECMA-262 v6, 26.2.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_PROXY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + proxy) +#endif /* JERRY_BUILTIN_PROXY */ + +/* Intrinsic hidden builtin object */ +BUILTIN (ECMA_BUILTIN_ID_INTRINSIC_OBJECT, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID__COUNT /* no prototype */, + true, + intrinsic) + +/* The Array.prototype[@@unscopables] object */ +BUILTIN (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE_UNSCOPABLES, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID__COUNT /* no prototype */, + true, + array_prototype_unscopables) + +/* The Symbol prototype object (ECMA-262 v6, 19.4.2.7) */ +BUILTIN (ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + symbol_prototype) + +/* The Symbol routine (ECMA-262 v6, 19.4.2.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_SYMBOL, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + symbol) + +/* The %AsyncFunction% object (ECMA-262 v11, 25.7.2) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ASYNC_FUNCTION, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION, + true, + async_function) + +/* The %AsyncFunctionPrototype% object (ECMA-262 v11, 25.7.3) */ +BUILTIN (ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + async_function_prototype) + +/* The %IteratorPrototype% object (ECMA-262 v6, 25.1.2) */ +BUILTIN (ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + iterator_prototype) + +/* The %ArrayIteratorPrototype% object (ECMA-262 v6, 22.1.5.2) */ +BUILTIN (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + array_iterator_prototype) + +/* The %StringIteratorPrototype% object (ECMA-262 v6, 22.1.5.2) */ +BUILTIN (ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + string_iterator_prototype) + +/* The %RegExpStringIteratorPrototype% object (ECMA-262 v11, 21.2.7.1) */ +BUILTIN (ECMA_BUILTIN_ID_REGEXP_STRING_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + regexp_string_iterator_prototype) + +/* The %AsyncIteratorPrototype% object (ECMA-262 v10, 25.1.3) */ +BUILTIN (ECMA_BUILTIN_ID_ASYNC_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + async_iterator_prototype) + +/* The %AsyncFromSyncIteratorPrototype% object (ECMA-262 v11, 25.1.4.2) */ +BUILTIN (ECMA_BUILTIN_ID_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ASYNC_ITERATOR_PROTOTYPE, + true, + async_from_sync_iterator_prototype) + +/* The %(GeneratorFunction)% object */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_GENERATOR_FUNCTION, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION, + true, + generator_function) + +/* The %(Generator)% object */ +BUILTIN (ECMA_BUILTIN_ID_GENERATOR, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + generator) + +/* The %(Generator).prototype% object */ +BUILTIN (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + generator_prototype) + +/* The %(AsyncGeneratorFunction)% object */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ASYNC_GENERATOR_FUNCTION, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION, + true, + async_generator_function) + +/* The %(AsyncGenerator)% object */ +BUILTIN (ECMA_BUILTIN_ID_ASYNC_GENERATOR, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + async_generator) + +/* The %(AsyncGenerator).prototype% object */ +BUILTIN (ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ASYNC_ITERATOR_PROTOTYPE, + true, + async_generator_prototype) + +#if JERRY_BUILTIN_CONTAINER +/* The %SetIteratorPrototype% object (ECMA-262 v6, 23.2.5.2) */ +BUILTIN (ECMA_BUILTIN_ID_SET_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + set_iterator_prototype) + +/* The %MapIteratorPrototype% object (ECMA-262 v6, 23.1.5.2) */ +BUILTIN (ECMA_BUILTIN_ID_MAP_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + map_iterator_prototype) +#endif /* JERRY_BUILTIN_CONTAINER */ + +#if JERRY_BUILTIN_BIGINT +/* The %BigInt.prototype% object */ +BUILTIN (ECMA_BUILTIN_ID_BIGINT_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + bigint_prototype) + +/* The %BigInt% object */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BIGINT, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + bigint) +#endif /* JERRY_BUILTIN_BIGINT */ + +#if JERRY_BUILTIN_DATAVIEW +/* The DataView prototype object (ECMA-262 v6, 24.2.3.1) */ +BUILTIN (ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + dataview_prototype) + +/* The DataView routine (ECMA-262 v6, 24.2.2.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_DATAVIEW, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + dataview) +#endif /* JERRY_BUILTIN_DATAVIEW */ + +/* The Global object (15.1) */ +BUILTIN (ECMA_BUILTIN_ID_GLOBAL, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, /* Implementation-dependent */ + true, + global) + +#undef BUILTIN diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/meson.build b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/meson.build new file mode 100644 index 00000000..89a95c0e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/meson.build @@ -0,0 +1,182 @@ +subdir('typedarray') + +source_file = [ + 'ecma-builtin-aggregateerror-prototype.inc.h', + 'ecma-builtin-aggregateerror.inc.h', + 'ecma-builtin-array-iterator-prototype.inc.h', + 'ecma-builtin-array-prototype-unscopables.inc.h', + 'ecma-builtin-array-prototype.inc.h', + 'ecma-builtin-array.inc.h', + 'ecma-builtin-arraybuffer-prototype.inc.h', + 'ecma-builtin-arraybuffer.inc.h', + 'ecma-builtin-async-from-sync-iterator-prototype.inc.h', + 'ecma-builtin-async-function-prototype.inc.h', + 'ecma-builtin-async-function.inc.h', + 'ecma-builtin-async-generator-function.inc.h', + 'ecma-builtin-async-generator-prototype.inc.h', + 'ecma-builtin-async-generator.inc.h', + 'ecma-builtin-async-iterator-prototype.inc.h', + 'ecma-builtin-atomics.inc.h', + 'ecma-builtin-bigint-prototype.inc.h', + 'ecma-builtin-bigint.inc.h', + 'ecma-builtin-boolean-prototype.inc.h', + 'ecma-builtin-boolean.inc.h', + 'ecma-builtin-dataview-prototype.inc.h', + 'ecma-builtin-dataview.inc.h', + 'ecma-builtin-date-prototype.inc.h', + 'ecma-builtin-date.inc.h', + 'ecma-builtin-error-prototype.inc.h', + 'ecma-builtin-error.inc.h', + 'ecma-builtin-evalerror-prototype.inc.h', + 'ecma-builtin-evalerror.inc.h', + 'ecma-builtin-function-prototype.h', + 'ecma-builtin-function-prototype.inc.h', + 'ecma-builtin-function.inc.h', + 'ecma-builtin-generator-function.inc.h', + 'ecma-builtin-generator-prototype.inc.h', + 'ecma-builtin-generator.inc.h', + 'ecma-builtin-global.inc.h', + 'ecma-builtin-handlers.h', + 'ecma-builtin-handlers.inc.h', + 'ecma-builtin-helpers-macro-defines.inc.h', + 'ecma-builtin-helpers-macro-undefs.inc.h', + 'ecma-builtin-helpers.h', + 'ecma-builtin-internal-routines-template.inc.h', + 'ecma-builtin-intrinsic.inc.h', + 'ecma-builtin-iterator-prototype.inc.h', + 'ecma-builtin-map-iterator-prototype.inc.h', + 'ecma-builtin-map-prototype.inc.h', + 'ecma-builtin-map.inc.h', + 'ecma-builtin-math.inc.h', + 'ecma-builtin-number-prototype.inc.h', + 'ecma-builtin-number.inc.h', + 'ecma-builtin-object-prototype.inc.h', + 'ecma-builtin-object.h', + 'ecma-builtin-object.inc.h', + 'ecma-builtin-promise-prototype.inc.h', + 'ecma-builtin-promise.inc.h', + 'ecma-builtin-proxy.inc.h', + 'ecma-builtin-rangeerror-prototype.inc.h', + 'ecma-builtin-rangeerror.inc.h', + 'ecma-builtin-referenceerror-prototype.inc.h', + 'ecma-builtin-referenceerror.inc.h', + 'ecma-builtin-reflect.inc.h', + 'ecma-builtin-regexp-prototype.inc.h', + 'ecma-builtin-regexp-string-iterator-prototype.inc.h', + 'ecma-builtin-regexp.inc.h', + 'ecma-builtin-set-iterator-prototype.inc.h', + 'ecma-builtin-set-prototype.inc.h', + 'ecma-builtin-set.inc.h', + 'ecma-builtin-shared-arraybuffer-prototype.inc.h', + 'ecma-builtin-shared-arraybuffer.inc.h', + 'ecma-builtin-string-iterator-prototype.inc.h', + 'ecma-builtin-string-prototype.inc.h', + 'ecma-builtin-string.inc.h', + 'ecma-builtin-symbol-prototype.inc.h', + 'ecma-builtin-symbol.inc.h', + 'ecma-builtin-syntaxerror-prototype.inc.h', + 'ecma-builtin-syntaxerror.inc.h', + 'ecma-builtin-type-error-thrower.inc.h', + 'ecma-builtin-typeerror-prototype.inc.h', + 'ecma-builtin-typeerror.inc.h', + 'ecma-builtin-urierror-prototype.inc.h', + 'ecma-builtin-urierror.inc.h', + 'ecma-builtin-weakmap-prototype.inc.h', + 'ecma-builtin-weakmap.inc.h', + 'ecma-builtin-weakref-prototype.inc.h', + 'ecma-builtin-weakref.inc.h', + 'ecma-builtin-weakset-prototype.inc.h', + 'ecma-builtin-weakset.inc.h', + 'ecma-builtins-internal.h', + 'ecma-builtins.h', + 'ecma-builtins.inc.h', + 'ecma-builtin-aggregateerror-prototype.cpp', + 'ecma-builtin-aggregateerror.cpp', + 'ecma-builtin-array-iterator-prototype.cpp', + 'ecma-builtin-array-prototype-unscopables.cpp', + 'ecma-builtin-array-prototype.cpp', + 'ecma-builtin-array.cpp', + 'ecma-builtin-arraybuffer-prototype.cpp', + 'ecma-builtin-arraybuffer.cpp', + 'ecma-builtin-async-from-sync-iterator-prototype.cpp', + 'ecma-builtin-async-function-prototype.cpp', + 'ecma-builtin-async-function.cpp', + 'ecma-builtin-async-generator-function.cpp', + 'ecma-builtin-async-generator-prototype.cpp', + 'ecma-builtin-async-generator.cpp', + 'ecma-builtin-async-iterator-prototype.cpp', + 'ecma-builtin-atomics.cpp', + 'ecma-builtin-bigint-prototype.cpp', + 'ecma-builtin-bigint.cpp', + 'ecma-builtin-boolean-prototype.cpp', + 'ecma-builtin-boolean.cpp', + 'ecma-builtin-dataview-prototype.cpp', + 'ecma-builtin-dataview.cpp', + 'ecma-builtin-date-prototype.cpp', + 'ecma-builtin-date.cpp', + 'ecma-builtin-error-prototype.cpp', + 'ecma-builtin-error.cpp', + 'ecma-builtin-evalerror-prototype.cpp', + 'ecma-builtin-evalerror.cpp', + 'ecma-builtin-function-prototype.cpp', + 'ecma-builtin-function.cpp', + 'ecma-builtin-generator-function.cpp', + 'ecma-builtin-generator-prototype.cpp', + 'ecma-builtin-generator.cpp', + 'ecma-builtin-global.cpp', + 'ecma-builtin-handlers.cpp', + 'ecma-builtin-helpers-date.cpp', + 'ecma-builtin-helpers-error.cpp', + 'ecma-builtin-helpers-sort.cpp', + 'ecma-builtin-helpers.cpp', + 'ecma-builtin-intrinsic.cpp', + 'ecma-builtin-iterator-prototype.cpp', + 'ecma-builtin-map-iterator-prototype.cpp', + 'ecma-builtin-map-prototype.cpp', + 'ecma-builtin-map.cpp', + 'ecma-builtin-math.cpp', + 'ecma-builtin-number-prototype.cpp', + 'ecma-builtin-number.cpp', + 'ecma-builtin-object-prototype.cpp', + 'ecma-builtin-object.cpp', + 'ecma-builtin-promise-prototype.cpp', + 'ecma-builtin-promise.cpp', + 'ecma-builtin-proxy.cpp', + 'ecma-builtin-rangeerror-prototype.cpp', + 'ecma-builtin-rangeerror.cpp', + 'ecma-builtin-referenceerror-prototype.cpp', + 'ecma-builtin-referenceerror.cpp', + 'ecma-builtin-reflect.cpp', + 'ecma-builtin-regexp-prototype.cpp', + 'ecma-builtin-regexp-string-iterator-prototype.cpp', + 'ecma-builtin-regexp.cpp', + 'ecma-builtin-set-iterator-prototype.cpp', + 'ecma-builtin-set-prototype.cpp', + 'ecma-builtin-set.cpp', + 'ecma-builtin-shared-arraybuffer-prototype.cpp', + 'ecma-builtin-shared-arraybuffer.cpp', + 'ecma-builtin-string-iterator-prototype.cpp', + 'ecma-builtin-string-prototype.cpp', + 'ecma-builtin-string.cpp', + 'ecma-builtin-symbol-prototype.cpp', + 'ecma-builtin-symbol.cpp', + 'ecma-builtin-syntaxerror-prototype.cpp', + 'ecma-builtin-syntaxerror.cpp', + 'ecma-builtin-type-error-thrower.cpp', + 'ecma-builtin-typeerror-prototype.cpp', + 'ecma-builtin-typeerror.cpp', + 'ecma-builtin-urierror-prototype.cpp', + 'ecma-builtin-urierror.cpp', + 'ecma-builtin-weakmap-prototype.cpp', + 'ecma-builtin-weakmap.cpp', + 'ecma-builtin-weakref-prototype.cpp', + 'ecma-builtin-weakref.cpp', + 'ecma-builtin-weakset-prototype.cpp', + 'ecma-builtin-weakset.cpp', + 'ecma-builtins.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.cpp new file mode 100644 index 00000000..3b33e033 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.cpp @@ -0,0 +1,45 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-bigint64array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID bigint64array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup bigint64arrayprototype ECMA BigInt64Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.inc.h new file mode 100644 index 00000000..5e1087bf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigInt64Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_BIGINT64ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.cpp new file mode 100644 index 00000000..ae7fc964 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.cpp @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-bigint64array.inc.h" +#define BUILTIN_UNDERSCORED_ID bigint64array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup bigint64array ECMA BigInt64Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of BigInt64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_bigint64array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_BIGINT64_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_bigint64array_dispatch_call */ + +/** + * Handle calling [[Construct]] of BigInt64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_bigint64array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_BIGINT64_ARRAY); +} /* ecma_builtin_bigint64array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.inc.h new file mode 100644 index 00000000..176fc26b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigInt64Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_BIGINT64_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_BIGINT64ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.cpp new file mode 100644 index 00000000..9844fbd5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.cpp @@ -0,0 +1,45 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-biguint64array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID biguint64array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup biguint64arrayprototype ECMA BigUInt64Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.inc.h new file mode 100644 index 00000000..03626442 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigUInt64Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_BIGUINT64ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.cpp new file mode 100644 index 00000000..2482ec2e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.cpp @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-biguint64array.inc.h" +#define BUILTIN_UNDERSCORED_ID biguint64array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup biguint64array ECMA BigUInt64Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of BigUInt64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_biguint64array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_BIG_UINT64_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_biguint64array_dispatch_call */ + +/** + * Handle calling [[Construct]] of BigUInt64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_biguint64array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_BIGUINT64_ARRAY); +} /* ecma_builtin_biguint64array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.inc.h new file mode 100644 index 00000000..ea38782a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.inc.h @@ -0,0 +1,29 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigUInt64Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_BIGUINT64_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_BIGUINT64ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY && JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.cpp new file mode 100644 index 00000000..1e6a6041 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-float32array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID float32array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup float32arrayprototype ECMA Float32Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.inc.h new file mode 100644 index 00000000..56bfeeae --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Float32Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_FLOAT32ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.cpp new file mode 100644 index 00000000..f4f3959f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-float32array.inc.h" +#define BUILTIN_UNDERSCORED_ID float32array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup float32array ECMA Float32Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Float32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_float32array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_FLOAT32_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_float32array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Float32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_float32array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_FLOAT32_ARRAY); +} /* ecma_builtin_float32array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.inc.h new file mode 100644 index 00000000..832b5119 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Float32Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_FLOAT32_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_FLOAT32ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.cpp new file mode 100644 index 00000000..205d23a7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.cpp @@ -0,0 +1,45 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_NUMBER_TYPE_FLOAT64 + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-float64array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID float64array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup float64arrayprototype ECMA Float64Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.inc.h new file mode 100644 index 00000000..815be714 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Float64Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_NUMBER_TYPE_FLOAT64 + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_FLOAT64ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.cpp new file mode 100644 index 00000000..fe3cebb8 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.cpp @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_NUMBER_TYPE_FLOAT64 + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-float64array.inc.h" +#define BUILTIN_UNDERSCORED_ID float64array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup float64array ECMA Float64Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Float64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_float64array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_FLOAT64_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_float64array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Float64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_float64array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_FLOAT64_ARRAY); +} /* ecma_builtin_float64array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.inc.h new file mode 100644 index 00000000..ea8bd422 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.inc.h @@ -0,0 +1,29 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Float64Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_NUMBER_TYPE_FLOAT64 + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_FLOAT64_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_FLOAT64ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.cpp new file mode 100644 index 00000000..1b9c435b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int16array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID int16array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int16arrayprototype ECMA Int16Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.inc.h new file mode 100644 index 00000000..7815d9a5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int16Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 2 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT16ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.cpp new file mode 100644 index 00000000..076a853b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int16array.inc.h" +#define BUILTIN_UNDERSCORED_ID int16array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int64array ECMA Int16Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Int16Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int16array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_INT16_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_int16array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Int16Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int16array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_INT16_ARRAY); +} /* ecma_builtin_int16array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.inc.h new file mode 100644 index 00000000..f744ed77 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int16Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 2 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_INT16_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT16ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.cpp new file mode 100644 index 00000000..36fc8470 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int32array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID int32array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int32arrayprototype ECMA Int32Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.inc.h new file mode 100644 index 00000000..9a31a062 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int32Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT32ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.cpp new file mode 100644 index 00000000..a322a301 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int32array.inc.h" +#define BUILTIN_UNDERSCORED_ID int32array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int32array ECMA Int32Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Int32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int32array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_INT32_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_int32array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Int32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int32array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_INT32_ARRAY); +} /* ecma_builtin_int32array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.inc.h new file mode 100644 index 00000000..ac786a0b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int32Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_INT32_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT32ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.cpp new file mode 100644 index 00000000..8221f309 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int8array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID int8array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int8arrayprototype ECMA Int8Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.inc.h new file mode 100644 index 00000000..99d072b1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int8Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT8ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.cpp new file mode 100644 index 00000000..402e3838 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int8array.inc.h" +#define BUILTIN_UNDERSCORED_ID int8array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int8array ECMA Int8Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Int8Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int8array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_INT8_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_int8array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Int8Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int8array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_INT8_ARRAY); +} /* ecma_builtin_int8array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.inc.h new file mode 100644 index 00000000..25c84de2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int8Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_INT8_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT8ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.cpp new file mode 100644 index 00000000..23681ddb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.cpp @@ -0,0 +1,74 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-typedarray-helpers.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#include "ecma-builtins.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-objects.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * Common implementation of the [[Construct]] call of TypedArrays. + * + * @return ecma value of the new TypedArray object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_typedarray_helper_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len, /**< number of arguments */ + ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + ecma_builtin_id_t proto_id = ecma_typedarray_helper_get_prototype_id (typedarray_id); + ecma_object_t *prototype_obj_p = NULL; + ecma_object_t *current_new_target_p = JERRY_CONTEXT (current_new_target_p); + + if (current_new_target_p != NULL) + { + prototype_obj_p = ecma_op_get_prototype_from_constructor (current_new_target_p, proto_id); + if (prototype_obj_p == NULL) + { + return ECMA_VALUE_ERROR; + } + } + else + { + prototype_obj_p = ecma_builtin_get (proto_id); + } + + ecma_value_t val = ecma_op_create_typedarray (arguments_list_p, + arguments_list_len, + prototype_obj_p, + ecma_typedarray_helper_get_shift_size (typedarray_id), + typedarray_id); + + if (current_new_target_p != NULL) + { + ecma_deref_object (prototype_obj_p); + } + + return val; +} /* ecma_typedarray_helper_dispatch_construct */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h new file mode 100644 index 00000000..d4064374 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_TYPEDARRAY_HELPERS_H +#define ECMA_TYPEDARRAY_HELPERS_H +#include "ecma-globals.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltinhelpers ECMA builtin helper operations + * @{ + */ + +ecma_value_t ecma_typedarray_helper_dispatch_construct (const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len, + ecma_typedarray_type_t typedarray_id); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#endif /* !ECMA_TYPEDARRAY_HELPERS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype-template.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype-template.inc.h new file mode 100644 index 00000000..beb63352 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype-template.inc.h @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#ifndef TYPEDARRAY_BYTES_PER_ELEMENT +#error "Please define TYPEDARRAY_BYTES_PER_ELEMENT" +#endif /* !TYPEDARRAY_BYTES_PER_ELEMENT */ + +#ifndef TYPEDARRAY_BUILTIN_ID +#error "Please define TYPEDARRAY_BUILTIN_ID" +#endif /* !TYPEDARRAY_BUILTIN_ID */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ES2015 22.2.3.4 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, TYPEDARRAY_BUILTIN_ID, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ES2015 22.2.6.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U, TYPEDARRAY_BYTES_PER_ELEMENT, ECMA_PROPERTY_FIXED) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" + +#undef TYPEDARRAY_BUILTIN_ID +#undef TYPEDARRAY_BYTES_PER_ELEMENT + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.cpp new file mode 100644 index 00000000..3738e175 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.cpp @@ -0,0 +1,2106 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-arraybuffer-object.h" +#include "ecma-bigint.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtin-typedarray-helpers.h" +#include "ecma-builtins.h" +#include "ecma-comparison.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-number-object.h" +#include "ecma-objects.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" +#include "jmem.h" +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + /* These routines must be in this order */ + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_START = 0, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_MAP, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE_RIGHT, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_EVERY, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SOME, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FOR_EACH, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILTER, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND_INDEX, + + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_AT, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LAST_INDEX_OF, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INCLUDES, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILL, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SORT, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REVERSE, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_COPY_WITHIN, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SLICE, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SUBARRAY, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_LOCALE_STRING, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_JOIN, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_KEYS, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_ENTRIES, + + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BUFFER_GETTER, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTELENGTH_GETTER, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTEOFFSET_GETTER, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LENGTH_GETTER, + + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SET, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_STRING_TAG_GETTER, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-typedarray-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID typedarray_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup typedarrayprototype ECMA %TypedArray%.prototype object built-in + * @{ + */ + +/** + * Type of routine. + */ +typedef enum +{ + TYPEDARRAY_ROUTINE_EVERY, /**< routine: every ES2015, 22.2.3.7 */ + TYPEDARRAY_ROUTINE_SOME, /**< routine: some ES2015, 22.2.3.9 */ + TYPEDARRAY_ROUTINE_FOREACH, /**< routine: forEach ES2015, 15.4.4.18 */ + TYPEDARRAY_ROUTINE__COUNT /**< count of the modes */ +} typedarray_routine_mode; + +/** + * The common function for 'every', 'some' and 'forEach' + * because they have a similar structure. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_exec_routine (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t cb_func_val, /**< callback function */ + ecma_value_t cb_this_arg, /**< 'this' of the callback function */ + typedarray_routine_mode mode) /**< mode: which routine */ +{ + JERRY_ASSERT (mode < TYPEDARRAY_ROUTINE__COUNT); + + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + ecma_object_t *func_object_p = ecma_get_object_from_value (cb_func_val); + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + uint32_t byte_pos = 0; + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + for (uint32_t index = 0; index < info_p->length && ecma_is_value_empty (ret_value); index++) + { + ecma_value_t current_index = ecma_make_uint32_value (index); + ecma_value_t element = typedarray_getter_cb (buffer_p + byte_pos); + + ecma_value_t call_args[] = { element, current_index, this_arg }; + + ecma_value_t call_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + + ecma_fast_free_value (current_index); + ecma_fast_free_value (element); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + ecma_free_value (call_value); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + bool to_bool_result = ecma_op_to_boolean (call_value); + ecma_free_value (call_value); + + if (mode == TYPEDARRAY_ROUTINE_EVERY) + { + if (!to_bool_result) + { + return ECMA_VALUE_FALSE; + } + } + else if (mode == TYPEDARRAY_ROUTINE_SOME && to_bool_result) + { + return ECMA_VALUE_TRUE; + } + + byte_pos += info_p->element_size; + } + + if (mode == TYPEDARRAY_ROUTINE_EVERY) + { + ret_value = ECMA_VALUE_TRUE; + } + else if (mode == TYPEDARRAY_ROUTINE_SOME) + { + ret_value = ECMA_VALUE_FALSE; + } + else + { + ret_value = ECMA_VALUE_UNDEFINED; + } + + return ret_value; +} /* ecma_builtin_typedarray_prototype_exec_routine */ + +/** + * The %TypedArray%.prototype object's 'map' routine + * + * See also: + * ES2015, 22.2.3.8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this object */ + ecma_typedarray_info_t *src_info_p, /**< object info */ + ecma_value_t cb_func_val, /**< callback function */ + ecma_value_t cb_this_arg) /**< this' of the callback function */ +{ + ecma_object_t *func_object_p = ecma_get_object_from_value (cb_func_val); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (src_info_p->array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (src_info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + // TODO: 22.2.3.18, 7-8. + ecma_value_t len = ecma_make_number_value (src_info_p->length); + ecma_value_t new_typedarray = ecma_typedarray_species_create (this_arg, &len, 1); + ecma_free_value (len); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + return new_typedarray; + } + + ecma_object_t *target_obj_p = ecma_get_object_from_value (new_typedarray); + + uint8_t *src_buffer_p = ecma_typedarray_get_buffer (src_info_p); + + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (target_obj_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (target_info.array_buffer_p)) + { + ecma_deref_object (target_obj_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (target_info.array_buffer_p)) + { + ecma_deref_object (target_obj_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info); + + ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (src_info_p->id); + ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id); + + for (uint32_t index = 0; index < src_info_p->length; index++) + { + ecma_value_t current_index = ecma_make_uint32_value (index); + ecma_value_t element = src_typedarray_getter_cb (src_buffer_p); + src_buffer_p += src_info_p->element_size; + + ecma_value_t call_args[] = { element, current_index, this_arg }; + ecma_value_t mapped_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + + ecma_free_value (current_index); + ecma_free_value (element); + + if (ECMA_IS_VALUE_ERROR (mapped_value)) + { + ecma_free_value (new_typedarray); + return mapped_value; + } + + if (ecma_arraybuffer_is_detached (src_info_p->array_buffer_p)) + { + ecma_free_value (mapped_value); + ecma_free_value (new_typedarray); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, mapped_value); + target_buffer_p += target_info.element_size; + ecma_free_value (mapped_value); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_free_value (new_typedarray); + return set_element; + } + } + + return new_typedarray; +} /* ecma_builtin_typedarray_prototype_map */ + +/** + * Reduce and reduceRight routines share a similar structure. + * And we use 'is_right' to distinguish between them. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_reduce_with_direction (ecma_value_t this_arg, /**< this object */ + ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t arguments_list_p[], /**arg_list*/ + uint32_t arguments_number, /**< length of arguments' list*/ + bool is_right) /**< choose order, true is reduceRight */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + uint32_t byte_pos; + + if (info_p->length == 0) + { + if (arguments_number < 2) + { + return ecma_raise_type_error (ECMA_ERR_INITIAL_VALUE_CANNOT_BE_UNDEFINED); + } + + return ecma_copy_value (arguments_list_p[1]); + } + + JERRY_ASSERT (info_p->length > 0); + + ecma_value_t accumulator = ECMA_VALUE_UNDEFINED; + uint32_t index = is_right ? (info_p->length - 1) : 0; + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + + if (ecma_is_value_undefined (arguments_list_p[1])) + { + byte_pos = index << info_p->shift; + accumulator = getter_cb (buffer_p + byte_pos); + + if (is_right) + { + if (index == 0) + { + return accumulator; + } + + index--; + } + else + { + index++; + + if (index == info_p->length) + { + return accumulator; + } + } + } + else + { + accumulator = ecma_copy_value (arguments_list_p[1]); + } + + ecma_object_t *func_object_p = ecma_get_object_from_value (arguments_list_p[0]); + + while (true) + { + ecma_value_t current_index = ecma_make_uint32_value (index); + byte_pos = index << info_p->shift; + ecma_value_t get_value = getter_cb (buffer_p + byte_pos); + + ecma_value_t call_args[] = { accumulator, get_value, current_index, this_arg }; + + JERRY_ASSERT (ecma_is_value_number (get_value) || ecma_is_value_bigint (get_value)); + + ecma_value_t call_value = ecma_op_function_call (func_object_p, ECMA_VALUE_UNDEFINED, call_args, 4); + + ecma_fast_free_value (accumulator); + ecma_fast_free_value (get_value); + ecma_fast_free_value (current_index); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + ecma_free_value (call_value); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + accumulator = call_value; + + if (is_right) + { + if (index == 0) + { + break; + } + + index--; + } + else + { + index++; + + if (index == info_p->length) + { + break; + } + } + } + + return accumulator; +} /* ecma_builtin_typedarray_prototype_reduce_with_direction */ + +/** + * The %TypedArray%.prototype object's 'filter' routine + * + * See also: + * ES2015, 22.2.3.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this object */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t cb_func_val, /**< callback function */ + ecma_value_t cb_this_arg) /**< 'this' of the callback function */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + + ecma_object_t *func_object_p = ecma_get_object_from_value (cb_func_val); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + // TODO: 22.2.3.9, 7-8. + if (info_p->length == 0) + { + return ecma_op_create_typedarray_with_type_and_length (info_p->id, 0); + } + + ecma_collection_t *collected_p = ecma_new_collection (); + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + ecma_value_t collected; + + for (uint32_t index = 0; index < info_p->length; index++) + { + ecma_value_t current_index = ecma_make_uint32_value (index); + ecma_value_t get_value = getter_cb (buffer_p); + + JERRY_ASSERT (ecma_is_value_number (get_value) || ecma_is_value_bigint (get_value)); + + ecma_value_t call_args[] = { get_value, current_index, this_arg }; + + ecma_value_t call_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + + ecma_fast_free_value (current_index); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ecma_fast_free_value (get_value); + goto cleanup; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + ecma_free_value (call_value); + ecma_fast_free_value (get_value); + ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto cleanup; + } + + if (ecma_op_to_boolean (call_value)) + { + ecma_collection_push_back (collected_p, get_value); + } + else + { + ecma_fast_free_value (get_value); + } + + buffer_p += info_p->element_size; + ecma_fast_free_value (call_value); + } + + collected = ecma_make_number_value (collected_p->item_count); + ret_value = ecma_typedarray_species_create (this_arg, &collected, 1); + ecma_free_value (collected); + + if (!ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (ret_value); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (new_typedarray_p); + + JERRY_ASSERT (target_info.offset == 0); + + uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info); + + ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id); + + for (uint32_t idx = 0; idx < collected_p->item_count; idx++) + { + ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, collected_p->buffer_p[idx]); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_deref_object (new_typedarray_p); + ret_value = ECMA_VALUE_ERROR; + goto cleanup; + } + + target_buffer_p += target_info.element_size; + } + } + +cleanup: + ecma_collection_free (collected_p); + + return ret_value; +} /* ecma_builtin_typedarray_prototype_filter */ + +/** + * The %TypedArray%.prototype object's 'reverse' routine + * + * See also: + * ES2015, 22.2.3.21 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_reverse (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p) /**< object info */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + uint32_t middle = (info_p->length / 2) << info_p->shift; + uint32_t buffer_last = (info_p->length << info_p->shift) - info_p->element_size; + + for (uint32_t lower = 0; lower < middle; lower += info_p->element_size) + { + uint32_t upper = buffer_last - lower; + uint8_t *lower_p = buffer_p + lower; + uint8_t *upper_p = buffer_p + upper; + + uint8_t tmp[8]; + memcpy (&tmp[0], lower_p, info_p->element_size); + memcpy (lower_p, upper_p, info_p->element_size); + memcpy (upper_p, &tmp[0], info_p->element_size); + } + + return ecma_copy_value (this_arg); +} /* ecma_builtin_typedarray_prototype_reverse */ + +/** + * The %TypedArray%.prototype object's 'set' routine for a typedArray source + * + * See also: + * ES2015, 22.2.3.22, 22.2.3.22.2 + * + * @return ecma value of undefined if success, error otherwise. + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_op_typedarray_set_with_typedarray (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arr_val, /**< typedarray object */ + ecma_value_t offset_val) /**< offset value */ +{ + /* 6.~ 8. targetOffset */ + ecma_number_t target_offset_num; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (offset_val, &target_offset_num))) + { + return ECMA_VALUE_ERROR; + } + + if (target_offset_num <= -1.0 || target_offset_num >= (ecma_number_t) UINT32_MAX + 0.5) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_OFFSET); + } + + ecma_object_t *target_typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (target_typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (target_info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (target_info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info); + + ecma_object_t *src_typedarray_p = ecma_get_object_from_value (arr_val); + ecma_typedarray_info_t src_info = ecma_typedarray_get_info (src_typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (src_info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (src_info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *src_buffer_p = ecma_typedarray_get_buffer (&src_info); + + uint32_t target_offset_uint32 = ecma_number_to_uint32 (target_offset_num); + + if ((int64_t) src_info.length + target_offset_uint32 > target_info.length) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_RANGE_OF_INDEX); + } + + /* Fast path first. If the source and target arrays are the same we do not need to copy anything. */ + if (this_arg == arr_val) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 26. targetByteIndex */ + target_buffer_p += target_offset_uint32 << target_info.shift; + + /* 27. limit */ + uint32_t limit = src_info.length << target_info.shift; + + if (src_info.id == target_info.id) + { + memmove (target_buffer_p, src_buffer_p, limit); + } + else + { + uint8_t *target_limit_p = target_buffer_p + limit; + ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (src_info.id); + ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id); + + while (target_buffer_p < target_limit_p) + { + ecma_value_t element = src_typedarray_getter_cb (src_buffer_p); + ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, element); + ecma_free_value (element); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + return set_element; + } + + src_buffer_p += src_info.element_size; + target_buffer_p += target_info.element_size; + } + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_typedarray_set_with_typedarray */ + +/** + * The %TypedArray%.prototype object's 'set' routine + * + * See also: + * ES2015, 22.2.3.22, 22.2.3.22.1 + * + * @return ecma value of undefined if success, error otherwise. + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arr_val, /**< array object */ + ecma_value_t offset_val) /**< offset value */ +{ + /* 1. */ + if (ecma_is_typedarray (arr_val)) + { + /* 22.2.3.22.2 */ + return ecma_op_typedarray_set_with_typedarray (this_arg, arr_val, offset_val); + } + + /* 6.~ 8. targetOffset */ + ecma_number_t target_offset_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (offset_val, &target_offset_num))) + { + return ECMA_VALUE_ERROR; + } + + if (target_offset_num <= -1.0 || target_offset_num >= (ecma_number_t) UINT32_MAX + 0.5) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_OFFSET); + } + uint32_t target_offset_uint32 = ecma_number_to_uint32 (target_offset_num); + + /* 11. ~ 15. */ + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (target_info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (target_info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info); + + /* 16.~ 17. */ + ecma_value_t source_obj = ecma_op_to_object (arr_val); + + if (ECMA_IS_VALUE_ERROR (source_obj)) + { + return source_obj; + } + + /* 18.~ 19. */ + ecma_object_t *source_obj_p = ecma_get_object_from_value (source_obj); + + ecma_length_t source_length; + + if (ECMA_IS_VALUE_ERROR (ecma_op_object_get_length (source_obj_p, &source_length))) + { + ecma_deref_object (source_obj_p); + return ECMA_VALUE_ERROR; + } + + /* 20. if srcLength + targetOffset > targetLength, throw a RangeError */ + if ((int64_t) source_length + target_offset_uint32 > target_info.length) + { + ecma_deref_object (source_obj_p); + return ecma_raise_range_error (ECMA_ERR_INVALID_RANGE_OF_INDEX); + } + JERRY_ASSERT (source_length <= UINT32_MAX); + uint32_t source_length_uint32 = (uint32_t) source_length; + + /* 21.~ 25. */ + target_buffer_p += target_offset_uint32 << target_info.shift; + + ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id); + uint32_t k = 0; + + while (k < source_length_uint32) + { + ecma_value_t elem = ecma_op_object_get_by_index (source_obj_p, k); + + if (ECMA_IS_VALUE_ERROR (elem)) + { + ecma_deref_object (source_obj_p); + return elem; + } + + ecma_value_t value_to_set; + +#if JERRY_BUILTIN_BIGINT + if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (target_info.id)) + { + value_to_set = ecma_bigint_to_bigint (elem, false); + + if (ECMA_IS_VALUE_ERROR (value_to_set)) + { + ecma_deref_object (source_obj_p); + ecma_free_value (elem); + return value_to_set; + } + } + else +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_number_t elem_num; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_numeric (elem, &elem_num, ECMA_TO_NUMERIC_NO_OPTS))) + { + ecma_free_value (elem); + ecma_deref_object (source_obj_p); + return ECMA_VALUE_ERROR; + } + + value_to_set = ecma_make_number_value (elem_num); + } + + ecma_free_value (elem); + + if (ecma_arraybuffer_is_detached (target_info.array_buffer_p)) + { + ecma_deref_object (source_obj_p); + ecma_free_value (value_to_set); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, value_to_set); + + ecma_free_value (value_to_set); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_deref_object (source_obj_p); + return set_element; + } + + k++; + target_buffer_p += target_info.element_size; + } + + ecma_deref_object (source_obj_p); + + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_typedarray_prototype_set */ + +/** + * TypedArray.prototype's 'toString' single element operation routine based + * on the Array.prototype's 'toString' single element operation routine + * + * See also: + * ECMA-262 v5.1, 15.4.4.2 + * + * @return NULL - if the converison fails + * ecma_string_t * - otherwise + */ +static ecma_string_t * +ecma_op_typedarray_get_to_string_at_index (ecma_object_t *obj_p, /**< this object */ + uint32_t index) /**< array index */ +{ + ecma_value_t index_value = ecma_op_object_get_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (index_value)) + { + return NULL; + } + + if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) + { + ecma_free_value (index_value); + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_string_t *ret_str_p = ecma_op_to_string (index_value); + + ecma_free_value (index_value); + + return ret_str_p; +} /* ecma_op_typedarray_get_to_string_at_index */ + +/** + * The TypedArray.prototype.toString's separator creation routine based on + * the Array.prototype.toString's separator routine + * + * See also: + * ECMA-262 v5.1, 15.4.4.2 4th step + * + * @return NULL - if the conversion fails + * ecma_string_t * - otherwise + */ +static ecma_string_t * +ecma_op_typedarray_get_separator_string (ecma_value_t separator) /**< possible separator */ +{ + if (ecma_is_value_undefined (separator)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR); + } + + return ecma_op_to_string (separator); +} /* ecma_op_typedarray_get_separator_string */ + +/** + * The TypedArray.prototype object's 'join' routine basen on + * the Array.porottype object's 'join' + * + * See also: + * ECMA-262 v5, 15.4.4.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_join (ecma_object_t *obj_p, /**< this object */ + ecma_value_t separator_arg) /**< separator argument */ +{ + ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p); + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* 2. */ + uint32_t length = ecma_typedarray_get_length (obj_p); + ecma_string_t *separator_string_p = ecma_op_typedarray_get_separator_string (separator_arg); + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + if (JERRY_UNLIKELY (separator_string_p == NULL)) + { + return ret_value; + } + + /* 7-8. */ + ecma_string_t *first_string_p = ecma_op_typedarray_get_to_string_at_index (obj_p, 0); + + if (JERRY_UNLIKELY (first_string_p == NULL)) + { + ecma_deref_ecma_string (separator_string_p); + return ret_value; + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (first_string_p); + + ecma_deref_ecma_string (first_string_p); + + /* 9-10. */ + for (uint32_t k = 1; k < length; k++) + { + /* 10.a */ + ecma_stringbuilder_append (&builder, separator_string_p); + + /* 10.d */ + ecma_string_t *next_string_p = ecma_op_typedarray_get_to_string_at_index (obj_p, k); + + if (JERRY_UNLIKELY (next_string_p == NULL)) + { + ecma_stringbuilder_destroy (&builder); + ecma_deref_ecma_string (separator_string_p); + return ret_value; + } + + ecma_stringbuilder_append (&builder, next_string_p); + + ecma_deref_ecma_string (next_string_p); + } + + ecma_deref_ecma_string (separator_string_p); + ret_value = ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + + return ret_value; +} /* ecma_builtin_typedarray_prototype_join */ + +/** + * The %TypedArray%.prototype object's 'subarray' routine. + * + * See also: + * ES2015, 22.2.3.26 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_subarray (ecma_value_t this_arg, /**< this object */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t begin, /**< begin */ + ecma_value_t end) /**< end */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 9. beginIndex, 12. endIndex */ + uint32_t begin_index_uint32 = 0, end_index_uint32 = 0; + + /* 7. relativeBegin */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (begin, info_p->length, &begin_index_uint32))) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_is_value_undefined (end)) + { + end_index_uint32 = (uint32_t) info_p->length; + } + else + { + /* 10. relativeEnd */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (end, info_p->length, &end_index_uint32))) + { + return ECMA_VALUE_ERROR; + } + } + + /* 13. newLength */ + uint32_t subarray_length = 0; + + if (end_index_uint32 > begin_index_uint32) + { + subarray_length = end_index_uint32 - begin_index_uint32; + } + + /* 17. beginByteOffset */ + uint32_t begin_byte_offset = info_p->offset + (begin_index_uint32 << info_p->shift); + + ecma_value_t arguments_p[3] = { ecma_make_object_value (info_p->array_buffer_p), + ecma_make_uint32_value (begin_byte_offset), + ecma_make_uint32_value (subarray_length) }; + + ret_value = ecma_typedarray_species_create (this_arg, arguments_p, 3); + + ecma_free_value (arguments_p[1]); + ecma_free_value (arguments_p[2]); + return ret_value; +} /* ecma_builtin_typedarray_prototype_subarray */ + +/** + * The %TypedArray%.prototype object's 'fill' routine. + * + * See also: + * ES2015, 22.2.3.8, 22.1.3.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_fill (ecma_value_t this_arg, /**< this object */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t value, /**< value */ + ecma_value_t begin, /**< begin */ + ecma_value_t end) /**< end */ +{ + ecma_value_t value_to_set; + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + +#if JERRY_BUILTIN_BIGINT + if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id)) + { + value_to_set = ecma_bigint_to_bigint (value, true); + + if (ECMA_IS_VALUE_ERROR (value_to_set)) + { + return value_to_set; + } + } + else +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_number_t value_num; + ecma_value_t ret_value = ecma_op_to_numeric (value, &value_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (!ecma_is_value_empty (ret_value)) + { + return ret_value; + } + + value_to_set = ecma_make_number_value (value_num); + } + + uint32_t begin_index_uint32 = 0, end_index_uint32 = 0; + + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (begin, info_p->length, &begin_index_uint32))) + { + ecma_free_value (value_to_set); + return ECMA_VALUE_ERROR; + } + + if (ecma_is_value_undefined (end)) + { + end_index_uint32 = (uint32_t) info_p->length; + } + else + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (end, info_p->length, &end_index_uint32))) + { + ecma_free_value (value_to_set); + return ECMA_VALUE_ERROR; + } + } + + uint32_t subarray_length = 0; + + if (end_index_uint32 > begin_index_uint32) + { + subarray_length = end_index_uint32 - begin_index_uint32; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + buffer_p += begin_index_uint32 << info_p->shift; + + uint8_t *limit_p = buffer_p + (subarray_length << info_p->shift); + ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (info_p->id); + + while (buffer_p < limit_p) + { + ecma_value_t set_element = typedarray_setter_cb (buffer_p, value_to_set); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_free_value (value_to_set); + return set_element; + } + + buffer_p += info_p->element_size; + } + + ecma_free_value (value_to_set); + + return ecma_copy_value (this_arg); +} /* ecma_builtin_typedarray_prototype_fill */ + +/** + * SortCompare abstract method + * + * See also: + * ECMA-262 v5, 15.4.4.11 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_sort_compare_helper (ecma_value_t lhs, /**< left value */ + ecma_value_t rhs, /**< right value */ + ecma_value_t compare_func, /**< compare function */ + ecma_object_t *array_buffer_p) /**< array buffer */ +{ + if (ecma_is_value_undefined (compare_func)) + { + /* Default comparison when no comparefn is passed. */ +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (lhs) && ecma_is_value_bigint (rhs)) + { + return ecma_make_number_value (ecma_bigint_compare_to_bigint (lhs, rhs)); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + ecma_number_t result = ECMA_NUMBER_ZERO; + + double lhs_value = (double) ecma_get_number_from_value (lhs); + double rhs_value = (double) ecma_get_number_from_value (rhs); + + if (ecma_number_is_nan (lhs_value)) + { + // Keep NaNs at the end of the array. + result = ECMA_NUMBER_ONE; + } + else if (ecma_number_is_nan (rhs_value)) + { + // Keep NaNs at the end of the array. + result = ECMA_NUMBER_MINUS_ONE; + } + else if (lhs_value < rhs_value) + { + result = ECMA_NUMBER_MINUS_ONE; + } + else if (lhs_value > rhs_value || (ecma_number_is_zero (rhs_value) && ecma_number_is_negative (rhs_value))) + { + result = ECMA_NUMBER_ONE; + } + else + { + result = ECMA_NUMBER_ZERO; + } + + return ecma_make_number_value (result); + } + + /* + * compare_func, if not undefined, will always contain a callable function object. + * We checked this previously, before this function was called. + */ + JERRY_ASSERT (ecma_op_is_callable (compare_func)); + ecma_object_t *comparefn_obj_p = ecma_get_object_from_value (compare_func); + + ecma_value_t compare_args[] = { lhs, rhs }; + + ecma_value_t call_value = ecma_op_function_call (comparefn_obj_p, ECMA_VALUE_UNDEFINED, compare_args, 2); + + if (ECMA_IS_VALUE_ERROR (call_value) || ecma_is_value_number (call_value)) + { + return call_value; + } + + ecma_number_t ret_num; + ecma_value_t number_result = ecma_op_to_number (call_value, &ret_num); + + ecma_free_value (call_value); + + if (ECMA_IS_VALUE_ERROR (number_result)) + { + return number_result; + } + + if (ecma_arraybuffer_is_detached (array_buffer_p)) + { + ecma_free_value (number_result); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + // If the coerced value can't be represented as a Number, compare them as equals. + if (ecma_number_is_nan (ret_num)) + { + return ecma_make_number_value (ECMA_NUMBER_ZERO); + } + + return ecma_make_number_value (ret_num); +} /* ecma_builtin_typedarray_prototype_sort_compare_helper */ + +/** + * The %TypedArray%.prototype object's 'sort' routine. + * + * See also: + * ES2015, 22.2.3.25, 22.1.3.24 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_sort (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t compare_func) /**< comparator fn */ +{ + JERRY_ASSERT (ecma_is_typedarray (this_arg)); + JERRY_ASSERT (ecma_is_value_undefined (compare_func) || ecma_op_is_callable (compare_func)); + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + if (!info_p->length) + { + return ecma_copy_value (this_arg); + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + JMEM_DEFINE_LOCAL_ARRAY (values_buffer, info_p->length, ecma_value_t); + + uint32_t buffer_index = 0; + + ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift); + ecma_typedarray_setter_fn_t typedarray_setter_cb; + + /* Copy unsorted array into a native c array. */ + while (buffer_p < limit_p) + { + JERRY_ASSERT (buffer_index < info_p->length); + ecma_value_t element_value = typedarray_getter_cb (buffer_p); + values_buffer[buffer_index++] = element_value; + buffer_p += info_p->element_size; + } + + JERRY_ASSERT (buffer_index == info_p->length); + + const ecma_builtin_helper_sort_compare_fn_t sort_cb = &ecma_builtin_typedarray_prototype_sort_compare_helper; + + ecma_value_t sort_value = ecma_builtin_helper_array_merge_sort_helper (values_buffer, + (uint32_t) (info_p->length), + compare_func, + sort_cb, + info_p->array_buffer_p); + + if (ECMA_IS_VALUE_ERROR (sort_value)) + { + ret_value = sort_value; + goto free_values; + } + + JERRY_ASSERT (sort_value == ECMA_VALUE_EMPTY); + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + typedarray_setter_cb = ecma_get_typedarray_setter_fn (info_p->id); + + buffer_p = limit_p - (info_p->length << info_p->shift); + buffer_index = 0; + + /* Put sorted values from the native array back into the typedarray buffer. */ + while (buffer_p < limit_p) + { + JERRY_ASSERT (buffer_index < info_p->length); + ecma_value_t element_value = values_buffer[buffer_index++]; + ecma_value_t set_element = typedarray_setter_cb (buffer_p, element_value); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ret_value = set_element; + goto free_values; + } + + buffer_p += info_p->element_size; + } + + JERRY_ASSERT (buffer_index == info_p->length); + + ret_value = ecma_copy_value (this_arg); + +free_values: + /* Free values that were copied to the local array. */ + for (uint32_t index = 0; index < info_p->length; index++) + { + ecma_free_value (values_buffer[index]); + } + + JMEM_FINALIZE_LOCAL_ARRAY (values_buffer); + + return ret_value; +} /* ecma_builtin_typedarray_prototype_sort */ + +/** + * The %TypedArray%.prototype object's 'find' and 'findIndex' routine helper + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_find_helper (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t predicate, /**< callback function */ + ecma_value_t predicate_this_arg, /**< this argument for + * invoke predicate */ + bool is_find) /**< true - find routine + * false - findIndex routine */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + JERRY_ASSERT (ecma_is_value_object (predicate)); + ecma_object_t *func_object_p = ecma_get_object_from_value (predicate); + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift); + ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + uint32_t buffer_index = 0; + + while (buffer_p < limit_p) + { + JERRY_ASSERT (buffer_index < info_p->length); + ecma_value_t element_value = typedarray_getter_cb (buffer_p); + buffer_p += info_p->element_size; + + ecma_value_t call_args[] = { element_value, ecma_make_uint32_value (buffer_index), this_arg }; + ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ecma_free_value (element_value); + return call_value; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + ecma_free_value (element_value); + ecma_free_value (call_value); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + bool call_result = ecma_op_to_boolean (call_value); + ecma_free_value (call_value); + + if (call_result) + { + if (is_find) + { + return element_value; + } + + ecma_free_value (element_value); + return ecma_make_uint32_value (buffer_index); + } + + buffer_index++; + ecma_free_value (element_value); + } + + return is_find ? ECMA_VALUE_UNDEFINED : ecma_make_integer_value (-1); +} /* ecma_builtin_typedarray_prototype_find_helper */ + +/** + * The %TypedArray%.prototype object's 'at' routine + * + * See also: + * ECMA-262 Stage 3 Draft Relative Indexing Method proposal + * from: https://tc39.es/proposal-relative-indexing-method + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_at (ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t index) /**< index argument */ +{ + ecma_length_t len = info_p->length; + ecma_length_t res_index; + ecma_value_t return_value = ecma_builtin_helper_calculate_index (index, len, &res_index); + + if (return_value != ECMA_VALUE_EMPTY) + { + return return_value; + } + + if (res_index >= UINT32_MAX) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_get_typedarray_element (info_p, (uint32_t) res_index); +} /* ecma_builtin_typedarray_prototype_at */ + +/** + * The %TypedArray%.prototype object's 'indexOf' routine + * + * See also: + * ECMA-262 v6, 22.2.3.13 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_index_of (ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + +#if JERRY_BUILTIN_BIGINT + bool is_bigint = ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id); +#else /* !JERRY_BUILTIN_BIGINT */ + bool is_bigint = false; +#endif /* JERRY_BUILTIN_BIGINT */ + + uint32_t from_index; + + /* 5. */ + if (args_number == 0 || (!ecma_is_value_number (args[0]) && !is_bigint) || info_p->length == 0) + { + return ecma_make_integer_value (-1); + } + if (args_number == 1) + { + from_index = 0; + } + else + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[1], info_p->length, &from_index))) + { + return ECMA_VALUE_ERROR; + } + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift); + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + + buffer_p += from_index << info_p->shift; + + /* 11. */ + while (buffer_p < limit_p) + { + ecma_value_t element = getter_cb (buffer_p); + + if (ecma_op_same_value_zero (args[0], element, true)) + { + ecma_free_value (element); + return ecma_make_number_value (from_index); + } + + ecma_free_value (element); + buffer_p += info_p->element_size; + from_index++; + } + + /* 12. */ + return ecma_make_integer_value (-1); +} /* ecma_builtin_typedarray_prototype_index_of */ + +/** + * The %TypedArray%.prototype object's 'lastIndexOf' routine + * + * See also: + * ECMA-262 v6, 22.2.3.16 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_last_index_of (ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + +#if JERRY_BUILTIN_BIGINT + bool is_bigint = ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id); +#else /* !JERRY_BUILTIN_BIGINT */ + bool is_bigint = false; +#endif /* JERRY_BUILTIN_BIGINT */ + + uint32_t from_index; + + /* 5. */ + if (args_number == 0 || (!ecma_is_value_number (args[0]) && !is_bigint) || info_p->length == 0) + { + return ecma_make_integer_value (-1); + } + + if (args_number == 1) + { + from_index = info_p->length - 1; + } + else + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[1], info_p->length, &from_index))) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t to_int; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &to_int))) + { + return ECMA_VALUE_ERROR; + } + + if (info_p->length + to_int < 0) + { + return ecma_make_integer_value (-1); + } + + from_index = JERRY_MIN (from_index, info_p->length - 1); + } + + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + uint8_t *current_element_p = buffer_p + (from_index << info_p->shift); + + /* 10. */ + while (current_element_p >= buffer_p) + { + ecma_value_t element = getter_cb (current_element_p); + + if (ecma_op_same_value_zero (args[0], element, true)) + { + ecma_free_value (element); + return ecma_make_number_value ((ecma_number_t) from_index); + } + + ecma_free_value (element); + current_element_p -= info_p->element_size; + from_index--; + } + + /* 11. */ + return ecma_make_integer_value (-1); +} /* ecma_builtin_typedarray_prototype_last_index_of */ + +/** + * The %TypedArray%.prototype object's 'copyWithin' routine + * + * See also: + * ECMA-262 v6, 22.2.3.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_copy_within (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint32_t relative_target = 0; + uint32_t relative_start = 0; + uint32_t relative_end = info_p->length; + + if (args_number > 0) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[0], info_p->length, &relative_target))) + { + return ECMA_VALUE_ERROR; + } + + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[1], info_p->length, &relative_start))) + { + return ECMA_VALUE_ERROR; + } + + if (args_number > 2 && args[2] != ECMA_VALUE_UNDEFINED) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[2], info_p->length, &relative_end))) + { + return ECMA_VALUE_ERROR; + } + } + } + } + + if (relative_target >= info_p->length || relative_start >= relative_end || relative_end == 0) + { + return ecma_copy_value (this_arg); + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + uint32_t distance = relative_end - relative_start; + uint32_t offset = info_p->length - relative_target; + uint32_t count = JERRY_MIN (distance, offset); + + memmove (buffer_p + (relative_target << info_p->shift), + buffer_p + (relative_start << info_p->shift), + (size_t) (count << info_p->shift)); + + return ecma_copy_value (this_arg); +} /* ecma_builtin_typedarray_prototype_copy_within */ + +/** + * The %TypedArray%.prototype object's 'slice' routine + * + * See also: + * ECMA-262 v6, 22.2.3.23 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + uint32_t relative_start = 0; + uint32_t relative_end = info_p->length; + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + if (args_number > 0) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[0], info_p->length, &relative_start))) + { + return ECMA_VALUE_ERROR; + } + + if (args_number > 1 && args[1] != ECMA_VALUE_UNDEFINED + && ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[1], info_p->length, &relative_end))) + { + return ECMA_VALUE_ERROR; + } + } + + uint8_t *src_buffer_p = ecma_typedarray_get_buffer (info_p); + + int32_t distance = (int32_t) (relative_end - relative_start); + uint32_t count = distance > 0 ? (uint32_t) distance : 0; + + ecma_value_t len = ecma_make_number_value (count); + // TODO: 22.2.3.23, 12-13. + ecma_value_t new_typedarray = ecma_typedarray_species_create (this_arg, &len, 1); + ecma_free_value (len); + + if (ECMA_IS_VALUE_ERROR (new_typedarray) || count == 0) + { + return new_typedarray; + } + + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); + ecma_typedarray_info_t new_typedarray_info = ecma_typedarray_get_info (new_typedarray_p); + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + ecma_deref_object (new_typedarray_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *dst_buffer_p = ecma_typedarray_get_buffer (&new_typedarray_info); + + JERRY_ASSERT (new_typedarray_info.offset == 0); + + src_buffer_p += relative_start << info_p->shift; + + if (info_p->id == new_typedarray_info.id) + { + // 22.2.3.23. Step 22. h-i. + memcpy (dst_buffer_p, src_buffer_p, count << info_p->shift); + } + else + { + // 22.2.3.23. Step 21. b. + ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + ecma_typedarray_setter_fn_t new_typedarray_setter_cb = ecma_get_typedarray_setter_fn (new_typedarray_info.id); + + for (uint32_t idx = 0; idx < count; idx++) + { + ecma_value_t element = src_typedarray_getter_cb (src_buffer_p); + ecma_value_t set_element = new_typedarray_setter_cb (dst_buffer_p, element); + ecma_free_value (element); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_deref_object (new_typedarray_p); + return set_element; + } + + src_buffer_p += info_p->element_size; + dst_buffer_p += new_typedarray_info.element_size; + } + } + + return new_typedarray; +} /* ecma_builtin_typedarray_prototype_slice */ + +/** + * The TypedArray.prototype's 'toLocaleString' single element operation routine. + * + * See also: + * ECMA-262 v6, 22.1.3.26 steps 7-10 and 12.b-e + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_to_locale_string_helper (ecma_typedarray_info_t *info_p, /**< object info */ + uint32_t index) /** array index */ +{ + ecma_value_t element_value = ecma_get_typedarray_element (info_p, index); + + if (ECMA_IS_VALUE_ERROR (element_value)) + { + return element_value; + } + + ecma_value_t call_value = ecma_op_invoke_by_magic_id (element_value, LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, NULL, 0); + + ecma_free_value (element_value); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + ecma_string_t *str_p = ecma_op_to_string (call_value); + + ecma_free_value (call_value); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + return ecma_make_string_value (str_p); +} /* ecma_builtin_typedarray_prototype_to_locale_string_helper */ + +/** + * The %TypedArray%.prototype object's 'toLocaleString' routine + * + * See also: + * ECMA-262 v6, 22.2.3.27 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_to_locale_string (ecma_typedarray_info_t *info_p) /**< object info */ +{ + if (info_p->length == 0) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + ecma_value_t first_element = ecma_builtin_typedarray_prototype_to_locale_string_helper (info_p, 0); + + if (ECMA_IS_VALUE_ERROR (first_element)) + { + return first_element; + } + + ecma_string_t *return_string_p = ecma_get_string_from_value (first_element); + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (return_string_p); + ecma_deref_ecma_string (return_string_p); + + for (uint32_t k = 1; k < info_p->length; k++) + { + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_COMMA); + ecma_value_t next_element = ecma_builtin_typedarray_prototype_to_locale_string_helper (info_p, k); + + if (ECMA_IS_VALUE_ERROR (next_element)) + { + ecma_stringbuilder_destroy (&builder); + return next_element; + } + + ecma_string_t *next_element_p = ecma_get_string_from_value (next_element); + ecma_stringbuilder_append (&builder, next_element_p); + ecma_deref_ecma_string (next_element_p); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_typedarray_prototype_to_locale_string */ + +/** + * The %TypedArray%.prototype object's 'includes' routine + * + * See also: + * ECMA-262 v11, 22.2.3.13. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_includes (ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ +#if JERRY_BUILTIN_BIGINT + bool is_bigint = ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id); +#else /* !JERRRY_BUILTIN_BIGINT */ + bool is_bigint = false; +#endif /* JERRRY_BUILTIN_BIGINT */ + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + if (args_number == 0 || (!ecma_is_value_number (args[0]) && !is_bigint) || info_p->length == 0) + { + return ECMA_VALUE_FALSE; + } + + uint32_t from_index = 0; + + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[1], info_p->length, &from_index))) + { + return ECMA_VALUE_ERROR; + } + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift); + + buffer_p += from_index << info_p->shift; + + while (buffer_p < limit_p) + { + ecma_value_t element = getter_cb (buffer_p); + + if (ecma_op_same_value_zero (args[0], element, false)) + { + ecma_free_value (element); + return ECMA_VALUE_TRUE; + } + + ecma_free_value (element); + buffer_p += info_p->element_size; + } + + return ECMA_VALUE_FALSE; +} /* ecma_builtin_typedarray_prototype_includes */ + +/** + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_typedarray_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + if (!ecma_is_typedarray (this_arg)) + { + if (builtin_routine_id == ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_STRING_TAG_GETTER) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY); + } + + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t info = { 0 }; + + if (builtin_routine_id < ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BUFFER_GETTER) + { + info = ecma_typedarray_get_info (typedarray_p); + + if (builtin_routine_id != ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SUBARRAY + && ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + } + + if (builtin_routine_id < ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF && !ecma_op_is_callable (arguments_list_p[0])) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + switch (builtin_routine_id) + { + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INCLUDES: + { + return ecma_builtin_typedarray_prototype_includes (&info, arguments_list_p, arguments_number); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_JOIN: + { + return ecma_builtin_typedarray_prototype_join (typedarray_p, arguments_list_p[0]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_EVERY: + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SOME: + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FOR_EACH: + { + uint8_t offset = (uint8_t) (builtin_routine_id - ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_EVERY); + + return ecma_builtin_typedarray_prototype_exec_routine (this_arg, + &info, + arguments_list_p[0], + arguments_list_p[1], + (typedarray_routine_mode) offset); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_MAP: + { + return ecma_builtin_typedarray_prototype_map (this_arg, &info, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE: + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE_RIGHT: + { + bool is_reduce = builtin_routine_id == ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE_RIGHT; + return ecma_builtin_typedarray_prototype_reduce_with_direction (this_arg, + &info, + arguments_list_p, + arguments_number, + is_reduce); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILTER: + { + return ecma_builtin_typedarray_prototype_filter (this_arg, &info, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REVERSE: + { + return ecma_builtin_typedarray_prototype_reverse (this_arg, &info); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SET: + { + return ecma_builtin_typedarray_prototype_set (this_arg, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SUBARRAY: + { + return ecma_builtin_typedarray_prototype_subarray (this_arg, &info, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILL: + { + return ecma_builtin_typedarray_prototype_fill (this_arg, + &info, + arguments_list_p[0], + arguments_list_p[1], + arguments_list_p[2]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SORT: + { + if (!ecma_is_value_undefined (arguments_list_p[0]) && !ecma_op_is_callable (arguments_list_p[0])) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + return ecma_builtin_typedarray_prototype_sort (this_arg, &info, arguments_list_p[0]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND: + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND_INDEX: + { + bool is_find = builtin_routine_id == ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND; + return ecma_builtin_typedarray_prototype_find_helper (this_arg, + &info, + arguments_list_p[0], + arguments_list_p[1], + is_find); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_AT: + { + return ecma_builtin_typedarray_prototype_at (&info, arguments_list_p[0]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF: + { + return ecma_builtin_typedarray_prototype_index_of (&info, arguments_list_p, arguments_number); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LAST_INDEX_OF: + { + return ecma_builtin_typedarray_prototype_last_index_of (&info, arguments_list_p, arguments_number); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_COPY_WITHIN: + { + return ecma_builtin_typedarray_prototype_copy_within (this_arg, &info, arguments_list_p, arguments_number); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SLICE: + { + return ecma_builtin_typedarray_prototype_slice (this_arg, &info, arguments_list_p, arguments_number); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_LOCALE_STRING: + { + return ecma_builtin_typedarray_prototype_to_locale_string (&info); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_KEYS: + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_ENTRIES: + { + ecma_iterator_kind_t iter_id = + (builtin_routine_id == ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_KEYS) ? ECMA_ITERATOR_KEYS : ECMA_ITERATOR_ENTRIES; + + return ecma_typedarray_iterators_helper (this_arg, iter_id); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BUFFER_GETTER: + { + ecma_object_t *buffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + ecma_ref_object (buffer_p); + + return ecma_make_object_value (buffer_p); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTELENGTH_GETTER: + { + ecma_object_t *buffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (ecma_arraybuffer_is_detached (buffer_p)) + { + return ecma_make_uint32_value (0); + } + + uint32_t length = ecma_typedarray_get_length (typedarray_p); + uint8_t shift = ecma_typedarray_get_element_size_shift (typedarray_p); + return ecma_make_uint32_value (length << shift); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTEOFFSET_GETTER: + { + return ecma_make_uint32_value (ecma_typedarray_get_offset (typedarray_p)); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LENGTH_GETTER: + { + ecma_object_t *buffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (ecma_arraybuffer_is_detached (buffer_p)) + { + return ecma_make_uint32_value (0); + } + + return ecma_make_uint32_value (ecma_typedarray_get_length (typedarray_p)); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_STRING_TAG_GETTER: + { + ecma_extended_object_t *object_p = (ecma_extended_object_t *) typedarray_p; + return ecma_make_magic_string_value (ecma_get_typedarray_magic_string_id ((ecma_typedarray_type_t) object_p->u.cls.u1.typedarray_type)); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_typedarray_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h new file mode 100644 index 00000000..9cace683 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h @@ -0,0 +1,86 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %TypedArrayPrototype% description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/* ES2015 22.2.3.4 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_TYPEDARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Readonly accessor properties */ +/* ES2015 22.2.3.1 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BUFFER, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BUFFER_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +/* ES2015 22.2.3.2 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTELENGTH_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +/* ES2015 22.2.3.3 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_OFFSET_UL, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTEOFFSET_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ES2015 22.2.3.17 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_LENGTH, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LENGTH_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.1.3.13 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_STRING_TAG_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_COPY_WITHIN, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_COPY_WITHIN, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_ENTRIES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_EVERY, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_EVERY, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FILL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILL, 3, 1) +ROUTINE (LIT_MAGIC_STRING_FILTER, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILTER, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FIND, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FIND_INDEX, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND_INDEX, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FOR_EACH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_INCLUDES, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INCLUDES, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_AT, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_JOIN, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_JOIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_KEYS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LAST_INDEX_OF, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_MAP, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_MAP, 2, 1) +ROUTINE (LIT_MAGIC_STRING_REDUCE, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE, 2, 1) +ROUTINE (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE_RIGHT, 2, 1) +ROUTINE (LIT_MAGIC_STRING_REVERSE, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REVERSE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SET, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SET, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SLICE, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SLICE, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_SOME, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SOME, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SORT, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SORT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SUBARRAY, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SUBARRAY, 2, 2) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_LOCALE_STRING, 0, 0) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_STRING_UL, LIT_MAGIC_STRING_TO_STRING_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_VALUES, + LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_GLOBAL_SYMBOL_ITERATOR, + LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-template.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-template.inc.h new file mode 100644 index 00000000..7c9313fc --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-template.inc.h @@ -0,0 +1,50 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#ifndef TYPEDARRAY_BYTES_PER_ELEMENT +#error "Please define TYPEDARRAY_BYTES_PER_ELEMENT" +#endif /* !TYPEDARRAY_BYTES_PER_ELEMENT */ + +#ifndef TYPEDARRAY_MAGIC_STRING_ID +#error "Please define TYPEDARRAY_MAGIC_STRING_ID" +#endif /* !TYPEDARRAY_MAGIC_STRING_ID */ + +#ifndef TYPEDARRAY_BUILTIN_ID +#error "Please define TYPEDARRAY_BUILTIN_ID" +#endif /* !TYPEDARRAY_BUILTIN_ID */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ES2015 22.2.5 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 3, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ES2015 22.2.5.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U, TYPEDARRAY_BYTES_PER_ELEMENT, ECMA_PROPERTY_FIXED) + +/* ES2015 22.2.5 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, TYPEDARRAY_MAGIC_STRING_ID, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ES2015 22.2.5.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, TYPEDARRAY_BUILTIN_ID, ECMA_PROPERTY_FIXED) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" + +#undef TYPEDARRAY_BUILTIN_ID +#undef TYPEDARRAY_MAGIC_STRING_ID +#undef TYPEDARRAY_BYTES_PER_ELEMENT + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.cpp new file mode 100644 index 00000000..c91f9764 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.cpp @@ -0,0 +1,215 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-typedarray.inc.h" +#define BUILTIN_UNDERSCORED_ID typedarray +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup typedarray ECMA %TypedArray% object built-in + * @{ + */ + +/** + * The %TypedArray%.from routine + * + * See also: + * ES2015 22.2.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_from (ecma_value_t this_arg, /**< 'this' argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (!ecma_is_constructor (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_CONSTRUCTOR); + } + + ecma_value_t source; + ecma_value_t map_fn = ECMA_VALUE_UNDEFINED; + ecma_value_t this_in_fn = ECMA_VALUE_UNDEFINED; + + if (arguments_list_len == 0) + { + return ecma_raise_type_error (ECMA_ERR_NO_SOURCE_ARGUMENT); + } + + source = arguments_list_p[0]; + + if (arguments_list_len > 1) + { + map_fn = arguments_list_p[1]; + + if (!ecma_op_is_callable (map_fn)) + { + return ecma_raise_type_error (ECMA_ERR_THE_MAPFN_ARGUMENT_IS_NOT_CALLABLE); + } + + if (arguments_list_len > 2) + { + this_in_fn = arguments_list_p[2]; + } + } + + return ecma_op_typedarray_from (this_arg, source, map_fn, this_in_fn); + +} /* ecma_builtin_typedarray_from */ + +/** + * The %TypedArray%.of routine + * + * See also: + * ES2015 22.2.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_of (ecma_value_t this_arg, /**< 'this' argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + if (!ecma_is_constructor (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_CONSTRUCTOR); + } + + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (this_arg); + ecma_value_t len_val = ecma_make_uint32_value (arguments_list_len); + ecma_value_t ret_val = ecma_typedarray_create (constructor_obj_p, &len_val, 1); + ecma_free_value (len_val); + + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + return ret_val; + } + + uint32_t k = 0; + ecma_object_t *ret_obj_p = ecma_get_object_from_value (ret_val); + ecma_typedarray_info_t info = ecma_typedarray_get_info (ret_obj_p); + ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + ecma_deref_object (ret_obj_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_deref_object (ret_obj_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + lit_utf8_byte_t *buffer_p = ecma_typedarray_get_buffer (&info); + + while (k < arguments_list_len) + { + ecma_value_t set_element = setter_cb (buffer_p, arguments_list_p[k]); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_deref_object (ret_obj_p); + return set_element; + } + + k++; + buffer_p += info.element_size; + } + + return ret_val; +} /* ecma_builtin_typedarray_of */ + +/** + * Handle calling [[Call]] of built-in %TypedArray% object + * + * ES2015 22.2.1 If %TypedArray% is directly called or + * called as part of a new expression an exception is thrown + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_typedarray_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_TYPEDARRAY_INTRINSTIC_DIRECTLY_CALLED); +} /* ecma_builtin_typedarray_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in %TypedArray% object + * + * ES2015 22.2.1 If %TypedArray% is directly called or + * called as part of a new expression an exception is thrown + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_typedarray_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_TYPEDARRAY_INTRINSTIC_CALLED_BY_NEW_EXPRESSION); +} /* ecma_builtin_typedarray_dispatch_construct */ + +/** + * 22.2.2.4 get %TypedArray% [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_typedarray_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_typedarray_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.inc.h new file mode 100644 index 00000000..bc8ab47d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.inc.h @@ -0,0 +1,48 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %TypedArray% description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/* ES2015 22.2.2 */ +/* ES11 22.2.1.1 - value of length changed to 0 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ES2015 22.2.2 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_TYPED_ARRAY_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ES2015 22.2.2.3 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ + +/* ES2015 22.2.2.1 */ +ROUTINE (LIT_MAGIC_STRING_FROM, ecma_builtin_typedarray_from, NON_FIXED, 1) + +/* ES2015 22.2.2.2 */ +ROUTINE (LIT_MAGIC_STRING_OF, ecma_builtin_typedarray_of, NON_FIXED, 0) + +/* ES2015 22.2.2.4 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_typedarray_species_get, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.cpp new file mode 100644 index 00000000..691da4ba --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint16array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID uint16array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint16arrayprototype ECMA Uint16Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.inc.h new file mode 100644 index 00000000..ec055f66 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint16Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 2 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT16ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.cpp new file mode 100644 index 00000000..18e5c6b3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint16array.inc.h" +#define BUILTIN_UNDERSCORED_ID uint16array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint16array ECMA Uint16Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Uint16Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint16array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_UINT16_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_uint16array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Uint16Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint16array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_UINT16_ARRAY); +} /* ecma_builtin_uint16array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.inc.h new file mode 100644 index 00000000..2c0af1f0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint16Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 2 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_UINT16_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT16ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.cpp new file mode 100644 index 00000000..4b5e3842 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint32array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID uint32array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint32arrayprototype ECMA Uint32Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.inc.h new file mode 100644 index 00000000..a04098a3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint32Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT32ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.cpp new file mode 100644 index 00000000..cb495615 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.cpp @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint32array.inc.h" +#define BUILTIN_UNDERSCORED_ID uint32array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint32array ECMA Uint32Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Uint32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint32array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_UINT32_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_uint32array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Uint32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint32array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_UINT32_ARRAY); +} /* ecma_builtin_uint32array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.inc.h new file mode 100644 index 00000000..fd0389a4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint32Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_UINT32_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT32ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.cpp new file mode 100644 index 00000000..8a8edb4a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint8array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID uint8array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint8arrayprototype ECMA Uint8Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.inc.h new file mode 100644 index 00000000..07f94b0b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint8Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT8ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.cpp new file mode 100644 index 00000000..5d20b7aa --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint8array.inc.h" +#define BUILTIN_UNDERSCORED_ID uint8array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint8array ECMA Uint8Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Uint8Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint8array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_UINT8_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_uint8array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Uint8Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint8array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_UINT8_ARRAY); +} /* ecma_builtin_uint8array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.inc.h new file mode 100644 index 00000000..d0259e9b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint8Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_UINT8_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT8ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.cpp new file mode 100644 index 00000000..534014b1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint8clampedarray-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID uint8clampedarray_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint8clampedarrayprototype ECMA Uint8ClampedArray.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.inc.h new file mode 100644 index 00000000..8564828a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint8ClampedArray prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.cpp new file mode 100644 index 00000000..9b348c24 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.cpp @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint8clampedarray.inc.h" +#define BUILTIN_UNDERSCORED_ID uint8clampedarray +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint8clampedarray ECMA Uint8ClampedArray object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Uint8ClampedArray + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint8clampedarray_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_UINT8_CLAMPED_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_uint8clampedarray_dispatch_call */ + +/** + * Handle calling [[Construct]] of Uint8ClampedArray + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint8clampedarray_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_UINT8_CLAMPED_ARRAY); +} /* ecma_builtin_uint8clampedarray_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.inc.h new file mode 100644 index 00000000..d3f0eb1f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint8ClampedArray description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/meson.build b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/meson.build new file mode 100644 index 00000000..0f00f5c6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/meson.build @@ -0,0 +1,59 @@ +source_file = [ +'ecma-builtin-bigint64array-prototype.inc.h', +'ecma-builtin-bigint64array.inc.h', +'ecma-builtin-biguint64array-prototype.inc.h', +'ecma-builtin-biguint64array.inc.h', +'ecma-builtin-float32array-prototype.inc.h', +'ecma-builtin-float32array.inc.h', +'ecma-builtin-float64array-prototype.inc.h', +'ecma-builtin-float64array.inc.h', +'ecma-builtin-int16array-prototype.inc.h', +'ecma-builtin-int16array.inc.h', +'ecma-builtin-int32array-prototype.inc.h', +'ecma-builtin-int32array.inc.h', +'ecma-builtin-int8array-prototype.inc.h', +'ecma-builtin-int8array.inc.h', +'ecma-builtin-typedarray-helpers.h', +'ecma-builtin-typedarray-prototype-template.inc.h', +'ecma-builtin-typedarray-prototype.inc.h', +'ecma-builtin-typedarray-template.inc.h', +'ecma-builtin-typedarray.inc.h', +'ecma-builtin-uint16array-prototype.inc.h', +'ecma-builtin-uint16array.inc.h', +'ecma-builtin-uint32array-prototype.inc.h', +'ecma-builtin-uint32array.inc.h', +'ecma-builtin-uint8array-prototype.inc.h', +'ecma-builtin-uint8array.inc.h', +'ecma-builtin-uint8clampedarray-prototype.inc.h', +'ecma-builtin-uint8clampedarray.inc.h', +'ecma-builtin-bigint64array-prototype.cpp', +'ecma-builtin-bigint64array.cpp', +'ecma-builtin-biguint64array-prototype.cpp', +'ecma-builtin-biguint64array.cpp', +'ecma-builtin-float32array-prototype.cpp', +'ecma-builtin-float32array.cpp', +'ecma-builtin-float64array-prototype.cpp', +'ecma-builtin-float64array.cpp', +'ecma-builtin-int16array-prototype.cpp', +'ecma-builtin-int16array.cpp', +'ecma-builtin-int32array-prototype.cpp', +'ecma-builtin-int32array.cpp', +'ecma-builtin-int8array-prototype.cpp', +'ecma-builtin-int8array.cpp', +'ecma-builtin-typedarray-helpers.cpp', +'ecma-builtin-typedarray-prototype.cpp', +'ecma-builtin-typedarray.cpp', +'ecma-builtin-uint16array-prototype.cpp', +'ecma-builtin-uint16array.cpp', +'ecma-builtin-uint32array-prototype.cpp', +'ecma-builtin-uint32array.cpp', +'ecma-builtin-uint8array-prototype.cpp', +'ecma-builtin-uint8array.cpp', +'ecma-builtin-uint8clampedarray-prototype.cpp', +'ecma-builtin-uint8clampedarray.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/meson.build b/src/loaders/lottie/jerryscript/jerry-core/ecma/meson.build new file mode 100644 index 00000000..31e83fc9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/meson.build @@ -0,0 +1,3 @@ +subdir('base') +subdir('builtin-objects') +subdir('operations') diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.cpp new file mode 100644 index 00000000..fd0c6798 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.cpp @@ -0,0 +1,461 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arguments-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaargumentsobject ECMA arguments object related routines + * @{ + */ + +/** + * Arguments object creation operation. + * + * See also: ECMA-262 v5, 10.6 + * + * @return ecma value of arguments object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, /**< shared context data */ + ecma_object_t *lex_env_p) /**< lexical environment the Arguments + * object is created for */ +{ + ecma_object_t *func_obj_p = shared_p->header.function_object_p; + const ecma_compiled_code_t *bytecode_data_p = shared_p->header.bytecode_header_p; + uint16_t formal_params_number; + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + formal_params_number = ((cbc_uint16_arguments_t *) bytecode_data_p)->argument_end; + } + else + { + formal_params_number = ((cbc_uint8_arguments_t *) bytecode_data_p)->argument_end; + } + + uint32_t object_size = sizeof (ecma_unmapped_arguments_t); + uint32_t saved_arg_count = JERRY_MAX (shared_p->arg_list_len, formal_params_number); + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + object_size = sizeof (ecma_mapped_arguments_t); + } + + ecma_object_t *obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), + object_size + (saved_arg_count * sizeof (ecma_value_t)), + ECMA_OBJECT_TYPE_CLASS); + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p; + + arguments_p->header.u.cls.type = ECMA_OBJECT_CLASS_ARGUMENTS; + arguments_p->header.u.cls.u1.arguments_flags = ECMA_ARGUMENTS_OBJECT_NO_FLAGS; + arguments_p->header.u.cls.u2.formal_params_number = formal_params_number; + arguments_p->header.u.cls.u3.arguments_number = 0; + arguments_p->callee = ecma_make_object_value (func_obj_p); + + ecma_value_t *argv_p = (ecma_value_t *) (((uint8_t *) obj_p) + object_size); + + for (uint32_t i = 0; i < shared_p->arg_list_len; i++) + { + argv_p[i] = ecma_copy_value_if_not_object (shared_p->arg_list_p[i]); + } + + for (uint32_t i = shared_p->arg_list_len; i < saved_arg_count; i++) + { + argv_p[i] = ECMA_VALUE_UNDEFINED; + } + + arguments_p->header.u.cls.u3.arguments_number = shared_p->arg_list_len; + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) obj_p; + + ECMA_SET_INTERNAL_VALUE_POINTER (mapped_arguments_p->lex_env, lex_env_p); + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_MAPPED; + +#if JERRY_SNAPSHOT_EXEC + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) + { + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE; + mapped_arguments_p->u.byte_code_p = (ecma_compiled_code_t *) bytecode_data_p; + } + else +#endif /* JERRY_SNAPSHOT_EXEC */ + { + ECMA_SET_INTERNAL_VALUE_POINTER (mapped_arguments_p->u.byte_code, bytecode_data_p); + } + + /* Static snapshots are not ref counted. */ + if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) == 0) + { + ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p); + } + + ecma_value_t *formal_parameter_start_p; + formal_parameter_start_p = ecma_compiled_code_resolve_arguments_start ((ecma_compiled_code_t *) bytecode_data_p); + + for (uint32_t i = 0; i < formal_params_number; i++) + { + /* For legacy (non-strict) argument definition the trailing duplicated arguments cannot be lazy instantiated + E.g: function f (a,a,a,a) {} */ + if (JERRY_UNLIKELY (ecma_is_value_empty (formal_parameter_start_p[i]))) + { + ecma_property_value_t *prop_value_p; + ecma_string_t *prop_name_p = ecma_new_ecma_string_from_uint32 (i); + + prop_value_p = + ecma_create_named_data_property (obj_p, prop_name_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + + ecma_deref_ecma_string (prop_name_p); + + prop_value_p->value = argv_p[i]; + argv_p[i] = ECMA_VALUE_EMPTY; + } + } + } + + return ecma_make_object_value (obj_p); +} /* ecma_op_create_arguments_object */ + +/** + * [[DefineOwnProperty]] ecma Arguments object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 10.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property + * descriptor */ +{ + /* 3. */ + ecma_value_t ret_value = ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p); + + if (ECMA_IS_VALUE_ERROR (ret_value) + || !(((ecma_extended_object_t *) object_p)->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) + { + return ret_value; + } + + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) object_p; + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index >= mapped_arguments_p->unmapped.header.u.cls.u2.formal_params_number) + { + return ret_value; + } + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (ecma_is_value_empty (argv_p[index]) || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK) + { + return ret_value; + } + + if (property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + ecma_free_value_if_not_object (argv_p[index]); + argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK; + return ret_value; + } + + if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); + + ecma_value_t completion = ecma_op_set_mutable_binding (lex_env_p, name_p, property_desc_p->value, true); + + JERRY_ASSERT (ecma_is_value_empty (completion)); + } + + if ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) && !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)) + { + ecma_free_value_if_not_object (argv_p[index]); + argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK; + } + + return ret_value; +} /* ecma_op_arguments_object_define_own_property */ + +/** + * Try to lazy instantiate the given property of a mapped/unmapped arguments object + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARGUMENTS)); + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p; + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + ecma_property_value_t *prop_value_p; + ecma_property_t *prop_p; + uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; + uint8_t flags = arguments_p->header.u.cls.u1.arguments_flags; + + if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + if (index >= arguments_number || ecma_is_value_empty (argv_p[index])) + { + return NULL; + } + + JERRY_ASSERT (argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK); + + prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE_WRITABLE, + &prop_p); + + /* Passing the reference */ + prop_value_p->value = argv_p[index]; + + argv_p[index] = ECMA_VALUE_UNDEFINED; + return prop_p; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH) + && !(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)) + { + prop_value_p = ecma_create_named_data_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, + &prop_p); + + prop_value_p->value = ecma_make_uint32_value (arguments_number); + return prop_p; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE) + && !(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)) + { + if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, + &prop_p); + + prop_value_p->value = arguments_p->callee; + } + else + { + ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); + + ecma_create_named_accessor_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE), + thrower_p, + thrower_p, + ECMA_PROPERTY_BUILT_IN_FIXED, + &prop_p); + } + return prop_p; + } + + if (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR) + && !(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)) + { + prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, + &prop_p); + + prop_value_p->value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT), + LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES); + + JERRY_ASSERT (ecma_is_value_object (prop_value_p->value)); + ecma_deref_object (ecma_get_object_from_value (prop_value_p->value)); + return prop_p; + } + + return NULL; +} /* ecma_op_arguments_object_try_to_lazy_instantiate_property */ + +/** + * Delete configurable properties of arguments object + */ +void +ecma_op_arguments_delete_built_in_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED; + return; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE)) + { + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)); + JERRY_ASSERT (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED; + return; + } + + if (ecma_prop_name_is_symbol (property_name_p)) + { + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)); + JERRY_ASSERT (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR)); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED; + return; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + + if (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1); + } + + JERRY_ASSERT (argv_p[index] == ECMA_VALUE_UNDEFINED || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK); + + argv_p[index] = ECMA_VALUE_EMPTY; +} /* ecma_op_arguments_delete_built_in_property */ + +/** + * List names of an arguments object's lazy instantiated properties + */ +void +ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, /**< arguments object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)); + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p; + + uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; + uint8_t flags = arguments_p->header.u.cls.u1.arguments_flags; + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + + if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) obj_p) + 1); + } + + for (uint32_t index = 0; index < arguments_number; index++) + { + if (!ecma_is_value_empty (argv_p[index])) + { + ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); + ecma_collection_push_back (prop_names_p, ecma_make_string_value (index_string_p)); + prop_counter_p->array_index_named_props++; + } + } + } + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + if (!(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + + if (!(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLEE)); + prop_counter_p->string_named_props++; + } + } + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) && !(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)) + { + ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR); + ecma_collection_push_back (prop_names_p, ecma_make_symbol_value (symbol_p)); + prop_counter_p->symbol_named_props++; + } +} /* ecma_op_arguments_object_list_lazy_property_names */ + +/** + * Get the formal parameter name corresponding to the given property index + * + * @return pointer to the formal parameter name + */ +ecma_string_t * +ecma_op_arguments_object_get_formal_parameter (ecma_mapped_arguments_t *mapped_arguments_p, /**< mapped arguments + * object */ + uint32_t index) /**< formal parameter index */ +{ + JERRY_ASSERT (mapped_arguments_p->unmapped.header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED); + JERRY_ASSERT (index < mapped_arguments_p->unmapped.header.u.cls.u2.formal_params_number); + + ecma_compiled_code_t *byte_code_p; + +#if JERRY_SNAPSHOT_EXEC + if (mapped_arguments_p->unmapped.header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE) + { + byte_code_p = mapped_arguments_p->u.byte_code_p; + } + else +#endif /* JERRY_SNAPSHOT_EXEC */ + { + byte_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, mapped_arguments_p->u.byte_code); + } + + ecma_value_t *formal_param_names_p = ecma_compiled_code_resolve_arguments_start (byte_code_p); + + return ecma_get_string_from_value (formal_param_names_p[index]); +} /* ecma_op_arguments_object_get_formal_parameter */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.h new file mode 100644 index 00000000..755b755c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.h @@ -0,0 +1,42 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ARGUMENTS_OBJECT_H +#define ECMA_ARGUMENTS_OBJECT_H + +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "vm-defines.h" + +ecma_value_t ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, ecma_object_t *lex_env_p); + +ecma_value_t ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); + +ecma_property_t *ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object_p, + ecma_string_t *property_name_p); + +void ecma_op_arguments_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +void ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +ecma_string_t *ecma_op_arguments_object_get_formal_parameter (ecma_mapped_arguments_t *mapped_arguments_p, + uint32_t index); +#endif /* !ECMA_ARGUMENTS_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.cpp new file mode 100644 index 00000000..5da891d7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.cpp @@ -0,0 +1,1215 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-array-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-property-hashmap.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaarrayobject ECMA Array object related routines + * @{ + */ + +/** + * Property name type flag for array indices. + */ +#define ECMA_FAST_ARRAY_UINT_DIRECT_STRING_PROP_TYPE (ECMA_DIRECT_STRING_UINT << ECMA_PROPERTY_NAME_TYPE_SHIFT) + +/** + * Allocate a new array object with the given length + * + * @return pointer to the constructed array object + */ +static ecma_object_t * +ecma_op_alloc_array_object (uint32_t length) /**< length of the new array */ +{ +#if JERRY_BUILTIN_ARRAY + ecma_object_t *array_prototype_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE); +#else /* !JERRY_BUILTIN_ARRAY */ + ecma_object_t *array_prototype_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#endif /* JERRY_BUILTIN_ARRAY */ + + ecma_object_t *object_p = + ecma_create_object (array_prototype_object_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_ARRAY); + + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARRAY type. + * + * See also: ecma_object_get_class_name + */ + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.array.length = length; + ext_obj_p->u.array.length_prop_and_hole_count = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_VIRTUAL; + + return object_p; +} /* ecma_op_alloc_array_object */ + +/** + * Check whether the given object is fast-access mode array + * + * @return true - if the object is fast-access mode array + * false, otherwise + */ +bool +ecma_op_object_is_fast_array (ecma_object_t *object_p) /**< ecma-object */ +{ + return (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY + && ecma_op_array_is_fast_array ((ecma_extended_object_t *) object_p)); +} /* ecma_op_object_is_fast_array */ + +/** + * Check whether the given array object is fast-access mode array + * + * @return true - if the array object is fast-access mode array + * false, otherwise + */ +bool +ecma_op_array_is_fast_array (ecma_extended_object_t *array_p) /**< ecma-array-object */ +{ + JERRY_ASSERT (ecma_get_object_base_type ((ecma_object_t *) array_p) == ECMA_OBJECT_BASE_TYPE_ARRAY); + + return array_p->u.array.length_prop_and_hole_count & ECMA_FAST_ARRAY_FLAG; +} /* ecma_op_array_is_fast_array */ + +/** + * Allocate a new array object with the given length + * + * Note: The returned array can be normal of fast access mode + * + * @return pointer to the constructed array object + */ +ecma_object_t * +ecma_op_new_array_object (uint32_t length) /**< length of the new array */ +{ + ecma_object_t *object_p = ecma_op_alloc_array_object (length); + + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (length); + ecma_value_t *values_p = NULL; + + if (length > 0) + { + if (length >= ECMA_FAST_ARRAY_MAX_HOLE_COUNT) + { + return object_p; + } + + values_p = (ecma_value_t *) jmem_heap_alloc_block_null_on_error (aligned_length * sizeof (ecma_value_t)); + + if (JERRY_UNLIKELY (values_p == NULL)) + { + return object_p; + } + } + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.array.length_prop_and_hole_count |= ECMA_FAST_ARRAY_FLAG; + ext_obj_p->u.array.length_prop_and_hole_count += length * ECMA_FAST_ARRAY_HOLE_ONE; + + for (uint32_t i = 0; i < aligned_length; i++) + { + values_p[i] = ECMA_VALUE_ARRAY_HOLE; + } + + JERRY_ASSERT (object_p->u1.property_list_cp == JMEM_CP_NULL); + ECMA_SET_POINTER (object_p->u1.property_list_cp, values_p); + return object_p; +} /* ecma_op_new_array_object */ + +/** + * Allocate a new array object from the given length + * + * Note: The returned array can be normal of fast access mode + * + * @return NULL - if the given length is invalid + * pointer to the constructed array object - otherwise + */ +ecma_object_t * +ecma_op_new_array_object_from_length (ecma_length_t length) /**< length of the new array */ +{ + if (length > UINT32_MAX) + { + ecma_raise_range_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + return NULL; + } + + return ecma_op_new_array_object ((uint32_t) length); +} /* ecma_op_new_array_object_from_length */ + +/** + * Allocate a new array object from the given buffer + * + * Note: The returned array can be normal of fast access mode + * + * @return ecma_value - constructed array object + */ +ecma_value_t +ecma_op_new_array_object_from_buffer (const ecma_value_t *args_p, /**< array element list */ + uint32_t length) /**< number of array elements */ +{ + if (length == 0) + { + return ecma_make_object_value (ecma_op_new_array_object (0)); + } + + ecma_object_t *object_p = ecma_op_alloc_array_object (length); + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (length); + ecma_value_t *values_p; + values_p = (ecma_value_t *) jmem_heap_alloc_block_null_on_error (aligned_length * sizeof (ecma_value_t)); + + if (values_p != NULL) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.array.length_prop_and_hole_count |= ECMA_FAST_ARRAY_FLAG; + JERRY_ASSERT (object_p->u1.property_list_cp == JMEM_CP_NULL); + + for (uint32_t i = 0; i < length; i++) + { + JERRY_ASSERT (!ecma_is_value_array_hole (args_p[i])); + values_p[i] = ecma_copy_value_if_not_object (args_p[i]); + } + + for (uint32_t i = length; i < aligned_length; i++) + { + values_p[i] = ECMA_VALUE_ARRAY_HOLE; + } + + ECMA_SET_POINTER (object_p->u1.property_list_cp, values_p); + } + else + { + for (uint32_t i = 0; i < length; i++) + { + JERRY_ASSERT (!ecma_is_value_array_hole (args_p[i])); + + ecma_string_t *prop_name_p = ecma_new_ecma_string_from_uint32 (i); + ecma_property_value_t *prop_value_p; + prop_value_p = + ecma_create_named_data_property (object_p, prop_name_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + ecma_deref_ecma_string (prop_name_p); + prop_value_p->value = ecma_copy_value_if_not_object (args_p[i]); + } + } + + return ecma_make_object_value (object_p); +} /* ecma_op_new_array_object_from_buffer */ + +/** + * Allocate a new fast acces mode array object from the given collection + * + * Note: The given collection will be unavailable after and it's underlying buffer is reused + * + * @return ecma_value - constructed fast access mode array object + */ +ecma_value_t +ecma_op_new_array_object_from_collection (ecma_collection_t *collection_p, /**< collection to create array from */ + bool unref_objects) /**< true - if the collection potentially + containts objects + false - otherwise */ +{ + const uint32_t item_count = collection_p->item_count; + + if (item_count == 0) + { + ecma_collection_destroy (collection_p); + return ecma_make_object_value (ecma_op_new_array_object (0)); + } + + ecma_object_t *object_p; + ecma_value_t *buffer_p = collection_p->buffer_p; + const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity); + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (collection_p->item_count); + + jmem_heap_free_block (collection_p, sizeof (ecma_collection_t)); + buffer_p = (ecma_value_t *) jmem_heap_realloc_block (buffer_p, old_size, aligned_length * sizeof (ecma_value_t)); + object_p = (ecma_object_t *) ecma_op_alloc_array_object (item_count); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.array.length_prop_and_hole_count |= ECMA_FAST_ARRAY_FLAG; + JERRY_ASSERT (object_p->u1.property_list_cp == JMEM_CP_NULL); + JERRY_ASSERT (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE); + ECMA_SET_POINTER (object_p->u1.property_list_cp, buffer_p); + + if (JERRY_UNLIKELY (unref_objects)) + { + for (uint32_t i = 0; i < item_count; i++) + { + /* Strong references from the collection are no longer needed + since GC will mark these object as a fast access mode array properties */ + ecma_deref_if_object (buffer_p[i]); + } + } + + for (uint32_t i = item_count; i < aligned_length; i++) + { + buffer_p[i] = ECMA_VALUE_ARRAY_HOLE; + } + + return ecma_make_object_value (object_p); +} /* ecma_op_new_array_object_from_collection */ + +/** + * Converts a fast access mode array back to a normal property list based array + */ +void +ecma_fast_array_convert_to_normal (ecma_object_t *object_p) /**< fast access mode array object */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + + if (object_p->u1.property_list_cp == JMEM_CP_NULL) + { + ext_obj_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_FAST_ARRAY_FLAG; + return; + } + + uint32_t length = ext_obj_p->u.array.length; + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (length); + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + ecma_ref_object (object_p); + + ecma_property_pair_t *property_pair_p = NULL; + jmem_cpointer_t next_property_pair_cp = JMEM_CP_NULL; + + uint32_t prop_index = 1; + int32_t index = (int32_t) (length - 1); + + while (index >= 0) + { + if (ecma_is_value_array_hole (values_p[index])) + { + index--; + continue; + } + + if (prop_index == 1) + { + property_pair_p = ecma_alloc_property_pair (); + property_pair_p->header.next_property_cp = next_property_pair_cp; + property_pair_p->names_cp[0] = LIT_INTERNAL_MAGIC_STRING_DELETED; + property_pair_p->header.types[0] = ECMA_PROPERTY_TYPE_DELETED; + ECMA_SET_NON_NULL_POINTER (next_property_pair_cp, property_pair_p); + } + + JERRY_ASSERT (index <= ECMA_DIRECT_STRING_MAX_IMM); + + property_pair_p->names_cp[prop_index] = (jmem_cpointer_t) index; + property_pair_p->header.types[prop_index] = + (ecma_property_t) (ECMA_PROPERTY_FLAG_DATA | ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE + | ECMA_FAST_ARRAY_UINT_DIRECT_STRING_PROP_TYPE); + + property_pair_p->values[prop_index].value = values_p[index]; + + index--; + prop_index = !prop_index; + } + + ext_obj_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_FAST_ARRAY_FLAG; + jmem_heap_free_block (values_p, aligned_length * sizeof (ecma_value_t)); + ECMA_SET_POINTER (object_p->u1.property_list_cp, property_pair_p); + + ecma_deref_object (object_p); +} /* ecma_fast_array_convert_to_normal */ + +/** + * [[Put]] operation for a fast access mode array + * + * @return false - If the property name is not array index, or the requested index to be set + * would result too much array hole in the underlying buffer. The these cases + * the array is converted back to normal property list based array. + * true - If the indexed property can be set with/without resizing the underlying buffer. + */ +bool +ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode array object */ + uint32_t index, /**< property name index */ + ecma_value_t value) /**< value to be set */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + uint32_t old_length = ext_obj_p->u.array.length; + + ecma_value_t *values_p; + + if (JERRY_LIKELY (index < old_length)) + { + JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); + + values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + if (ecma_is_value_array_hole (values_p[index])) + { + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; + } + else + { + ecma_free_value_if_not_object (values_p[index]); + } + + values_p[index] = ecma_copy_value_if_not_object (value); + + return true; + } + + uint32_t old_holes = ext_obj_p->u.array.length_prop_and_hole_count; + uint32_t new_holes = index - old_length; + + if (JERRY_UNLIKELY (new_holes > (ECMA_FAST_ARRAY_MAX_HOLE_COUNT - (old_holes >> ECMA_FAST_ARRAY_HOLE_SHIFT)))) + { + ecma_fast_array_convert_to_normal (object_p); + + return false; + } + + uint32_t new_length = index + 1; + + JERRY_ASSERT (new_length < UINT32_MAX); + + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length); + + if (JERRY_LIKELY (index < aligned_length)) + { + JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); + + values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + /* This area is filled with ECMA_VALUE_ARRAY_HOLE, but not counted in u.array.length_prop_and_hole_count */ + JERRY_ASSERT (ecma_is_value_array_hole (values_p[index])); + ext_obj_p->u.array.length_prop_and_hole_count += new_holes * ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length = new_length; + } + else + { + values_p = ecma_fast_array_extend (object_p, new_length); + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; + } + + values_p[index] = ecma_copy_value_if_not_object (value); + + return true; +} /* ecma_fast_array_set_property */ + +/** + * Get the number of array holes in a fast access array object + * + * @return number of array holes in a fast access array object + */ +uint32_t +ecma_fast_array_get_hole_count (ecma_object_t *obj_p) /**< fast access mode array object */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (obj_p)); + + return ((ecma_extended_object_t *) obj_p)->u.array.length_prop_and_hole_count >> ECMA_FAST_ARRAY_HOLE_SHIFT; +} /* ecma_fast_array_get_hole_count */ + +/** + * Extend the underlying buffer of a fast mode access array for the given new length + * + * @return pointer to the extended underlying buffer + */ +ecma_value_t * +ecma_fast_array_extend (ecma_object_t *object_p, /**< fast access mode array object */ + uint32_t new_length) /**< new length of the fast access mode array */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + uint32_t old_length = ext_obj_p->u.array.length; + + JERRY_ASSERT (old_length < new_length); + + ecma_ref_object (object_p); + + ecma_value_t *new_values_p; + const uint32_t old_length_aligned = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length); + const uint32_t new_length_aligned = ECMA_FAST_ARRAY_ALIGN_LENGTH (new_length); + + if (object_p->u1.property_list_cp == JMEM_CP_NULL) + { + new_values_p = (ecma_value_t *) jmem_heap_alloc_block (new_length_aligned * sizeof (ecma_value_t)); + } + else + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + new_values_p = (ecma_value_t *) jmem_heap_realloc_block (values_p, + old_length_aligned * sizeof (ecma_value_t), + new_length_aligned * sizeof (ecma_value_t)); + } + + for (uint32_t i = old_length; i < new_length_aligned; i++) + { + new_values_p[i] = ECMA_VALUE_ARRAY_HOLE; + } + + ext_obj_p->u.array.length_prop_and_hole_count += (new_length - old_length) * ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length = new_length; + + ECMA_SET_NON_NULL_POINTER (object_p->u1.property_list_cp, new_values_p); + + ecma_deref_object (object_p); + return new_values_p; +} /* ecma_fast_array_extend */ + +/** + * Delete the array object's property referenced by its value pointer. + * + * Note: specified property must be owned by specified object. + * + * @return true, if the property is deleted + * false, otherwise + */ +bool +ecma_array_object_delete_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + + if (!ecma_op_object_is_fast_array (object_p)) + { + return false; + } + + JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); + + uint32_t index = ecma_string_get_array_index (property_name_p); + + JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); + JERRY_ASSERT (index < ext_obj_p->u.array.length); + + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + if (ecma_is_value_array_hole (values_p[index])) + { + return true; + } + + ecma_free_value_if_not_object (values_p[index]); + + values_p[index] = ECMA_VALUE_ARRAY_HOLE; + ext_obj_p->u.array.length_prop_and_hole_count += ECMA_FAST_ARRAY_HOLE_ONE; + return true; +} /* ecma_array_object_delete_property */ + +/** + * Low level delete of fast access mode array items + * + * @return the updated value of new_length + */ +uint32_t +ecma_delete_fast_array_properties (ecma_object_t *object_p, /**< fast access mode array */ + uint32_t new_length) /**< new length of the fast access mode array */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + + ecma_ref_object (object_p); + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + uint32_t old_length = ext_obj_p->u.array.length; + const uint32_t old_aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length); + JERRY_ASSERT (new_length < old_length); + + for (uint32_t i = new_length; i < old_length; i++) + { + if (ecma_is_value_array_hole (values_p[i])) + { + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; + } + else + { + ecma_free_value_if_not_object (values_p[i]); + } + } + + jmem_cpointer_t new_property_list_cp; + + if (new_length == 0) + { + jmem_heap_free_block (values_p, old_aligned_length * sizeof (ecma_value_t)); + new_property_list_cp = JMEM_CP_NULL; + } + else + { + const uint32_t new_aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (new_length); + + ecma_value_t *new_values_p; + new_values_p = (ecma_value_t *) jmem_heap_realloc_block (values_p, + old_aligned_length * sizeof (ecma_value_t), + new_aligned_length * sizeof (ecma_value_t)); + + for (uint32_t i = new_length; i < new_aligned_length; i++) + { + new_values_p[i] = ECMA_VALUE_ARRAY_HOLE; + } + + ECMA_SET_NON_NULL_POINTER (new_property_list_cp, new_values_p); + } + + ext_obj_p->u.array.length = new_length; + object_p->u1.property_list_cp = new_property_list_cp; + + ecma_deref_object (object_p); + + return new_length; +} /* ecma_delete_fast_array_properties */ + +/** + * Update the length of a fast access mode array to a new length + * + * Note: if the new length would result too much array hole in the underlying arraybuffer + * the array is converted back to normal property list based array + */ +static void +ecma_fast_array_set_length (ecma_object_t *object_p, /**< fast access mode array object */ + uint32_t new_length) /**< new length of the fast access mode array object*/ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + uint32_t old_length = ext_obj_p->u.array.length; + + JERRY_ASSERT (new_length >= old_length); + + if (new_length == old_length) + { + return; + } + + uint32_t old_holes = ext_obj_p->u.array.length_prop_and_hole_count; + uint32_t new_holes = new_length - old_length; + + if (JERRY_UNLIKELY (new_holes > (ECMA_FAST_ARRAY_MAX_HOLE_COUNT - (old_holes >> ECMA_FAST_ARRAY_HOLE_SHIFT)))) + { + ecma_fast_array_convert_to_normal (object_p); + } + else + { + ecma_fast_array_extend (object_p, new_length); + } +} /* ecma_fast_array_set_length */ + +/** + * Get collection of property names of a fast access mode array object + * + * Note: Since the fast array object only contains indexed, enumerable, writable, configurable properties + * we can return a collection of non-array hole array indices + * + * @return collection of strings - property names + */ +ecma_collection_t * +ecma_fast_array_object_own_property_keys (ecma_object_t *object_p, /**< fast access mode array object */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_collection_t *ret_p = ecma_new_collection (); + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + uint32_t length = ext_obj_p->u.array.length; + + if (length != 0) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + for (uint32_t i = 0; i < length; i++) + { + if (ecma_is_value_array_hole (values_p[i])) + { + continue; + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (i); + + ecma_collection_push_back (ret_p, ecma_make_string_value (index_str_p)); + } + } + } + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + ecma_collection_push_back (ret_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + } + + return ret_p; +} /* ecma_fast_array_object_own_property_keys */ + +/** + * Array object creation with custom prototype. + * + * See also: ECMA-262 v6, 9.4.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_object_t * +ecma_op_array_species_create (ecma_object_t *original_array_p, /**< The object from whom the new array object + * is being created */ + ecma_length_t length) /**< length of the array */ +{ + ecma_value_t constructor = ECMA_VALUE_UNDEFINED; + ecma_value_t original_array = ecma_make_object_value (original_array_p); + + ecma_value_t is_array = ecma_is_value_array (original_array); + + if (ECMA_IS_VALUE_ERROR (is_array)) + { + return NULL; + } + + if (ecma_is_value_true (is_array)) + { + constructor = ecma_op_object_get_by_magic_id (original_array_p, LIT_MAGIC_STRING_CONSTRUCTOR); + if (ECMA_IS_VALUE_ERROR (constructor)) + { + return NULL; + } + +#if JERRY_BUILTIN_REALMS + if (ecma_is_constructor (constructor)) + { + ecma_object_t *constructor_p = ecma_get_object_from_value (constructor); + ecma_global_object_t *global_object_p = ecma_op_function_get_function_realm (constructor_p); + + if ((ecma_object_t *) global_object_p != ecma_builtin_get_global () + && constructor_p == ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_ARRAY)) + { + ecma_deref_object (constructor_p); + constructor = ECMA_VALUE_UNDEFINED; + } + } +#endif /* JERRY_BUILTIN_REALMS */ + + if (ecma_is_value_object (constructor)) + { + ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor); + constructor = ecma_op_object_get_by_symbol_id (ctor_object_p, LIT_GLOBAL_SYMBOL_SPECIES); + ecma_deref_object (ctor_object_p); + + if (ECMA_IS_VALUE_ERROR (constructor)) + { + return NULL; + } + + if (ecma_is_value_null (constructor)) + { + constructor = ECMA_VALUE_UNDEFINED; + } + } + } + + if (ecma_is_value_undefined (constructor)) + { + return ecma_op_new_array_object_from_length (length); + } + + if (!ecma_is_constructor (constructor)) + { + ecma_free_value (constructor); + ecma_raise_type_error (ECMA_ERR_INVALID_SPECIES_CONSTRUCTOR); + return NULL; + } + + ecma_value_t len_val = ecma_make_length_value (length); + ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor); + ecma_value_t ret_val = ecma_op_function_construct (ctor_object_p, ctor_object_p, &len_val, 1); + + ecma_deref_object (ctor_object_p); + ecma_free_value (len_val); + + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + return NULL; + } + + return ecma_get_object_from_value (ret_val); +} /* ecma_op_array_species_create */ + +/** + * CreateArrayIterator Abstract Operation + * + * See also: + * ECMA-262 v6, 22.1.5.1 + * + * Referenced by: + * ECMA-262 v6, 22.1.3.4 + * ECMA-262 v6, 22.1.3.13 + * ECMA-262 v6, 22.1.3.29 + * ECMA-262 v6, 22.1.3.30 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return array iterator object + */ +ecma_value_t +ecma_op_create_array_iterator (ecma_object_t *obj_p, /**< array object */ + ecma_iterator_kind_t kind) /**< array iterator kind */ +{ + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE); + + return ecma_op_create_iterator_object (ecma_make_object_value (obj_p), + prototype_obj_p, + ECMA_OBJECT_CLASS_ARRAY_ITERATOR, + kind); +} /* ecma_op_create_array_iterator */ + +/** + * Low level delete of array items from new_length to old_length + * + * Note: new_length must be less than old_length + * + * @return the updated value of new_length + */ +static uint32_t +ecma_delete_array_properties (ecma_object_t *object_p, /**< object */ + uint32_t new_length, /**< new length */ + uint32_t old_length) /**< old length */ +{ + JERRY_ASSERT (new_length < old_length); + JERRY_ASSERT (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY); + + if (ecma_op_object_is_fast_array (object_p)) + { + return ecma_delete_fast_array_properties (object_p, new_length); + } + + /* First the minimum value of new_length is updated. */ + jmem_cpointer_t current_prop_cp = object_p->u1.property_list_cp; + + if (current_prop_cp == JMEM_CP_NULL) + { + return new_length; + } + + ecma_property_header_t *current_prop_p; + +#if JERRY_PROPERTY_HASHMAP + current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp); + + if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + current_prop_cp = current_prop_p->next_property_cp; + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (current_prop_cp != JMEM_CP_NULL) + { + current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (current_prop_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (current_prop_p->types[i] != ECMA_PROPERTY_TYPE_DELETED + && !ecma_is_property_configurable (current_prop_p->types[i])) + { + uint32_t index = ecma_string_get_property_index (current_prop_p->types[i], prop_pair_p->names_cp[i]); + + if (index < old_length && index >= new_length) + { + JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); + + new_length = index + 1; + + if (new_length == old_length) + { + /* Early return. */ + return new_length; + } + } + } + } + + current_prop_cp = current_prop_p->next_property_cp; + } + + /* Second all properties between new_length and old_length are deleted. */ + current_prop_cp = object_p->u1.property_list_cp; + ecma_property_header_t *prev_prop_p = NULL; + +#if JERRY_PROPERTY_HASHMAP + JERRY_ASSERT (current_prop_cp != JMEM_CP_NULL); + + ecma_property_hashmap_delete_status hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP; + current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp); + + if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prev_prop_p = current_prop_p; + current_prop_cp = current_prop_p->next_property_cp; + hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP; + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (current_prop_cp != JMEM_CP_NULL) + { + current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (current_prop_p)); + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p; + + for (uint32_t i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (current_prop_p->types[i] != ECMA_PROPERTY_TYPE_DELETED + && ecma_is_property_configurable (current_prop_p->types[i])) + { + uint32_t index = ecma_string_get_property_index (current_prop_p->types[i], prop_pair_p->names_cp[i]); + + if (index < old_length && index >= new_length) + { + JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); + +#if JERRY_PROPERTY_HASHMAP + if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP) + { + hashmap_status = + ecma_property_hashmap_delete (object_p, prop_pair_p->names_cp[i], current_prop_p->types + i); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + ecma_gc_free_property (object_p, prop_pair_p, i); + current_prop_p->types[i] = ECMA_PROPERTY_TYPE_DELETED; + prop_pair_p->names_cp[i] = LIT_INTERNAL_MAGIC_STRING_DELETED; + } + } + } + + if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_DELETED + && current_prop_p->types[1] == ECMA_PROPERTY_TYPE_DELETED) + { + if (prev_prop_p == NULL) + { + object_p->u1.property_list_cp = current_prop_p->next_property_cp; + } + else + { + prev_prop_p->next_property_cp = current_prop_p->next_property_cp; + } + + jmem_cpointer_t next_prop_cp = current_prop_p->next_property_cp; + ecma_dealloc_property_pair ((ecma_property_pair_t *) current_prop_p); + current_prop_cp = next_prop_cp; + } + else + { + prev_prop_p = current_prop_p; + current_prop_cp = current_prop_p->next_property_cp; + } + } + +#if JERRY_PROPERTY_HASHMAP + if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP) + { + ecma_property_hashmap_free (object_p); + ecma_property_hashmap_create (object_p); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + return new_length; +} /* ecma_delete_array_properties */ + +/** + * Update the length of an array to a new length + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object */ + ecma_value_t new_value, /**< new length value */ + uint16_t flags) /**< property descriptor flags */ +{ + ecma_number_t new_len_num; + ecma_value_t completion = ecma_op_to_number (new_value, &new_len_num); + + if (ECMA_IS_VALUE_ERROR (completion)) + { + return completion; + } + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion)); + + if (ecma_is_value_object (new_value)) + { + ecma_value_t compared_num_val = ecma_op_to_number (new_value, &new_len_num); + + if (ECMA_IS_VALUE_ERROR (compared_num_val)) + { + return compared_num_val; + } + } + + uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); + + if (((ecma_number_t) new_len_uint32) != new_len_num) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + } + + /* Only the writable and data properties can be modified. */ + if (flags + & (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags); + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + uint32_t old_len_uint32 = ext_object_p->u.array.length; + + if (new_len_num == old_len_uint32) + { + /* Only the writable flag must be updated. */ + if (flags & JERRY_PROP_IS_WRITABLE_DEFINED) + { + if (!(flags & JERRY_PROP_IS_WRITABLE)) + { + if (ecma_op_array_is_fast_array (ext_object_p)) + { + ecma_fast_array_convert_to_normal (object_p); + } + + ext_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_PROPERTY_FLAG_WRITABLE; + } + else if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags); + } + } + return ECMA_VALUE_TRUE; + } + else if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags); + } + + uint32_t current_len_uint32 = new_len_uint32; + + if (new_len_uint32 < old_len_uint32) + { + current_len_uint32 = ecma_delete_array_properties (object_p, new_len_uint32, old_len_uint32); + } + else if (ecma_op_object_is_fast_array (object_p)) + { + ecma_fast_array_set_length (object_p, new_len_uint32); + } + + ext_object_p->u.array.length = current_len_uint32; + + if ((flags & JERRY_PROP_IS_WRITABLE_DEFINED) && !(flags & JERRY_PROP_IS_WRITABLE)) + { + if (ecma_op_array_is_fast_array (ext_object_p)) + { + ecma_fast_array_convert_to_normal (object_p); + } + + ext_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_PROPERTY_FLAG_WRITABLE; + } + + if (current_len_uint32 == new_len_uint32) + { + return ECMA_VALUE_TRUE; + } + + return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags); +} /* ecma_op_array_object_set_length */ + +/** + * Property descriptor bitset for fast array data properties. + * If the property desciptor fields contains all the flags below + * attempt to stay fast access array during [[DefineOwnProperty]] operation. + */ +#define ECMA_FAST_ARRAY_DATA_PROP_FLAGS \ + (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE \ + | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_WRITABLE_DEFINED \ + | JERRY_PROP_IS_WRITABLE) + +/** + * [[DefineOwnProperty]] ecma array object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 15.4.5.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the array object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property descriptor */ +{ + if (ecma_string_is_length (property_name_p)) + { + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)); + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)); + + if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + return ecma_op_array_object_set_length (object_p, property_desc_p->value, property_desc_p->flags); + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ecma_value_t length_value = ecma_make_uint32_value (ext_object_p->u.array.length); + + ecma_value_t result = ecma_op_array_object_set_length (object_p, length_value, property_desc_p->flags); + + ecma_fast_free_value (length_value); + return result; + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ecma_op_object_is_fast_array (object_p)) + { + if ((property_desc_p->flags & ECMA_FAST_ARRAY_DATA_PROP_FLAGS) == ECMA_FAST_ARRAY_DATA_PROP_FLAGS) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (JERRY_UNLIKELY (index == ECMA_STRING_NOT_ARRAY_INDEX)) + { + ecma_fast_array_convert_to_normal (object_p); + } + else if (ecma_fast_array_set_property (object_p, index, property_desc_p->value)) + { + return ECMA_VALUE_TRUE; + } + + JERRY_ASSERT (!ecma_op_array_is_fast_array (ext_object_p)); + } + else + { + ecma_fast_array_convert_to_normal (object_p); + } + } + + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX) + { + return ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p); + } + + bool update_length = (index >= ext_object_p->u.array.length); + + if (update_length && !ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + ecma_property_descriptor_t prop_desc; + + prop_desc = *property_desc_p; + prop_desc.flags &= (uint16_t) ~JERRY_PROP_SHOULD_THROW; + + ecma_value_t completition = ecma_op_general_object_define_own_property (object_p, property_name_p, &prop_desc); + JERRY_ASSERT (ecma_is_value_boolean (completition)); + + if (ecma_is_value_false (completition)) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + if (update_length) + { + ext_object_p->u.array.length = index + 1; + } + + return ECMA_VALUE_TRUE; +} /* ecma_op_array_object_define_own_property */ + +/** + * Get the length of the an array object + * + * @return the array length + */ +uint32_t +ecma_array_get_length (ecma_object_t *array_p) /**< array object */ +{ + JERRY_ASSERT (ecma_get_object_base_type (array_p) == ECMA_OBJECT_BASE_TYPE_ARRAY); + + return ((ecma_extended_object_t *) array_p)->u.array.length; +} /* ecma_array_get_length */ + +/** + * The Array.prototype and %TypedArray%.prototype objects' 'toString' routine. + * + * See also: + * ECMA-262 v5, 15.4.4.2 + * ECMA-262 v6, 22.1.3.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_array_object_to_string (ecma_value_t this_arg) /**< this argument */ +{ + JERRY_ASSERT (ecma_is_value_object (this_arg)); + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); + + /* 2. */ + ecma_value_t join_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_JOIN); + if (ECMA_IS_VALUE_ERROR (join_value)) + { + return join_value; + } + + if (!ecma_op_is_callable (join_value)) + { + /* 3. */ + ret_value = ecma_builtin_helper_object_to_string (this_arg); + } + else + { + /* 4. */ + ecma_object_t *join_func_obj_p = ecma_get_object_from_value (join_value); + + ret_value = ecma_op_function_call (join_func_obj_p, this_arg, NULL, 0); + } + + ecma_free_value (join_value); + + return ret_value; +} /* ecma_array_object_to_string */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.h new file mode 100644 index 00000000..73d65805 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.h @@ -0,0 +1,110 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ARRAY_OBJECT_H +#define ECMA_ARRAY_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaarrayobject ECMA Array object related routines + * @{ + */ + +/** + * Attributes of fast access mode arrays: + * + * - The internal property is replaced with a buffer which directly stores the values + * - Whenever any operation would change the following attributes of the array it should be converted back to normal + * - All properties must be enumerable configurable writable data properties + * - The prototype must be Array.prototype + * - [[Extensible]] internal property must be true + * - 'length' property of the array must be writable + * + * - The conversion is also required when a property is set if: + * - The property name is not an array index + * - The new hole count of the array would reach ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT + */ + +/** + * Maximum number of new array holes in a fast mode access array. + * If the number of new holes exceeds this limit, the array is converted back + * to normal property list based array. + */ +#define ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT 32 + +/** + * Bitshift index for fast array hole count representation + */ +#define ECMA_FAST_ARRAY_HOLE_SHIFT 8 + +/** + * This number represents 1 array hole in underlying buffer of a fast acces mode array + */ +#define ECMA_FAST_ARRAY_HOLE_ONE (1 << ECMA_FAST_ARRAY_HOLE_SHIFT) + +/** + * Maximum number of array holes in a fast access mode array + */ +#define ECMA_FAST_ARRAY_MAX_HOLE_COUNT (1 << 16) + +ecma_object_t *ecma_op_new_array_object (uint32_t length); + +ecma_object_t *ecma_op_new_array_object_from_length (ecma_length_t length); + +ecma_value_t ecma_op_new_array_object_from_buffer (const ecma_value_t *args_p, uint32_t length); + +ecma_value_t ecma_op_new_array_object_from_collection (ecma_collection_t *collection_p, bool unref_objects); + +bool ecma_op_object_is_fast_array (ecma_object_t *object_p); + +bool ecma_op_array_is_fast_array (ecma_extended_object_t *array_p); + +uint32_t ecma_fast_array_get_hole_count (ecma_object_t *obj_p); + +ecma_value_t *ecma_fast_array_extend (ecma_object_t *object_p, uint32_t new_lengt); + +bool ecma_fast_array_set_property (ecma_object_t *object_p, uint32_t index, ecma_value_t value); + +bool ecma_array_object_delete_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +uint32_t ecma_delete_fast_array_properties (ecma_object_t *object_p, uint32_t new_length); + +ecma_collection_t *ecma_fast_array_object_own_property_keys (ecma_object_t *object_p, jerry_property_filter_t filter); + +void ecma_fast_array_convert_to_normal (ecma_object_t *object_p); + +ecma_object_t *ecma_op_array_species_create (ecma_object_t *original_array_p, ecma_length_t length); + +ecma_value_t ecma_op_create_array_iterator (ecma_object_t *obj_p, ecma_iterator_kind_t kind); + +ecma_value_t ecma_op_array_object_set_length (ecma_object_t *object_p, ecma_value_t new_value, uint16_t flags); + +ecma_value_t ecma_op_array_object_define_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); + +uint32_t ecma_array_get_length (ecma_object_t *array_p); + +ecma_value_t ecma_array_object_to_string (ecma_value_t this_arg); + +/** + * @} + * @} + */ + +#endif /* !ECMA_ARRAY_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.cpp new file mode 100644 index 00000000..be61d7cd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.cpp @@ -0,0 +1,562 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-shared-arraybuffer-object.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaarraybufferobject ECMA ArrayBuffer object related routines + * @{ + */ + +/** + * Creating ArrayBuffer objects with a buffer after the arraybuffer header + * + * @return new ArrayBuffer object + */ +ecma_object_t * +ecma_arraybuffer_create_object (uint8_t type, /**< type of the arraybuffer */ + uint32_t length) /**< length of the arraybuffer */ +{ + ecma_builtin_id_t prototype_id; + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER || type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER); + + prototype_id = (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER ? ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE + : ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER); + + prototype_id = ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE; +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + + ecma_object_t *object_p = ecma_create_object (ecma_builtin_get (prototype_id), + sizeof (ecma_extended_object_t) + length, + ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = type; + ext_object_p->u.cls.u1.array_buffer_flags = ECMA_ARRAYBUFFER_ALLOCATED; + ext_object_p->u.cls.u3.length = length; + + memset ((uint8_t *) (ext_object_p + 1), 0, length); + return object_p; +} /* ecma_arraybuffer_create_object */ + +/** + * Creating ArrayBuffer objects with a pointer to its buffer + * + * @return new ArrayBuffer object + */ +ecma_object_t * +ecma_arraybuffer_create_object_with_buffer (uint8_t type, /**< type of the arraybuffer */ + uint32_t length) +{ + ecma_builtin_id_t prototype_id; + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER || type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER); + + prototype_id = (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER ? ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE + : ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER); + + prototype_id = ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE; +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + + ecma_object_t *object_p = + ecma_create_object (ecma_builtin_get (prototype_id), sizeof (ecma_arraybuffer_pointer_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p; + arraybuffer_pointer_p->extended_object.u.cls.type = type; + arraybuffer_pointer_p->extended_object.u.cls.u1.array_buffer_flags = ECMA_ARRAYBUFFER_HAS_POINTER; + arraybuffer_pointer_p->extended_object.u.cls.u3.length = length; + + arraybuffer_pointer_p->buffer_p = NULL; + arraybuffer_pointer_p->arraybuffer_user_p = NULL; + + return object_p; +} /* ecma_arraybuffer_create_object_with_buffer */ + +/** + * Creating ArrayBuffer objects based on the array length + * + * @return new ArrayBuffer object + */ +ecma_object_t * +ecma_arraybuffer_new_object (uint32_t length) /**< length of the arraybuffer */ +{ + if (length > JERRY_CONTEXT (arraybuffer_compact_allocation_limit)) + { + return ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_ARRAY_BUFFER, length); + } + + return ecma_arraybuffer_create_object (ECMA_OBJECT_CLASS_ARRAY_BUFFER, length); +} /* ecma_arraybuffer_new_object */ + +/** + * Allocate a backing store for an array buffer. + * + * @return buffer pointer on success, + * NULL otherwise + */ +ecma_value_t +ecma_arraybuffer_allocate_buffer (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */ +{ + JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)); + + ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) arraybuffer_p; + + if (ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_DETACHED) + { + extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED; + return ECMA_VALUE_UNDEFINED; + } + + uint32_t arraybuffer_length = extended_object_p->u.cls.u3.length; + ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p; + jerry_arraybuffer_allocate_cb_t arraybuffer_allocate_callback = JERRY_CONTEXT (arraybuffer_allocate_callback); + uint8_t *buffer_p; + + if (arraybuffer_allocate_callback != NULL) + { + jerry_arraybuffer_type_t type = JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER; + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + if (extended_object_p->u.cls.type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER) + { + type = JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER; + } +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + + buffer_p = arraybuffer_allocate_callback (type, + arraybuffer_length, + &arraybuffer_pointer_p->arraybuffer_user_p, + JERRY_CONTEXT (arraybuffer_allocate_callback_user_p)); + } + else + { + buffer_p = (uint8_t *) jmem_heap_alloc_block_null_on_error (arraybuffer_length); + } + + if (buffer_p == NULL) + { + return ecma_raise_range_error (ECMA_ERR_ALLOCATE_ARRAY_BUFFER); + } + + arraybuffer_pointer_p->buffer_p = buffer_p; + extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED; + + memset (buffer_p, 0, arraybuffer_length); + return ECMA_VALUE_UNDEFINED; +} /* ecma_arraybuffer_allocate_buffer */ + +/** + * Allocate a backing store for an array buffer, throws an error if the allocation fails. + * + * @return ECMA_VALUE_UNDEFINED on success, + * ECMA_VALUE_ERROR otherwise + */ +ecma_value_t +ecma_arraybuffer_allocate_buffer_throw (ecma_object_t *arraybuffer_p) +{ + JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)); + + return ecma_arraybuffer_allocate_buffer (arraybuffer_p); +} /* ecma_arraybuffer_allocate_buffer_throw */ + +/** + * Release the backing store allocated by an array buffer. + */ +void +ecma_arraybuffer_release_buffer (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */ +{ + JERRY_ASSERT (ecma_object_class_is (arraybuffer_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (arraybuffer_p)); + + jerry_arraybuffer_free_cb_t free_callback = JERRY_CONTEXT (arraybuffer_free_callback); + ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p; + + if (arraybuffer_pointer_p->buffer_p == NULL) + { + return; + } + + uint32_t arraybuffer_length = arraybuffer_pointer_p->extended_object.u.cls.u3.length; + + if (free_callback == NULL) + { + jmem_heap_free_block (arraybuffer_pointer_p->buffer_p, arraybuffer_length); + return; + } + + jerry_arraybuffer_type_t type = JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER; + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + if (arraybuffer_pointer_p->extended_object.u.cls.type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER) + { + type = JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER; + } +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + + free_callback (type, + (uint8_t*) arraybuffer_pointer_p->buffer_p, + arraybuffer_length, + arraybuffer_pointer_p->arraybuffer_user_p, + JERRY_CONTEXT (arraybuffer_allocate_callback_user_p)); +} /* ecma_arraybuffer_release_buffer */ + +/** + * ArrayBuffer object creation operation. + * + * See also: ES2015 24.1.1.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_arraybuffer_object (const ecma_value_t *arguments_list_p, /**< list of arguments that + * are passed to String constructor */ + uint32_t arguments_list_len) /**< length of the arguments' list */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t length_num = 0; + + if (arguments_list_len > 0) + { + if (ecma_is_value_number (arguments_list_p[0])) + { + length_num = ecma_get_number_from_value (arguments_list_p[0]); + } + else + { + ecma_value_t to_number_value = ecma_op_to_number (arguments_list_p[0], &length_num); + + if (ECMA_IS_VALUE_ERROR (to_number_value)) + { + ecma_deref_object (proto_p); + return to_number_value; + } + } + + if (ecma_number_is_nan (length_num)) + { + length_num = 0; + } + + const uint32_t maximum_size_in_byte = UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1; + + if (length_num <= -1.0 || length_num > (ecma_number_t) maximum_size_in_byte + 0.5) + { + ecma_deref_object (proto_p); + return ecma_raise_range_error (ECMA_ERR_INVALID_ARRAYBUFFER_LENGTH); + } + } + + uint32_t length_uint32 = ecma_number_to_uint32 (length_num); + + ecma_object_t *array_buffer = ecma_arraybuffer_new_object (length_uint32); + ECMA_SET_NON_NULL_POINTER (array_buffer->u2.prototype_cp, proto_p); + ecma_deref_object (proto_p); + + return ecma_make_object_value (array_buffer); +} /* ecma_op_create_arraybuffer_object */ + +/** + * Helper function: check if the target is ArrayBuffer + * + * + * See also: ES2015 24.1.1.4 + * + * @return true - if value is an ArrayBuffer object + * false - otherwise + */ +bool +ecma_is_arraybuffer (ecma_value_t target) /**< the target value */ +{ + return (ecma_is_value_object (target) + && ecma_object_class_is (ecma_get_object_from_value (target), ECMA_OBJECT_CLASS_ARRAY_BUFFER)); +} /* ecma_is_arraybuffer */ + +/** + * Helper function: return the length of the buffer inside the arraybuffer object + * + * @return uint32_t, the length of the arraybuffer + */ +uint32_t JERRY_ATTR_PURE +ecma_arraybuffer_get_length (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */ +{ + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (object_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + return ecma_arraybuffer_is_detached (object_p) ? 0 : ext_object_p->u.cls.u3.length; +} /* ecma_arraybuffer_get_length */ + +/** + * Helper function: return the pointer to the data buffer inside the arraybuffer object + * + * @return pointer to the data buffer + */ +uint8_t *JERRY_ATTR_PURE +ecma_arraybuffer_get_buffer (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */ +{ + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (object_p)); + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_HAS_POINTER)) + { + return (uint8_t *) object_p + sizeof (ecma_extended_object_t); + } + + ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p; + return (uint8_t *) arraybuffer_pointer_p->buffer_p; +} /* ecma_arraybuffer_get_buffer */ + +/** + * Helper function: check if the target ArrayBuffer is detached + * + * @return true - if value is an detached ArrayBuffer object + * false - otherwise + */ +bool JERRY_ATTR_PURE +ecma_arraybuffer_is_detached (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */ +{ + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (object_p)); + + return (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_DETACHED) != 0; +} /* ecma_arraybuffer_is_detached */ + +/** + * ArrayBuffer object detaching operation + * + * See also: ES2015 24.1.1.3 + * + * @return true - if detach operation is succeeded + * false - otherwise + */ +bool +ecma_arraybuffer_detach (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */ +{ + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)); + + if (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_DETACHED) + { + return false; + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_DETACHED; + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_ALLOCATED)) + { + return true; + } + + ext_object_p->u.cls.u1.array_buffer_flags &= (uint8_t) ~ECMA_ARRAYBUFFER_ALLOCATED; + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_HAS_POINTER)) + { + return true; + } + + ecma_arraybuffer_release_buffer (object_p); + return true; +} /* ecma_arraybuffer_detach */ + +/** + * ArrayBuffer slice operation + * + * See also: + * ECMA-262 v11, 24.1.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_arraybuffer_slice (ecma_value_t this_arg, const ecma_value_t *argument_list_p, uint32_t arguments_number) +{ + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + /* 3-4. */ + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (object_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (object_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* 5. */ + uint32_t len = ecma_arraybuffer_get_length (object_p); + + uint32_t start = 0; + uint32_t end = len; + + if (arguments_number > 0) + { + /* 6-7. */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (argument_list_p[0], len, &start))) + { + return ECMA_VALUE_ERROR; + } + + if (arguments_number > 1 && !ecma_is_value_undefined (argument_list_p[1])) + { + /* 8-9. */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (argument_list_p[1], len, &end))) + { + return ECMA_VALUE_ERROR; + } + } + } + + /* 10. */ + uint32_t new_len = (end >= start) ? (end - start) : 0; + + /* 11. */ + ecma_builtin_id_t buffer_builtin_id = ECMA_BUILTIN_ID_ARRAYBUFFER; + + if (ecma_is_shared_arraybuffer (this_arg)) + { + buffer_builtin_id = ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER; + } + + ecma_value_t ctor = ecma_op_species_constructor (object_p, buffer_builtin_id); + + if (ECMA_IS_VALUE_ERROR (ctor)) + { + return ctor; + } + + /* 12. */ + ecma_object_t *ctor_obj_p = ecma_get_object_from_value (ctor); + ecma_value_t new_len_value = ecma_make_uint32_value (new_len); + + ecma_value_t new_arraybuffer = ecma_op_function_construct (ctor_obj_p, ctor_obj_p, &new_len_value, 1); + + ecma_deref_object (ctor_obj_p); + ecma_free_value (new_len_value); + + if (ECMA_IS_VALUE_ERROR (new_arraybuffer)) + { + return new_arraybuffer; + } + + ecma_object_t *new_arraybuffer_p = ecma_get_object_from_value (new_arraybuffer); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + lit_utf8_byte_t *old_buf; + lit_utf8_byte_t *new_buf; + + /* 13. */ + if (!(ecma_object_class_is (new_arraybuffer_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (new_arraybuffer_p))) + { + ret_value = ecma_raise_type_error (ECMA_ERR_RETURN_VALUE_IS_NOT_AN_ARRAYBUFFER_OBJECT); + goto free_new_arraybuffer; + } + + /* 14-15. */ + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (new_arraybuffer_p)) + { + ret_value = ECMA_VALUE_ERROR; + goto free_new_arraybuffer; + } + + if (ecma_arraybuffer_is_detached (new_arraybuffer_p)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto free_new_arraybuffer; + } + + /* 16. */ + if (new_arraybuffer == this_arg) + { + ret_value = ecma_raise_type_error (ECMA_ERR_ARRAY_BUFFER_RETURNED_THIS_FROM_CONSTRUCTOR); + goto free_new_arraybuffer; + } + + /* 17. */ + if (ecma_arraybuffer_get_length (new_arraybuffer_p) < new_len) + { + ret_value = ecma_raise_type_error (ECMA_ERR_DERIVED_ARRAY_BUFFER_CTOR_BUFFER_TOO_SMALL); + goto free_new_arraybuffer; + } + + /* 19. */ + if (ecma_arraybuffer_is_detached (object_p)) + { + ret_value = ECMA_VALUE_ERROR; + goto free_new_arraybuffer; + } + + /* 20. */ + old_buf = ecma_arraybuffer_get_buffer (object_p); + + /* 21. */ + new_buf = ecma_arraybuffer_get_buffer (new_arraybuffer_p); + + /* 22. */ + memcpy (new_buf, old_buf + start, new_len); + +free_new_arraybuffer: + if (ret_value != ECMA_VALUE_EMPTY) + { + ecma_deref_object (new_arraybuffer_p); + } + else + { + /* 23. */ + ret_value = ecma_make_object_value (new_arraybuffer_p); + } + + return ret_value; +} /* ecma_builtin_arraybuffer_slice */ + +/** + * @} + * @} + */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.h new file mode 100644 index 00000000..6dc28b59 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.h @@ -0,0 +1,68 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ARRAYBUFFER_OBJECT_H +#define ECMA_ARRAYBUFFER_OBJECT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaarraybufferobject ECMA ArrayBuffer object related routines + * @{ + */ + +/** + * Get array buffer flags. + */ +#define ECMA_ARRAYBUFFER_GET_FLAGS(arraybuffer_p) \ + (((ecma_extended_object_t *) (arraybuffer_p))->u.cls.u1.array_buffer_flags) + +/** + * Check whether the backing store is allocated for an array buffer. + */ +#define ECMA_ARRAYBUFFER_LAZY_ALLOC(arraybuffer_p) \ + (JERRY_UNLIKELY (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)) \ + && ecma_arraybuffer_allocate_buffer_throw (arraybuffer_p) == ECMA_VALUE_ERROR) + +ecma_value_t ecma_op_create_arraybuffer_object (const ecma_value_t *, uint32_t); + +/** + * Helper functions for arraybuffer. + */ +ecma_object_t *ecma_arraybuffer_create_object (uint8_t type, uint32_t length); +ecma_object_t *ecma_arraybuffer_create_object_with_buffer (uint8_t type, uint32_t length); +ecma_object_t *ecma_arraybuffer_new_object (uint32_t length); +ecma_value_t ecma_arraybuffer_allocate_buffer (ecma_object_t *arraybuffer_p); +ecma_value_t ecma_arraybuffer_allocate_buffer_throw (ecma_object_t *arraybuffer_p); +void ecma_arraybuffer_release_buffer (ecma_object_t *arraybuffer_p); +uint8_t *JERRY_ATTR_PURE ecma_arraybuffer_get_buffer (ecma_object_t *obj_p); +uint32_t JERRY_ATTR_PURE ecma_arraybuffer_get_length (ecma_object_t *obj_p); +bool JERRY_ATTR_PURE ecma_arraybuffer_is_detached (ecma_object_t *obj_p); +bool ecma_arraybuffer_detach (ecma_object_t *obj_p); +bool ecma_is_arraybuffer (ecma_value_t val); +ecma_value_t +ecma_builtin_arraybuffer_slice (ecma_value_t this_arg, const ecma_value_t *argument_list_p, uint32_t arguments_number); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#endif /* !ECMA_ARRAYBUFFER_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.cpp new file mode 100644 index 00000000..1e548bbc --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.cpp @@ -0,0 +1,523 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-async-generator-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-errors.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" +#include "opcodes.h" +#include "vm-stack.h" +#include "vm.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaasyncgeneratorobject ECMA AsyncGenerator object related routines + * @{ + */ + +/** + * Enqueue a task into the command queue of an async generator + * + * @return ecma Promise value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_async_generator_enqueue (vm_executable_object_t *async_generator_object_p, /**< async generator */ + ecma_async_generator_operation_type_t operation, /**< operation */ + ecma_value_t value) /**< value argument of operation */ +{ + ecma_async_generator_task_t *task_p = (ecma_async_generator_task_t *) jmem_heap_alloc_block (sizeof (ecma_async_generator_task_t)); + + ECMA_SET_INTERNAL_VALUE_ANY_POINTER (task_p->next, NULL); + task_p->operation_value = ecma_copy_value_if_not_object (value); + task_p->operation_type = (uint8_t) operation; + + ecma_value_t result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL); + task_p->promise = result; + + ecma_value_t head = async_generator_object_p->extended_object.u.cls.u3.head; + + if (ECMA_IS_INTERNAL_VALUE_NULL (head)) + { + ECMA_SET_INTERNAL_VALUE_POINTER (async_generator_object_p->extended_object.u.cls.u3.head, task_p); + + if (async_generator_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_ASYNC_GENERATOR_CALLED) + { + ecma_value_t executable_object = ecma_make_object_value ((ecma_object_t *) async_generator_object_p); + ecma_enqueue_promise_async_generator_job (executable_object); + return result; + } + + async_generator_object_p->extended_object.u.cls.u2.executable_obj_flags |= ECMA_ASYNC_GENERATOR_CALLED; + ecma_async_generator_run (async_generator_object_p); + return result; + } + + /* Append the new task at the end. */ + ecma_async_generator_task_t *prev_task_p; + prev_task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, head); + + while (!ECMA_IS_INTERNAL_VALUE_NULL (prev_task_p->next)) + { + prev_task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, prev_task_p->next); + } + + ECMA_SET_INTERNAL_VALUE_POINTER (prev_task_p->next, task_p); + return result; +} /* ecma_async_generator_enqueue */ + +/** + * Call a function and await its return value + * + * @return ECMA_VALUE_UNDEFINED on success, error otherwise + */ +static ecma_value_t +ecma_async_yield_call (ecma_value_t function, /**< function (takes reference) */ + vm_executable_object_t *async_generator_object_p, /**< async generator */ + ecma_value_t argument) /**< argument passed to the function */ +{ + ecma_value_t iterator = async_generator_object_p->iterator; + ecma_value_t result; + + if (argument == ECMA_VALUE_EMPTY) + { + result = ecma_op_function_validated_call (function, iterator, NULL, 0); + } + else + { + result = ecma_op_function_validated_call (function, iterator, &argument, 1); + } + + ecma_free_value (function); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + return ecma_promise_async_await ((ecma_extended_object_t *) async_generator_object_p, result); +} /* ecma_async_yield_call */ + +/** + * Perform an exception throw and call the approprite handler + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_async_yield_throw (vm_executable_object_t *async_generator_object_p, /**< async generator */ + ecma_value_t value) /**< thrown value */ +{ + ecma_object_t *obj_p = ecma_get_object_from_value (async_generator_object_p->iterator); + ecma_value_t result = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_THROW); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (result == ECMA_VALUE_UNDEFINED) + { + result = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_RETURN); + + if (result == ECMA_VALUE_UNDEFINED) + { + return ecma_raise_type_error (ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE); + } + + result = ecma_async_yield_call (result, async_generator_object_p, ECMA_VALUE_EMPTY); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ECMA_AWAIT_CHANGE_STATE (async_generator_object_p, YIELD_OPERATION, YIELD_CLOSE); + return ECMA_VALUE_UNDEFINED; + } + + result = ecma_async_yield_call (result, async_generator_object_p, value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ECMA_AWAIT_CHANGE_STATE (async_generator_object_p, YIELD_OPERATION, YIELD_NEXT); + return ECMA_VALUE_UNDEFINED; +} /* ecma_async_yield_throw */ + +/** + * Execute the next task in the command queue of the async generator + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_async_generator_run (vm_executable_object_t *async_generator_object_p) /**< async generator */ +{ + JERRY_ASSERT (async_generator_object_p->extended_object.u.cls.type == ECMA_OBJECT_CLASS_ASYNC_GENERATOR); + JERRY_ASSERT (!ECMA_IS_INTERNAL_VALUE_NULL (async_generator_object_p->extended_object.u.cls.u3.head)); + + ecma_value_t head = async_generator_object_p->extended_object.u.cls.u3.head; + ecma_async_generator_task_t *task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, head); + ecma_value_t result; + + if (async_generator_object_p->extended_object.u.cls.u2.executable_obj_flags + & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + { + switch (task_p->operation_type) + { + case ECMA_ASYNC_GENERATOR_DO_NEXT: + { + result = ecma_op_iterator_next (async_generator_object_p->iterator, + async_generator_object_p->frame_ctx.stack_top_p[-1], + task_p->operation_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + break; + } + + result = ecma_promise_async_await ((ecma_extended_object_t *) async_generator_object_p, result); + + if (ECMA_IS_VALUE_ERROR (result)) + { + break; + } + + ECMA_AWAIT_CHANGE_STATE (async_generator_object_p, YIELD_OPERATION, YIELD_NEXT); + break; + } + case ECMA_ASYNC_GENERATOR_DO_THROW: + { + result = ecma_async_yield_throw (async_generator_object_p, task_p->operation_value); + break; + } + default: + { + JERRY_ASSERT (task_p->operation_type == ECMA_ASYNC_GENERATOR_DO_RETURN); + + result = ecma_copy_value (task_p->operation_value); + result = ecma_promise_async_await ((ecma_extended_object_t *) async_generator_object_p, result); + + if (ECMA_IS_VALUE_ERROR (result)) + { + break; + } + + ECMA_AWAIT_CHANGE_STATE (async_generator_object_p, YIELD_OPERATION, YIELD_RETURN); + break; + } + } + + ecma_free_value_if_not_object (task_p->operation_value); + task_p->operation_value = ECMA_VALUE_UNDEFINED; + + if (result == ECMA_VALUE_UNDEFINED) + { + return ECMA_VALUE_UNDEFINED; + } + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result)); + + async_generator_object_p->extended_object.u.cls.u2.executable_obj_flags &= ECMA_AWAIT_CLEAR_MASK; + async_generator_object_p->iterator = ECMA_VALUE_UNDEFINED; + async_generator_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + + JERRY_ASSERT (async_generator_object_p->frame_ctx.stack_top_p[-1] == ECMA_VALUE_UNDEFINED + || ecma_is_value_object (async_generator_object_p->frame_ctx.stack_top_p[-1])); + async_generator_object_p->frame_ctx.stack_top_p--; + + result = jcontext_take_exception (); + } + else + { + if (task_p->operation_type == ECMA_ASYNC_GENERATOR_DO_RETURN) + { + async_generator_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_return; + } + else if (task_p->operation_type == ECMA_ASYNC_GENERATOR_DO_THROW) + { + async_generator_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + } + + result = task_p->operation_value; + ecma_ref_if_object (result); + task_p->operation_value = ECMA_VALUE_UNDEFINED; + } + + result = opfunc_resume_executable_object (async_generator_object_p, result); + + if (async_generator_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_COMPLETED) + { + JERRY_ASSERT (head == async_generator_object_p->extended_object.u.cls.u3.head); + ecma_async_generator_finalize (async_generator_object_p, result); + result = ECMA_VALUE_UNDEFINED; + } + + return result; +} /* ecma_async_generator_run */ + +/** + * Finalize the promises of an executable generator + */ +void +ecma_async_generator_finalize (vm_executable_object_t *async_generator_object_p, /**< async generator */ + ecma_value_t value) /**< final value (takes reference) */ +{ + ecma_value_t next = async_generator_object_p->extended_object.u.cls.u3.head; + ecma_async_generator_task_t *task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, next); + + if (ECMA_IS_VALUE_ERROR (value)) + { + value = jcontext_take_exception (); + ecma_reject_promise (task_p->promise, value); + } + else + { + ecma_value_t result = ecma_create_iter_result_object (value, ECMA_VALUE_TRUE); + ecma_fulfill_promise (task_p->promise, result); + ecma_free_value (result); + } + + ecma_free_value (value); + + next = task_p->next; + async_generator_object_p->extended_object.u.cls.u3.head = next; + jmem_heap_free_block (task_p, sizeof (ecma_async_generator_task_t)); + + while (!ECMA_IS_INTERNAL_VALUE_NULL (next)) + { + task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, next); + + if (task_p->operation_type != ECMA_ASYNC_GENERATOR_DO_THROW) + { + value = ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + ecma_fulfill_promise (task_p->promise, value); + ecma_free_value (value); + } + else + { + ecma_reject_promise (task_p->promise, task_p->operation_value); + } + + ecma_free_value_if_not_object (task_p->operation_value); + + next = task_p->next; + async_generator_object_p->extended_object.u.cls.u3.head = next; + jmem_heap_free_block (task_p, sizeof (ecma_async_generator_task_t)); + } +} /* ecma_async_generator_finalize */ + +/** + * Continue after an await operation is completed. + * + * @return an updated value for the value argument + */ +ecma_value_t +ecma_await_continue (vm_executable_object_t *executable_object_p, /**< executable object */ + ecma_value_t value) /**< job value (takes reference) */ +{ + ecma_await_states_t state = (ecma_await_states_t) ECMA_AWAIT_GET_STATE (executable_object_p); + + switch (state) + { + case ECMA_AWAIT_YIELD_NEXT: + case ECMA_AWAIT_YIELD_NEXT_RETURN: + { + if (!ecma_is_value_object (value)) + { + ecma_free_value (value); + return ecma_raise_type_error (ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT); + } + + ecma_object_t *result_obj_p = ecma_get_object_from_value (value); + ecma_value_t result = ecma_op_object_get_by_magic_id (result_obj_p, LIT_MAGIC_STRING_DONE); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (result_obj_p); + return result; + } + + bool done = ecma_op_to_boolean (result); + ecma_free_value (result); + result = ecma_op_object_get_by_magic_id (result_obj_p, LIT_MAGIC_STRING_VALUE); + ecma_deref_object (result_obj_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (!done) + { + ECMA_AWAIT_SET_STATE (executable_object_p, YIELD_NEXT_VALUE); + return ecma_promise_async_await ((ecma_extended_object_t *) executable_object_p, result); + } + + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (executable_object_p); + + if (state == ECMA_AWAIT_YIELD_NEXT_RETURN) + { + executable_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_return; + } + return result; + } + case ECMA_AWAIT_YIELD_RETURN: + { + ecma_object_t *obj_p = ecma_get_object_from_value (executable_object_p->iterator); + ecma_value_t result = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_RETURN); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_free_value (value); + return result; + } + + if (result == ECMA_VALUE_UNDEFINED) + { + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (executable_object_p); + executable_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_return; + return value; + } + + result = ecma_async_yield_call (result, executable_object_p, value); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + JERRY_ASSERT (result == ECMA_VALUE_UNDEFINED); + ECMA_AWAIT_CHANGE_STATE (executable_object_p, YIELD_RETURN, YIELD_NEXT_RETURN); + return ECMA_VALUE_UNDEFINED; + } + case ECMA_AWAIT_YIELD_NEXT_VALUE: + { + ECMA_AWAIT_CHANGE_STATE (executable_object_p, YIELD_NEXT_VALUE, YIELD_OPERATION); + opfunc_async_generator_yield ((ecma_extended_object_t *) executable_object_p, value); + return ECMA_VALUE_UNDEFINED; + } + case ECMA_AWAIT_YIELD_OPERATION: + { + /* Currently this is always a throw exception case. */ + ecma_value_t result = ecma_async_yield_throw (executable_object_p, value); + ecma_free_value (value); + return result; + } + case ECMA_AWAIT_YIELD_CLOSE: + { + ecma_error_msg_t msg = (ecma_is_value_object (value) ? ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE + : ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT); + + ecma_free_value (value); + return ecma_raise_type_error (msg); + } + case ECMA_AWAIT_FOR_CLOSE: + { + bool is_value_object = ecma_is_value_object (value); + ecma_free_value (value); + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (executable_object_p); + + if (!is_value_object + && VM_GET_CONTEXT_TYPE (executable_object_p->frame_ctx.stack_top_p[-1]) != VM_CONTEXT_FINALLY_THROW) + { + return ecma_raise_type_error (ECMA_ERR_ITERATOR_RETURN_RESULT_IS_NOT_OBJECT); + } + return ECMA_VALUE_EMPTY; + } + default: + { + JERRY_ASSERT (state == ECMA_AWAIT_FOR_NEXT); + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (executable_object_p->frame_ctx.stack_top_p[-1]) == VM_CONTEXT_FOR_AWAIT_OF); + JERRY_ASSERT (!(executable_object_p->frame_ctx.stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR)); + + if (!ecma_is_value_object (value)) + { + ecma_free_value (value); + return ecma_raise_type_error (ECMA_ERR_VALUE_RECEIVED_BY_FOR_ASYNC_OF_IS_NOT_OBJECT); + } + + ecma_object_t *result_obj_p = ecma_get_object_from_value (value); + ecma_value_t result = ecma_op_object_get_by_magic_id (result_obj_p, LIT_MAGIC_STRING_DONE); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (result_obj_p); + return result; + } + + bool done = ecma_op_to_boolean (result); + ecma_free_value (result); + + ecma_value_t *stack_top_p = executable_object_p->frame_ctx.stack_top_p; + JERRY_ASSERT (stack_top_p[-2] == ECMA_VALUE_UNDEFINED); + JERRY_ASSERT (ecma_is_value_object (stack_top_p[-3])); + JERRY_ASSERT (stack_top_p[-4] == ECMA_VALUE_UNDEFINED || ecma_is_value_object (stack_top_p[-4])); + + if (!done) + { + result = ecma_op_object_get_by_magic_id (result_obj_p, LIT_MAGIC_STRING_VALUE); + ecma_deref_object (result_obj_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + /* It seems browsers call Await(result) here, although the standard does not + * requests to do so. The following code might follow browsers in the future. */ + ecma_deref_if_object (result); + stack_top_p[-1] |= VM_CONTEXT_CLOSE_ITERATOR; + stack_top_p[-2] = result; + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (executable_object_p); + return ECMA_VALUE_EMPTY; + } + + ecma_deref_object (result_obj_p); + + /* This code jumps to the end regardless of the byte code which triggered this await. */ + uint32_t context_end = VM_GET_CONTEXT_END (stack_top_p[-1]); + executable_object_p->frame_ctx.byte_code_p = executable_object_p->frame_ctx.byte_code_start_p + context_end; + + VM_MINUS_EQUAL_U16 (executable_object_p->frame_ctx.context_depth, PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION; + executable_object_p->frame_ctx.stack_top_p = stack_top_p; + + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (executable_object_p); + return ECMA_VALUE_EMPTY; + } + } +} /* ecma_await_continue */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.h new file mode 100644 index 00000000..bcd58e0f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.h @@ -0,0 +1,88 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ASYNC_GENERATOR_OBJECT_H +#define ECMA_ASYNC_GENERATOR_OBJECT_H + +#include "ecma-globals.h" + +#include "vm-defines.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaasyncgeneratorobject ECMA AsyncGenerator object related routines + * @{ + */ + +/** + * AsyncGenerator command types. + */ +typedef enum +{ + ECMA_ASYNC_GENERATOR_DO_NEXT, /**< async generator next operation */ + ECMA_ASYNC_GENERATOR_DO_THROW, /**< async generator throw operation */ + ECMA_ASYNC_GENERATOR_DO_RETURN, /**< async generator return operation */ +} ecma_async_generator_operation_type_t; + +/** + * Get the state of an async yield iterator. + */ +#define ECMA_AWAIT_GET_STATE(async_generator_object_p) \ + ((async_generator_object_p)->extended_object.u.cls.u2.executable_obj_flags >> ECMA_AWAIT_STATE_SHIFT) + +/** + * Set the state of an async yield iterator. + */ +#define ECMA_AWAIT_SET_STATE(async_generator_object_p, to) \ + do \ + { \ + uint16_t extra_info = (async_generator_object_p)->extended_object.u.cls.u2.executable_obj_flags; \ + extra_info &= ((1 << ECMA_AWAIT_STATE_SHIFT) - 1); \ + extra_info |= (ECMA_AWAIT_##to) << ECMA_AWAIT_STATE_SHIFT; \ + (async_generator_object_p)->extended_object.u.cls.u2.executable_obj_flags = extra_info; \ + } while (false) + +/** + * Mask for clearing all ASYNC_AWAIT status bits + */ +#define ECMA_AWAIT_CLEAR_MASK (((1 << ECMA_AWAIT_STATE_SHIFT) - 1) - ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + +/** + * Helper macro for ECMA_AWAIT_CHANGE_STATE. + */ +#define ECMA_AWAIT_CS_HELPER(from, to) (((ECMA_AWAIT_##from) ^ (ECMA_AWAIT_##to)) << ECMA_AWAIT_STATE_SHIFT) + +/** + * Change the state of an async yield iterator. + */ +#define ECMA_AWAIT_CHANGE_STATE(async_generator_object_p, from, to) \ + ((async_generator_object_p)->extended_object.u.cls.u2.executable_obj_flags ^= ECMA_AWAIT_CS_HELPER (from, to)) + +ecma_value_t ecma_async_generator_enqueue (vm_executable_object_t *async_generator_object_p, + ecma_async_generator_operation_type_t operation, + ecma_value_t value); + +ecma_value_t ecma_async_generator_run (vm_executable_object_t *async_generator_object_p); +void ecma_async_generator_finalize (vm_executable_object_t *async_generator_object_p, ecma_value_t value); + +ecma_value_t ecma_await_continue (vm_executable_object_t *async_generator_object_p, ecma_value_t value); + +/** + * @} + * @} + */ + +#endif /* !ECMA_ASYNC_GENERATOR_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.cpp new file mode 100644 index 00000000..c42ad875 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.cpp @@ -0,0 +1,263 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-atomics-object.h" + +#include "ecma-arraybuffer-object.h" +#include "ecma-bigint.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-shared-arraybuffer-object.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" +#include "jmem.h" + +#if JERRY_BUILTIN_ATOMICS + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaatomicsobject ECMA builtin Atomics helper functions + * @{ + */ + +/** + * Atomics validate Shared integer typedArray + * + * See also: ES11 24.4.1.1 + * + * @return ecma value + */ +ecma_value_t +ecma_validate_shared_integer_typedarray (ecma_value_t typedarray, /**< typedArray argument */ + bool waitable) /**< waitable argument */ +{ + /* 2. */ + if (!ecma_is_typedarray (typedarray)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY); + } + + /* 3-4. */ + ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p); + + /* 5-6. */ + if (waitable) + { + if (!(target_info.id == ECMA_BIGINT64_ARRAY || target_info.id == ECMA_INT32_ARRAY)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_NOT_SUPPORTED); + } + } + else + { + if (target_info.id == ECMA_UINT8_CLAMPED_ARRAY || target_info.id == ECMA_FLOAT32_ARRAY + || target_info.id == ECMA_FLOAT64_ARRAY) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_NOT_SUPPORTED); + } + } + + /* 7. */ + JERRY_ASSERT (target_info.array_buffer_p != NULL); + + /* 8-10. */ + ecma_object_t *buffer = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (!ecma_object_class_is (buffer, ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_NOT_SHARED_ARRAY_BUFFER); + } + + return ecma_make_object_value (buffer); +} /* ecma_validate_shared_integer_typedarray */ + +/** + * Atomics validate Atomic Access + * + * See also: ES11 24.4.1.2 + * + * @return ecma value + */ +ecma_value_t +ecma_validate_atomic_access (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t request_index) /**< request_index argument */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (typedarray) + && ecma_typedarray_get_arraybuffer (ecma_get_object_from_value (typedarray)) != NULL); + + ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray); + + /* 2. */ + ecma_number_t access_index; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_index (request_index, &access_index))) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p); + + /* 4. */ + JERRY_ASSERT (access_index >= 0); + + /* 5-6. */ + if (JERRY_UNLIKELY (access_index >= target_info.length)) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_LENGTH); + } + + return ecma_make_number_value (access_index); +} /* ecma_validate_atomic_access */ + +/** + * Atomics read, modify, write + * + * See also: ES11 24.4.1.11 + * + * @return ecma value + */ +ecma_value_t +ecma_atomic_read_modify_write (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index, /**< index argument */ + ecma_value_t value, /**< value argument */ + ecma_atomics_op_t op) /**< operation argument */ +{ + /* 1. */ + ecma_value_t buffer = ecma_validate_shared_integer_typedarray (typedarray, false); + + if (ECMA_IS_VALUE_ERROR (buffer)) + { + return buffer; + } + + /* 2. */ + ecma_value_t idx = ecma_validate_atomic_access (typedarray, index); + + if (ECMA_IS_VALUE_ERROR (idx)) + { + return idx; + } + + /* 3. */ + ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p); + + /* 4-5. */ + ecma_value_t val = ECMA_VALUE_ERROR; + ecma_number_t tmp; + if (target_info.id == ECMA_BIGINT64_ARRAY || target_info.id == ECMA_BIGUINT64_ARRAY) + { + val = ecma_bigint_to_bigint (value, true); + } + else if (!ECMA_IS_VALUE_ERROR (ecma_op_to_integer (value, &tmp))) + { + val = ecma_make_number_value (tmp); + } + + if (ECMA_IS_VALUE_ERROR (val)) + { + return val; + } + + /* 6. */ + uint8_t element_size = target_info.element_size; + + /* 7. */ + ecma_typedarray_type_t element_type = target_info.id; + + /* 8. */ + uint32_t offset = target_info.offset; + + /* 9. */ + uint32_t indexed_position = ecma_number_to_uint32 (idx) * element_size + offset; + + ecma_free_value (idx); + + JERRY_UNUSED (indexed_position); + JERRY_UNUSED (element_type); + JERRY_UNUSED (val); + JERRY_UNUSED (buffer); + JERRY_UNUSED (op); + + ecma_free_value (val); + + /* 10. */ + return ecma_make_uint32_value (0); +} /* ecma_atomic_read_modify_write */ + +/** + * Atomics load + * + * See also: ES11 24.4.1.12 + * + * @return ecma value + */ +ecma_value_t +ecma_atomic_load (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index) /**< index argument */ +{ + ecma_value_t buffer = ecma_validate_shared_integer_typedarray (typedarray, false); + + if (ECMA_IS_VALUE_ERROR (buffer)) + { + return buffer; + } + + /* 2. */ + ecma_value_t idx = ecma_validate_atomic_access (typedarray, index); + + if (ECMA_IS_VALUE_ERROR (idx)) + { + return idx; + } + + /* 3. */ + ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p); + + /* 4. */ + uint8_t element_size = target_info.element_size; + + /* 5. */ + ecma_typedarray_type_t element_type = target_info.id; + + /* 6. */ + uint32_t offset = target_info.offset; + + /* 7. */ + uint32_t indexed_position = ecma_number_to_uint32 (idx) * element_size + offset; + + JERRY_UNUSED (indexed_position); + JERRY_UNUSED (element_type); + JERRY_UNUSED (buffer); + + /* 8. */ + return ecma_make_uint32_value (0); +} /* ecma_atomic_load */ + +/** + * @} + * @} + */ +#endif /* JERRY_BUILTIN_ATOMICS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.h new file mode 100644 index 00000000..d73ae99b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.h @@ -0,0 +1,56 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ATOMICS_OBJECT_H +#define ECMA_ATOMICS_OBJECT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_ATOMICS + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaatomicsobject ECMA builtin Atomics helper functions + * @{ + */ + +/** + * Atomics flags. + */ +typedef enum +{ + ECMA_ATOMICS_ADD, /**< Atomics add operation */ + ECMA_ATOMICS_SUBTRACT, /**< Atomics subtract operation */ + ECMA_ATOMICS_AND, /**< Atomics and operation */ + ECMA_ATOMICS_OR, /**< Atomics or operation */ + ECMA_ATOMICS_XOR, /**< Atomics xor operation */ + ECMA_ATOMICS_EXCHANGE, /**< Atomics exchange operation */ + ECMA_ATOMICS_COMPARE_EXCHANGE /**< Atomics compare exchange operation */ +} ecma_atomics_op_t; + +ecma_value_t ecma_validate_shared_integer_typedarray (ecma_value_t typedarray, bool waitable); +ecma_value_t ecma_validate_atomic_access (ecma_value_t typedarray, ecma_value_t request_index); +ecma_value_t +ecma_atomic_read_modify_write (ecma_value_t typedarray, ecma_value_t index, ecma_value_t value, ecma_atomics_op_t op); +ecma_value_t ecma_atomic_load (ecma_value_t typedarray, ecma_value_t index); +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ATOMICS */ + +#endif /* ECMA_ATOMICS_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.cpp new file mode 100644 index 00000000..b98f27ee --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.cpp @@ -0,0 +1,1775 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-big-uint.h" + +#include "ecma-helpers.h" + +#include "jmem.h" +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_BIGINT + +JERRY_STATIC_ASSERT ((sizeof (ecma_bigint_two_digits_t) == 2 * sizeof (ecma_bigint_digit_t)), + ecma_big_int_two_digits_must_be_twice_as_long_as_ecma_big_int_digit); + +JERRY_STATIC_ASSERT (((1 << (int)ECMA_BIGINT_DIGIT_SHIFT) == (8 * sizeof (ecma_bigint_digit_t))), + ecma_bigint_digit_shift_is_incorrect); + +JERRY_STATIC_ASSERT ((((int)ECMA_BIG_UINT_BITWISE_DECREASE_LEFT << 1) == (int)ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT), + ecma_big_uint_bitwise_left_and_right_sub_option_bits_must_follow_each_other); + +/** + * Create a new BigInt value + * + * @return new BigInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_bigint_create (uint32_t size) /**< size of the new BigInt value */ +{ + JERRY_ASSERT (size > 0); + JERRY_ASSERT ((size % sizeof (ecma_bigint_digit_t)) == 0); + + if (JERRY_UNLIKELY (size > ECMA_BIGINT_MAX_SIZE)) + { + return NULL; + } + + ecma_extended_primitive_t *value_p; + + size_t mem_size = ECMA_BIGINT_GET_BYTE_SIZE (size) + sizeof (ecma_extended_primitive_t); + value_p = (ecma_extended_primitive_t *) jmem_heap_alloc_block_null_on_error (mem_size); + + if (JERRY_UNLIKELY (value_p == NULL)) + { + return NULL; + } + + value_p->refs_and_type = ECMA_EXTENDED_PRIMITIVE_REF_ONE | ECMA_TYPE_BIGINT; + value_p->u.bigint_sign_and_size = size; + return value_p; +} /* ecma_bigint_create */ + +/** + * Extend a BigUInt value with a new data prefix value + * + * @return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_extend (ecma_extended_primitive_t *value_p, /**< BigUInt value */ + ecma_bigint_digit_t digit) /**< new digit */ +{ + uint32_t old_size = ECMA_BIGINT_GET_SIZE (value_p); + + if (ECMA_BIGINT_SIZE_IS_ODD (old_size)) + { + value_p->u.bigint_sign_and_size += (uint32_t) sizeof (ecma_bigint_digit_t); + *ECMA_BIGINT_GET_DIGITS (value_p, old_size) = digit; + return value_p; + } + + ecma_extended_primitive_t *result_p = ecma_bigint_create (old_size + (uint32_t) sizeof (ecma_bigint_digit_t)); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + ecma_deref_bigint (value_p); + return NULL; + } + + memcpy (result_p + 1, value_p + 1, old_size); + ecma_deref_bigint (value_p); + + *ECMA_BIGINT_GET_DIGITS (result_p, old_size) = digit; + return result_p; +} /* ecma_big_uint_extend */ + +/** + * Count the number of leading zero bits of a digit + * + * return number of leading zero bits + */ +ecma_bigint_digit_t +ecma_big_uint_count_leading_zero (ecma_bigint_digit_t digit) /**< digit value */ +{ + ecma_bigint_digit_t shift = 4 * sizeof (ecma_bigint_digit_t); + ecma_bigint_digit_t result = 8 * sizeof (ecma_bigint_digit_t); + + do + { + ecma_bigint_digit_t value = digit >> shift; + if (value > 0) + { + digit = value; + result -= shift; + } + shift >>= 1; + } while (shift > 0); + + return result - digit; +} /* ecma_big_uint_count_leading_zero */ + +/** + * Helper function which discards the leading zero digits of a BigUInt value + * + * @return new BigUInt value, NULL on error + */ +static ecma_extended_primitive_t * +ecma_big_uint_normalize_result (ecma_extended_primitive_t *value_p, /**< BigUInt value */ + ecma_bigint_digit_t *last_digit_p) /**< points to the end of BigUInt */ +{ + JERRY_ASSERT (last_digit_p[-1] == 0); + + ecma_bigint_digit_t *first_digit_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + + /* The following code is tricky. The value stored in first_digit_p[-1] is the size + * of the BigUInt value, and it cannot be zero. Hence the loop below will terminate. */ + JERRY_ASSERT (first_digit_p[-1] != 0); + + do + { + --last_digit_p; + } while (last_digit_p[-1] == 0); + + JERRY_ASSERT (last_digit_p >= first_digit_p); + + if (first_digit_p == last_digit_p) + { + ecma_deref_bigint (value_p); + return ECMA_BIGINT_POINTER_TO_ZERO; + } + + uint32_t new_size = (uint32_t) ((uint8_t *) last_digit_p - (uint8_t *) first_digit_p); + + if (ECMA_BIGINT_SIZE_IS_ODD (new_size) + && ((new_size + sizeof (ecma_bigint_digit_t)) == ECMA_BIGINT_GET_SIZE (value_p))) + { + value_p->u.bigint_sign_and_size -= (uint32_t) sizeof (ecma_bigint_digit_t); + return value_p; + } + + ecma_extended_primitive_t *result_p = ecma_bigint_create (new_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + ecma_deref_bigint (value_p); + return NULL; + } + + memcpy (ECMA_BIGINT_GET_DIGITS (result_p, 0), ECMA_BIGINT_GET_DIGITS (value_p, 0), new_size); + ecma_deref_bigint (value_p); + + return result_p; +} /* ecma_big_uint_normalize_result */ + +/** + * Helper function which increases the result by 1 and extends or shrinks the BigUInt when necessary + * + * @return new BigUInt value, NULL on error + */ +static ecma_extended_primitive_t * +ecma_big_uint_increase_result (ecma_extended_primitive_t *value_p) /**< BigUInt value */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0); + + ecma_bigint_digit_t *first_digit_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + ecma_bigint_digit_t *last_digit_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + + while (*first_digit_p == ~((ecma_bigint_digit_t) 0)) + { + *first_digit_p++ = 0; + + if (first_digit_p == last_digit_p) + { + return ecma_big_uint_extend (value_p, 1); + } + } + + (*first_digit_p)++; + + if (last_digit_p[-1] != 0) + { + return value_p; + } + + return ecma_big_uint_normalize_result (value_p, last_digit_p); +} /* ecma_big_uint_increase_result */ + +/** + * Compare two BigUInt numbers + * + * return -1, if left value < right value, 0 if they are equal, and 1 otherwise + */ +int +ecma_big_uint_compare (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0); + + if (left_size > right_size) + { + return 1; + } + + if (left_size < right_size) + { + return -1; + } + + ecma_bigint_digit_t *start_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, left_size); + ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, left_size); + + do + { + ecma_bigint_digit_t left_value = *(--left_p); + ecma_bigint_digit_t right_value = *(--right_p); + + if (left_value < right_value) + { + return -1; + } + + if (left_value > right_value) + { + return 1; + } + } while (left_p > start_p); + + return 0; +} /* ecma_big_uint_compare */ + +/** + * In-place multiply and addition operation with digit + * + * return updated value on success, NULL if no memory is available + */ +ecma_extended_primitive_t * +ecma_big_uint_mul_digit (ecma_extended_primitive_t *value_p, /**< BigUInt value */ + ecma_bigint_digit_t mul, /**< multiply value */ + ecma_bigint_digit_t add) /**< addition value */ +{ + JERRY_ASSERT (mul > 1); + JERRY_ASSERT (add < mul); + + if (JERRY_UNLIKELY (value_p == NULL)) + { + JERRY_ASSERT (add > 0); + + value_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t)); + + if (JERRY_UNLIKELY (value_p == NULL)) + { + return NULL; + } + + *ECMA_BIGINT_GET_DIGITS (value_p, 0) = add; + return value_p; + } + + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + ecma_bigint_digit_t *current_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + ecma_bigint_digit_t carry = add; + + do + { + ecma_bigint_two_digits_t multiply_result = ((ecma_bigint_two_digits_t) *current_p) * mul; + ecma_bigint_digit_t multiply_result_low, new_carry; + + multiply_result_low = (ecma_bigint_digit_t) multiply_result; + new_carry = (ecma_bigint_digit_t) (multiply_result >> (8 * sizeof (ecma_bigint_digit_t))); + + multiply_result_low += carry; + if (multiply_result_low < carry) + { + new_carry++; + } + + *current_p++ = multiply_result_low; + carry = new_carry; + } while (current_p < end_p); + + if (carry == 0) + { + return value_p; + } + + return ecma_big_uint_extend (value_p, carry); +} /* ecma_big_uint_mul_digit */ + +/** + * Convert a BigUInt to a human readable number + * + * return char sequence on success, NULL otherwise + */ +lit_utf8_byte_t * +ecma_big_uint_to_string (ecma_extended_primitive_t *value_p, /**< BigUInt value */ + uint32_t radix, /**< radix number between 2 and 36 */ + uint32_t *char_start_p, /**< [out] start offset of numbers */ + uint32_t *char_size_p) /**< [out] size of the output buffer */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (radix >= 2 && radix <= 36); + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + uint32_t max_size = size * 8; + + if (radix < 16) + { + if (radix >= 8) + { + /* Most frequent case. */ + max_size = (max_size + 2) / 3; + } + else if (radix >= 4) + { + max_size = (max_size + 1) >> 1; + } + } + else if (radix < 32) + { + max_size = (max_size + 3) >> 2; + } + else + { + max_size = (max_size + 4) / 5; + } + + /* This space can be used to store a sign. */ + max_size += (uint32_t) (2 * sizeof (ecma_bigint_digit_t) - 1); + max_size &= ~(uint32_t) (sizeof (ecma_bigint_digit_t) - 1); + *char_size_p = max_size; + + lit_utf8_byte_t *result_p = (lit_utf8_byte_t *) jmem_heap_alloc_block_null_on_error (max_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + memcpy (result_p, value_p + 1, size); + + ecma_bigint_digit_t *start_p = (ecma_bigint_digit_t *) (result_p + size); + ecma_bigint_digit_t *end_p = (ecma_bigint_digit_t *) result_p; + lit_utf8_byte_t *string_p = result_p + max_size; + + do + { + ecma_bigint_digit_t *current_p = (ecma_bigint_digit_t *) start_p; + ecma_bigint_digit_t remainder = 0; + + if (sizeof (uintptr_t) == sizeof (ecma_bigint_two_digits_t)) + { + do + { + ecma_bigint_two_digits_t result = *(--current_p) | ECMA_BIGINT_HIGH_DIGIT (remainder); + + *current_p = (ecma_bigint_digit_t) (result / radix); + remainder = (ecma_bigint_digit_t) (result % radix); + } while (current_p > end_p); + } + else + { + if (ECMA_BIGINT_SIZE_IS_ODD ((uintptr_t) current_p - (uintptr_t) end_p)) + { + ecma_bigint_digit_t result = *(--current_p); + *current_p = result / radix; + remainder = result % radix; + } + + while (current_p > end_p) + { + /* The following algorithm splits the 64 bit input into three numbers, extend + * them with remainder, divide them by radix, and updates the three bit ranges + * corresponding to the three numbers. */ + + const uint32_t extract_bits_low = 10; + const uint32_t extract_bits_low_mask = (uint32_t) ((1 << extract_bits_low) - 1); + const uint32_t extract_bits_high = (uint32_t) ((sizeof (ecma_bigint_digit_t) * 8) - extract_bits_low); + const uint32_t extract_bits_high_mask = (uint32_t) ((1 << extract_bits_high) - 1); + + ecma_bigint_digit_t result_high = current_p[-1]; + ecma_bigint_digit_t result_mid = (result_high & extract_bits_low_mask) << extract_bits_low; + + result_high = (result_high >> extract_bits_low) | (remainder << extract_bits_high); + result_mid |= (result_high % radix) << (extract_bits_low * 2); + result_high = (result_high / radix) << extract_bits_low; + + ecma_bigint_digit_t result_low = current_p[-2]; + result_mid |= result_low >> extract_bits_high; + result_low = (result_low & extract_bits_high_mask) | ((result_mid % radix) << extract_bits_high); + + result_mid = result_mid / radix; + + current_p[-1] = result_high | (result_mid >> extract_bits_low); + current_p[-2] = (result_low / radix) | (result_mid << extract_bits_high); + + remainder = result_low % radix; + current_p -= 2; + } + } + + *(--string_p) = + (lit_utf8_byte_t) ((remainder < 10) ? (remainder + LIT_CHAR_0) : (remainder + (LIT_CHAR_LOWERCASE_A - 10))); + JERRY_ASSERT (string_p >= (lit_utf8_byte_t *) start_p); + + if (start_p[-1] == 0) + { + start_p--; + } + } while (start_p > end_p); + + *char_start_p = (uint32_t) (string_p - result_p); + return result_p; +} /* ecma_big_uint_to_string */ + +/** + * Increase the value of a BigUInt value by 1 + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_increase (ecma_extended_primitive_t *value_p) /**< BigUInt value */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + ecma_bigint_digit_t *digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + ecma_bigint_digit_t *digits_end_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + + if (JERRY_UNLIKELY (digits_p[0] == ~((ecma_bigint_digit_t) 0) && digits_end_p[-1] == ~((ecma_bigint_digit_t) 0))) + { + do + { + digits_p++; + } while (digits_p < digits_end_p && digits_p[0] == ~((ecma_bigint_digit_t) 0)); + + if (digits_p == digits_end_p) + { + ecma_extended_primitive_t *result_value_p; + result_value_p = ecma_bigint_create ((uint32_t) (size + sizeof (ecma_bigint_digit_t))); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + memset (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), 0, size); + *ECMA_BIGINT_GET_DIGITS (result_value_p, size) = 1; + return result_value_p; + } + + digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + + while (digits_p[0] == ~((ecma_bigint_digit_t) 0)) + { + digits_p++; + *result_p++ = 0; + } + + *result_p++ = (*digits_p++) + 1; + + if (digits_p < digits_end_p) + { + memcpy (result_p, digits_p, (size_t) ((uint8_t *) digits_end_p - (uint8_t *) digits_p)); + } + return result_value_p; +} /* ecma_big_uint_increase */ + +/** + * Decrease the value of a BigUInt value by 1 + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_decrease (ecma_extended_primitive_t *value_p) /**< BigUInt value */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + ecma_bigint_digit_t *digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + ecma_bigint_digit_t *digits_end_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + + JERRY_ASSERT (size > sizeof (ecma_bigint_digit_t) || *digits_p > 1); + + if (JERRY_UNLIKELY (digits_p[0] == 0 && digits_end_p[-1] == 1)) + { + do + { + digits_p++; + JERRY_ASSERT (digits_p < digits_end_p); + } while (digits_p[0] == 0); + + if (digits_p + 1 == digits_end_p) + { + size -= (uint32_t) sizeof (ecma_bigint_digit_t); + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + memset (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), 0xff, size); + return result_value_p; + } + + digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + + while (digits_p[0] == 0) + { + digits_p++; + *result_p++ = ~((ecma_bigint_digit_t) 0); + } + + *result_p++ = (*digits_p++) - 1; + + if (digits_p < digits_end_p) + { + memcpy (result_p, digits_p, (size_t) ((uint8_t *) digits_end_p - (uint8_t *) digits_p)); + } + return result_value_p; +} /* ecma_big_uint_decrease */ + +/** + * Add right BigUInt value to the left BigUInt value + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_add (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0); + + if (left_size < right_size) + { + /* Swap values. */ + ecma_extended_primitive_t *tmp_value_p = left_value_p; + left_value_p = right_value_p; + right_value_p = tmp_value_p; + + uint32_t tmp_size = left_size; + left_size = right_size; + right_size = tmp_size; + } + + ecma_extended_primitive_t *result_p = ecma_bigint_create (left_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *current_p = ECMA_BIGINT_GET_DIGITS (result_p, 0); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (result_p, right_size); + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, 0); + ecma_bigint_digit_t carry = 0; + + left_size -= right_size; + + do + { + ecma_bigint_digit_t left = *left_p++; + + if (carry == 0 || left != ~(ecma_bigint_digit_t) 0) + { + left += carry; + carry = 0; + } + else + { + left = 0; + carry = 1; + } + + ecma_bigint_digit_t right = *right_p++; + left += right; + + if (left < right) + { + JERRY_ASSERT (carry == 0); + carry = 1; + } + + *current_p++ = left; + } while (current_p < end_p); + + end_p = (ecma_bigint_digit_t *) (((uint8_t *) end_p) + left_size); + + if (carry != 0) + { + while (true) + { + if (JERRY_UNLIKELY (current_p == end_p)) + { + return ecma_big_uint_extend (result_p, 1); + } + + ecma_bigint_digit_t value = *left_p++; + + if (value != ~(ecma_bigint_digit_t) 0) + { + *current_p++ = value + 1; + break; + } + + *current_p++ = 0; + } + } + + if (current_p < end_p) + { + memcpy (current_p, left_p, (size_t) ((uint8_t *) end_p - (uint8_t *) current_p)); + } + + return result_p; +} /* ecma_big_uint_add */ + +/** + * Substract right BigUInt value from the left BigUInt value + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_sub (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0); + JERRY_ASSERT (left_size >= right_size); + + ecma_extended_primitive_t *result_p = ecma_bigint_create (left_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *current_p = ECMA_BIGINT_GET_DIGITS (result_p, 0); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (result_p, right_size); + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, 0); + ecma_bigint_digit_t carry = 0; + + left_size -= right_size; + + do + { + ecma_bigint_digit_t left = *left_p++; + ecma_bigint_digit_t right = *right_p++; + + if (carry == 0 || left != 0) + { + left -= carry; + carry = left < right; + } + else + { + left = ~(ecma_bigint_digit_t) 0; + carry = 1; + } + + *current_p++ = left - right; + } while (current_p < end_p); + + end_p = (ecma_bigint_digit_t *) (((uint8_t *) end_p) + left_size); + + if (carry != 0) + { + while (true) + { + JERRY_ASSERT (current_p < end_p); + + ecma_bigint_digit_t value = *left_p++; + + if (value != 0) + { + *current_p++ = value - 1; + break; + } + + *current_p++ = ~(ecma_bigint_digit_t) 0; + } + } + + if (current_p < end_p) + { + memcpy (current_p, left_p, (size_t) ((uint8_t *) end_p - (uint8_t *) current_p)); + return result_p; + } + + if (current_p[-1] != 0) + { + return result_p; + } + + return ecma_big_uint_normalize_result (result_p, current_p); +} /* ecma_big_uint_sub */ + +/** + * Multiply two BigUInt values + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_mul (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0); + + if (left_size < right_size) + { + /* Swap values. */ + ecma_extended_primitive_t *tmp_value_p = left_value_p; + left_value_p = right_value_p; + right_value_p = tmp_value_p; + + uint32_t tmp_size = left_size; + left_size = right_size; + right_size = tmp_size; + } + + uint32_t result_size = left_size + right_size - (uint32_t) sizeof (ecma_bigint_digit_t); + + ecma_extended_primitive_t *result_p = ecma_bigint_create (result_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + memset (ECMA_BIGINT_GET_DIGITS (result_p, 0), 0, result_size); + + /* Lower amount of space is allocated by default. This value provides extra space if needed. */ + ecma_bigint_digit_t extra_space[1] = { 0 }; + + ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, 0); + ecma_bigint_digit_t *right_end_p = ECMA_BIGINT_GET_DIGITS (right_value_p, right_size); + ecma_bigint_digit_t *left_start_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *left_end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, left_size); + + ecma_bigint_digit_t *result_start_p = ECMA_BIGINT_GET_DIGITS (result_p, 0); + ecma_bigint_digit_t *result_end_p = ECMA_BIGINT_GET_DIGITS (result_p, result_size); + + do + { + ecma_bigint_two_digits_t right = *right_p++; + + if (right == 0) + { + result_start_p++; + continue; + } + + ecma_bigint_digit_t *left_p = left_start_p; + ecma_bigint_digit_t *destination_p = result_start_p; + ecma_bigint_digit_t carry = 0; + + do + { + JERRY_ASSERT (destination_p != (ecma_bigint_digit_t *) (extra_space + 1)); + + ecma_bigint_two_digits_t multiply_result; + ecma_bigint_digit_t multiply_result_low, new_carry; + ecma_bigint_digit_t value = *destination_p; + + multiply_result = ((ecma_bigint_two_digits_t) (*left_p++)) * ((ecma_bigint_two_digits_t) right); + multiply_result_low = (ecma_bigint_digit_t) multiply_result; + value += multiply_result_low; + new_carry = (ecma_bigint_digit_t) (multiply_result >> (8 * sizeof (ecma_bigint_digit_t))); + + /* The new_carry can never overflow because: + * a) If left or right is less than 0xff..ff, new_carry will be less than or equal to + * 0xff...fd, and increasing it by maximum of two (carries) cannot overflow. + * b) If left and right are both equal to 0xff..ff, multiply_result_low will be 1, + * and computing value + carry + 1 can only increase new_carry at most once. */ + + if (value < multiply_result_low) + { + JERRY_ASSERT (new_carry < ~(ecma_bigint_digit_t) 0); + new_carry++; + } + + value += carry; + + if (value < carry) + { + JERRY_ASSERT (new_carry < ~(ecma_bigint_digit_t) 0); + new_carry++; + } + + carry = new_carry; + *destination_p++ = value; + + if (destination_p == result_end_p) + { + destination_p = (ecma_bigint_digit_t *) extra_space; + } + } while (left_p < left_end_p); + + while (carry > 0) + { + JERRY_ASSERT (destination_p != (ecma_bigint_digit_t *) (extra_space + 1)); + + ecma_bigint_digit_t value = *destination_p; + + value += carry; + carry = (value < carry); + + *destination_p++ = value; + + if (destination_p == result_end_p) + { + destination_p = (ecma_bigint_digit_t *) extra_space; + } + } + + result_start_p++; + } while (right_p < right_end_p); + + if (extra_space[0] == 0) + { + return result_p; + } + + return ecma_big_uint_extend (result_p, extra_space[0]); +} /* ecma_big_uint_mul */ + +/** + * Divide left BigUInt value with right digit value + * + * return new BigUInt value, NULL on error + */ +static ecma_extended_primitive_t * +ecma_big_uint_div_digit (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_bigint_digit_t divisor_digit, /**< divisor value */ + bool is_mod) /**< true if return with remainder */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (divisor_digit > 0); + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, left_size - sizeof (ecma_bigint_digit_t)); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + + ecma_bigint_digit_t last_digit = *left_p; + ecma_bigint_digit_t remainder = last_digit % divisor_digit; + + last_digit = last_digit / divisor_digit; + + ecma_extended_primitive_t *result_p = NULL; + ecma_bigint_digit_t *current_p = NULL; + + if (!is_mod) + { + ecma_bigint_digit_t result_size = left_size; + + if (last_digit == 0) + { + result_size -= (uint32_t) sizeof (ecma_bigint_digit_t); + } + + result_p = ecma_bigint_create (result_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + current_p = ECMA_BIGINT_GET_DIGITS (result_p, result_size); + + if (last_digit != 0) + { + *(--current_p) = last_digit; + } + } + + while (left_p > end_p) + { + const uint32_t shift = 1 << ECMA_BIGINT_DIGIT_SHIFT; + + ecma_bigint_two_digits_t result = *(--left_p) | (((ecma_bigint_two_digits_t) remainder) << shift); + + if (!is_mod) + { + *(--current_p) = (ecma_bigint_digit_t) (result / divisor_digit); + } + + remainder = (ecma_bigint_digit_t) (result % divisor_digit); + } + + if (!is_mod) + { + JERRY_ASSERT (current_p == ECMA_BIGINT_GET_DIGITS (result_p, 0)); + return result_p; + } + + if (remainder == 0) + { + return ECMA_BIGINT_POINTER_TO_ZERO; + } + + result_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t)); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + *ECMA_BIGINT_GET_DIGITS (result_p, 0) = remainder; + return result_p; +} /* ecma_big_uint_div_digit */ + +/** + * Shift left a BigUInt value by a digit value + * + * return newly allocated buffer, NULL on error + */ +static ecma_bigint_digit_t * +ecma_big_uint_div_shift_left (ecma_extended_primitive_t *value_p, /**< BigUInt value */ + ecma_bigint_digit_t shift_left, /**< left shift */ + bool extend) /**< extend the result with an extra digit */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + ecma_bigint_digit_t *source_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + + if (extend) + { + size += (uint32_t) sizeof (ecma_bigint_digit_t); + } + + ecma_bigint_digit_t *result_p = (ecma_bigint_digit_t *) jmem_heap_alloc_block_null_on_error (size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return result_p; + } + + if (shift_left == 0) + { + JERRY_ASSERT (extend); + + size -= (uint32_t) sizeof (ecma_bigint_digit_t); + *(ecma_bigint_digit_t *) (((uint8_t *) result_p) + size) = 0; + + memcpy (result_p, source_p, size); + return result_p; + } + + ecma_bigint_digit_t *destination_p = result_p; + ecma_bigint_digit_t carry = 0; + uint32_t shift_right = (1 << ECMA_BIGINT_DIGIT_SHIFT) - shift_left; + + do + { + ecma_bigint_digit_t value = *source_p++; + + *destination_p++ = (value << shift_left) | carry; + carry = value >> shift_right; + } while (source_p < end_p); + + if (extend) + { + *destination_p++ = carry; + } + + return result_p; +} /* ecma_big_uint_div_shift_left */ + +/** + * Divide left BigUInt value with right BigUInt value + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_div_mod (ecma_extended_primitive_t *dividend_value_p, /**< divider BigUInt value */ + ecma_extended_primitive_t *divisor_value_p, /**< divisor BigUInt value */ + bool is_mod) /**< true if return with remainder instead of quotient */ +{ + /* This algorithm is based on Donald Knuth’s "Algorithm D" */ + uint32_t divisor_size = ECMA_BIGINT_GET_SIZE (divisor_value_p); + + JERRY_ASSERT (divisor_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (divisor_value_p, divisor_size) != 0); + + /* The divisor must have at least two digits, so the single digit case is handled separately. */ + if (divisor_size == sizeof (ecma_bigint_digit_t)) + { + return ecma_big_uint_div_digit (dividend_value_p, *ECMA_BIGINT_GET_DIGITS (divisor_value_p, 0), is_mod); + } + + /* D1. [Normalize] */ + ecma_bigint_digit_t divisor_high = ECMA_BIGINT_GET_LAST_DIGIT (divisor_value_p, divisor_size); + ecma_bigint_digit_t shift_left = ecma_big_uint_count_leading_zero (divisor_high); + ecma_bigint_digit_t *buffer_p = ecma_big_uint_div_shift_left (dividend_value_p, shift_left, true); + ecma_bigint_digit_t *dividend_end_p; + ecma_bigint_digit_t *dividend_p; + ecma_bigint_digit_t *divisor_end_p; + ecma_bigint_digit_t divisor_low; + + if (JERRY_UNLIKELY (buffer_p == NULL)) + { + return NULL; + } + + uint32_t dividend_size = ECMA_BIGINT_GET_SIZE (dividend_value_p); + ecma_extended_primitive_t *result_p = NULL; + ecma_bigint_digit_t *divisor_p; + + JERRY_ASSERT (dividend_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (dividend_value_p, dividend_size) != 0); + JERRY_ASSERT (dividend_size >= divisor_size); + + if (shift_left > 0) + { + divisor_p = ecma_big_uint_div_shift_left (divisor_value_p, shift_left, false); + + if (JERRY_UNLIKELY (divisor_p == NULL)) + { + goto error; + } + } + else + { + divisor_p = ECMA_BIGINT_GET_DIGITS (divisor_value_p, 0); + } + + dividend_end_p = (ecma_bigint_digit_t *) (((uint8_t *) buffer_p) + dividend_size); + dividend_p = (ecma_bigint_digit_t *) (((uint8_t *) dividend_end_p) - divisor_size); + divisor_end_p = (ecma_bigint_digit_t *) (((uint8_t *) divisor_p) + divisor_size); + divisor_low = divisor_end_p[-2]; + + divisor_high = divisor_end_p[-1]; + JERRY_ASSERT ((divisor_high & (((ecma_bigint_digit_t) 1) << (8 * sizeof (ecma_bigint_digit_t) - 1))) != 0); + + do + { + /* D3. [Calculate Q′] */ + ecma_bigint_digit_t result_div; + + /* This do-while(false) statement allows local declarations and early exit. */ + do + { + ecma_bigint_digit_t result_mod; + + if (dividend_end_p[0] < divisor_high) + { + ecma_bigint_two_digits_t dividend = dividend_end_p[-1] | ECMA_BIGINT_HIGH_DIGIT (dividend_end_p[0]); + result_div = (ecma_bigint_digit_t) (dividend / divisor_high); + result_mod = (ecma_bigint_digit_t) (dividend % divisor_high); + } + else + { + JERRY_ASSERT (dividend_end_p[0] == divisor_high && dividend_end_p[-1] < divisor_high); + + result_div = ~((ecma_bigint_digit_t) 0); + result_mod = dividend_end_p[-1] + divisor_high; + + if (result_mod < divisor_high) + { + break; + } + } + + ecma_bigint_two_digits_t low_digits = ((ecma_bigint_two_digits_t) result_div) * divisor_low; + + while (low_digits > (ECMA_BIGINT_HIGH_DIGIT (result_mod) | divisor_low)) + { + result_div--; + result_mod += divisor_high; + + /* If result_mod becomes a two digit long number, the condition of the loop must be true, + * so the loop can be aborted. This loop stops after maximum of two iterations, since + * the highest bit of divisor_high is set. */ + if (result_mod < divisor_high) + { + break; + } + + /* Subtraction is faster than recomputing result_div * divisor_low. */ + low_digits -= divisor_low; + } + } while (false); + + /* D4. [Multiply and subtract] */ + ecma_bigint_digit_t *destination_p = dividend_p; + ecma_bigint_digit_t *source_p = divisor_p; + ecma_bigint_digit_t carry = 0; + + do + { + ecma_bigint_two_digits_t multiply_result = ((ecma_bigint_two_digits_t) (*source_p++)) * result_div; + ecma_bigint_digit_t multiply_result_low, new_carry; + ecma_bigint_digit_t value = *destination_p; + + /* The new carry never overflows. See the comment in ecma_big_uint_mul. */ + new_carry = (ecma_bigint_digit_t) (multiply_result >> (8 * sizeof (ecma_bigint_digit_t))); + multiply_result_low = (ecma_bigint_digit_t) multiply_result; + + if (value < multiply_result_low) + { + new_carry++; + } + + value -= multiply_result_low; + + if (value < carry) + { + new_carry++; + } + + *destination_p++ = value - carry; + carry = new_carry; + } while (source_p < divisor_end_p); + + bool negative_result = *destination_p < carry; + *destination_p -= carry; + + if (negative_result) + { + /* D6. [Add back] */ + result_div--; + + destination_p = dividend_p; + source_p = divisor_p; + carry = 0; + + do + { + ecma_bigint_digit_t left = *destination_p; + + if (carry == 0 || left != ~(ecma_bigint_digit_t) 0) + { + left += carry; + carry = 0; + } + else + { + left = 0; + carry = 1; + } + + ecma_bigint_digit_t right = *source_p++; + left += right; + + if (left < right) + { + JERRY_ASSERT (carry == 0); + carry = 1; + } + + *destination_p++ = left; + } while (source_p < divisor_end_p); + } + + *dividend_end_p = result_div; + + dividend_p--; + dividend_end_p--; + } while (dividend_p >= buffer_p); + + ecma_bigint_digit_t *source_p; + ecma_bigint_digit_t *source_end_p; + + if (is_mod) + { + source_p = buffer_p; + source_end_p = dividend_end_p; + + while (source_end_p > source_p && *source_end_p == 0) + { + source_end_p--; + } + + if ((*source_end_p >> shift_left) != 0) + { + source_end_p++; + /* This is required to reset carry below. */ + *source_end_p = 0; + } + } + else + { + source_p = dividend_end_p + 1; + source_end_p = (ecma_bigint_digit_t *) (((uint8_t *) buffer_p) + dividend_size); + + if (*source_end_p != 0) + { + source_end_p++; + } + } + + result_p = ECMA_BIGINT_POINTER_TO_ZERO; + + if (source_p < source_end_p) + { + result_p = ecma_bigint_create ((uint32_t) ((uint8_t *) source_end_p - (uint8_t *) source_p)); + + if (result_p != NULL) + { + ecma_bigint_digit_t *destination_p = ECMA_BIGINT_GET_DIGITS (result_p, 0); + + if (is_mod && shift_left > 0) + { + ecma_bigint_digit_t shift_right = shift_left; + + shift_left = (ecma_bigint_digit_t) (8 * (sizeof (ecma_bigint_digit_t)) - shift_left); + destination_p += source_end_p - source_p; + + ecma_bigint_digit_t carry = *source_end_p << shift_left; + + do + { + ecma_bigint_digit_t value = *(--source_end_p); + + *(--destination_p) = (value >> shift_right) | carry; + carry = value << shift_left; + } while (source_end_p > source_p); + } + else + { + memcpy (destination_p, source_p, (size_t) ((uint8_t *) source_end_p - (uint8_t *) source_p)); + } + } + } + +error: + jmem_heap_free_block (buffer_p, dividend_size + sizeof (ecma_bigint_digit_t)); + + if (shift_left > 0 && divisor_p != NULL) + { + jmem_heap_free_block (divisor_p, divisor_size); + } + + return result_p; +} /* ecma_big_uint_div_mod */ + +/** + * Shift left BigUInt values by an uint32 value + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_shift_left (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + uint32_t right_value) /**< shift value */ +{ + JERRY_ASSERT (right_value > 0); + + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + + uint32_t zero_size = (right_value >> ECMA_BIGINT_DIGIT_SHIFT) * (uint32_t) sizeof (ecma_bigint_digit_t); + uint32_t result_size = left_size + zero_size; + + uint32_t shift_left = right_value & ((1 << ECMA_BIGINT_DIGIT_SHIFT) - 1); + uint32_t shift_right = (1 << ECMA_BIGINT_DIGIT_SHIFT) - shift_left; + + if (shift_left > 0 && (ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) >> shift_right) != 0) + { + result_size += (uint32_t) sizeof (ecma_bigint_digit_t); + } + + if (result_size > ECMA_BIGINT_MAX_SIZE) + { + return NULL; + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (result_size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + + if (zero_size > 0) + { + memset (result_p, 0, zero_size); + result_p = (ecma_bigint_digit_t *) (((uint8_t *) result_p) + zero_size); + } + + if (shift_left == 0) + { + /* Shift by full digits. */ + memcpy (result_p, left_p, left_size); + return result_value_p; + } + + ecma_bigint_digit_t *left_end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, left_size); + ecma_bigint_digit_t carry = 0; + + do + { + ecma_bigint_digit_t value = *left_p++; + + *result_p++ = (value << shift_left) | carry; + carry = value >> shift_right; + } while (left_p < left_end_p); + + if (carry > 0) + { + *result_p = carry; + } + + return result_value_p; +} /* ecma_big_uint_shift_left */ + +/** + * Shift right BigUInt values by an uint32 value + * + * @return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_shift_right (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + uint32_t right_value, /**< shift value */ + bool increase_result) /**< increase result */ +{ + JERRY_ASSERT (right_value > 0); + + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + + uint32_t crop_size = (right_value >> ECMA_BIGINT_DIGIT_SHIFT) * (uint32_t) sizeof (ecma_bigint_digit_t); + + uint32_t shift_right = right_value & ((1 << ECMA_BIGINT_DIGIT_SHIFT) - 1); + uint32_t shift_left = (1 << ECMA_BIGINT_DIGIT_SHIFT) - shift_right; + ecma_bigint_digit_t carry = 0; + + if (shift_right > 0 && (ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) >> shift_right) == 0) + { + carry = ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) << shift_left; + left_size -= (uint32_t) sizeof (ecma_bigint_digit_t); + } + + if (left_size <= crop_size) + { + if (JERRY_LIKELY (!increase_result)) + { + return ECMA_BIGINT_POINTER_TO_ZERO; + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t)); + if (result_value_p != NULL) + { + *ECMA_BIGINT_GET_DIGITS (result_value_p, 0) = 1; + } + return result_value_p; + } + + if (JERRY_UNLIKELY (increase_result) + && (shift_right == 0 || (*ECMA_BIGINT_GET_DIGITS (left_value_p, crop_size) << shift_left) == 0)) + { + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *left_end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, crop_size); + + while (left_p < left_end_p) + { + if (*left_p != 0) + { + break; + } + left_p++; + } + + if (left_p == left_end_p) + { + increase_result = false; + } + } + + uint32_t size = left_size - crop_size; + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + if (shift_right == 0) + { + memcpy (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), ECMA_BIGINT_GET_DIGITS (left_value_p, crop_size), size); + + if (JERRY_LIKELY (!increase_result)) + { + return result_value_p; + } + return ecma_big_uint_increase_result (result_value_p); + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, left_size); + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, size); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + + do + { + ecma_bigint_digit_t value = *(--left_p); + + *(--result_p) = (value >> shift_right) | carry; + carry = value << shift_left; + } while (result_p > end_p); + + if (JERRY_LIKELY (!increase_result)) + { + return result_value_p; + } + return ecma_big_uint_increase_result (result_value_p); +} /* ecma_big_uint_shift_right */ + +/** + * Compute the left value raised to the power of right value + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_pow (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + uint32_t right_value) /**< power value */ +{ + ecma_extended_primitive_t *result_p = ECMA_BIGINT_NUMBER_IS_ODD (right_value) ? left_value_p : NULL; + ecma_extended_primitive_t *square_p = left_value_p; + + JERRY_ASSERT (right_value >= 2); + + while (true) + { + ecma_extended_primitive_t *new_square_p = ecma_big_uint_mul (square_p, square_p); + + if (JERRY_UNLIKELY (new_square_p == NULL)) + { + if (result_p != NULL && result_p != left_value_p) + { + ecma_deref_bigint (result_p); + } + result_p = NULL; + break; + } + + if (square_p != left_value_p) + { + ecma_deref_bigint (square_p); + } + + square_p = new_square_p; + right_value >>= 1; + + if (ECMA_BIGINT_NUMBER_IS_ODD (right_value)) + { + if (result_p != NULL) + { + ecma_extended_primitive_t *new_result_p = ecma_big_uint_mul (square_p, result_p); + + if (result_p != left_value_p) + { + ecma_deref_bigint (result_p); + } + + result_p = new_result_p; + } + else + { + ecma_ref_extended_primitive (square_p); + result_p = square_p; + } + + if (JERRY_UNLIKELY (result_p == NULL) || right_value == 1) + { + break; + } + } + } + + if (square_p != left_value_p) + { + ecma_deref_bigint (square_p); + } + + return result_p; +} /* ecma_big_uint_pow */ + +/** + * Perform bitwise operations on two BigUInt numbers + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_bitwise_op (uint32_t operation_and_options, /**< bitwise operation type and options */ + ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0); + + uint32_t operation_type = ECMA_BIGINT_BITWISE_GET_OPERATION_TYPE (operation_and_options); + + switch (operation_type) + { + case ECMA_BIG_UINT_BITWISE_AND: + { + if (left_size > right_size) + { + left_size = right_size; + break; + } + /* FALLTHRU */ + } + case ECMA_BIG_UINT_BITWISE_AND_NOT: + { + if (right_size > left_size) + { + right_size = left_size; + } + break; + } + default: + { + JERRY_ASSERT (operation_type == ECMA_BIG_UINT_BITWISE_OR || operation_type == ECMA_BIG_UINT_BITWISE_XOR); + + if (right_size <= left_size) + { + break; + } + + /* Swap values. */ + ecma_extended_primitive_t *tmp_value_p = left_value_p; + left_value_p = right_value_p; + right_value_p = tmp_value_p; + + uint32_t tmp_size = left_size; + left_size = right_size; + right_size = tmp_size; + + uint32_t decrease_opts = (operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_BOTH); + + /* When exactly one bit is set, invert both bits. */ + if (decrease_opts >= ECMA_BIG_UINT_BITWISE_DECREASE_LEFT && decrease_opts <= ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT) + { + operation_and_options ^= ECMA_BIG_UINT_BITWISE_DECREASE_BOTH; + } + break; + } + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (left_size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, 0); + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + ecma_bigint_digit_t *result_end_p = ECMA_BIGINT_GET_DIGITS (result_value_p, right_size); + + if (!(operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_BOTH)) + { + JERRY_ASSERT (!(operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT)); + + if (operation_type == ECMA_BIG_UINT_BITWISE_AND) + { + do + { + *result_p++ = *left_p++ & *right_p++; + } while (result_p < result_end_p); + + if (result_p[-1] == 0) + { + return ecma_big_uint_normalize_result (result_value_p, result_p); + } + return result_value_p; + } + + if (operation_type == ECMA_BIG_UINT_BITWISE_OR) + { + do + { + *result_p++ = *left_p++ | *right_p++; + } while (result_p < result_end_p); + + if (left_size > right_size) + { + memcpy (result_p, left_p, left_size - right_size); + } + return result_value_p; + } + + JERRY_ASSERT (operation_type == ECMA_BIG_UINT_BITWISE_XOR); + + do + { + *result_p++ = *left_p++ ^ *right_p++; + } while (result_p < result_end_p); + + if (left_size > right_size) + { + memcpy (result_p, left_p, left_size - right_size); + return result_value_p; + } + + if (result_p[-1] == 0) + { + return ecma_big_uint_normalize_result (result_value_p, result_p); + } + return result_value_p; + } + + uint32_t left_carry = 0, right_carry = 0; + + if (operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_LEFT) + { + left_carry = 1; + } + + if (operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT) + { + right_carry = 1; + } + + do + { + ecma_bigint_digit_t left = (*left_p++) - left_carry; + + if (left != ~((ecma_bigint_digit_t) 0)) + { + left_carry = 0; + } + + ecma_bigint_digit_t right = (*right_p++) - right_carry; + + if (right != ~((ecma_bigint_digit_t) 0)) + { + right_carry = 0; + } + + switch (operation_type) + { + case ECMA_BIG_UINT_BITWISE_AND: + { + *result_p++ = left & right; + break; + } + case ECMA_BIG_UINT_BITWISE_OR: + { + *result_p++ = left | right; + break; + } + case ECMA_BIG_UINT_BITWISE_XOR: + { + *result_p++ = left ^ right; + break; + } + default: + { + JERRY_ASSERT (operation_type == ECMA_BIG_UINT_BITWISE_AND_NOT); + *result_p++ = left & ~right; + break; + } + } + } while (result_p < result_end_p); + + if (operation_type != ECMA_BIG_UINT_BITWISE_AND) + { + result_end_p = ECMA_BIGINT_GET_DIGITS (result_value_p, left_size); + + if (left_carry > 0) + { + while (*left_p == 0) + { + *result_p++ = ~((ecma_bigint_digit_t) 0); + left_p++; + + JERRY_ASSERT (result_p < result_end_p); + } + + *result_p++ = *left_p++ - 1; + } + + if (result_p < result_end_p) + { + memcpy (result_p, left_p, (size_t) ((uint8_t *) result_end_p - (uint8_t *) result_p)); + + if (operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT) + { + return ecma_big_uint_increase_result (result_value_p); + } + return result_value_p; + } + } + + if (operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT) + { + return ecma_big_uint_increase_result (result_value_p); + } + + if (result_p[-1] == 0) + { + return ecma_big_uint_normalize_result (result_value_p, result_p); + } + return result_value_p; +} /* ecma_big_uint_bitwise_op */ + +#endif /* JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.h new file mode 100644 index 00000000..727d780f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.h @@ -0,0 +1,135 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BIG_UINT_H +#define ECMA_BIG_UINT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_BIGINT + +/** + * Limit of BigUInt memory allocation in JerryScript. + */ +#define ECMA_BIGINT_MAX_SIZE 0x10000 + +/** + * Unsigned type which can hold two digits. + */ +typedef uint64_t ecma_bigint_two_digits_t; + +/** + * Shift used by left/right shifting of a value. + */ +#define ECMA_BIGINT_DIGIT_SHIFT 5 + +/** + * Return with the digits of a BigInt value. + */ +#define ECMA_BIGINT_GET_DIGITS(value_p, offset) \ + ((ecma_bigint_digit_t *) (((uint8_t *) (value_p)) + sizeof (ecma_extended_primitive_t) + (offset))) + +/** + * Return with the digits of a BigInt value. + */ +#define ECMA_BIGINT_GET_LAST_DIGIT(value_p, size) *ECMA_BIGINT_GET_DIGITS (value_p, size - sizeof (ecma_bigint_digit_t)) + +/** + * Returns true if size is an odd number. + */ +#define ECMA_BIGINT_SIZE_IS_ODD(size) (((size) & sizeof (ecma_bigint_digit_t)) != 0) + +/** + * Returns a two digit value where the high digit is set to the passed digit. + */ +#define ECMA_BIGINT_HIGH_DIGIT(digit) (((ecma_bigint_two_digits_t) digit) << (8 * sizeof (ecma_bigint_digit_t))) + +/** + * Tells whether a number (usually a digit or uint32_t value) is an odd number. + */ +#define ECMA_BIGINT_NUMBER_IS_ODD(number) ((number & 0x1) != 0) + +/** + * Bitwise operation types. + */ +typedef enum +{ + ECMA_BIG_UINT_BITWISE_AND, /**< bitwise 'and' operation */ + ECMA_BIG_UINT_BITWISE_OR, /**< bitwise 'or' operation */ + ECMA_BIG_UINT_BITWISE_XOR, /**< bitwise 'xor' operation */ + ECMA_BIG_UINT_BITWISE_AND_NOT, /**< bitwise 'and not' operation */ +} ecma_big_uint_bitwise_operation_types_t; + +/** + * Returns with the type of the operation. + */ +#define ECMA_BIGINT_BITWISE_GET_OPERATION_TYPE(operation_and_options) ((operation_and_options) &0xf) + +/** + * Options for bitwise operations. + */ +typedef enum +{ + ECMA_BIG_UINT_BITWISE_DECREASE_LEFT = (1 << 4), /**< subtract 1 from left value */ + ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT = (1 << 5), /**< subtract 1 from right value */ + ECMA_BIG_UINT_BITWISE_INCREASE_RESULT = (1 << 6), /**< add 1 to the result */ +} ecma_big_uint_bitwise_options_t; + +/** + * Subtract 1 from both left and right values. + */ +#define ECMA_BIG_UINT_BITWISE_DECREASE_BOTH (ECMA_BIG_UINT_BITWISE_DECREASE_LEFT | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT) + +ecma_extended_primitive_t *ecma_bigint_create (uint32_t size); +ecma_extended_primitive_t *ecma_big_uint_extend (ecma_extended_primitive_t *value_p, ecma_bigint_digit_t digit); + +ecma_bigint_digit_t ecma_big_uint_count_leading_zero (ecma_bigint_digit_t digit); + +int ecma_big_uint_compare (ecma_extended_primitive_t *left_value_p, ecma_extended_primitive_t *right_value_p); + +ecma_extended_primitive_t * +ecma_big_uint_mul_digit (ecma_extended_primitive_t *value_p, ecma_bigint_digit_t mul, ecma_bigint_digit_t add); + +uint8_t *ecma_big_uint_to_string (ecma_extended_primitive_t *value_p, + uint32_t radix, + uint32_t *char_start_p, + uint32_t *char_size_p); + +ecma_extended_primitive_t *ecma_big_uint_increase (ecma_extended_primitive_t *value_p); +ecma_extended_primitive_t *ecma_big_uint_decrease (ecma_extended_primitive_t *value_p); + +ecma_extended_primitive_t *ecma_big_uint_add (ecma_extended_primitive_t *left_value_p, + ecma_extended_primitive_t *right_value_p); +ecma_extended_primitive_t *ecma_big_uint_sub (ecma_extended_primitive_t *left_value_p, + ecma_extended_primitive_t *right_value_p); +ecma_extended_primitive_t *ecma_big_uint_mul (ecma_extended_primitive_t *left_value_p, + ecma_extended_primitive_t *right_value_p); +ecma_extended_primitive_t *ecma_big_uint_div_mod (ecma_extended_primitive_t *dividend_value_p, + ecma_extended_primitive_t *divisor_value_p, + bool is_mod); + +ecma_extended_primitive_t *ecma_big_uint_shift_left (ecma_extended_primitive_t *left_value_p, uint32_t right_value); +ecma_extended_primitive_t * +ecma_big_uint_shift_right (ecma_extended_primitive_t *left_value_p, uint32_t right_value, bool increase_result); + +ecma_extended_primitive_t *ecma_big_uint_pow (ecma_extended_primitive_t *left_value_p, uint32_t right_value); + +ecma_extended_primitive_t *ecma_big_uint_bitwise_op (uint32_t operation_and_options, + ecma_extended_primitive_t *left_value_p, + ecma_extended_primitive_t *right_value_p); + +#endif /* JERRY_BUILTIN_BIGINT */ + +#endif /* ECMA_BIG_UINT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.cpp new file mode 100644 index 00000000..6d03cd51 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.cpp @@ -0,0 +1,66 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-bigint-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#if JERRY_BUILTIN_BIGINT + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabigintobject ECMA BigInt object related routines + * @{ + */ + +/** + * BigInt object creation operation. + * + * See also: ECMA-262 v11, 7.1.18 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_bigint_object (ecma_value_t arg) /**< argument passed to the toObject operation */ +{ + JERRY_ASSERT (ecma_is_value_bigint (arg)); + + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_BIGINT_PROTOTYPE); + + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_BIGINT; + ext_object_p->u.cls.u3.value = ecma_copy_value (arg); + + return ecma_make_object_value (object_p); +} /* ecma_op_create_bigint_object */ + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.h new file mode 100644 index 00000000..72adefec --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.h @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BIGINT_OBJECT_H +#define ECMA_BIGINT_OBJECT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_BIGINT + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabigintobject ECMA BigInt object related routines + * @{ + */ + +ecma_value_t ecma_op_create_bigint_object (ecma_value_t arg); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ + +#endif /* !ECMA_BIGINT_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.cpp new file mode 100644 index 00000000..7a4464e0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.cpp @@ -0,0 +1,1703 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-bigint.h" + +#include "ecma-big-uint.h" +#include "ecma-exceptions.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_BIGINT + +/** + * Raise a not enough memory error + * + * @return ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_bigint_raise_memory_error (void) +{ + return ecma_raise_range_error (ECMA_ERR_ALLOCATE_BIGINT_VALUE); +} /* ecma_bigint_raise_memory_error */ + +/** + * Create a single digit long BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_bigint_create_from_digit (ecma_bigint_digit_t digit, /* single digit */ + bool sign) /* set ECMA_BIGINT_SIGN if true */ +{ + JERRY_ASSERT (digit != 0); + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t)); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if (sign) + { + result_value_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + + *ECMA_BIGINT_GET_DIGITS (result_value_p, 0) = digit; + return ecma_make_extended_primitive_value (result_value_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_create_from_digit */ + +/** + * Parse a string and create a BigInt value + * + * @return ecma BigInt value or a special value allowed by the option flags + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, /**< string represenation of the BigInt */ + lit_utf8_size_t size, /**< string size */ + uint32_t options) /**< ecma_bigint_parse_string_options_t option bits */ +{ + ecma_bigint_digit_t radix = 10; + uint32_t sign = (options & ECMA_BIGINT_PARSE_SET_NEGATIVE) ? ECMA_BIGINT_SIGN : 0; + bool allow_underscore = options & ECMA_BIGINT_PARSE_ALLOW_UNDERSCORE; + + const lit_utf8_byte_t *string_end_p = string_p + size; + string_p = ecma_string_trim_front (string_p, string_p + size); + size = (lit_utf8_size_t) (string_end_p - string_p); + + if (size >= 3 && string_p[0] == LIT_CHAR_0) + { + radix = lit_char_to_radix (string_p[1]); + + if (radix != 10) + { + string_p += 2; + size -= 2; + } + } + else if (size >= 2) + { + if (string_p[0] == LIT_CHAR_PLUS) + { + size--; + string_p++; + } + else if (string_p[0] == LIT_CHAR_MINUS) + { + sign = ECMA_BIGINT_SIGN; + size--; + string_p++; + } + } + else if (size == 0) + { + return ECMA_BIGINT_ZERO; + } + + while (string_p < string_end_p && (*string_p == LIT_CHAR_0 || (*string_p == LIT_CHAR_UNDERSCORE && allow_underscore))) + { + string_p++; + } + + ecma_extended_primitive_t *result_p = NULL; + + if (string_p == string_end_p) + { + return ECMA_BIGINT_ZERO; + } + + do + { + ecma_bigint_digit_t digit = radix; + + if (*string_p >= LIT_CHAR_0 && *string_p <= LIT_CHAR_9) + { + digit = (ecma_bigint_digit_t) (*string_p - LIT_CHAR_0); + } + else if (*string_p == LIT_CHAR_UNDERSCORE && allow_underscore) + { + continue; + } + else + { + lit_utf8_byte_t character = (lit_utf8_byte_t) LEXER_TO_ASCII_LOWERCASE (*string_p); + + if (character >= LIT_CHAR_LOWERCASE_A && character <= LIT_CHAR_LOWERCASE_F) + { + digit = (ecma_bigint_digit_t) (character - (LIT_CHAR_LOWERCASE_A - 10)); + } + else if (ecma_string_trim_front (string_p, string_end_p) == string_end_p) + { + string_p = string_end_p; + break; + } + } + if (digit >= radix) + { + if (result_p != NULL) + { + ecma_deref_bigint (result_p); + } + + if (options & ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR) + { + return ECMA_VALUE_FALSE; + } + return ecma_raise_syntax_error (ECMA_ERR_STRING_CANNOT_BE_CONVERTED_TO_BIGINT_VALUE); + } + + result_p = ecma_big_uint_mul_digit (result_p, radix, digit); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + break; + } + } while (++string_p < string_end_p); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + if (options & ECMA_BIGINT_PARSE_DISALLOW_MEMORY_ERROR) + { + return ECMA_VALUE_NULL; + } + return ecma_bigint_raise_memory_error (); + } + + result_p->u.bigint_sign_and_size |= sign; + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_parse_string */ + +/** + * Parse a string value and create a BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_parse_string_value (ecma_value_t string, /**< ecma string */ + uint32_t options) /**< ecma_bigint_parse_string_options_t option bits */ +{ + JERRY_ASSERT (ecma_is_value_string (string)); + + ECMA_STRING_TO_UTF8_STRING (ecma_get_string_from_value (string), string_buffer_p, string_buffer_size); + + ecma_value_t result = ecma_bigint_parse_string (string_buffer_p, string_buffer_size, options); + ECMA_FINALIZE_UTF8_STRING (string_buffer_p, string_buffer_size); + + return result; +} /* ecma_bigint_parse_string_value */ + +/** + * Create a string representation for a BigInt value + * + * @return ecma string or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_string_t * +ecma_bigint_to_string (ecma_value_t value, /**< BigInt value */ + ecma_bigint_digit_t radix) /**< conversion radix */ +{ + JERRY_ASSERT (ecma_is_value_bigint (value)); + + if (value == ECMA_BIGINT_ZERO) + { + return ecma_new_ecma_string_from_code_unit (LIT_CHAR_0); + } + + uint32_t char_start_p, char_size_p; + ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (value); + lit_utf8_byte_t *string_buffer_p = ecma_big_uint_to_string (bigint_p, radix, &char_start_p, &char_size_p); + + if (JERRY_UNLIKELY (string_buffer_p == NULL)) + { + ecma_raise_range_error (ECMA_ERR_ALLOCATE_BIGINT_STRING); + return NULL; + } + + JERRY_ASSERT (char_start_p > 0); + + if (bigint_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + string_buffer_p[--char_start_p] = LIT_CHAR_MINUS; + } + + ecma_string_t *string_p; + string_p = ecma_new_ecma_string_from_ascii (string_buffer_p + char_start_p, char_size_p - char_start_p); + + jmem_heap_free_block (string_buffer_p, char_size_p); + return string_p; +} /* ecma_bigint_to_string */ + +/** + * Get the size of zero digits from the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE(value) (((value) &0xffff) * (uint32_t) sizeof (ecma_bigint_digit_t)) + +/** + * Get the number of digits from the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS(value) ((value) >> 20) + +/** + * Get the size of digits from the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE(value) \ + (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (value) * (uint32_t) sizeof (ecma_bigint_digit_t)) + +/** + * Set number of digits in the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS(value) ((uint32_t) (value) << 20) + +/** + * This flag is set when the number passed to ecma_bigint_number_to_digits has fraction part + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION 0x10000 + +/** + * Convert a number to maximum of 3 digits and left shift + * + * @return packed value, ECMA_BIGINT_NUMBER_TO_DIGITS* macros can be used to decode it + */ +static uint32_t +ecma_bigint_number_to_digits (ecma_number_t number, /**< ecma number */ + ecma_bigint_digit_t *digits_p) /**< [out] BigInt digits */ +{ + if (ecma_number_is_zero (number)) + { + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (0); + } + + ecma_binary_num_t binary = ecma_number_to_binary (number); + uint32_t biased_exp = ecma_number_biased_exp (binary); + uint64_t fraction = ecma_number_fraction (binary); + + if (biased_exp < ((1 << (ECMA_NUMBER_BIASED_EXP_WIDTH - 1)) - 1)) + { + /* Number is less than 1. */ + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (0) | ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION; + } + + biased_exp -= ((1 << (ECMA_NUMBER_BIASED_EXP_WIDTH - 1)) - 1); + fraction |= ((uint64_t) 1) << ECMA_NUMBER_FRACTION_WIDTH; + + if (biased_exp <= ECMA_NUMBER_FRACTION_WIDTH) + { + uint32_t has_fraction = 0; + + if (biased_exp < ECMA_NUMBER_FRACTION_WIDTH + && (fraction << (biased_exp + ((8 * sizeof (uint64_t)) - ECMA_NUMBER_FRACTION_WIDTH))) != 0) + { + has_fraction |= ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION; + } + + fraction >>= ECMA_NUMBER_FRACTION_WIDTH - biased_exp; + digits_p[0] = (ecma_bigint_digit_t) fraction; + +#if JERRY_NUMBER_TYPE_FLOAT64 + digits_p[1] = (ecma_bigint_digit_t) (fraction >> (8 * sizeof (ecma_bigint_digit_t))); + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (digits_p[1] == 0 ? 1 : 2) | has_fraction; +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (1) | has_fraction; +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + } + + digits_p[0] = (ecma_bigint_digit_t) fraction; +#if JERRY_NUMBER_TYPE_FLOAT64 + digits_p[1] = (ecma_bigint_digit_t) (fraction >> (8 * sizeof (ecma_bigint_digit_t))); +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + + biased_exp -= ECMA_NUMBER_FRACTION_WIDTH; + + uint32_t shift_left = biased_exp & ((8 * sizeof (ecma_bigint_digit_t)) - 1); + biased_exp = biased_exp >> ECMA_BIGINT_DIGIT_SHIFT; + + if (shift_left == 0) + { +#if JERRY_NUMBER_TYPE_FLOAT64 + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (2); +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (1); +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + } + + uint32_t shift_right = (1 << ECMA_BIGINT_DIGIT_SHIFT) - shift_left; + +#if JERRY_NUMBER_TYPE_FLOAT64 + digits_p[2] = digits_p[1] >> shift_right; + digits_p[1] = (digits_p[1] << shift_left) | (digits_p[0] >> shift_right); + digits_p[0] <<= shift_left; + + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (digits_p[2] == 0 ? 2 : 3); +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ + digits_p[1] = digits_p[0] >> shift_right; + digits_p[0] <<= shift_left; + + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (digits_p[1] == 0 ? 1 : 2); +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +} /* ecma_bigint_number_to_digits */ + +/** + * Convert an ecma number to BigInt value + * + * See also: + * ECMA-262 v11, 20.2.1.1.1 + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_bigint_number_to_bigint (ecma_number_t number) /**< ecma number */ +{ + if (ecma_number_is_nan (number) || ecma_number_is_infinity (number)) + { + return ecma_raise_range_error (ECMA_ERR_INFINITY_OR_NAN_CANNOT_BE_CONVERTED_TO_BIGINT); + } + + ecma_bigint_digit_t digits[3]; + uint32_t result = ecma_bigint_number_to_digits (number, digits); + + JERRY_ASSERT (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) == 0 + || digits[ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) - 1] > 0); + + if (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION) + { + return ecma_raise_range_error (ECMA_ERR_ONLY_INTEGER_NUMBERS_CAN_BE_CONVERTED_TO_BIGINT); + } + + uint32_t digits_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE (result); + + if (digits_size == 0) + { + return ECMA_BIGINT_ZERO; + } + + uint32_t zero_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE (result); + + ecma_extended_primitive_t *result_p = ecma_bigint_create (digits_size + zero_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + uint8_t *data_p = (uint8_t *) ECMA_BIGINT_GET_DIGITS (result_p, 0); + memset (data_p, 0, zero_size); + memcpy (data_p + zero_size, digits, digits_size); + + if (number < 0) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_number_to_bigint */ + +/** + * Convert a value to BigInt value + * + * See also: + * ECMA-262 v11, 7.1.13 + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_to_bigint (ecma_value_t value, /**< any value */ + bool allow_numbers) /**< converting ecma numbers is allowed */ +{ + bool free_value = false; + + if (ecma_is_value_object (value)) + { + value = ecma_op_object_default_value (ecma_get_object_from_value (value), ECMA_PREFERRED_TYPE_NUMBER); + free_value = true; + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + } + + ecma_value_t result; + + if (ecma_is_value_string (value)) + { + result = ecma_bigint_parse_string_value (value, ECMA_BIGINT_PARSE_NO_OPTIONS); + } + else if (ecma_is_value_bigint (value)) + { + result = value; + + if (!free_value && value != ECMA_BIGINT_ZERO) + { + ecma_ref_extended_primitive (ecma_get_extended_primitive_from_value (value)); + } + else + { + free_value = false; + } + } + else if (allow_numbers && ecma_is_value_number (value)) + { + result = ecma_bigint_number_to_bigint (ecma_get_number_from_value (value)); + } + else if (ecma_is_value_false (value)) + { + result = ECMA_BIGINT_ZERO; + } + else if (ecma_is_value_true (value)) + { + result = ecma_bigint_create_from_digit (1, false); + } + else + { + result = ecma_raise_type_error (ECMA_ERR_VALUE_CANNOT_BE_CONVERTED_TO_BIGINT); + } + + if (free_value) + { + ecma_free_value (value); + } + + return result; +} /* ecma_bigint_to_bigint */ + +/** + * Convert a BigInt value to number value + * + * @return ecma number value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_to_number (ecma_value_t value) /**< BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (value)); + + if (value == ECMA_BIGINT_ZERO) + { + return ecma_make_integer_value (0); + } + + ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value); + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + ecma_bigint_digit_t *digits_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + + if (size == sizeof (ecma_bigint_digit_t)) + { + if (!(value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + if (digits_p[-1] <= ECMA_INTEGER_NUMBER_MAX) + { + return ecma_make_integer_value ((ecma_integer_value_t) digits_p[-1]); + } + } + else if (digits_p[-1] <= -ECMA_INTEGER_NUMBER_MIN) + { + return ecma_make_integer_value (-(ecma_integer_value_t) digits_p[-1]); + } + } + + uint64_t fraction = 0; + ecma_bigint_digit_t shift_left; + + if (digits_p[-1] == 1) + { + JERRY_ASSERT (size > sizeof (ecma_bigint_digit_t)); + + fraction = ((uint64_t) digits_p[-2]) << (8 * sizeof (ecma_bigint_digit_t)); + shift_left = (uint32_t) (8 * sizeof (ecma_bigint_digit_t)); + + if (size >= 3 * sizeof (ecma_bigint_digit_t)) + { + fraction |= (uint64_t) digits_p[-3]; + } + } + else + { + shift_left = ecma_big_uint_count_leading_zero (digits_p[-1]) + 1; + + fraction = ((uint64_t) digits_p[-1]) << (8 * sizeof (ecma_bigint_digit_t) + shift_left); + + if (size >= 2 * sizeof (ecma_bigint_digit_t)) + { + fraction |= ((uint64_t) digits_p[-2]) << shift_left; + } + + if (size >= 3 * sizeof (ecma_bigint_digit_t)) + { + fraction |= ((uint64_t) digits_p[-3]) >> (8 * sizeof (ecma_bigint_digit_t) - shift_left); + } + } + + uint32_t biased_exp = (uint32_t) (((1 << (ECMA_NUMBER_BIASED_EXP_WIDTH - 1)) - 1) + (size * 8 - shift_left)); + + /* Rounding result. */ + const uint64_t rounding_bit = (((uint64_t) 1) << (8 * sizeof (uint64_t) - ECMA_NUMBER_FRACTION_WIDTH - 1)); + bool round_up = false; + + if (fraction & rounding_bit) + { + round_up = true; + + /* IEEE_754 roundTiesToEven mode: when rounding_bit is set, and all the remaining bits + * are zero, the number needs to be rounded down the bit before rounding_bit is zero. */ + if ((fraction & ((rounding_bit << 2) - 1)) == rounding_bit) + { + round_up = false; + + if ((size >= (3 * sizeof (ecma_bigint_digit_t))) + && (shift_left == (8 * sizeof (ecma_bigint_digit_t)) + || (digits_p[-3] & ((((ecma_bigint_digit_t) 1) << shift_left) - 1)) == 0)) + { + ecma_bigint_digit_t *digits_start_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + + digits_p -= 3; + + while (digits_p > digits_start_p) + { + if (digits_p[-1] != 0) + { + round_up = true; + break; + } + digits_p--; + } + } + } + } + + if (round_up) + { + fraction += rounding_bit; + fraction >>= (8 * sizeof (uint64_t) - ECMA_NUMBER_FRACTION_WIDTH); + + if (fraction == 0) + { + biased_exp++; + } + } + else + { + fraction >>= (8 * sizeof (uint64_t) - ECMA_NUMBER_FRACTION_WIDTH); + } + + bool sign = (value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN); + ecma_number_t result; + + if (biased_exp < (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1) + { + result = ecma_number_create (sign, biased_exp, fraction); + } + else + { + result = ecma_number_make_infinity (sign); + } + + return ecma_make_number_value (result); +} /* ecma_bigint_to_number */ + +/** + * Returns with a BigInt if the value is BigInt, + * or the value is object, and its default value is BigInt + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_get_bigint (ecma_value_t value, /**< any value */ + bool *free_result_p) /**< [out] result should be freed */ +{ + *free_result_p = false; + + if (ecma_is_value_bigint (value)) + { + return value; + } + + if (ecma_is_value_object (value)) + { + ecma_object_t *object_p = ecma_get_object_from_value (value); + ecma_value_t default_value = ecma_op_object_default_value (object_p, ECMA_PREFERRED_TYPE_NUMBER); + + if (ECMA_IS_VALUE_ERROR (default_value)) + { + return default_value; + } + + if (ecma_is_value_bigint (default_value)) + { + *free_result_p = (default_value != ECMA_BIGINT_ZERO); + return default_value; + } + + ecma_free_value (default_value); + } + + return ecma_raise_type_error (ECMA_ERR_CONVERT_BIGINT_TO_NUMBER); +} /* ecma_bigint_get_bigint */ + +/** + * Create BigInt value from uint64 digits + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_create_from_digits (const uint64_t *digits_p, /**< BigInt digits */ + uint32_t size, /**< number of BigInt digits */ + bool sign) /**< sign bit, true if the result should be negative */ +{ + const uint64_t *digits_end_p = digits_p + size; + + while (digits_end_p > digits_p && digits_end_p[-1] == 0) + { + digits_end_p--; + } + + if (digits_p == digits_end_p) + { + return ECMA_BIGINT_ZERO; + } + + size = (uint32_t) (digits_end_p - digits_p); + + if (size < ECMA_BIGINT_MAX_SIZE) + { + size *= (uint32_t) sizeof (uint64_t); + } + + if ((digits_end_p[-1] >> (8 * sizeof (ecma_bigint_digit_t))) == 0) + { + size -= (uint32_t) sizeof (ecma_bigint_digit_t); + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if (sign) + { + result_value_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + + while (digits_p < digits_end_p) + { + uint64_t digit = *digits_p++; + + result_p[0] = (ecma_bigint_digit_t) digit; + result_p[1] = (ecma_bigint_digit_t) (digit >> (8 * sizeof (ecma_bigint_digit_t))); + result_p += 2; + } + + return ecma_make_extended_primitive_value (result_value_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_create_from_digits */ + +/** + * Get the number of uint64 digits of a BigInt value + * + * @return number of uint64 digits + */ +uint32_t +ecma_bigint_get_size_in_digits (ecma_value_t value) /**< BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (value)); + + if (value == ECMA_BIGINT_ZERO) + { + return 0; + } + + ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value); + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + return (size + (uint32_t) sizeof (ecma_bigint_digit_t)) / sizeof (uint64_t); +} /* ecma_bigint_get_size_in_digits */ + +/** + * Get the uint64 digits of a BigInt value + */ +void +ecma_bigint_get_digits_and_sign (ecma_value_t value, /**< BigInt value */ + uint64_t *digits_p, /**< [out] buffer for digits */ + uint32_t size, /**< buffer size in digits */ + bool *sign_p) /**< [out] sign of BigInt */ +{ + JERRY_ASSERT (ecma_is_value_bigint (value)); + + if (value == ECMA_BIGINT_ZERO) + { + if (sign_p != NULL) + { + *sign_p = false; + } + memset (digits_p, 0, size * sizeof (uint64_t)); + return; + } + + ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value); + + if (sign_p != NULL) + { + *sign_p = (value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) != 0; + } + + uint32_t bigint_size = ECMA_BIGINT_GET_SIZE (value_p); + uint32_t copy_size = bigint_size / sizeof (uint64_t); + + if (copy_size > size) + { + copy_size = size; + } + + const uint64_t *digits_end_p = digits_p + copy_size; + ecma_bigint_digit_t *source_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + + while (digits_p < digits_end_p) + { + *digits_p++ = source_p[0] | (((uint64_t) source_p[1]) << (8 * sizeof (ecma_bigint_digit_t))); + source_p += 2; + } + + size -= copy_size; + + if (size == 0) + { + return; + } + + if (ECMA_BIGINT_SIZE_IS_ODD (bigint_size)) + { + *digits_p++ = source_p[0]; + size--; + } + + if (size > 0) + { + memset (digits_p, 0, size * sizeof (uint64_t)); + } +} /* ecma_bigint_get_digits_and_sign */ + +/** + * Compare two BigInt values + * + * @return true if they are the same, false otherwise + */ +bool +ecma_bigint_is_equal_to_bigint (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (left_value == ECMA_BIGINT_ZERO) + { + return right_value == ECMA_BIGINT_ZERO; + } + else if (right_value == ECMA_BIGINT_ZERO) + { + return false; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (left_p->u.bigint_sign_and_size != right_p->u.bigint_sign_and_size) + { + return false; + } + + uint32_t size = ECMA_BIGINT_GET_SIZE (left_p); + return memcmp (ECMA_BIGINT_GET_DIGITS (left_p, 0), ECMA_BIGINT_GET_DIGITS (right_p, 0), size) == 0; +} /* ecma_bigint_is_equal_to_bigint */ + +/** + * Compare a BigInt value and a number + * + * @return true if they are the same, false otherwise + */ +bool +ecma_bigint_is_equal_to_number (ecma_value_t left_value, /**< left BigInt value */ + ecma_number_t right_value) /**< right number value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value)); + + if (ecma_number_is_nan (right_value) || ecma_number_is_infinity (right_value)) + { + return false; + } + + if (left_value == ECMA_BIGINT_ZERO) + { + return right_value == 0; + } + + ecma_extended_primitive_t *left_value_p = ecma_get_extended_primitive_from_value (left_value); + + /* Sign must be the same. */ + if (left_value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + if (right_value > 0) + { + return false; + } + } + else if (right_value < 0) + { + return false; + } + + ecma_bigint_digit_t digits[3]; + uint32_t result = ecma_bigint_number_to_digits (right_value, digits); + + JERRY_ASSERT (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) == 0 + || digits[ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) - 1] > 0); + + if (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION) + { + return false; + } + + uint32_t digits_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE (result); + uint32_t zero_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE (result); + + if (ECMA_BIGINT_GET_SIZE (left_value_p) != digits_size + zero_size) + { + return false; + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *left_end_p = (ecma_bigint_digit_t *) (((uint8_t *) left_p) + zero_size); + + /* Check value bits first. */ + if (memcmp (left_end_p, digits, digits_size) != 0) + { + return false; + } + + while (left_p < left_end_p) + { + if (*left_p++ != 0) + { + return false; + } + } + + return true; +} /* ecma_bigint_is_equal_to_number */ + +/** + * Convert 0 to 1, and 1 to -1. Useful for getting sign. + */ +#define ECMA_BIGINT_TO_SIGN(value) (1 - (((int) (value)) << 1)) + +/** + * Convert 0 to -1, and 1 to 1. Useful for getting negated sign. + */ +#define ECMA_BIGINT_TO_NEGATED_SIGN(value) (-1 + (((int) (value)) << 1)) + +/** + * Compare two BigInt values + * + * return -1, if left value < right value, 0 if they are equal, 1 otherwise + */ +int +ecma_bigint_compare_to_bigint (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (left_value == ECMA_BIGINT_ZERO) + { + if (right_value == ECMA_BIGINT_ZERO) + { + return 0; + } + + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + return ECMA_BIGINT_TO_NEGATED_SIGN (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN); + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + uint32_t left_sign = left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + + if (right_value == ECMA_BIGINT_ZERO) + { + return ECMA_BIGINT_TO_SIGN (left_sign); + } + + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + uint32_t right_sign = right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + + if ((left_sign ^ right_sign) != 0) + { + return ECMA_BIGINT_TO_SIGN (left_sign); + } + + if (left_sign == 0) + { + return ecma_big_uint_compare (left_p, right_p); + } + + return -ecma_big_uint_compare (left_p, right_p); +} /* ecma_bigint_compare_to_bigint */ + +/** + * Compare a BigInt value and a number + * + * return -1, if left value < right value, 0 if they are equal, 1 otherwise + */ +int +ecma_bigint_compare_to_number (ecma_value_t left_value, /**< left BigInt value */ + ecma_number_t right_value) /**< right number value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value)); + JERRY_ASSERT (!ecma_number_is_nan (right_value)); + + int right_invert_sign = ECMA_BIGINT_TO_SIGN (right_value > 0); + + if (left_value == ECMA_BIGINT_ZERO) + { + if (right_value == 0) + { + return 0; + } + + return right_invert_sign; + } + + ecma_extended_primitive_t *left_value_p = ecma_get_extended_primitive_from_value (left_value); + int left_sign = ECMA_BIGINT_TO_SIGN (left_value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN); + + if (right_value == 0 || left_sign == right_invert_sign) + { + /* Second condition: a positive BigInt is always greater than any negative number, and the opposite is true. */ + return left_sign; + } + + if (ecma_number_is_infinity (right_value)) + { + /* Infinity is always bigger than any BigInt number. */ + return right_invert_sign; + } + + ecma_bigint_digit_t digits[3]; + uint32_t result = ecma_bigint_number_to_digits (right_value, digits); + + JERRY_ASSERT (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) == 0 + || digits[ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) - 1] > 0); + + uint32_t digits_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE (result); + + if (digits_size == 0) + { + JERRY_ASSERT (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION); + /* The number is between [-1 .. 1] exclusive. */ + return left_sign; + } + + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = digits_size + ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE (result); + + if (left_size != right_size) + { + return left_size > right_size ? left_sign : -left_sign; + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, right_size); + ecma_bigint_digit_t *left_end_p = (ecma_bigint_digit_t *) (((uint8_t *) left_p) - digits_size); + ecma_bigint_digit_t *digits_p = (ecma_bigint_digit_t *) (((uint8_t *) digits) + digits_size); + + do + { + ecma_bigint_digit_t left = *(--left_p); + ecma_bigint_digit_t right = *(--digits_p); + + if (left != right) + { + return left > right ? left_sign : -left_sign; + } + } while (left_p > left_end_p); + + left_end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + + while (left_p > left_end_p) + { + if (*(--left_p) != 0) + { + return left_sign; + } + } + + return (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION) ? -left_sign : 0; +} /* ecma_bigint_compare_to_number */ + +#undef ECMA_BIGINT_TO_SIGN + +/** + * Negate a non-zero BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_negate (ecma_extended_primitive_t *value_p) /**< BigInt value */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + ecma_extended_primitive_t *result_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + memcpy (result_p + 1, value_p + 1, size); + result_p->refs_and_type = ECMA_EXTENDED_PRIMITIVE_REF_ONE | ECMA_TYPE_BIGINT; + result_p->u.bigint_sign_and_size = value_p->u.bigint_sign_and_size ^ ECMA_BIGINT_SIGN; + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_negate */ + +/** + * Invert all bits of a BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_unary (ecma_value_t value, /**< BigInt value */ + ecma_bigint_unary_operation_type type) /**< type of unary operation */ +{ + JERRY_ASSERT (ecma_is_value_bigint (value)); + + if (value == ECMA_BIGINT_ZERO) + { + return ecma_bigint_create_from_digit (1, type != ECMA_BIGINT_UNARY_INCREASE); + } + + ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value); + + uint32_t sign = (type != ECMA_BIGINT_UNARY_DECREASE) ? ECMA_BIGINT_SIGN : 0; + + if ((value_p->u.bigint_sign_and_size == (uint32_t) (sizeof (ecma_bigint_digit_t) | sign)) + && *ECMA_BIGINT_GET_DIGITS (value_p, 0) == 1) + { + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *result_p; + + if ((value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) == (sign ^ ECMA_BIGINT_SIGN)) + { + result_p = ecma_big_uint_increase (value_p); + + if (type != ECMA_BIGINT_UNARY_INCREASE && result_p != NULL) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + } + else + { + result_p = ecma_big_uint_decrease (value_p); + + if (type == ECMA_BIGINT_UNARY_INCREASE && result_p != NULL) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + } + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_unary */ + +/** + * Add/subtract right BigInt value to/from left BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_add_sub (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value, /**< right BigInt value */ + bool is_add) /**< true if add operation should be performed */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (right_value == ECMA_BIGINT_ZERO) + { + return ecma_copy_value (left_value); + } + + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (left_value == ECMA_BIGINT_ZERO) + { + if (!is_add) + { + return ecma_bigint_negate (right_p); + } + + ecma_ref_extended_primitive (right_p); + return right_value; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + uint32_t sign = is_add ? 0 : ECMA_BIGINT_SIGN; + + if (((left_p->u.bigint_sign_and_size ^ right_p->u.bigint_sign_and_size) & ECMA_BIGINT_SIGN) == sign) + { + ecma_extended_primitive_t *result_p = ecma_big_uint_add (left_p, right_p); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + result_p->u.bigint_sign_and_size |= left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); + } + + int compare_result = ecma_big_uint_compare (left_p, right_p); + ecma_extended_primitive_t *result_p; + + if (compare_result == 0) + { + return ECMA_BIGINT_ZERO; + } + + if (compare_result > 0) + { + sign = left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + result_p = ecma_big_uint_sub (left_p, right_p); + } + else + { + sign = right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + + if (!is_add) + { + sign ^= ECMA_BIGINT_SIGN; + } + + result_p = ecma_big_uint_sub (right_p, left_p); + } + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + result_p->u.bigint_sign_and_size |= sign; + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_add_sub */ + +/** + * Multiply two BigInt values + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_mul (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (left_value == ECMA_BIGINT_ZERO || right_value == ECMA_BIGINT_ZERO) + { + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_p); + + if (left_size == sizeof (ecma_bigint_digit_t) + && ECMA_BIGINT_GET_LAST_DIGIT (left_p, sizeof (ecma_bigint_digit_t)) == 1) + { + if (left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + return ecma_bigint_negate (right_p); + } + + ecma_ref_extended_primitive (right_p); + return right_value; + } + + if (right_size == sizeof (ecma_bigint_digit_t) + && ECMA_BIGINT_GET_LAST_DIGIT (right_p, sizeof (ecma_bigint_digit_t)) == 1) + { + if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + return ecma_bigint_negate (left_p); + } + + ecma_ref_extended_primitive (left_p); + return left_value; + } + + ecma_extended_primitive_t *result_p = ecma_big_uint_mul (left_p, right_p); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + uint32_t sign = (left_p->u.bigint_sign_and_size ^ right_p->u.bigint_sign_and_size) & ECMA_BIGINT_SIGN; + result_p->u.bigint_sign_and_size |= sign; + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_mul */ + +/** + * Divide two BigInt values + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_div_mod (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value, /**< right BigInt value */ + bool is_mod) /**< true if return with remainder */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (right_value == ECMA_BIGINT_ZERO) + { + return ecma_raise_range_error (ECMA_ERR_BIGINT_ZERO_DIVISION); + } + + if (left_value == ECMA_BIGINT_ZERO) + { + return left_value; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + int compare_result = ecma_big_uint_compare (left_p, right_p); + ecma_extended_primitive_t *result_p; + + if (compare_result < 0) + { + if (!is_mod) + { + return ECMA_BIGINT_ZERO; + } + + ecma_ref_extended_primitive (left_p); + return left_value; + } + else if (compare_result == 0) + { + if (is_mod) + { + return ECMA_BIGINT_ZERO; + } + + result_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t)); + + if (result_p != NULL) + { + *ECMA_BIGINT_GET_DIGITS (result_p, 0) = 1; + } + } + else + { + result_p = ecma_big_uint_div_mod (left_p, right_p, is_mod); + + if (result_p == ECMA_BIGINT_POINTER_TO_ZERO) + { + return ECMA_BIGINT_ZERO; + } + } + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if (is_mod) + { + result_p->u.bigint_sign_and_size |= left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + } + else + { + uint32_t sign = (left_p->u.bigint_sign_and_size ^ right_p->u.bigint_sign_and_size) & ECMA_BIGINT_SIGN; + result_p->u.bigint_sign_and_size |= sign; + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_div_mod */ + +/** + * Shift left BigInt value to left or right + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_shift (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value, /**< right BigInt value */ + bool is_left) /**< true if left shift operation should be performed */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (left_value == ECMA_BIGINT_ZERO) + { + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + + if (right_value == ECMA_BIGINT_ZERO) + { + ecma_ref_extended_primitive (left_p); + return left_value; + } + + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + is_left = !is_left; + } + + if (ECMA_BIGINT_GET_SIZE (right_p) > sizeof (ecma_bigint_digit_t)) + { + if (is_left) + { + return ecma_bigint_raise_memory_error (); + } + else if (left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + /* Shifting a negative value with a very big number to the right should be -1. */ + return ecma_bigint_create_from_digit (1, true); + } + + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *result_p; + ecma_bigint_digit_t shift = ECMA_BIGINT_GET_LAST_DIGIT (right_p, sizeof (ecma_bigint_digit_t)); + uint32_t left_sign = left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + + if (is_left) + { + result_p = ecma_big_uint_shift_left (left_p, shift); + } + else + { + /* -x >> y == ~(x - 1) >> y == ~((x - 1) >> y) == -(((x - 1) >> y) + 1) + * When a non-zero bit is shifted out: (x - 1) >> y == x >> y, so the formula is -((x >> y) + 1) + * When only zero bits are shifted out: (((x - 1) >> y) + 1) == x >> y so the formula is: -(x >> y) */ + result_p = ecma_big_uint_shift_right (left_p, shift, left_sign != 0); + + if (result_p == ECMA_BIGINT_POINTER_TO_ZERO) + { + return ECMA_BIGINT_ZERO; + } + } + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + result_p->u.bigint_sign_and_size |= left_sign; + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_shift */ + +/** + * Compute the left value raised to the power of right value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_pow (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (right_value == ECMA_BIGINT_ZERO) + { + return ecma_bigint_create_from_digit (1, false); + } + + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + return ecma_raise_range_error (ECMA_ERR_NEGATIVE_EXPONENT_IS_NOT_ALLOWED_FOR_BIGINTS); + } + + if (left_value == ECMA_BIGINT_ZERO) + { + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_bigint_digit_t base = 0; + + if (ECMA_BIGINT_GET_SIZE (left_p) == sizeof (ecma_bigint_digit_t)) + { + base = *ECMA_BIGINT_GET_DIGITS (left_p, 0); + + JERRY_ASSERT (base != 0); + + if (base == 1) + { + if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + || ECMA_BIGINT_NUMBER_IS_ODD (*ECMA_BIGINT_GET_DIGITS (right_p, 0))) + { + ecma_ref_extended_primitive (left_p); + return left_value; + } + + return ecma_bigint_create_from_digit (1, false); + } + } + + if (JERRY_UNLIKELY (ECMA_BIGINT_GET_SIZE (right_p) > sizeof (ecma_bigint_digit_t))) + { + return ecma_bigint_raise_memory_error (); + } + + ecma_bigint_digit_t power = *ECMA_BIGINT_GET_DIGITS (right_p, 0); + + if (power == 1) + { + ecma_ref_extended_primitive (left_p); + return left_value; + } + + ecma_extended_primitive_t *result_p; + + if (base == 2) + { + result_p = ecma_big_uint_shift_left (left_p, power - 1); + } + else + { + result_p = ecma_big_uint_pow (left_p, power); + } + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if ((left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) && ECMA_BIGINT_NUMBER_IS_ODD (power)) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_pow */ + +/** + * Convert the result to an ecma value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_bigint_bitwise_op (uint32_t operation_and_options, /**< bitwise operation type and options */ + ecma_extended_primitive_t *left_value_p, /**< left BigInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigInt value */ +{ + ecma_extended_primitive_t *result_p; + result_p = ecma_big_uint_bitwise_op (operation_and_options, left_value_p, right_value_p); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if (result_p == ECMA_BIGINT_POINTER_TO_ZERO) + { + return ECMA_BIGINT_ZERO; + } + + if (operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_bitwise_op */ + +/** + * Perform bitwise 'and' operations on two BigUInt numbers + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_and (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + if (left_value == ECMA_BIGINT_ZERO || right_value == ECMA_BIGINT_ZERO) + { + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + return ecma_bigint_bitwise_op (ECMA_BIG_UINT_BITWISE_AND, left_p, right_p); + } + + /* x & (-y) == x & ~(y-1) == x &~ (y-1) */ + uint32_t operation_and_options = ECMA_BIG_UINT_BITWISE_AND_NOT | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT; + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); + } + + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + /* (-x) & y == ~(x-1) & y == y &~ (x-1) */ + uint32_t operation_and_options = ECMA_BIG_UINT_BITWISE_AND_NOT | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT; + return ecma_bigint_bitwise_op (operation_and_options, right_p, left_p); + } + + /* (-x) & (-y) == ~(x-1) & ~(y-1) == ~((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_OR | ECMA_BIG_UINT_BITWISE_DECREASE_BOTH | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); +} /* ecma_bigint_and */ + +/** + * Perform bitwise 'or' operations on two BigUInt numbers + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_or (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + if (left_value == ECMA_BIGINT_ZERO) + { + return ecma_copy_value (right_value); + } + + if (right_value == ECMA_BIGINT_ZERO) + { + return ecma_copy_value (left_value); + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + return ecma_bigint_bitwise_op (ECMA_BIG_UINT_BITWISE_OR, left_p, right_p); + } + + /* x | (-y) == x | ~(y-1) == ~((y-1) &~ x) == -(((y-1) &~ x) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_AND_NOT | ECMA_BIG_UINT_BITWISE_DECREASE_LEFT | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, right_p, left_p); + } + + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + /* (-x) | y == ~(x-1) | y == ~((x-1) &~ y) == -(((x-1) &~ y) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_AND_NOT | ECMA_BIG_UINT_BITWISE_DECREASE_LEFT | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); + } + + /* (-x) | (-y) == ~(x-1) | ~(y-1) == ~((x-1) & (y-1)) = -(((x-1) & (y-1)) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_AND | ECMA_BIG_UINT_BITWISE_DECREASE_BOTH | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); +} /* ecma_bigint_or */ + +/** + * Perform bitwise 'xor' operations on two BigUInt numbers + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_xor (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + if (left_value == ECMA_BIGINT_ZERO) + { + return ecma_copy_value (right_value); + } + + if (right_value == ECMA_BIGINT_ZERO) + { + return ecma_copy_value (left_value); + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + return ecma_bigint_bitwise_op (ECMA_BIG_UINT_BITWISE_XOR, left_p, right_p); + } + + /* x ^ (-y) == x ^ ~(y-1) == ~(x ^ (y-1)) == -((x ^ (y-1)) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_XOR | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); + } + + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + /* (-x) | y == ~(x-1) ^ y == ~((x-1) ^ y) == -(((x-1) ^ y) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_XOR | ECMA_BIG_UINT_BITWISE_DECREASE_LEFT | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); + } + + /* (-x) ^ (-y) == ~(x-1) ^ ~(y-1) == (x-1) ^ (y-1) */ + uint32_t operation_and_options = ECMA_BIG_UINT_BITWISE_XOR | ECMA_BIG_UINT_BITWISE_DECREASE_BOTH; + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); +} /* ecma_bigint_xor */ + +#endif /* JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.h new file mode 100644 index 00000000..460ed769 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.h @@ -0,0 +1,81 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BIG_INT_H +#define ECMA_BIG_INT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_BIGINT + +/** + * Sign bit of a BigInt value. The number is negative, if this bit is set. + */ +#define ECMA_BIGINT_SIGN 0x1 + +/** + * Flags for ecma_bigint_parse_string. + */ +typedef enum +{ + ECMA_BIGINT_PARSE_NO_OPTIONS = 0, /**< no options */ + ECMA_BIGINT_PARSE_SET_NEGATIVE = (1 << 0), /**< return with a negative BigInt value */ + ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR = (1 << 1), /**< don't throw SyntaxError, + * return with ECMA_VALUE_FALSE */ + ECMA_BIGINT_PARSE_DISALLOW_MEMORY_ERROR = (1 << 2), /**< don't throw out-of-memory error, + * return with ECMA_VALUE_NULL instead */ + ECMA_BIGINT_PARSE_ALLOW_UNDERSCORE = (1 << 3), /** allow parse underscore characters */ +} ecma_bigint_parse_string_options_t; + +/** + * Types for unary operations + */ +typedef enum +{ + ECMA_BIGINT_UNARY_BITWISE_NOT, /**< bitwise not operation */ + ECMA_BIGINT_UNARY_INCREASE, /**< increase operation */ + ECMA_BIGINT_UNARY_DECREASE, /**< decrease operation */ +} ecma_bigint_unary_operation_type; + +ecma_value_t ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, lit_utf8_size_t size, uint32_t options); +ecma_value_t ecma_bigint_parse_string_value (ecma_value_t string, uint32_t options); +ecma_string_t *ecma_bigint_to_string (ecma_value_t value, ecma_bigint_digit_t radix); +ecma_value_t ecma_bigint_to_bigint (ecma_value_t value, bool allow_numbers); +ecma_value_t ecma_bigint_to_number (ecma_value_t value); +ecma_value_t ecma_bigint_get_bigint (ecma_value_t value, bool *free_result_p); +ecma_value_t ecma_bigint_create_from_digits (const uint64_t *digits_p, uint32_t size, bool sign); +uint32_t ecma_bigint_get_size_in_digits (ecma_value_t value); +void ecma_bigint_get_digits_and_sign (ecma_value_t value, uint64_t *digits_p, uint32_t size, bool *sign_p); + +bool ecma_bigint_is_equal_to_bigint (ecma_value_t left_value, ecma_value_t right_value); +bool ecma_bigint_is_equal_to_number (ecma_value_t left_value, ecma_number_t right_value); +int ecma_bigint_compare_to_bigint (ecma_value_t left_value, ecma_value_t right_value); +int ecma_bigint_compare_to_number (ecma_value_t left_value, ecma_number_t right_value); + +ecma_value_t ecma_bigint_negate (ecma_extended_primitive_t *value_p); +ecma_value_t ecma_bigint_unary (ecma_value_t value, ecma_bigint_unary_operation_type type); +ecma_value_t ecma_bigint_add_sub (ecma_value_t left_value, ecma_value_t right_value, bool is_add); +ecma_value_t ecma_bigint_mul (ecma_value_t left_value, ecma_value_t right_value); +ecma_value_t ecma_bigint_div_mod (ecma_value_t left_value, ecma_value_t right_value, bool is_mod); +ecma_value_t ecma_bigint_shift (ecma_value_t left_value, ecma_value_t right_value, bool is_left); +ecma_value_t ecma_bigint_pow (ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t ecma_bigint_and (ecma_value_t left_value, ecma_value_t right_value); +ecma_value_t ecma_bigint_or (ecma_value_t left_value, ecma_value_t right_value); +ecma_value_t ecma_bigint_xor (ecma_value_t left_value, ecma_value_t right_value); + +#endif /* JERRY_BUILTIN_BIGINT */ + +#endif /* ECMA_BIG_INT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.cpp new file mode 100644 index 00000000..956aa4a7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.cpp @@ -0,0 +1,88 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-boolean-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabooleanobject ECMA Boolean object related routines + * @{ + */ + +/** + * Boolean object creation operation. + * + * See also: ECMA-262 v5, 15.6.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_boolean_object (ecma_value_t arg) /**< argument passed to the Boolean constructor */ +{ + bool boolean_value = ecma_op_to_boolean (arg); + ecma_builtin_id_t proto_id; + +#if JERRY_BUILTIN_BOOLEAN + proto_id = ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE; +#else /* JERRY_BUILTIN_BOOLEAN */ + proto_id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; +#endif /* !(JERRY_BUILTIN_BOOLEAN */ + + ecma_object_t *prototype_obj_p = ecma_builtin_get (proto_id); + + ecma_object_t *new_target = JERRY_CONTEXT (current_new_target_p); + if (new_target) + { + prototype_obj_p = ecma_op_get_prototype_from_constructor (new_target, proto_id); + + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + } + + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_BOOLEAN; + ext_object_p->u.cls.u3.value = ecma_make_boolean_value (boolean_value); + + if (new_target) + { + ecma_deref_object (prototype_obj_p); + } + + return ecma_make_object_value (object_p); +} /* ecma_op_create_boolean_object */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.h new file mode 100644 index 00000000..adf0353d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BOOLEAN_OBJECT_H +#define ECMA_BOOLEAN_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabooleanobject ECMA Boolean object related routines + * @{ + */ + +ecma_value_t ecma_op_create_boolean_object (ecma_value_t arg); + +/** + * @} + * @} + */ + +#endif /* !ECMA_BOOLEAN_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.cpp new file mode 100644 index 00000000..5a32a2c6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.cpp @@ -0,0 +1,536 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-comparison.h" + +#include "ecma-bigint.h" +#include "ecma-conversion.h" +#include "ecma-globals.h" +#include "ecma-objects.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmacomparison ECMA comparison + * @{ + */ + +/** + * ECMA abstract equality comparison routine. + * + * See also: ECMA-262 v5, 11.9.3 + * + * Note: + * This function might raise an exception, so the + * returned value must be freed with ecma_free_value. + * + * @return true - if values are equal, + * false - otherwise + * error - in case of any problems + */ +ecma_value_t +ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */ + ecma_value_t y) /**< second operand */ +{ + if (x == y) + { + return ECMA_VALUE_TRUE; + } + + if (ecma_are_values_integer_numbers (x, y)) + { + /* Note: the (x == y) comparison captures the true case. */ + return ECMA_VALUE_FALSE; + } + + if (ecma_is_value_number (x)) + { + if (ecma_is_value_number (y)) + { + /* 1.c */ + ecma_number_t x_num = ecma_get_number_from_value (x); + ecma_number_t y_num = ecma_get_number_from_value (y); + + bool is_x_equal_to_y = (x_num == y_num); + +#ifndef JERRY_NDEBUG + bool is_x_equal_to_y_check; + + if (ecma_number_is_nan (x_num) || ecma_number_is_nan (y_num)) + { + is_x_equal_to_y_check = false; + } + else if (x_num == y_num || (ecma_number_is_zero (x_num) && ecma_number_is_zero (y_num))) + { + is_x_equal_to_y_check = true; + } + else + { + is_x_equal_to_y_check = false; + } + + JERRY_ASSERT (is_x_equal_to_y == is_x_equal_to_y_check); +#endif /* !JERRY_NDEBUG */ + + return ecma_make_boolean_value (is_x_equal_to_y); + } + + /* Swap values. */ + x ^= y; + y ^= x; + x ^= y; + } + + if (ecma_is_value_string (x)) + { + if (ecma_is_value_string (y)) + { + /* 1., d. */ + ecma_string_t *x_str_p = ecma_get_string_from_value (x); + ecma_string_t *y_str_p = ecma_get_string_from_value (y); + + bool is_equal = ecma_compare_ecma_strings (x_str_p, y_str_p); + + return ecma_make_boolean_value (is_equal); + } + + if (ecma_is_value_number (y)) + { + /* 4. */ + ecma_number_t num; + ecma_value_t x_num_value = ecma_op_to_number (x, &num); + + if (ECMA_IS_VALUE_ERROR (x_num_value)) + { + return x_num_value; + } + ecma_value_t num_value = ecma_make_number_value (num); + ecma_value_t compare_result = ecma_op_abstract_equality_compare (num_value, y); + + ecma_free_value (num_value); + return compare_result; + } + + /* Swap values. */ + x ^= y; + y ^= x; + x ^= y; + } + + if (ecma_is_value_boolean (y)) + { + if (ecma_is_value_boolean (x)) + { + /* 1., e. */ + /* Note: the (x == y) comparison captures the true case. */ + return ECMA_VALUE_FALSE; + } + + /* 7. */ + return ecma_op_abstract_equality_compare (x, ecma_make_integer_value (ecma_is_value_true (y) ? 1 : 0)); + } + + if (ecma_is_value_boolean (x)) + { + /* 6. */ + return ecma_op_abstract_equality_compare (ecma_make_integer_value (ecma_is_value_true (x) ? 1 : 0), y); + } + +#if JERRY_BUILTIN_BIGINT + if (JERRY_UNLIKELY (ecma_is_value_bigint (x))) + { + if (ecma_is_value_bigint (y)) + { + return ecma_make_boolean_value (ecma_bigint_is_equal_to_bigint (x, y)); + } + + if (ecma_is_value_string (y)) + { + ecma_value_t bigint = ecma_bigint_parse_string_value (y, ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR); + + if (ECMA_IS_VALUE_ERROR (bigint) || bigint == ECMA_VALUE_FALSE) + { + return bigint; + } + + JERRY_ASSERT (ecma_is_value_bigint (bigint)); + + ecma_value_t result = ecma_make_boolean_value (ecma_bigint_is_equal_to_bigint (x, bigint)); + + ecma_free_value (bigint); + return result; + } + + if (ecma_is_value_number (y)) + { + return ecma_make_boolean_value (ecma_bigint_is_equal_to_number (x, ecma_get_number_from_value (y))); + } + + /* Swap values. */ + x ^= y; + y ^= x; + x ^= y; + } +#endif /* JERRY_BUILTIN_BIGINT */ + + if (ecma_is_value_undefined (x) || ecma_is_value_null (x)) + { + /* 1. a., b. */ + /* 2., 3. */ + bool is_equal = ecma_is_value_undefined (y) || ecma_is_value_null (y); + + return ecma_make_boolean_value (is_equal); + } + + if (JERRY_UNLIKELY (ecma_is_value_symbol (x))) + { + if (!ecma_is_value_object (y)) + { + return ECMA_VALUE_FALSE; + } + + /* Swap values. */ + x ^= y; + y ^= x; + x ^= y; + } + + JERRY_ASSERT (ecma_is_value_object (x)); + + if (ecma_is_value_string (y) || ecma_is_value_symbol (y) +#if JERRY_BUILTIN_BIGINT + || ecma_is_value_bigint (y) +#endif /* JERRY_BUILTIN_BIGINT */ + || ecma_is_value_number (y)) + { + /* 9. */ + ecma_object_t *obj_p = ecma_get_object_from_value (x); + + ecma_value_t def_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NO); + + if (ECMA_IS_VALUE_ERROR (def_value)) + { + return def_value; + } + + ecma_value_t compare_result = ecma_op_abstract_equality_compare (def_value, y); + + ecma_free_value (def_value); + + return compare_result; + } + + return ECMA_VALUE_FALSE; +} /* ecma_op_abstract_equality_compare */ + +/** + * ECMA strict equality comparison routine. + * + * See also: ECMA-262 v5, 11.9.6 + * + * @return true - if values are strict equal, + * false - otherwise + */ +bool +ecma_op_strict_equality_compare (ecma_value_t x, /**< first operand */ + ecma_value_t y) /**< second operand */ +{ + if (ecma_is_value_direct (x) || ecma_is_value_direct (y) || ecma_is_value_symbol (x) || ecma_is_value_symbol (y) + || ecma_is_value_object (x) || ecma_is_value_object (y)) + { + JERRY_ASSERT (!ecma_is_value_direct (x) || ecma_is_value_undefined (x) || ecma_is_value_null (x) + || ecma_is_value_boolean (x) || ecma_is_value_integer_number (x)); + + JERRY_ASSERT (!ecma_is_value_direct (y) || ecma_is_value_undefined (y) || ecma_is_value_null (y) + || ecma_is_value_boolean (y) || ecma_is_value_integer_number (y)); + + if ((x != ecma_make_integer_value (0) || !ecma_is_value_float_number (y)) + && (y != ecma_make_integer_value (0) || !ecma_is_value_float_number (x))) + { + return (x == y); + } + + /* The +0 === -0 case handled below. */ + } + + JERRY_ASSERT (ecma_is_value_number (x) || ecma_is_value_string (x) || ecma_is_value_bigint (x)); + JERRY_ASSERT (ecma_is_value_number (y) || ecma_is_value_string (y) || ecma_is_value_bigint (y)); + + if (ecma_is_value_string (x)) + { + if (!ecma_is_value_string (y)) + { + return false; + } + + ecma_string_t *x_str_p = ecma_get_string_from_value (x); + ecma_string_t *y_str_p = ecma_get_string_from_value (y); + + return ecma_compare_ecma_strings (x_str_p, y_str_p); + } + +#if JERRY_BUILTIN_BIGINT + if (JERRY_UNLIKELY (ecma_is_value_bigint (x))) + { + if (!ecma_is_value_bigint (y)) + { + return false; + } + + return ecma_bigint_is_equal_to_bigint (x, y); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + if (!ecma_is_value_number (y)) + { + return false; + } + + ecma_number_t x_num = ecma_get_number_from_value (x); + ecma_number_t y_num = ecma_get_number_from_value (y); + + bool is_x_equal_to_y = (x_num == y_num); + +#ifndef JERRY_NDEBUG + bool is_x_equal_to_y_check; + + if (ecma_number_is_nan (x_num) || ecma_number_is_nan (y_num)) + { + is_x_equal_to_y_check = false; + } + else if (x_num == y_num || (ecma_number_is_zero (x_num) && ecma_number_is_zero (y_num))) + { + is_x_equal_to_y_check = true; + } + else + { + is_x_equal_to_y_check = false; + } + + JERRY_ASSERT (is_x_equal_to_y == is_x_equal_to_y_check); +#endif /* !JERRY_NDEBUG */ + + return is_x_equal_to_y; +} /* ecma_op_strict_equality_compare */ + +/** + * ECMA abstract relational comparison routine. + * + * See also: ECMA-262 v5, 11.8.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_abstract_relational_compare (ecma_value_t x, /**< first operand */ + ecma_value_t y, /**< second operand */ + bool left_first) /**< 'LeftFirst' flag */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 1., 2. */ + ecma_value_t prim_first_converted_value = ecma_op_to_primitive (x, ECMA_PREFERRED_TYPE_NUMBER); + if (ECMA_IS_VALUE_ERROR (prim_first_converted_value)) + { + return prim_first_converted_value; + } + + ecma_value_t prim_second_converted_value = ecma_op_to_primitive (y, ECMA_PREFERRED_TYPE_NUMBER); + if (ECMA_IS_VALUE_ERROR (prim_second_converted_value)) + { + ecma_free_value (prim_first_converted_value); + return prim_second_converted_value; + } + + ecma_value_t px = left_first ? prim_first_converted_value : prim_second_converted_value; + ecma_value_t py = left_first ? prim_second_converted_value : prim_first_converted_value; + + const bool is_px_string = ecma_is_value_string (px); + const bool is_py_string = ecma_is_value_string (py); + + if (!(is_px_string && is_py_string)) + { +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (!ecma_is_value_bigint (px)) && JERRY_LIKELY (!ecma_is_value_bigint (py))) + { +#endif /* JERRY_BUILTIN_BIGINT */ + /* 3. */ + + /* a. */ + + ecma_number_t nx; + ecma_number_t ny; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (px, &nx)) || ECMA_IS_VALUE_ERROR (ecma_op_to_number (py, &ny))) + { + ret_value = ECMA_VALUE_ERROR; + goto end; + } + + /* b. */ + if (ecma_number_is_nan (nx) || ecma_number_is_nan (ny)) + { + /* c., d. */ + ret_value = ECMA_VALUE_UNDEFINED; + } + else + { + bool is_x_less_than_y = (nx < ny); + +#ifndef JERRY_NDEBUG + bool is_x_less_than_y_check; + + if (nx == ny || (ecma_number_is_zero (nx) && ecma_number_is_zero (ny))) + { + /* e., f., g. */ + is_x_less_than_y_check = false; + } + else if (ecma_number_is_infinity (nx) && !ecma_number_is_negative (nx)) + { + /* h. */ + is_x_less_than_y_check = false; + } + else if (ecma_number_is_infinity (ny) && !ecma_number_is_negative (ny)) + { + /* i. */ + is_x_less_than_y_check = true; + } + else if (ecma_number_is_infinity (ny) && ecma_number_is_negative (ny)) + { + /* j. */ + is_x_less_than_y_check = false; + } + else if (ecma_number_is_infinity (nx) && ecma_number_is_negative (nx)) + { + /* k. */ + is_x_less_than_y_check = true; + } + else + { + /* l. */ + JERRY_ASSERT (!ecma_number_is_nan (nx) && !ecma_number_is_infinity (nx)); + JERRY_ASSERT (!ecma_number_is_nan (ny) && !ecma_number_is_infinity (ny)); + JERRY_ASSERT (!(ecma_number_is_zero (nx) && ecma_number_is_zero (ny))); + + if (nx < ny) + { + is_x_less_than_y_check = true; + } + else + { + is_x_less_than_y_check = false; + } + } + + JERRY_ASSERT (is_x_less_than_y_check == is_x_less_than_y); +#endif /* !JERRY_NDEBUG */ + + ret_value = ecma_make_boolean_value (is_x_less_than_y); + } +#if JERRY_BUILTIN_BIGINT + } + else + { + bool invert_result = false; + int compare_result = 0; + + if (!ecma_is_value_bigint (px)) + { + ecma_value_t tmp = px; + px = py; + py = tmp; + invert_result = true; + } + + JERRY_ASSERT (ecma_is_value_bigint (px)); + + if (ecma_is_value_bigint (py)) + { + compare_result = ecma_bigint_compare_to_bigint (px, py); + } + else if (ecma_is_value_string (py)) + { + ret_value = ecma_bigint_parse_string_value (py, ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR); + + if (!ECMA_IS_VALUE_ERROR (ret_value)) + { + if (ret_value == ECMA_VALUE_FALSE) + { + ret_value = ECMA_VALUE_UNDEFINED; + } + else + { + compare_result = ecma_bigint_compare_to_bigint (px, ret_value); + ecma_free_value (ret_value); + ret_value = ECMA_VALUE_EMPTY; + } + } + } + else + { + ecma_number_t ny; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (py, &ny))) + { + ret_value = ECMA_VALUE_ERROR; + goto end; + } + + if (ecma_number_is_nan (ny)) + { + ret_value = ECMA_VALUE_UNDEFINED; + } + else + { + compare_result = ecma_bigint_compare_to_number (px, ny); + } + } + + if (ret_value == ECMA_VALUE_EMPTY) + { + if (invert_result) + { + compare_result = -compare_result; + } + + ret_value = ecma_make_boolean_value (compare_result < 0); + } + } +#endif /* JERRY_BUILTIN_BIGINT */ + } + else + { /* 4. */ + JERRY_ASSERT (is_px_string && is_py_string); + + ecma_string_t *str_x_p = ecma_get_string_from_value (px); + ecma_string_t *str_y_p = ecma_get_string_from_value (py); + + bool is_px_less = ecma_compare_ecma_strings_relational (str_x_p, str_y_p); + + ret_value = ecma_make_boolean_value (is_px_less); + } + +end: + ecma_free_value (prim_second_converted_value); + ecma_free_value (prim_first_converted_value); + + return ret_value; +} /* ecma_op_abstract_relational_compare */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.h new file mode 100644 index 00000000..d8e0084e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_COMPARISON_H +#define ECMA_COMPARISON_H + +#include "ecma-globals.h" +#include "ecma-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmacomparison ECMA comparison + * @{ + */ + +ecma_value_t ecma_op_abstract_equality_compare (ecma_value_t x, ecma_value_t y); +bool ecma_op_strict_equality_compare (ecma_value_t x, ecma_value_t y); +ecma_value_t ecma_op_abstract_relational_compare (ecma_value_t x, ecma_value_t y, bool left_first); + +/** + * @} + * @} + */ + +#endif /* !ECMA_COMPARISON_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.cpp new file mode 100644 index 00000000..bc602f96 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.cpp @@ -0,0 +1,1143 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ecma-container-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-property-hashmap.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_CONTAINER + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup \addtogroup ecmamaphelpers ECMA builtin Map/Set helper functions + * @{ + */ + +/** + * Create a new internal buffer. + * + * Note: + * The first element of the collection tracks the size of the buffer. + * ECMA_VALUE_EMPTY values are not calculated into the size. + * + * @return pointer to the internal buffer + */ +static inline ecma_collection_t * +ecma_op_create_internal_buffer (void) +{ + ecma_collection_t *collection_p = ecma_new_collection (); + ecma_collection_push_back (collection_p, (ecma_value_t) 0); + + return collection_p; +} /* ecma_op_create_internal_buffer */ + +/** + * Append values to the internal buffer. + */ +static void +ecma_op_internal_buffer_append (ecma_collection_t *container_p, /**< internal container pointer */ + ecma_value_t key_arg, /**< key argument */ + ecma_value_t value_arg, /**< value argument */ + lit_magic_string_id_t lit_id) /**< class id */ +{ + JERRY_ASSERT (container_p != NULL); + + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) + { + ecma_value_t values[] = { ecma_copy_value_if_not_object (key_arg), ecma_copy_value_if_not_object (value_arg) }; + ecma_collection_append (container_p, values, 2); + } + else + { + ecma_collection_push_back (container_p, ecma_copy_value_if_not_object (key_arg)); + } + + ECMA_CONTAINER_SET_SIZE (container_p, ECMA_CONTAINER_GET_SIZE (container_p) + 1); +} /* ecma_op_internal_buffer_append */ + +/** + * Update the value of a given entry. + */ +static inline void +ecma_op_internal_buffer_update (ecma_value_t *entry_p, /**< entry pointer */ + ecma_value_t value_arg, /**< value argument */ + lit_magic_string_id_t lit_id) /**< class id */ +{ + JERRY_ASSERT (entry_p != NULL); + + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) + { + ecma_free_value_if_not_object (((ecma_container_pair_t *) entry_p)->value); + + ((ecma_container_pair_t *) entry_p)->value = ecma_copy_value_if_not_object (value_arg); + } +} /* ecma_op_internal_buffer_update */ + +/** + * Delete element from the internal buffer. + */ +static void +ecma_op_internal_buffer_delete (ecma_collection_t *container_p, /**< internal container pointer */ + ecma_container_pair_t *entry_p, /**< entry pointer */ + lit_magic_string_id_t lit_id) /**< class id */ +{ + JERRY_ASSERT (container_p != NULL); + JERRY_ASSERT (entry_p != NULL); + + ecma_free_value_if_not_object (entry_p->key); + entry_p->key = ECMA_VALUE_EMPTY; + + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) + { + ecma_free_value_if_not_object (entry_p->value); + entry_p->value = ECMA_VALUE_EMPTY; + } + + ECMA_CONTAINER_SET_SIZE (container_p, ECMA_CONTAINER_GET_SIZE (container_p) - 1); +} /* ecma_op_internal_buffer_delete */ + +/** + * Find an entry in the collection. + * + * @return pointer to the appropriate entry. + */ +static ecma_value_t * +ecma_op_internal_buffer_find (ecma_collection_t *container_p, /**< internal container pointer */ + ecma_value_t key_arg, /**< key argument */ + lit_magic_string_id_t lit_id) /**< class id */ +{ + JERRY_ASSERT (container_p != NULL); + + uint8_t entry_size = ecma_op_container_entry_size (lit_id); + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + + for (uint32_t i = 0; i < entry_count; i += entry_size) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_op_same_value_zero (*entry_p, key_arg, false)) + { + return entry_p; + } + } + + return NULL; +} /* ecma_op_internal_buffer_find */ + +/** + * Get the value that belongs to the key. + * + * Note: in case of Set containers, the values are the same as the keys. + * + * @return ecma value + */ +static ecma_value_t +ecma_op_container_get_value (ecma_value_t *entry_p, /**< entry (key) pointer */ + lit_magic_string_id_t lit_id) /**< class id */ +{ + JERRY_ASSERT (entry_p != NULL); + + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) + { + return ((ecma_container_pair_t *) entry_p)->value; + } + + return *entry_p; +} /* ecma_op_container_get_value */ + +/** + * Get the size (in ecma_value_t) of the stored entries. + * + * @return size of the entries. + */ +uint8_t +ecma_op_container_entry_size (lit_magic_string_id_t lit_id) /**< class id */ +{ + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) + { + return ECMA_CONTAINER_PAIR_SIZE; + } + + return ECMA_CONTAINER_VALUE_SIZE; +} /* ecma_op_container_entry_size */ + +/** + * Release the entries in the WeakSet container. + */ +static void +ecma_op_container_free_weakset_entries (ecma_object_t *object_p, /**< object pointer */ + ecma_collection_t *container_p) /** internal buffer pointer */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (container_p != NULL); + + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_VALUE_SIZE) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_is_value_empty (*entry_p)) + { + continue; + } + + ecma_op_object_unref_weak (ecma_get_object_from_value (*entry_p), ecma_make_object_value (object_p)); + ecma_op_container_remove_weak_entry (object_p, *entry_p); + + *entry_p = ECMA_VALUE_EMPTY; + } +} /* ecma_op_container_free_weakset_entries */ + +/** + * Release the entries in the WeakMap container. + */ +static void +ecma_op_container_free_weakmap_entries (ecma_object_t *object_p, /**< object pointer */ + ecma_collection_t *container_p) /**< internal buffer pointer */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (container_p != NULL); + + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE) + { + ecma_container_pair_t *entry_p = (ecma_container_pair_t *) (start_p + i); + + if (ecma_is_value_empty (entry_p->key)) + { + continue; + } + + ecma_op_object_unref_weak (ecma_get_object_from_value (entry_p->key), ecma_make_object_value (object_p)); + ecma_op_container_remove_weak_entry (object_p, entry_p->key); + + ecma_free_value_if_not_object (entry_p->value); + + entry_p->key = ECMA_VALUE_EMPTY; + entry_p->value = ECMA_VALUE_EMPTY; + } +} /* ecma_op_container_free_weakmap_entries */ + +/** + * Release the entries in the Set container. + */ +static void +ecma_op_container_free_set_entries (ecma_collection_t *container_p) +{ + JERRY_ASSERT (container_p != NULL); + + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_VALUE_SIZE) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_is_value_empty (*entry_p)) + { + continue; + } + + ecma_free_value_if_not_object (*entry_p); + *entry_p = ECMA_VALUE_EMPTY; + } +} /* ecma_op_container_free_set_entries */ + +/** + * Release the entries in the Map container. + */ +static void +ecma_op_container_free_map_entries (ecma_collection_t *container_p) +{ + JERRY_ASSERT (container_p != NULL); + + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE) + { + ecma_container_pair_t *entry_p = (ecma_container_pair_t *) (start_p + i); + + if (ecma_is_value_empty (entry_p->key)) + { + continue; + } + + ecma_free_value_if_not_object (entry_p->key); + ecma_free_value_if_not_object (entry_p->value); + + entry_p->key = ECMA_VALUE_EMPTY; + entry_p->value = ECMA_VALUE_EMPTY; + } +} /* ecma_op_container_free_map_entries */ + +/** + * Release the internal buffer and the stored entries. + */ +void +ecma_op_container_free_entries (ecma_object_t *object_p) /**< collection object pointer */ +{ + JERRY_ASSERT (object_p != NULL); + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + switch (map_object_p->u.cls.u2.container_id) + { + case LIT_MAGIC_STRING_WEAKSET_UL: + { + ecma_op_container_free_weakset_entries (object_p, container_p); + break; + } + case LIT_MAGIC_STRING_WEAKMAP_UL: + { + ecma_op_container_free_weakmap_entries (object_p, container_p); + break; + } + case LIT_MAGIC_STRING_SET_UL: + { + ecma_op_container_free_set_entries (container_p); + break; + } + case LIT_MAGIC_STRING_MAP_UL: + { + ecma_op_container_free_map_entries (container_p); + break; + } + default: + { + break; + } + } + + ECMA_CONTAINER_SET_SIZE (container_p, 0); +} /* ecma_op_container_free_entries */ + +/** + * Handle calling [[Construct]] of built-in Map/Set like objects + * + * @return ecma value + */ +ecma_value_t +ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len, /**< number of arguments */ + lit_magic_string_id_t lit_id, /**< internal class id */ + ecma_builtin_id_t proto_id) /**< prototype builtin id */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + JERRY_ASSERT (lit_id == LIT_MAGIC_STRING_MAP_UL || lit_id == LIT_MAGIC_STRING_SET_UL + || lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL); + JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p) != NULL); + + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), proto_id); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_collection_t *container_p = ecma_op_create_internal_buffer (); + ecma_object_t *object_p = ecma_create_object (proto_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + ecma_deref_object (proto_p); + ecma_extended_object_t *map_obj_p = (ecma_extended_object_t *) object_p; + map_obj_p->u.cls.type = ECMA_OBJECT_CLASS_CONTAINER; + map_obj_p->u.cls.u1.container_flags = ECMA_CONTAINER_FLAGS_EMPTY; + map_obj_p->u.cls.u2.container_id = (uint16_t) lit_id; + ecma_value_t iterator; + ecma_object_t *adder_func_p; + + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL) + { + map_obj_p->u.cls.u1.container_flags |= ECMA_CONTAINER_FLAGS_WEAK; + } + + ECMA_SET_INTERNAL_VALUE_POINTER (map_obj_p->u.cls.u3.value, container_p); + + ecma_value_t set_value = ecma_make_object_value (object_p); + ecma_value_t result = set_value; + + if (arguments_list_len == 0) + { + return result; + } + + ecma_value_t iterable = arguments_list_p[0]; + + if (ecma_is_value_undefined (iterable) || ecma_is_value_null (iterable)) + { + return result; + } + + lit_magic_string_id_t adder_string_id; + if (lit_id == LIT_MAGIC_STRING_MAP_UL || lit_id == LIT_MAGIC_STRING_WEAKMAP_UL) + { + adder_string_id = LIT_MAGIC_STRING_SET; + } + else + { + adder_string_id = LIT_MAGIC_STRING_ADD; + } + + result = ecma_op_object_get_by_magic_id (object_p, adder_string_id); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_object; + } + + if (!ecma_op_is_callable (result)) + { + ecma_free_value (result); + result = ecma_raise_type_error (ECMA_ERR_FUNCTION_ADD_ORSET_IS_NOT_CALLABLE); + goto cleanup_object; + } + + adder_func_p = ecma_get_object_from_value (result); + + ecma_value_t next_method; + result = ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, &next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_adder; + } + + iterator = result; + + while (true) + { + result = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_iterator; + } + + if (ecma_is_value_false (result)) + { + break; + } + + const ecma_value_t next = result; + result = ecma_op_iterator_value (next); + ecma_free_value (next); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_iterator; + } + + if (lit_id == LIT_MAGIC_STRING_SET_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL) + { + const ecma_value_t value = result; + + ecma_value_t arguments[] = { value }; + result = ecma_op_function_call (adder_func_p, set_value, arguments, 1); + + ecma_free_value (value); + } + else + { + if (!ecma_is_value_object (result)) + { + ecma_free_value (result); + ecma_raise_type_error (ECMA_ERR_ITERATOR_VALUE_IS_NOT_AN_OBJECT); + result = ecma_op_iterator_close (iterator); + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result)); + goto cleanup_iterator; + } + + ecma_object_t *next_object_p = ecma_get_object_from_value (result); + + result = ecma_op_object_get_by_index (next_object_p, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (next_object_p); + ecma_op_iterator_close (iterator); + goto cleanup_iterator; + } + + const ecma_value_t key = result; + + result = ecma_op_object_get_by_index (next_object_p, 1); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (next_object_p); + ecma_free_value (key); + ecma_op_iterator_close (iterator); + goto cleanup_iterator; + } + + const ecma_value_t value = result; + ecma_value_t arguments[] = { key, value }; + result = ecma_op_function_call (adder_func_p, set_value, arguments, 2); + + ecma_free_value (key); + ecma_free_value (value); + ecma_deref_object (next_object_p); + } + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_op_iterator_close (iterator); + goto cleanup_iterator; + } + + ecma_free_value (result); + } + + ecma_ref_object (object_p); + result = ecma_make_object_value (object_p); + +cleanup_iterator: + ecma_free_value (iterator); + ecma_free_value (next_method); +cleanup_adder: + ecma_deref_object (adder_func_p); +cleanup_object: + ecma_deref_object (object_p); + + return result; +} /* ecma_op_container_create */ + +/** + * Get Map/Set object pointer + * + * Note: + * If the function returns with NULL, the error object has + * already set, and the caller must return with ECMA_VALUE_ERROR + * + * @return pointer to the Map/Set if this_arg is a valid Map/Set object + * NULL otherwise + */ +ecma_extended_object_t * +ecma_op_container_get_object (ecma_value_t this_arg, /**< this argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *map_object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (map_object_p, ECMA_OBJECT_CLASS_CONTAINER) + && ((ecma_extended_object_t *) map_object_p)->u.cls.u2.container_id == lit_id) + { + return (ecma_extended_object_t *) map_object_p; + } + } + +#if JERRY_ERROR_MESSAGES + ecma_raise_standard_error_with_format (JERRY_ERROR_TYPE, + "Expected a % object", + ecma_make_string_value (ecma_get_magic_string (lit_id))); +#else /* !JERRY_ERROR_MESSAGES */ + ecma_raise_type_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + + return NULL; +} /* ecma_op_container_get_object */ + +/** + * Returns with the size of the Map/Set object. + * + * @return size of the Map/Set object as ecma-value. + */ +ecma_value_t +ecma_op_container_size (ecma_extended_object_t *map_object_p) /**< internal class id */ +{ + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + return ecma_make_uint32_value (ECMA_CONTAINER_GET_SIZE (container_p)); +} /* ecma_op_container_size */ + +/** + * The generic Map/WeakMap prototype object's 'get' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_get (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t key_arg, /**< key argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL && !ecma_is_value_object (key_arg)) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + if (ECMA_CONTAINER_GET_SIZE (container_p) == 0) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); + + if (entry_p == NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_copy_value (((ecma_container_pair_t *) entry_p)->value); +} /* ecma_op_container_get */ + +/** + * The generic Map/Set prototype object's 'has' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_has (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t key_arg, /**< key argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + if ((map_object_p->u.cls.u1.container_flags & ECMA_CONTAINER_FLAGS_WEAK) != 0 && !ecma_is_value_object (key_arg)) + { + return ECMA_VALUE_FALSE; + } + + if (ECMA_CONTAINER_GET_SIZE (container_p) == 0) + { + return ECMA_VALUE_FALSE; + } + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); + + return ecma_make_boolean_value (entry_p != NULL); +} /* ecma_op_container_has */ + +/** + * Helper method for the Map.prototype.set and Set.prototype.add methods to swap the sign of the given value if needed + * + * See also: + * ECMA-262 v6, 23.2.3.1 step 6 + * ECMA-262 v6, 23.1.3.9 step 6 + * + * @return ecma value + */ +static ecma_value_t +ecma_op_container_set_noramlize_zero (ecma_value_t this_arg) /*< this arg */ +{ + if (ecma_is_value_number (this_arg)) + { + ecma_number_t number_value = ecma_get_number_from_value (this_arg); + + if (JERRY_UNLIKELY (ecma_number_is_zero (number_value) && ecma_number_is_negative (number_value))) + { + return ecma_make_integer_value (0); + } + } + + return this_arg; +} /* ecma_op_container_set_noramlize_zero */ + +/** + * The generic Map prototype object's 'set' and Set prototype object's 'add' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_set (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t key_arg, /**< key argument */ + ecma_value_t value_arg, /**< value argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + if ((map_object_p->u.cls.u1.container_flags & ECMA_CONTAINER_FLAGS_WEAK) != 0 && !ecma_is_value_object (key_arg)) + { + return ecma_raise_type_error (ECMA_ERR_KEY_MUST_BE_AN_OBJECT); + } + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); + + if (entry_p == NULL) + { + ecma_op_internal_buffer_append (container_p, ecma_op_container_set_noramlize_zero (key_arg), value_arg, lit_id); + + if ((map_object_p->u.cls.u1.container_flags & ECMA_CONTAINER_FLAGS_WEAK) != 0) + { + ecma_object_t *key_p = ecma_get_object_from_value (key_arg); + ecma_op_object_set_weak (key_p, (ecma_object_t *) map_object_p); + } + } + else + { + ecma_op_internal_buffer_update (entry_p, ecma_op_container_set_noramlize_zero (value_arg), lit_id); + } + + ecma_ref_object ((ecma_object_t *) map_object_p); + return ecma_make_object_value ((ecma_object_t *) map_object_p); +} /* ecma_op_container_set */ + +/** + * The generic Map/Set prototype object's 'forEach' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_foreach (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t predicate, /**< callback function */ + ecma_value_t predicate_this_arg, /**< this argument for + * invoke predicate */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + if (!ecma_op_is_callable (predicate)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + JERRY_ASSERT (ecma_is_value_object (predicate)); + ecma_object_t *func_object_p = ecma_get_object_from_value (predicate); + ecma_value_t ret_value = ECMA_VALUE_UNDEFINED; + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + uint8_t entry_size = ecma_op_container_entry_size (lit_id); + + for (uint32_t i = 0; i < ECMA_CONTAINER_ENTRY_COUNT (container_p); i += entry_size) + { + ecma_value_t *entry_p = ECMA_CONTAINER_START (container_p) + i; + + if (ecma_is_value_empty (*entry_p)) + { + continue; + } + + ecma_value_t key_arg = *entry_p; + ecma_value_t value_arg = ecma_op_container_get_value (entry_p, lit_id); + + ecma_value_t this_arg = ecma_make_object_value ((ecma_object_t *) map_object_p); + ecma_value_t call_args[] = { value_arg, key_arg, this_arg }; + ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ret_value = call_value; + break; + } + + ecma_free_value (call_value); + } + + return ret_value; +} /* ecma_op_container_foreach */ + +/** + * The Map/Set prototype object's 'clear' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_clear (ecma_extended_object_t *map_object_p) /**< this argument */ +{ + ecma_op_container_free_entries ((ecma_object_t *) map_object_p); + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_container_clear */ + +/** + * The generic Map/Set prototype object's 'delete' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_delete (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t key_arg, /**< key argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); + + if (entry_p == NULL) + { + return ECMA_VALUE_FALSE; + } + + ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, lit_id); + return ECMA_VALUE_TRUE; +} /* ecma_op_container_delete */ + +/** + * The generic WeakMap/WeakSet prototype object's 'delete' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_delete_weak (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t key_arg, /**< key argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + if (!ecma_is_value_object (key_arg)) + { + return ECMA_VALUE_FALSE; + } + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); + + if (entry_p == NULL) + { + return ECMA_VALUE_FALSE; + } + + ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, lit_id); + + ecma_object_t *key_object_p = ecma_get_object_from_value (key_arg); + ecma_op_object_unref_weak (key_object_p, ecma_make_object_value ((ecma_object_t *) map_object_p)); + + return ECMA_VALUE_TRUE; +} /* ecma_op_container_delete_weak */ + +/** + * Helper function to get the value from a weak container object + * + * @return value property + */ +ecma_value_t +ecma_op_container_find_weak_value (ecma_object_t *object_p, /**< internal container object */ + ecma_value_t key_arg) /**< key */ +{ + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (map_object_p->u.cls.type == ECMA_OBJECT_CLASS_CONTAINER + && map_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKMAP_UL); + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, (lit_magic_string_id_t) map_object_p->u.cls.u2.container_id); + + JERRY_ASSERT (entry_p != NULL); + + return entry_p[1]; +} /* ecma_op_container_find_weak_value */ + +/** + * Helper function to remove a key/value pair from a weak container object + */ +void +ecma_op_container_remove_weak_entry (ecma_object_t *object_p, /**< internal container object */ + ecma_value_t key_arg) /**< key */ +{ + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (map_object_p->u.cls.type == ECMA_OBJECT_CLASS_CONTAINER + && (map_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKSET_UL + || map_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKMAP_UL)); + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, (lit_magic_string_id_t) map_object_p->u.cls.u2.container_id); + + JERRY_ASSERT (entry_p != NULL); + + ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, (lit_magic_string_id_t) map_object_p->u.cls.u2.container_id); +} /* ecma_op_container_remove_weak_entry */ + +/** + * The Create{Set, Map}Iterator Abstract operation + * + * See also: + * ECMA-262 v6, 23.1.5.1 + * ECMA-262 v6, 23.2.5.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return Map/Set iterator object, if success + * error - otherwise + */ +ecma_value_t +ecma_op_container_create_iterator (ecma_value_t this_arg, /**< this argument */ + ecma_builtin_id_t proto_id, /**< prototype builtin id */ + ecma_object_class_type_t iterator_type, /**< iterator type */ + ecma_iterator_kind_t kind) /**< iterator kind */ +{ + return ecma_op_create_iterator_object (this_arg, ecma_builtin_get (proto_id), iterator_type, kind); +} /* ecma_op_container_create_iterator */ + +/** + * Get the index of the iterator object. + * + * @return index of the iterator. + */ +static uint32_t +ecma_op_iterator_get_index (ecma_object_t *iter_obj_p) /**< iterator object pointer */ +{ + uint32_t index = ((ecma_extended_object_t *) iter_obj_p)->u.cls.u2.iterator_index; + + if (JERRY_UNLIKELY (index == ECMA_ITERATOR_INDEX_LIMIT)) + { + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); + ecma_property_t *property_p = ecma_find_named_property (iter_obj_p, prop_name_p); + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + return (uint32_t) (ecma_get_number_from_value (value_p->value)); + } + + return index; +} /* ecma_op_iterator_get_index */ + +/** + * Set the index of the iterator object. + */ +static void +ecma_op_iterator_set_index (ecma_object_t *iter_obj_p, /**< iterator object pointer */ + uint32_t index) /* iterator index to set */ +{ + if (JERRY_UNLIKELY (index >= ECMA_ITERATOR_INDEX_LIMIT)) + { + /* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]] + property is stored as an internal property */ + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); + ecma_property_t *property_p = ecma_find_named_property (iter_obj_p, prop_name_p); + ecma_property_value_t *value_p; + + if (property_p == NULL) + { + value_p = ecma_create_named_data_property (iter_obj_p, prop_name_p, ECMA_PROPERTY_FLAG_WRITABLE, &property_p); + value_p->value = ecma_make_uint32_value (index); + } + else + { + value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + value_p->value = ecma_make_uint32_value (index); + } + } + else + { + ((ecma_extended_object_t *) iter_obj_p)->u.cls.u2.iterator_index = (uint16_t) index; + } +} /* ecma_op_iterator_set_index */ + +/** + * The %{Set, Map}IteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 23.1.5.2.1 + * ECMA-262 v6, 23.2.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +ecma_value_t +ecma_op_container_iterator_next (ecma_value_t this_val, /**< this argument */ + ecma_object_class_type_t iterator_type) /**< type of the iterator */ +{ + if (!ecma_is_value_object (this_val)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_val); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (!ecma_object_class_is (obj_p, iterator_type)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR); + } + + ecma_value_t iterated_value = ext_obj_p->u.cls.u3.iterated_value; + + if (ecma_is_value_empty (iterated_value)) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) (ecma_get_object_from_value (iterated_value)); + lit_magic_string_id_t lit_id = (lit_magic_string_id_t) map_object_p->u.cls.u2.container_id; + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + uint32_t index = ecma_op_iterator_get_index (obj_p); + + if (index == entry_count) + { + ext_obj_p->u.cls.u3.iterated_value = ECMA_VALUE_EMPTY; + + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + uint8_t entry_size = ecma_op_container_entry_size (lit_id); + uint8_t iterator_kind = ext_obj_p->u.cls.u1.iterator_kind; + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + ecma_value_t ret_value = ECMA_VALUE_UNDEFINED; + + for (uint32_t i = index; i < entry_count; i += entry_size) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_is_value_empty (*entry_p)) + { + if (i == (entry_count - entry_size)) + { + ret_value = ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + break; + } + + continue; + } + + ecma_op_iterator_set_index (obj_p, i + entry_size); + + ecma_value_t key_arg = *entry_p; + ecma_value_t value_arg = ecma_op_container_get_value (entry_p, lit_id); + + if (iterator_kind == ECMA_ITERATOR_KEYS) + { + ret_value = ecma_create_iter_result_object (key_arg, ECMA_VALUE_FALSE); + } + else if (iterator_kind == ECMA_ITERATOR_VALUES) + { + ret_value = ecma_create_iter_result_object (value_arg, ECMA_VALUE_FALSE); + } + else + { + JERRY_ASSERT (iterator_kind == ECMA_ITERATOR_ENTRIES); + + ecma_value_t entry_array_value; + entry_array_value = ecma_create_array_from_iter_element (value_arg, key_arg); + + ret_value = ecma_create_iter_result_object (entry_array_value, ECMA_VALUE_FALSE); + ecma_free_value (entry_array_value); + } + + break; + } + + return ret_value; +} /* ecma_op_container_iterator_next */ + +/** + * Dispatcher of builtin container routines. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_container_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); + + if (map_object_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + switch (builtin_routine_id) + { + case ECMA_CONTAINER_ROUTINE_DELETE: + { + return ecma_op_container_delete (map_object_p, arguments_list_p[0], lit_id); + } + case ECMA_CONTAINER_ROUTINE_DELETE_WEAK: + { + return ecma_op_container_delete_weak (map_object_p, arguments_list_p[0], lit_id); + } + case ECMA_CONTAINER_ROUTINE_GET: + { + return ecma_op_container_get (map_object_p, arguments_list_p[0], lit_id); + } + case ECMA_CONTAINER_ROUTINE_SET: + { + return ecma_op_container_set (map_object_p, arguments_list_p[0], arguments_list_p[1], lit_id); + } + case ECMA_CONTAINER_ROUTINE_HAS: + { + return ecma_op_container_has (map_object_p, arguments_list_p[0], lit_id); + } + case ECMA_CONTAINER_ROUTINE_FOREACH: + { + return ecma_op_container_foreach (map_object_p, arguments_list_p[0], arguments_list_p[1], lit_id); + } + case ECMA_CONTAINER_ROUTINE_SIZE_GETTER: + { + return ecma_op_container_size (map_object_p); + } + case ECMA_CONTAINER_ROUTINE_ADD: + { + return ecma_op_container_set (map_object_p, arguments_list_p[0], arguments_list_p[0], lit_id); + } + case ECMA_CONTAINER_ROUTINE_CLEAR: + { + return ecma_op_container_clear (map_object_p); + } + case ECMA_CONTAINER_ROUTINE_KEYS: + case ECMA_CONTAINER_ROUTINE_VALUES: + case ECMA_CONTAINER_ROUTINE_ENTRIES: + { + ecma_builtin_id_t builtin_iterator_prototype = ECMA_BUILTIN_ID_MAP_ITERATOR_PROTOTYPE; + ecma_object_class_type_t iterator_type = ECMA_OBJECT_CLASS_MAP_ITERATOR; + + if (lit_id != LIT_MAGIC_STRING_MAP_UL) + { + builtin_iterator_prototype = ECMA_BUILTIN_ID_SET_ITERATOR_PROTOTYPE; + iterator_type = ECMA_OBJECT_CLASS_SET_ITERATOR; + } + + ecma_iterator_kind_t kind = (ecma_iterator_kind_t) (builtin_routine_id - ECMA_CONTAINER_ROUTINE_KEYS); + + return ecma_op_container_create_iterator (this_arg, builtin_iterator_prototype, iterator_type, kind); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_container_dispatch_routine */ + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.h new file mode 100644 index 00000000..92fc6eb2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.h @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_CONTAINER_OBJECT_H +#define ECMA_CONTAINER_OBJECT_H + +#include "ecma-builtins.h" +#include "ecma-globals.h" + +#if JERRY_BUILTIN_CONTAINER + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmamaphelpers ECMA builtin map/set helper functions + * @{ + */ + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_CONTAINER_ROUTINE_START = 0, + ECMA_CONTAINER_ROUTINE_ADD, + ECMA_CONTAINER_ROUTINE_CLEAR, + ECMA_CONTAINER_ROUTINE_DELETE_WEAK, + ECMA_CONTAINER_ROUTINE_DELETE, + ECMA_CONTAINER_ROUTINE_FOREACH, + ECMA_CONTAINER_ROUTINE_HAS, + ECMA_CONTAINER_ROUTINE_SIZE_GETTER, + ECMA_CONTAINER_ROUTINE_GET, + ECMA_CONTAINER_ROUTINE_SET, + /* Note: These 3 routines MUST be in this order */ + ECMA_CONTAINER_ROUTINE_KEYS, + ECMA_CONTAINER_ROUTINE_VALUES, + ECMA_CONTAINER_ROUTINE_ENTRIES +}; + +uint8_t ecma_op_container_entry_size (lit_magic_string_id_t lit_id); +ecma_extended_object_t *ecma_op_container_get_object (ecma_value_t this_arg, lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_create (const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len, + lit_magic_string_id_t lit_id, + ecma_builtin_id_t proto_id); +ecma_value_t ecma_op_container_size (ecma_extended_object_t *map_object_p); +ecma_value_t +ecma_op_container_get (ecma_extended_object_t *map_object_p, ecma_value_t key_arg, lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_foreach (ecma_extended_object_t *map_object_p, + ecma_value_t predicate, + ecma_value_t predicate_this_arg, + lit_magic_string_id_t lit_id); +ecma_value_t +ecma_op_container_has (ecma_extended_object_t *map_object_p, ecma_value_t key_arg, lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_set (ecma_extended_object_t *map_object_p, + ecma_value_t key_arg, + ecma_value_t value_arg, + lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_clear (ecma_extended_object_t *map_object_p); +ecma_value_t +ecma_op_container_delete (ecma_extended_object_t *map_object_p, ecma_value_t key_arg, lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_delete_weak (ecma_extended_object_t *map_object_p, + ecma_value_t key_arg, + lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_find_weak_value (ecma_object_t *object_p, ecma_value_t key_arg); +void ecma_op_container_remove_weak_entry (ecma_object_t *object_p, ecma_value_t key_arg); +void ecma_op_container_free_entries (ecma_object_t *object_p); +ecma_value_t ecma_op_container_create_iterator (ecma_value_t this_arg, + ecma_builtin_id_t proto_id, + ecma_object_class_type_t iterator_type, + ecma_iterator_kind_t kind); +ecma_value_t ecma_op_container_iterator_next (ecma_value_t this_val, ecma_object_class_type_t iterator_type); +ecma_value_t ecma_builtin_container_dispatch_routine (uint16_t builtin_routine_id, + ecma_value_t this_arg, + const ecma_value_t arguments_list_p[], + lit_magic_string_id_t lit_id); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#endif /* !ECMA_CONTAINER_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.cpp new file mode 100644 index 00000000..68865ba4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.cpp @@ -0,0 +1,1082 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of ECMA-defined conversion routines + */ + +#include "ecma-conversion.h" + +#include + +#include "ecma-alloc.h" +#include "ecma-bigint-object.h" +#include "ecma-bigint.h" +#include "ecma-boolean-object.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-number-object.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" +#include "ecma-symbol-object.h" + +#include "jrt-libc-includes.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaconversion ECMA conversion routines + * @{ + */ + +/** + * RequireObjectCoercible operation. + * + * See also: + * ECMA-262 v11, 7.2.1 + * + * @return true - if the value can be coerced to object without any exceptions + * false - otherwise + */ +bool +ecma_op_require_object_coercible (ecma_value_t value) /**< ecma value */ +{ + ecma_check_value_type_is_spec_defined (value); + + if (ecma_is_value_undefined (value) || ecma_is_value_null (value)) + { + ecma_raise_type_error (ECMA_ERR_ARGUMENT_CANNOT_CONVERT_TO_OBJECT); + return false; + } + + return true; +} /* ecma_op_require_object_coercible */ + +/** + * SameValue operation. + * + * See also: + * ECMA-262 v5, 9.12 + * + * @return true - if the value are same according to ECMA-defined SameValue algorithm, + * false - otherwise + */ +bool +ecma_op_same_value (ecma_value_t x, /**< ecma value */ + ecma_value_t y) /**< ecma value */ +{ + if (x == y) + { + return true; + } + + ecma_type_t type_of_x = ecma_get_value_type_field (x); + + if (type_of_x != ecma_get_value_type_field (y) || type_of_x == ECMA_TYPE_DIRECT) + { + return false; + } + + if (ecma_is_value_number (x)) + { + ecma_number_t x_num = ecma_get_number_from_value (x); + ecma_number_t y_num = ecma_get_number_from_value (y); + + bool is_x_nan = ecma_number_is_nan (x_num); + bool is_y_nan = ecma_number_is_nan (y_num); + + if (is_x_nan || is_y_nan) + { + return is_x_nan && is_y_nan; + } + + if (ecma_number_is_zero (x_num) && ecma_number_is_zero (y_num) + && ecma_number_is_negative (x_num) != ecma_number_is_negative (y_num)) + { + return false; + } + + return (x_num == y_num); + } + + if (ecma_is_value_string (x)) + { + ecma_string_t *x_str_p = ecma_get_string_from_value (x); + ecma_string_t *y_str_p = ecma_get_string_from_value (y); + + return ecma_compare_ecma_strings (x_str_p, y_str_p); + } + +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (x)) + { + return (ecma_is_value_bigint (y) && ecma_bigint_compare_to_bigint (x, y) == 0); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + JERRY_ASSERT (ecma_is_value_object (x) || ecma_is_value_symbol (x)); + + return false; +} /* ecma_op_same_value */ + +#if JERRY_BUILTIN_CONTAINER +/** + * SameValueZero operation. + * + * See also: + * ECMA-262 v6, 7.2.10 + * + * @return true - if the value are same according to ECMA-defined SameValueZero algorithm, + * false - otherwise + */ +bool +ecma_op_same_value_zero (ecma_value_t x, /**< ecma value */ + ecma_value_t y, /**< ecma value */ + bool strict_equality) /**< strict equality */ +{ + if (ecma_is_value_number (x) && ecma_is_value_number (y)) + { + ecma_number_t x_num = ecma_get_number_from_value (x); + ecma_number_t y_num = ecma_get_number_from_value (y); + + bool is_x_nan = ecma_number_is_nan (x_num); + bool is_y_nan = ecma_number_is_nan (y_num); + + if (strict_equality && is_x_nan && is_y_nan) + { + return false; + } + + if (is_x_nan || is_y_nan) + { + return (is_x_nan && is_y_nan); + } + + if (ecma_number_is_zero (x_num) && ecma_number_is_zero (y_num) + && ecma_number_is_negative (x_num) != ecma_number_is_negative (y_num)) + { + return true; + } + + return (x_num == y_num); + } + + return ecma_op_same_value (x, y); +} /* ecma_op_same_value_zero */ +#endif /* JERRY_BUILTIN_CONTAINER */ + +/** + * ToPrimitive operation. + * + * See also: + * ECMA-262 v5, 9.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_to_primitive (ecma_value_t value, /**< ecma value */ + ecma_preferred_type_hint_t preferred_type) /**< preferred type hint */ +{ + ecma_check_value_type_is_spec_defined (value); + + if (ecma_is_value_object (value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + return ecma_op_object_default_value (obj_p, preferred_type); + } + else + { + return ecma_copy_value (value); + } +} /* ecma_op_to_primitive */ + +/** + * ToBoolean operation. Cannot throw an exception. + * + * See also: + * ECMA-262 v5, 9.2 + * + * @return true - if the logical value is true + * false - otherwise + */ +bool +ecma_op_to_boolean (ecma_value_t value) /**< ecma value */ +{ + ecma_check_value_type_is_spec_defined (value); + + if (ecma_is_value_simple (value)) + { + JERRY_ASSERT (ecma_is_value_boolean (value) || ecma_is_value_undefined (value) || ecma_is_value_null (value)); + + return ecma_is_value_true (value); + } + + if (ecma_is_value_integer_number (value)) + { + return (value != ecma_make_integer_value (0)); + } + + if (ecma_is_value_float_number (value)) + { + ecma_number_t num = ecma_get_float_from_value (value); + + return (!ecma_number_is_nan (num) && !ecma_number_is_zero (num)); + } + + if (ecma_is_value_string (value)) + { + ecma_string_t *str_p = ecma_get_string_from_value (value); + + return !ecma_string_is_empty (str_p); + } + +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (value)) + { + return value != ECMA_BIGINT_ZERO; + } +#endif /* JERRY_BUILTIN_BIGINT */ + + JERRY_ASSERT (ecma_is_value_object (value) || ecma_is_value_symbol (value)); + + return true; +} /* ecma_op_to_boolean */ + +/** + * ToNumber operation. + * + * See also: + * ECMA-262 v5, 9.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_to_number (ecma_value_t value, /**< ecma value */ + ecma_number_t *number_p) /**< [out] ecma number */ +{ + return ecma_op_to_numeric (value, number_p, ECMA_TO_NUMERIC_NO_OPTS); +} /* ecma_op_to_number */ + +/** + * Helper to get the numeric value of an ecma value + * + * See also: + * ECMA-262 v11, 7.1.3 + * + * @return ECMA_VALUE_EMPTY if converted to number, BigInt if + * converted to BigInt, and conversion error otherwise + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_to_numeric (ecma_value_t value, /**< ecma value */ + ecma_number_t *number_p, /**< [out] ecma number */ + ecma_to_numeric_options_t options) /**< option bits */ +{ + JERRY_UNUSED (options); + + if (ecma_is_value_integer_number (value)) + { + *number_p = (ecma_number_t) ecma_get_integer_from_value (value); + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_float_number (value)) + { + *number_p = ecma_get_float_from_value (value); + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_string (value)) + { + ecma_string_t *str_p = ecma_get_string_from_value (value); + *number_p = ecma_string_to_number (str_p); + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_undefined (value)) + { + *number_p = ecma_number_make_nan (); + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_null (value)) + { + *number_p = 0; + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_true (value)) + { + *number_p = 1; + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_false (value)) + { + *number_p = 0; + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_symbol (value)) + { + return ecma_raise_type_error (ECMA_ERR_CONVERT_SYMBOL_TO_NUMBER); + } + +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (value)) + { + if (options & ECMA_TO_NUMERIC_ALLOW_BIGINT) + { + return ecma_copy_value (value); + } + return ecma_raise_type_error (ECMA_ERR_CONVERT_BIGINT_TO_NUMBER); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + JERRY_ASSERT (ecma_is_value_object (value)); + + ecma_object_t *object_p = ecma_get_object_from_value (value); + + ecma_value_t def_value = ecma_op_object_default_value (object_p, ECMA_PREFERRED_TYPE_NUMBER); + + if (ECMA_IS_VALUE_ERROR (def_value)) + { + return def_value; + } + + ecma_value_t ret_value = ecma_op_to_numeric (def_value, number_p, options); + + ecma_fast_free_value (def_value); + + return ret_value; +} /* ecma_op_to_numeric */ + +/** + * ToString operation. + * + * See also: + * ECMA-262 v5, 9.8 + * + * @return NULL - if the conversion fails + * pointer to the string descriptor - otherwise + */ +ecma_string_t * +ecma_op_to_string (ecma_value_t value) /**< ecma value */ +{ + ecma_check_value_type_is_spec_defined (value); + + if (ecma_is_value_string (value)) + { + ecma_string_t *res_p = ecma_get_string_from_value (value); + ecma_ref_ecma_string (res_p); + return res_p; + } + + if (ecma_is_value_integer_number (value)) + { + ecma_integer_value_t num = ecma_get_integer_from_value (value); + + if (num < 0) + { + return ecma_new_ecma_string_from_number ((ecma_number_t) num); + } + else + { + return ecma_new_ecma_string_from_uint32 ((uint32_t) num); + } + } + + if (ecma_is_value_float_number (value)) + { + ecma_number_t num = ecma_get_float_from_value (value); + return ecma_new_ecma_string_from_number (num); + } + + if (ecma_is_value_undefined (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED); + } + + if (ecma_is_value_null (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_NULL); + } + + if (ecma_is_value_true (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_TRUE); + } + + if (ecma_is_value_false (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_FALSE); + } + + if (ecma_is_value_symbol (value)) + { + ecma_raise_type_error (ECMA_ERR_CONVERT_SYMBOL_TO_STRING); + return NULL; + } + +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (value)) + { + return ecma_bigint_to_string (value, 10); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + JERRY_ASSERT (ecma_is_value_object (value)); + + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + ecma_value_t def_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_STRING); + + if (ECMA_IS_VALUE_ERROR (def_value)) + { + return NULL; + } + + ecma_string_t *ret_string_p = ecma_op_to_string (def_value); + + ecma_free_value (def_value); + + return ret_string_p; +} /* ecma_op_to_string */ + +/** + * ToPropertyKey operation. + * + * See also: + * ECMA 262 v6, 7.1.14 + * ECMA 262 v10, 7.1.14 + * ECMA 262 v11, 7.1.19 + * + * @return NULL - if the conversion fails + * ecma-string - otherwise + */ +ecma_string_t * +ecma_op_to_property_key (ecma_value_t value) /**< ecma value */ +{ + /* Fast path for strings and symbols */ + if (JERRY_LIKELY (ecma_is_value_prop_name (value))) + { + ecma_string_t *key_p = ecma_get_prop_name_from_value (value); + ecma_ref_ecma_string (key_p); + return key_p; + } + + ecma_value_t key = ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING); + + if (ECMA_IS_VALUE_ERROR (key)) + { + return NULL; + } + + if (ecma_is_value_symbol (key)) + { + ecma_string_t *symbol_p = ecma_get_symbol_from_value (key); + return symbol_p; + } + + ecma_string_t *result = ecma_op_to_string (key); + ecma_free_value (key); + + return result; +} /* ecma_op_to_property_key */ + +/** + * ToObject operation. + * + * See also: + * ECMA-262 v5, 9.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_to_object (ecma_value_t value) /**< ecma value */ +{ + ecma_check_value_type_is_spec_defined (value); + ecma_builtin_id_t proto_id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; + uint8_t class_type; + + if (ecma_is_value_number (value)) + { +#if JERRY_BUILTIN_NUMBER + proto_id = ECMA_BUILTIN_ID_NUMBER_PROTOTYPE; +#endif /* JERRY_BUILTIN_NUMBER */ + class_type = ECMA_OBJECT_CLASS_NUMBER; + } + else if (ecma_is_value_string (value)) + { +#if JERRY_BUILTIN_STRING + proto_id = ECMA_BUILTIN_ID_STRING_PROTOTYPE; +#endif /* JERRY_BUILTIN_STRING */ + class_type = ECMA_OBJECT_CLASS_STRING; + } + else if (ecma_is_value_object (value)) + { + return ecma_copy_value (value); + } + else if (ecma_is_value_symbol (value)) + { + proto_id = ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE; + class_type = ECMA_OBJECT_CLASS_SYMBOL; + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (value)) + { + return ecma_op_create_bigint_object (value); + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + if (ecma_is_value_undefined (value) || ecma_is_value_null (value)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_CANNOT_CONVERT_TO_OBJECT); + } + else + { + JERRY_ASSERT (ecma_is_value_boolean (value)); +#if JERRY_BUILTIN_BOOLEAN + proto_id = ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE; +#endif /* JERRY_BUILTIN_BOOLEAN */ + class_type = ECMA_OBJECT_CLASS_BOOLEAN; + } + } + + ecma_object_t *object_p = + ecma_create_object (ecma_builtin_get (proto_id), sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = class_type; + ext_object_p->u.cls.u3.value = ecma_copy_value_if_not_object (value); + + return ecma_make_object_value (object_p); +} /* ecma_op_to_object */ + +/** + * FromPropertyDescriptor operation. + * + * See also: + * ECMA-262 v5, 8.10.4 + * + * @return constructed object + */ +ecma_object_t * +ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p) /**< property descriptor */ +{ + /* 2. */ + ecma_object_t *obj_p = ecma_op_create_object_object_noarg (); + + ecma_value_t completion; + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + { + prop_desc.flags = (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE + | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE + | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE); + } + + /* 3. */ + if (src_prop_desc_p->flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) + { + JERRY_ASSERT ((prop_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) + == (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)); + + /* a. */ + prop_desc.value = src_prop_desc_p->value; + + completion = ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_VALUE), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + + /* b. */ + prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & JERRY_PROP_IS_WRITABLE); + + completion = + ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + } + else if (src_prop_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + /* a. */ + if (src_prop_desc_p->get_p == NULL) + { + prop_desc.value = ECMA_VALUE_UNDEFINED; + } + else + { + prop_desc.value = ecma_make_object_value (src_prop_desc_p->get_p); + } + + completion = ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_GET), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + + /* b. */ + if (src_prop_desc_p->set_p == NULL) + { + prop_desc.value = ECMA_VALUE_UNDEFINED; + } + else + { + prop_desc.value = ecma_make_object_value (src_prop_desc_p->set_p); + } + + completion = ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_SET), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + } + + prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & JERRY_PROP_IS_ENUMERABLE); + + completion = + ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + + prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE); + + completion = + ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + + return obj_p; +} /* ecma_op_from_property_descriptor */ + +/** + * ToPropertyDescriptor operation. + * + * See also: + * ECMA-262 v5, 8.10.5 + * + * @return ECMA_VALUE_EMPTY if successful, ECMA_VALUE_ERROR otherwise + */ +ecma_value_t +ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ + ecma_property_descriptor_t *out_prop_desc_p) /**< [out] filled property descriptor + * if the operation is successful, + * unmodified otherwise */ +{ + /* 1. */ + if (!ecma_is_value_object (obj_value)) + { + return ecma_raise_type_error (ECMA_ERR_EXPECTED_AN_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + ecma_value_t set_prop_value; + ecma_value_t get_prop_value; + ecma_value_t writable_prop_value; + ecma_value_t value_prop_value; + ecma_value_t configurable_prop_value; + ecma_property_descriptor_t prop_desc; + ecma_value_t enumerable_prop_value; + + /* 3. */ + enumerable_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE)); + + if (ECMA_IS_VALUE_ERROR (enumerable_prop_value)) + { + return enumerable_prop_value; + } + + /* 2. */ + prop_desc = ecma_make_empty_property_descriptor (); + + if (ecma_is_value_found (enumerable_prop_value)) + { + uint32_t is_enumerable = + (ecma_op_to_boolean (enumerable_prop_value) ? JERRY_PROP_IS_ENUMERABLE : JERRY_PROP_NO_OPTS); + + prop_desc.flags |= (uint16_t) (JERRY_PROP_IS_ENUMERABLE_DEFINED | is_enumerable); + + ecma_free_value (enumerable_prop_value); + } + + /* 4. */ + configurable_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE)); + + if (ECMA_IS_VALUE_ERROR (configurable_prop_value)) + { + goto free_desc; + } + + if (ecma_is_value_found (configurable_prop_value)) + { + uint32_t is_configurable = + (ecma_op_to_boolean (configurable_prop_value) ? JERRY_PROP_IS_CONFIGURABLE : JERRY_PROP_NO_OPTS); + + prop_desc.flags |= (uint16_t) (JERRY_PROP_IS_CONFIGURABLE_DEFINED | is_configurable); + + ecma_free_value (configurable_prop_value); + } + + /* 5. */ + value_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_VALUE)); + + if (ECMA_IS_VALUE_ERROR (value_prop_value)) + { + goto free_desc; + } + + if (ecma_is_value_found (value_prop_value)) + { + prop_desc.flags |= JERRY_PROP_IS_VALUE_DEFINED; + prop_desc.value = ecma_copy_value (value_prop_value); + ecma_free_value (value_prop_value); + } + + /* 6. */ + writable_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE)); + + if (ECMA_IS_VALUE_ERROR (writable_prop_value)) + { + goto free_desc; + } + + if (ecma_is_value_found (writable_prop_value)) + { + uint32_t is_writable = (ecma_op_to_boolean (writable_prop_value) ? JERRY_PROP_IS_WRITABLE : JERRY_PROP_NO_OPTS); + + prop_desc.flags |= (uint16_t) (JERRY_PROP_IS_WRITABLE_DEFINED | is_writable); + + ecma_free_value (writable_prop_value); + } + + /* 7. */ + get_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_GET)); + + if (ECMA_IS_VALUE_ERROR (get_prop_value)) + { + goto free_desc; + } + + if (ecma_is_value_found (get_prop_value)) + { + if (!ecma_op_is_callable (get_prop_value) && !ecma_is_value_undefined (get_prop_value)) + { + ecma_free_value (get_prop_value); + ret_value = ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + goto free_desc; + } + + prop_desc.flags |= JERRY_PROP_IS_GET_DEFINED; + + if (ecma_is_value_undefined (get_prop_value)) + { + prop_desc.get_p = NULL; + } + else + { + JERRY_ASSERT (ecma_is_value_object (get_prop_value)); + + ecma_object_t *get_p = ecma_get_object_from_value (get_prop_value); + ecma_ref_object (get_p); + + prop_desc.get_p = get_p; + } + + ecma_free_value (get_prop_value); + } + + /* 8. */ + set_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_SET)); + + if (ECMA_IS_VALUE_ERROR (set_prop_value)) + { + goto free_desc; + } + + if (ecma_is_value_found (set_prop_value)) + { + if (!ecma_op_is_callable (set_prop_value) && !ecma_is_value_undefined (set_prop_value)) + { + ecma_free_value (set_prop_value); + ret_value = ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + goto free_desc; + } + + prop_desc.flags |= JERRY_PROP_IS_SET_DEFINED; + + if (ecma_is_value_undefined (set_prop_value)) + { + prop_desc.set_p = NULL; + } + else + { + JERRY_ASSERT (ecma_is_value_object (set_prop_value)); + + ecma_object_t *set_p = ecma_get_object_from_value (set_prop_value); + ecma_ref_object (set_p); + + prop_desc.set_p = set_p; + } + + ecma_free_value (set_prop_value); + } + + /* 9. */ + if ((prop_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) + && (prop_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED))) + { + ret_value = ecma_raise_type_error (ECMA_ERR_ACCESSOR_WRITABLE); + } + else + { + *out_prop_desc_p = prop_desc; + ret_value = ECMA_VALUE_EMPTY; + } + +free_desc: + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_free_property_descriptor (&prop_desc); + } + + return ret_value; +} /* ecma_op_to_property_descriptor */ + +/** + * IsInteger operation. + * + * See also: + * ECMA-262 v5, 9.4 + * ECMA-262 v6, 7.1.4 + * + * @return true - if the argument is integer + * false - otherwise + */ +bool +ecma_op_is_integer (ecma_number_t num) /**< ecma number */ +{ + if (ecma_number_is_nan (num) || ecma_number_is_infinity (num)) + { + return false; + } + + ecma_number_t floor_fabs = (ecma_number_t) floor (fabs (num)); + ecma_number_t fabs_value = (ecma_number_t) fabs (num); + + return (floor_fabs == fabs_value); +} /* ecma_op_is_integer */ + +/** + * ToInteger operation. + * + * See also: + * ECMA-262 v5, 9.4 + * ECMA-262 v6, 7.1.4 + * + * @return ECMA_VALUE_EMPTY if successful + * conversion error otherwise + */ +ecma_value_t +ecma_op_to_integer (ecma_value_t value, /**< ecma value */ + ecma_number_t *number_p) /**< [out] ecma number */ +{ + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + /* 1 */ + ecma_value_t to_number = ecma_op_to_number (value, number_p); + + /* 2 */ + if (ECMA_IS_VALUE_ERROR (to_number)) + { + return to_number; + } + + ecma_number_t number = *number_p; + + /* 3 */ + if (ecma_number_is_nan (number)) + { + *number_p = ECMA_NUMBER_ZERO; + return ECMA_VALUE_EMPTY; + } + + /* 4 */ + if (ecma_number_is_zero (number) || ecma_number_is_infinity (number)) + { + return ECMA_VALUE_EMPTY; + } + + ecma_number_t floor_fabs = (ecma_number_t) floor (fabs (number)); + /* 5 */ + *number_p = ecma_number_is_negative (number) ? -floor_fabs : floor_fabs; + return ECMA_VALUE_EMPTY; +} /* ecma_op_to_integer */ + +/** + * ToLength operation. + * + * See also: + * ECMA-262 v6, 7.1.15 + * + * @return ECMA_VALUE_EMPTY if successful + * conversion error otherwise + */ +ecma_value_t +ecma_op_to_length (ecma_value_t value, /**< ecma value */ + ecma_length_t *length) /**< [out] ecma number */ +{ + /* 1 */ + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + /* 2 */ + ecma_number_t num; + ecma_value_t length_num = ecma_op_to_integer (value, &num); + + /* 3 */ + if (ECMA_IS_VALUE_ERROR (length_num)) + { + return length_num; + } + + /* 4 */ + if (num <= 0.0f) + { + *length = 0; + return ECMA_VALUE_EMPTY; + } + + /* 5 */ + if (num >= ECMA_NUMBER_MAX_SAFE_INTEGER) + { + *length = (ecma_length_t) ECMA_NUMBER_MAX_SAFE_INTEGER; + return ECMA_VALUE_EMPTY; + } + + /* 6 */ + *length = (ecma_length_t) num; + return ECMA_VALUE_EMPTY; +} /* ecma_op_to_length */ + +/** + * ToIndex operation. + * + * See also: + * ECMA-262 v11, 7.1.22 + * + * @return ECMA_VALUE_EMPTY if successful + * conversion error otherwise + */ +ecma_value_t +ecma_op_to_index (ecma_value_t value, /**< ecma value */ + ecma_number_t *index) /**< [out] ecma number */ +{ + /* 1. */ + if (ecma_is_value_undefined (value)) + { + *index = 0; + return ECMA_VALUE_EMPTY; + } + + /* 2.a */ + ecma_number_t integer_index; + ecma_value_t index_value = ecma_op_to_integer (value, &integer_index); + + if (ECMA_IS_VALUE_ERROR (index_value)) + { + return index_value; + } + + /* 2.b - 2.d */ + if (integer_index < 0.0f || integer_index > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_OR_OUT_OF_RANGE_INDEX); + } + + /* 3. */ + *index = integer_index; + return ECMA_VALUE_EMPTY; +} /* ecma_op_to_index */ + +/** + * CreateListFromArrayLike operation. + * Different types are not handled yet. + * + * See also: + * ECMA-262 v6, 7.3.17 + * + * @return ecma_collection_t if successful + * NULL otherwise + */ +ecma_collection_t * +ecma_op_create_list_from_array_like (ecma_value_t arr, /**< array value */ + bool prop_names_only) /**< true - accept only property names + false - otherwise */ +{ + /* 1. */ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (arr)); + + /* 3. */ + if (!ecma_is_value_object (arr)) + { + ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + return NULL; + } + ecma_object_t *obj_p = ecma_get_object_from_value (arr); + + /* 4. 5. */ + ecma_length_t len; + if (ECMA_IS_VALUE_ERROR (ecma_op_object_get_length (obj_p, &len))) + { + return NULL; + } + + /* 6. */ + ecma_collection_t *list_ptr = ecma_new_collection (); + + /* 7. 8. */ + for (ecma_length_t idx = 0; idx < len; idx++) + { + ecma_value_t next = ecma_op_object_get_by_index (obj_p, idx); + if (ECMA_IS_VALUE_ERROR (next)) + { + ecma_collection_free (list_ptr); + return NULL; + } + + if (prop_names_only && !ecma_is_value_prop_name (next)) + { + ecma_free_value (next); + ecma_collection_free (list_ptr); + ecma_raise_type_error (ECMA_ERR_PROPERTY_NAME_IS_NEITHER_SYMBOL_NOR_STRING); + return NULL; + } + + ecma_collection_push_back (list_ptr, next); + } + + /* 9. */ + return list_ptr; +} /* ecma_op_create_list_from_array_like */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.h new file mode 100644 index 00000000..a19ade54 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.h @@ -0,0 +1,76 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_CONVERSION_H +#define ECMA_CONVERSION_H + +#include "ecma-builtins.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaconversion ECMA conversion routines + * @{ + */ + +/** + * Second argument of 'ToPrimitive' operation that is a hint, + * specifying the preferred type of conversion result. + */ +typedef enum +{ + ECMA_PREFERRED_TYPE_NO = 0, /**< no preferred type is specified */ + ECMA_PREFERRED_TYPE_NUMBER, /**< Number */ + ECMA_PREFERRED_TYPE_STRING /**< String */ +} ecma_preferred_type_hint_t; + +/** + * Option bits for ecma_op_to_numeric. + */ +typedef enum +{ + ECMA_TO_NUMERIC_NO_OPTS = 0, /**< no options (same as toNumber operation) */ + ECMA_TO_NUMERIC_ALLOW_BIGINT = (1 << 0), /**< allow BigInt values (ignored if BigInts are disabled) */ +} ecma_to_numeric_options_t; + +bool ecma_op_require_object_coercible (ecma_value_t value); +bool ecma_op_same_value (ecma_value_t x, ecma_value_t y); +#if JERRY_BUILTIN_CONTAINER +bool ecma_op_same_value_zero (ecma_value_t x, ecma_value_t y, bool strict_equality); +#endif /* JERRY_BUILTIN_CONTAINER */ +ecma_value_t ecma_op_to_primitive (ecma_value_t value, ecma_preferred_type_hint_t preferred_type); +bool ecma_op_to_boolean (ecma_value_t value); +ecma_value_t ecma_op_to_number (ecma_value_t value, ecma_number_t *number_p); +ecma_value_t ecma_op_to_numeric (ecma_value_t value, ecma_number_t *number_p, ecma_to_numeric_options_t options); +ecma_string_t *ecma_op_to_string (ecma_value_t value); +ecma_string_t *ecma_op_to_property_key (ecma_value_t value); +ecma_value_t ecma_op_to_object (ecma_value_t value); +bool ecma_op_is_integer (ecma_number_t value); +ecma_value_t ecma_op_to_integer (ecma_value_t value, ecma_number_t *number_p); +ecma_value_t ecma_op_to_length (ecma_value_t value, ecma_length_t *length); +ecma_value_t ecma_op_to_index (ecma_value_t value, ecma_number_t *index); +ecma_collection_t *ecma_op_create_list_from_array_like (ecma_value_t arr, bool prop_names_only); + +ecma_object_t *ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p); +ecma_value_t ecma_op_to_property_descriptor (ecma_value_t obj_value, ecma_property_descriptor_t *out_prop_desc_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_CONVERSION_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.cpp new file mode 100644 index 00000000..db2ae0a6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.cpp @@ -0,0 +1,409 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-dataview-object.h" + +#include "ecma-arraybuffer-object.h" +#include "ecma-bigint.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-shared-arraybuffer-object.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_DATAVIEW + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmadataviewobject ECMA builtin DataView helper functions + * @{ + */ + +/** + * Handle calling [[Construct]] of built-in DataView like objects + * + * See also: + * ECMA-262 v11, 24.3.2.1 + * + * @return created DataView object as an ecma-value - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_dataview_create (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p)); + + ecma_value_t buffer = arguments_list_len > 0 ? arguments_list_p[0] : ECMA_VALUE_UNDEFINED; + + /* 2. */ + if (!ecma_is_value_object (buffer)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_BUFFER_NOT_OBJECT); + } + + ecma_object_t *buffer_p = ecma_get_object_from_value (buffer); + + if (!(ecma_object_class_is (buffer_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (buffer_p))) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_BUFFER_NOT_ARRAY_OR_SHARED_BUFFER); + } + + /* 3. */ + ecma_number_t offset = 0; + + if (arguments_list_len > 1) + { + ecma_value_t offset_value = ecma_op_to_index (arguments_list_p[1], &offset); + if (ECMA_IS_VALUE_ERROR (offset_value)) + { + return offset_value; + } + } + + /* 4. */ + if (ecma_arraybuffer_is_detached (buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* 5. */ + ecma_number_t buffer_byte_length = ecma_arraybuffer_get_length (buffer_p); + + /* 6. */ + if (offset > buffer_byte_length) + { + return ecma_raise_range_error (ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER); + } + + /* 7. */ + uint32_t view_byte_length; + if (arguments_list_len > 2 && !ecma_is_value_undefined (arguments_list_p[2])) + { + /* 8.a */ + ecma_number_t byte_length_to_index; + ecma_value_t byte_length_value = ecma_op_to_index (arguments_list_p[2], &byte_length_to_index); + + if (ECMA_IS_VALUE_ERROR (byte_length_value)) + { + return byte_length_value; + } + + /* 8.b */ + if (offset + byte_length_to_index > buffer_byte_length) + { + return ecma_raise_range_error (ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER); + } + + JERRY_ASSERT (byte_length_to_index <= UINT32_MAX); + view_byte_length = (uint32_t) byte_length_to_index; + } + else + { + /* 7.a */ + view_byte_length = (uint32_t) (buffer_byte_length - offset); + } + + /* 9. */ + ecma_object_t *prototype_obj_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE); + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 10. */ + if (ecma_arraybuffer_is_detached (buffer_p)) + { + ecma_deref_object (prototype_obj_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* 9. */ + /* It must happen after 10., because uninitialized object can't be destroyed properly. */ + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_dataview_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_deref_object (prototype_obj_p); + + /* 11 - 14. */ + ecma_dataview_object_t *dataview_obj_p = (ecma_dataview_object_t *) object_p; + dataview_obj_p->header.u.cls.type = ECMA_OBJECT_CLASS_DATAVIEW; + dataview_obj_p->header.u.cls.u3.length = view_byte_length; + dataview_obj_p->buffer_p = buffer_p; + dataview_obj_p->byte_offset = (uint32_t) offset; + + return ecma_make_object_value (object_p); +} /* ecma_op_dataview_create */ + +/** + * Get the DataView object pointer + * + * Note: + * If the function returns with NULL, the error object has + * already set, and the caller must return with ECMA_VALUE_ERROR + * + * @return pointer to the dataView if this_arg is a valid dataView object + * NULL otherwise + */ +ecma_dataview_object_t * +ecma_op_dataview_get_object (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_DATAVIEW)) + { + return (ecma_dataview_object_t *) object_p; + } + } + + ecma_raise_type_error (ECMA_ERR_EXPECTED_A_DATAVIEW_OBJECT); + return NULL; +} /* ecma_op_dataview_get_object */ + +/** + * Helper union to specify the system's endiannes + */ +typedef union +{ + uint32_t number; /**< for write numeric data */ + char data[sizeof (uint32_t)]; /**< for read numeric data */ +} ecma_dataview_endiannes_check_t; + +/** + * Helper function to check the current system endiannes + * + * @return true - if the current system has little endian byteorder + * false - otherwise + */ +static bool +ecma_dataview_check_little_endian (void) +{ + ecma_dataview_endiannes_check_t checker; + checker.number = 0x01; + + return checker.data[0] == 0x01; +} /* ecma_dataview_check_little_endian */ + +/** + * Helper function for swap bytes if the system's endiannes + * does not match with the requested endiannes. + */ +static void +ecma_dataview_swap_order (bool system_is_little_endian, /**< true - if the system has little endian byteorder + * false - otherwise */ + bool is_little_endian, /**< true - if little endian byteorder is requested + * false - otherwise */ + uint32_t element_size, /**< element size byte according to the Table 49.*/ + lit_utf8_byte_t *block_p) /**< data block */ +{ + if (system_is_little_endian ^ is_little_endian) + { + for (uint32_t i = 0; i < element_size / 2; i++) + { + lit_utf8_byte_t tmp = block_p[i]; + block_p[i] = block_p[element_size - i - 1]; + block_p[element_size - i - 1] = tmp; + } + } +} /* ecma_dataview_swap_order */ + +/** + * GetViewValue and SetViewValue abstact operation + * + * See also: + * ECMA-262 v11, 24.3.1.1 + * ECMA-262 v11, 24.3.1.2 + * + * @return ecma value + */ +ecma_value_t +ecma_op_dataview_get_set_view_value (ecma_value_t view, /**< the operation's 'view' argument */ + ecma_value_t request_index, /**< the operation's 'requestIndex' argument */ + ecma_value_t is_little_endian_value, /**< the operation's + * 'isLittleEndian' argument */ + ecma_value_t value_to_set, /**< the operation's 'value' argument */ + ecma_typedarray_type_t id) /**< the operation's 'type' argument */ +{ + /* 1 - 2. */ + ecma_dataview_object_t *view_p = ecma_op_dataview_get_object (view); + + if (JERRY_UNLIKELY (view_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *buffer_p = view_p->buffer_p; + JERRY_ASSERT (ecma_object_class_is (buffer_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (buffer_p)); + + /* 3. */ + ecma_number_t get_index; + ecma_value_t number_index_value = ecma_op_to_index (request_index, &get_index); + + if (ECMA_IS_VALUE_ERROR (number_index_value)) + { + return number_index_value; + } + + /* SetViewValue 4 - 5. */ + if (!ecma_is_value_empty (value_to_set)) + { +#if JERRY_BUILTIN_BIGINT + if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (id)) + { + value_to_set = ecma_bigint_to_bigint (value_to_set, true); + + if (ECMA_IS_VALUE_ERROR (value_to_set)) + { + return value_to_set; + } + } + else +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_number_t value_to_set_number; + ecma_value_t value = ecma_op_to_number (value_to_set, &value_to_set_number); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + value_to_set = ecma_make_number_value (value_to_set_number); + } + } + + /* GetViewValue 4., SetViewValue 6. */ + bool is_little_endian = ecma_op_to_boolean (is_little_endian_value); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (buffer_p)) + { + ecma_free_value (value_to_set); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (buffer_p)) + { + ecma_free_value (value_to_set); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* GetViewValue 7., SetViewValue 9. */ + uint32_t view_offset = view_p->byte_offset; + + /* GetViewValue 8., SetViewValue 10. */ + uint32_t view_size = view_p->header.u.cls.u3.length; + + /* GetViewValue 9., SetViewValue 11. */ + uint8_t element_size = (uint8_t) (1 << (ecma_typedarray_helper_get_shift_size (id))); + + /* GetViewValue 10., SetViewValue 12. */ + if (get_index + element_size > (ecma_number_t) view_size) + { + ecma_free_value (value_to_set); + return ecma_raise_range_error (ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER); + } + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (buffer_p)) + { + ecma_free_value (value_to_set); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (buffer_p)) + { + ecma_free_value (value_to_set); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* GetViewValue 11., SetViewValue 13. */ + bool system_is_little_endian = ecma_dataview_check_little_endian (); + + ecma_typedarray_info_t info; + info.id = id; + info.length = view_size; + info.shift = ecma_typedarray_helper_get_shift_size (id); + info.element_size = element_size; + info.offset = view_p->byte_offset; + info.array_buffer_p = buffer_p; + + /* GetViewValue 12. */ + uint8_t *block_p = ecma_arraybuffer_get_buffer (buffer_p) + (uint32_t) get_index + view_offset; + + if (ecma_is_value_empty (value_to_set)) + { + JERRY_VLA (lit_utf8_byte_t, swap_block_p, element_size); + memcpy (swap_block_p, block_p, element_size * sizeof (lit_utf8_byte_t)); + ecma_dataview_swap_order (system_is_little_endian, is_little_endian, element_size, swap_block_p); + + ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info.id); + return typedarray_getter_cb (swap_block_p); + } + + if (!ecma_number_is_nan (get_index) && get_index <= 0) + { + get_index = 0; + } + + /* SetViewValue 14. */ + ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (info.id); + ecma_value_t set_element = typedarray_setter_cb (block_p, value_to_set); + + ecma_free_value (value_to_set); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + return set_element; + } + + ecma_dataview_swap_order (system_is_little_endian, is_little_endian, element_size, block_p); + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_dataview_get_set_view_value */ + +/** + * Check if the value is dataview + * + * @return true - if value is a DataView object + * false - otherwise + */ +bool +ecma_is_dataview (ecma_value_t value) /**< the target need to be checked */ +{ + if (!ecma_is_value_object (value)) + { + return false; + } + + return ecma_object_class_is (ecma_get_object_from_value (value), ECMA_OBJECT_CLASS_DATAVIEW); +} /* ecma_is_dataview */ + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATAVIEW */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.h new file mode 100644 index 00000000..1d56c9be --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.h @@ -0,0 +1,46 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_DATAVIEW_OBJECT_H +#define ECMA_DATAVIEW_OBJECT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_DATAVIEW + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmadataviewobject ECMA builtin DataView helper functions + * @{ + */ + +ecma_value_t ecma_op_dataview_create (const ecma_value_t *arguments_list_p, uint32_t arguments_list_len); +ecma_dataview_object_t *ecma_op_dataview_get_object (ecma_value_t this_arg); +ecma_value_t ecma_op_dataview_get_set_view_value (ecma_value_t view, + ecma_value_t request_index, + ecma_value_t little_endian, + ecma_value_t value_to_set, + ecma_typedarray_type_t id); +bool ecma_is_dataview (ecma_value_t value); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATAVIEW */ + +#endif /* !ECMA_DATAVIEW_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.cpp new file mode 100644 index 00000000..ac8e2c40 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.cpp @@ -0,0 +1,100 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-eval.h" + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" + +#include "jcontext.h" +#include "js-parser.h" +#include "vm.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup eval eval + * @{ + */ + +/** + * Perform 'eval' with code stored in ecma-string + * + * See also: + * ecma_op_eval_chars_buffer + * ECMA-262 v5, 15.1.2.1 (steps 2 to 8) + * + * @return ecma value + */ +ecma_value_t +ecma_op_eval (ecma_value_t source_code, /**< source code */ + uint32_t parse_opts) /**< ecma_parse_opts_t option bits */ +{ + JERRY_ASSERT (ecma_is_value_string (source_code)); + + if (ecma_is_value_magic_string (source_code, LIT_MAGIC_STRING__EMPTY)) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_op_eval_chars_buffer ((void *) &source_code, parse_opts | ECMA_PARSE_HAS_SOURCE_VALUE); +} /* ecma_op_eval */ + +/** + * Perform 'eval' with code stored in continuous character buffer + * + * See also: + * ecma_op_eval + * ECMA-262 v5, 15.1.2.1 (steps 2 to 8) + * + * @return ecma value + */ +ecma_value_t +ecma_op_eval_chars_buffer (void *source_p, /**< source code */ + uint32_t parse_opts) /**< ecma_parse_opts_t option bits */ +{ +#if JERRY_PARSER + JERRY_ASSERT (source_p != NULL); + + uint32_t is_strict_call = ECMA_PARSE_STRICT_MODE | ECMA_PARSE_DIRECT_EVAL; + + if ((parse_opts & is_strict_call) != is_strict_call) + { + parse_opts &= (uint32_t) ~ECMA_PARSE_STRICT_MODE; + } + + parse_opts |= ECMA_PARSE_EVAL; + + ECMA_CLEAR_LOCAL_PARSE_OPTS (); + + ecma_compiled_code_t *bytecode_p = parser_parse_script (source_p, parse_opts, NULL); + + if (JERRY_UNLIKELY (bytecode_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + return vm_run_eval (bytecode_p, parse_opts); +#endif /* JERRY_PARSER */ +} /* ecma_op_eval_chars_buffer */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.h new file mode 100644 index 00000000..c06ad5d5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_EVAL_H +#define ECMA_EVAL_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup eval eval + * @{ + */ + +ecma_value_t ecma_op_eval (ecma_value_t source_code, uint32_t parse_opts); + +ecma_value_t ecma_op_eval_chars_buffer (void *source_p, uint32_t parse_opts); + +/** + * @} + * @} + */ + +#endif /* !ECMA_EVAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.cpp new file mode 100644 index 00000000..675aaf92 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.cpp @@ -0,0 +1,520 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-exceptions.h" + +#include + +#include "ecma-array-object.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-symbol-object.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_LINE_INFO +#include "vm.h" +#endif /* JERRY_LINE_INFO */ + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup exceptions Exceptions + * @{ + */ + +/** + * Standard ecma-error object constructor. + * + * Note: + * message_string_p can be NULL. + * + * Note: + * calling with JERRY_ERROR_NONE does not make sense thus it will + * cause a fault in the system. + * + * @return pointer to ecma-object representing specified error + * with reference counter set to one. + */ +ecma_object_t * +ecma_new_standard_error (jerry_error_t error_type, /**< native error type */ + ecma_string_t *message_string_p) /**< message string */ +{ +#if JERRY_BUILTIN_ERRORS + ecma_builtin_id_t prototype_id = ECMA_BUILTIN_ID__COUNT; + + switch (error_type) + { + case JERRY_ERROR_EVAL: + { + prototype_id = ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_RANGE: + { + prototype_id = ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_REFERENCE: + { + prototype_id = ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_TYPE: + { + prototype_id = ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_AGGREGATE: + { + prototype_id = ECMA_BUILTIN_ID_AGGREGATE_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_URI: + { + prototype_id = ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_SYNTAX: + { + prototype_id = ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE; + break; + } + + default: + { + JERRY_ASSERT (error_type == JERRY_ERROR_COMMON); + + prototype_id = ECMA_BUILTIN_ID_ERROR_PROTOTYPE; + break; + } + } +#else /* !JERRY_BUILTIN_ERRORS */ + JERRY_UNUSED (error_type); + ecma_builtin_id_t prototype_id = ECMA_BUILTIN_ID_ERROR_PROTOTYPE; +#endif /* JERRY_BUILTIN_ERRORS */ + + ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id); + + ecma_object_t *error_object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) error_object_p; + extended_object_p->u.cls.type = ECMA_OBJECT_CLASS_ERROR; + extended_object_p->u.cls.u1.error_type = (uint8_t) error_type; + + if (message_string_p != NULL) + { + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (error_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE), + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + + ecma_ref_ecma_string (message_string_p); + prop_value_p->value = ecma_make_string_value (message_string_p); + } + + /* Avoid calling the decorator function recursively. */ + if (JERRY_CONTEXT (error_object_created_callback_p) != NULL + && !(JERRY_CONTEXT (status_flags) & ECMA_STATUS_ERROR_UPDATE)) + { + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_ERROR_UPDATE; + JERRY_CONTEXT (error_object_created_callback_p) + (ecma_make_object_value (error_object_p), JERRY_CONTEXT (error_object_created_callback_user_p)); + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_ERROR_UPDATE; + } + else + { +#if JERRY_LINE_INFO + /* Default decorator when line info is enabled. */ + ecma_string_t *stack_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_STACK); + + ecma_property_value_t *prop_value_p = + ecma_create_named_data_property (error_object_p, stack_str_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE, NULL); + ecma_deref_ecma_string (stack_str_p); + + ecma_value_t backtrace_value = vm_get_backtrace (0); + + prop_value_p->value = backtrace_value; + ecma_deref_object (ecma_get_object_from_value (backtrace_value)); +#endif /* JERRY_LINE_INFO */ + } + + return error_object_p; +} /* ecma_new_standard_error */ + +/** + * aggregate-error object constructor. + * + * @return newly constructed aggregate errors + */ +ecma_value_t +ecma_new_aggregate_error (ecma_value_t error_list_val, /**< errors list */ + ecma_value_t message_val) /**< message string */ +{ + ecma_object_t *new_error_object_p; + + if (!ecma_is_value_undefined (message_val)) + { + ecma_string_t *message_string_p = ecma_op_to_string (message_val); + + if (JERRY_UNLIKELY (message_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + new_error_object_p = ecma_new_standard_error (JERRY_ERROR_AGGREGATE, message_string_p); + ecma_deref_ecma_string (message_string_p); + } + else + { + new_error_object_p = ecma_new_standard_error (JERRY_ERROR_AGGREGATE, NULL); + } + + ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (error_list_val, LIT_GLOBAL_SYMBOL_ITERATOR); + + if (ECMA_IS_VALUE_ERROR (using_iterator)) + { + ecma_deref_object (new_error_object_p); + return using_iterator; + } + + if (!ecma_is_value_undefined (using_iterator)) + { + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (error_list_val, using_iterator, &next_method); + ecma_free_value (using_iterator); + + if (ECMA_IS_VALUE_ERROR (iterator)) + { + ecma_deref_object (new_error_object_p); + return iterator; + } + + ecma_collection_t *error_list_p = ecma_new_collection (); + ecma_value_t result = ECMA_VALUE_ERROR; + + while (true) + { + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (next)) + { + break; + } + + if (next == ECMA_VALUE_FALSE) + { + result = ECMA_VALUE_UNDEFINED; + break; + } + + /* 8.e.iii */ + ecma_value_t next_error = ecma_op_iterator_value (next); + ecma_free_value (next); + + if (ECMA_IS_VALUE_ERROR (next_error)) + { + break; + } + + ecma_collection_push_back (error_list_p, next_error); + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_collection_free (error_list_p); + ecma_deref_object (new_error_object_p); + return result; + } + + JERRY_ASSERT (ecma_is_value_undefined (result)); + + ecma_value_t error_list_arr = ecma_op_new_array_object_from_collection (error_list_p, true); + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (new_error_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_ERRORS_UL), + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + prop_value_p->value = error_list_arr; + ecma_free_value (error_list_arr); + } + + return ecma_make_object_value (new_error_object_p); +} /* ecma_new_aggregate_error */ + +/** + * Return the error type for an Error object. + * + * @return one of the jerry_error_t value + * if it is not an Error object then JERRY_ERROR_NONE will be returned + */ +jerry_error_t +ecma_get_error_type (ecma_object_t *error_object_p) /**< possible error object */ +{ + if (!ecma_object_class_is (error_object_p, ECMA_OBJECT_CLASS_ERROR)) + { + return JERRY_ERROR_NONE; + } + + return (jerry_error_t) ((ecma_extended_object_t *) error_object_p)->u.cls.u1.error_type; +} /* ecma_get_error_type */ + +/** + * Raise a standard ecma-error with the given type and message. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_standard_error (jerry_error_t error_type, /**< error type */ + ecma_error_msg_t msg) /**< error message */ +{ + ecma_object_t *error_obj_p; + const lit_utf8_byte_t *str_p = (lit_utf8_byte_t *) ecma_get_error_msg (msg); + + if (msg != ECMA_ERR_EMPTY) + { + ecma_string_t *error_msg_p = ecma_new_ecma_external_string_from_cesu8 (str_p, ecma_get_error_size (msg), NULL); + error_obj_p = ecma_new_standard_error (error_type, error_msg_p); + ecma_deref_ecma_string (error_msg_p); + } + else + { + error_obj_p = ecma_new_standard_error (error_type, NULL); + } + + jcontext_raise_exception (ecma_make_object_value (error_obj_p)); + return ECMA_VALUE_ERROR; +} /* ecma_raise_standard_error */ + +#if JERRY_ERROR_MESSAGES + +/** + * Raise a standard ecma-error with the given format string and arguments. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_standard_error_with_format (jerry_error_t error_type, /**< error type */ + const char *format, /**< format string */ + ...) /**< ecma-values */ +{ + JERRY_ASSERT (format != NULL); + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + const char *start_p = format; + const char *end_p = format; + + va_list args; + + va_start (args, format); + + while (*end_p) + { + if (*end_p == '%') + { + /* Concat template string. */ + if (end_p > start_p) + { + ecma_stringbuilder_append_raw (&builder, (lit_utf8_byte_t *) start_p, (lit_utf8_size_t) (end_p - start_p)); + } + + /* Convert an argument to string without side effects. */ + ecma_string_t *arg_string_p; + const ecma_value_t arg_val = va_arg (args, ecma_value_t); + + if (JERRY_UNLIKELY (ecma_is_value_object (arg_val))) + { + ecma_object_t *arg_object_p = ecma_get_object_from_value (arg_val); + lit_magic_string_id_t class_name = ecma_object_get_class_name (arg_object_p); + arg_string_p = ecma_get_magic_string (class_name); + } + else if (ecma_is_value_symbol (arg_val)) + { + ecma_value_t symbol_desc_value = ecma_get_symbol_descriptive_string (arg_val); + arg_string_p = ecma_get_string_from_value (symbol_desc_value); + } + else + { + arg_string_p = ecma_op_to_string (arg_val); + JERRY_ASSERT (arg_string_p != NULL); + } + + /* Concat argument. */ + ecma_stringbuilder_append (&builder, arg_string_p); + + ecma_deref_ecma_string (arg_string_p); + + start_p = end_p + 1; + } + + end_p++; + } + + va_end (args); + + /* Concat reset of template string. */ + if (start_p < end_p) + { + ecma_stringbuilder_append_raw (&builder, (lit_utf8_byte_t *) start_p, (lit_utf8_size_t) (end_p - start_p)); + } + + ecma_string_t *builder_str_p = ecma_stringbuilder_finalize (&builder); + + ecma_object_t *error_obj_p = ecma_new_standard_error (error_type, builder_str_p); + + ecma_deref_ecma_string (builder_str_p); + + jcontext_raise_exception (ecma_make_object_value (error_obj_p)); + return ECMA_VALUE_ERROR; +} /* ecma_raise_standard_error_with_format */ + +#endif /* JERRY_ERROR_MESSAGES */ + +/** + * Raise a common error with the given message. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_common_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_COMMON, msg); +} /* ecma_raise_common_error */ + +/** + * Raise a RangeError with the given message. + * + * See also: ECMA-262 v5, 15.11.6.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_range_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_RANGE, msg); +} /* ecma_raise_range_error */ + +/** + * Raise a ReferenceError with the given message. + * + * See also: ECMA-262 v5, 15.11.6.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_reference_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_REFERENCE, msg); +} /* ecma_raise_reference_error */ + +/** + * Raise a SyntaxError with the given message. + * + * See also: ECMA-262 v5, 15.11.6.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_syntax_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_SYNTAX, msg); +} /* ecma_raise_syntax_error */ + +/** + * Raise a TypeError with the given message. + * + * See also: ECMA-262 v5, 15.11.6.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_type_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_TYPE, msg); +} /* ecma_raise_type_error */ + +/** + * Raise a URIError with the given message. + * + * See also: ECMA-262 v5, 15.11.6.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_uri_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_URI, msg); +} /* ecma_raise_uri_error */ + +#if (JERRY_STACK_LIMIT != 0) +/** + * Raise a RangeError with "Maximum call stack size exceeded" message. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_maximum_callstack_error (void) +{ + return ecma_raise_range_error (ECMA_ERR_MAXIMUM_CALL_STACK_SIZE_EXCEEDED); +} /* ecma_raise_maximum_callstack_error */ +#endif /* (JERRY_STACK_LIMIT != 0) */ + +/** + * Raise a AggregateError with the given errors and message. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_aggregate_error (ecma_value_t error_list_val, /**< errors list */ + ecma_value_t message_val) /**< error message */ +{ + ecma_value_t aggre_val = ecma_new_aggregate_error (error_list_val, message_val); + jcontext_raise_exception (aggre_val); + + return ECMA_VALUE_ERROR; +} /* ecma_raise_aggregate_error */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.h new file mode 100644 index 00000000..c367a6bf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.h @@ -0,0 +1,53 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_EXCEPTIONS_H +#define ECMA_EXCEPTIONS_H + +#include "ecma-globals.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup exceptions Exceptions + * @{ + */ + +jerry_error_t ecma_get_error_type (ecma_object_t *error_object_p); +ecma_object_t *ecma_new_standard_error (jerry_error_t error_type, ecma_string_t *message_string_p); +#if JERRY_ERROR_MESSAGES +ecma_value_t ecma_raise_standard_error_with_format (jerry_error_t error_type, const char *msg_p, ...); +#endif /* JERRY_ERROR_MESSAGES */ +ecma_value_t ecma_raise_standard_error (jerry_error_t error_type, ecma_error_msg_t msg); +ecma_value_t ecma_raise_common_error (ecma_error_msg_t msg); +ecma_value_t ecma_raise_range_error (ecma_error_msg_t msg); +ecma_value_t ecma_raise_reference_error (ecma_error_msg_t msg); +ecma_value_t ecma_raise_syntax_error (ecma_error_msg_t msg); +ecma_value_t ecma_raise_type_error (ecma_error_msg_t msg); +ecma_value_t ecma_raise_uri_error (ecma_error_msg_t msg); +#if (JERRY_STACK_LIMIT != 0) +ecma_value_t ecma_raise_maximum_callstack_error (void); +#endif /* (JERRY_STACK_LIMIT != 0) */ +ecma_value_t ecma_new_aggregate_error (ecma_value_t error_list_val, ecma_value_t message_val); +ecma_value_t ecma_raise_aggregate_error (ecma_value_t error_list_val, ecma_value_t message_val); + +/** + * @} + * @} + */ + +#endif /* !ECMA_EXCEPTIONS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.cpp new file mode 100644 index 00000000..2dde89e6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.cpp @@ -0,0 +1,2208 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-function-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtin-handlers.h" +#include "ecma-builtin-helpers.h" +#include "ecma-errors.h" +#include "ecma-exceptions.h" +#include "ecma-extended-info.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" +#include "ecma-proxy-object.h" +#include "ecma-symbol-object.h" + +#include "jcontext.h" +#include "lit-char-helpers.h" +#include "opcodes.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmafunctionobject ECMA Function object related routines + * @{ + */ + +/** + * SetFunctionName operation + * + * See also: ECMAScript v6, 9.2.1.1 + * + * @return source name as ecma-string + */ +ecma_value_t +ecma_op_function_form_name (ecma_string_t *prop_name_p, /**< property name */ + char *prefix_p, /**< prefix */ + lit_utf8_size_t prefix_size) /**< prefix length */ +{ + /* 4. */ + if (ecma_prop_name_is_symbol (prop_name_p)) + { + /* .a */ + ecma_value_t string_desc = ecma_get_symbol_description (prop_name_p); + + /* .b */ + if (ecma_is_value_undefined (string_desc)) + { + prop_name_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + /* .c */ + else + { + ecma_string_t *string_desc_p = ecma_get_string_from_value (string_desc); + ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) "[", 1); + ecma_stringbuilder_append (&builder, string_desc_p); + ecma_stringbuilder_append_byte (&builder, (lit_utf8_byte_t) LIT_CHAR_RIGHT_SQUARE); + prop_name_p = ecma_stringbuilder_finalize (&builder); + } + } + else + { + ecma_ref_ecma_string (prop_name_p); + } + + /* 5. */ + if (JERRY_UNLIKELY (prefix_p != NULL)) + { + ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) prefix_p, prefix_size); + ecma_stringbuilder_append (&builder, prop_name_p); + ecma_deref_ecma_string (prop_name_p); + prop_name_p = ecma_stringbuilder_finalize (&builder); + } + + return ecma_make_string_value (prop_name_p); +} /* ecma_op_function_form_name */ + +#if JERRY_BUILTIN_PROXY +/** + * IsCallable operation for proxy object. + * + * @return true - if the given proxy object is callable; + * false - otherwise + */ +bool +ecma_op_proxy_object_is_callable (ecma_object_t *obj_p) /**< ecma object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + + return (obj_p->u2.prototype_cp & ECMA_PROXY_IS_CALLABLE) != 0; +} /* ecma_op_proxy_object_is_callable */ +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * IsCallable operation. + * + * See also: ECMA-262 v5, 9.11 + * + * @return true - if the given object is callable; + * false - otherwise + */ +bool +ecma_op_object_is_callable (ecma_object_t *obj_p) /**< ecma object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + + const ecma_object_type_t type = ecma_get_object_type (obj_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_TYPE_IS_PROXY (type)) + { + return ecma_op_proxy_object_is_callable (obj_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return type >= ECMA_OBJECT_TYPE_FUNCTION; +} /* ecma_op_object_is_callable */ + +/** + * IsCallable operation. + * + * See also: ECMA-262 v5, 9.11 + * + * @return true - if value is callable object; + * false - otherwise + */ +bool +ecma_op_is_callable (ecma_value_t value) /**< ecma value */ +{ + return (ecma_is_value_object (value) && ecma_op_object_is_callable (ecma_get_object_from_value (value))); +} /* ecma_op_is_callable */ + +/** + * Implement IsConstructor abstract operation. + * + * + * @return ECMA_IS_VALID_CONSTRUCTOR - if object is a valid for constructor call + * ecma_error_msg_t id of error - otherwise + */ +ecma_error_msg_t +ecma_object_check_constructor (ecma_object_t *obj_p) /**< ecma object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + + ecma_object_type_t type = ecma_get_object_type (obj_p); + + if (JERRY_UNLIKELY (type < ECMA_OBJECT_TYPE_PROXY)) + { + return ECMA_ERR_INVALID_TYPE_FOR_CONSTRUCTOR_CALL; + } + + while (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)) + { + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) obj_p; + + obj_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + + type = ecma_get_object_type (obj_p); + } + + if (JERRY_LIKELY (type == ECMA_OBJECT_TYPE_FUNCTION)) + { + const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) obj_p); + + if (!CBC_FUNCTION_IS_CONSTRUCTABLE (byte_code_p->status_flags)) + { +#if JERRY_ERROR_MESSAGES + switch (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags)) + { + case CBC_FUNCTION_SCRIPT: + { + return ECMA_ERR_SCRIPT_GLOBAL_FUNCTIONS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_GENERATOR: + { + return ECMA_ERR_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_ASYNC: + { + return ECMA_ERR_ASYNC_FUNCTIONS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_ASYNC_GENERATOR: + { + return ECMA_ERR_ASYNC_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_ACCESSOR: + { + return ECMA_ERR_ACCESSOR_FUNCTIONS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_METHOD: + { + return ECMA_ERR_METHODS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_ARROW: + { + return ECMA_ERR_ARROW_FUNCTIONS_INVOKE_WITH_NEW; + } + default: + { + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_ASYNC_ARROW); + return ECMA_ERR_ASYNC_ARROW_FUNCTIONS_INVOKE_WITH_NEW; + } + } +#else /* !JERRY_ERROR_MESSAGES */ + return ECMA_ERR_EMPTY; +#endif /* JERRY_ERROR_MESSAGES */ + } + + return ECMA_IS_VALID_CONSTRUCTOR; + } + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_TYPE_IS_PROXY (type)) + { + if (!(obj_p->u2.prototype_cp & ECMA_PROXY_IS_CONSTRUCTABLE)) + { + return ECMA_ERR_PROXY_TARGET_IS_NOT_A_CONSTRUCTOR; + } + + return ECMA_IS_VALID_CONSTRUCTOR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION || type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + || type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); + + if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) + { + if (ecma_builtin_function_is_routine (obj_p)) + { + return ECMA_ERR_BULTIN_ROUTINES_HAVE_NO_CONSTRUCTOR; + } + + JERRY_ASSERT (((ecma_extended_object_t *) obj_p)->u.built_in.id != ECMA_BUILTIN_ID_HANDLER); + } + + return ECMA_IS_VALID_CONSTRUCTOR; +} /* ecma_object_check_constructor */ + +/** + * Implement IsConstructor abstract operation. + * + * @return ECMA_IS_VALID_CONSTRUCTOR - if the input value is a constructor. + * ecma_error_msg_t id of error - otherwise + */ +ecma_error_msg_t +ecma_check_constructor (ecma_value_t value) /**< ecma object */ +{ + if (!ecma_is_value_object (value)) + { + return ECMA_ERR_INVALID_TYPE_FOR_CONSTRUCTOR_CALL; + } + + return ecma_object_check_constructor (ecma_get_object_from_value (value)); +} /* ecma_check_constructor */ + +/** + * Checks whether the given object implements [[Construct]]. + * + * @return true - if the given object is constructor; + * false - otherwise + */ +bool +ecma_object_is_constructor (ecma_object_t *obj_p) /**< ecma object */ +{ + return ecma_object_check_constructor (obj_p) == ECMA_IS_VALID_CONSTRUCTOR; +} /* ecma_object_is_constructor */ + +/** + * Checks whether the value is Object that implements [[Construct]]. + * + * @return true - if value is constructor object; + * false - otherwise + */ +bool +ecma_is_constructor (ecma_value_t value) /**< ecma value */ +{ + return (ecma_is_value_object (value) && ecma_object_is_constructor (ecma_get_object_from_value (value))); +} /* ecma_is_constructor */ + +/** + * Helper method to count and convert the arguments for the Function/GeneratorFunction constructor call. + * + * See also: + * ECMA 262 v5.1 15.3.2.1 steps 5.a-d + * ECMA 262 v6 19.2.1.1.1 steps 8 + * + * @return ecma value - concatenated arguments as a string. + * Returned value must be freed with ecma_free_value. + */ +static ecma_string_t * +ecma_op_create_dynamic_function_arguments_helper (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len <= 1) + { + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return str_p; + } + + if (arguments_list_len == 2) + { + return str_p; + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (str_p); + ecma_deref_ecma_string (str_p); + + for (uint32_t idx = 1; idx < arguments_list_len - 1; idx++) + { + str_p = ecma_op_to_string (arguments_list_p[idx]); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + ecma_stringbuilder_destroy (&builder); + return str_p; + } + + ecma_stringbuilder_append_char (&builder, LIT_CHAR_COMMA); + ecma_stringbuilder_append (&builder, str_p); + ecma_deref_ecma_string (str_p); + } + + return ecma_stringbuilder_finalize (&builder); +} /* ecma_op_create_dynamic_function_arguments_helper */ + +/** + * Function object creation operation. + * + * See also: ECMA-262 v5, 13.2 + * + * @return pointer to newly created Function object + */ +static ecma_object_t * +ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */ + const ecma_compiled_code_t *bytecode_data_p, /**< byte-code array */ + ecma_builtin_id_t proto_id) /**< builtin id of the prototype object */ +{ + JERRY_ASSERT (ecma_is_lexical_environment (scope_p)); + + /* 1., 4., 13. */ + ecma_object_t *prototype_obj_p = ecma_builtin_get (proto_id); + + size_t function_object_size = sizeof (ecma_extended_object_t); + +#if JERRY_SNAPSHOT_EXEC + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) + { + function_object_size = sizeof (ecma_static_function_t); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + ecma_object_t *func_p = ecma_create_object (prototype_obj_p, function_object_size, ECMA_OBJECT_TYPE_FUNCTION); + + /* 2., 6., 7., 8. */ + /* + * We don't setup [[Get]], [[Call]], [[Construct]], [[HasInstance]] for each function object. + * Instead we set the object's type to ECMA_OBJECT_TYPE_FUNCTION + * that defines which version of the routine should be used on demand. + */ + + /* 3. */ + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. + * + * See also: ecma_object_get_class_name + */ + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p; + + /* 9. */ + ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, scope_p, 0); + + /* 10., 11., 12. */ + +#if JERRY_SNAPSHOT_EXEC + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) + { + ext_func_p->u.function.bytecode_cp = JMEM_CP_NULL; + ((ecma_static_function_t *) func_p)->bytecode_p = bytecode_data_p; + } + else +#endif /* JERRY_SNAPSHOT_EXEC */ + { + ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.bytecode_cp, bytecode_data_p); + ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p); + } + + /* 14., 15., 16., 17., 18. */ + /* + * 'length' and 'prototype' properties are instantiated lazily + * + * See also: ecma_op_function_try_to_lazy_instantiate_property + */ + + return func_p; +} /* ecma_op_create_function_object */ + +/** + * CreateDynamicFunction operation + * + * See also: + * ECMA-262 v5, 15.3. + * ECMA-262 v6, 19.2.1.1 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * constructed function object - otherwise + */ +ecma_value_t +ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len, /**< number of arguments */ + ecma_parse_opts_t parse_opts) /**< parse options */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_string_t *arguments_str_p = + ecma_op_create_dynamic_function_arguments_helper (arguments_list_p, arguments_list_len); + + if (JERRY_UNLIKELY (arguments_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_string_t *function_body_str_p; + + if (arguments_list_len > 0) + { + function_body_str_p = ecma_op_to_string (arguments_list_p[arguments_list_len - 1]); + + if (JERRY_UNLIKELY (function_body_str_p == NULL)) + { + ecma_deref_ecma_string (arguments_str_p); + return ECMA_VALUE_ERROR; + } + } + else + { + /* Very unlikely code path, not optimized. */ + function_body_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_value_t source[2]; + source[0] = ecma_make_string_value (function_body_str_p); + source[1] = ecma_make_string_value (arguments_str_p); + + parse_opts = (ecma_parse_opts_t) ((int) parse_opts | ((int) ECMA_PARSE_HAS_SOURCE_VALUE | (int) ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE)); + + ecma_compiled_code_t *bytecode_p = parser_parse_script ((void *) source, parse_opts, NULL); + + ecma_deref_ecma_string (arguments_str_p); + ecma_deref_ecma_string (function_body_str_p); + + if (JERRY_UNLIKELY (bytecode_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t *func_name_p; + func_name_p = ecma_compiled_code_resolve_function_name ((const ecma_compiled_code_t *) bytecode_p); + *func_name_p = ecma_make_magic_string_value (LIT_MAGIC_STRING_ANONYMOUS); + + ecma_object_t *global_object_p = ecma_builtin_get_global (); + +#if JERRY_BUILTIN_REALMS + JERRY_ASSERT (global_object_p == (ecma_object_t *) ecma_op_function_get_realm (bytecode_p)); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *global_env_p = ecma_get_global_environment (global_object_p); + ecma_builtin_id_t fallback_proto = ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE; + ecma_object_t *new_target_p = JERRY_CONTEXT (current_new_target_p); + ecma_builtin_id_t fallback_ctor = ECMA_BUILTIN_ID_FUNCTION; + + if (JERRY_UNLIKELY (parse_opts & (ECMA_PARSE_GENERATOR_FUNCTION | ECMA_PARSE_ASYNC_FUNCTION))) + { + fallback_proto = ECMA_BUILTIN_ID_ASYNC_GENERATOR; + fallback_ctor = ECMA_BUILTIN_ID_ASYNC_GENERATOR_FUNCTION; + + if (!(parse_opts & ECMA_PARSE_GENERATOR_FUNCTION)) + { + fallback_proto = ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE; + fallback_ctor = ECMA_BUILTIN_ID_ASYNC_FUNCTION; + } + else if (!(parse_opts & ECMA_PARSE_ASYNC_FUNCTION)) + { + fallback_proto = ECMA_BUILTIN_ID_GENERATOR; + fallback_ctor = ECMA_BUILTIN_ID_GENERATOR_FUNCTION; + } + } + + if (new_target_p == NULL) + { + new_target_p = ecma_builtin_get (fallback_ctor); + } + + ecma_object_t *proto = ecma_op_get_prototype_from_constructor (new_target_p, fallback_proto); + + if (JERRY_UNLIKELY (proto == NULL)) + { + ecma_bytecode_deref (bytecode_p); + return ECMA_VALUE_ERROR; + } + + ecma_object_t *func_obj_p = ecma_op_create_function_object (global_env_p, bytecode_p, fallback_proto); + + ECMA_SET_NON_NULL_POINTER (func_obj_p->u2.prototype_cp, proto); + ecma_deref_object (proto); + + ecma_bytecode_deref (bytecode_p); + return ecma_make_object_value (func_obj_p); +} /* ecma_op_create_dynamic_function */ + +/** + * Function object creation operation. + * + * See also: ECMA-262 v5, 13.2 + * + * @return pointer to newly created Function object + */ +ecma_object_t * +ecma_op_create_simple_function_object (ecma_object_t *scope_p, /**< function's scope */ + const ecma_compiled_code_t *bytecode_data_p) /**< byte-code array */ +{ + return ecma_op_create_function_object (scope_p, bytecode_data_p, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); +} /* ecma_op_create_simple_function_object */ + +/** + * Create a function object with the appropriate prototype. + * + * @return pointer to newly created Function object + */ +ecma_object_t * +ecma_op_create_any_function_object (ecma_object_t *scope_p, /**< function's scope */ + const ecma_compiled_code_t *bytecode_data_p) /**< byte-code array */ +{ + ecma_builtin_id_t proto_id; + + switch (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags)) + { + case CBC_FUNCTION_GENERATOR: + { + proto_id = ECMA_BUILTIN_ID_GENERATOR; + break; + } + case CBC_FUNCTION_ASYNC: + { + proto_id = ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE; + break; + } + case CBC_FUNCTION_ASYNC_GENERATOR: + { + proto_id = ECMA_BUILTIN_ID_ASYNC_GENERATOR; + break; + } + default: + { + proto_id = ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE; + break; + } + } + + return ecma_op_create_function_object (scope_p, bytecode_data_p, proto_id); +} /* ecma_op_create_any_function_object */ + +/** + * Arrow function object creation operation. + * + * See also: ES2015, 9.2.12 + * + * @return pointer to newly created Function object + */ +ecma_object_t * +ecma_op_create_arrow_function_object (ecma_object_t *scope_p, /**< function's scope */ + const ecma_compiled_code_t *bytecode_data_p, /**< byte-code array */ + ecma_value_t this_binding) /**< value of 'this' binding */ +{ + ecma_object_t *prototype_obj_p; + + if (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_ARROW) + { + prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + } + else + { + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_ASYNC_ARROW); + prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE); + } + + size_t arrow_function_object_size = sizeof (ecma_arrow_function_t); + +#if JERRY_SNAPSHOT_EXEC + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) + { + arrow_function_object_size = sizeof (ecma_static_arrow_function_t); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + ecma_object_t *func_p = ecma_create_object (prototype_obj_p, arrow_function_object_size, ECMA_OBJECT_TYPE_FUNCTION); + + ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_p; + + ECMA_SET_NON_NULL_POINTER_TAG (arrow_func_p->header.u.function.scope_cp, scope_p, 0); + +#if JERRY_SNAPSHOT_EXEC + if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + { + arrow_func_p->header.u.function.bytecode_cp = ECMA_NULL_POINTER; + ((ecma_static_arrow_function_t *) func_p)->bytecode_p = bytecode_data_p; + } + else + { +#endif /* JERRY_SNAPSHOT_EXEC */ + ECMA_SET_INTERNAL_VALUE_POINTER (arrow_func_p->header.u.function.bytecode_cp, bytecode_data_p); + ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p); +#if JERRY_SNAPSHOT_EXEC + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + arrow_func_p->this_binding = ecma_copy_value_if_not_object (this_binding); + arrow_func_p->new_target = ECMA_VALUE_UNDEFINED; + + if (JERRY_CONTEXT (current_new_target_p) != NULL) + { + arrow_func_p->new_target = ecma_make_object_value (JERRY_CONTEXT (current_new_target_p)); + } + return func_p; +} /* ecma_op_create_arrow_function_object */ + +/** + * External function object creation operation. + * + * Note: + * external function object is implementation-defined object type + * that represent functions implemented in native code, using Embedding API + * + * @return pointer to newly created external function object + */ +ecma_object_t * +ecma_op_create_external_function_object (ecma_native_handler_t handler_cb) /**< pointer to external native handler */ +{ + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + + ecma_object_t *function_obj_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_native_function_t), ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_NATIVE_FUNCTION type. + * + * See also: ecma_object_get_class_name + */ + + ecma_native_function_t *native_function_p = (ecma_native_function_t *) function_obj_p; +#if JERRY_BUILTIN_REALMS + ECMA_SET_INTERNAL_VALUE_POINTER (native_function_p->realm_value, ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + native_function_p->native_handler_cb = handler_cb; + + return function_obj_p; +} /* ecma_op_create_external_function_object */ + +/** + * Create built-in native handler object. + * + * @return pointer to newly created native handler object + */ +ecma_object_t * +ecma_op_create_native_handler (ecma_native_handler_id_t id, /**< handler id */ + size_t object_size) /**< created object size */ +{ + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + + ecma_object_t *function_obj_p = ecma_create_object (prototype_obj_p, object_size, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) function_obj_p; + ext_func_obj_p->u.built_in.id = ECMA_BUILTIN_ID_HANDLER; + ext_func_obj_p->u.built_in.routine_id = (uint8_t) id; + ext_func_obj_p->u.built_in.u2.routine_flags = ECMA_NATIVE_HANDLER_FLAGS_NONE; + +#if JERRY_BUILTIN_REALMS + ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_obj_p->u.built_in.realm_value, ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + + return function_obj_p; +} /* ecma_op_create_native_handler */ + +/** + * Get compiled code of a function object. + * + * @return compiled code + */ +const ecma_compiled_code_t * +ecma_op_function_get_compiled_code (ecma_extended_object_t *function_p) /**< function pointer */ +{ +#if JERRY_SNAPSHOT_EXEC + if (JERRY_LIKELY (function_p->u.function.bytecode_cp != ECMA_NULL_POINTER)) + { + return ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t, function_p->u.function.bytecode_cp); + } + + return ((ecma_static_function_t *) function_p)->bytecode_p; +#else /* !JERRY_SNAPSHOT_EXEC */ + return ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t, function_p->u.function.bytecode_cp); +#endif /* JERRY_SNAPSHOT_EXEC */ +} /* ecma_op_function_get_compiled_code */ + +#if JERRY_BUILTIN_REALMS + +/** + * Get realm from a byte code. + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to realm (global) object + */ +ecma_global_object_t * +ecma_op_function_get_realm (const ecma_compiled_code_t *bytecode_header_p) /**< byte code header */ +{ +#if JERRY_SNAPSHOT_EXEC + if (JERRY_UNLIKELY (bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + { + return (ecma_global_object_t *) ecma_builtin_get_global (); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_header_p)->script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + return (ecma_global_object_t *) script_p->realm_p; +} /* ecma_op_function_get_realm */ + +/** + * Get realm from a function + * + * Note: + * Does not increase the reference counter. + * + * @return realm (global) object + */ +ecma_global_object_t * +ecma_op_function_get_function_realm (ecma_object_t *func_obj_p) /**< function object */ +{ + while (true) + { + ecma_object_type_t type = ecma_get_object_type (func_obj_p); + + if (type == ECMA_OBJECT_TYPE_FUNCTION) + { + ecma_extended_object_t *ext_function_obj_p = (ecma_extended_object_t *) func_obj_p; + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_function_obj_p); + return ecma_op_function_get_realm (bytecode_data_p); + } + + if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) + { + ecma_extended_object_t *ext_function_obj_p = (ecma_extended_object_t *) func_obj_p; + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, ext_function_obj_p->u.built_in.realm_value); + } + + if (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION) + { + ecma_native_function_t *native_function_p = (ecma_native_function_t *) func_obj_p; + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, native_function_p->realm_value); + } + + if (type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION) + { + ecma_value_t script_value = ((ecma_extended_object_t *) func_obj_p)->u.constructor_function.script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + return (ecma_global_object_t *) script_p->realm_p; + } + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (func_obj_p)) + { + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) func_obj_p; + if (ecma_is_value_null (proxy_obj_p->handler)) + { + ecma_raise_type_error (ECMA_ERR_PROTOTYPE_FROM_REVOKED_PROXY_IS_INVALID); + return NULL; + } + func_obj_p = ecma_get_object_from_value (proxy_obj_p->target); + continue; + } +#endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p; + func_obj_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + } +} /* ecma_op_function_get_function_realm */ + +#endif /* JERRY_BUILTIN_REALMS */ + +/** + * 15.3.5.3 implementation of [[HasInstance]] for Function objects + * + * @return true/false - if arguments are valid + * error - otherwise + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t value) /**< argument 'V' */ +{ + JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); + + if (!ecma_is_value_object (value)) + { + return ECMA_VALUE_FALSE; + } + + while (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION) + { + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + /* 1. 3. */ + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p; + + func_obj_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + } + + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION + || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION + || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION + || ECMA_OBJECT_IS_PROXY (func_obj_p)); + + ecma_object_t *v_obj_p = ecma_get_object_from_value (value); + + ecma_value_t prototype_obj_value = ecma_op_object_get_by_magic_id (func_obj_p, LIT_MAGIC_STRING_PROTOTYPE); + + if (ECMA_IS_VALUE_ERROR (prototype_obj_value)) + { + return prototype_obj_value; + } + + if (!ecma_is_value_object (prototype_obj_value)) + { + ecma_free_value (prototype_obj_value); + return ecma_raise_type_error (ECMA_ERR_OBJECT_EXPECTED); + } + + ecma_object_t *prototype_obj_p = ecma_get_object_from_value (prototype_obj_value); + JERRY_ASSERT (prototype_obj_p != NULL); + +#if JERRY_BUILTIN_PROXY + ecma_value_t result = ECMA_VALUE_ERROR; +#else /* !JERRY_BUILTIN_PROXY */ + ecma_value_t result = ECMA_VALUE_FALSE; +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_ref_object (v_obj_p); + + while (true) + { + ecma_object_t *current_proto_p = ecma_op_object_get_prototype_of (v_obj_p); + ecma_deref_object (v_obj_p); + + if (current_proto_p == NULL) + { +#if JERRY_BUILTIN_PROXY + result = ECMA_VALUE_FALSE; +#endif /* JERRY_BUILTIN_PROXY */ + break; + } + else if (current_proto_p == ECMA_OBJECT_POINTER_ERROR) + { + break; + } + + if (current_proto_p == prototype_obj_p) + { + ecma_deref_object (current_proto_p); + result = ECMA_VALUE_TRUE; + break; + } + + /* Advance up on prototype chain. */ + v_obj_p = current_proto_p; + } + + ecma_deref_object (prototype_obj_p); + return result; +} /* ecma_op_function_has_instance */ + +/** + * GetSuperConstructor operation for class methods + * + * See also: ECMAScript v6, 12.3.5.2 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * super constructor - otherwise + */ +ecma_value_t +ecma_op_function_get_super_constructor (ecma_object_t *func_obj_p) /**< function object */ +{ + ecma_object_t *super_ctor_p = ecma_op_object_get_prototype_of (func_obj_p); + + if (JERRY_UNLIKELY (super_ctor_p == ECMA_OBJECT_POINTER_ERROR)) + { + return ECMA_VALUE_ERROR; + } + else if (super_ctor_p == NULL || !ecma_object_is_constructor (super_ctor_p)) + { + if (super_ctor_p != NULL) + { + ecma_deref_object (super_ctor_p); + } + return ecma_raise_type_error (ECMA_ERR_SUPER_BINDING_MUST_BE_A_CONSTRUCTOR); + } + + return ecma_make_object_value (super_ctor_p); +} /* ecma_op_function_get_super_constructor */ + +/** + * Ordinary internal method: GetPrototypeFromConstructor (constructor, intrinsicDefaultProto) + * + * See also: + * - ECMAScript v6, 9.1.15 + * - ECMAScript v10, 9.1.14 + * + * @return NULL - if the operation fail (exception on the global context is raised) + * pointer to the prototype object - otherwise + */ +ecma_object_t * +ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, /**< constructor to get prototype from */ + ecma_builtin_id_t default_proto_id) /**< intrinsicDefaultProto */ +{ + JERRY_ASSERT (ecma_op_object_is_callable (ctor_obj_p)); + JERRY_ASSERT (default_proto_id < ECMA_BUILTIN_ID__COUNT); + + ecma_value_t proto = ecma_op_object_get_by_magic_id (ctor_obj_p, LIT_MAGIC_STRING_PROTOTYPE); + + if (ECMA_IS_VALUE_ERROR (proto)) + { + return NULL; + } + + ecma_object_t *proto_obj_p; + + if (!ecma_is_value_object (proto)) + { + ecma_free_value (proto); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (ctor_obj_p)) + { + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) ctor_obj_p; + if (ecma_is_value_null (proxy_obj_p->handler)) + { + ecma_raise_type_error (ECMA_ERR_PROTOTYPE_FROM_REVOKED_PROXY_IS_INVALID); + return NULL; + } + } +#endif /* JERRY_BUILTIN_PROXY */ + +#if JERRY_BUILTIN_REALMS + proto_obj_p = ecma_builtin_get_from_realm (ecma_op_function_get_function_realm (ctor_obj_p), default_proto_id); +#else /* !JERRY_BUILTIN_REALMS */ + proto_obj_p = ecma_builtin_get (default_proto_id); +#endif /* JERRY_BUILTIN_REALMS */ + ecma_ref_object (proto_obj_p); + } + else + { + proto_obj_p = ecma_get_object_from_value (proto); + } + + return proto_obj_p; +} /* ecma_op_get_prototype_from_constructor */ + +/** + * Perform a JavaScript class function object method call. + * + * The input function object should be a JavaScript class constructor + * + * @return the result of the function call. + */ +static ecma_value_t JERRY_ATTR_NOINLINE +ecma_op_function_call_constructor (vm_frame_ctx_shared_args_t *shared_args_p, /**< shared data */ + ecma_object_t *scope_p, /**< lexical environment to use */ + ecma_value_t this_binding) /**< value of 'ThisBinding' */ +{ + shared_args_p->header.status_flags |= VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; + + ecma_value_t ret_value; + ecma_global_object_t *saved_global_object_p; + ecma_extended_object_t *ext_func_p; + + if (JERRY_CONTEXT (current_new_target_p) == NULL) + { + ret_value = ecma_raise_type_error (ECMA_ERR_CLASS_CONSTRUCTOR_REQUIRES_NEW); + goto exit; + } + + ext_func_p = (ecma_extended_object_t *) shared_args_p->header.function_object_p; + if (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + this_binding = ECMA_VALUE_UNINITIALIZED; + } + + ecma_op_create_environment_record (scope_p, this_binding, shared_args_p->header.function_object_p); + +#if JERRY_BUILTIN_REALMS + saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = ecma_op_function_get_realm (shared_args_p->header.bytecode_header_p); +#endif /* JERRY_BUILTIN_REALMS */ + + ret_value = vm_run (&shared_args_p->header, this_binding, scope_p); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + /* ECMAScript v6, 9.2.2.13 */ + if (JERRY_UNLIKELY (this_binding == ECMA_VALUE_UNINITIALIZED)) + { + if (!ECMA_IS_VALUE_ERROR (ret_value) && !ecma_is_value_object (ret_value)) + { + if (!ecma_is_value_undefined (ret_value)) + { + ecma_free_value (ret_value); + ret_value = ecma_raise_type_error (ECMA_ERR_DERIVED_CTOR_RETURN_NOR_OBJECT_OR_UNDEFINED); + } + else + { + ret_value = ecma_op_get_this_binding (scope_p); + } + } + } + +exit: + if (JERRY_UNLIKELY (shared_args_p->header.status_flags & VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV)) + { + ecma_deref_object (scope_p); + } + + return ret_value; +} /* ecma_op_function_call_constructor */ + +/** + * Perform a JavaScript function object method call. + * + * The input function object should be a pure JavaScript method + * + * @return the result of the function call. + */ +static ecma_value_t +ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_binding, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); + + vm_frame_ctx_shared_args_t shared_args; + shared_args.header.status_flags = VM_FRAME_CTX_SHARED_HAS_ARG_LIST; + shared_args.header.function_object_p = func_obj_p; + shared_args.arg_list_p = arguments_list_p; + shared_args.arg_list_len = arguments_list_len; + + /* Entering Function Code (ECMA-262 v5, 10.4.3) */ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; + + ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp); + + /* 8. */ + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); + uint16_t status_flags = bytecode_data_p->status_flags; + + shared_args.header.bytecode_header_p = bytecode_data_p; + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *realm_p = ecma_op_function_get_realm (bytecode_data_p); +#endif /* JERRY_BUILTIN_REALMS */ + + /* 5. */ + if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)) + { + shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV; + scope_p = ecma_create_decl_lex_env (scope_p); + } + + /* 1. */ + switch (CBC_FUNCTION_GET_TYPE (status_flags)) + { + case CBC_FUNCTION_CONSTRUCTOR: + { + return ecma_op_function_call_constructor (&shared_args, scope_p, this_binding); + } + case CBC_FUNCTION_ARROW: + { + ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_obj_p; + + if (ecma_is_value_undefined (arrow_func_p->new_target)) + { + JERRY_CONTEXT (current_new_target_p) = NULL; + } + else + { + JERRY_CONTEXT (current_new_target_p) = ecma_get_object_from_value (arrow_func_p->new_target); + } + + this_binding = arrow_func_p->this_binding; + + if (JERRY_UNLIKELY (this_binding == ECMA_VALUE_UNINITIALIZED)) + { + ecma_environment_record_t *env_record_p = ecma_op_get_environment_record (scope_p); + JERRY_ASSERT (env_record_p); + this_binding = env_record_p->this_binding; + } + break; + } + default: + { + shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; + + if (status_flags & CBC_CODE_FLAGS_STRICT_MODE) + { + break; + } + + if (ecma_is_value_undefined (this_binding) || ecma_is_value_null (this_binding)) + { + /* 2. */ +#if JERRY_BUILTIN_REALMS + this_binding = realm_p->this_binding; +#else /* !JERRY_BUILTIN_REALMS */ + this_binding = ecma_make_object_value (ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + } + else if (!ecma_is_value_object (this_binding)) + { + /* 3., 4. */ + this_binding = ecma_op_to_object (this_binding); + shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_FREE_THIS; + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (this_binding)); + } + break; + } + } + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = realm_p; +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_value_t ret_value = vm_run (&shared_args.header, this_binding, scope_p); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV)) + { + ecma_deref_object (scope_p); + } + + if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_FREE_THIS)) + { + ecma_free_value (this_binding); + } + + return ret_value; +} /* ecma_op_function_call_simple */ + +/** + * Perform a built-in method call. + * + * @return the result of the function call. + */ +static ecma_value_t JERRY_ATTR_NOINLINE +ecma_op_function_call_native_built_in (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_arg_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + JERRY_CONTEXT (global_object_p) = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, ext_func_obj_p->u.built_in.realm_value); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_value_t ret_value = + ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + return ret_value; +} /* ecma_op_function_call_native_built_in */ + +/** + * Perform a native C method call which was registered via the API. + * + * @return the result of the function call. + */ +static ecma_value_t JERRY_ATTR_NOINLINE +ecma_op_function_call_native (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_arg_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + + ecma_native_function_t *native_function_p = (ecma_native_function_t *) func_obj_p; + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, native_function_p->realm_value); +#endif /* JERRY_BUILTIN_REALMS */ + + jerry_call_info_t call_info; + call_info.function = ecma_make_object_value (func_obj_p); + call_info.this_value = this_arg_value; + + ecma_object_t *new_target_p = JERRY_CONTEXT (current_new_target_p); + call_info.new_target = (new_target_p == NULL) ? ECMA_VALUE_UNDEFINED : ecma_make_object_value (new_target_p); + + JERRY_ASSERT (native_function_p->native_handler_cb != NULL); + ecma_value_t ret_value = native_function_p->native_handler_cb (&call_info, arguments_list_p, arguments_list_len); +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + if (JERRY_UNLIKELY (ecma_is_value_exception (ret_value))) + { + ecma_throw_exception (ret_value); + return ECMA_VALUE_ERROR; + } + + return ret_value; +} /* ecma_op_function_call_native */ + +/** + * Append the bound arguments into the given collection + * + * Note: + * - The whole bound chain is resolved + * - The first element of the collection contains the bounded this value + * + * @return target function of the bound function + */ +JERRY_ATTR_NOINLINE static ecma_object_t * +ecma_op_bound_function_get_argument_list (ecma_object_t *func_obj_p, /**< bound bunction object */ + ecma_collection_t *list_p) /**< list of arguments */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p; + + func_obj_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + + uint32_t args_length = 1; + + if (ecma_is_value_integer_number (args_len_or_this)) + { + args_length = (uint32_t) ecma_get_integer_from_value (args_len_or_this); + } + + /* 5. */ + if (args_length != 1) + { + const ecma_value_t *args_p = (const ecma_value_t *) (bound_func_p + 1); + list_p->buffer_p[0] = *args_p; + + if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION) + { + func_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, list_p); + } + ecma_collection_append (list_p, args_p + 1, args_length - 1); + } + else + { + list_p->buffer_p[0] = args_len_or_this; + } + + return func_obj_p; +} /* ecma_op_bound_function_get_argument_list */ + +/** + * [[Call]] internal method for bound function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t JERRY_ATTR_NOINLINE +ecma_op_function_call_bound (ecma_object_t *func_obj_p, /**< Function object */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; + + ecma_collection_t *bound_arg_list_p = ecma_new_collection (); + ecma_collection_push_back (bound_arg_list_p, ECMA_VALUE_EMPTY); + + ecma_object_t *target_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, bound_arg_list_p); + + ecma_collection_append (bound_arg_list_p, arguments_list_p, arguments_list_len); + + JERRY_ASSERT (!ecma_is_value_empty (bound_arg_list_p->buffer_p[0])); + + ecma_value_t ret_value = ecma_op_function_call (target_obj_p, + bound_arg_list_p->buffer_p[0], + bound_arg_list_p->buffer_p + 1, + (uint32_t) (bound_arg_list_p->item_count - 1)); + + ecma_collection_destroy (bound_arg_list_p); + + return ret_value; +} /* ecma_op_function_call_bound */ + +/** + * General [[Call]] implementation + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_function_validated_call (ecma_value_t callee, /**< callee */ + ecma_value_t this_arg_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + if (!ecma_is_value_object (callee)) + { + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + } + + return ecma_op_function_call (ecma_get_object_from_value (callee), + this_arg_value, + arguments_list_p, + arguments_list_len); +} /* ecma_op_function_validated_call */ + +/** + * General [[Call]] implementation + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_arg_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); + + ECMA_CHECK_STACK_USAGE (); + + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + + if (JERRY_UNLIKELY (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL))) + { + JERRY_CONTEXT (current_new_target_p) = NULL; + } + + ecma_value_t result; + + switch (ecma_get_object_type (func_obj_p)) + { + case ECMA_OBJECT_TYPE_FUNCTION: + { + result = ecma_op_function_call_simple (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + result = ecma_op_function_call_native_built_in (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + break; + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + result = ecma_proxy_object_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + result = ecma_raise_type_error (ECMA_ERR_CLASS_CONSTRUCTOR_NEW); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + result = ecma_op_function_call_native (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + result = ecma_op_function_call_bound (func_obj_p, arguments_list_p, arguments_list_len); + break; + } + default: + { + result = ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + break; + } + } + + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + + return result; +} /* ecma_op_function_call */ + +/** + * [[Construct]] internal method for ECMAScript function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_simple (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); + + ecma_object_t *new_this_obj_p = NULL; + ecma_value_t this_arg; + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + + /* 5. */ + if (!ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_obj_p->u.function.scope_cp)) + { + /* 5.a */ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + /* 5.b */ + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (proto_p); + this_arg = ecma_make_object_value (new_this_obj_p); + } + else + { + this_arg = ECMA_VALUE_UNDEFINED; + } + + /* 6. */ + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; + + ecma_value_t ret_value = ecma_op_function_call_simple (func_obj_p, this_arg, arguments_list_p, arguments_list_len); + + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + + /* 13.a */ + if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value)) + { + if (new_this_obj_p != NULL) + { + ecma_deref_object (new_this_obj_p); + } + + return ret_value; + } + + /* 13.b */ + ecma_free_value (ret_value); + return this_arg; +} /* ecma_op_function_construct_simple */ + +/** + * [[Construct]] internal method for built-in function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_built_in (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_UNUSED (new_target_p); + + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + ecma_value_t realm_value = ((ecma_extended_object_t *) func_obj_p)->u.built_in.realm_value; + JERRY_CONTEXT (global_object_p) = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; + + ecma_value_t ret_value = ecma_builtin_dispatch_construct (func_obj_p, arguments_list_p, arguments_list_len); + + JERRY_CONTEXT (current_new_target_p) = old_new_target; + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + return ret_value; +} /* ecma_op_function_construct_built_in */ + +/** + * [[Construct]] internal method for bound function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t JERRY_ATTR_NOINLINE +ecma_op_function_construct_bound (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + ecma_collection_t *bound_arg_list_p = ecma_new_collection (); + ecma_collection_push_back (bound_arg_list_p, ECMA_VALUE_EMPTY); + + ecma_object_t *target_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, bound_arg_list_p); + + ecma_collection_append (bound_arg_list_p, arguments_list_p, arguments_list_len); + + if (func_obj_p == new_target_p) + { + new_target_p = target_obj_p; + } + + ecma_value_t ret_value = ecma_op_function_construct (target_obj_p, + new_target_p, + bound_arg_list_p->buffer_p + 1, + (uint32_t) (bound_arg_list_p->item_count - 1)); + + ecma_collection_destroy (bound_arg_list_p); + + return ret_value; +} /* ecma_op_function_construct_bound */ + +/** + * [[Construct]] internal method for class implicit constructor objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_constructor (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); + + ecma_extended_object_t *constructor_object_p = (ecma_extended_object_t *) func_obj_p; + + if (!(constructor_object_p->u.constructor_function.flags & ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE)) + { + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *new_this_object_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (proto_p); + + jerry_value_t new_this_value = ecma_make_object_value (new_this_object_p); + jerry_value_t ret_value = opfunc_init_class_fields (func_obj_p, new_this_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_object (new_this_object_p); + return ret_value; + } + + return new_this_value; + } + + ecma_value_t super_ctor = ecma_op_function_get_super_constructor (func_obj_p); + + if (ECMA_IS_VALUE_ERROR (super_ctor)) + { + return super_ctor; + } + + ecma_object_t *super_ctor_p = ecma_get_object_from_value (super_ctor); + ecma_value_t result = ecma_op_function_construct (super_ctor_p, new_target_p, arguments_list_p, arguments_list_len); + ecma_deref_object (super_ctor_p); + + if (ecma_is_value_object (result)) + { + ecma_value_t fields_value = opfunc_init_class_fields (func_obj_p, result); + + if (ECMA_IS_VALUE_ERROR (fields_value)) + { + ecma_free_value (result); + return fields_value; + } + } + + return result; +} /* ecma_op_function_construct_constructor */ + +/** + * [[Construct]] internal method for external function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_native (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_value_t this_arg = ecma_make_object_value (new_this_obj_p); + ecma_deref_object (proto_p); + + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; + + ecma_value_t ret_value = ecma_op_function_call_native (func_obj_p, this_arg, arguments_list_p, arguments_list_len); + + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + + if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value)) + { + ecma_deref_object (new_this_obj_p); + return ret_value; + } + + ecma_free_value (ret_value); + + return this_arg; +} /* ecma_op_function_construct_native */ + +/** + * General [[Construct]] implementation function objects + * + * See also: ECMAScript v6, 9.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); + + ECMA_CHECK_STACK_USAGE (); + + switch (ecma_get_object_type (func_obj_p)) + { + case ECMA_OBJECT_TYPE_FUNCTION: + { + return ecma_op_function_construct_simple (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + return ecma_op_function_construct_built_in (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + return ecma_proxy_object_construct (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + return ecma_op_function_construct_constructor (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + return ecma_op_function_construct_bound (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + return ecma_op_function_construct_native (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } + default: + { + JERRY_UNREACHABLE (); + } + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_function_construct */ + +/** + * Lazy instantiation of 'prototype' property for non-builtin and external functions + * + * @return pointer to newly instantiated property + */ +static ecma_property_t * +ecma_op_lazy_instantiate_prototype_object (ecma_object_t *object_p) /**< the function object */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION + || ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *global_object_p; + + if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + global_object_p = ecma_op_function_get_realm (bytecode_data_p); + } + else + { + ecma_native_function_t *native_function_p = (ecma_native_function_t *) object_p; + + global_object_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, native_function_p->realm_value); + } +#endif /* JERRY_BUILTIN_REALMS */ + + /* ECMA-262 v5, 13.2, 16-18 */ + + ecma_object_t *proto_object_p = NULL; + bool init_constructor = true; + + if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + if (!CBC_FUNCTION_HAS_PROTOTYPE (byte_code_p->status_flags)) + { + return NULL; + } + + if (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_GENERATOR) + { + ecma_object_t *prototype_p; + +#if JERRY_BUILTIN_REALMS + prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE); +#else /* !JERRY_BUILTIN_REALMS */ + prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE); +#endif /* JERRY_BUILTIN_REALMS */ + + proto_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + init_constructor = false; + } + + if (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR) + { + ecma_object_t *prototype_p; + +#if JERRY_BUILTIN_REALMS + prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE); +#else /* !JERRY_BUILTIN_REALMS */ + prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE); +#endif /* JERRY_BUILTIN_REALMS */ + + proto_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + init_constructor = false; + } + } + + if (proto_object_p == NULL) + { + ecma_object_t *prototype_p; + +#if JERRY_BUILTIN_REALMS + prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#else /* !JERRY_BUILTIN_REALMS */ + prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#endif /* JERRY_BUILTIN_REALMS */ + + proto_object_p = ecma_op_create_object_object_noarg_and_set_prototype (prototype_p); + } + + /* 17. */ + if (init_constructor) + { + ecma_property_value_t *constructor_prop_value_p; + constructor_prop_value_p = ecma_create_named_data_property (proto_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR), + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + + constructor_prop_value_p->value = ecma_make_object_value (object_p); + } + + /* 18. */ + ecma_property_t *prototype_prop_p; + ecma_property_value_t *prototype_prop_value_p; + prototype_prop_value_p = ecma_create_named_data_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE), + ECMA_PROPERTY_BUILT_IN_WRITABLE, + &prototype_prop_p); + + prototype_prop_value_p->value = ecma_make_object_value (proto_object_p); + + ecma_deref_object (proto_object_p); + + return prototype_prop_p; +} /* ecma_op_lazy_instantiate_prototype_object */ + +/** + * Lazy instantiation of non-builtin ecma function object's properties + * + * Warning: + * Only non-configurable properties could be instantiated lazily in this function, + * as configurable properties could be deleted and it would be incorrect + * to reinstantiate them in the function in second time. + * + * @return pointer to newly instantiated property, if a property was instantiated, + * NULL - otherwise + */ +ecma_property_t * +ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< the function object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION); + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + return NULL; + } + + /* Initialize 'length' property */ + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); + uint32_t len; + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; + len = args_p->argument_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; + len = args_p->argument_end; + } + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) + { + uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (bytecode_data_p); + + if (*extended_info_p & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) + { + len = ecma_extended_info_decode_vlq (&extended_info_p); + } + } + + ecma_property_t *value_prop_p; + ecma_property_value_t *value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &value_prop_p); + value_p->value = ecma_make_uint32_value (len); + return value_prop_p; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)) + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + return NULL; + } + + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); + + if (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_CONSTRUCTOR) + { + return NULL; + } + + ecma_value_t value = *ecma_compiled_code_resolve_function_name (bytecode_data_p); + JERRY_ASSERT (ecma_is_value_string (value)); + + /* Initialize 'name' property */ + ecma_property_t *value_prop_p; + ecma_property_value_t *value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &value_prop_p); + value_p->value = ecma_copy_value (value); + return value_prop_p; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE) + && ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + return ecma_op_lazy_instantiate_prototype_object (object_p); + } + + const bool is_arguments = ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_ARGUMENTS); + + if (is_arguments || ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER)) + { + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) + && CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_NORMAL) + { + ecma_property_t *value_prop_p; + /* The property_name_p argument contains the name. */ + ecma_property_value_t *value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_FIXED, &value_prop_p); + value_p->value = is_arguments ? ECMA_VALUE_NULL : ECMA_VALUE_UNDEFINED; + return value_prop_p; + } + } + + return NULL; +} /* ecma_op_function_try_to_lazy_instantiate_property */ + +/** + * Create specification defined non-configurable properties for external functions. + * + * See also: + * ECMA-262 v5, 15.3.4.5 + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_op_external_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE)) + { + return ecma_op_lazy_instantiate_prototype_object (object_p); + } + + return NULL; +} /* ecma_op_external_function_try_to_lazy_instantiate_property */ + +/** + * Create specification defined non-configurable properties for bound functions. + * + * See also: + * ECMA-262 v5, 15.3.4.5 + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + if (ecma_string_is_length (property_name_p)) + { + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + ecma_number_t length = 0; + ecma_integer_value_t args_length = 1; + uint8_t length_attributes; + + if (ecma_is_value_integer_number (args_len_or_this)) + { + args_length = ecma_get_integer_from_value (args_len_or_this); + } + + if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)) + { + return NULL; + } + + length_attributes = ECMA_PROPERTY_BUILT_IN_CONFIGURABLE; + length = ecma_get_number_from_value (bound_func_p->target_length) - (args_length - 1); + + if (length < 0) + { + length = 0; + } + + ecma_property_t *len_prop_p; + ecma_property_value_t *len_prop_value_p = + ecma_create_named_data_property (object_p, property_name_p, length_attributes, &len_prop_p); + + len_prop_value_p->value = ecma_make_number_value (length); + return len_prop_p; + } + + return NULL; +} /* ecma_op_bound_function_try_to_lazy_instantiate_property */ + +/** + * Delete configurable properties of functions. + */ +void +ecma_op_function_delete_built_in_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)); + ECMA_SET_FIRST_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp); + return; + } + + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); + JERRY_ASSERT (!ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)); + + ECMA_SET_SECOND_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp); +} /* ecma_op_function_delete_built_in_property */ + +/** + * Delete configurable properties of bound functions. + */ +void +ecma_op_bound_function_delete_built_in_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_UNUSED (property_name_p); + + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)); + JERRY_ASSERT (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)); + + ECMA_SET_FIRST_BIT_TO_POINTER_TAG (bound_func_p->header.u.bound_function.target_function); +} /* ecma_op_bound_function_delete_built_in_property */ + +/** + * List names of a Function object's lazy instantiated properties, + * adding them to corresponding string collections + * + * See also: + * ecma_op_function_try_to_lazy_instantiate_property + */ +void +ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functionobject */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + return; + } + + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + + if (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR + && !ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + /* Unintialized 'name' property is non-enumerable (ECMA-262 v6, 19.2.4.2) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_NAME)); + prop_counter_p->string_named_props++; + } + + if (!CBC_FUNCTION_HAS_PROTOTYPE (bytecode_data_p->status_flags) + || (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_CONSTRUCTOR)) + { + return; + } + + if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)) + { + /* 'arguments' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_ARGUMENTS)); + + /* 'caller' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER)); + + prop_counter_p->string_named_props += 2; + } + + /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE)); + prop_counter_p->string_named_props++; +} /* ecma_op_function_list_lazy_property_names */ + +/** + * List names of an External Function object's lazy instantiated properties, + * adding them to corresponding string collections + * + * See also: + * ecma_op_external_function_try_to_lazy_instantiate_property + */ +void +ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, /**< function object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name + * filter options */ +{ + JERRY_UNUSED (object_p); + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + return; + } + + /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE)); + prop_counter_p->string_named_props++; +} /* ecma_op_external_function_list_lazy_property_names */ + +/** + * List names of a Bound Function object's lazy instantiated properties, + * adding them to corresponding string collections + * + * See also: + * ecma_op_bound_function_try_to_lazy_instantiate_property + */ +void +ecma_op_bound_function_list_lazy_property_names (ecma_object_t *object_p, /**< bound function object*/ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + return; + } + + /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + + /* 'caller' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER)); + + /* 'arguments' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_ARGUMENTS)); + + prop_counter_p->string_named_props += 2; +} /* ecma_op_bound_function_list_lazy_property_names */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.h new file mode 100644 index 00000000..08300f57 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.h @@ -0,0 +1,130 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_FUNCTION_OBJECT_H +#define ECMA_FUNCTION_OBJECT_H + +#include "ecma-builtin-handlers.h" +#include "ecma-builtins.h" +#include "ecma-globals.h" + +#include "vm.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmafunctionobject ECMA Function object related routines + * @{ + */ + +ecma_value_t ecma_op_function_form_name (ecma_string_t *prop_name_p, char *prefix_p, lit_utf8_size_t prefix_size); + +bool ecma_op_is_callable (ecma_value_t value); +#if JERRY_BUILTIN_PROXY +bool ecma_op_proxy_object_is_callable (ecma_object_t *obj_p); +#endif /* JERRY_BUILTIN_PROXY */ +bool ecma_op_object_is_callable (ecma_object_t *obj_p); +bool ecma_is_constructor (ecma_value_t value); +bool ecma_object_is_constructor (ecma_object_t *obj_p); + +/** + * Special constant indicating that the value is a valid constructor + * + * Use after the ecma_*_check_constructor calls. + */ + +ecma_error_msg_t ecma_object_check_constructor (ecma_object_t *obj_p); +ecma_error_msg_t ecma_check_constructor (ecma_value_t value); + +ecma_object_t *ecma_op_create_simple_function_object (ecma_object_t *scope_p, + const ecma_compiled_code_t *bytecode_data_p); + +ecma_object_t *ecma_op_create_external_function_object (ecma_native_handler_t handler_cb); + +const ecma_compiled_code_t *ecma_op_function_get_compiled_code (ecma_extended_object_t *function_p); + +#if JERRY_BUILTIN_REALMS +ecma_global_object_t *ecma_op_function_get_realm (const ecma_compiled_code_t *bytecode_header_p); + +ecma_global_object_t *ecma_op_function_get_function_realm (ecma_object_t *func_obj_p); +#endif /* JERRY_BUILTIN_REALMS */ + +ecma_value_t ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len, + ecma_parse_opts_t opts); + +ecma_value_t ecma_op_function_get_super_constructor (ecma_object_t *func_obj_p); + +ecma_object_t *ecma_op_create_any_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p); + +ecma_object_t *ecma_op_create_arrow_function_object (ecma_object_t *scope_p, + const ecma_compiled_code_t *bytecode_data_p, + ecma_value_t this_binding); + +ecma_object_t *ecma_op_create_native_handler (ecma_native_handler_id_t id, size_t object_size); + +ecma_object_t *ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, ecma_builtin_id_t default_proto_id); + +ecma_value_t ecma_op_function_has_instance (ecma_object_t *func_obj_p, ecma_value_t value); + +ecma_value_t ecma_op_function_validated_call (ecma_value_t callee, + ecma_value_t this_arg_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +ecma_value_t ecma_op_function_call (ecma_object_t *func_obj_p, + ecma_value_t this_arg_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +ecma_value_t ecma_op_function_construct (ecma_object_t *func_obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +ecma_property_t *ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, + ecma_string_t *property_name_p); + +ecma_property_t *ecma_op_external_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, + ecma_string_t *property_name_p); + +ecma_property_t *ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, + ecma_string_t *property_name_p); + +void ecma_op_function_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +void ecma_op_bound_function_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +void ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +void ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +void ecma_op_bound_function_list_lazy_property_names (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +/** + * @} + * @} + */ + +#endif /* !ECMA_FUNCTION_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-get-put-value.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-get-put-value.cpp new file mode 100644 index 00000000..39d4d373 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-get-put-value.cpp @@ -0,0 +1,322 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of ECMA GetValue and PutValue + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-reference.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup lexicalenvironment Lexical environment + * @{ + */ + +/** + * GetValue operation part + * + * See also: ECMA-262 v5, 8.7.1, sections 3 and 5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_get_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_object_t **ref_base_lex_env_p, /**< [out] reference's base (lexical environment) */ + ecma_string_t *name_p) /**< variable name */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + + while (true) + { + switch (ecma_get_lex_env_type (lex_env_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL) + { + *ref_base_lex_env_p = lex_env_p; + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + return ecma_fast_copy_value (property_value_p->value); + } + break; + } + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { +#if JERRY_MODULE_SYSTEM + if (ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL) + { + *ref_base_lex_env_p = lex_env_p; + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + property_value_p = ecma_get_property_value_from_named_reference (property_value_p); + } + + if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + return ecma_fast_copy_value (property_value_p->value); + } + } +#endif /* JERRY_MODULE_SYSTEM */ + break; + } + default: + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_value_t result = ecma_op_object_bound_environment_resolve_reference_value (lex_env_p, name_p); + + if (ecma_is_value_found (result)) + { + /* Note: the result may contains ECMA_VALUE_ERROR */ + *ref_base_lex_env_p = lex_env_p; + return result; + } + + break; + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + *ref_base_lex_env_p = NULL; +#if JERRY_ERROR_MESSAGES + return ecma_raise_standard_error_with_format (JERRY_ERROR_REFERENCE, + "% is not defined", + ecma_make_string_value (name_p)); +#else /* JERRY_ERROR_MESSAGES */ + return ecma_raise_reference_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + +} /* ecma_op_get_value_lex_env_base */ + +/** + * GetValue operation part (object base). + * + * See also: ECMA-262 v5, 8.7.1, section 4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_get_value_object_base (ecma_value_t base_value, /**< base value */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_object_t *obj_p; + + if (JERRY_UNLIKELY (ecma_is_value_object (base_value))) + { + obj_p = ecma_get_object_from_value (base_value); + } + else + { + ecma_builtin_id_t id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; + + if (JERRY_LIKELY (ecma_is_value_string (base_value))) + { + ecma_string_t *string_p = ecma_get_string_from_value (base_value); + + if (ecma_string_is_length (property_name_p)) + { + return ecma_make_uint32_value (ecma_string_get_length (string_p)); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX && index < ecma_string_get_length (string_p)) + { + ecma_char_t char_at_idx = ecma_string_get_char_at_pos (string_p, index); + return ecma_make_string_value (ecma_new_ecma_string_from_code_unit (char_at_idx)); + } + +#if JERRY_BUILTIN_STRING + id = ECMA_BUILTIN_ID_STRING_PROTOTYPE; +#endif /* JERRY_BUILTIN_STRING */ + } + else if (ecma_is_value_number (base_value)) + { +#if JERRY_BUILTIN_NUMBER + id = ECMA_BUILTIN_ID_NUMBER_PROTOTYPE; +#endif /* JERRY_BUILTIN_NUMBER */ + } + else if (ecma_is_value_symbol (base_value)) + { + id = ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE; + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (base_value)) + { + id = ECMA_BUILTIN_ID_BIGINT_PROTOTYPE; + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + JERRY_ASSERT (ecma_is_value_boolean (base_value)); +#if JERRY_BUILTIN_BOOLEAN + id = ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE; +#endif /* JERRY_BUILTIN_BOOLEAN */ + } + + obj_p = ecma_builtin_get (id); + } + + return ecma_op_object_get_with_receiver (obj_p, property_name_p, base_value); +} /* ecma_op_get_value_object_base */ + +/** + * PutValue operation part + * + * See also: ECMA-262 v5, 8.7.2, sections 3 and 5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< variable name */ + bool is_strict, /**< flag indicating strict mode */ + ecma_value_t value) /**< ECMA-value */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + + while (true) + { + switch (ecma_get_lex_env_type (lex_env_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { + if (!ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + break; + } + /* FALLTHRU */ + } + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL) + { + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + JERRY_ASSERT (!(*property_p & ECMA_PROPERTY_FLAG_WRITABLE) || (*property_p & ECMA_PROPERTY_FLAG_DATA)); + + if ((*property_p & ECMA_PROPERTY_FLAG_WRITABLE) && property_value_p->value != ECMA_VALUE_UNINITIALIZED) + { + ecma_named_data_property_assign_value (lex_env_p, property_value_p, value); + return ECMA_VALUE_EMPTY; + } + + return ecma_op_raise_set_binding_error (property_p, is_strict); + } + break; + } + default: + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + ecma_value_t has_property = ecma_op_object_has_property (binding_obj_p, name_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (has_property)) + { + return has_property; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (has_property)) + { + ecma_value_t completion = ecma_op_object_put (binding_obj_p, name_p, value, is_strict); + + if (ECMA_IS_VALUE_ERROR (completion)) + { + return completion; + } + + JERRY_ASSERT (ecma_is_value_boolean (completion)); + return ECMA_VALUE_EMPTY; + } + + break; + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + if (is_strict) + { +#if JERRY_ERROR_MESSAGES + return ecma_raise_standard_error_with_format (JERRY_ERROR_REFERENCE, + "% is not defined", + ecma_make_string_value (name_p)); +#else /* !JERRY_ERROR_MESSAGES */ + return ecma_raise_reference_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + } + + ecma_value_t completion = ecma_op_object_put (ecma_get_lex_env_binding_object (lex_env_p), name_p, value, false); + + JERRY_ASSERT (ecma_is_value_boolean (completion)); + + return ECMA_VALUE_EMPTY; +} /* ecma_op_put_value_lex_env_base */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.cpp new file mode 100644 index 00000000..3e8ef7ea --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.cpp @@ -0,0 +1,719 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-iterator-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaiteratorobject ECMA iterator object related routines + * @{ + */ + +/** + * Implementation of 'CreateArrayFromList' specialized for iterators + * + * See also: + * ECMA-262 v6, 7.3.16. + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return new array object + */ +ecma_value_t +ecma_create_array_from_iter_element (ecma_value_t value, /**< value */ + ecma_value_t index_value) /**< iterator index */ +{ + /* 2. */ + ecma_object_t *new_array_p = ecma_op_new_array_object (0); + + /* 3-4. */ + ecma_value_t completion; + completion = + ecma_builtin_helper_def_prop_by_index (new_array_p, 0, index_value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + /* 4.b */ + JERRY_ASSERT (ecma_is_value_true (completion)); + + completion = + ecma_builtin_helper_def_prop_by_index (new_array_p, 1, value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (completion)); + + /* 5. */ + return ecma_make_object_value (new_array_p); +} /* ecma_create_array_from_iter_element */ + +/** + * CreateIterResultObject operation + * + * See also: + * ECMA-262 v6, 7.4.7. + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object + */ +ecma_value_t +ecma_create_iter_result_object (ecma_value_t value, /**< value */ + ecma_value_t done) /**< ECMA_VALUE_{TRUE,FALSE} based + * on the iterator index */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_boolean (done)); + + /* 2. */ + ecma_object_t *object_p = + ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL); + + /* 3. */ + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_VALUE), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + prop_value_p->value = ecma_copy_value_if_not_object (value); + + /* 4. */ + prop_value_p = ecma_create_named_data_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_DONE), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + prop_value_p->value = done; + + /* 5. */ + return ecma_make_object_value (object_p); +} /* ecma_create_iter_result_object */ + +/** + * General iterator object creation operation. + * + * See also: ECMA-262 v6, 21.1.5.1, 22.1.5.1, 23.1.5.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator object + */ +ecma_value_t +ecma_op_create_iterator_object (ecma_value_t iterated_value, /**< value from create iterator */ + ecma_object_t *prototype_obj_p, /**< prototype object */ + ecma_object_class_type_t iterator_type, /**< iterator type */ + ecma_iterator_kind_t kind) /**< iterator kind*/ +{ + /* 1. */ + JERRY_ASSERT (iterator_type == ECMA_OBJECT_CLASS_ARRAY_ITERATOR || iterator_type == ECMA_OBJECT_CLASS_SET_ITERATOR + || iterator_type == ECMA_OBJECT_CLASS_MAP_ITERATOR + || iterator_type == ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR + || iterator_type == ECMA_OBJECT_CLASS_STRING_ITERATOR); + JERRY_ASSERT (kind < ECMA_ITERATOR__COUNT); + + /* 2. */ + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.cls.type = (uint8_t) iterator_type; + + /* 3. */ + ext_obj_p->u.cls.u3.iterated_value = iterated_value; + /* 4. */ + ext_obj_p->u.cls.u2.iterator_index = 0; + /* 5. */ + ext_obj_p->u.cls.u1.iterator_kind = (uint8_t) kind; + + /* 6. */ + return ecma_make_object_value (object_p); +} /* ecma_op_create_iterator_object */ + +/** + * GetIterator operation + * + * See also: ECMA-262 v10, 7.4.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator object - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_get_iterator (ecma_value_t value, /**< value to get iterator from */ + ecma_value_t method, /**< provided method argument */ + ecma_value_t *next_method_p) /**< [out] next method */ +{ + JERRY_ASSERT (next_method_p != NULL); + *next_method_p = ECMA_VALUE_UNDEFINED; + + /* 1. */ + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + bool use_default_method = false; + + /* 2. */ + if (method == ECMA_VALUE_SYNC_ITERATOR) + { + /* 2.a */ + use_default_method = true; + method = ecma_op_get_method_by_symbol_id (value, LIT_GLOBAL_SYMBOL_ITERATOR); + + /* 2.b */ + if (ECMA_IS_VALUE_ERROR (method)) + { + return method; + } + } + /* 3.a */ + else if (method == ECMA_VALUE_ASYNC_ITERATOR) + { + use_default_method = true; + + /* 3.a.i */ + method = ecma_op_get_method_by_symbol_id (value, LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR); + + if (ECMA_IS_VALUE_ERROR (method)) + { + return method; + } + + /* 3.a.ii */ + + if (ecma_is_value_undefined (method)) + { + method = ecma_op_get_method_by_symbol_id (value, LIT_GLOBAL_SYMBOL_ITERATOR); + + if (ECMA_IS_VALUE_ERROR (method)) + { + return method; + } + + ecma_value_t sync_next_method; + ecma_value_t sync_iterator = ecma_op_get_iterator (value, method, &sync_next_method); + + if (ECMA_IS_VALUE_ERROR (sync_iterator)) + { + ecma_free_value (method); + return sync_iterator; + } + + ecma_value_t async_iterator = + ecma_op_create_async_from_sync_iterator (sync_iterator, sync_next_method, next_method_p); + + ecma_free_value (method); + ecma_free_value (sync_iterator); + ecma_free_value (sync_next_method); + + return async_iterator; + } + } + + /* 3. */ + ecma_value_t iterator = ecma_op_function_validated_call (method, value, NULL, 0); + + if (use_default_method) + { + ecma_free_value (method); + } + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (iterator)) + { + return iterator; + } + + /* 5. */ + if (!ecma_is_value_object (iterator)) + { + ecma_free_value (iterator); + return ecma_raise_type_error (ECMA_ERR_ITERATOR_IS_NOT_AN_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (iterator); + ecma_value_t next_method = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_NEXT); + + if (ECMA_IS_VALUE_ERROR (next_method)) + { + ecma_free_value (iterator); + return next_method; + } + + if (ecma_op_is_callable (next_method)) + { + *next_method_p = next_method; + } + else + { + ecma_free_value (next_method); + } + + /* 6. */ + return iterator; +} /* ecma_op_get_iterator */ + +/** + * IteratorNext operation + * + * See also: ECMA-262 v10, 7.4.2 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_iterator_next (ecma_value_t iterator, /**< iterator value */ + ecma_value_t next_method, /**< next method */ + ecma_value_t value) /**< the routines's value argument */ +{ + JERRY_ASSERT (ecma_is_value_object (iterator)); + + /* 1 - 2. */ + if (next_method == ECMA_VALUE_UNDEFINED) + { + return ecma_raise_type_error (ECMA_ERR_ITERATOR_NEXT_IS_NOT_CALLABLE); + } + + ecma_object_t *next_method_obj_p = ecma_get_object_from_value (next_method); + + bool has_value = !ecma_is_value_empty (value); + + if (has_value) + { + return ecma_op_function_call (next_method_obj_p, iterator, &value, 1); + } + + return ecma_op_function_call (next_method_obj_p, iterator, NULL, 0); +} /* ecma_op_iterator_next */ + +/** + * IteratorReturn operation + * + * See also: ECMA-262 v6, 14.4.14 (last part) + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object - if success + * raised error - otherwise + */ +static ecma_value_t +ecma_op_iterator_return (ecma_value_t iterator, /**< iterator value */ + ecma_value_t value) /**< the routines's value argument */ +{ + JERRY_ASSERT (ecma_is_value_object (iterator)); + + ecma_object_t *obj_p = ecma_get_object_from_value (iterator); + ecma_value_t func_return = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_RETURN); + + if (ECMA_IS_VALUE_ERROR (func_return)) + { + return func_return; + } + + if (func_return == ECMA_VALUE_UNDEFINED) + { + return ecma_create_iter_result_object (value, ECMA_VALUE_TRUE); + } + + ecma_value_t result = ecma_op_function_validated_call (func_return, iterator, &value, 1); + ecma_free_value (func_return); + + return result; +} /* ecma_op_iterator_return */ + +/** + * IteratorThrow operation + * + * See also: ECMA-262 v6, 14.4.14 (last part) + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object - if success + * raised error - otherwise + */ +static ecma_value_t +ecma_op_iterator_throw (ecma_value_t iterator, /**< iterator value */ + ecma_value_t value) /**< the routines's value argument */ +{ + JERRY_ASSERT (ecma_is_value_object (iterator)); + + ecma_object_t *obj_p = ecma_get_object_from_value (iterator); + ecma_value_t func_throw = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_THROW); + + if (ECMA_IS_VALUE_ERROR (func_throw)) + { + return func_throw; + } + + if (func_throw == ECMA_VALUE_UNDEFINED) + { + ecma_value_t result = ecma_op_iterator_close (iterator); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_free_value (result); + return ecma_raise_type_error (ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE); + } + + ecma_value_t result = ecma_op_function_validated_call (func_throw, iterator, &value, 1); + ecma_free_value (func_throw); + + return result; +} /* ecma_op_iterator_throw */ + +/** + * IteratorComplete operation + * + * See also: ECMA-262 v10, 7.4.3 + * + * @return true/false - whether the iteration ended + */ +ecma_value_t +ecma_op_iterator_complete (ecma_value_t iter_result) /**< iterator value */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (iter_result)); + + /* 2. */ + ecma_object_t *obj_p = ecma_get_object_from_value (iter_result); + + ecma_value_t done = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_DONE); + + if (ECMA_IS_VALUE_ERROR (done)) + { + return done; + } + + ecma_value_t res = ecma_make_boolean_value (ecma_op_to_boolean (done)); + ecma_free_value (done); + + return res; +} /* ecma_op_iterator_complete */ + +/** + * IteratorValue operation + * + * See also: ECMA-262 v6, 7.4.4 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return value of the iterator result object + */ +ecma_value_t +ecma_op_iterator_value (ecma_value_t iter_result) /**< iterator value */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (iter_result)); + + /* 2. */ + ecma_object_t *obj_p = ecma_get_object_from_value (iter_result); + return ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_VALUE); +} /* ecma_op_iterator_value */ + +/** + * IteratorClose operation + * + * See also: ECMA-262 v6, 7.4.6 + * + * @return ECMA_VALUE_EMPTY - if "return" is succesfully invoked, + * and the operation is called with normal completion + * ECMA_VALUE_ERROR - otherwise + */ +ecma_value_t +ecma_op_iterator_close (ecma_value_t iterator) /**< iterator value */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (iterator)); + + /* 2. */ + ecma_value_t completion = ECMA_VALUE_EMPTY; + + if (jcontext_has_pending_exception ()) + { + completion = jcontext_take_exception (); + } + + /* 3. */ + ecma_value_t return_method = ecma_op_get_method_by_magic_id (iterator, LIT_MAGIC_STRING_RETURN); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (return_method)) + { + ecma_free_value (completion); + return return_method; + } + + /* 5. */ + if (ecma_is_value_undefined (return_method)) + { + if (ecma_is_value_empty (completion)) + { + return ECMA_VALUE_UNDEFINED; + } + + jcontext_raise_exception (completion); + return ECMA_VALUE_ERROR; + } + + /* 6. */ + ecma_object_t *return_obj_p = ecma_get_object_from_value (return_method); + ecma_value_t inner_result = ecma_op_function_call (return_obj_p, iterator, NULL, 0); + ecma_deref_object (return_obj_p); + + /* 7. */ + if (!ecma_is_value_empty (completion)) + { + if (ECMA_IS_VALUE_ERROR (inner_result)) + { + jcontext_release_exception (); + } + else + { + ecma_free_value (inner_result); + } + + jcontext_raise_exception (completion); + return ECMA_VALUE_ERROR; + } + + /* 8. */ + if (ECMA_IS_VALUE_ERROR (inner_result)) + { + ecma_free_value (completion); + return inner_result; + } + + /* 9. */ + bool is_object = ecma_is_value_object (inner_result); + ecma_free_value (inner_result); + + if (!is_object) + { + ecma_free_value (completion); + return ecma_raise_type_error (ECMA_ERR_METHOD_RETURN_IS_NOT_CALLABLE); + } + + /* 10. */ + if (ecma_is_value_empty (completion)) + { + return ECMA_VALUE_UNDEFINED; + } + + jcontext_raise_exception (completion); + return ECMA_VALUE_ERROR; +} /* ecma_op_iterator_close */ + +/** + * IteratorStep operation + * + * See also: ECMA-262 v6, 7.4.5 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator object or ECMA_VALUE_FALSE - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_iterator_step (ecma_value_t iterator, /**< iterator value */ + ecma_value_t next_method) /**< next method */ +{ + /* 1. */ + ecma_value_t result = ecma_op_iterator_next (iterator, next_method, ECMA_VALUE_EMPTY); + + /* 2. */ + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (!ecma_is_value_object (result)) + { + ecma_free_value (result); + return ecma_raise_type_error (ECMA_ERR_ITERATOR_RESULT_IS_NOT_AN_OBJECT); + } + + /* 3. */ + ecma_object_t *obj_p = ecma_get_object_from_value (result); + ecma_value_t done = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_DONE); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (done)) + { + ecma_free_value (result); + return done; + } + + bool is_done = ecma_op_to_boolean (done); + ecma_free_value (done); + + /* 5. */ + if (is_done) + { + ecma_free_value (result); + return ECMA_VALUE_FALSE; + } + + /* 6. */ + return result; +} /* ecma_op_iterator_step */ + +/** + * Perform a command specified by the command argument + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator object - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_iterator_do (ecma_iterator_command_type_t command, /**< command to be executed */ + ecma_value_t iterator, /**< iterator object */ + ecma_value_t next_method, /**< next method */ + ecma_value_t value, /**< the routines's value argument */ + bool *done_p) /**< it contains the logical value of the done property */ +{ + ecma_value_t result; + + if (command == ECMA_ITERATOR_NEXT) + { + result = ecma_op_iterator_next (iterator, next_method, value); + } + else if (command == ECMA_ITERATOR_THROW) + { + result = ecma_op_iterator_throw (iterator, value); + } + else + { + JERRY_ASSERT (command == ECMA_ITERATOR_RETURN); + result = ecma_op_iterator_return (iterator, value); + } + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (!ecma_is_value_object (result)) + { + ecma_free_value (result); + return ecma_raise_type_error (ECMA_ERR_ITERATOR_RESULT_IS_NOT_AN_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (result); + ecma_value_t done = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_DONE); + + if (ECMA_IS_VALUE_ERROR (done)) + { + ecma_free_value (result); + return done; + } + + *done_p = ecma_op_to_boolean (done); + ecma_free_value (done); + + return result; +} /* ecma_op_iterator_do */ + +/** + * CreateAsyncFromSyncIterator operation + * + * See also: ECMA-262 v10, 25.1.4.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return async from sync iterator object + */ +ecma_value_t +ecma_op_create_async_from_sync_iterator (ecma_value_t sync_iterator, /**< sync iterator */ + ecma_value_t sync_next_method, /**< sync iterator next method */ + ecma_value_t *async_next_method_p) /**< [out] async next method */ +{ + JERRY_ASSERT (ecma_is_value_object (sync_iterator)); + JERRY_ASSERT (ecma_is_value_object (sync_next_method) || ecma_is_value_undefined (sync_next_method)); + + /* 1. */ + ecma_object_t *obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE), + sizeof (ecma_async_from_sync_iterator_object_t), + ECMA_OBJECT_TYPE_CLASS); + + ecma_async_from_sync_iterator_object_t *ext_obj_p = (ecma_async_from_sync_iterator_object_t *) obj_p; + + /* 2. */ + ext_obj_p->sync_next_method = sync_next_method; + ext_obj_p->header.u.cls.u3.sync_iterator = sync_iterator; + ext_obj_p->header.u.cls.type = ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR; + + /* 3. */ + *async_next_method_p = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_NEXT); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (*async_next_method_p)); + + /* 4. */ + return ecma_make_object_value (obj_p); +} /* ecma_op_create_async_from_sync_iterator */ + +/** + * Async-from-Sync Iterator Value Unwrap Functions + * + * See also: ES11 25.1.4.2.4 + * + * @return iterator result object + */ +ecma_value_t +ecma_async_from_sync_iterator_unwrap_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + ecma_extended_object_t *unwrap_p = (ecma_extended_object_t *) function_obj_p; + + /* 2. */ + ecma_value_t arg = args_count > 0 ? args_p[0] : ECMA_VALUE_UNDEFINED; + ecma_value_t done = + ecma_make_boolean_value (unwrap_p->u.built_in.u2.routine_flags >> ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT); + + return ecma_create_iter_result_object (arg, done); +} /* ecma_async_from_sync_iterator_unwrap_cb */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.h new file mode 100644 index 00000000..0963b03f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.h @@ -0,0 +1,84 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ITERATOR_OBJECT_H +#define ECMA_ITERATOR_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaiteratorobject ECMA iterator object related routines + * @{ + */ + +/** + * Generator resume execution flags. + */ +typedef enum +{ + ECMA_ITERATOR_NEXT, /**< generator should continue its execution */ + ECMA_ITERATOR_THROW, /**< generator should perform a throw operation */ + ECMA_ITERATOR_RETURN, /**< generator should perform a return operation */ +} ecma_iterator_command_type_t; + +/** + * Maximum value of [[%Iterator%NextIndex]] until it can be stored + * in an ecma pseudo array object structure element. + */ +#define ECMA_ITERATOR_INDEX_LIMIT UINT16_MAX + +ecma_value_t ecma_op_create_iterator_object (ecma_value_t iterated_value, + ecma_object_t *prototype_obj_p, + ecma_object_class_type_t iterator_type, + ecma_iterator_kind_t kind); + +ecma_value_t ecma_create_iter_result_object (ecma_value_t value, ecma_value_t done); + +ecma_value_t ecma_create_array_from_iter_element (ecma_value_t value, ecma_value_t index_value); + +ecma_value_t ecma_op_get_iterator (ecma_value_t value, ecma_value_t method, ecma_value_t *next_method_p); + +ecma_value_t ecma_op_iterator_complete (ecma_value_t iter_result); + +ecma_value_t ecma_op_iterator_value (ecma_value_t iter_result); + +ecma_value_t ecma_op_iterator_next (ecma_value_t iterator, ecma_value_t next_method, ecma_value_t value); + +ecma_value_t ecma_op_iterator_close (ecma_value_t iterator); + +ecma_value_t ecma_op_iterator_step (ecma_value_t iterator, ecma_value_t next_method); + +ecma_value_t ecma_op_iterator_do (ecma_iterator_command_type_t command, + ecma_value_t iterator, + ecma_value_t next_method, + ecma_value_t value, + bool *done_p); + +ecma_value_t ecma_op_create_async_from_sync_iterator (ecma_value_t sync_iterator, + ecma_value_t sync_next_method, + ecma_value_t *async_next_method_p); + +ecma_value_t ecma_async_from_sync_iterator_unwrap_cb (ecma_object_t *function_obj_p, + const ecma_value_t args_p[], + const uint32_t args_count); + +/** + * @} + * @} + */ + +#endif /* !ECMA_ITERATOR_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.cpp new file mode 100644 index 00000000..4826676b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.cpp @@ -0,0 +1,582 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-jobqueue.h" + +#include "ecma-async-generator-object.h" +#include "ecma-function-object.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" +#include "opcodes.h" +#include "vm-stack.h" + +/** + * Mask for job queue type. + */ +#define ECMA_JOB_QUEURE_TYPE_MASK ((uintptr_t) 0x07) + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmajobqueue ECMA Job Queue related routines + * @{ + */ + +/** + * Description of the PromiseReactionJob + */ +typedef struct +{ + ecma_job_queue_item_t header; /**< job queue item header */ + ecma_value_t capability; /**< capability object */ + ecma_value_t handler; /**< handler function */ + ecma_value_t argument; /**< argument for the reaction */ +} ecma_job_promise_reaction_t; + +/** + * Description of the PromiseAsyncReactionJob + */ +typedef struct +{ + ecma_job_queue_item_t header; /**< job queue item header */ + ecma_value_t executable_object; /**< executable object */ + ecma_value_t argument; /**< argument for the reaction */ +} ecma_job_promise_async_reaction_t; + +/** + * Description of the PromiseAsyncGeneratorJob + */ +typedef struct +{ + ecma_job_queue_item_t header; /**< job queue item header */ + ecma_value_t executable_object; /**< executable object */ +} ecma_job_promise_async_generator_t; + +/** + * Description of the PromiseResolveThenableJob + */ +typedef struct +{ + ecma_job_queue_item_t header; /**< job queue item header */ + ecma_value_t promise; /**< promise to be resolved */ + ecma_value_t thenable; /**< thenable object */ + ecma_value_t then; /**< 'then' function */ +} ecma_job_promise_resolve_thenable_t; + +/** + * Initialize the jobqueue. + */ +void +ecma_job_queue_init (void) +{ + JERRY_CONTEXT (job_queue_head_p) = NULL; + JERRY_CONTEXT (job_queue_tail_p) = NULL; +} /* ecma_job_queue_init */ + +/** + * Get the type of the job. + * + * @return type of the job + */ +static inline ecma_job_queue_item_type_t +ecma_job_queue_get_type (ecma_job_queue_item_t *job_p) /**< the job */ +{ + return (ecma_job_queue_item_type_t) (job_p->next_and_type & ECMA_JOB_QUEURE_TYPE_MASK); +} /* ecma_job_queue_get_type */ + +/** + * Get the next job of the job queue. + * + * @return next job + */ +static inline ecma_job_queue_item_t * +ecma_job_queue_get_next (ecma_job_queue_item_t *job_p) /**< the job */ +{ + return (ecma_job_queue_item_t *) (job_p->next_and_type & ~ECMA_JOB_QUEURE_TYPE_MASK); +} /* ecma_job_queue_get_next */ + +/** + * Free the heap and the member of the PromiseReactionJob. + */ +static void +ecma_free_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< points to the PromiseReactionJob */ +{ + JERRY_ASSERT (job_p != NULL); + + ecma_free_value (job_p->capability); + ecma_free_value (job_p->handler); + ecma_free_value (job_p->argument); + + jmem_heap_free_block (job_p, sizeof (ecma_job_promise_reaction_t)); +} /* ecma_free_promise_reaction_job */ + +/** + * Free the heap and the member of the PromiseAsyncReactionJob. + */ +static void +ecma_free_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_p) /**< points to the + * PromiseAsyncReactionJob */ +{ + JERRY_ASSERT (job_p != NULL); + + ecma_free_value (job_p->executable_object); + ecma_free_value (job_p->argument); + + jmem_heap_free_block (job_p, sizeof (ecma_job_promise_async_reaction_t)); +} /* ecma_free_promise_async_reaction_job */ + +/** + * Free the heap and the member of the PromiseAsyncGeneratorJob. + */ +static void +ecma_free_promise_async_generator_job (ecma_job_promise_async_generator_t *job_p) /**< points to the + * PromiseAsyncReactionJob */ +{ + JERRY_ASSERT (job_p != NULL); + + ecma_free_value (job_p->executable_object); + + jmem_heap_free_block (job_p, sizeof (ecma_job_promise_async_generator_t)); +} /* ecma_free_promise_async_generator_job */ + +/** + * Free the heap and the member of the PromiseResolveThenableJob. + */ +static void +ecma_free_promise_resolve_thenable_job (ecma_job_promise_resolve_thenable_t *job_p) /**< points to the + * PromiseResolveThenableJob */ +{ + JERRY_ASSERT (job_p != NULL); + + ecma_free_value (job_p->promise); + ecma_free_value (job_p->thenable); + ecma_free_value (job_p->then); + + jmem_heap_free_block (job_p, sizeof (ecma_job_promise_resolve_thenable_t)); +} /* ecma_free_promise_resolve_thenable_job */ + +/** + * The processor for PromiseReactionJob. + * + * See also: ES2015 25.4.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_process_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< the job to be operated */ +{ + /* 2. */ + JERRY_ASSERT ( + ecma_object_class_is (ecma_get_object_from_value (job_p->capability), ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + ecma_promise_capabality_t *capability_p; + capability_p = (ecma_promise_capabality_t *) ecma_get_object_from_value (job_p->capability); + + /* 3. */ + ecma_value_t handler = job_p->handler; + + JERRY_ASSERT (ecma_is_value_boolean (handler) || ecma_op_is_callable (handler)); + + ecma_value_t handler_result; + + if (ecma_is_value_boolean (handler)) + { + /* 4-5. True indicates "identity" and false indicates "thrower" */ + handler_result = ecma_copy_value (job_p->argument); + } + else + { + /* 6. */ + handler_result = + ecma_op_function_call (ecma_get_object_from_value (handler), ECMA_VALUE_UNDEFINED, &(job_p->argument), 1); + } + + ecma_value_t status; + + if (ecma_is_value_false (handler) || ECMA_IS_VALUE_ERROR (handler_result)) + { + if (ECMA_IS_VALUE_ERROR (handler_result)) + { + handler_result = jcontext_take_exception (); + } + + /* 7. */ + status = ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), + ECMA_VALUE_UNDEFINED, + &handler_result, + 1); + } + else + { + /* 8. */ + status = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), + ECMA_VALUE_UNDEFINED, + &handler_result, + 1); + } + + ecma_free_value (handler_result); + + ecma_free_promise_reaction_job (job_p); + + return status; +} /* ecma_process_promise_reaction_job */ + +/** + * The processor for PromiseAsyncReactionJob. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_process_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_p) /**< the job to be operated */ +{ + ecma_object_t *object_p = ecma_get_object_from_value (job_p->executable_object); + vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p; + + if (ecma_job_queue_get_type (&job_p->header) == ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED) + { + if (!(executable_object_p->extended_object.u.cls.u2.executable_obj_flags + & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD)) + { + executable_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + } + else if (ECMA_AWAIT_GET_STATE (executable_object_p) == ECMA_AWAIT_YIELD_RETURN) + { + /* Unlike other operations, return captures rejected promises as well. */ + ECMA_AWAIT_CHANGE_STATE (executable_object_p, YIELD_RETURN, YIELD_OPERATION); + } + else + { + if (ECMA_AWAIT_GET_STATE (executable_object_p) <= ECMA_AWAIT_YIELD_END) + { + JERRY_ASSERT (ecma_is_value_object (executable_object_p->iterator)); + executable_object_p->iterator = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (executable_object_p->frame_ctx.stack_top_p[-1] == ECMA_VALUE_UNDEFINED + || ecma_is_value_object (executable_object_p->frame_ctx.stack_top_p[-1])); + executable_object_p->frame_ctx.stack_top_p--; + } + else if (ECMA_AWAIT_GET_STATE (executable_object_p) == ECMA_AWAIT_FOR_CLOSE + && VM_GET_CONTEXT_TYPE (executable_object_p->frame_ctx.stack_top_p[-1]) == VM_CONTEXT_FINALLY_THROW) + { + ecma_free_value (job_p->argument); + job_p->argument = ecma_copy_value (executable_object_p->frame_ctx.stack_top_p[-2]); + } + + /* Exception: Abort iterators, clear all status. */ + executable_object_p->extended_object.u.cls.u2.executable_obj_flags &= ECMA_AWAIT_CLEAR_MASK; + executable_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + } + } + + ecma_value_t result; + uint16_t expected_bits; + + if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + { + job_p->argument = ecma_await_continue (executable_object_p, job_p->argument); + + if (ECMA_IS_VALUE_ERROR (job_p->argument)) + { + job_p->argument = jcontext_take_exception (); + executable_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + } + else if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags + & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + { + /* Continue iteration. */ + JERRY_ASSERT (job_p->argument == ECMA_VALUE_UNDEFINED); + result = ECMA_VALUE_UNDEFINED; + goto free_job; + } + + if (ECMA_AWAIT_GET_STATE (executable_object_p) <= ECMA_AWAIT_YIELD_END) + { + JERRY_ASSERT (ecma_is_value_object (executable_object_p->iterator)); + executable_object_p->iterator = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (executable_object_p->frame_ctx.stack_top_p[-1] == ECMA_VALUE_UNDEFINED + || ecma_is_value_object (executable_object_p->frame_ctx.stack_top_p[-1])); + executable_object_p->frame_ctx.stack_top_p--; + } + + /* Clear all status. */ + executable_object_p->extended_object.u.cls.u2.executable_obj_flags &= ECMA_AWAIT_CLEAR_MASK; + } + + result = opfunc_resume_executable_object (executable_object_p, job_p->argument); + /* Argument reference has been taken by opfunc_resume_executable_object. */ + job_p->argument = ECMA_VALUE_UNDEFINED; + + expected_bits = (ECMA_EXECUTABLE_OBJECT_COMPLETED | ECMA_ASYNC_GENERATOR_CALLED); + if ((executable_object_p->extended_object.u.cls.u2.executable_obj_flags & expected_bits) == expected_bits) + { + ecma_async_generator_finalize (executable_object_p, result); + result = ECMA_VALUE_UNDEFINED; + } + +free_job: + + ecma_free_promise_async_reaction_job (job_p); + return result; +} /* ecma_process_promise_async_reaction_job */ + +/** + * The processor for PromiseAsyncGeneratorJob. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_process_promise_async_generator_job (ecma_job_promise_async_generator_t *job_p) /**< the job to be operated */ +{ + ecma_object_t *object_p = ecma_get_object_from_value (job_p->executable_object); + + ecma_value_t result = ecma_async_generator_run ((vm_executable_object_t *) object_p); + + ecma_free_value (job_p->executable_object); + jmem_heap_free_block (job_p, sizeof (ecma_job_promise_async_generator_t)); + return result; +} /* ecma_process_promise_async_generator_job */ + +/** + * Process the PromiseResolveThenableJob. + * + * See also: ES2015 25.4.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_process_promise_resolve_thenable_job (ecma_job_promise_resolve_thenable_t *job_p) /**< the job to be operated */ +{ + ecma_promise_object_t *promise_p = (ecma_promise_object_t *) ecma_get_object_from_value (job_p->promise); + + promise_p->header.u.cls.u1.promise_flags &= (uint8_t) ~ECMA_PROMISE_ALREADY_RESOLVED; + + ecma_value_t ret = ecma_promise_run_executor ((ecma_object_t *) promise_p, job_p->then, job_p->thenable); + + if (ECMA_IS_VALUE_ERROR (ret)) + { + ret = jcontext_take_exception (); + ecma_reject_promise_with_checks (job_p->promise, ret); + ecma_free_value (ret); + ret = ECMA_VALUE_UNDEFINED; + } + + ecma_free_promise_resolve_thenable_job (job_p); + + return ret; +} /* ecma_process_promise_resolve_thenable_job */ + +/** + * Enqueue a Promise job into the jobqueue. + */ +static void +ecma_enqueue_job (ecma_job_queue_item_t *job_p) /**< the job */ +{ + JERRY_ASSERT (job_p->next_and_type <= ECMA_JOB_QUEURE_TYPE_MASK); + + if (JERRY_CONTEXT (job_queue_head_p) == NULL) + { + JERRY_CONTEXT (job_queue_head_p) = job_p; + JERRY_CONTEXT (job_queue_tail_p) = job_p; + } + else + { + JERRY_ASSERT ((JERRY_CONTEXT (job_queue_tail_p)->next_and_type & ~ECMA_JOB_QUEURE_TYPE_MASK) == 0); + + JERRY_CONTEXT (job_queue_tail_p)->next_and_type |= (uintptr_t) job_p; + JERRY_CONTEXT (job_queue_tail_p) = job_p; + } +} /* ecma_enqueue_job */ + +/** + * Enqueue a PromiseReactionJob into the job queue. + */ +void +ecma_enqueue_promise_reaction_job (ecma_value_t capability, /**< capability object */ + ecma_value_t handler, /**< handler function */ + ecma_value_t argument) /**< argument for the reaction */ +{ + ecma_job_promise_reaction_t *job_p; + job_p = (ecma_job_promise_reaction_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_reaction_t)); + job_p->header.next_and_type = ECMA_JOB_PROMISE_REACTION; + job_p->capability = ecma_copy_value (capability); + job_p->handler = ecma_copy_value (handler); + job_p->argument = ecma_copy_value (argument); + + ecma_enqueue_job (&job_p->header); +} /* ecma_enqueue_promise_reaction_job */ + +/** + * Enqueue a PromiseAsyncReactionJob into the job queue. + */ +void +ecma_enqueue_promise_async_reaction_job (ecma_value_t executable_object, /**< executable object */ + ecma_value_t argument, /**< argument */ + bool is_rejected) /**< is_fulfilled */ +{ + ecma_job_promise_async_reaction_t *job_p; + job_p = (ecma_job_promise_async_reaction_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_async_reaction_t)); + job_p->header.next_and_type = + (is_rejected ? ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED : ECMA_JOB_PROMISE_ASYNC_REACTION_FULFILLED); + job_p->executable_object = ecma_copy_value (executable_object); + job_p->argument = ecma_copy_value (argument); + + ecma_enqueue_job (&job_p->header); +} /* ecma_enqueue_promise_async_reaction_job */ + +/** + * Enqueue a PromiseAsyncGeneratorJob into the job queue. + */ +void +ecma_enqueue_promise_async_generator_job (ecma_value_t executable_object) /**< executable object */ +{ + ecma_job_promise_async_generator_t *job_p; + job_p = (ecma_job_promise_async_generator_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_async_generator_t)); + job_p->header.next_and_type = ECMA_JOB_PROMISE_ASYNC_GENERATOR; + job_p->executable_object = ecma_copy_value (executable_object); + + ecma_enqueue_job (&job_p->header); +} /* ecma_enqueue_promise_async_generator_job */ + +/** + * Enqueue a PromiseResolveThenableJob into the job queue. + */ +void +ecma_enqueue_promise_resolve_thenable_job (ecma_value_t promise, /**< promise to be resolved */ + ecma_value_t thenable, /**< thenable object */ + ecma_value_t then) /**< 'then' function */ +{ + JERRY_ASSERT (ecma_is_promise (ecma_get_object_from_value (promise))); + JERRY_ASSERT (ecma_is_value_object (thenable)); + JERRY_ASSERT (ecma_op_is_callable (then)); + + ecma_job_promise_resolve_thenable_t *job_p; + job_p = (ecma_job_promise_resolve_thenable_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_resolve_thenable_t)); + job_p->header.next_and_type = ECMA_JOB_PROMISE_THENABLE; + job_p->promise = ecma_copy_value (promise); + job_p->thenable = ecma_copy_value (thenable); + job_p->then = ecma_copy_value (then); + + ecma_enqueue_job (&job_p->header); +} /* ecma_enqueue_promise_resolve_thenable_job */ + +/** + * Process enqueued Promise jobs until the first thrown error or until the + * jobqueue becomes empty. + * + * @return result of the last processed job - if the jobqueue was non-empty, + * undefined - otherwise. + */ +ecma_value_t +ecma_process_all_enqueued_jobs (void) +{ + ecma_value_t ret = ECMA_VALUE_UNDEFINED; + + while (JERRY_CONTEXT (job_queue_head_p) != NULL) + { + ecma_job_queue_item_t *job_p = JERRY_CONTEXT (job_queue_head_p); + JERRY_CONTEXT (job_queue_head_p) = ecma_job_queue_get_next (job_p); + + ecma_fast_free_value (ret); + + switch (ecma_job_queue_get_type (job_p)) + { + case ECMA_JOB_PROMISE_REACTION: + { + ret = ecma_process_promise_reaction_job ((ecma_job_promise_reaction_t *) job_p); + break; + } + case ECMA_JOB_PROMISE_ASYNC_REACTION_FULFILLED: + case ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED: + { + ret = ecma_process_promise_async_reaction_job ((ecma_job_promise_async_reaction_t *) job_p); + break; + } + case ECMA_JOB_PROMISE_ASYNC_GENERATOR: + { + ret = ecma_process_promise_async_generator_job ((ecma_job_promise_async_generator_t *) job_p); + break; + } + default: + { + JERRY_ASSERT (ecma_job_queue_get_type (job_p) == ECMA_JOB_PROMISE_THENABLE); + + ret = ecma_process_promise_resolve_thenable_job ((ecma_job_promise_resolve_thenable_t *) job_p); + break; + } + } + + if (ECMA_IS_VALUE_ERROR (ret)) + { + return ret; + } + } + + ecma_free_value (ret); + return ECMA_VALUE_UNDEFINED; +} /* ecma_process_all_enqueued_jobs */ + +/** + * Release enqueued Promise jobs. + */ +void +ecma_free_all_enqueued_jobs (void) +{ + while (JERRY_CONTEXT (job_queue_head_p) != NULL) + { + ecma_job_queue_item_t *job_p = JERRY_CONTEXT (job_queue_head_p); + JERRY_CONTEXT (job_queue_head_p) = ecma_job_queue_get_next (job_p); + + switch (ecma_job_queue_get_type (job_p)) + { + case ECMA_JOB_PROMISE_REACTION: + { + ecma_free_promise_reaction_job ((ecma_job_promise_reaction_t *) job_p); + break; + } + case ECMA_JOB_PROMISE_ASYNC_REACTION_FULFILLED: + case ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED: + { + ecma_free_promise_async_reaction_job ((ecma_job_promise_async_reaction_t *) job_p); + break; + } + case ECMA_JOB_PROMISE_ASYNC_GENERATOR: + { + ecma_free_promise_async_generator_job ((ecma_job_promise_async_generator_t *) job_p); + break; + } + default: + { + JERRY_ASSERT (ecma_job_queue_get_type (job_p) == ECMA_JOB_PROMISE_THENABLE); + + ecma_free_promise_resolve_thenable_job ((ecma_job_promise_resolve_thenable_t *) job_p); + break; + } + } + } +} /* ecma_free_all_enqueued_jobs */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.h new file mode 100644 index 00000000..b56027ca --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.h @@ -0,0 +1,63 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_JOB_QUEUE_H +#define ECMA_JOB_QUEUE_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmajobqueue ECMA Job Queue related routines + * @{ + */ + +/** + * Job queue item types. + */ +typedef enum +{ + ECMA_JOB_PROMISE_REACTION, /**< promise reaction job */ + ECMA_JOB_PROMISE_ASYNC_REACTION_FULFILLED, /**< fulfilled promise async reaction job */ + ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED, /**< rejected promise async reaction job */ + ECMA_JOB_PROMISE_ASYNC_GENERATOR, /**< continue async generator */ + ECMA_JOB_PROMISE_THENABLE, /**< promise thenable job */ +} ecma_job_queue_item_type_t; + +/** + * Description of the job queue item. + */ +typedef struct +{ + uintptr_t next_and_type; /**< next and type members of a queue item */ +} ecma_job_queue_item_t; + +void ecma_job_queue_init (void); + +void ecma_enqueue_promise_reaction_job (ecma_value_t capability, ecma_value_t handler, ecma_value_t argument); +void ecma_enqueue_promise_async_reaction_job (ecma_value_t executable_object, ecma_value_t argument, bool is_rejected); +void ecma_enqueue_promise_async_generator_job (ecma_value_t executable_object); +void ecma_enqueue_promise_resolve_thenable_job (ecma_value_t promise, ecma_value_t thenable, ecma_value_t then); +void ecma_free_all_enqueued_jobs (void); + +ecma_value_t ecma_process_all_enqueued_jobs (void); + +/** + * @} + * @} + */ + +#endif /* !ECMA_JOB_QUEUE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.cpp new file mode 100644 index 00000000..0b04a38f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.cpp @@ -0,0 +1,643 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-lex-env.h" + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup lexicalenvironment Lexical environment + * @{ + * + * \addtogroup globallexicalenvironment Global lexical environment + * @{ + */ + +/** + * Initialize Global environment + */ +void +ecma_init_global_environment (void) +{ + JERRY_CONTEXT (global_object_p) = ecma_builtin_create_global_object (); +} /* ecma_init_global_environment */ + +/** + * Finalize Global environment + */ +void +ecma_finalize_global_environment (void) +{ + /* After this point the gc can free the global object, but the global_object_p pointer + * is not set to NULL because the global object might still be used before the free. */ + ecma_deref_object ((ecma_object_t *) JERRY_CONTEXT (global_object_p)); +} /* ecma_finalize_global_environment */ + +/** + * Get reference to Global lexical environment + * without increasing its reference count. + * + * @return pointer to the object's instance + */ +ecma_object_t * +ecma_get_global_environment (ecma_object_t *global_object_p) /**< global object */ +{ + JERRY_ASSERT (global_object_p != NULL && ecma_builtin_is_global (global_object_p)); + return ECMA_GET_NON_NULL_POINTER (ecma_object_t, ((ecma_global_object_t *) global_object_p)->global_env_cp); +} /* ecma_get_global_environment */ + +/** + * Create the global lexical block on top of the global environment. + */ +void +ecma_create_global_lexical_block (ecma_object_t *global_object_p) /**< global object */ +{ + JERRY_ASSERT (global_object_p != NULL && ecma_builtin_is_global (global_object_p)); + + ecma_global_object_t *real_global_object_p = (ecma_global_object_t *) global_object_p; + + if (real_global_object_p->global_scope_cp == real_global_object_p->global_env_cp) + { + ecma_object_t *global_scope_p = ecma_create_decl_lex_env (ecma_get_global_environment (global_object_p)); + global_scope_p->type_flags_refs |= ECMA_OBJECT_FLAG_BLOCK; + ECMA_SET_NON_NULL_POINTER (real_global_object_p->global_scope_cp, global_scope_p); + ecma_deref_object (global_scope_p); + } +} /* ecma_create_global_lexical_block */ + +/** + * Raise the appropriate error when setting a binding is failed + * + * @return ECMA_VALUE_EMPTY or ECMA_VALUE_ERROR + */ +ecma_value_t +ecma_op_raise_set_binding_error (ecma_property_t *property_p, /**< property */ + bool is_strict) /**< flag indicating strict mode */ +{ + JERRY_UNUSED (property_p); + + const ecma_property_t expected_bits = (ECMA_PROPERTY_FLAG_DATA | ECMA_PROPERTY_FLAG_ENUMERABLE); + + if ((*property_p & expected_bits) == expected_bits) + { + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + JERRY_ASSERT (!ecma_is_property_writable (*property_p)); + + return ecma_raise_type_error (ECMA_ERR_CONSTANT_BINDINGS_CANNOT_BE_REASSIGNED); + } + + if (is_strict) + { + return ecma_raise_type_error (ECMA_ERR_BINDING_CANNOT_SET); + } + return ECMA_VALUE_EMPTY; +} /* ecma_op_raise_set_binding_error */ + +/** + * Get reference to Global lexical scope + * without increasing its reference count. + * + * @return pointer to the object's instance + */ +ecma_object_t * +ecma_get_global_scope (ecma_object_t *global_object_p) /**< global object */ +{ + JERRY_ASSERT (global_object_p != NULL && ecma_builtin_is_global (global_object_p)); + return ECMA_GET_NON_NULL_POINTER (ecma_object_t, ((ecma_global_object_t *) global_object_p)->global_scope_cp); +} /* ecma_get_global_scope */ + +/** + * @} + */ + +/** + * HasBinding operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return true / false + */ +ecma_value_t +ecma_op_has_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p) /**< argument N */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + + ecma_lexical_environment_type_t lex_env_type = ecma_get_lex_env_type (lex_env_p); + + switch (lex_env_type) + { + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { + if (!ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + return ECMA_VALUE_FALSE; + } + /* FALLTHRU */ + } + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + return ecma_make_boolean_value (property_p != NULL); + } + default: + { + JERRY_ASSERT (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + return ecma_op_object_has_property (binding_obj_p, name_p); + } + } +} /* ecma_op_has_binding */ + +/** + * CreateMutableBinding operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return ECMA_PROPERTY_POINTER_ERROR - if the operation raises error + * pointer to the created property - if the binding was created into a declerative environment + * NULL - otherwise + */ +ecma_property_t * +ecma_op_create_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< argument N */ + bool is_deletable) /**< argument D */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (name_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; + + if (is_deletable) + { + prop_attributes = (uint8_t) (prop_attributes | ECMA_PROPERTY_FLAG_CONFIGURABLE); + } + + ecma_property_t *prop_p; + + ecma_create_named_data_property (lex_env_p, name_p, prop_attributes, &prop_p); + return prop_p; + } + else + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + +#if JERRY_BUILTIN_PROXY && JERRY_BUILTIN_REALMS + if (ECMA_OBJECT_IS_PROXY (binding_obj_p)) + { + ecma_value_t result = ecma_proxy_object_is_extensible (binding_obj_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return ECMA_PROPERTY_POINTER_ERROR; + } + + if (result == ECMA_VALUE_FALSE) + { + return NULL; + } + } + else if (!ecma_op_ordinary_object_is_extensible (binding_obj_p)) + { + return NULL; + } +#else /* !JERRY_BUILTIN_PROXY || !JERRY_BUILTIN_REALMS */ + if (!ecma_op_ordinary_object_is_extensible (binding_obj_p)) + { + return NULL; + } +#endif /* JERRY_BUILTIN_PROXY && JERRY_BUILTIN_REALMS */ + + const uint32_t flags = ECMA_PROPERTY_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + + ecma_value_t completion = + ecma_builtin_helper_def_prop (binding_obj_p, + name_p, + ECMA_VALUE_UNDEFINED, + is_deletable ? flags | ECMA_PROPERTY_FLAG_CONFIGURABLE : flags); + + if (ECMA_IS_VALUE_ERROR (completion)) + { + return ECMA_PROPERTY_POINTER_ERROR; + } + else + { + JERRY_ASSERT (ecma_is_value_boolean (completion)); + } + } + + return NULL; +} /* ecma_op_create_mutable_binding */ + +/** + * SetMutableBinding operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_set_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< argument N */ + ecma_value_t value, /**< argument V */ + bool is_strict) /**< argument S */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (name_p != NULL); + + switch (ecma_get_lex_env_type (lex_env_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { + if (!ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + return ECMA_VALUE_EMPTY; + } + /* FALLTHRU */ + } + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (JERRY_UNLIKELY (property_p == NULL)) + { + property_p = ecma_op_create_mutable_binding (lex_env_p, name_p, is_strict); + JERRY_ASSERT (property_p != ECMA_PROPERTY_POINTER_ERROR); + } + + JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*property_p)); + JERRY_ASSERT (!(*property_p & ECMA_PROPERTY_FLAG_WRITABLE) || (*property_p & ECMA_PROPERTY_FLAG_DATA)); + + if ((*property_p & ECMA_PROPERTY_FLAG_WRITABLE)) + { + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + JERRY_ASSERT (property_value_p->value != ECMA_VALUE_UNINITIALIZED); + + ecma_named_data_property_assign_value (lex_env_p, property_value_p, value); + return ECMA_VALUE_EMPTY; + } + + return ecma_op_raise_set_binding_error (property_p, is_strict); + } + default: + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + ecma_value_t completion = ecma_op_object_put (binding_obj_p, name_p, value, is_strict); + + if (ECMA_IS_VALUE_ERROR (completion)) + { + return completion; + } + + JERRY_ASSERT (ecma_is_value_boolean (completion)); + return ECMA_VALUE_EMPTY; + } + } +} /* ecma_op_set_mutable_binding */ + +/** + * GetBindingValue operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_get_binding_value (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< argument N */ + bool is_strict) /**< argument S */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (name_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_value_t *prop_value_p = ecma_get_named_data_property (lex_env_p, name_p); + + return ecma_copy_value (prop_value_p->value); + } + else + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + ecma_value_t result = ecma_op_object_find (binding_obj_p, name_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (!ecma_is_value_found (result)) + { + if (is_strict) + { + result = ecma_raise_reference_error (ECMA_ERR_BINDING_NOT_EXIST_OR_UNINITIALIZED); + } + else + { + result = ECMA_VALUE_UNDEFINED; + } + } + + return result; + } +} /* ecma_op_get_binding_value */ + +/** + * DeleteBinding operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return ecma value + * Return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the binding can be deleted + */ +ecma_value_t +ecma_op_delete_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p) /**< argument N */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (name_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *prop_p = ecma_find_named_property (lex_env_p, name_p); + ecma_value_t ret_val; + + if (prop_p == NULL) + { + ret_val = ECMA_VALUE_TRUE; + } + else + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW_DATA (*prop_p)); + + if (!ecma_is_property_configurable (*prop_p)) + { + ret_val = ECMA_VALUE_FALSE; + } + else + { + ecma_delete_property (lex_env_p, ECMA_PROPERTY_VALUE_PTR (prop_p)); + + ret_val = ECMA_VALUE_TRUE; + } + } + + return ret_val; + } + else + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + return ecma_op_object_delete (binding_obj_p, name_p, false); + } +} /* ecma_op_delete_binding */ + +/** + * ImplicitThisValue operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_implicit_this_value (ecma_object_t *lex_env_p) /**< lexical environment */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + return ECMA_VALUE_UNDEFINED; + } + else + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + ecma_ref_object (binding_obj_p); + + return ecma_make_object_value (binding_obj_p); + } +} /* ecma_op_implicit_this_value */ + +/** + * CreateImmutableBinding operation. + * + * See also: ECMA-262 v5, 10.2.1 + */ +void +ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< argument N */ + ecma_value_t value) /**< argument V */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + + /* + * Warning: + * Whether immutable bindings are deletable seems not to be defined by ECMA v5. + */ + ecma_property_value_t *prop_value_p = ecma_create_named_data_property (lex_env_p, name_p, ECMA_PROPERTY_FIXED, NULL); + + prop_value_p->value = ecma_copy_value_if_not_object (value); +} /* ecma_op_create_immutable_binding */ + +/** + * InitializeBinding operation. + * + * See also: ECMA-262 v6, 8.1.1.1.4 + */ +void +ecma_op_initialize_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< argument N */ + ecma_value_t value) /**< argument V */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + + ecma_property_t *prop_p = ecma_find_named_property (lex_env_p, name_p); + JERRY_ASSERT (prop_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*prop_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p); + JERRY_ASSERT (prop_value_p->value == ECMA_VALUE_UNINITIALIZED); + + prop_value_p->value = ecma_copy_value_if_not_object (value); +} /* ecma_op_initialize_binding */ + +/** + * BindThisValue operation for an empty lexical environment + * + * See also: ECMA-262 v6, 8.1.1.3.1 + */ +void +ecma_op_create_environment_record (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_value_t this_binding, /**< this binding value */ + ecma_object_t *func_obj_p) /**< function object */ +{ + JERRY_ASSERT (lex_env_p != NULL); + JERRY_ASSERT (ecma_is_value_object (this_binding) || this_binding == ECMA_VALUE_UNINITIALIZED); + + ecma_environment_record_t *environment_record_p; + environment_record_p = (ecma_environment_record_t *) jmem_heap_alloc_block (sizeof (ecma_environment_record_t)); + + environment_record_p->this_binding = this_binding; + environment_record_p->function_object = ecma_make_object_value (func_obj_p); + + ecma_string_t *property_name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD); + + ecma_property_t *property_p; + ecma_property_value_t *prop_value_p; + ECMA_CREATE_INTERNAL_PROPERTY (lex_env_p, property_name_p, property_p, prop_value_p); + + ECMA_SET_INTERNAL_VALUE_POINTER (prop_value_p->value, environment_record_p); +} /* ecma_op_create_environment_record */ + +/** + * GetThisEnvironment operation. + * + * See also: ECMA-262 v6, 8.3.2 + * + * @return property pointer for the internal [[ThisBindingValue]] property + */ +ecma_environment_record_t * +ecma_op_get_environment_record (ecma_object_t *lex_env_p) /**< lexical environment */ +{ + JERRY_ASSERT (lex_env_p != NULL); + + ecma_string_t *property_name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD); + while (true) + { + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, property_name_p); + + if (property_p != NULL) + { + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_environment_record_t, property_value_p->value); + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + return NULL; +} /* ecma_op_get_environment_record */ + +/** + * Get the environment record [[ThisBindingStatus]] internal property. + * + * See also: ECMA-262 v6, 8.1.1.3 + * + * @return true - if the status is "initialzed" + * false - otherwise + */ +bool +ecma_op_this_binding_is_initialized (ecma_environment_record_t *environment_record_p) /**< environment record */ +{ + JERRY_ASSERT (environment_record_p != NULL); + + return environment_record_p->this_binding != ECMA_VALUE_UNINITIALIZED; +} /* ecma_op_this_binding_is_initialized */ + +/** + * BindThisValue operation. + * + * See also: ECMA-262 v6, 8.1.1.3.1 + */ +void +ecma_op_bind_this_value (ecma_environment_record_t *environment_record_p, /**< environment record */ + ecma_value_t this_binding) /**< this binding value */ +{ + JERRY_ASSERT (environment_record_p != NULL); + JERRY_ASSERT (ecma_is_value_object (this_binding)); + JERRY_ASSERT (!ecma_op_this_binding_is_initialized (environment_record_p)); + + environment_record_p->this_binding = this_binding; +} /* ecma_op_bind_this_value */ + +/** + * GetThisBinding operation. + * + * See also: ECMA-262 v6, 8.1.1.3.4 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ecma-object - otherwise + */ +ecma_value_t +ecma_op_get_this_binding (ecma_object_t *lex_env_p) /**< lexical environment */ +{ + JERRY_ASSERT (lex_env_p != NULL); + + ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (lex_env_p); + JERRY_ASSERT (environment_record_p != NULL); + + ecma_value_t this_value = environment_record_p->this_binding; + + if (this_value == ECMA_VALUE_UNINITIALIZED) + { + return ecma_raise_reference_error (ECMA_ERR_CALL_SUPER_CONSTRUCTOR_DERIVED_CLASS_BEFORE_THIS); + } + + ecma_ref_object (ecma_get_object_from_value (this_value)); + + return this_value; +} /* ecma_op_get_this_binding */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.h new file mode 100644 index 00000000..e71d729f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.h @@ -0,0 +1,85 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_LEX_ENV_H +#define ECMA_LEX_ENV_H + +#include "ecma-globals.h" +#include "ecma-reference.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup lexicalenvironment Lexical environment + * @{ + * + * \addtogroup globallexicalenvironment Global lexical environment + * @{ + */ + +void ecma_init_global_environment (void); +void ecma_finalize_global_environment (void); +ecma_object_t *ecma_get_global_environment (ecma_object_t *global_object_p); +ecma_object_t *ecma_get_global_scope (ecma_object_t *global_object_p); +void ecma_create_global_lexical_block (ecma_object_t *global_object_p); +ecma_value_t ecma_op_raise_set_binding_error (ecma_property_t *property_p, bool is_strict); + +#if JERRY_MODULE_SYSTEM +void ecma_module_add_lex_env (ecma_object_t *lex_env_p); +void ecma_module_finalize_lex_envs (void); +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * @} + */ + +/* ECMA-262 v5, 8.7.1 and 8.7.2 */ +ecma_value_t +ecma_op_get_value_lex_env_base (ecma_object_t *lex_env_p, ecma_object_t **ref_base_lex_env_p, ecma_string_t *name_p); +ecma_value_t ecma_op_get_value_object_base (ecma_value_t base_value, ecma_string_t *property_name_p); +ecma_value_t ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, + ecma_string_t *var_name_string_p, + bool is_strict, + ecma_value_t value); + +/* ECMA-262 v5, Table 17. Abstract methods of Environment Records */ +ecma_value_t ecma_op_has_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p); +ecma_property_t *ecma_op_create_mutable_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p, bool is_deletable); +ecma_value_t +ecma_op_set_mutable_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p, ecma_value_t value, bool is_strict); +ecma_value_t ecma_op_get_binding_value (ecma_object_t *lex_env_p, ecma_string_t *name_p, bool is_strict); +ecma_value_t ecma_op_delete_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p); +ecma_value_t ecma_op_implicit_this_value (ecma_object_t *lex_env_p); + +/* ECMA-262 v5, Table 18. Additional methods of Declarative Environment Records */ +void ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p, ecma_value_t value); + +void ecma_op_initialize_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p, ecma_value_t value); + +void ecma_op_create_environment_record (ecma_object_t *lex_env_p, ecma_value_t this_binding, ecma_object_t *func_obj_p); +ecma_environment_record_t *ecma_op_get_environment_record (ecma_object_t *lex_env_p); + +bool ecma_op_this_binding_is_initialized (ecma_environment_record_t *environment_record_p); +void ecma_op_bind_this_value (ecma_environment_record_t *environment_record_p, ecma_value_t this_binding); +ecma_value_t ecma_op_get_this_binding (ecma_object_t *lex_env_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_LEX_ENV_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.cpp new file mode 100644 index 00000000..548f2f73 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.cpp @@ -0,0 +1,95 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-number-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmanumberobject ECMA Number object related routines + * @{ + */ + +/** + * Number object creation operation. + * + * See also: ECMA-262 v5, 15.7.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */ +{ + ecma_number_t num; + ecma_value_t conv_to_num_completion = ecma_op_to_number (arg, &num); + + if (ECMA_IS_VALUE_ERROR (conv_to_num_completion)) + { + return conv_to_num_completion; + } + + conv_to_num_completion = ecma_make_number_value (num); + ecma_builtin_id_t proto_id; +#if JERRY_BUILTIN_NUMBER + proto_id = ECMA_BUILTIN_ID_NUMBER_PROTOTYPE; +#else /* JERRY_BUILTIN_NUMBER */ + proto_id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; +#endif /* JERRY_BUILTIN_NUMBER */ + ecma_object_t *prototype_obj_p = ecma_builtin_get (proto_id); + + ecma_object_t *new_target = JERRY_CONTEXT (current_new_target_p); + if (new_target) + { + prototype_obj_p = ecma_op_get_prototype_from_constructor (new_target, proto_id); + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + } + + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_NUMBER; + + /* Pass reference (no need to free conv_to_num_completion). */ + ext_object_p->u.cls.u3.value = conv_to_num_completion; + + if (new_target) + { + ecma_deref_object (prototype_obj_p); + } + + return ecma_make_object_value (object_p); +} /* ecma_op_create_number_object */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.h new file mode 100644 index 00000000..c4baf75f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_NUMBER_OBJECT_H +#define ECMA_NUMBER_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmanumberobject ECMA Number object related routines + * @{ + */ + +ecma_value_t ecma_op_create_number_object (ecma_value_t arg); + +/** + * @} + * @} + */ + +#endif /* !ECMA_NUMBER_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.cpp new file mode 100644 index 00000000..f4425c83 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.cpp @@ -0,0 +1,753 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-objects-general.h" + +#include "ecma-arguments-object.h" +#include "ecma-array-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaobjectsinternalops ECMA objects' operations + * @{ + */ + +/** + * 'Object' object creation operation with no arguments. + * + * See also: ECMA-262 v5, 15.2.2.1 + * + * @return pointer to newly created 'Object' object + */ +ecma_object_t * +ecma_op_create_object_object_noarg (void) +{ + ecma_object_t *object_prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + /* 3., 4., 6., 7. */ + return ecma_op_create_object_object_noarg_and_set_prototype (object_prototype_p); +} /* ecma_op_create_object_object_noarg */ + +/** + * Object creation operation with no arguments. + * It sets the given prototype to the newly created object. + * + * See also: ECMA-262 v5, 15.2.2.1, 15.2.3.5 + * + * @return pointer to newly created object + */ +ecma_object_t * +ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prototype_p) /**< pointer to prototype of + the object + (can be NULL) */ +{ + ecma_object_t *obj_p = ecma_create_object (object_prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + + /* + * [[Class]] property of ECMA_OBJECT_TYPE_GENERAL type objects + * without ECMA_INTERNAL_PROPERTY_CLASS internal property + * is "Object". + * + * See also: ecma_object_get_class_name + */ + + return obj_p; +} /* ecma_op_create_object_object_noarg_and_set_prototype */ + +/** + * [[Delete]] ecma general object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + bool is_throw) /**< flag that controls failure handling */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (property_name_p != NULL); + + /* 1. */ + ecma_property_ref_t property_ref; + + ecma_property_t property = + ecma_op_object_get_own_property (obj_p, property_name_p, &property_ref, ECMA_PROPERTY_GET_NO_OPTIONS); + + /* 2. */ + if (!ECMA_PROPERTY_IS_FOUND (property)) + { + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + return ECMA_VALUE_TRUE; + } + + /* 3. */ + if (!ecma_is_property_configurable (property)) + { + /* 4. */ + if (is_throw) + { + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_CONFIGURABLE_PROPERTY); + } + + /* 5. */ + return ECMA_VALUE_FALSE; + } + + ecma_object_type_t type = ecma_get_object_type (obj_p); + + if (type == ECMA_OBJECT_TYPE_ARRAY && ecma_array_object_delete_property (obj_p, property_name_p)) + { + return ECMA_VALUE_TRUE; + } + + /* a. */ + ecma_delete_property (obj_p, property_ref.value_p); + + if (property & ECMA_PROPERTY_FLAG_BUILT_IN) + { + switch (type) + { + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + if (ecma_builtin_function_is_routine (obj_p)) + { + ecma_builtin_routine_delete_built_in_property (obj_p, property_name_p); + break; + } + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + ecma_builtin_delete_built_in_property (obj_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)); + ecma_op_arguments_delete_built_in_property (obj_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + ecma_op_function_delete_built_in_property (obj_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_op_bound_function_delete_built_in_property (obj_p, property_name_p); + break; + } + default: + { + JERRY_UNREACHABLE (); + break; + } + } + } + + /* b. */ + return ECMA_VALUE_TRUE; +} /* ecma_op_general_object_delete */ + +/** + * Property invocation order during [[DefaultValue]] operation with string hint + */ +static const lit_magic_string_id_t to_primitive_string_hint_method_names[2] = { + LIT_MAGIC_STRING_TO_STRING_UL, /**< toString operation */ + LIT_MAGIC_STRING_VALUE_OF_UL, /**< valueOf operation */ +}; + +/** + * Property invocation order during [[DefaultValue]] operation with non string hint + */ +static const lit_magic_string_id_t to_primitive_non_string_hint_method_names[2] = { + LIT_MAGIC_STRING_VALUE_OF_UL, /**< valueOf operation */ + LIT_MAGIC_STRING_TO_STRING_UL, /**< toString operation */ +}; + +/** + * Hints for the ecma general object's toPrimitve operation + */ +static const lit_magic_string_id_t hints[3] = { + LIT_MAGIC_STRING_DEFAULT, /**< "default" hint */ + LIT_MAGIC_STRING_NUMBER, /**< "number" hint */ + LIT_MAGIC_STRING_STRING, /**< "string" hint */ +}; + +/** + * [[DefaultValue]] ecma general object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_general_object_default_value (ecma_object_t *obj_p, /**< the object */ + ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + + ecma_value_t obj_value = ecma_make_object_value (obj_p); + + ecma_value_t exotic_to_prim = ecma_op_get_method_by_symbol_id (obj_value, LIT_GLOBAL_SYMBOL_TO_PRIMITIVE); + + if (ECMA_IS_VALUE_ERROR (exotic_to_prim)) + { + return exotic_to_prim; + } + + if (!ecma_is_value_undefined (exotic_to_prim)) + { + ecma_object_t *call_func_p = ecma_get_object_from_value (exotic_to_prim); + ecma_value_t argument = ecma_make_magic_string_value (hints[hint]); + + ecma_value_t result = ecma_op_function_call (call_func_p, obj_value, &argument, 1); + + ecma_free_value (exotic_to_prim); + + if (ECMA_IS_VALUE_ERROR (result) || !ecma_is_value_object (result)) + { + return result; + } + + ecma_free_value (result); + + return ecma_raise_type_error (ECMA_ERR_RESULT_OF_DEFAULTVALUE_IS_INVALID); + } + + ecma_free_value (exotic_to_prim); + + if (hint == ECMA_PREFERRED_TYPE_NO) + { + hint = ECMA_PREFERRED_TYPE_NUMBER; + } + + return ecma_op_general_object_ordinary_value (obj_p, hint); +} /* ecma_op_general_object_default_value */ + +/** + * Ecma general object's OrdinaryToPrimitive operation + * + * See also: + * ECMA-262 v6 7.1.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_general_object_ordinary_value (ecma_object_t *obj_p, /**< the object */ + ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ +{ + const lit_magic_string_id_t *function_name_ids_p = + (hint == ECMA_PREFERRED_TYPE_STRING ? to_primitive_string_hint_method_names + : to_primitive_non_string_hint_method_names); + + for (uint32_t i = 0; i < 2; i++) + { + ecma_value_t function_value = ecma_op_object_get_by_magic_id (obj_p, function_name_ids_p[i]); + + if (ECMA_IS_VALUE_ERROR (function_value)) + { + return function_value; + } + + ecma_value_t call_completion = ECMA_VALUE_EMPTY; + + if (ecma_op_is_callable (function_value)) + { + ecma_object_t *func_obj_p = ecma_get_object_from_value (function_value); + + call_completion = ecma_op_function_call (func_obj_p, ecma_make_object_value (obj_p), NULL, 0); + } + + ecma_free_value (function_value); + + if (ECMA_IS_VALUE_ERROR (call_completion) + || (!ecma_is_value_empty (call_completion) && !ecma_is_value_object (call_completion))) + { + return call_completion; + } + + ecma_free_value (call_completion); + } + + return ecma_raise_type_error (ECMA_ERR_RESULT_OF_DEFAULTVALUE_IS_INVALID); +} /* ecma_op_general_object_ordinary_value */ + +/** + * Special types for ecma_op_general_object_define_own_property. + */ +typedef enum +{ + ECMA_OP_OBJECT_DEFINE_GENERIC = 1, /**< generic property */ + ECMA_OP_OBJECT_DEFINE_ACCESSOR = 0, /**< accessor property */ + ECMA_OP_OBJECT_DEFINE_DATA = ECMA_PROPERTY_FLAG_DATA /**< data property */ +} ecma_op_object_define_own_property_type_t; + +/** + * [[DefineOwnProperty]] ecma general object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property + * descriptor */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_define_own_property (object_p, property_name_p, property_desc_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + JERRY_ASSERT (property_name_p != NULL); + + uint8_t property_desc_type = ECMA_OP_OBJECT_DEFINE_GENERIC; + + if (property_desc_p->flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) + { + /* A property descriptor cannot be both named data and named accessor. */ + JERRY_ASSERT ((property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + != (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)); + property_desc_type = ECMA_OP_OBJECT_DEFINE_DATA; + } + else if (property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + JERRY_ASSERT (!(property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED)); + property_desc_type = ECMA_OP_OBJECT_DEFINE_ACCESSOR; + } + + /* These three asserts ensures that a new property is created with the appropriate default flags. + * E.g. if JERRY_PROP_IS_CONFIGURABLE_DEFINED is false, the newly created property must be non-configurable. */ + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)); + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)); + + /* 1. */ + ecma_extended_property_ref_t ext_property_ref = { {NULL, }, NULL }; + ecma_property_t current_prop; + + current_prop = ecma_op_object_get_own_property (object_p, + property_name_p, + &ext_property_ref.property_ref, + ECMA_PROPERTY_GET_VALUE | ECMA_PROPERTY_GET_EXT_REFERENCE); + + if (!ECMA_PROPERTY_IS_FOUND (current_prop)) + { + JERRY_ASSERT (current_prop == ECMA_PROPERTY_TYPE_NOT_FOUND + || current_prop == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + + /* 3. */ + if (!ecma_op_ordinary_object_is_extensible (object_p)) + { + /* 2. */ + return ECMA_REJECT_WITH_FORMAT (property_desc_p->flags & JERRY_PROP_SHOULD_THROW, + "Cannot define property '%', object is not extensible", + ecma_make_prop_name_value (property_name_p)); + } + + /* 4. */ + uint8_t prop_attributes = (uint8_t) (property_desc_p->flags & ECMA_PROPERTY_FLAGS_MASK); + + if (property_desc_type != ECMA_OP_OBJECT_DEFINE_ACCESSOR) + { + /* a. */ + JERRY_ASSERT (property_desc_type == ECMA_OP_OBJECT_DEFINE_GENERIC + || property_desc_type == ECMA_OP_OBJECT_DEFINE_DATA); + + ecma_property_value_t *new_prop_value_p = + ecma_create_named_data_property (object_p, property_name_p, prop_attributes, NULL); + + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + || ecma_is_value_undefined (property_desc_p->value)); + + new_prop_value_p->value = ecma_copy_value_if_not_object (property_desc_p->value); + } + else + { + /* b. */ + ecma_create_named_accessor_property (object_p, + property_name_p, + property_desc_p->get_p, + property_desc_p->set_p, + prop_attributes, + NULL); + } + + return ECMA_VALUE_TRUE; + } + + /* 6. */ + const bool is_current_configurable = ecma_is_property_configurable (current_prop); + + /* 7. a., b. */ + bool is_enumerable = (property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE) != 0; + if (!is_current_configurable + && ((property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE) + || ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + && (is_enumerable != ecma_is_property_enumerable (current_prop))))) + { + if (ECMA_PROPERTY_IS_VIRTUAL (current_prop)) + { + ecma_free_value (ext_property_ref.property_ref.virtual_value); + } + + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + if (ECMA_PROPERTY_IS_VIRTUAL (current_prop)) + { + bool writable_check_failed = (property_desc_p->flags & JERRY_PROP_IS_WRITABLE); + +#if JERRY_MODULE_SYSTEM + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE_NAMESPACE)) + { + if (JERRY_UNLIKELY (ext_property_ref.property_ref.virtual_value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + if (property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + { + writable_check_failed = ((property_desc_p->flags ^ current_prop) & JERRY_PROP_IS_WRITABLE) != 0; + } + } + else + { + JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop)); + } +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop)); +#endif /* JERRY_MODULE_SYSTEM */ + + ecma_value_t result = ECMA_VALUE_TRUE; + + if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR || writable_check_failed + || ((property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + && !ecma_op_same_value (property_desc_p->value, ext_property_ref.property_ref.virtual_value))) + { + result = ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + ecma_free_value (ext_property_ref.property_ref.virtual_value); + return result; + } + + /* 8. */ + if (property_desc_type == ECMA_OP_OBJECT_DEFINE_GENERIC) + { + /* No action required. */ + } + else if (JERRY_LIKELY (property_desc_type == (current_prop & ECMA_PROPERTY_FLAG_DATA))) + { + /* If property is configurable, there is no need for checks. */ + if (JERRY_UNLIKELY (!is_current_configurable)) + { + if (property_desc_type == ECMA_OP_OBJECT_DEFINE_DATA) + { + /* 10. a. i. & ii. */ + if (!ecma_is_property_writable (current_prop) + && ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE) + || ((property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + && !ecma_op_same_value (property_desc_p->value, ext_property_ref.property_ref.value_p->value)))) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + } + else + { + /* 11. */ + + /* a. */ + ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p; + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (value_p); + jmem_cpointer_t prop_desc_getter_cp, prop_desc_setter_cp; + ECMA_SET_POINTER (prop_desc_getter_cp, property_desc_p->get_p); + ECMA_SET_POINTER (prop_desc_setter_cp, property_desc_p->set_p); + + if (((property_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) && prop_desc_getter_cp != get_set_pair_p->getter_cp) + || ((property_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + && prop_desc_setter_cp != get_set_pair_p->setter_cp)) + { + /* i., ii. */ + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + } + } + } + else + { + /* 9. */ + if (!is_current_configurable) + { + /* a. */ + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p; + + if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR) + { + JERRY_ASSERT (current_prop & ECMA_PROPERTY_FLAG_DATA); + ecma_free_value_if_not_object (value_p->value); + +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t)); + getter_setter_pair_p->getter_cp = JMEM_CP_NULL; + getter_setter_pair_p->setter_cp = JMEM_CP_NULL; + ECMA_SET_NON_NULL_POINTER (value_p->getter_setter_pair_cp, getter_setter_pair_p); +#else /* !JERRY_CPOINTER_32_BIT */ + value_p->getter_setter_pair.getter_cp = JMEM_CP_NULL; + value_p->getter_setter_pair.setter_cp = JMEM_CP_NULL; +#endif /* JERRY_CPOINTER_32_BIT */ + } + else + { + JERRY_ASSERT (!(current_prop & ECMA_PROPERTY_FLAG_DATA)); +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, value_p->getter_setter_pair_cp); + jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t)); +#endif /* JERRY_CPOINTER_32_BIT */ + value_p->value = ECMA_VALUE_UNDEFINED; + } + + /* Update flags */ + ecma_property_t prop_flags = *(ext_property_ref.property_p); + prop_flags = (ecma_property_t) (prop_flags & ~ECMA_PROPERTY_FLAG_WRITABLE); + prop_flags ^= ECMA_PROPERTY_FLAG_DATA; + *(ext_property_ref.property_p) = prop_flags; + } + + /* 12. */ + if (property_desc_type == ECMA_OP_OBJECT_DEFINE_DATA) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW_DATA (*ext_property_ref.property_p)); + + if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + ecma_named_data_property_assign_value (object_p, ext_property_ref.property_ref.value_p, property_desc_p->value); + } + + if (property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + { + ecma_set_property_writable_attr (ext_property_ref.property_p, (property_desc_p->flags & JERRY_PROP_IS_WRITABLE)); + } + } + else if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR) + { + JERRY_ASSERT (!(*ext_property_ref.property_p & ECMA_PROPERTY_FLAG_DATA)); + + if (property_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + ecma_set_named_accessor_property_getter (object_p, ext_property_ref.property_ref.value_p, property_desc_p->get_p); + } + + if (property_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + ecma_set_named_accessor_property_setter (object_p, ext_property_ref.property_ref.value_p, property_desc_p->set_p); + } + } + + if (property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + { + ecma_set_property_enumerable_attr (ext_property_ref.property_p, + (property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)); + } + + if (property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) + { + ecma_set_property_configurable_attr (ext_property_ref.property_p, + (property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); + } + + return ECMA_VALUE_TRUE; +} /* ecma_op_general_object_define_own_property */ + +/** + * The IsCompatiblePropertyDescriptor method for Proxy object internal methods + * + * See also: + * ECMAScript v6, 9.1.6.2 + * + * @return bool + */ +bool +ecma_op_is_compatible_property_descriptor (const ecma_property_descriptor_t *desc_p, /**< target descriptor */ + const ecma_property_descriptor_t *current_p, /**< current descriptor */ + bool is_extensible) /**< true - if target object is extensible + false - otherwise */ +{ + JERRY_ASSERT (desc_p != NULL); + + /* 2. */ + if (current_p == NULL) + { + return is_extensible; + } + + /* 3. */ + if (desc_p->flags == 0) + { + return true; + } + + /* 4. */ + if ((current_p->flags & desc_p->flags) == desc_p->flags) + { + if ((current_p->flags & JERRY_PROP_IS_VALUE_DEFINED) && ecma_op_same_value (current_p->value, desc_p->value)) + { + return true; + } + + if ((current_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED) && current_p->get_p == desc_p->get_p + && current_p->set_p == desc_p->set_p)) + { + return true; + } + } + + /* 5. */ + if (!(current_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + { + if (desc_p->flags & JERRY_PROP_IS_CONFIGURABLE) + { + return false; + } + if ((desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + && ((current_p->flags & JERRY_PROP_IS_ENUMERABLE) != (desc_p->flags & JERRY_PROP_IS_ENUMERABLE))) + { + return false; + } + } + + const uint32_t accessor_desc_flags = (JERRY_PROP_IS_SET_DEFINED | JERRY_PROP_IS_GET_DEFINED); + const uint32_t data_desc_flags = (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED); + + bool desc_is_accessor = (desc_p->flags & accessor_desc_flags) != 0; + bool desc_is_data = (desc_p->flags & data_desc_flags) != 0; + bool current_is_data = (current_p->flags & data_desc_flags) != 0; + + /* 6. */ + if (!desc_is_accessor && !desc_is_data) + { + return true; + } + + /* 7. */ + if (current_is_data != desc_is_data) + { + return (current_p->flags & JERRY_PROP_IS_CONFIGURABLE) != 0; + } + + /* 8. */ + if (current_is_data) + { + if (!(current_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + { + if (!(current_p->flags & JERRY_PROP_IS_WRITABLE) && (desc_p->flags & JERRY_PROP_IS_WRITABLE)) + { + return false; + } + + if (!(current_p->flags & JERRY_PROP_IS_WRITABLE) && (desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + && !ecma_op_same_value (desc_p->value, current_p->value)) + { + return false; + } + } + + return true; + } + + JERRY_ASSERT ((current_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) != 0); + JERRY_ASSERT ((desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) != 0); + + /* 9. */ + if (!(current_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + { + if ((desc_p->flags & JERRY_PROP_IS_SET_DEFINED) && desc_p->set_p != current_p->set_p) + { + return false; + } + + if ((desc_p->flags & JERRY_PROP_IS_GET_DEFINED) && desc_p->get_p != current_p->get_p) + { + return false; + } + } + + return true; +} /* ecma_op_is_compatible_property_descriptor */ + +/** + * CompletePropertyDescriptor method for proxy internal method + * + * See also: + * ECMA-262 v6, 6.2.4.5 + */ +void +ecma_op_to_complete_property_descriptor (ecma_property_descriptor_t *desc_p) /**< target descriptor */ +{ + /* 4. */ + if (!(desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED))) + { + /* a. */ + desc_p->flags |= JERRY_PROP_IS_VALUE_DEFINED; + } + /* 5. */ + else + { + desc_p->flags |= (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED); + } +} /* ecma_op_to_complete_property_descriptor */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.h new file mode 100644 index 00000000..210f176c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.h @@ -0,0 +1,50 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_OBJECTS_GENERAL_H +#define ECMA_OBJECTS_GENERAL_H + +#include "ecma-conversion.h" +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaobjectsinternalops ECMA objects' operations + * @{ + */ + +ecma_object_t *ecma_op_create_object_object_noarg (void); +ecma_object_t *ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prototype_p); + +ecma_value_t ecma_op_general_object_delete (ecma_object_t *obj_p, ecma_string_t *property_name_p, bool is_throw); +ecma_value_t ecma_op_general_object_default_value (ecma_object_t *obj_p, ecma_preferred_type_hint_t hint); +ecma_value_t ecma_op_general_object_ordinary_value (ecma_object_t *obj_p, ecma_preferred_type_hint_t hint); +ecma_value_t ecma_op_general_object_define_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); + +void ecma_op_to_complete_property_descriptor (ecma_property_descriptor_t *desc_p); + +bool ecma_op_is_compatible_property_descriptor (const ecma_property_descriptor_t *desc_p, + const ecma_property_descriptor_t *current_p, + bool is_extensible); + +/** + * @} + * @} + */ + +#endif /* !ECMA_OBJECTS_GENERAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.cpp new file mode 100644 index 00000000..b77fb824 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.cpp @@ -0,0 +1,3450 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-objects.h" + +#include "ecma-arguments-object.h" +#include "ecma-array-object.h" +#include "ecma-bigint.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lcache.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-proxy-object.h" +#include "ecma-string-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#include "ecma-arraybuffer-object.h" +#include "ecma-typedarray-object.h" +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaobjectsinternalops ECMA objects' operations + * @{ + */ + +/** + * Hash bitmap size for ecma objects + */ +#define ECMA_OBJECT_HASH_BITMAP_SIZE 256 + +/** + * Assert that specified object type value is valid + * + * @param type object's implementation-defined type + */ +#ifndef JERRY_NDEBUG +#define JERRY_ASSERT_OBJECT_TYPE_IS_VALID(type) JERRY_ASSERT (type < ECMA_OBJECT_TYPE__MAX); +#else /* JERRY_NDEBUG */ +#define JERRY_ASSERT_OBJECT_TYPE_IS_VALID(type) +#endif /* !JERRY_NDEBUG */ + +/** + * [[GetOwnProperty]] ecma object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return pointer to a property - if it exists, + * NULL (i.e. ecma-undefined) - otherwise. + */ +ecma_property_t +ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_property_ref_t *property_ref_p, /**< property reference */ + uint32_t options) /**< option bits */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); +#if JERRY_BUILTIN_PROXY + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); +#endif /* JERRY_BUILTIN_PROXY */ + JERRY_ASSERT (property_name_p != NULL); + JERRY_ASSERT (options == ECMA_PROPERTY_GET_NO_OPTIONS || property_ref_p != NULL); + + ecma_object_base_type_t base_type = ecma_get_object_base_type (object_p); + + switch (base_type) + { + case ECMA_OBJECT_BASE_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_STRING: + { + if (ecma_string_is_length (property_name_p)) + { + if (options & ECMA_PROPERTY_GET_VALUE) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + + lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); + property_ref_p->virtual_value = ecma_make_uint32_value (length); + } + + return ECMA_PROPERTY_VIRTUAL; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + + if (index < ecma_string_get_length (prim_value_str_p)) + { + if (options & ECMA_PROPERTY_GET_VALUE) + { + ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index); + ecma_string_t *char_str_p = ecma_new_ecma_string_from_code_unit (char_at_idx); + property_ref_p->virtual_value = ecma_make_string_value (char_str_p); + } + + return ECMA_PROPERTY_FLAG_ENUMERABLE | ECMA_PROPERTY_VIRTUAL; + } + } + break; + } +#if JERRY_BUILTIN_TYPEDARRAY + /* ES2015 9.4.5.1 */ + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + if (ecma_prop_name_is_symbol (property_name_p)) + { + break; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX) + { + JERRY_ASSERT (index == UINT32_MAX); + + if (!ecma_typedarray_is_element_index (property_name_p)) + { + break; + } + } + + ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p); + ecma_value_t value = ecma_get_typedarray_element (&info, index); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW; + } + + if (JERRY_UNLIKELY (ecma_is_value_undefined (value))) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; + } + + if (options & ECMA_PROPERTY_GET_VALUE) + { + property_ref_p->virtual_value = value; + } + else + { + ecma_fast_free_value (value); + } + + return ECMA_PROPERTY_ENUMERABLE_WRITABLE | ECMA_PROPERTY_VIRTUAL; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: + { + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + if (!ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG)) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; + } + + /* ECMA-262 v11, 26.3.1 */ + if (options & ECMA_PROPERTY_GET_VALUE) + { + property_ref_p->virtual_value = ecma_make_magic_string_value (LIT_MAGIC_STRING_MODULE_UL); + } + + return ECMA_PROPERTY_VIRTUAL; + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; + } + + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + if (*property_p & ECMA_PROPERTY_FLAG_DATA) + { + if (options & ECMA_PROPERTY_GET_EXT_REFERENCE) + { + ((ecma_extended_property_ref_t *) property_ref_p)->property_p = property_p; + } + + if (property_ref_p != NULL) + { + property_ref_p->value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + } + + return *property_p; + } + + if (options & ECMA_PROPERTY_GET_VALUE) + { + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + prop_value_p = ecma_get_property_value_from_named_reference (prop_value_p); + property_ref_p->virtual_value = ecma_fast_copy_value (prop_value_p->value); + } + + return ECMA_PROPERTY_ENUMERABLE_WRITABLE | ECMA_PROPERTY_VIRTUAL; + } +#endif /* JERRY_MODULE_SYSTEM */ + } + break; + } + case ECMA_OBJECT_BASE_TYPE_ARRAY: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ecma_string_is_length (property_name_p)) + { + if (options & ECMA_PROPERTY_GET_VALUE) + { + property_ref_p->virtual_value = ecma_make_uint32_value (ext_object_p->u.array.length); + } + + uint32_t length_prop = ext_object_p->u.array.length_prop_and_hole_count; + return length_prop & (ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_VIRTUAL); + } + + if (ecma_op_array_is_fast_array (ext_object_p)) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + if (JERRY_LIKELY (index < ext_object_p->u.array.length)) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + if (ecma_is_value_array_hole (values_p[index])) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND; + } + + if (options & ECMA_PROPERTY_GET_VALUE) + { + property_ref_p->virtual_value = ecma_fast_copy_value (values_p[index]); + } + + return ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | ECMA_PROPERTY_VIRTUAL; + } + } + + return ECMA_PROPERTY_TYPE_NOT_FOUND; + } + + break; + } + default: + { + break; + } + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + ecma_object_type_t type = ecma_get_object_type (object_p); + + if (property_p == NULL) + { + switch (type) + { + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + if (ecma_builtin_function_is_routine (object_p)) + { + property_p = ecma_builtin_routine_try_to_instantiate_property (object_p, property_name_p); + break; + } + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + if (((ecma_extended_object_t *) object_p)->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS) + { + property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); + } + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + /* Get prototype physical property. */ + property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + default: + { + break; + } + } + + if (property_p == NULL) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND; + } + } + else if (type == ECMA_OBJECT_TYPE_CLASS + && ((ecma_extended_object_t *) object_p)->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS + && (((ecma_extended_object_t *) object_p)->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index < ext_object_p->u.cls.u2.formal_params_number) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) + { +#if JERRY_LCACHE + /* Mapped arguments initialized properties MUST not be lcached */ + if (ecma_is_property_lcached (property_p)) + { + jmem_cpointer_t prop_name_cp; + + if (JERRY_UNLIKELY (ECMA_IS_DIRECT_STRING (property_name_p))) + { + prop_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (property_name_p); + } + else + { + ECMA_SET_NON_NULL_POINTER (prop_name_cp, property_name_p); + } + ecma_lcache_invalidate (object_p, prop_name_cp, property_p); + } +#endif /* JERRY_LCACHE */ + ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); + + ecma_value_t binding_value = ecma_op_get_binding_value (lex_env_p, name_p, true); + + ecma_named_data_property_assign_value (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), binding_value); + ecma_free_value (binding_value); + } + } + } + + if (options & ECMA_PROPERTY_GET_EXT_REFERENCE) + { + ((ecma_extended_property_ref_t *) property_ref_p)->property_p = property_p; + } + + if (property_ref_p != NULL) + { + property_ref_p->value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + } + + return *property_p; +} /* ecma_op_object_get_own_property */ + +/** + * Generic [[HasProperty]] operation + * + * See also: + * ECMAScript v6, 9.1.7.1 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE_FALSE} - whether the property is found + */ +ecma_value_t +ecma_op_object_has_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + while (true) + { +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_has (object_p, property_name_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 2 - 3. */ + ecma_property_t property = + ecma_op_object_get_own_property (object_p, property_name_p, NULL, ECMA_PROPERTY_GET_NO_OPTIONS); + + if (property != ECMA_PROPERTY_TYPE_NOT_FOUND) + { +#if JERRY_BUILTIN_TYPEDARRAY + if (JERRY_UNLIKELY (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW)) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP || ECMA_PROPERTY_IS_FOUND (property)); + + return ecma_make_boolean_value (property != ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + } + + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (object_p); + + /* 7. */ + if (proto_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_FALSE; + } + + object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + } +} /* ecma_op_object_has_property */ + +/** + * Search the value corresponding to a property name + * + * Note: search includes prototypes + * + * @return ecma value if property is found + * ECMA_VALUE_NOT_FOUND if property is not found + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ + ecma_object_t *object_p, /**< target object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (property_name_p != NULL); + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + + ecma_object_base_type_t base_type = ecma_get_object_base_type (object_p); + + switch (base_type) + { + case ECMA_OBJECT_BASE_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_STRING: + { + if (ecma_string_is_length (property_name_p)) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); + + return ecma_make_uint32_value (length); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + + if (index < ecma_string_get_length (prim_value_str_p)) + { + ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index); + return ecma_make_string_value (ecma_new_ecma_string_from_code_unit (char_at_idx)); + } + } + break; + } + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + if (!(ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) + { + break; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index < ext_object_p->u.cls.u2.formal_params_number) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) + { + ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); + + return ecma_op_get_binding_value (lex_env_p, name_p, true); + } + } + break; + } +#if JERRY_BUILTIN_TYPEDARRAY + /* ES2015 9.4.5.4 */ + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + if (ecma_prop_name_is_symbol (property_name_p)) + { + break; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX) + { + JERRY_ASSERT (index == UINT32_MAX); + + if (!ecma_typedarray_is_element_index (property_name_p)) + { + break; + } + } + + ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p); + return ecma_get_typedarray_element (&info, index); + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: + { + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + /* ECMA-262 v11, 26.3.1 */ + if (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_MODULE_UL); + } + + return ECMA_VALUE_NOT_FOUND; + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) + { + return ECMA_VALUE_NOT_FOUND; + } + + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + prop_value_p = ecma_get_property_value_from_named_reference (prop_value_p); + + if (JERRY_UNLIKELY (prop_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + } + + return ecma_fast_copy_value (prop_value_p->value); + } +#endif /* JERRY_MODULE_SYSTEM */ + } + break; + } + case ECMA_OBJECT_BASE_TYPE_ARRAY: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ecma_string_is_length (property_name_p)) + { + return ecma_make_uint32_value (ext_object_p->u.array.length); + } + + if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p))) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (JERRY_LIKELY (index != ECMA_STRING_NOT_ARRAY_INDEX)) + { + if (JERRY_LIKELY (index < ext_object_p->u.array.length)) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + return (ecma_is_value_array_hole (values_p[index]) ? ECMA_VALUE_NOT_FOUND + : ecma_fast_copy_value (values_p[index])); + } + } + return ECMA_VALUE_NOT_FOUND; + } + + break; + } + default: + { + break; + } + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) + { + switch (ecma_get_object_type (object_p)) + { + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + if (ecma_builtin_function_is_routine (object_p)) + { + property_p = ecma_builtin_routine_try_to_instantiate_property (object_p, property_name_p); + break; + } + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + if (((ecma_extended_object_t *) object_p)->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS) + { + property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); + } + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + /* Get prototype physical property. */ + property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + default: + { + break; + } + } + + if (property_p == NULL) + { + return ECMA_VALUE_NOT_FOUND; + } + } + + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (*property_p & ECMA_PROPERTY_FLAG_DATA) + { + return ecma_fast_copy_value (prop_value_p->value); + } + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (prop_value_p); + + if (get_set_pair_p->getter_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); + + return ecma_op_function_call (getter_p, base_value, NULL, 0); +} /* ecma_op_object_find_own */ + +/** + * Search the value corresponding to a property index + * + * Note: this method falls back to the general ecma_op_object_find + * + * @return ecma value if property is found + * ECMA_VALUE_NOT_FOUND if property is not found + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_find_by_index (ecma_object_t *object_p, /**< the object */ + ecma_length_t index) /**< property index */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_op_object_find (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index)); + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_op_object_find (object_p, index_str_p); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_op_object_find_by_index */ + +/** + * Search the value corresponding to a property name + * + * Note: search includes prototypes + * + * @return ecma value if property is found + * ECMA_VALUE_NOT_FOUND if property is not found + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_find (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_value_t base_value = ecma_make_object_value (object_p); + + while (true) + { +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_find (object_p, property_name_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t value = ecma_op_object_find_own (base_value, object_p, property_name_p); + + if (ecma_is_value_found (value)) + { + return value; + } + + if (object_p->u2.prototype_cp == JMEM_CP_NULL) + { + break; + } + + object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, object_p->u2.prototype_cp); + } + + return ECMA_VALUE_NOT_FOUND; +} /* ecma_op_object_find */ + +/** + * [[Get]] operation of ecma object + * + * This function returns the value of a named property, or undefined + * if the property is not found in the prototype chain. If the property + * is an accessor, it calls the "get" callback function and returns + * with its result (including error throws). + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + return ecma_op_object_get_with_receiver (object_p, property_name_p, ecma_make_object_value (object_p)); +} /* ecma_op_object_get */ + +/** + * [[Get]] operation of ecma object with the specified receiver + * + * This function returns the value of a named property, or undefined + * if the property is not found in the prototype chain. If the property + * is an accessor, it calls the "get" callback function and returns + * with its result (including error throws). + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get_with_receiver (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t receiver) /**< receiver to invoke getter function */ +{ + while (true) + { +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_get (object_p, property_name_p, receiver); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t value = ecma_op_object_find_own (receiver, object_p, property_name_p); + + if (ecma_is_value_found (value)) + { + return value; + } + + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (object_p); + + if (proto_cp == JMEM_CP_NULL) + { + break; + } + + object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_object_get_with_receiver */ + +/** + * [[Get]] operation of ecma object specified for property index + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get_by_index (ecma_object_t *object_p, /**< the object */ + ecma_length_t index) /**< property index */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_op_object_get (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index)); + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_op_object_get (object_p, index_str_p); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_op_object_get_by_index */ + +/** + * Perform ToLength(O.[[Get]]("length")) operation + * + * The property is converted to uint32 during the operation + * + * @return ECMA_VALUE_ERROR - if there was any error during the operation + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +ecma_op_object_get_length (ecma_object_t *object_p, /**< the object */ + ecma_length_t *length_p) /**< [out] length value converted to uint32 */ +{ + if (JERRY_LIKELY (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY)) + { + *length_p = (ecma_length_t) ecma_array_get_length (object_p); + return ECMA_VALUE_EMPTY; + } + + ecma_value_t len_value = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_LENGTH); + ecma_value_t len_number = ecma_op_to_length (len_value, length_p); + ecma_free_value (len_value); + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (len_number) || ecma_is_value_empty (len_number)); + + return len_number; +} /* ecma_op_object_get_length */ + +/** + * [[Get]] operation of ecma object where the property name is a magic string + * + * This function returns the value of a named property, or undefined + * if the property is not found in the prototype chain. If the property + * is an accessor, it calls the "get" callback function and returns + * with its result (including error throws). + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get_by_magic_id (ecma_object_t *object_p, /**< the object */ + lit_magic_string_id_t property_id) /**< property magic string id */ +{ + return ecma_op_object_get (object_p, ecma_get_magic_string (property_id)); +} /* ecma_op_object_get_by_magic_id */ + +/** + * Descriptor string for each global symbol + */ +static const uint16_t ecma_global_symbol_descriptions[] = { + LIT_MAGIC_STRING_ASYNC_ITERATOR, LIT_MAGIC_STRING_HAS_INSTANCE, LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, + LIT_MAGIC_STRING_ITERATOR, LIT_MAGIC_STRING_MATCH, LIT_MAGIC_STRING_REPLACE, + LIT_MAGIC_STRING_SEARCH, LIT_MAGIC_STRING_SPECIES, LIT_MAGIC_STRING_SPLIT, + LIT_MAGIC_STRING_TO_PRIMITIVE, LIT_MAGIC_STRING_TO_STRING_TAG, LIT_MAGIC_STRING_UNSCOPABLES, + LIT_MAGIC_STRING_MATCH_ALL, +}; + +JERRY_STATIC_ASSERT ((sizeof (ecma_global_symbol_descriptions) / sizeof (uint16_t) == ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT), + ecma_global_symbol_descriptions_must_have_global_symbol_count_elements); + +/** + * [[Get]] a well-known symbol by the given property id + * + * @return pointer to the requested well-known symbol + */ +ecma_string_t * +ecma_op_get_global_symbol (lit_magic_string_id_t property_id) /**< property symbol id */ +{ + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (property_id)); + + uint32_t symbol_index = (uint32_t) property_id - (uint32_t) LIT_GLOBAL_SYMBOL__FIRST; + jmem_cpointer_t symbol_cp = JERRY_CONTEXT (global_symbols_cp)[symbol_index]; + + if (symbol_cp != JMEM_CP_NULL) + { + ecma_string_t *symbol_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, symbol_cp); + ecma_ref_ecma_string (symbol_p); + return symbol_p; + } + + ecma_string_t *symbol_dot_p = ecma_get_magic_string (LIT_MAGIC_STRING_SYMBOL_DOT_UL); + uint16_t description = ecma_global_symbol_descriptions[symbol_index]; + ecma_string_t *name_p = ecma_get_magic_string ((lit_magic_string_id_t) description); + ecma_string_t *descriptor_p = ecma_concat_ecma_strings (symbol_dot_p, name_p); + + ecma_string_t *symbol_p = ecma_new_symbol_from_descriptor_string (ecma_make_string_value (descriptor_p)); + symbol_p->u.hash = (uint16_t) ((property_id << ECMA_SYMBOL_FLAGS_SHIFT) | ECMA_SYMBOL_FLAG_GLOBAL); + + ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (global_symbols_cp)[symbol_index], symbol_p); + + ecma_ref_ecma_string (symbol_p); + return symbol_p; +} /* ecma_op_get_global_symbol */ + +/** + * Checks whether the string equals to the global symbol. + * + * @return true - if the string equals to the global symbol + * false - otherwise + */ +bool +ecma_op_compare_string_to_global_symbol (ecma_string_t *string_p, /**< string to compare */ + lit_magic_string_id_t property_id) /**< property symbol id */ +{ + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (property_id)); + + uint32_t symbol_index = (uint32_t) property_id - (uint32_t) LIT_GLOBAL_SYMBOL__FIRST; + jmem_cpointer_t symbol_cp = JERRY_CONTEXT (global_symbols_cp)[symbol_index]; + + return (symbol_cp != JMEM_CP_NULL && string_p == ECMA_GET_NON_NULL_POINTER (ecma_string_t, symbol_cp)); +} /* ecma_op_compare_string_to_global_symbol */ + +/** + * [[Get]] operation of ecma object where the property is a well-known symbol + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get_by_symbol_id (ecma_object_t *object_p, /**< the object */ + lit_magic_string_id_t property_id) /**< property symbol id */ +{ + ecma_string_t *symbol_p = ecma_op_get_global_symbol (property_id); + ecma_value_t ret_value = ecma_op_object_get (object_p, symbol_p); + ecma_deref_ecma_string (symbol_p); + + return ret_value; +} /* ecma_op_object_get_by_symbol_id */ + +/** + * GetMethod operation + * + * See also: ECMA-262 v6, 7.3.9 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator function object - if success + * raised error - otherwise + */ +static ecma_value_t +ecma_op_get_method (ecma_value_t value, /**< ecma value */ + ecma_string_t *prop_name_p) /**< property name */ +{ + /* 2. */ + ecma_value_t obj_value = ecma_op_to_object (value); + + if (ECMA_IS_VALUE_ERROR (obj_value)) + { + return obj_value; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); + ecma_value_t func; + + func = ecma_op_object_get (obj_p, prop_name_p); + ecma_deref_object (obj_p); + + /* 3. */ + if (ECMA_IS_VALUE_ERROR (func)) + { + return func; + } + + /* 4. */ + if (ecma_is_value_undefined (func) || ecma_is_value_null (func)) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 5. */ + if (!ecma_op_is_callable (func)) + { + ecma_free_value (func); + return ecma_raise_type_error (ECMA_ERR_ITERATOR_IS_NOT_CALLABLE); + } + + /* 6. */ + return func; +} /* ecma_op_get_method */ + +/** + * GetMethod operation when the property is a well-known symbol + * + * See also: ECMA-262 v6, 7.3.9 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator function object - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_get_method_by_symbol_id (ecma_value_t value, /**< ecma value */ + lit_magic_string_id_t symbol_id) /**< property symbol id */ +{ + ecma_string_t *prop_name_p = ecma_op_get_global_symbol (symbol_id); + ecma_value_t ret_value = ecma_op_get_method (value, prop_name_p); + ecma_deref_ecma_string (prop_name_p); + + return ret_value; +} /* ecma_op_get_method_by_symbol_id */ + +/** + * GetMethod operation when the property is a magic string + * + * See also: ECMA-262 v6, 7.3.9 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator function object - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_get_method_by_magic_id (ecma_value_t value, /**< ecma value */ + lit_magic_string_id_t magic_id) /**< property magic id */ +{ + return ecma_op_get_method (value, ecma_get_magic_string (magic_id)); +} /* ecma_op_get_method_by_magic_id */ + +/** + * [[Put]] ecma general object's operation specialized for property index + * + * Note: This function falls back to the general ecma_op_object_put + * + * @return ecma value + * The returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_object_put_by_index (ecma_object_t *object_p, /**< the object */ + ecma_length_t index, /**< property index */ + ecma_value_t value, /**< ecma value */ + bool is_throw) /**< flag that controls failure handling */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_op_object_put (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), value, is_throw); + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_op_object_put (object_p, index_str_p, value, is_throw); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_op_object_put_by_index */ + +/** + * [[Put]] ecma general object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.5 + * Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4 + * + * @return ecma value + * The returned value must be freed with ecma_free_value. + * + * Returns with ECMA_VALUE_TRUE if the operation is + * successful. Otherwise it returns with an error object + * or ECMA_VALUE_FALSE. + * + * Note: even if is_throw is false, the setter can throw an + * error, and this function returns with that error. + */ +ecma_value_t +ecma_op_object_put (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + bool is_throw) /**< flag that controls failure handling */ +{ + return ecma_op_object_put_with_receiver (object_p, + property_name_p, + value, + ecma_make_object_value (object_p), + is_throw); +} /* ecma_op_object_put */ + +/** + * [[Set]] ( P, V, Receiver) operation part for ordinary objects + * + * See also: ECMAScript v6, 9.19.9 + * + * @return ecma value + * The returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_op_object_put_apply_receiver (ecma_value_t receiver, /**< receiver */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< value to set */ + bool is_throw) /**< flag that controls failure handling */ +{ + /* 5.b */ + if (!ecma_is_value_object (receiver)) + { + return ECMA_REJECT (is_throw, ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT); + } + + ecma_object_t *receiver_obj_p = ecma_get_object_from_value (receiver); + + ecma_property_descriptor_t prop_desc; + /* 5.c */ + ecma_value_t status = ecma_op_object_get_own_property_descriptor (receiver_obj_p, property_name_p, &prop_desc); + + /* 5.d */ + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + /* 5.e */ + if (ecma_is_value_true (status)) + { + ecma_value_t result; + + /* 5.e.i - 5.e.ii */ + if (prop_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED) + || !(prop_desc.flags & JERRY_PROP_IS_WRITABLE)) + { + result = ecma_raise_property_redefinition (property_name_p, prop_desc.flags); + } + else + { + /* 5.e.iii */ + JERRY_ASSERT (prop_desc.flags & JERRY_PROP_IS_VALUE_DEFINED); + ecma_free_value (prop_desc.value); + prop_desc.value = ecma_copy_value (value); + + /* 5.e.iv */ + result = ecma_op_object_define_own_property (receiver_obj_p, property_name_p, &prop_desc); + + if (JERRY_UNLIKELY (ecma_is_value_false (result))) + { + result = ECMA_REJECT (is_throw, ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH); + } + } + + ecma_free_property_descriptor (&prop_desc); + + return result; + } + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (receiver_obj_p)) + { + ecma_property_descriptor_t desc; + /* Based on: ES6 9.1.9 [[Set]] 4.d.i. / ES11 9.1.9.2 OrdinarySetWithOwnDescriptor 2.c.i. */ + desc.flags = (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE + | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED + | JERRY_PROP_IS_VALUE_DEFINED); + desc.value = value; + ecma_value_t ret_value = ecma_proxy_object_define_own_property (receiver_obj_p, property_name_p, &desc); + + if (JERRY_UNLIKELY (ecma_is_value_false (ret_value))) + { + ret_value = ECMA_REJECT (is_throw, ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH); + } + + return ret_value; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (receiver_obj_p))) + { + ecma_fast_array_convert_to_normal (receiver_obj_p); + } + + /* 5.f.i */ + ecma_property_value_t *new_prop_value_p; + new_prop_value_p = ecma_create_named_data_property (receiver_obj_p, + property_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + JERRY_ASSERT (ecma_is_value_undefined (new_prop_value_p->value)); + new_prop_value_p->value = ecma_copy_value_if_not_object (value); + + return ECMA_VALUE_TRUE; +} /* ecma_op_object_put_apply_receiver */ + +/** + * [[Put]] ecma general object's operation with given receiver + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.5 + * ECMA-262 v6, 9.1.9 + * Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4 + * + * @return ecma value + * The returned value must be freed with ecma_free_value. + * + * Returns with ECMA_VALUE_TRUE if the operation is + * successful. Otherwise it returns with an error object + * or ECMA_VALUE_FALSE. + * + * Note: even if is_throw is false, the setter can throw an + * error, and this function returns with that error. + */ +ecma_value_t +ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + ecma_value_t receiver, /**< receiver */ + bool is_throw) /**< flag that controls failure handling */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (property_name_p != NULL); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_set (object_p, property_name_p, value, receiver, is_throw); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_object_base_type_t base_type = ecma_get_object_base_type (object_p); + + switch (base_type) + { + case ECMA_OBJECT_BASE_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + if (!(ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) + { + break; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index < ext_object_p->u.cls.u2.formal_params_number) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) + { + ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); + ecma_op_set_mutable_binding (lex_env_p, name_p, value, true); + return ECMA_VALUE_TRUE; + } + } + break; + } +#if JERRY_BUILTIN_TYPEDARRAY + /* ES2015 9.4.5.5 */ + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + if (ecma_prop_name_is_symbol (property_name_p)) + { + break; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX) + { + JERRY_ASSERT (index == UINT32_MAX); + + if (!ecma_typedarray_is_element_index (property_name_p)) + { + break; + } + } + + ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p); + return ecma_set_typedarray_element (&info, value, index); + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } +#endif /* JERRY_MODULE_SYSTEM */ + } + break; + } + case ECMA_OBJECT_BASE_TYPE_ARRAY: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ecma_string_is_length (property_name_p)) + { + if (ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_op_array_object_set_length (object_p, value, 0); + } + + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + + if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p))) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (JERRY_UNLIKELY (index == ECMA_STRING_NOT_ARRAY_INDEX)) + { + ecma_fast_array_convert_to_normal (object_p); + } + else if (ecma_fast_array_set_property (object_p, index, value)) + { + return ECMA_VALUE_TRUE; + } + } + + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + break; + } + default: + { + break; + } + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) + { + switch (ecma_get_object_type (object_p)) + { + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + if (ecma_builtin_function_is_routine (object_p)) + { + property_p = ecma_builtin_routine_try_to_instantiate_property (object_p, property_name_p); + break; + } + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_STRING: + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + + if (index < ecma_string_get_length (prim_value_str_p)) + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + } + break; + } + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + } + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + if (ecma_string_is_length (property_name_p)) + { + /* Uninitialized 'length' property is non-writable (ECMA-262 v6, 19.2.4.1) */ + if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (((ecma_extended_object_t *) object_p)->u.function.scope_cp)) + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + } + + /* Get prototype physical property. */ + property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + default: + { + break; + } + } + } + + jmem_cpointer_t setter_cp = JMEM_CP_NULL; + + if (property_p != NULL) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + if (*property_p & ECMA_PROPERTY_FLAG_DATA) + { + if (ecma_is_property_writable (*property_p)) + { + if (ecma_make_object_value (object_p) != receiver) + { + return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw); + } + + /* There is no need for special casing arrays here because changing the + * value of an existing property never changes the length of an array. */ + ecma_named_data_property_assign_value (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); + return ECMA_VALUE_TRUE; + } + } + else + { + ecma_getter_setter_pointers_t *get_set_pair_p; + get_set_pair_p = ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (property_p)); + setter_cp = get_set_pair_p->setter_cp; + } + } + else + { + bool create_new_property = true; + + jmem_cpointer_t obj_cp; + ECMA_SET_NON_NULL_POINTER (obj_cp, object_p); + ecma_object_t *proto_p = object_p; + + while (true) + { + obj_cp = ecma_op_ordinary_object_get_prototype_of (proto_p); + + if (obj_cp == JMEM_CP_NULL) + { + break; + } + + ecma_property_ref_t property_ref = { NULL }; + proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_cp); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (proto_p)) + { + return ecma_op_object_put_with_receiver (proto_p, property_name_p, value, receiver, is_throw); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_property_t inherited_property = + ecma_op_object_get_own_property (proto_p, property_name_p, &property_ref, ECMA_PROPERTY_GET_NO_OPTIONS); + + if (ECMA_PROPERTY_IS_FOUND (inherited_property)) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (inherited_property)); + + if (!(inherited_property & ECMA_PROPERTY_FLAG_DATA)) + { + setter_cp = ecma_get_named_accessor_property (property_ref.value_p)->setter_cp; + create_new_property = false; + break; + } + + create_new_property = ecma_is_property_writable (inherited_property); + break; + } + + JERRY_ASSERT (inherited_property == ECMA_PROPERTY_TYPE_NOT_FOUND + || inherited_property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + } + +#if JERRY_BUILTIN_PROXY + if (create_new_property && ecma_is_value_object (receiver) + && ECMA_OBJECT_IS_PROXY (ecma_get_object_from_value (receiver))) + { + return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw); + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (create_new_property && ecma_op_ordinary_object_is_extensible (object_p)) + { + const ecma_object_base_type_t obj_base_type = ecma_get_object_base_type (object_p); + + if (obj_base_type == ECMA_OBJECT_BASE_TYPE_CLASS) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS + && ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + return ecma_builtin_helper_def_prop (object_p, property_name_p, value, flags); + } + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (obj_base_type == ECMA_OBJECT_BASE_TYPE_ARRAY && index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (index < UINT32_MAX && index >= ext_object_p->u.array.length) + { + if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + + ext_object_p->u.array.length = index + 1; + } + } + + return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw); + + ecma_property_value_t *new_prop_value_p; + new_prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + JERRY_ASSERT (ecma_is_value_undefined (new_prop_value_p->value)); + new_prop_value_p->value = ecma_copy_value_if_not_object (value); + return ECMA_VALUE_TRUE; + } + } + + if (setter_cp == JMEM_CP_NULL) + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + + ecma_value_t ret_value = + ecma_op_function_call (ECMA_GET_NON_NULL_POINTER (ecma_object_t, setter_cp), receiver, &value, 1); + + if (!ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_fast_free_value (ret_value); + ret_value = ECMA_VALUE_TRUE; + } + + return ret_value; +} /* ecma_op_object_put_with_receiver */ + +/** + * [[Delete]] ecma object's operation specialized for property index + * + * Note: + * This method falls back to the general ecma_op_object_delete + * + * @return true - if deleted successfully + * false - or type error otherwise (based in 'is_throw') + */ +ecma_value_t +ecma_op_object_delete_by_index (ecma_object_t *obj_p, /**< the object */ + ecma_length_t index, /**< property index */ + bool is_throw) /**< flag that controls failure handling */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_op_object_delete (obj_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), is_throw); + ; + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_op_object_delete (obj_p, index_str_p, is_throw); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_op_object_delete_by_index */ + +/** + * [[Delete]] ecma object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * Note: + * returned value must be freed with ecma_free_value + * + * @return true - if deleted successfully + * false - or type error otherwise (based in 'is_throw') + */ +ecma_value_t +ecma_op_object_delete (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + bool is_strict) /**< flag that controls failure handling */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (property_name_p != NULL); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_delete_property (obj_p, property_name_p, is_strict); + } +#endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); + + return ecma_op_general_object_delete (obj_p, property_name_p, is_strict); +} /* ecma_op_object_delete */ + +/** + * [[DefaultValue]] ecma object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_default_value (ecma_object_t *obj_p, /**< the object */ + ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + + JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); + + /* + * typedef ecma_property_t * (*default_value_ptr_t) (ecma_object_t *, ecma_string_t *); + * static const default_value_ptr_t default_value [ECMA_OBJECT_TYPE__COUNT] = + * { + * [ECMA_OBJECT_TYPE_GENERAL] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_CLASS] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_FUNCTION] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_NATIVE_FUNCTION] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_ARRAY] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_BOUND_FUNCTION] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_PSEUDO_ARRAY] = &ecma_op_general_object_default_value + * }; + * + * return default_value[type] (obj_p, property_name_p); + */ + + return ecma_op_general_object_default_value (obj_p, hint); +} /* ecma_op_object_default_value */ + +/** + * [[DefineOwnProperty]] ecma object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_define_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property + * descriptor */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (property_name_p != NULL); + + const ecma_object_type_t type = ecma_get_object_type (obj_p); + + switch (type) + { + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + return ecma_op_arguments_object_define_own_property (obj_p, property_name_p, property_desc_p); + } +#if JERRY_BUILTIN_TYPEDARRAY + /* ES2015 9.4.5.1 */ + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + return ecma_op_typedarray_define_own_property (obj_p, property_name_p, property_desc_p); + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + } + break; + } + case ECMA_OBJECT_TYPE_ARRAY: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + return ecma_op_array_object_define_own_property (obj_p, property_name_p, property_desc_p); + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + return ecma_proxy_object_define_own_property (obj_p, property_name_p, property_desc_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + default: + { + break; + } + } + + return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p); +} /* ecma_op_object_define_own_property */ + +/** + * Get property descriptor from specified property + * + * depending on the property type the following fields are set: + * - for named data properties: { [Value], [Writable], [Enumerable], [Configurable] }; + * - for named accessor properties: { [Get] - if defined, + * [Set] - if defined, + * [Enumerable], [Configurable] + * }. + * + * The output property descriptor will always be initialized to an empty descriptor. + * + * @return ECMA_VALUE_ERROR - if the Proxy.[[GetOwnProperty]] operation raises error + * ECMA_VALUE_{TRUE, FALSE} - if property found or not + */ +ecma_value_t +ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + *prop_desc_p = ecma_make_empty_property_descriptor (); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_get_own_property_descriptor (object_p, property_name_p, prop_desc_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_property_ref_t property_ref; + property_ref.virtual_value = ECMA_VALUE_EMPTY; + ecma_property_t property = + ecma_op_object_get_own_property (object_p, property_name_p, &property_ref, ECMA_PROPERTY_GET_VALUE); + + if (!ECMA_PROPERTY_IS_FOUND (property)) + { +#if JERRY_BUILTIN_TYPEDARRAY + if (JERRY_UNLIKELY (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW)) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + + return ECMA_VALUE_FALSE; + } + + uint32_t flags = ecma_is_property_enumerable (property) ? JERRY_PROP_IS_ENUMERABLE : JERRY_PROP_NO_OPTS; + flags |= ecma_is_property_configurable (property) ? JERRY_PROP_IS_CONFIGURABLE : JERRY_PROP_NO_OPTS; + + prop_desc_p->flags = (uint16_t) (JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE_DEFINED | flags); + + if (property & ECMA_PROPERTY_FLAG_DATA) + { + if (!ECMA_PROPERTY_IS_VIRTUAL (property)) + { + prop_desc_p->value = ecma_copy_value (property_ref.value_p->value); + } + else + { +#if JERRY_MODULE_SYSTEM + if (JERRY_UNLIKELY (property_ref.virtual_value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } +#endif /* JERRY_MODULE_SYSTEM */ + prop_desc_p->value = property_ref.virtual_value; + } + + prop_desc_p->flags |= + (uint16_t) (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED + | (ecma_is_property_writable (property) ? JERRY_PROP_IS_WRITABLE : JERRY_PROP_NO_OPTS)); + } + else + { + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (property_ref.value_p); + prop_desc_p->flags |= (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED); + + if (get_set_pair_p->getter_cp == JMEM_CP_NULL) + { + prop_desc_p->get_p = NULL; + } + else + { + prop_desc_p->get_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); + ecma_ref_object (prop_desc_p->get_p); + } + + if (get_set_pair_p->setter_cp == JMEM_CP_NULL) + { + prop_desc_p->set_p = NULL; + } + else + { + prop_desc_p->set_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp); + ecma_ref_object (prop_desc_p->set_p); + } + } + + return ECMA_VALUE_TRUE; +} /* ecma_op_object_get_own_property_descriptor */ + +#if JERRY_BUILTIN_PROXY +/** + * Get property descriptor from a target value for a specified property. + * + * For more details see ecma_op_object_get_own_property_descriptor + * + * @return ECMA_VALUE_ERROR - if the Proxy.[[GetOwnProperty]] operation raises error + * ECMA_VALUE_{TRUE, FALSE} - if property found or not + */ +ecma_value_t +ecma_op_get_own_property_descriptor (ecma_value_t target, /**< target value */ + ecma_string_t *property_name_p, /**< property name */ + ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (!ecma_is_value_object (target)) + { + return ECMA_VALUE_FALSE; + } + + return ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (target), property_name_p, prop_desc_p); +} /* ecma_op_get_own_property_descriptor */ +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * [[HasInstance]] ecma object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 9 + * + * @return ecma value containing a boolean value or an error + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_has_instance (ecma_object_t *obj_p, /**< the object */ + ecma_value_t value) /**< argument 'V' */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + + JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); + + if (ecma_op_object_is_callable (obj_p)) + { + return ecma_op_function_has_instance (obj_p, value); + } + + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION_OBJECT); +} /* ecma_op_object_has_instance */ + +/** + * General [[GetPrototypeOf]] abstract operation + * + * Note: returned valid object must be freed. + * + * @return ecma_object_t * - prototype of the input object. + * ECMA_OBJECT_POINTER_ERROR - error reported during Proxy resolve. + * NULL - the input object does not have a prototype. + */ +ecma_object_t * +ecma_op_object_get_prototype_of (ecma_object_t *obj_p) /**< input object */ +{ + JERRY_ASSERT (obj_p != NULL); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + ecma_value_t proto = ecma_proxy_object_get_prototype_of (obj_p); + + if (ECMA_IS_VALUE_ERROR (proto)) + { + return ECMA_OBJECT_POINTER_ERROR; + } + if (ecma_is_value_null (proto)) + { + return NULL; + } + + JERRY_ASSERT (ecma_is_value_object (proto)); + + return ecma_get_object_from_value (proto); + } + else +#endif /* JERRY_BUILTIN_PROXY */ + { + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (obj_p); + + if (proto_cp == JMEM_CP_NULL) + { + return NULL; + } + + ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + ecma_ref_object (proto_p); + + return proto_p; + } +} /* ecma_op_object_get_prototype_of */ + +/** + * Object's isPrototypeOf operation + * + * See also: + * ECMA-262 v5, 15.2.4.6; 3 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if the target object is prototype of the base object + * ECMA_VALUE_FALSE - if the target object is not prototype of the base object + */ +ecma_value_t +ecma_op_object_is_prototype_of (ecma_object_t *base_p, /**< base object */ + ecma_object_t *target_p) /**< target object */ +{ + ecma_ref_object (target_p); + + do + { + ecma_object_t *proto_p = ecma_op_object_get_prototype_of (target_p); + ecma_deref_object (target_p); + + if (proto_p == NULL) + { + return ECMA_VALUE_FALSE; + } + else if (proto_p == ECMA_OBJECT_POINTER_ERROR) + { + return ECMA_VALUE_ERROR; + } + else if (proto_p == base_p) + { + ecma_deref_object (proto_p); + return ECMA_VALUE_TRUE; + } + + /* Advance up on prototype chain. */ + target_p = proto_p; + } while (true); +} /* ecma_op_object_is_prototype_of */ + +/** + * Object's EnumerableOwnPropertyNames operation + * + * See also: + * ECMA-262 v11, 7.3.23 + * + * @return NULL - if operation fails + * collection of property names / values / name-value pairs - otherwise + */ +ecma_collection_t * +ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_enumerable_property_names_options_t option) /**< listing option */ +{ + /* 2. */ + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS); + +#if JERRY_BUILTIN_PROXY + if (JERRY_UNLIKELY (prop_names_p == NULL)) + { + return prop_names_p; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *names_buffer_p = prop_names_p->buffer_p; + /* 3. */ + ecma_collection_t *properties_p = ecma_new_collection (); + + /* 4. */ + for (uint32_t i = 0; i < prop_names_p->item_count; i++) + { + /* 4.a */ + if (ecma_is_value_string (names_buffer_p[i])) + { + ecma_string_t *key_p = ecma_get_string_from_value (names_buffer_p[i]); + + /* 4.a.i */ + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, key_p, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_free (prop_names_p); + ecma_collection_free (properties_p); + + return NULL; + } + + const bool is_enumerable = (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) != 0; + ecma_free_property_descriptor (&prop_desc); + /* 4.a.ii */ + if (is_enumerable) + { + /* 4.a.ii.1 */ + if (option == ECMA_ENUMERABLE_PROPERTY_KEYS) + { + ecma_collection_push_back (properties_p, ecma_copy_value (names_buffer_p[i])); + } + else + { + /* 4.a.ii.2.a */ + ecma_value_t value = ecma_op_object_get (obj_p, key_p); + + if (ECMA_IS_VALUE_ERROR (value)) + { + ecma_collection_free (prop_names_p); + ecma_collection_free (properties_p); + + return NULL; + } + + /* 4.a.ii.2.b */ + if (option == ECMA_ENUMERABLE_PROPERTY_VALUES) + { + ecma_collection_push_back (properties_p, value); + } + else + { + /* 4.a.ii.2.c.i */ + JERRY_ASSERT (option == ECMA_ENUMERABLE_PROPERTY_ENTRIES); + + /* 4.a.ii.2.c.ii */ + ecma_object_t *entry_p = ecma_op_new_array_object (2); + + ecma_builtin_helper_def_prop_by_index (entry_p, + 0, + names_buffer_p[i], + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_builtin_helper_def_prop_by_index (entry_p, 1, value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_free_value (value); + + /* 4.a.ii.2.c.iii */ + ecma_collection_push_back (properties_p, ecma_make_object_value (entry_p)); + } + } + } + } + } + + ecma_collection_free (prop_names_p); + + return properties_p; +} /* ecma_op_object_get_enumerable_property_names */ + +/** + * Helper method for getting lazy instantiated properties for [[OwnPropertyKeys]] + */ +static void +ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + switch (ecma_get_object_type (obj_p)) + { + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + if (ecma_builtin_function_is_routine (obj_p)) + { + ecma_builtin_routine_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + ecma_builtin_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_STRING: + { + ecma_op_string_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + ecma_op_arguments_object_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } +#if JERRY_BUILTIN_TYPEDARRAY + /* ES2015 9.4.5.1 */ + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + } + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + ecma_op_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + ecma_op_external_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_op_bound_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + case ECMA_OBJECT_TYPE_ARRAY: + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + break; + } + default: + { + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_GENERAL + || ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); + break; + } + } +} /* ecma_object_list_lazy_property_names */ + +/** + * Helper routine for heapsort algorithm. + */ +static void +ecma_op_object_heap_sort_shift_down (ecma_value_t *buffer_p, /**< array of items */ + uint32_t item_count, /**< number of items */ + uint32_t item_index) /**< index of updated item */ +{ + while (true) + { + uint32_t highest_index = item_index; + uint32_t current_index = (item_index << 1) + 1; + + if (current_index >= item_count) + { + return; + } + + uint32_t value = ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[highest_index])); + uint32_t left_value = ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[current_index])); + + if (value < left_value) + { + highest_index = current_index; + value = left_value; + } + + current_index++; + + if (current_index < item_count + && value < ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[current_index]))) + { + highest_index = current_index; + } + + if (highest_index == item_index) + { + return; + } + + ecma_value_t tmp = buffer_p[highest_index]; + buffer_p[highest_index] = buffer_p[item_index]; + buffer_p[item_index] = tmp; + + item_index = highest_index; + } +} /* ecma_op_object_heap_sort_shift_down */ + +/** + * Object's [[OwnPropertyKeys]] internal method + * + * Order of names in the collection: + * - integer indices in ascending order + * - other indices in creation order (for built-ins: the order of the properties are listed in specification). + * + * Note: + * Implementation of the routine assumes that new properties are appended to beginning of corresponding object's + * property list, and the list is not reordered (in other words, properties are stored in order that is reversed + * to the properties' addition order). + * + * @return NULL - if the Proxy.[[OwnPropertyKeys]] operation raises error + * collection of property names - otherwise + */ +ecma_collection_t * +ecma_op_object_own_property_keys (ecma_object_t *obj_p, /**< object */ + jerry_property_filter_t filter) /**< name filters */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_own_property_keys (obj_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_op_object_is_fast_array (obj_p)) + { + return ecma_fast_array_object_own_property_keys (obj_p, filter); + } + + ecma_collection_t *prop_names_p = ecma_new_collection (); + ecma_property_counter_t prop_counter = { 0, 0, 0 }; + + ecma_object_list_lazy_property_names (obj_p, prop_names_p, &prop_counter, filter); + + jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + jmem_cpointer_t counter_prop_iter_cp = prop_iter_cp; + + uint32_t array_index_named_props = 0; + uint32_t string_named_props = 0; + uint32_t symbol_named_props = 0; + + while (counter_prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, counter_prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + ecma_property_t *property_p = prop_iter_p->types + i; + + if (!ECMA_PROPERTY_IS_RAW (*property_p) || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) + { + continue; + } + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC + && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT + && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) + { + continue; + } + + ecma_string_t *name_p = ecma_string_from_property_name (*property_p, prop_pair_p->names_cp[i]); + + if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) + { + array_index_named_props++; + } + else if (ecma_prop_name_is_symbol (name_p)) + { + if (!(name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_KEY)) + { + symbol_named_props++; + } + } + else + { + string_named_props++; + } + + ecma_deref_ecma_string (name_p); + } + + counter_prop_iter_cp = prop_iter_p->next_property_cp; + } + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES) + { + JERRY_ASSERT (prop_counter.array_index_named_props == 0); + array_index_named_props = 0; + } + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + JERRY_ASSERT (prop_counter.string_named_props == 0); + string_named_props = 0; + } + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) + { + JERRY_ASSERT (prop_counter.symbol_named_props == 0); + symbol_named_props = 0; + } + + uint32_t total = array_index_named_props + string_named_props + symbol_named_props; + + if (total == 0) + { + return prop_names_p; + } + + ecma_collection_reserve (prop_names_p, total); + prop_names_p->item_count += total; + + ecma_value_t *buffer_p = prop_names_p->buffer_p; + ecma_value_t *array_index_current_p = buffer_p + array_index_named_props + prop_counter.array_index_named_props; + ecma_value_t *string_current_p = array_index_current_p + string_named_props + prop_counter.string_named_props; + + ecma_value_t *symbol_current_p = string_current_p + symbol_named_props + prop_counter.symbol_named_props; + + if (prop_counter.symbol_named_props > 0 && (array_index_named_props + string_named_props) > 0) + { + memmove ((void *) string_current_p, + (void *) (buffer_p + prop_counter.array_index_named_props + prop_counter.string_named_props), + prop_counter.symbol_named_props * sizeof (ecma_value_t)); + } + + if (prop_counter.string_named_props > 0 && array_index_named_props > 0) + { + memmove ((void *) array_index_current_p, + (void *) (buffer_p + prop_counter.array_index_named_props), + prop_counter.string_named_props * sizeof (ecma_value_t)); + } + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + ecma_property_t *property_p = prop_iter_p->types + i; + + if (!ECMA_PROPERTY_IS_RAW (*property_p) || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) + { + continue; + } + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC + && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT + && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) + { + continue; + } + + ecma_string_t *name_p = ecma_string_from_property_name (*property_p, prop_pair_p->names_cp[i]); + + if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + *(--array_index_current_p) = ecma_make_string_value (name_p); + continue; + } + } + else if (ecma_prop_name_is_symbol (name_p)) + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) && !(name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_KEY)) + { + *(--symbol_current_p) = ecma_make_symbol_value (name_p); + continue; + } + } + else + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + *(--string_current_p) = ecma_make_string_value (name_p); + continue; + } + } + + ecma_deref_ecma_string (name_p); + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } + + if (array_index_named_props > 1 || (array_index_named_props == 1 && prop_counter.array_index_named_props > 0)) + { + uint32_t prev_value = 0; + ecma_value_t *array_index_p = buffer_p + prop_counter.array_index_named_props; + ecma_value_t *array_index_end_p = array_index_p + array_index_named_props; + + if (prop_counter.array_index_named_props > 0) + { + prev_value = ecma_string_get_array_index (ecma_get_string_from_value (array_index_p[-1])); + } + + do + { + uint32_t value = ecma_string_get_array_index (ecma_get_string_from_value (*array_index_p++)); + + if (value < prev_value) + { + uint32_t array_props = prop_counter.array_index_named_props + array_index_named_props; + uint32_t i = (array_props >> 1) - 1; + + do + { + ecma_op_object_heap_sort_shift_down (buffer_p, array_props, i); + } while (i-- > 0); + + i = array_props - 1; + + do + { + ecma_value_t tmp = buffer_p[i]; + buffer_p[i] = buffer_p[0]; + buffer_p[0] = tmp; + + ecma_op_object_heap_sort_shift_down (buffer_p, i, 0); + } while (--i > 0); + + break; + } + + prev_value = value; + } while (array_index_p < array_index_end_p); + } + + return prop_names_p; +} /* ecma_op_object_own_property_keys */ + +/** + * EnumerateObjectProperties abstract method + * + * See also: + * ECMA-262 v11, 13.7.5.15 + * + * @return NULL - if the Proxy.[[OwnPropertyKeys]] operation raises error + * collection of enumerable property names - otherwise + */ +ecma_collection_t * +ecma_op_object_enumerate (ecma_object_t *obj_p) /**< object */ +{ + ecma_collection_t *visited_names_p = ecma_new_collection (); + ecma_collection_t *return_names_p = ecma_new_collection (); + + ecma_ref_object (obj_p); + + while (true) + { + ecma_collection_t *keys = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS); + + if (JERRY_UNLIKELY (keys == NULL)) + { + ecma_collection_free (return_names_p); + ecma_collection_free (visited_names_p); + ecma_deref_object (obj_p); + return keys; + } + + for (uint32_t i = 0; i < keys->item_count; i++) + { + ecma_value_t prop_name = keys->buffer_p[i]; + ecma_string_t *name_p = ecma_get_prop_name_from_value (prop_name); + + if (ecma_prop_name_is_symbol (name_p)) + { + continue; + } + + ecma_property_descriptor_t prop_desc; + ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (obj_p, name_p, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (get_desc)) + { + ecma_collection_free (keys); + ecma_collection_free (return_names_p); + ecma_collection_free (visited_names_p); + ecma_deref_object (obj_p); + return NULL; + } + + if (ecma_is_value_true (get_desc)) + { + bool is_enumerable = (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) != 0; + ecma_free_property_descriptor (&prop_desc); + + if (ecma_collection_has_string_value (visited_names_p, name_p) + || ecma_collection_has_string_value (return_names_p, name_p)) + { + continue; + } + + ecma_ref_ecma_string (name_p); + + if (is_enumerable) + { + ecma_collection_push_back (return_names_p, prop_name); + } + else + { + ecma_collection_push_back (visited_names_p, prop_name); + } + } + } + + ecma_collection_free (keys); + + /* Query the prototype. */ + ecma_object_t *proto_p = ecma_op_object_get_prototype_of (obj_p); + ecma_deref_object (obj_p); + + if (proto_p == NULL) + { + break; + } + else if (JERRY_UNLIKELY (proto_p == ECMA_OBJECT_POINTER_ERROR)) + { + ecma_collection_free (return_names_p); + ecma_collection_free (visited_names_p); + return NULL; + } + + /* Advance up on prototype chain. */ + obj_p = proto_p; + } + + ecma_collection_free (visited_names_p); + + return return_names_p; +} /* ecma_op_object_enumerate */ + +#ifndef JERRY_NDEBUG + +/** + * Check if passed object is the instance of specified built-in. + * + * @return true - if the object is instance of the specified built-in + * false - otherwise + */ +static bool +ecma_builtin_is (ecma_object_t *object_p, /**< pointer to an object */ + ecma_builtin_id_t builtin_id) /**< id of built-in to check on */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + + ecma_object_type_t type = ecma_get_object_type (object_p); + + switch (type) + { + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + ecma_extended_object_t *built_in_object_p = (ecma_extended_object_t *) object_p; + + return (built_in_object_p->u.built_in.id == builtin_id && built_in_object_p->u.built_in.routine_id == 0); + } + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + ecma_extended_built_in_object_t *extended_built_in_object_p = (ecma_extended_built_in_object_t *) object_p; + + return (extended_built_in_object_p->built_in.id == builtin_id + && extended_built_in_object_p->built_in.routine_id == 0); + } + default: + { + return false; + } + } +} /* ecma_builtin_is */ + +#endif /* !JERRY_NDEBUG */ + +/** + * The function is used in the assert of ecma_object_get_class_name + * + * @return true - if class name is an object + * false - otherwise + */ +static inline bool +ecma_object_check_class_name_is_object (ecma_object_t *obj_p) /**< object */ +{ +#ifndef JERRY_NDEBUG + return (ecma_builtin_is_global (obj_p) +#if JERRY_BUILTIN_TYPEDARRAY + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE) +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE) +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_INT8ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT8ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_INT16ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT16ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_INT32ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT32ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_FLOAT32ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY_PROTOTYPE) +#if JERRY_NUMBER_TYPE_FLOAT64 + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_FLOAT64ARRAY_PROTOTYPE) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_BIGINT_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_BIGINT64ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_BIGUINT64ARRAY_PROTOTYPE) +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ARRAY_PROTOTYPE_UNSCOPABLES) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_REGEXP_STRING_ITERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_AGGREGATE_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_DATE_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_REGEXP_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_PROMISE_PROTOTYPE) +#if JERRY_BUILTIN_CONTAINER + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_MAP_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SET_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_MAP_ITERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SET_ITERATOR_PROTOTYPE) +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_WEAKREF + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_WEAKREF_PROTOTYPE) +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_DATAVIEW + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE) +#endif /* JERRY_BUILTIN_DATAVIEW */ + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE)); +#else /* JERRY_NDEBUG */ + JERRY_UNUSED (obj_p); + return true; +#endif /* !JERRY_NDEBUG */ +} /* ecma_object_check_class_name_is_object */ + +/** + * Used by ecma_object_get_class_name to get the magic string id of class objects + */ +static const uint16_t ecma_class_object_magic_string_id[] = { + /* These objects require custom property resolving. */ + LIT_MAGIC_STRING_STRING_UL, /**< magic string id of ECMA_OBJECT_CLASS_STRING */ + LIT_MAGIC_STRING_ARGUMENTS_UL, /**< magic string id of ECMA_OBJECT_CLASS_ARGUMENTS */ +#if JERRY_BUILTIN_TYPEDARRAY + LIT_MAGIC_STRING__EMPTY, /**< ECMA_OBJECT_CLASS_TYPEDARRAY needs special resolver */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + LIT_MAGIC_STRING_MODULE_UL, /**< magic string id of ECMA_OBJECT_CLASS_MODULE_NAMESPACE */ +#endif /* JERRY_MODULE_SYSTEM */ + + /* These objects are marked by Garbage Collector. */ + LIT_MAGIC_STRING_GENERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_GENERATOR */ + LIT_MAGIC_STRING_ASYNC_GENERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_ASYNC_GENERATOR */ + LIT_MAGIC_STRING_ARRAY_ITERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_ARRAY_ITERATOR */ + LIT_MAGIC_STRING_SET_ITERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_SET_ITERATOR */ + LIT_MAGIC_STRING_MAP_ITERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_MAP_ITERATOR */ +#if JERRY_BUILTIN_REGEXP + LIT_MAGIC_STRING_REGEXP_STRING_ITERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR */ +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_MODULE_SYSTEM + LIT_MAGIC_STRING_MODULE_UL, /**< magic string id of ECMA_OBJECT_CLASS_MODULE */ +#endif /* JERRY_MODULE_SYSTEM */ + LIT_MAGIC_STRING_PROMISE_UL, /**< magic string id of ECMA_OBJECT_CLASS_PROMISE */ + LIT_MAGIC_STRING_OBJECT_UL, /**< magic string id of ECMA_OBJECT_CLASS_PROMISE_CAPABILITY */ + LIT_MAGIC_STRING_OBJECT_UL, /**< magic string id of ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR */ +#if JERRY_BUILTIN_DATAVIEW + LIT_MAGIC_STRING_DATAVIEW_UL, /**< magic string id of ECMA_OBJECT_CLASS_DATAVIEW */ +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_CONTAINER + LIT_MAGIC_STRING__EMPTY, /**< magic string id of ECMA_OBJECT_CLASS_CONTAINER needs special resolver */ +#endif /* JERRY_BUILTIN_CONTAINER */ + + /* Normal objects. */ + LIT_MAGIC_STRING_BOOLEAN_UL, /**< magic string id of ECMA_OBJECT_CLASS_BOOLEAN */ + LIT_MAGIC_STRING_NUMBER_UL, /**< magic string id of ECMA_OBJECT_CLASS_NUMBER */ + LIT_MAGIC_STRING_ERROR_UL, /**< magic string id of ECMA_OBJECT_CLASS_ERROR */ + LIT_MAGIC_STRING_OBJECT_UL, /**< magic string id of ECMA_OBJECT_CLASS_INTERNAL_OBJECT */ +#if JERRY_PARSER + LIT_MAGIC_STRING_SCRIPT_UL, /**< magic string id of ECMA_OBJECT_CLASS_SCRIPT */ +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_DATE + LIT_MAGIC_STRING_DATE_UL, /**< magic string id of ECMA_OBJECT_CLASS_DATE */ +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP + LIT_MAGIC_STRING_REGEXP_UL, /**< magic string id of ECMA_OBJECT_CLASS_REGEXP */ +#endif /* JERRY_BUILTIN_REGEXP */ + LIT_MAGIC_STRING_SYMBOL_UL, /**< magic string id of ECMA_OBJECT_CLASS_SYMBOL */ + LIT_MAGIC_STRING_STRING_ITERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_STRING_ITERATOR */ +#if JERRY_BUILTIN_TYPEDARRAY + LIT_MAGIC_STRING_ARRAY_BUFFER_UL, /**< magic string id of ECMA_OBJECT_CLASS_ARRAY_BUFFER */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + LIT_MAGIC_STRING_SHARED_ARRAY_BUFFER_UL, /**< magic string id of ECMA_OBJECT_CLASS_SHAREDARRAY_BUFFER */ +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#if JERRY_BUILTIN_BIGINT + LIT_MAGIC_STRING_BIGINT_UL, /**< magic string id of ECMA_OBJECT_CLASS_BIGINT */ +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_WEAKREF + LIT_MAGIC_STRING_WEAKREF_UL, /**< magic string id of ECMA_OBJECT_CLASS_WEAKREF */ +#endif /* JERRY_BUILTIN_WEAKREF */ +}; + +JERRY_STATIC_ASSERT ((sizeof (ecma_class_object_magic_string_id) == ECMA_OBJECT_CLASS__MAX * sizeof (uint16_t)), + ecma_class_object_magic_string_id_must_have_object_class_max_elements); + +/** + * Get [[Class]] string of specified object + * + * @return class name magic string + */ +lit_magic_string_id_t +ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */ +{ + ecma_object_type_t type = ecma_get_object_type (obj_p); + + switch (type) + { + case ECMA_OBJECT_TYPE_ARRAY: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + return LIT_MAGIC_STRING_ARRAY_UL; + } + case ECMA_OBJECT_TYPE_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + switch (ext_object_p->u.cls.type) + { +#if JERRY_BUILTIN_TYPEDARRAY + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + return ecma_get_typedarray_magic_string_id ((ecma_typedarray_type_t) ext_object_p->u.cls.u1.typedarray_type); + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_CONTAINER + case ECMA_OBJECT_CLASS_CONTAINER: + { + return (lit_magic_string_id_t) ext_object_p->u.cls.u2.container_id; + } +#endif /* JERRY_BUILTIN_CONTAINER */ + default: + { + break; + } + } + + JERRY_ASSERT (ext_object_p->u.cls.type < ECMA_OBJECT_CLASS__MAX); + JERRY_ASSERT (ecma_class_object_magic_string_id[ext_object_p->u.cls.type] != LIT_MAGIC_STRING__EMPTY); + + return (lit_magic_string_id_t) ecma_class_object_magic_string_id[ext_object_p->u.cls.type]; + } + case ECMA_OBJECT_TYPE_FUNCTION: + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + return LIT_MAGIC_STRING_FUNCTION_UL; + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + if (!ecma_is_value_null (proxy_obj_p->target) && ecma_is_value_object (proxy_obj_p->target)) + { + ecma_object_t *target_obj_p = ecma_get_object_from_value (proxy_obj_p->target); + return ecma_object_get_class_name (target_obj_p); + } + return LIT_MAGIC_STRING_OBJECT_UL; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + switch (ext_obj_p->u.built_in.id) + { +#if JERRY_BUILTIN_MATH + case ECMA_BUILTIN_ID_MATH: + { + return LIT_MAGIC_STRING_MATH_UL; + } +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_REFLECT + case ECMA_BUILTIN_ID_REFLECT: + { + return LIT_MAGIC_STRING_REFLECT_UL; + } +#endif /* JERRY_BUILTIN_REFLECT */ + case ECMA_BUILTIN_ID_GENERATOR: + { + return LIT_MAGIC_STRING_GENERATOR_UL; + } + case ECMA_BUILTIN_ID_ASYNC_GENERATOR: + { + return LIT_MAGIC_STRING_ASYNC_GENERATOR_UL; + } +#if JERRY_BUILTIN_ATOMICS + case ECMA_BUILTIN_ID_ATOMICS: + { + return LIT_MAGIC_STRING_ATOMICS_U; + } +#endif /* JERRY_BUILTIN_ATOMICS */ + default: + { + break; + } + } + + JERRY_ASSERT (ecma_object_check_class_name_is_object (obj_p)); + return LIT_MAGIC_STRING_OBJECT_UL; + } + default: + { + JERRY_ASSERT (type == ECMA_OBJECT_TYPE_GENERAL || type == ECMA_OBJECT_TYPE_PROXY); + + return LIT_MAGIC_STRING_OBJECT_UL; + } + } +} /* ecma_object_get_class_name */ + +#if JERRY_BUILTIN_REGEXP +/** + * Checks if the given argument has [[RegExpMatcher]] internal slot + * + * @return true - if the given argument is a regexp + * false - otherwise + */ +bool +ecma_object_is_regexp_object (ecma_value_t arg) /**< argument */ +{ + return (ecma_is_value_object (arg) + && ecma_object_class_is (ecma_get_object_from_value (arg), ECMA_OBJECT_CLASS_REGEXP)); +} /* ecma_object_is_regexp_object */ +#endif /* JERRY_BUILTIN_REGEXP */ + +/** + * Object's IsConcatSpreadable operation, used for Array.prototype.concat + * It checks the argument's [Symbol.isConcatSpreadable] property value + * + * See also: + * ECMA-262 v6, 22.1.3.1.1; + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if the argument is concatSpreadable + * ECMA_VALUE_FALSE - otherwise + */ +ecma_value_t +ecma_op_is_concat_spreadable (ecma_value_t arg) /**< argument */ +{ + if (!ecma_is_value_object (arg)) + { + return ECMA_VALUE_FALSE; + } + + ecma_value_t spreadable = + ecma_op_object_get_by_symbol_id (ecma_get_object_from_value (arg), LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE); + + if (ECMA_IS_VALUE_ERROR (spreadable)) + { + return spreadable; + } + + if (!ecma_is_value_undefined (spreadable)) + { + const bool to_bool = ecma_op_to_boolean (spreadable); + ecma_free_value (spreadable); + return ecma_make_boolean_value (to_bool); + } + + return ecma_is_value_array (arg); +} /* ecma_op_is_concat_spreadable */ + +/** + * IsRegExp operation + * + * See also: + * ECMA-262 v6, 22.1.3.1.1; + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if the argument is regexp + * ECMA_VALUE_FALSE - otherwise + */ +ecma_value_t +ecma_op_is_regexp (ecma_value_t arg) /**< argument */ +{ + if (!ecma_is_value_object (arg)) + { + return ECMA_VALUE_FALSE; + } + + ecma_value_t is_regexp = ecma_op_object_get_by_symbol_id (ecma_get_object_from_value (arg), LIT_GLOBAL_SYMBOL_MATCH); + + if (ECMA_IS_VALUE_ERROR (is_regexp)) + { + return is_regexp; + } + + if (!ecma_is_value_undefined (is_regexp)) + { + const bool to_bool = ecma_op_to_boolean (is_regexp); + ecma_free_value (is_regexp); + return ecma_make_boolean_value (to_bool); + } + + return ecma_make_boolean_value (ecma_object_is_regexp_object (arg)); +} /* ecma_op_is_regexp */ + +/** + * SpeciesConstructor operation + * See also: + * ECMA-262 v6, 7.3.20; + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_species_constructor (ecma_object_t *this_value, /**< This Value */ + ecma_builtin_id_t default_constructor_id) /**< Builtin ID of default constructor */ +{ + ecma_object_t *default_constructor_p = ecma_builtin_get (default_constructor_id); + ecma_value_t constructor = ecma_op_object_get_by_magic_id (this_value, LIT_MAGIC_STRING_CONSTRUCTOR); + if (ECMA_IS_VALUE_ERROR (constructor)) + { + return constructor; + } + + if (ecma_is_value_undefined (constructor)) + { + ecma_ref_object (default_constructor_p); + return ecma_make_object_value (default_constructor_p); + } + + if (!ecma_is_value_object (constructor)) + { + ecma_free_value (constructor); + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_NOT_AN_OBJECT); + } + + ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor); + ecma_value_t species = ecma_op_object_get_by_symbol_id (ctor_object_p, LIT_GLOBAL_SYMBOL_SPECIES); + ecma_deref_object (ctor_object_p); + + if (ECMA_IS_VALUE_ERROR (species)) + { + return species; + } + + if (ecma_is_value_undefined (species) || ecma_is_value_null (species)) + { + ecma_ref_object (default_constructor_p); + return ecma_make_object_value (default_constructor_p); + } + + if (!ecma_is_constructor (species)) + { + ecma_free_value (species); + return ecma_raise_type_error (ECMA_ERR_SPECIES_MUST_BE_A_CONSTRUCTOR); + } + + return species; +} /* ecma_op_species_constructor */ + +/** + * 7.3.18 Abstract operation Invoke when property name is a magic string + * + * @return ecma_value result of the invoked function or raised error + * note: returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_invoke_by_symbol_id (ecma_value_t object, /**< Object value */ + lit_magic_string_id_t symbol_id, /**< Symbol ID */ + ecma_value_t *args_p, /**< Argument list */ + uint32_t args_len) /**< Argument list length */ +{ + ecma_string_t *symbol_p = ecma_op_get_global_symbol (symbol_id); + ecma_value_t ret_value = ecma_op_invoke (object, symbol_p, args_p, args_len); + ecma_deref_ecma_string (symbol_p); + + return ret_value; +} /* ecma_op_invoke_by_symbol_id */ + +/** + * 7.3.18 Abstract operation Invoke when property name is a magic string + * + * @return ecma_value result of the invoked function or raised error + * note: returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_invoke_by_magic_id (ecma_value_t object, /**< Object value */ + lit_magic_string_id_t magic_string_id, /**< Magic string ID */ + ecma_value_t *args_p, /**< Argument list */ + uint32_t args_len) /**< Argument list length */ +{ + return ecma_op_invoke (object, ecma_get_magic_string (magic_string_id), args_p, args_len); +} /* ecma_op_invoke_by_magic_id */ + +/** + * 7.3.18 Abstract operation Invoke + * + * @return ecma_value result of the invoked function or raised error + * note: returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_invoke (ecma_value_t object, /**< Object value */ + ecma_string_t *property_name_p, /**< Property name */ + ecma_value_t *args_p, /**< Argument list */ + uint32_t args_len) /**< Argument list length */ +{ + /* 3. */ + ecma_value_t object_value = ecma_op_to_object (object); + if (ECMA_IS_VALUE_ERROR (object_value)) + { + return object_value; + } + + ecma_object_t *object_p = ecma_get_object_from_value (object_value); + + ecma_value_t func = ecma_op_object_get_with_receiver (object_p, property_name_p, object); + + if (ECMA_IS_VALUE_ERROR (func)) + { + ecma_deref_object (object_p); + return func; + } + + /* 4. */ + ecma_value_t call_result = ecma_op_function_validated_call (func, object, args_p, args_len); + ecma_free_value (func); + + ecma_deref_object (object_p); + + return call_result; +} /* ecma_op_invoke */ + +/** + * Ordinary object [[GetPrototypeOf]] operation + * + * See also: + * ECMAScript v6, 9.1.1 + * + * @return the value of the [[Prototype]] internal slot of the given object. + */ +jmem_cpointer_t +ecma_op_ordinary_object_get_prototype_of (ecma_object_t *obj_p) /**< object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (obj_p)); + + return obj_p->u2.prototype_cp; +} /* ecma_op_ordinary_object_get_prototype_of */ + +/** + * Ordinary object [[SetPrototypeOf]] operation + * + * See also: + * ECMAScript v6, 9.1.2 + * + * @return ECMA_VALUE_FALSE - if the operation fails + * ECMA_VALUE_TRUE - otherwise + */ +ecma_value_t +ecma_op_ordinary_object_set_prototype_of (ecma_object_t *obj_p, /**< base object */ + ecma_value_t proto) /**< prototype object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (obj_p)); + + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (proto) || ecma_is_value_null (proto)); + + /* 3. */ + ecma_object_t *current_proto_p = ECMA_GET_POINTER (ecma_object_t, ecma_op_ordinary_object_get_prototype_of (obj_p)); + ecma_object_t *new_proto_p = ecma_is_value_null (proto) ? NULL : ecma_get_object_from_value (proto); + + /* 4. */ + if (new_proto_p == current_proto_p) + { + return ECMA_VALUE_TRUE; + } + + /* 2 - 5. */ + if (!ecma_op_ordinary_object_is_extensible (obj_p)) + { + return ECMA_VALUE_FALSE; + } + + /** + * When the prototype of a fast array changes, it is required to convert the + * array to a "normal" array. This ensures that all [[Get]]/[[Set]]/etc. + * calls works as expected. + */ + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_fast_array_convert_to_normal (obj_p); + } + + /* 6. */ + ecma_object_t *iter_p = new_proto_p; + + /* 7 - 8. */ + while (true) + { + /* 8.a */ + if (iter_p == NULL) + { + break; + } + + /* 8.b */ + if (obj_p == iter_p) + { + return ECMA_VALUE_FALSE; + } + + /* 8.c.i */ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (iter_p)) + { + /** + * Prevent setting 'Object.prototype.__proto__' + * to avoid circular referencing in the prototype chain. + */ + if (obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE)) + { + return ECMA_VALUE_FALSE; + } + + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 8.c.ii */ + iter_p = ECMA_GET_POINTER (ecma_object_t, ecma_op_ordinary_object_get_prototype_of (iter_p)); + } + + /* 9. */ + ECMA_SET_POINTER (obj_p->u2.prototype_cp, new_proto_p); + + /* 10. */ + return ECMA_VALUE_TRUE; +} /* ecma_op_ordinary_object_set_prototype_of */ + +/** + * [[IsExtensible]] operation for Ordinary object. + * + * See also: + * ECMAScript v6, 9.1.2 + * + * @return true - if object is extensible + * false - otherwise + */ +bool JERRY_ATTR_PURE +ecma_op_ordinary_object_is_extensible (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + + bool is_extensible = (object_p->type_flags_refs & ECMA_OBJECT_FLAG_EXTENSIBLE) != 0; + + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p) || is_extensible); + + return is_extensible; +} /* ecma_op_ordinary_object_is_extensible */ + +/** + * Set value of [[Extensible]] object's internal property. + * + * @return void + */ +void JERRY_ATTR_NOINLINE +ecma_op_ordinary_object_prevent_extensions (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + + if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (object_p))) + { + ecma_fast_array_convert_to_normal (object_p); + } + + object_p->type_flags_refs &= (ecma_object_descriptor_t) ~ECMA_OBJECT_FLAG_EXTENSIBLE; +} /* ecma_op_ordinary_object_prevent_extensions */ + +/** + * Checks whether an object (excluding prototypes) has a named property + * + * @return true - if property is found + * false - otherwise + */ +ecma_value_t +ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + + ecma_property_t property = + ecma_op_object_get_own_property (object_p, property_name_p, NULL, ECMA_PROPERTY_GET_NO_OPTIONS); + +#if JERRY_BUILTIN_TYPEDARRAY + if (JERRY_UNLIKELY (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW)) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + JERRY_ASSERT (ECMA_PROPERTY_IS_FOUND (property) || property == ECMA_PROPERTY_TYPE_NOT_FOUND + || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + + return ecma_make_boolean_value (ECMA_PROPERTY_IS_FOUND (property)); +} /* ecma_op_ordinary_object_has_own_property */ + +/** + * Checks whether an object (excluding prototypes) has a named property. Handles proxy objects too. + * + * @return true - if property is found + * false - otherwise + */ +ecma_value_t +ecma_op_object_has_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + ecma_property_descriptor_t prop_desc; + + ecma_value_t status = ecma_proxy_object_get_own_property_descriptor (object_p, property_name_p, &prop_desc); + + if (ecma_is_value_true (status)) + { + ecma_free_property_descriptor (&prop_desc); + } + + return status; + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ecma_op_ordinary_object_has_own_property (object_p, property_name_p); +} /* ecma_op_object_has_own_property */ + +#if JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER + +/** + * Set a weak reference from a container or WeakRefObject to a key object + */ +void +ecma_op_object_set_weak (ecma_object_t *object_p, /**< key object */ + ecma_object_t *target_p) /**< target object */ +{ + if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (object_p))) + { + ecma_fast_array_convert_to_normal (object_p); + } + + ecma_string_t *weak_refs_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_WEAK_REFS); + ecma_property_t *property_p = ecma_find_named_property (object_p, weak_refs_string_p); + ecma_collection_t *refs_p; + + if (property_p == NULL) + { + refs_p = ecma_new_collection (); + + ecma_property_value_t *value_p; + ECMA_CREATE_INTERNAL_PROPERTY (object_p, weak_refs_string_p, property_p, value_p); + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, refs_p); + } + else + { + refs_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, (ECMA_PROPERTY_VALUE_PTR (property_p)->value)); + } + + const ecma_value_t target_value = ecma_make_object_value ((ecma_object_t *) target_p); + for (uint32_t i = 0; i < refs_p->item_count; i++) + { + if (ecma_is_value_empty (refs_p->buffer_p[i])) + { + refs_p->buffer_p[i] = target_value; + return; + } + } + + ecma_collection_push_back (refs_p, target_value); +} /* ecma_op_object_set_weak */ + +/** + * Helper function to remove a weak reference to an object. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +void +ecma_op_object_unref_weak (ecma_object_t *object_p, /**< this argument */ + ecma_value_t ref_holder) /**< key argument */ +{ + ecma_string_t *weak_refs_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_WEAK_REFS); + + ecma_property_t *property_p = ecma_find_named_property (object_p, weak_refs_string_p); + JERRY_ASSERT (property_p != NULL); + + ecma_collection_t *refs_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, ECMA_PROPERTY_VALUE_PTR (property_p)->value); + ecma_value_t *buffer_p = refs_p->buffer_p; + + while (true) + { + if (*buffer_p == ref_holder) + { + *buffer_p = ECMA_VALUE_EMPTY; + return; + } + JERRY_ASSERT (buffer_p < refs_p->buffer_p + refs_p->item_count); + buffer_p++; + } +} /* ecma_op_object_unref_weak */ + +#endif /* JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER */ +/** + * Raise property redefinition error + * + * @return ECMA_VALUE_FALSE - if JERRY_PROP_SHOULD_THROW is not set + * raised TypeError - otherwise + */ +ecma_value_t +ecma_raise_property_redefinition (ecma_string_t *property_name_p, /**< property name */ + uint16_t flags) /**< property descriptor flags */ +{ + JERRY_UNUSED (property_name_p); + + return ECMA_REJECT_WITH_FORMAT (flags & JERRY_PROP_SHOULD_THROW, + "Cannot redefine property: %", + ecma_make_prop_name_value (property_name_p)); +} /* ecma_raise_property_redefinition */ + +/** + * Raise readonly assignment error + * + * @return ECMA_VALUE_FALSE - if is_throw is true + * raised TypeError - otherwise + */ +ecma_value_t +ecma_raise_readonly_assignment (ecma_string_t *property_name_p, /**< property name */ + bool is_throw) /**< is throw flag */ +{ + JERRY_UNUSED (property_name_p); + + return ECMA_REJECT_WITH_FORMAT (is_throw, + "Cannot assign to read only property '%'", + ecma_make_prop_name_value (property_name_p)); +} /* ecma_raise_readonly_assignment */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.h new file mode 100644 index 00000000..87e25388 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.h @@ -0,0 +1,147 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_OBJECTS_H +#define ECMA_OBJECTS_H + +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaobjectsinternalops ECMA objects' operations + * @{ + */ + +#if JERRY_ERROR_MESSAGES +/** + * Reject with TypeError depending on 'is_throw' with the given format + */ +#define ECMA_REJECT_WITH_FORMAT(is_throw, msg, ...) \ + ((is_throw) ? ecma_raise_standard_error_with_format (JERRY_ERROR_TYPE, (msg), __VA_ARGS__) : ECMA_VALUE_FALSE) + +/** + * Reject with TypeError depending on 'is_throw' with the given message + */ +#define ECMA_REJECT(is_throw, msg) ((is_throw) ? ecma_raise_type_error (msg) : ECMA_VALUE_FALSE) +#else /* !JERRY_ERROR_MESSAGES */ +/** + * Reject with TypeError depending on is_throw flags wit the given format + */ +#define ECMA_REJECT_WITH_FORMAT(is_throw, msg, ...) ECMA_REJECT ((is_throw), (msg)) + +/** + * Reject with TypeError depending on is_throw flags wit the given message + */ +#define ECMA_REJECT(is_throw, msg) ((is_throw) ? ecma_raise_type_error (ECMA_ERR_EMPTY) : ECMA_VALUE_FALSE) +#endif /* JERRY_ERROR_MESSAGES */ + +ecma_value_t ecma_raise_property_redefinition (ecma_string_t *property_name_p, uint16_t flags); +ecma_value_t ecma_raise_readonly_assignment (ecma_string_t *property_name_p, bool is_throw); + +ecma_property_t ecma_op_object_get_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + ecma_property_ref_t *property_ref_p, + uint32_t options); +ecma_value_t ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_has_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_has_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_find_own (ecma_value_t base_value, ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_find (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_find_by_index (ecma_object_t *object_p, ecma_length_t index); +ecma_value_t ecma_op_object_get (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t +ecma_op_object_get_with_receiver (ecma_object_t *object_p, ecma_string_t *property_name_p, ecma_value_t receiver); +ecma_value_t ecma_op_object_get_length (ecma_object_t *object_p, ecma_length_t *length_p); +ecma_value_t ecma_op_object_get_by_index (ecma_object_t *object_p, ecma_length_t index); +ecma_value_t ecma_op_object_get_by_magic_id (ecma_object_t *object_p, lit_magic_string_id_t property_id); +ecma_string_t *ecma_op_get_global_symbol (lit_magic_string_id_t property_id); +bool ecma_op_compare_string_to_global_symbol (ecma_string_t *string_p, lit_magic_string_id_t property_id); +ecma_value_t ecma_op_object_get_by_symbol_id (ecma_object_t *object_p, lit_magic_string_id_t property_id); +ecma_value_t ecma_op_get_method_by_symbol_id (ecma_value_t value, lit_magic_string_id_t symbol_id); +ecma_value_t ecma_op_get_method_by_magic_id (ecma_value_t value, lit_magic_string_id_t magic_id); +ecma_value_t ecma_op_object_put_with_receiver (ecma_object_t *object_p, + ecma_string_t *property_name_p, + ecma_value_t value, + ecma_value_t receiver, + bool is_throw); +ecma_value_t +ecma_op_object_put (ecma_object_t *object_p, ecma_string_t *property_name_p, ecma_value_t value, bool is_throw); +ecma_value_t ecma_op_object_put_with_receiver (ecma_object_t *object_p, + ecma_string_t *property_name_p, + ecma_value_t value, + ecma_value_t receiver, + bool is_throw); +ecma_value_t +ecma_op_object_put_by_index (ecma_object_t *object_p, ecma_length_t index, ecma_value_t value, bool is_throw); +ecma_value_t ecma_op_object_delete (ecma_object_t *obj_p, ecma_string_t *property_name_p, bool is_throw); +ecma_value_t ecma_op_object_delete_by_index (ecma_object_t *obj_p, ecma_length_t index, bool is_throw); +ecma_value_t ecma_op_object_default_value (ecma_object_t *obj_p, ecma_preferred_type_hint_t hint); +ecma_value_t ecma_op_object_define_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); +ecma_value_t ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, + ecma_string_t *property_name_p, + ecma_property_descriptor_t *prop_desc_p); +ecma_value_t ecma_op_object_has_instance (ecma_object_t *obj_p, ecma_value_t value); +ecma_object_t *ecma_op_object_get_prototype_of (ecma_object_t *obj_p); + +ecma_value_t ecma_op_object_is_prototype_of (ecma_object_t *base_p, ecma_object_t *target_p); +ecma_collection_t *ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, + ecma_enumerable_property_names_options_t option); +ecma_collection_t *ecma_op_object_own_property_keys (ecma_object_t *obj_p, jerry_property_filter_t filter); +ecma_collection_t *ecma_op_object_enumerate (ecma_object_t *obj_p); + +lit_magic_string_id_t ecma_object_get_class_name (ecma_object_t *obj_p); +#if JERRY_BUILTIN_REGEXP +bool ecma_object_is_regexp_object (ecma_value_t arg); +#endif /* JERRY_BUILTIN_REGEXP */ +ecma_value_t ecma_op_is_concat_spreadable (ecma_value_t arg); +ecma_value_t ecma_op_is_regexp (ecma_value_t arg); +ecma_value_t ecma_op_species_constructor (ecma_object_t *this_value, ecma_builtin_id_t default_constructor_id); +ecma_value_t ecma_op_invoke_by_symbol_id (ecma_value_t object, + lit_magic_string_id_t magic_string_id, + ecma_value_t *args_p, + uint32_t args_len); +#if JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER +void ecma_op_object_set_weak (ecma_object_t *object_p, ecma_object_t *target_p); +void ecma_op_object_unref_weak (ecma_object_t *object_p, ecma_value_t ref_holder); +#endif /* JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER */ +ecma_value_t +ecma_op_invoke (ecma_value_t object, ecma_string_t *property_name_p, ecma_value_t *args_p, uint32_t args_len); +ecma_value_t ecma_op_invoke_by_magic_id (ecma_value_t object, + lit_magic_string_id_t magic_string_id, + ecma_value_t *args_p, + uint32_t args_len); + +jmem_cpointer_t ecma_op_ordinary_object_get_prototype_of (ecma_object_t *obj_p); +ecma_value_t ecma_op_ordinary_object_set_prototype_of (ecma_object_t *base_p, ecma_value_t proto); +bool JERRY_ATTR_PURE ecma_op_ordinary_object_is_extensible (ecma_object_t *object_p); +void ecma_op_ordinary_object_prevent_extensions (ecma_object_t *object_p); + +#if JERRY_BUILTIN_PROXY +ecma_value_t ecma_op_get_own_property_descriptor (ecma_value_t target, + ecma_string_t *property_name_p, + ecma_property_descriptor_t *prop_desc_p); +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_OBJECTS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.cpp new file mode 100644 index 00000000..333aa202 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.cpp @@ -0,0 +1,1237 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-promise-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-boolean-object.h" +#include "ecma-builtin-handlers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-jobqueue.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmapromiseobject ECMA Promise object related routines + * @{ + */ + +/** + * Check if an object is promise. + * + * @return true - if the object is a promise. + * false - otherwise. + */ +bool +ecma_is_promise (ecma_object_t *obj_p) /**< points to object */ +{ + return ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_PROMISE); +} /* ecma_is_promise */ + +/** + * Get the result of the promise. + * + * @return ecma value of the promise result. + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_promise_get_result (ecma_object_t *obj_p) /**< points to promise object */ +{ + JERRY_ASSERT (ecma_is_promise (obj_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + return ecma_copy_value (ext_object_p->u.cls.u3.value); +} /* ecma_promise_get_result */ + +/** + * Set the PromiseResult of promise. + * + * @return void + */ +static inline void +ecma_promise_set_result (ecma_object_t *obj_p, /**< points to promise object */ + ecma_value_t result) /**< the result value */ +{ + JERRY_ASSERT (ecma_is_promise (obj_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + JERRY_ASSERT (ext_object_p->u.cls.u3.value == ECMA_VALUE_UNDEFINED); + + ext_object_p->u.cls.u3.value = result; +} /* ecma_promise_set_result */ + +/** + * Get the PromiseState of promise. + * + * @return the state's enum value + */ +uint8_t +ecma_promise_get_flags (ecma_object_t *obj_p) /**< points to promise object */ +{ + JERRY_ASSERT (ecma_is_promise (obj_p)); + + return ((ecma_extended_object_t *) obj_p)->u.cls.u1.promise_flags; +} /* ecma_promise_get_flags */ + +/** + * Set the PromiseState of promise. + * + * @return void + */ +static inline void +ecma_promise_set_state (ecma_object_t *obj_p, /**< points to promise object */ + bool is_fulfilled) /**< new flags */ +{ + JERRY_ASSERT (ecma_is_promise (obj_p)); + JERRY_ASSERT (ecma_promise_get_flags (obj_p) & ECMA_PROMISE_IS_PENDING); + + uint8_t flags_to_invert = + (is_fulfilled ? (ECMA_PROMISE_IS_PENDING | ECMA_PROMISE_IS_FULFILLED) : ECMA_PROMISE_IS_PENDING); + + ((ecma_extended_object_t *) obj_p)->u.cls.u1.promise_flags ^= flags_to_invert; +} /* ecma_promise_set_state */ + +/** + * Take a collection of Reactions and enqueue a new PromiseReactionJob for each Reaction. + * + * See also: ES2015 25.4.1.8 + */ +static void +ecma_promise_trigger_reactions (ecma_collection_t *reactions, /**< lists of reactions */ + ecma_value_t value, /**< value for resolve or reject */ + bool is_reject) /**< true if promise is rejected, false otherwise */ +{ + ecma_value_t *buffer_p = reactions->buffer_p; + ecma_value_t *buffer_end_p = buffer_p + reactions->item_count; + + while (buffer_p < buffer_end_p) + { + ecma_value_t object_with_tag = *buffer_p++; + ecma_object_t *object_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, object_with_tag); + ecma_value_t object = ecma_make_object_value (object_p); + + if (JMEM_CP_GET_THIRD_BIT_FROM_POINTER_TAG (object_with_tag)) + { + ecma_enqueue_promise_async_reaction_job (object, value, is_reject); + continue; + } + + if (!is_reject) + { + ecma_value_t handler = ECMA_VALUE_TRUE; + + if (JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (object_with_tag)) + { + handler = *buffer_p++; + } + + ecma_enqueue_promise_reaction_job (object, handler, value); + } + else if (JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (object_with_tag)) + { + buffer_p++; + } + + if (is_reject) + { + ecma_value_t handler = ECMA_VALUE_FALSE; + + if (JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (object_with_tag)) + { + handler = *buffer_p++; + } + + ecma_enqueue_promise_reaction_job (object, handler, value); + } + else if (JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (object_with_tag)) + { + buffer_p++; + } + } +} /* ecma_promise_trigger_reactions */ + +/** + * Checks whether a resolver is called before. + * + * @return true if it was called before, false otherwise + */ +static inline bool +ecma_is_resolver_already_called (ecma_object_t *promise_obj_p) /**< promise */ +{ + return (ecma_promise_get_flags (promise_obj_p) & ECMA_PROMISE_ALREADY_RESOLVED) != 0; +} /* ecma_is_resolver_already_called */ + +/** + * Reject a Promise with a reason. + * + * See also: ES2015 25.4.1.7 + */ +void +ecma_reject_promise (ecma_value_t promise, /**< promise */ + ecma_value_t reason) /**< reason for reject */ +{ + ecma_object_t *obj_p = ecma_get_object_from_value (promise); + + JERRY_ASSERT (ecma_promise_get_flags (obj_p) & ECMA_PROMISE_IS_PENDING); + + ecma_promise_set_state (obj_p, false); + ecma_promise_set_result (obj_p, ecma_copy_value_if_not_object (reason)); + ecma_promise_object_t *promise_p = (ecma_promise_object_t *) obj_p; + + /* GC can be triggered by ecma_new_collection so freeing the collection + first and creating a new one might cause a heap after use event. */ + ecma_collection_t *reactions = promise_p->reactions; + + /* Fulfill reactions will never be triggered. */ + ecma_promise_trigger_reactions (reactions, reason, true); + + promise_p->reactions = ecma_new_collection (); + + ecma_collection_destroy (reactions); +} /* ecma_reject_promise */ + +/** + * Fulfill a Promise with a value. + * + * See also: ES2015 25.4.1.4 + */ +void +ecma_fulfill_promise (ecma_value_t promise, /**< promise */ + ecma_value_t value) /**< fulfilled value */ +{ + ecma_object_t *obj_p = ecma_get_object_from_value (promise); + + JERRY_ASSERT (ecma_promise_get_flags (obj_p) & ECMA_PROMISE_IS_PENDING); + + if (promise == value) + { + ecma_raise_type_error (ECMA_ERR_PROMISE_RESOLVE_ITSELF); + ecma_value_t exception = jcontext_take_exception (); + ecma_reject_promise (promise, exception); + ecma_free_value (exception); + return; + } + + if (ecma_is_value_object (value)) + { + ecma_value_t then = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (value), LIT_MAGIC_STRING_THEN); + + if (ECMA_IS_VALUE_ERROR (then)) + { + then = jcontext_take_exception (); + ecma_reject_promise (promise, then); + ecma_free_value (then); + return; + } + + if (ecma_op_is_callable (then)) + { + ecma_enqueue_promise_resolve_thenable_job (promise, value, then); + ecma_free_value (then); + return; + } + + ecma_free_value (then); + } + + ecma_promise_set_state (obj_p, true); + ecma_promise_set_result (obj_p, ecma_copy_value_if_not_object (value)); + ecma_promise_object_t *promise_p = (ecma_promise_object_t *) obj_p; + + /* GC can be triggered by ecma_new_collection so freeing the collection + first and creating a new one might cause a heap after use event. */ + ecma_collection_t *reactions = promise_p->reactions; + + /* Reject reactions will never be triggered. */ + ecma_promise_trigger_reactions (reactions, value, false); + + promise_p->reactions = ecma_new_collection (); + + ecma_collection_destroy (reactions); +} /* ecma_fulfill_promise */ + +/** + * Reject a Promise with a reason. Sanity checks are performed before the reject. + * + * See also: ES2015 25.4.1.3.1 + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_reject_promise_with_checks (ecma_value_t promise, /**< promise */ + ecma_value_t reason) /**< reason for reject */ +{ + /* 1. */ + ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise); + JERRY_ASSERT (ecma_is_promise (promise_obj_p)); + + /* 3., 4. */ + if (JERRY_UNLIKELY (ecma_is_resolver_already_called (promise_obj_p))) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 5. */ + ((ecma_extended_object_t *) promise_obj_p)->u.cls.u1.promise_flags |= ECMA_PROMISE_ALREADY_RESOLVED; + + /* 6. */ + ecma_reject_promise (promise, reason); + return ECMA_VALUE_UNDEFINED; +} /* ecma_reject_promise_with_checks */ + +/** + * Fulfill a Promise with a value. Sanity checks are performed before the resolve. + * + * See also: ES2015 25.4.1.3.2 + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_fulfill_promise_with_checks (ecma_value_t promise, /**< promise */ + ecma_value_t value) /**< fulfilled value */ +{ + /* 1. */ + ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise); + JERRY_ASSERT (ecma_is_promise (promise_obj_p)); + + /* 3., 4. */ + if (JERRY_UNLIKELY (ecma_is_resolver_already_called (promise_obj_p))) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 5. */ + ((ecma_extended_object_t *) promise_obj_p)->u.cls.u1.promise_flags |= ECMA_PROMISE_ALREADY_RESOLVED; + + ecma_fulfill_promise (promise, value); + return ECMA_VALUE_UNDEFINED; +} /* ecma_fulfill_promise_with_checks */ + +/** + * Native handler for Promise Reject Function. + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_promise_reject_handler (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + ecma_promise_resolver_t *function_p = (ecma_promise_resolver_t *) function_obj_p; + + ecma_value_t reject_value = (args_count == 0) ? ECMA_VALUE_UNDEFINED : args_p[0]; + return ecma_reject_promise_with_checks (function_p->promise, reject_value); +} /* ecma_promise_reject_handler */ + +/** + * Native handler for Promise Resolve Function. + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_promise_resolve_handler (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + ecma_promise_resolver_t *function_p = (ecma_promise_resolver_t *) function_obj_p; + + ecma_value_t fulfilled_value = (args_count == 0) ? ECMA_VALUE_UNDEFINED : args_p[0]; + return ecma_fulfill_promise_with_checks (function_p->promise, fulfilled_value); +} /* ecma_promise_resolve_handler */ + +/** + * Helper function for PromiseCreateResolvingFunctions. + * + * See also: ES2015 25.4.1.3 2. - 7. + * + * @return pointer to the resolving function + */ +static ecma_object_t * +ecma_promise_create_resolving_function (ecma_object_t *promise_p, /**< Promise Object */ + ecma_native_handler_id_t id) /**< Callback handler */ +{ + ecma_object_t *func_obj_p = ecma_op_create_native_handler (id, sizeof (ecma_promise_resolver_t)); + + ecma_promise_resolver_t *resolver_p = (ecma_promise_resolver_t *) func_obj_p; + resolver_p->promise = ecma_make_object_value (promise_p); + + return func_obj_p; +} /* ecma_promise_create_resolving_function */ + +/** + * Helper function for running an executor. + * + * @return ecma value of the executor callable + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_promise_run_executor (ecma_object_t *promise_p, /**< Promise Object */ + ecma_value_t executor, /**< executor function */ + ecma_value_t this_value) /**< this value */ +{ + ecma_object_t *resolve_func_p, *reject_func_p; + resolve_func_p = ecma_promise_create_resolving_function (promise_p, ECMA_NATIVE_HANDLER_PROMISE_RESOLVE); + reject_func_p = ecma_promise_create_resolving_function (promise_p, ECMA_NATIVE_HANDLER_PROMISE_REJECT); + + ecma_value_t argv[] = { ecma_make_object_value (resolve_func_p), ecma_make_object_value (reject_func_p) }; + ecma_value_t result = ecma_op_function_call (ecma_get_object_from_value (executor), this_value, argv, 2); + ecma_deref_object (resolve_func_p); + ecma_deref_object (reject_func_p); + + return result; +} /* ecma_promise_run_executor */ + +/** + * Create a promise object. + * + * See also: ES2015 25.4.3.1 + * + * @return ecma value of the new promise object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function or ECMA_VALUE_EMPTY */ + ecma_value_t parent, /**< parent promise if available */ + ecma_object_t *new_target_p) /**< new.target value */ +{ + JERRY_UNUSED (parent); + + if (new_target_p == NULL) + { + new_target_p = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE); + } + + /* 3. */ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_PROMISE_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* Calling ecma_new_collection might trigger a GC call, so this + * allocation is performed before the object is constructed. */ + ecma_collection_t *reactions = ecma_new_collection (); + + ecma_object_t *object_p = ecma_create_object (proto_p, sizeof (ecma_promise_object_t), ECMA_OBJECT_TYPE_CLASS); + ecma_deref_object (proto_p); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_PROMISE; + /* 5 */ + ext_object_p->u.cls.u1.promise_flags = ECMA_PROMISE_IS_PENDING; + ext_object_p->u.cls.u3.value = ECMA_VALUE_UNDEFINED; + + /* 6-8. */ + ecma_promise_object_t *promise_object_p = (ecma_promise_object_t *) object_p; + promise_object_p->reactions = reactions; + + /* 9. */ + ecma_value_t completion = ECMA_VALUE_UNDEFINED; + + if (executor != ECMA_VALUE_EMPTY) + { + JERRY_ASSERT (ecma_op_is_callable (executor)); + + completion = ecma_promise_run_executor (object_p, executor, ECMA_VALUE_UNDEFINED); + } + + ecma_value_t status = ECMA_VALUE_EMPTY; + + if (ECMA_IS_VALUE_ERROR (completion)) + { + /* 10.a. */ + completion = jcontext_take_exception (); + ecma_reject_promise_with_checks (ecma_make_object_value (object_p), completion); + } + + ecma_free_value (completion); + + /* 10.b. */ + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_deref_object (object_p); + return status; + } + + /* 11. */ + ecma_free_value (status); + return ecma_make_object_value (object_p); +} /* ecma_op_create_promise_object */ + +/** + * Helper function for increase or decrease the remaining count. + * + * @return the current remaining count after increase or decrease. + */ +uint32_t +ecma_promise_remaining_inc_or_dec (ecma_value_t remaining, /**< the remaining count */ + bool is_inc) /**< whether to increase the count */ +{ + JERRY_ASSERT (ecma_is_value_object (remaining)); + + ecma_object_t *remaining_p = ecma_get_object_from_value (remaining); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) remaining_p; + + JERRY_ASSERT (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_NUMBER); + + JERRY_ASSERT (ecma_is_value_integer_number (ext_object_p->u.cls.u3.value)); + + uint32_t current = (uint32_t) ecma_get_integer_from_value (ext_object_p->u.cls.u3.value); + + if (is_inc) + { + current++; + } + else + { + current--; + } + ext_object_p->u.cls.u3.value = ecma_make_uint32_value (current); + + return current; +} /* ecma_promise_remaining_inc_or_dec */ + +/** + * Native handler for Promise.all and Promise.allSettled Resolve Element Function. + * + * See also: + * ES2015 25.4.4.1.2 + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_promise_all_or_all_settled_handler_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + ecma_value_t arg = args_count > 0 ? args_p[0] : ECMA_VALUE_UNDEFINED; + + ecma_promise_all_executor_t *executor_p = (ecma_promise_all_executor_t *) function_obj_p; + uint8_t promise_type = executor_p->header.u.built_in.u2.routine_flags; + + promise_type = (uint8_t) (promise_type >> ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT); + + /* 1 - 2. */ + if (executor_p->index == 0) + { + return ECMA_VALUE_UNDEFINED; + } + + if (promise_type == ECMA_PROMISE_ALL_RESOLVE || promise_type == ECMA_PROMISE_ANY_REJECT) + { + /* 8. */ + ecma_op_object_put_by_index (ecma_get_object_from_value (executor_p->values), + (uint32_t) (executor_p->index - 1), + arg, + false); + } + else + { + lit_magic_string_id_t status_property_val = LIT_MAGIC_STRING_REJECTED; + lit_magic_string_id_t data_propery_name = LIT_MAGIC_STRING_REASON; + + if (promise_type == ECMA_PROMISE_ALLSETTLED_RESOLVE) + { + status_property_val = LIT_MAGIC_STRING_FULFILLED; + data_propery_name = LIT_MAGIC_STRING_VALUE; + } + + ecma_object_t *obj_p = + ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_STATUS), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + prop_value_p->value = ecma_make_magic_string_value (status_property_val); + + prop_value_p = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (data_propery_name), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + prop_value_p->value = ecma_copy_value_if_not_object (arg); + + ecma_value_t obj_val = ecma_make_object_value (obj_p); + /* 12. */ + ecma_op_object_put_by_index (ecma_get_object_from_value (executor_p->values), + (uint32_t) (executor_p->index - 1), + obj_val, + false); + ecma_deref_object (obj_p); + } + /* 3. */ + executor_p->index = 0; + + /* 9-10. */ + ecma_value_t ret = ECMA_VALUE_UNDEFINED; + if (ecma_promise_remaining_inc_or_dec (executor_p->remaining_elements, false) == 0) + { + ecma_value_t capability = executor_p->capability; + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) ecma_get_object_from_value (capability); + if (promise_type == ECMA_PROMISE_ANY_REJECT) + { + ecma_value_t error_val = ecma_new_aggregate_error (executor_p->values, ECMA_VALUE_UNDEFINED); + ret = + ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &error_val, 1); + ecma_free_value (error_val); + } + else + { + ret = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), + ECMA_VALUE_UNDEFINED, + &executor_p->values, + 1); + } + } + + return ret; +} /* ecma_promise_all_or_all_settled_handler_cb */ + +/** + * GetCapabilitiesExecutor Functions + * + * Checks and sets a promiseCapability's resolve and reject properties. + * + * See also: ES11 25.6.1.5.1 + * + * @return ECMA_VALUE_UNDEFINED or TypeError + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_get_capabilities_executor_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + /* 1. */ + ecma_promise_capability_executor_t *executor_p = (ecma_promise_capability_executor_t *) function_obj_p; + + /* 2-3. */ + ecma_object_t *capability_obj_p = ecma_get_object_from_value (executor_p->capability); + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + + /* 4. */ + if (!ecma_is_value_undefined (capability_p->resolve)) + { + return ecma_raise_type_error (ECMA_ERR_RESOLVE_MUST_BE_UNDEFINED); + } + + /* 5. */ + if (!ecma_is_value_undefined (capability_p->reject)) + { + return ecma_raise_type_error (ECMA_ERR_REJECT_MUST_BE_UNDEFINED); + } + + /* 6. */ + capability_p->resolve = (args_count > 0) ? args_p[0] : ECMA_VALUE_UNDEFINED; + /* 7. */ + capability_p->reject = (args_count > 1) ? args_p[1] : ECMA_VALUE_UNDEFINED; + + /* 8. */ + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_get_capabilities_executor_cb */ + +/** + * Create a new PromiseCapability. + * + * See also: ES11 25.6.1.5 + * + * @return NULL - if the operation raises error + * new PromiseCapability object - otherwise + */ +ecma_object_t * +ecma_promise_new_capability (ecma_value_t constructor, /**< constructor function */ + ecma_value_t parent) /**< parent promise if available */ +{ + /* 1. */ + if (!ecma_is_constructor (constructor)) + { + ecma_raise_type_error (ECMA_ERR_INVALID_CAPABILITY); + return NULL; + } + + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); + + /* 3. */ + ecma_object_t *capability_obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), + sizeof (ecma_promise_capabality_t), + ECMA_OBJECT_TYPE_CLASS); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + capability_p->header.u.cls.type = ECMA_OBJECT_CLASS_PROMISE_CAPABILITY; + capability_p->header.u.cls.u3.promise = ECMA_VALUE_UNDEFINED; + capability_p->resolve = ECMA_VALUE_UNDEFINED; + capability_p->reject = ECMA_VALUE_UNDEFINED; + + /* 4-5. */ + ecma_object_t *executor_p = ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_CAPABILITY_EXECUTOR, + sizeof (ecma_promise_capability_executor_t)); + + /* 6. */ + ecma_promise_capability_executor_t *executor_func_p = (ecma_promise_capability_executor_t *) executor_p; + executor_func_p->capability = ecma_make_object_value (capability_obj_p); + + /* 7. */ + ecma_value_t executor = ecma_make_object_value (executor_p); + ecma_value_t promise; + + if (constructor_obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE)) + { + promise = ecma_op_create_promise_object (executor, parent, constructor_obj_p); + } + else + { + promise = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &executor, 1); + } + + ecma_deref_object (executor_p); + + if (ECMA_IS_VALUE_ERROR (promise)) + { + ecma_deref_object (capability_obj_p); + return NULL; + } + + /* 8. */ + if (!ecma_op_is_callable (capability_p->resolve)) + { + ecma_free_value (promise); + ecma_deref_object (capability_obj_p); + ecma_raise_type_error (ECMA_ERR_PARAMETER_RESOLVE_MUST_BE_CALLABLE); + return NULL; + } + + /* 9. */ + if (!ecma_op_is_callable (capability_p->reject)) + { + ecma_free_value (promise); + ecma_deref_object (capability_obj_p); + ecma_raise_type_error (ECMA_ERR_PARAMETER_REJECT_MUST_BE_CALLABLE); + return NULL; + } + + /* 10. */ + capability_p->header.u.cls.u3.promise = promise; + + ecma_free_value (promise); + + /* 11. */ + return capability_obj_p; +} /* ecma_promise_new_capability */ + +/** + * The common function for 'reject' and 'resolve'. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argument */ + ecma_value_t value, /**< rejected or resolved value */ + bool is_resolve) /**< the operation is resolve */ +{ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + if (is_resolve && ecma_is_value_object (value) && ecma_is_promise (ecma_get_object_from_value (value))) + { + ecma_object_t *object_p = ecma_get_object_from_value (value); + ecma_value_t constructor = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_CONSTRUCTOR); + + if (ECMA_IS_VALUE_ERROR (constructor)) + { + return constructor; + } + + /* The this_arg must be an object. */ + bool is_same_value = (constructor == this_arg); + ecma_free_value (constructor); + + if (is_same_value) + { + return ecma_copy_value (value); + } + } + + ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg, ECMA_VALUE_UNDEFINED); + + if (JERRY_UNLIKELY (capability_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + + ecma_value_t func = is_resolve ? capability_p->resolve : capability_p->reject; + + ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (func), ECMA_VALUE_UNDEFINED, &value, 1); + + if (ECMA_IS_VALUE_ERROR (call_ret)) + { + ecma_deref_object (capability_obj_p); + return call_ret; + } + + ecma_free_value (call_ret); + + ecma_value_t promise = ecma_copy_value (capability_p->header.u.cls.u3.promise); + ecma_deref_object (capability_obj_p); + + return promise; +} /* ecma_promise_reject_or_resolve */ + +/** + * The common function for ecma_builtin_promise_prototype_then + * and ecma_builtin_promise_prototype_catch. + * + * @return ecma value of a new promise object. + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_promise_then (ecma_value_t promise, /**< the promise which call 'then' */ + ecma_value_t on_fulfilled, /**< on_fulfilled function */ + ecma_value_t on_rejected) /**< on_rejected function */ +{ + if (!ecma_is_value_object (promise)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj = ecma_get_object_from_value (promise); + + if (!ecma_is_promise (obj)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_PROMISE); + } + + ecma_value_t species = ecma_op_species_constructor (obj, ECMA_BUILTIN_ID_PROMISE); + if (ECMA_IS_VALUE_ERROR (species)) + { + return species; + } + + ecma_object_t *result_capability_obj_p = ecma_promise_new_capability (species, promise); + ecma_free_value (species); + + if (JERRY_UNLIKELY (result_capability_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret = ecma_promise_perform_then (promise, on_fulfilled, on_rejected, result_capability_obj_p); + ecma_deref_object (result_capability_obj_p); + + return ret; +} /* ecma_promise_then */ + +/** + * Definition of valueThunk function + * + * See also: + * ES2020 25.6.5.3.1 step 8. + * + * @return ecma value + */ +ecma_value_t +ecma_value_thunk_helper_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + JERRY_UNUSED_2 (args_p, args_count); + + ecma_promise_value_thunk_t *value_thunk_obj_p = (ecma_promise_value_thunk_t *) function_obj_p; + + return ecma_copy_value (value_thunk_obj_p->value); +} /* ecma_value_thunk_helper_cb */ + +/** + * Definition of thrower function + * + * See also: + * ES2020 25.6.5.3.2 step 8. + * + * @return ecma value + */ +ecma_value_t +ecma_value_thunk_thrower_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + JERRY_UNUSED_2 (args_p, args_count); + + ecma_promise_value_thunk_t *value_thunk_obj_p = (ecma_promise_value_thunk_t *) function_obj_p; + + jcontext_raise_exception (ecma_copy_value (value_thunk_obj_p->value)); + + return ECMA_VALUE_ERROR; +} /* ecma_value_thunk_thrower_cb */ + +/** + * Helper function for Then Finally and Catch Finally common parts + * + * See also: + * ES2020 25.6.5.3.1 + * ES2020 25.6.5.3.2 + * + * @return ecma value + */ +static ecma_value_t +ecma_promise_then_catch_finally_helper (ecma_object_t *function_obj_p, /**< function object */ + ecma_native_handler_id_t id, /**< handler id */ + ecma_value_t arg) /**< callback function argument */ +{ + /* 2. */ + ecma_promise_finally_function_t *finally_func_obj = (ecma_promise_finally_function_t *) function_obj_p; + + /* 3. */ + JERRY_ASSERT (ecma_op_is_callable (finally_func_obj->on_finally)); + + /* 4. */ + ecma_value_t result = + ecma_op_function_call (ecma_get_object_from_value (finally_func_obj->on_finally), ECMA_VALUE_UNDEFINED, NULL, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + /* 6. */ + JERRY_ASSERT (ecma_is_constructor (finally_func_obj->constructor)); + + /* 7. */ + ecma_value_t promise = ecma_promise_reject_or_resolve (finally_func_obj->constructor, result, true); + + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (promise)) + { + return promise; + } + + /* 8. */ + ecma_object_t *value_thunk_func_p; + value_thunk_func_p = ecma_op_create_native_handler (id, sizeof (ecma_promise_value_thunk_t)); + + ecma_promise_value_thunk_t *value_thunk_func_obj = (ecma_promise_value_thunk_t *) value_thunk_func_p; + value_thunk_func_obj->value = ecma_copy_value_if_not_object (arg); + + /* 9. */ + ecma_value_t value_thunk = ecma_make_object_value (value_thunk_func_p); + ecma_value_t ret_value = ecma_op_invoke_by_magic_id (promise, LIT_MAGIC_STRING_THEN, &value_thunk, 1); + + ecma_free_value (promise); + ecma_deref_object (value_thunk_func_p); + + return ret_value; +} /* ecma_promise_then_catch_finally_helper */ + +/** + * Definition of Then Finally Function + * + * See also: + * ES2020 25.6.5.3.1 + * + * @return ecma value + */ +ecma_value_t +ecma_promise_then_finally_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + JERRY_UNUSED (args_count); + JERRY_ASSERT (args_count > 0); + + return ecma_promise_then_catch_finally_helper (function_obj_p, ECMA_NATIVE_HANDLER_VALUE_THUNK, args_p[0]); +} /* ecma_promise_then_finally_cb */ + +/** + * Definition of Catch Finally Function + * + * See also: + * ES2020 25.6.5.3.2 + * + * @return ecma value + */ +ecma_value_t +ecma_promise_catch_finally_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + JERRY_UNUSED (args_count); + JERRY_ASSERT (args_count > 0); + + return ecma_promise_then_catch_finally_helper (function_obj_p, ECMA_NATIVE_HANDLER_VALUE_THROWER, args_p[0]); +} /* ecma_promise_catch_finally_cb */ + +/** + * The common function for ecma_builtin_promise_prototype_finally + * + * @return ecma value of a new promise object. + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_promise_finally (ecma_value_t promise, /**< the promise which call 'finally' */ + ecma_value_t on_finally) /**< on_finally function */ +{ + /* 2. */ + if (!ecma_is_value_object (promise)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj = ecma_get_object_from_value (promise); + + /* 3. */ + ecma_value_t species = ecma_op_species_constructor (obj, ECMA_BUILTIN_ID_PROMISE); + + if (ECMA_IS_VALUE_ERROR (species)) + { + return species; + } + + /* 4. */ + JERRY_ASSERT (ecma_is_constructor (species)); + + /* 5. */ + if (!ecma_op_is_callable (on_finally)) + { + ecma_free_value (species); + ecma_value_t invoke_args[2] = { on_finally, on_finally }; + return ecma_op_invoke_by_magic_id (promise, LIT_MAGIC_STRING_THEN, invoke_args, 2); + } + + /* 6.a-b */ + ecma_object_t *then_finally_obj_p; + then_finally_obj_p = + ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_THEN_FINALLY, sizeof (ecma_promise_finally_function_t)); + + /* 6.c-d */ + ecma_promise_finally_function_t *then_finally_func_obj_p = (ecma_promise_finally_function_t *) then_finally_obj_p; + then_finally_func_obj_p->constructor = species; + then_finally_func_obj_p->on_finally = on_finally; + + /* 6.e-f */ + ecma_object_t *catch_finally_obj_p; + catch_finally_obj_p = + ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_CATCH_FINALLY, sizeof (ecma_promise_finally_function_t)); + + /* 6.g-h */ + ecma_promise_finally_function_t *catch_finally_func_obj = (ecma_promise_finally_function_t *) catch_finally_obj_p; + catch_finally_func_obj->constructor = species; + catch_finally_func_obj->on_finally = on_finally; + + ecma_deref_object (ecma_get_object_from_value (species)); + + /* 7. */ + ecma_value_t invoke_args[2] = { ecma_make_object_value (then_finally_obj_p), + ecma_make_object_value (catch_finally_obj_p) }; + + ecma_value_t ret_value = ecma_op_invoke_by_magic_id (promise, LIT_MAGIC_STRING_THEN, invoke_args, 2); + + ecma_deref_object (then_finally_obj_p); + ecma_deref_object (catch_finally_obj_p); + + return ret_value; +} /* ecma_promise_finally */ + +/** + * Resume the execution of an async function after the promise is resolved + */ +void +ecma_promise_async_then (ecma_value_t promise, /**< promise object */ + ecma_value_t executable_object) /**< executable object of the async function */ +{ + ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise); + uint16_t flags = ecma_promise_get_flags (promise_obj_p); + + if (flags & ECMA_PROMISE_IS_PENDING) + { + ecma_value_t executable_object_with_tag; + ECMA_SET_NON_NULL_POINTER_TAG (executable_object_with_tag, ecma_get_object_from_value (executable_object), 0); + ECMA_SET_THIRD_BIT_TO_POINTER_TAG (executable_object_with_tag); + + ecma_collection_push_back (((ecma_promise_object_t *) promise_obj_p)->reactions, executable_object_with_tag); + return; + } + + ecma_value_t value = ecma_promise_get_result (promise_obj_p); + ecma_enqueue_promise_async_reaction_job (executable_object, value, !(flags & ECMA_PROMISE_IS_FULFILLED)); + ecma_free_value (value); + +} /* ecma_promise_async_then */ + +/** + * Resolves the value and resume the execution of an async function after the resolve is completed + * + * @return ECMA_VALUE_UNDEFINED if not error is occurred, an error otherwise + */ +ecma_value_t +ecma_promise_async_await (ecma_extended_object_t *async_generator_object_p, /**< async generator function */ + ecma_value_t value) /**< value to be resolved (takes the reference) */ +{ + ecma_value_t promise = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE)); + ecma_value_t result = ecma_promise_reject_or_resolve (promise, value, true); + + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_promise_async_then (result, ecma_make_object_value ((ecma_object_t *) async_generator_object_p)); + ecma_free_value (result); + return ECMA_VALUE_UNDEFINED; +} /* ecma_promise_async_await */ + +/** + * Reject the promise if the value is error. + * + * See also: + * ES2015 25.4.1.1.1 + * + * @return ecma value of the new promise. + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_if_abrupt_reject_promise (ecma_value_t *value_p, /**< [in - out] completion value */ + ecma_object_t *capability_obj_p) /**< capability */ +{ + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + + if (!ECMA_IS_VALUE_ERROR (*value_p)) + { + return ECMA_VALUE_EMPTY; + } + + ecma_value_t reason = jcontext_take_exception (); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + ecma_value_t call_ret = + ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &reason, 1); + ecma_free_value (reason); + + if (ECMA_IS_VALUE_ERROR (call_ret)) + { + *value_p = call_ret; + return call_ret; + } + + ecma_free_value (call_ret); + *value_p = ecma_copy_value (capability_p->header.u.cls.u3.promise); + + return ECMA_VALUE_EMPTY; +} /* ecma_op_if_abrupt_reject_promise */ + +/** + * It performs the "then" operation on promiFulfilled + * and onRejected as its settlement actions. + * + * See also: 25.4.5.3.1 + * + * @return ecma value of the new promise object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_promise_perform_then (ecma_value_t promise, /**< the promise which call 'then' */ + ecma_value_t on_fulfilled, /**< on_fulfilled function */ + ecma_value_t on_rejected, /**< on_rejected function */ + ecma_object_t *result_capability_obj_p) /**< promise capability */ +{ + JERRY_ASSERT (ecma_object_class_is (result_capability_obj_p, ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) result_capability_obj_p; + + /* 3. boolean true indicates "indentity" */ + if (!ecma_op_is_callable (on_fulfilled)) + { + on_fulfilled = ECMA_VALUE_TRUE; + } + + /* 4. boolean false indicates "thrower" */ + if (!ecma_op_is_callable (on_rejected)) + { + on_rejected = ECMA_VALUE_FALSE; + } + + ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise); + ecma_promise_object_t *promise_p = (ecma_promise_object_t *) promise_obj_p; + + uint16_t flags = ecma_promise_get_flags (promise_obj_p); + + if (flags & ECMA_PROMISE_IS_PENDING) + { + /* 7. */ + /* [ capability, (on_fulfilled), (on_rejected) ] */ + ecma_value_t reaction_values[3]; + ecma_value_t *reactions_p = reaction_values + 1; + + uint8_t tag = 0; + + if (on_fulfilled != ECMA_VALUE_TRUE) + { + tag |= JMEM_FIRST_TAG_BIT_MASK; + *reactions_p++ = on_fulfilled; + } + + if (on_rejected != ECMA_VALUE_FALSE) + { + tag |= JMEM_SECOND_TAG_BIT_MASK; + *reactions_p++ = on_rejected; + } + + ECMA_SET_NON_NULL_POINTER_TAG (reaction_values[0], result_capability_obj_p, tag); + + uint32_t value_count = (uint32_t) (reactions_p - reaction_values); + ecma_collection_append (promise_p->reactions, reaction_values, value_count); + } + else if (flags & ECMA_PROMISE_IS_FULFILLED) + { + /* 8. */ + ecma_value_t value = ecma_promise_get_result (promise_obj_p); + ecma_enqueue_promise_reaction_job (ecma_make_object_value (result_capability_obj_p), on_fulfilled, value); + ecma_free_value (value); + } + else + { + /* 9. */ + ecma_value_t reason = ecma_promise_get_result (promise_obj_p); + ecma_enqueue_promise_reaction_job (ecma_make_object_value (result_capability_obj_p), on_rejected, reason); + ecma_free_value (reason); + } + + /* 10. */ + return ecma_copy_value (capability_p->header.u.cls.u3.promise); +} /* ecma_promise_perform_then */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.h new file mode 100644 index 00000000..8cfaa454 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.h @@ -0,0 +1,146 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_PROMISE_OBJECT_H +#define ECMA_PROMISE_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaarraybufferobject ECMA ArrayBuffer object related routines + * @{ + */ + +/** + * The PromiseState of promise object. + */ +typedef enum +{ + ECMA_PROMISE_IS_PENDING = (1 << 0), /**< pending state */ + ECMA_PROMISE_IS_FULFILLED = (1 << 1), /**< fulfilled state */ + ECMA_PROMISE_ALREADY_RESOLVED = (1 << 2), /**< already resolved */ +#if JERRY_PROMISE_CALLBACK + ECMA_PROMISE_UNHANDLED_REJECT = (1 << 3), /**< a Promise is rejected without a catch handler, + * related to ES11: 25.6.6 [[PromiseIsHandled]] */ +#endif /* JERRY_PROMISE_CALLBACK */ +} ecma_promise_flags_t; + +/** + * Description of a promise resolving function. + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object part */ + ecma_value_t promise; /**< [[Promise]] internal slot */ +} ecma_promise_resolver_t; + +/** + * Description of the promise object. + * It need more space than normal object to store builtin properties. + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object part */ + ecma_collection_t *reactions; /**< list of promise reactions */ +} ecma_promise_object_t; + +/** + * Description of the finally function object + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object part */ + ecma_value_t constructor; /**< [[Constructor]] internal slot */ + ecma_value_t on_finally; /**< [[OnFinally]] internal slot */ +} ecma_promise_finally_function_t; + +/** + * Description of the thunk function object + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object part */ + ecma_value_t value; /**< value thunk */ +} ecma_promise_value_thunk_t; + +/* The Promise reaction is a compressed structure, where each item can + * be a sequence of up to three ecma object values as seen below: + * + * [ Capability ][ Optional fullfilled callback ][ Optional rejected callback ] + * [ Async function callback ] + * + * The first member is an object, which lower bits specify the type of the reaction: + * bit 2 is not set: callback reactions + * The first two objects specify the resolve/reject functions of the promise + * returned by the `then` operation which can be used to chain event handlers. + * + * bit 0: has a fullfilled callback + * bit 1: has a rejected callback + * + * bit 2 is set: async function callback + */ + +bool ecma_is_promise (ecma_object_t *obj_p); +ecma_value_t ecma_op_create_promise_object (ecma_value_t executor, ecma_value_t parent, ecma_object_t *new_target_p); +uint8_t ecma_promise_get_flags (ecma_object_t *promise_p); +ecma_value_t ecma_promise_get_result (ecma_object_t *promise_p); +void ecma_reject_promise (ecma_value_t promise, ecma_value_t reason); +void ecma_fulfill_promise (ecma_value_t promise, ecma_value_t value); +ecma_value_t ecma_reject_promise_with_checks (ecma_value_t promise, ecma_value_t reason); +ecma_value_t ecma_fulfill_promise_with_checks (ecma_value_t promise, ecma_value_t value); +ecma_object_t *ecma_promise_new_capability (ecma_value_t constructor, ecma_value_t parent); +ecma_value_t ecma_promise_reject_or_resolve (ecma_value_t this_arg, ecma_value_t value, bool is_resolve); +ecma_value_t ecma_promise_then (ecma_value_t promise, ecma_value_t on_fulfilled, ecma_value_t on_rejected); + +ecma_value_t +ecma_value_thunk_helper_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); +ecma_value_t +ecma_value_thunk_thrower_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); +ecma_value_t +ecma_promise_then_finally_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); +ecma_value_t +ecma_promise_catch_finally_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); +ecma_value_t +ecma_promise_reject_handler (ecma_object_t *function_obj_p, const ecma_value_t argv[], const uint32_t args_count); +ecma_value_t +ecma_promise_resolve_handler (ecma_object_t *function_obj_p, const ecma_value_t argv[], const uint32_t args_count); +ecma_value_t ecma_promise_all_or_all_settled_handler_cb (ecma_object_t *function_obj_p, + const ecma_value_t args_p[], + const uint32_t args_count); +ecma_value_t ecma_op_get_capabilities_executor_cb (ecma_object_t *function_obj_p, + const ecma_value_t args_p[], + const uint32_t args_count); + +ecma_value_t ecma_promise_finally (ecma_value_t promise, ecma_value_t on_finally); +void ecma_promise_async_then (ecma_value_t promise, ecma_value_t executable_object); +ecma_value_t ecma_promise_async_await (ecma_extended_object_t *async_generator_object_p, ecma_value_t value); +ecma_value_t ecma_promise_run_executor (ecma_object_t *promise_p, ecma_value_t executor, ecma_value_t this_value); +ecma_value_t ecma_op_if_abrupt_reject_promise (ecma_value_t *value_p, ecma_object_t *capability_obj_p); + +uint32_t ecma_promise_remaining_inc_or_dec (ecma_value_t remaining, bool is_inc); + +ecma_value_t ecma_promise_perform_then (ecma_value_t promise, + ecma_value_t on_fulfilled, + ecma_value_t on_rejected, + ecma_object_t *result_capability_obj_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_PROMISE_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.cpp new file mode 100644 index 00000000..35ff2bf0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.cpp @@ -0,0 +1,1875 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-proxy-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-handlers.h" +#include "ecma-builtin-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaproxyobject ECMA Proxy object related routines + * @{ + */ + +#if JERRY_BUILTIN_PROXY +/** + * ProxyCreate operation for create a new proxy object + * + * See also: + * ES2015 9.5.15 + * ES11+: 9.5.14 ProxyCreate + * + * @return created Proxy object as an ecma-value - if success + * raised error - otherwise + */ +ecma_object_t * +ecma_proxy_create (ecma_value_t target, /**< proxy target */ + ecma_value_t handler, /**< proxy handler */ + uint32_t options) /**< ecma_proxy_flag_types_t option bits */ +{ + /* ES2015: 1, 3. */ + /* ES11+: 1 - 2. */ + if (!ecma_is_value_object (target) || !ecma_is_value_object (handler)) + { + ecma_raise_type_error (ECMA_ERR_CANNOT_CREATE_PROXY); + return NULL; + } + + /* ES2015: 5 - 6. */ + /* ES11+: 3 - 4. */ + /* A Proxy does not have [[Prototype]] value as per standard */ + ecma_object_t *obj_p = ecma_create_object (NULL, sizeof (ecma_proxy_object_t), ECMA_OBJECT_TYPE_PROXY); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + obj_p->u2.prototype_cp = (jmem_cpointer_t) options; + + /* ES2015: 7. */ + /* ES11+: 5. */ + if (ecma_op_is_callable (target)) + { + obj_p->u2.prototype_cp |= ECMA_PROXY_IS_CALLABLE; + + /* ES2015: 7.b. */ + /* ES11+: 5.b. */ + if (ecma_is_constructor (target)) + { + obj_p->u2.prototype_cp |= ECMA_PROXY_IS_CONSTRUCTABLE; + } + } + + /* ES2015: 8. */ + /* ES11+: 6. */ + proxy_obj_p->target = target; + + /* ES2015: 9. */ + /* ES11+: 7. */ + proxy_obj_p->handler = handler; + + /* ES2015: 10. */ + /* ES11+: 8 */ + return obj_p; +} /* ecma_proxy_create */ + +/** + * Definition of Proxy Revocation Function + * + * See also: + * ES2015 26.2.2.1.1 + * + * @return ECMA_VALUE_UNDEFINED + */ +ecma_value_t +ecma_proxy_revoke_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + JERRY_UNUSED_2 (args_p, args_count); + + /* 1. */ + ecma_revocable_proxy_object_t *rev_proxy_p = (ecma_revocable_proxy_object_t *) function_obj_p; + + /* 2. */ + if (ecma_is_value_null (rev_proxy_p->proxy)) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 4. */ + ecma_proxy_object_t *proxy_p = (ecma_proxy_object_t *) ecma_get_object_from_value (rev_proxy_p->proxy); + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY ((ecma_object_t *) proxy_p)); + + /* 3. */ + rev_proxy_p->proxy = ECMA_VALUE_NULL; + + /* 5. */ + proxy_p->target = ECMA_VALUE_NULL; + + /* 6. */ + proxy_p->handler = ECMA_VALUE_NULL; + + /* 7. */ + return ECMA_VALUE_UNDEFINED; +} /* ecma_proxy_revoke_cb */ + +/** + * Proxy.revocable operation for create a new revocable proxy object + * + * See also: + * ES2015 26.2.2.1 + * + * @return NULL - if the operation fails + * pointer to the newly created revocable proxy object - otherwise + */ +ecma_object_t * +ecma_proxy_create_revocable (ecma_value_t target, /**< target argument */ + ecma_value_t handler) /**< handler argument */ +{ + /* 1. */ + ecma_object_t *proxy_p = ecma_proxy_create (target, handler, 0); + + /* 2. */ + if (proxy_p == NULL) + { + return proxy_p; + } + + ecma_value_t proxy_value = ecma_make_object_value (proxy_p); + + /* 3. */ + ecma_object_t *func_obj_p; + func_obj_p = ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROXY_REVOKE, sizeof (ecma_revocable_proxy_object_t)); + + /* 4. */ + ecma_revocable_proxy_object_t *rev_proxy_p = (ecma_revocable_proxy_object_t *) func_obj_p; + rev_proxy_p->proxy = proxy_value; + + ecma_property_value_t *prop_value_p; + ecma_value_t revoker = ecma_make_object_value (func_obj_p); + + /* 5. */ + ecma_object_t *obj_p = + ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL); + + /* 6. */ + prop_value_p = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_PROXY), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + prop_value_p->value = proxy_value; + + /* 7. */ + prop_value_p = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_REVOKE), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + prop_value_p->value = revoker; + + ecma_deref_object (proxy_p); + ecma_deref_object (func_obj_p); + + /* 8. */ + return obj_p; +} /* ecma_proxy_create_revocable */ + +/** + * Internal find property operation for Proxy object + * + * Note: Returned value must be freed with ecma_free_value. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_NOT_FOUND - if the property is not found + * value of the property - otherwise + */ +ecma_value_t +ecma_proxy_object_find (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p) /**< property name */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + + ecma_value_t has_result = ecma_proxy_object_has (obj_p, prop_name_p); + + if (ECMA_IS_VALUE_ERROR (has_result)) + { + return has_result; + } + + if (ecma_is_value_false (has_result)) + { + return ECMA_VALUE_NOT_FOUND; + } + + return ecma_proxy_object_get (obj_p, prop_name_p, ecma_make_object_value (obj_p)); +} /* ecma_proxy_object_find */ + +/** + * Helper method for validate the proxy object + * + * @return proxy trap - if the validation is successful + * ECMA_VALUE_ERROR - otherwise + */ +static ecma_value_t +ecma_validate_proxy_object (ecma_value_t handler, /**< proxy handler */ + lit_magic_string_id_t magic_id) /**< routine magic id */ +{ + if (ecma_is_value_null (handler)) + { + return ecma_raise_type_error (ECMA_ERR_HANDLER_CANNOT_BE_NULL); + } + + JERRY_ASSERT (ecma_is_value_object (handler)); + + return ecma_op_get_method_by_magic_id (handler, magic_id); +} /* ecma_validate_proxy_object */ + +/* Interal operations */ + +/** + * The Proxy object [[GetPrototypeOf]] internal routine + * + * See also: + * ECMAScript v6, 9.5.1 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_NULL or valid object (prototype) otherwise + */ +ecma_value_t +ecma_proxy_object_get_prototype_of (ecma_object_t *obj_p) /**< proxy object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_GET_PROTOTYPE_OF_UL); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 7. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_builtin_object_object_get_prototype_of (target_obj_p); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + + /* 8. */ + ecma_value_t handler_proto = ecma_op_function_call (func_obj_p, handler, &target, 1); + + ecma_deref_object (func_obj_p); + + /* 9. */ + if (ECMA_IS_VALUE_ERROR (handler_proto)) + { + return handler_proto; + } + + /* 10. */ + if (!ecma_is_value_object (handler_proto) && !ecma_is_value_null (handler_proto)) + { + ecma_free_value (handler_proto); + + return ecma_raise_type_error (ECMA_ERR_TRAP_RETURNED_NEITHER_OBJECT_NOR_NULL); + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return handler_proto; + } + + /* 11. */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + /* 12. */ + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + ecma_free_value (handler_proto); + + return extensible_target; + } + + /* 13. */ + if (ecma_is_value_true (extensible_target)) + { + return handler_proto; + } + + /* 14. */ + ecma_value_t target_proto = ecma_builtin_object_object_get_prototype_of (target_obj_p); + + /* 15. */ + if (ECMA_IS_VALUE_ERROR (target_proto)) + { + return target_proto; + } + + ecma_value_t ret_value = handler_proto; + + /* 16. */ + if (handler_proto != target_proto) + { + ecma_free_value (handler_proto); + + ret_value = ecma_raise_type_error (ECMA_ERR_TARGET_NOT_EXTENSIBLE_NOT_RETURNED_ITS_PROTOTYPE); + } + + ecma_free_value (target_proto); + + /* 17. */ + return ret_value; +} /* ecma_proxy_object_get_prototype_of */ + +/** + * The Proxy object [[SetPrototypeOf]] internal routine + * + * See also: + * ECMAScript v6, 9.5.2 + * ECMAScript v11: 9.5.2 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the new prototype can be set for the given object + */ +ecma_value_t +ecma_proxy_object_set_prototype_of (ecma_object_t *obj_p, /**< proxy object */ + ecma_value_t proto) /**< new prototype object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (proto) || ecma_is_value_null (proto)); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL); + + /* 7.*/ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + if (ECMA_OBJECT_IS_PROXY (target_obj_p)) + { + ecma_value_t result = ecma_proxy_object_set_prototype_of (target_obj_p, proto); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_value_t result = ecma_op_ordinary_object_set_prototype_of (target_obj_p, proto); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t args[] = { target, proto }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* ES11: 9 */ + if (!boolean_trap_result) + { + return ecma_make_boolean_value (false); + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return ecma_make_boolean_value (boolean_trap_result); + } + + /* 11. */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + /* 12. */ + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + return extensible_target; + } + + /* 13. */ + if (ecma_is_value_true (extensible_target)) + { + return ecma_make_boolean_value (boolean_trap_result); + } + + /* 14. */ + ecma_value_t target_proto = ecma_builtin_object_object_get_prototype_of (target_obj_p); + + /* 15. */ + if (ECMA_IS_VALUE_ERROR (target_proto)) + { + return target_proto; + } + + ecma_value_t ret_value = ecma_make_boolean_value (boolean_trap_result); + + /* 16. */ + if (boolean_trap_result && (target_proto != proto)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TARGET_NOT_EXTENSIBLE_DIFFERENT_PROTOTYPE_RETURNED); + } + + ecma_free_value (target_proto); + + /* 17. */ + return ret_value; +} /* ecma_proxy_object_set_prototype_of */ + +/** + * The Proxy object [[isExtensible]] internal routine + * + * See also: + * ECMAScript v6, 9.5.3 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the object is extensible + */ +ecma_value_t +ecma_proxy_object_is_extensible (ecma_object_t *obj_p) /**< proxy object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_IS_EXTENSIBLE); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 7. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_builtin_object_object_is_extensible (target_obj_p); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + + /* 8. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, &target, 1); + + ecma_deref_object (func_obj_p); + + /* 9. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return ecma_make_boolean_value (boolean_trap_result); + } + + bool target_result; + + /* 10. */ + if (ECMA_OBJECT_IS_PROXY (target_obj_p)) + { + ecma_value_t proxy_is_ext = ecma_proxy_object_is_extensible (target_obj_p); + + if (ECMA_IS_VALUE_ERROR (proxy_is_ext)) + { + return proxy_is_ext; + } + + target_result = ecma_is_value_true (proxy_is_ext); + } + else + { + target_result = ecma_op_ordinary_object_is_extensible (target_obj_p); + } + + /* 12. */ + if (boolean_trap_result != target_result) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_EXTENSIBILITY); + } + + return ecma_make_boolean_value (boolean_trap_result); +} /* ecma_proxy_object_is_extensible */ + +/** + * The Proxy object [[PreventExtensions]] internal routine + * + * See also: + * ECMAScript v6, 9.5.4 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the object can be set as inextensible + */ +ecma_value_t +ecma_proxy_object_prevent_extensions (ecma_object_t *obj_p) /**< proxy object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 7. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t ret_value = ecma_builtin_object_object_prevent_extensions (target_obj_p); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + + ecma_deref_object (target_obj_p); + + return ECMA_VALUE_TRUE; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + + /* 8. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, &target, 1); + + ecma_deref_object (func_obj_p); + + /* 9. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* 10. */ + if (boolean_trap_result && !(obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION)) + { + ecma_value_t target_is_ext = ecma_builtin_object_object_is_extensible (target_obj_p); + + if (ECMA_IS_VALUE_ERROR (target_is_ext)) + { + return target_is_ext; + } + + if (ecma_is_value_true (target_is_ext)) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_INEXTENSIBILITY); + } + } + + /* 11. */ + return ecma_make_boolean_value (boolean_trap_result); +} /* ecma_proxy_object_prevent_extensions */ + +/** + * The Proxy object [[GetOwnProperty]] internal routine + * + * See also: + * ECMAScript v6, 9.5.5 + * + * Note: - Returned value is always a simple value so freeing it is unnecessary. + * - If the operation does not fail, freeing the filled property descriptor is the caller's responsibility + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE_FALSE} - depends on whether object has property with the given name + */ +ecma_value_t +ecma_proxy_object_get_own_property_descriptor (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p, /**< property name */ + ecma_property_descriptor_t *prop_desc_p) /**< [out] property + * descriptor */ +{ + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL); + + ecma_value_t target = proxy_obj_p->target; + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, prop_desc_p); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t args[] = { target, prop_value }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + /* 11. */ + if (!ecma_is_value_object (trap_result) && !ecma_is_value_undefined (trap_result)) + { + ecma_free_value (trap_result); + return ecma_raise_type_error (ECMA_ERR_TRAP_IS_NEITHER_AN_OBJECT_NOR_UNDEFINED); + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + if (ecma_is_value_undefined (trap_result)) + { + return ECMA_VALUE_FALSE; + } + + ecma_value_t result_val = ecma_op_to_property_descriptor (trap_result, prop_desc_p); + ecma_free_value (trap_result); + + if (ECMA_IS_VALUE_ERROR (result_val)) + { + return result_val; + } + + ecma_op_to_complete_property_descriptor (prop_desc_p); + return ECMA_VALUE_TRUE; + } + + /* 12. */ + ecma_property_descriptor_t target_desc; + ecma_value_t target_status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + /* 13. */ + if (ECMA_IS_VALUE_ERROR (target_status)) + { + ecma_free_value (trap_result); + return target_status; + } + + /* 14. */ + if (ecma_is_value_undefined (trap_result)) + { + /* .a */ + if (ecma_is_value_false (target_status)) + { + return ECMA_VALUE_FALSE; + } + /* .b */ + if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + { + ecma_free_property_descriptor (&target_desc); + return ecma_raise_type_error (ECMA_ERR_GIVEN_PROPERTY_IS_A_NON_CONFIGURABLE); + } + + /* .c */ + ecma_free_property_descriptor (&target_desc); + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + /* .d */ + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + return extensible_target; + } + + /* .e */ + JERRY_ASSERT (ecma_is_value_boolean (extensible_target)); + + /* .f */ + if (ecma_is_value_false (extensible_target)) + { + return ecma_raise_type_error (ECMA_ERR_TARGET_NOT_EXTENSIBLE); + } + + /* .g */ + return ECMA_VALUE_FALSE; + } + + /* 15. */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + /* 16. */ + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + if (ecma_is_value_true (target_status)) + { + ecma_free_property_descriptor (&target_desc); + } + ecma_free_value (trap_result); + return extensible_target; + } + + /* 17, 19 */ + ecma_value_t result_val = ecma_op_to_property_descriptor (trap_result, prop_desc_p); + + ecma_op_to_complete_property_descriptor (prop_desc_p); + ecma_free_value (trap_result); + + /* 18. */ + if (ECMA_IS_VALUE_ERROR (result_val)) + { + if (ecma_is_value_true (target_status)) + { + ecma_free_property_descriptor (&target_desc); + } + return result_val; + } + + /* 20. */ + bool is_extensible = ecma_is_value_true (extensible_target); + + bool is_valid = ecma_op_is_compatible_property_descriptor (prop_desc_p, + (ecma_is_value_true (target_status) ? &target_desc : NULL), + is_extensible); + + bool target_has_desc = ecma_is_value_true (target_status); + bool target_is_writable = (target_desc.flags & JERRY_PROP_IS_WRITABLE); + bool target_is_configurable = false; + + if (target_has_desc) + { + target_is_configurable = ((target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) != 0); + ecma_free_property_descriptor (&target_desc); + } + + /* 21. */ + if (!is_valid) + { + ecma_free_property_descriptor (prop_desc_p); + return ecma_raise_type_error (ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE); + } + + /* 22. */ + else if (!(prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + { + const uint16_t mask = (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE); + + if (!target_has_desc || target_is_configurable + || ((prop_desc_p->flags & mask) == JERRY_PROP_IS_WRITABLE_DEFINED && target_is_writable)) + { + ecma_free_property_descriptor (prop_desc_p); + return ecma_raise_type_error (ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE); + } + } + return ECMA_VALUE_TRUE; +} /* ecma_proxy_object_get_own_property_descriptor */ + +/** + * The Proxy object [[DefineOwnProperty]] internal routine + * + * See also: + * ECMAScript v6, 9.5.6 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE_FALSE} - depends on whether the property can be defined for the given object + */ +ecma_value_t +ecma_proxy_object_define_own_property (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p, /**< property name */ + const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_DEFINE_PROPERTY_UL); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_op_object_define_own_property (target_obj_p, prop_name_p, prop_desc_p); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + /* 9. */ + ecma_object_t *desc_obj = ecma_op_from_property_descriptor (prop_desc_p); + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t desc_obj_value = ecma_make_object_value (desc_obj); + ecma_value_t args[] = { target, prop_value, desc_obj_value }; + + /* 10. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 3); + + ecma_deref_object (func_obj_p); + ecma_deref_object (desc_obj); + + /* 11. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* 12. */ + if (!boolean_trap_result) + { + return ECMA_VALUE_FALSE; + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return ECMA_VALUE_TRUE; + } + + /* 13. */ + ecma_property_descriptor_t target_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + /* 14. */ + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + bool target_prop_found = ecma_is_value_true (status); + + /* 15. */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + bool is_target_ext = ecma_is_value_true (extensible_target); + + /* 16. */ + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + if (target_prop_found) + { + ecma_free_property_descriptor (&target_desc); + } + + return extensible_target; + } + + /* 17. */ + bool setting_config_false = + ((prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) && !(prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); + + /* 19. */ + if (!target_prop_found) + { + if (!is_target_ext) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_ADDING_PROPERTY_NON_EXTENSIBLE_TARGET); + } + + if (setting_config_false) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY); + } + } + /* 20. */ + else + { + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if (!ecma_op_is_compatible_property_descriptor (prop_desc_p, &target_desc, is_target_ext)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_ADD_PROPERTY_INCOMPATIBLE_OTHER_PROP); + } + else if (setting_config_false && (target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY); + } + /* ES11: 16.c */ + else if ((target_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) != 0 + && (prop_desc_p->flags & (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)) + == JERRY_PROP_IS_WRITABLE_DEFINED + && (target_desc.flags & (JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_CONFIGURABLE)) == JERRY_PROP_IS_WRITABLE) + + { + ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY); + } + + ecma_free_property_descriptor (&target_desc); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + } + + return ECMA_VALUE_TRUE; +} /* ecma_proxy_object_define_own_property */ + +/** + * The Proxy object [[HasProperty]] internal routine + * + * See also: + * ECMAScript v6, 9.5.7 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE_FALSE} - depends on whether the property is found + */ +ecma_value_t +ecma_proxy_object_has (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p) /**< property name */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_HAS); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_op_object_has_property (target_obj_p, prop_name_p); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t args[] = { target, prop_value }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* 11. */ + if (!boolean_trap_result && !(obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION)) + { + ecma_property_descriptor_t target_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + if (ecma_is_value_true (status)) + { + bool prop_is_configurable = target_desc.flags & JERRY_PROP_IS_CONFIGURABLE; + + ecma_free_property_descriptor (&target_desc); + + if (!prop_is_configurable) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_FALSISH_PROPERTY_NON_CONFIGURABLE); + } + + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + return extensible_target; + } + + if (ecma_is_value_false (extensible_target)) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_FALSISH_PROPERTY_TARGET_NOT_EXTENSIBLE); + } + } + } + + /* 12. */ + return ecma_make_boolean_value (boolean_trap_result); +} /* ecma_proxy_object_has */ + +/** + * The Proxy object [[Get]] internal routine + * + * See also: + * ECMAScript v6, 9.5.8 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * value of the given nameddata property or the result of the getter function call - otherwise + */ +ecma_value_t +ecma_proxy_object_get (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p, /**< property name */ + ecma_value_t receiver) /**< receiver to invoke getter function */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_GET); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_object_t *target_obj_p = ecma_get_object_from_value (proxy_obj_p->target); + ecma_value_t result = ecma_op_object_get_with_receiver (target_obj_p, prop_name_p, receiver); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t args[] = { proxy_obj_p->target, prop_value, receiver }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 3); + + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result) || (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION)) + { + return trap_result; + } + + /* 11. */ + ecma_property_descriptor_t target_desc; + ecma_value_t status = ecma_op_get_own_property_descriptor (proxy_obj_p->target, prop_name_p, &target_desc); + + /* 12. */ + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_free_value (trap_result); + return status; + } + + /* 13. */ + if (ecma_is_value_true (status)) + { + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if ((target_desc.flags & JERRY_PROP_IS_VALUE_DEFINED) && !(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) + && !(target_desc.flags & JERRY_PROP_IS_WRITABLE) && !ecma_op_same_value (trap_result, target_desc.value)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_INCORRECT_RETURN_PROXY_GET_TRAP); + } + else if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) + && (target_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + && target_desc.get_p == NULL && !ecma_is_value_undefined (trap_result)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_PROXY_PROPERTY_NOT_CONFIGURABLE_NOT_HAVE_GETTER); + } + + ecma_free_property_descriptor (&target_desc); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_free_value (trap_result); + + return ret_value; + } + } + + /* 14. */ + return trap_result; +} /* ecma_proxy_object_get */ + +/** + * The Proxy object [[Set]] internal routine + * + * See also: + * ECMAScript v6, 9.5.9 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the propety can be set to the given object + */ +ecma_value_t +ecma_proxy_object_set (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p, /**< property name */ + ecma_value_t value, /**< value to set */ + ecma_value_t receiver, /**< receiver to invoke setter function */ + bool is_strict) /**< indicate strict mode */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_SET); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_op_object_put_with_receiver (target_obj_p, prop_name_p, value, receiver, is_strict); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_name_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t args[] = { target, prop_name_value, value, receiver }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 4); + + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* 11. */ + if (!boolean_trap_result) + { + if (is_strict) + { + return ecma_raise_type_error (ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH); + } + + return ECMA_VALUE_FALSE; + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return ECMA_VALUE_TRUE; + } + + /* 12. */ + ecma_property_descriptor_t target_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + /* 13. */ + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + /* 14. */ + if (ecma_is_value_true (status)) + { + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if ((target_desc.flags & JERRY_PROP_IS_VALUE_DEFINED) && !(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) + && !(target_desc.flags & JERRY_PROP_IS_WRITABLE) && !ecma_op_same_value (value, target_desc.value)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_INCORRECT_RETURN_PROXY_SET_TRAP); + } + else if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) + && (target_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + && target_desc.set_p == NULL) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TARGET_PROPERTY_CONFIGURE_ACCESSOR_WITHOUT_SETTER); + } + + ecma_free_property_descriptor (&target_desc); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + } + + /* 15. */ + return ECMA_VALUE_TRUE; +} /* ecma_proxy_object_set */ + +/** + * The Proxy object [[Delete]] internal routine + * + * See also: + * ECMAScript v6, 9.5.10 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the propety can be deleted + */ +ecma_value_t +ecma_proxy_object_delete_property (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p, /**< property name */ + bool is_strict) /**< delete in strict mode? */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6.*/ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_DELETE_PROPERTY_UL); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_op_object_delete (target_obj_p, prop_name_p, is_strict); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_name_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t args[] = { target, prop_name_value }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* 11. */ + if (!boolean_trap_result) + { + return ECMA_VALUE_FALSE; + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return ECMA_VALUE_TRUE; + } + + /* 12. */ + ecma_property_descriptor_t target_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + /* 13. */ + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + /* 14. */ + if (ecma_is_value_false (status)) + { + return ECMA_VALUE_TRUE; + } + + ecma_value_t ret_value = ECMA_VALUE_TRUE; + + /* 15. */ + if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_PROPERTY_NON_CONFIGURABLE); + } + /* ES11: 13-14 */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + if (!ecma_is_value_true (extensible_target)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_TARGET_NOT_EXTENSIBLE); + } + + ecma_free_property_descriptor (&target_desc); + + /* 16. */ + return ret_value; +} /* ecma_proxy_object_delete_property */ + +/** + * Helper method for the Proxy object [[OwnPropertyKeys]] operation + * + * See also: + * ECMAScript v6, 9.5.12 steps 21. 23. + * + * @return ECMA_VALUE_ERROR - if a target key is not in the unchecked_result_keys collection + * ECMA_VALUE_EMPTY - otherwise + */ +static ecma_value_t +ecma_proxy_object_own_property_keys_helper (ecma_collection_t *target_collection, /**< target keys */ + ecma_collection_t *unchecked_result_keys, /**< unchecked keys */ + uint32_t *counter) /**< unchecked property counter */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + for (uint32_t i = 0; i < target_collection->item_count; i++) + { + ecma_string_t *current_prop_name = ecma_get_prop_name_from_value (target_collection->buffer_p[i]); + + ret_value = ECMA_VALUE_ERROR; + + for (uint32_t j = 0; j < unchecked_result_keys->item_count; j++) + { + if (ecma_is_value_empty (unchecked_result_keys->buffer_p[j])) + { + continue; + } + + ecma_string_t *unchecked_prop_name = ecma_get_prop_name_from_value (unchecked_result_keys->buffer_p[j]); + + if (ecma_compare_ecma_strings (current_prop_name, unchecked_prop_name)) + { + ecma_deref_ecma_string (unchecked_prop_name); + ret_value = ECMA_VALUE_EMPTY; + unchecked_result_keys->buffer_p[j] = ECMA_VALUE_EMPTY; + (*counter)++; + } + } + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + break; + } + } + + return ret_value; +} /* ecma_proxy_object_own_property_keys_helper */ + +/** + * Helper method for checking the invariants in the Proxy object [[OwnPropertyKeys]] operation + * + * See also: + * ECMAScript v6, 9.5.12 steps 20-25. + * + * @return true - if none of the invariants got violated + * false - otherwise + */ +static bool +ecma_proxy_check_invariants_for_own_prop_keys (ecma_collection_t *trap_result, + ecma_collection_t *target_non_configurable_keys, + ecma_collection_t *target_configurable_keys, + ecma_value_t extensible_target) +{ + /* 20. */ + ecma_collection_t *unchecked_result_keys = ecma_new_collection (); + + ecma_collection_append (unchecked_result_keys, trap_result->buffer_p, trap_result->item_count); + + for (uint32_t i = 0; i < unchecked_result_keys->item_count; i++) + { + ecma_string_t *unchecked_prop_name = ecma_get_prop_name_from_value (unchecked_result_keys->buffer_p[i]); + ecma_ref_ecma_string (unchecked_prop_name); + } + + bool check_ok = false; + uint32_t unchecked_prop_name_counter = 0; + + /* 21. */ + if (ECMA_IS_VALUE_ERROR (ecma_proxy_object_own_property_keys_helper (target_non_configurable_keys, + unchecked_result_keys, + &unchecked_prop_name_counter))) + { + ecma_raise_type_error (ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_NON_CONFIGURABLE_KEYS); + } + /* 22. */ + else if (ecma_is_value_true (extensible_target)) + { + check_ok = true; + } + /* 23. */ + else if (ECMA_IS_VALUE_ERROR (ecma_proxy_object_own_property_keys_helper (target_configurable_keys, + unchecked_result_keys, + &unchecked_prop_name_counter))) + { + ecma_raise_type_error (ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_CONFIGURABLE_KEYS); + } + /* 24. */ + else if (unchecked_result_keys->item_count != unchecked_prop_name_counter) + { + ecma_raise_type_error (ECMA_ERR_TRAP_EXTRA_KEYS_FOR_A_NON_EXTENSIBLE_TARGET); + } + /* 25. */ + else + { + check_ok = true; + } + + ecma_collection_free (unchecked_result_keys); + + return check_ok; +} /* ecma_proxy_check_invariants_for_own_prop_keys */ + +/** + * The Proxy object [[OwnPropertyKeys]] internal routine + * + * See also: + * ECMAScript v11, 9.5.11 + * + * Note: If the returned collection is not NULL, it must be freed with + * ecma_collection_free if it is no longer needed + * + * @return NULL - if the operation fails + * pointer to a newly allocated list of property names - otherwise + */ +ecma_collection_t * +ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE_RETURN (NULL); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_OWN_KEYS_UL); + + if (ECMA_IS_VALUE_ERROR (trap)) + { + return NULL; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 6. */ + if (ecma_is_value_undefined (trap)) + { + ecma_collection_t *result = ecma_op_object_own_property_keys (target_obj_p, JERRY_PROPERTY_FILTER_ALL); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + + /* 7. */ + ecma_value_t trap_result_array = ecma_op_function_call (func_obj_p, handler, &target, 1); + + ecma_deref_object (func_obj_p); + + if (ECMA_IS_VALUE_ERROR (trap_result_array)) + { + return NULL; + } + + /* 8. */ + ecma_collection_t *trap_result = ecma_op_create_list_from_array_like (trap_result_array, true); + + ecma_free_value (trap_result_array); + + if (trap_result == NULL || (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION)) + { + return trap_result; + } + + /* 9. */ + if (ecma_collection_check_duplicated_entries (trap_result)) + { + ecma_collection_free (trap_result); + ecma_raise_type_error (ECMA_ERR_TRAP_WITH_DUPLICATED_ENTRIES); + return NULL; + } + + /* 10. */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + ecma_collection_free (trap_result); + return NULL; + } + + /* 11. */ + ecma_collection_t *target_keys = ecma_op_object_own_property_keys (target_obj_p, JERRY_PROPERTY_FILTER_ALL); + + if (target_keys == NULL) + { + ecma_collection_free (trap_result); + return target_keys; + } + + /* 14. */ + ecma_collection_t *target_configurable_keys = ecma_new_collection (); + + /* 15. */ + ecma_collection_t *target_non_configurable_keys = ecma_new_collection (); + + ecma_collection_t *ret_value = NULL; + + /* 16. */ + for (uint32_t i = 0; i < target_keys->item_count; i++) + { + ecma_property_descriptor_t target_desc; + + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (target_keys->buffer_p[i]); + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_free (trap_result); + goto free_target_collections; + } + + ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); + + if (ecma_is_value_true (status) && !(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + { + ecma_collection_push_back (target_non_configurable_keys, prop_value); + } + else + { + ecma_collection_push_back (target_configurable_keys, prop_value); + } + + if (ecma_is_value_true (status)) + { + ecma_free_property_descriptor (&target_desc); + } + } + + /* 17. */ + if (ecma_is_value_true (extensible_target) && target_non_configurable_keys->item_count == 0) + { + ret_value = trap_result; + } + /* 18-22. */ + else if (ecma_proxy_check_invariants_for_own_prop_keys (trap_result, + target_non_configurable_keys, + target_configurable_keys, + extensible_target)) + { + ret_value = trap_result; + } + else + { + JERRY_ASSERT (ret_value == NULL); + ecma_collection_free (trap_result); + } + +free_target_collections: + ecma_collection_destroy (target_keys); + ecma_collection_free (target_configurable_keys); + ecma_collection_free (target_non_configurable_keys); + + /* 23. */ + return ret_value; +} /* ecma_proxy_object_own_property_keys */ + +/** + * The Proxy object [[Call]] internal routine + * + * See also: + * ECMAScript v6, 9.5.13 + * + * Note: Returned value must be freed with ecma_free_value. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * result of the function call - otherwise + */ +ecma_value_t +ecma_proxy_object_call (ecma_object_t *obj_p, /**< proxy object */ + ecma_value_t this_argument, /**< this argument to invoke the function */ + const ecma_value_t *args_p, /**< argument list */ + uint32_t argc) /**< number of arguments */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + + if (!ecma_op_proxy_object_is_callable (obj_p)) + { + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + } + + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5.*/ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_APPLY); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + + /* 7. */ + if (ecma_is_value_undefined (trap)) + { + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + ecma_value_t result = ecma_op_function_call (target_obj_p, this_argument, args_p, argc); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + /* 8. */ + ecma_value_t args_array = ecma_op_new_array_object_from_buffer (args_p, argc); + ecma_value_t value_array[] = { target, this_argument, args_array }; + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + /* 9. */ + ecma_value_t ret_value = ecma_op_function_call (func_obj_p, handler, value_array, 3); + ecma_deref_object (func_obj_p); + ecma_free_object (args_array); + + return ret_value; +} /* ecma_proxy_object_call */ + +/** + * The Proxy object [[Construct]] internal routine + * + * See also: + * ECMAScript v6, 9.5.14 + * + * Note: Returned value must be freed with ecma_free_value. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * result of the construct call - otherwise + */ +ecma_value_t +ecma_proxy_object_construct (ecma_object_t *obj_p, /**< proxy object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *args_p, /**< argument list */ + uint32_t argc) /**< number of arguments */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_CONSTRUCT); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 7. */ + if (ecma_is_value_undefined (trap)) + { + JERRY_ASSERT (ecma_object_is_constructor (target_obj_p)); + + ecma_value_t result = ecma_op_function_construct (target_obj_p, new_target_p, args_p, argc); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + /* 8. */ + ecma_value_t args_array = ecma_op_new_array_object_from_buffer (args_p, argc); + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t new_target_value = ecma_make_object_value (new_target_p); + ecma_value_t function_call_args[] = { target, args_array, new_target_value }; + + /* 9. */ + ecma_value_t new_obj = ecma_op_function_call (func_obj_p, handler, function_call_args, 3); + + ecma_free_object (args_array); + ecma_deref_object (func_obj_p); + + /* 10 .*/ + if (ECMA_IS_VALUE_ERROR (new_obj)) + { + return new_obj; + } + + /* 11. */ + if (!ecma_is_value_object (new_obj)) + { + ecma_free_value (new_obj); + + return ecma_raise_type_error (ECMA_ERR_TRAP_MUST_RETURN_WITH_AN_OBJECT); + } + + /* 12. */ + return new_obj; +} /* ecma_proxy_object_construct */ + +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.h new file mode 100644 index 00000000..82537bca --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.h @@ -0,0 +1,86 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_PROXY_OBJECT_H +#define ECMA_PROXY_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaproxyobject ECMA Proxy object related routines + * @{ + */ + +#if JERRY_BUILTIN_PROXY + +ecma_object_t *ecma_proxy_create (ecma_value_t target, ecma_value_t handler, uint32_t options); + +ecma_object_t *ecma_proxy_create_revocable (ecma_value_t target, ecma_value_t handler); + +ecma_value_t +ecma_proxy_revoke_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); + +ecma_value_t ecma_proxy_object_find (ecma_object_t *obj_p, ecma_string_t *prop_name_p); + +/* Interal operations */ + +ecma_value_t ecma_proxy_object_get_prototype_of (ecma_object_t *obj_p); + +ecma_value_t ecma_proxy_object_set_prototype_of (ecma_object_t *obj_p, ecma_value_t proto); + +ecma_value_t ecma_proxy_object_is_extensible (ecma_object_t *obj_p); + +ecma_value_t ecma_proxy_object_prevent_extensions (ecma_object_t *obj_p); + +ecma_value_t ecma_proxy_object_get_own_property_descriptor (ecma_object_t *obj_p, + ecma_string_t *prop_name_p, + ecma_property_descriptor_t *prop_desc_p); + +ecma_value_t ecma_proxy_object_define_own_property (ecma_object_t *obj_p, + ecma_string_t *prop_name_p, + const ecma_property_descriptor_t *prop_desc_p); + +ecma_value_t ecma_proxy_object_has (ecma_object_t *obj_p, ecma_string_t *prop_name_p); + +ecma_value_t ecma_proxy_object_get (ecma_object_t *obj_p, ecma_string_t *prop_name_p, ecma_value_t receiver); + +ecma_value_t ecma_proxy_object_set (ecma_object_t *obj_p, + ecma_string_t *prop_name_p, + ecma_value_t name, + ecma_value_t receiver, + bool is_strict); + +ecma_value_t ecma_proxy_object_delete_property (ecma_object_t *obj_p, ecma_string_t *prop_name_p, bool is_strict); + +ecma_collection_t *ecma_proxy_object_own_property_keys (ecma_object_t *obj_p); + +ecma_value_t +ecma_proxy_object_call (ecma_object_t *obj_p, ecma_value_t this_argument, const ecma_value_t *args_p, uint32_t argc); + +ecma_value_t ecma_proxy_object_construct (ecma_object_t *obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *args_p, + uint32_t argc); + +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_PROXY_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.cpp new file mode 100644 index 00000000..bc8f3866 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.cpp @@ -0,0 +1,404 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-reference.h" + +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lcache.h" +#include "ecma-lex-env.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup references ECMA-Reference + * @{ + */ + +/** + * Resolve syntactic reference. + * + * @return ECMA_OBJECT_POINTER_ERROR - if the operation fails + * pointer to lexical environment - if the reference's base is resolved successfully, + * NULL - otherwise. + */ +ecma_object_t * +ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical environment */ + ecma_string_t *name_p) /**< identifier's name */ +{ + JERRY_ASSERT (lex_env_p != NULL); + + while (true) + { + ecma_value_t has_binding = ecma_op_has_binding (lex_env_p, name_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (has_binding)) + { + return ECMA_OBJECT_POINTER_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (has_binding)) + { + return lex_env_p; + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + return NULL; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } +} /* ecma_op_resolve_reference_base */ + +/** + * Check if the passed lexical environment is a global lexical environment + * + * @return true - if the lexical environment is a global lexical environment + * false - otherwise + */ +static inline bool +ecma_op_is_global_environment (ecma_object_t *lex_env_p) /**< lexical environment */ +{ + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); +#if JERRY_BUILTIN_REALMS + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL + || (ecma_make_object_value (ecma_get_lex_env_binding_object (lex_env_p)) + == ((ecma_global_object_t *) ecma_builtin_get_global ())->this_binding)); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL + || ecma_get_lex_env_binding_object (lex_env_p) == ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + + return lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL; +} /* ecma_op_is_global_environment */ + +/** + * Perform GetThisEnvironment and GetSuperBase operations + * + * See also: ECMAScript v6, 8.1.1.3.5 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_UNDEFINED - if the home object is null + * value of the [[HomeObject]].[[Prototype]] internal slot - otherwise + */ +ecma_value_t +ecma_op_resolve_super_base (ecma_object_t *lex_env_p) /**< starting lexical environment */ +{ + while (true) + { + JERRY_ASSERT (lex_env_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && !ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + ecma_object_t *home_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u1.home_object_cp); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (home_p)) + { + return ecma_proxy_object_get_prototype_of (home_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (home_p); + + if (proto_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_NULL; + } + + ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + ecma_ref_object (proto_p); + + return ecma_make_object_value (proto_p); + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_resolve_super_base */ + +/** + * Helper method for HasBindig operation + * + * See also: + * ECMA-262 v6, 8.1.1.2.1 steps 7-9; + * + * @return ECMA_VALUE_TRUE - if the property is unscopable + * ECMA_VALUE_FALSE - if a the property is not unscopable + * ECMA_VALUE_ERROR - otherwise + */ +static ecma_value_t +ecma_op_is_prop_unscopable (ecma_object_t *binding_obj_p, /**< binding object */ + ecma_string_t *prop_name_p) /**< property's name */ +{ + ecma_value_t unscopables = ecma_op_object_get_by_symbol_id (binding_obj_p, LIT_GLOBAL_SYMBOL_UNSCOPABLES); + + if (ECMA_IS_VALUE_ERROR (unscopables)) + { + return unscopables; + } + + if (ecma_is_value_object (unscopables)) + { + ecma_object_t *unscopables_obj_p = ecma_get_object_from_value (unscopables); + ecma_value_t get_unscopables_value = ecma_op_object_get (unscopables_obj_p, prop_name_p); + ecma_deref_object (unscopables_obj_p); + + if (ECMA_IS_VALUE_ERROR (get_unscopables_value)) + { + return get_unscopables_value; + } + + bool is_blocked = ecma_op_to_boolean (get_unscopables_value); + + ecma_free_value (get_unscopables_value); + + return ecma_make_boolean_value (is_blocked); + } + + ecma_free_value (unscopables); + + return ECMA_VALUE_FALSE; +} /* ecma_op_is_prop_unscopable */ + +/** + * Helper method for HasBindig operation + * + * See also: + * ECMA-262 v6, 8.1.1.2.1 steps 7-9; + * + * @return ECMA_VALUE_TRUE - if the property is unscopable + * ECMA_VALUE_FALSE - if a the property is not unscopable + * ECMA_VALUE_ERROR - otherwise + */ + +/** + * Resolve value corresponding to the given object environment reference. + * + * Note: the steps are already include the HasBindig operation steps + * + * See also: + * ECMA-262 v6, 8.1.1.2.1 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_NOT_FOUND - if the binding not exists or blocked via @@unscopables + * result of the binding - otherwise + */ +ecma_value_t +ecma_op_object_bound_environment_resolve_reference_value (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p) /**< variable name */ +{ + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + ecma_value_t found_binding; + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (binding_obj_p)) + { + found_binding = ecma_proxy_object_has (binding_obj_p, name_p); + + if (!ecma_is_value_true (found_binding)) + { + return ECMA_IS_VALUE_ERROR (found_binding) ? found_binding : ECMA_VALUE_NOT_FOUND; + } + } + else + { +#endif /* JERRY_BUILTIN_PROXY */ + found_binding = ecma_op_object_find (binding_obj_p, name_p); + + if (ECMA_IS_VALUE_ERROR (found_binding) || !ecma_is_value_found (found_binding)) + { + return found_binding; + } + + if (JERRY_LIKELY (ecma_op_is_global_environment (lex_env_p))) + { + return found_binding; + } +#if JERRY_BUILTIN_PROXY + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t blocked = ecma_op_is_prop_unscopable (binding_obj_p, name_p); + + if (ecma_is_value_false (blocked)) + { +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (binding_obj_p)) + { + return ecma_proxy_object_get (binding_obj_p, name_p, ecma_make_object_value (binding_obj_p)); + } +#endif /* JERRY_BUILTIN_PROXY */ + return found_binding; + } + +#if JERRY_BUILTIN_PROXY + if (!ECMA_OBJECT_IS_PROXY (binding_obj_p)) + { + ecma_free_value (found_binding); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ECMA_IS_VALUE_ERROR (blocked) ? blocked : ECMA_VALUE_NOT_FOUND; +} /* ecma_op_object_bound_environment_resolve_reference_value */ + +/** + * Resolve value corresponding to reference. + * + * @return value of the reference + */ +ecma_value_t +ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */ + ecma_string_t *name_p) /**< identifier's name */ +{ + JERRY_ASSERT (lex_env_p != NULL); + + while (true) + { + switch (ecma_get_lex_env_type (lex_env_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p == NULL) + { + break; + } + + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + return ecma_fast_copy_value (property_value_p->value); + } + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { +#if JERRY_MODULE_SYSTEM + if (ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p == NULL) + { + break; + } + + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + property_value_p = ecma_get_property_value_from_named_reference (property_value_p); + } + + if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + return ecma_fast_copy_value (property_value_p->value); + } +#endif /* JERRY_MODULE_SYSTEM */ + break; + } + default: + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + if (ecma_op_is_global_environment (lex_env_p)) + { +#if JERRY_LCACHE + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + ecma_property_t *property_p = ecma_lcache_lookup (binding_obj_p, name_p); + + if (property_p != NULL) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (*property_p & ECMA_PROPERTY_FLAG_DATA) + { + return ecma_fast_copy_value (prop_value_p->value); + } + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (prop_value_p); + + if (get_set_pair_p->getter_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); + + ecma_value_t base_value = ecma_make_object_value (binding_obj_p); + return ecma_op_function_call (getter_p, base_value, NULL, 0); + } +#endif /* JERRY_LCACHE */ + } + + ecma_value_t result = ecma_op_object_bound_environment_resolve_reference_value (lex_env_p, name_p); + + if (ecma_is_value_found (result)) + { + /* Note: the result may contains ECMA_VALUE_ERROR */ + return result; + } + break; + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + +#if JERRY_ERROR_MESSAGES + ecma_value_t name_val = ecma_make_string_value (name_p); + ecma_value_t error_value = + ecma_raise_standard_error_with_format (JERRY_ERROR_REFERENCE, "% is not defined", name_val); +#else /* JERRY_ERROR_MESSAGES */ + ecma_value_t error_value = ecma_raise_reference_error (ECMA_ERR_EMPTY); +#endif /* !JERRY_ERROR_MESSAGES */ + return error_value; +} /* ecma_op_resolve_reference_value */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.h new file mode 100644 index 00000000..e1d4ae79 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.h @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_REFERENCE_H +#define ECMA_REFERENCE_H + +#include "ecma-globals.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup references ECMA-Reference + * @{ + */ + +ecma_object_t *ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, ecma_string_t *name_p); +ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, ecma_string_t *name_p); +ecma_value_t ecma_op_object_bound_environment_resolve_reference_value (ecma_object_t *lex_env_p, ecma_string_t *name_p); +ecma_value_t ecma_op_resolve_super_base (ecma_object_t *lex_env_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_REFERENCE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.cpp new file mode 100644 index 00000000..29fc9893 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.cpp @@ -0,0 +1,3219 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-regexp-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt-libc-includes.h" +#include "lit-char-helpers.h" +#include "re-compiler.h" + +#if JERRY_BUILTIN_REGEXP + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaregexpobject ECMA RegExp object related routines + * @{ + */ + +/** + * Index of the global capturing group + */ +#define RE_GLOBAL_CAPTURE 0 + +/** + * Parse RegExp flags (global, ignoreCase, multiline) + * + * See also: ECMA-262 v5, 15.10.4.1 + * + * @return empty ecma value - if parsed successfully + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_regexp_parse_flags (ecma_string_t *flags_str_p, /**< Input string with flags */ + uint16_t *flags_p) /**< [out] parsed flag bits */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + uint16_t result_flags = RE_FLAG_EMPTY; + + ECMA_STRING_TO_UTF8_STRING (flags_str_p, flags_start_p, flags_start_size); + + const lit_utf8_byte_t *flags_str_curr_p = flags_start_p; + const lit_utf8_byte_t *flags_str_end_p = flags_start_p + flags_start_size; + + while (flags_str_curr_p < flags_str_end_p) + { + ecma_regexp_flags_t flag; + switch (*flags_str_curr_p++) + { + case 'g': + { + flag = RE_FLAG_GLOBAL; + break; + } + case 'i': + { + flag = RE_FLAG_IGNORE_CASE; + break; + } + case 'm': + { + flag = RE_FLAG_MULTILINE; + break; + } + case 'y': + { + flag = RE_FLAG_STICKY; + break; + } + case 'u': + { + flag = RE_FLAG_UNICODE; + break; + } + case 's': + { + flag = RE_FLAG_DOTALL; + break; + } + default: + { + flag = RE_FLAG_EMPTY; + break; + } + } + + if (flag == RE_FLAG_EMPTY || (result_flags & flag) != 0) + { + ret_value = ecma_raise_syntax_error (ECMA_ERR_INVALID_REGEXP_FLAGS); + break; + } + + result_flags = (uint16_t) (result_flags | flag); + } + + ECMA_FINALIZE_UTF8_STRING (flags_start_p, flags_start_size); + + *flags_p = result_flags; + return ret_value; +} /* ecma_regexp_parse_flags */ + +/** + * RegExpAlloc method + * + * See also: ECMA-262 v5, 15.10.4.1 + * ECMA-262 v6, 21.2.3.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return ecma_object_t + */ +ecma_object_t * +ecma_op_regexp_alloc (ecma_object_t *ctr_obj_p) /**< constructor object pointer */ +{ + if (ctr_obj_p == NULL) + { + ctr_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP); + } + + ecma_object_t *proto_obj_p = ecma_op_get_prototype_from_constructor (ctr_obj_p, ECMA_BUILTIN_ID_REGEXP_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_obj_p == NULL)) + { + return proto_obj_p; + } + + ecma_object_t *new_object_p = + ecma_create_object (proto_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_deref_object (proto_obj_p); + + ecma_extended_object_t *regexp_obj_p = (ecma_extended_object_t *) new_object_p; + + /* Class id will be initialized after the bytecode is compiled. */ + regexp_obj_p->u.cls.type = ECMA_OBJECT_CLASS__MAX; + + ecma_value_t status = ecma_builtin_helper_def_prop (new_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + ECMA_PROPERTY_FLAG_WRITABLE | JERRY_PROP_SHOULD_THROW); + + JERRY_ASSERT (ecma_is_value_true (status)); + + return new_object_p; +} /* ecma_op_regexp_alloc */ + +/** + * Helper method for initializing an aready existing RegExp object. + */ +static inline void +ecma_op_regexp_initialize (ecma_object_t *regexp_obj_p, /**< RegExp object */ + const re_compiled_code_t *bc_p) /**< bytecode */ +{ + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) regexp_obj_p; + ext_obj_p->u.cls.type = ECMA_OBJECT_CLASS_REGEXP; + ECMA_SET_INTERNAL_VALUE_POINTER (ext_obj_p->u.cls.u3.value, bc_p); +} /* ecma_op_regexp_initialize */ + +/** + * Method for creating a RegExp object from pattern. + * + * Note: + * Allocation have to happen before invoking this function using ecma_op_regexp_alloc. + * + * @return ecma_value_t + */ +ecma_value_t +ecma_op_create_regexp_from_pattern (ecma_object_t *regexp_obj_p, /**< RegExp object */ + ecma_value_t pattern_value, /**< pattern */ + ecma_value_t flags_value) /**< flags */ +{ + ecma_string_t *pattern_str_p = ecma_regexp_read_pattern_str_helper (pattern_value); + uint16_t flags = 0; + + if (JERRY_UNLIKELY (pattern_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + if (!ecma_is_value_undefined (flags_value)) + { + ecma_string_t *flags_str_p = ecma_op_to_string (flags_value); + + if (JERRY_UNLIKELY (flags_str_p == NULL)) + { + ecma_deref_ecma_string (pattern_str_p); + return ECMA_VALUE_ERROR; + } + + ecma_value_t parse_flags_value = ecma_regexp_parse_flags (flags_str_p, &flags); + ecma_deref_ecma_string (flags_str_p); + + if (ECMA_IS_VALUE_ERROR (parse_flags_value)) + { + ecma_deref_ecma_string (pattern_str_p); + return parse_flags_value; + } + + JERRY_ASSERT (ecma_is_value_empty (parse_flags_value)); + } + + re_compiled_code_t *bc_p = re_compile_bytecode (pattern_str_p, flags); + + if (JERRY_UNLIKELY (bc_p == NULL)) + { + ecma_deref_ecma_string (pattern_str_p); + return ECMA_VALUE_ERROR; + } + + ecma_op_regexp_initialize (regexp_obj_p, bc_p); + ecma_deref_ecma_string (pattern_str_p); + + return ecma_make_object_value (regexp_obj_p); +} /* ecma_op_create_regexp_from_pattern */ + +/** + * Method for creating a RegExp object from bytecode. + * + * Note: + * Allocation have to happen before invoking this function using ecma_op_regexp_alloc. + * + * @return ecma_value_t + */ +ecma_value_t +ecma_op_create_regexp_from_bytecode (ecma_object_t *regexp_obj_p, /**< RegExp object */ + re_compiled_code_t *bc_p) /**< bytecode */ +{ + ecma_bytecode_ref ((ecma_compiled_code_t *) bc_p); + + ecma_op_regexp_initialize (regexp_obj_p, bc_p); + + return ecma_make_object_value (regexp_obj_p); +} /* ecma_op_create_regexp_from_bytecode */ + +/** + * Method for creating a RegExp object from pattern with already parsed flags. + * + * Note: + * Allocation have to happen before invoking this function using ecma_op_regexp_alloc. + * + * @return ecma_value_t + */ +ecma_value_t +ecma_op_create_regexp_with_flags (ecma_object_t *regexp_obj_p, /**< RegExp object */ + ecma_value_t pattern_value, /**< pattern */ + uint16_t flags) /**< flags */ +{ + ecma_string_t *pattern_str_p = ecma_regexp_read_pattern_str_helper (pattern_value); + + if (JERRY_UNLIKELY (pattern_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + re_compiled_code_t *bc_p = re_compile_bytecode (pattern_str_p, flags); + ecma_deref_ecma_string (pattern_str_p); + + if (JERRY_UNLIKELY (bc_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_op_regexp_initialize (regexp_obj_p, bc_p); + + return ecma_make_object_value (regexp_obj_p); +} /* ecma_op_create_regexp_with_flags */ + +/** + * Canonicalize a character + * + * @return ecma_char_t canonicalized character + */ +lit_code_point_t +ecma_regexp_canonicalize_char (lit_code_point_t ch, /**< character */ + bool unicode) /**< unicode */ +{ + if (unicode) + { + /* In unicode mode the mappings contained in the CaseFolding.txt file should be used to canonicalize the character. + * These mappings generally correspond to the lowercase variant of the character, however there are some + * differences. In some cases the uppercase variant is used, in others the lowercase of the uppercase character is + * used, and there are also cases where the character has no case folding mapping even though it has upper/lower + * variants. Since lowercasing is the most common this is used as the default behaviour, and characters with + * differing behaviours are encoded in lookup tables. */ + + if (lit_char_fold_to_upper (ch)) + { + ch = lit_char_to_upper_case (ch, NULL); + JERRY_ASSERT (ch != LIT_MULTIPLE_CU); + } + + if (lit_char_fold_to_lower (ch)) + { + ch = lit_char_to_lower_case (ch, NULL); + JERRY_ASSERT (ch != LIT_MULTIPLE_CU); + } + + return ch; + } + + JERRY_UNUSED (unicode); + lit_code_point_t cu = lit_char_to_upper_case (ch, NULL); + + if (ch <= LIT_UTF8_1_BYTE_CODE_POINT_MAX || (cu > LIT_UTF8_1_BYTE_CODE_POINT_MAX && cu != LIT_MULTIPLE_CU)) + { + return cu; + } + + return ch; +} /* ecma_regexp_canonicalize_char */ + +/** + * RegExp Canonicalize abstract operation + * + * See also: ECMA-262 v5, 15.10.2.8 + * + * @return ecma_char_t canonicalized character + */ +static inline lit_code_point_t +ecma_regexp_canonicalize (lit_code_point_t ch, /**< character */ + uint16_t flags) /**< flags */ +{ + if (flags & RE_FLAG_IGNORE_CASE) + { + return ecma_regexp_canonicalize_char (ch, flags & RE_FLAG_UNICODE); + } + + return ch; +} /* ecma_regexp_canonicalize */ + +/** + * Check if a code point is matched by a class escape. + * + * @return true, if code point matches escape + * false, otherwise + */ +static bool +ecma_regexp_check_class_escape (lit_code_point_t cp, /**< char */ + ecma_class_escape_t escape) /**< escape */ +{ + switch (escape) + { + case RE_ESCAPE_DIGIT: + { + return (cp >= LIT_CHAR_0 && cp <= LIT_CHAR_9); + } + case RE_ESCAPE_NOT_DIGIT: + { + return (cp < LIT_CHAR_0 || cp > LIT_CHAR_9); + } + case RE_ESCAPE_WORD_CHAR: + { + return lit_char_is_word_char (cp); + } + case RE_ESCAPE_NOT_WORD_CHAR: + { + return !lit_char_is_word_char (cp); + } + case RE_ESCAPE_WHITESPACE: + { + return lit_char_is_white_space ((ecma_char_t) cp); + } + case RE_ESCAPE_NOT_WHITESPACE: + { + return !lit_char_is_white_space ((ecma_char_t) cp); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_regexp_check_class_escape */ + +/** + * Helper function to get current code point or code unit depending on execution mode, + * and advance the string pointer. + * + * @return lit_code_point_t current code point + */ +static lit_code_point_t +ecma_regexp_advance (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */ + const lit_utf8_byte_t **str_p) /**< reference to string pointer */ +{ + JERRY_ASSERT (str_p != NULL); + lit_code_point_t cp = lit_cesu8_read_next (str_p); + + if (JERRY_UNLIKELY (re_ctx_p->flags & RE_FLAG_UNICODE) && lit_is_code_point_utf16_high_surrogate ((ecma_char_t) cp) + && *str_p < re_ctx_p->input_end_p) + { + const ecma_char_t next_ch = lit_cesu8_peek_next (*str_p); + if (lit_is_code_point_utf16_low_surrogate (next_ch)) + { + cp = lit_convert_surrogate_pair_to_code_point ((ecma_char_t) cp, next_ch); + *str_p += LIT_UTF8_MAX_BYTES_IN_CODE_UNIT; + } + } + + return ecma_regexp_canonicalize (cp, re_ctx_p->flags); +} /* ecma_regexp_advance */ + +/** + * Helper function to get current full unicode code point and advance the string pointer. + * + * @return lit_code_point_t current code point + */ +lit_code_point_t +ecma_regexp_unicode_advance (const lit_utf8_byte_t **str_p, /**< reference to string pointer */ + const lit_utf8_byte_t *end_p) /**< string end pointer */ +{ + JERRY_ASSERT (str_p != NULL); + const lit_utf8_byte_t *current_p = *str_p; + + lit_code_point_t ch = lit_cesu8_read_next (¤t_p); + if (lit_is_code_point_utf16_high_surrogate ((ecma_char_t) ch) && current_p < end_p) + { + const ecma_char_t next_ch = lit_cesu8_peek_next (current_p); + if (lit_is_code_point_utf16_low_surrogate (next_ch)) + { + ch = lit_convert_surrogate_pair_to_code_point ((ecma_char_t) ch, next_ch); + current_p += LIT_UTF8_MAX_BYTES_IN_CODE_UNIT; + } + } + + *str_p = current_p; + return ch; +} /* ecma_regexp_unicode_advance */ + +/** + * Helper function to revert the string pointer to the previous code point. + * + * @return pointer to previous code point + */ +static JERRY_ATTR_NOINLINE const lit_utf8_byte_t * +ecma_regexp_step_back (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */ + const lit_utf8_byte_t *str_p) /**< reference to string pointer */ +{ + JERRY_ASSERT (str_p != NULL); + + lit_code_point_t ch = lit_cesu8_read_prev (&str_p); + if (JERRY_UNLIKELY (re_ctx_p->flags & RE_FLAG_UNICODE) && lit_is_code_point_utf16_low_surrogate (ch) + && lit_is_code_point_utf16_high_surrogate (lit_cesu8_peek_prev (str_p))) + { + str_p -= LIT_UTF8_MAX_BYTES_IN_CODE_UNIT; + } + + return str_p; +} /* ecma_regexp_step_back */ + +/** + * Check if the current poisition is on a word boundary. + * + * @return true, if on a word boundary + * false - otherwise + */ +static bool +ecma_regexp_is_word_boundary (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */ + const lit_utf8_byte_t *str_p) /**< string pointer */ +{ + lit_code_point_t left_cp; + lit_code_point_t right_cp; + + if (JERRY_UNLIKELY (str_p <= re_ctx_p->input_start_p)) + { + left_cp = LIT_INVALID_CP; + } + else if (JERRY_UNLIKELY ((re_ctx_p->flags & (RE_FLAG_UNICODE | RE_FLAG_IGNORE_CASE)) + == (RE_FLAG_UNICODE | RE_FLAG_IGNORE_CASE))) + { + const lit_utf8_byte_t *prev_p = ecma_regexp_step_back (re_ctx_p, str_p); + left_cp = ecma_regexp_advance (re_ctx_p, &prev_p); + JERRY_ASSERT (prev_p == str_p); + } + else + { + left_cp = str_p[-1]; + } + + if (JERRY_UNLIKELY (str_p >= re_ctx_p->input_end_p)) + { + right_cp = LIT_INVALID_CP; + } + else if (JERRY_UNLIKELY ((re_ctx_p->flags & (RE_FLAG_UNICODE | RE_FLAG_IGNORE_CASE)) + == (RE_FLAG_UNICODE | RE_FLAG_IGNORE_CASE))) + { + right_cp = ecma_regexp_advance (re_ctx_p, &str_p); + } + else + { + right_cp = str_p[0]; + } + + return lit_char_is_word_char (left_cp) != lit_char_is_word_char (right_cp); +} /* ecma_regexp_is_word_boundary */ + +/** + * Recursive function for executing RegExp bytecode. + * + * See also: + * ECMA-262 v5, 15.10.2.1 + * + * @return pointer to the end of the currently matched substring + * NULL, if pattern did not match + */ +static const lit_utf8_byte_t * +ecma_regexp_run (ecma_regexp_ctx_t *re_ctx_p, /**< RegExp matcher context */ + const uint8_t *bc_p, /**< pointer to the current RegExp bytecode */ + const lit_utf8_byte_t *str_curr_p) /**< input string pointer */ +{ +#if (JERRY_STACK_LIMIT != 0) + if (JERRY_UNLIKELY (ecma_get_current_stack_usage () > CONFIG_MEM_STACK_LIMIT)) + { + return ECMA_RE_OUT_OF_STACK; + } +#endif /* JERRY_STACK_LIMIT != 0 */ + + const lit_utf8_byte_t *str_start_p = str_curr_p; + const uint8_t *next_alternative_p = NULL; + + while (true) + { + const re_opcode_t op = re_get_opcode (&bc_p); + + switch (op) + { + case RE_OP_EOF: + { + re_ctx_p->captures_p[RE_GLOBAL_CAPTURE].end_p = str_curr_p; + /* FALLTHRU */ + } + case RE_OP_ASSERT_END: + case RE_OP_ITERATOR_END: + { + return str_curr_p; + } + case RE_OP_ALTERNATIVE_START: + { + const uint32_t offset = re_get_value (&bc_p); + next_alternative_p = bc_p + offset; + continue; + } + case RE_OP_ALTERNATIVE_NEXT: + { + while (true) + { + const uint32_t offset = re_get_value (&bc_p); + bc_p += offset; + + if (*bc_p != RE_OP_ALTERNATIVE_NEXT) + { + break; + } + + bc_p++; + } + + continue; + } + case RE_OP_NO_ALTERNATIVE: + { + return NULL; + } + case RE_OP_CAPTURING_GROUP_START: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_capture_t *const group_p = re_ctx_p->captures_p + group_idx; + group_p->subcapture_count = re_get_value (&bc_p); + + const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p; + const lit_utf8_byte_t *const saved_end_p = group_p->end_p; + const uint32_t saved_iterator = group_p->iterator; + + const uint32_t qmin = re_get_value (&bc_p); + group_p->end_p = NULL; + + /* If zero iterations are allowed, then execute the end opcode which will handle further iterations, + * otherwise run the 1st iteration immediately by executing group bytecode. */ + if (qmin == 0) + { + group_p->iterator = 0; + group_p->begin_p = NULL; + const uint32_t end_offset = re_get_value (&bc_p); + group_p->bc_p = bc_p; + + bc_p += end_offset; + } + else + { + group_p->iterator = 1; + group_p->begin_p = str_curr_p; + group_p->bc_p = bc_p; + } + + const lit_utf8_byte_t *matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + group_p->iterator = saved_iterator; + + if (matched_p == NULL) + { + group_p->begin_p = saved_begin_p; + group_p->end_p = saved_end_p; + goto fail; + } + + return matched_p; + } + case RE_OP_NON_CAPTURING_GROUP_START: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_non_capture_t *const group_p = re_ctx_p->non_captures_p + group_idx; + + group_p->subcapture_start = re_get_value (&bc_p); + group_p->subcapture_count = re_get_value (&bc_p); + + const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p; + const uint32_t saved_iterator = group_p->iterator; + const uint32_t qmin = re_get_value (&bc_p); + + /* If zero iterations are allowed, then execute the end opcode which will handle further iterations, + * otherwise run the 1st iteration immediately by executing group bytecode. */ + if (qmin == 0) + { + group_p->iterator = 0; + group_p->begin_p = NULL; + const uint32_t end_offset = re_get_value (&bc_p); + group_p->bc_p = bc_p; + + bc_p += end_offset; + } + else + { + group_p->iterator = 1; + group_p->begin_p = str_curr_p; + group_p->bc_p = bc_p; + } + + const lit_utf8_byte_t *matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + group_p->iterator = saved_iterator; + + if (matched_p == NULL) + { + group_p->begin_p = saved_begin_p; + goto fail; + } + + return matched_p; + } + case RE_OP_GREEDY_CAPTURING_GROUP_END: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_capture_t *const group_p = re_ctx_p->captures_p + group_idx; + const uint32_t qmin = re_get_value (&bc_p); + + if (group_p->iterator < qmin) + { + /* No need to save begin_p since we don't have to backtrack beyond the minimum iteration count, but we have + * to clear nested capturing groups. */ + group_p->begin_p = str_curr_p; + for (uint32_t i = 1; i < group_p->subcapture_count; ++i) + { + group_p[i].begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + group_p->iterator--; + goto fail; + } + + /* Empty matches are not allowed after reaching the minimum number of iterations. */ + if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin)) + { + goto fail; + } + + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + if (JERRY_UNLIKELY (group_p->iterator >= qmax)) + { + /* Reached maximum number of iterations, try to match tail bytecode. */ + group_p->end_p = str_curr_p; + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + goto fail; + } + + { + /* Save and clear all nested capturing groups, and try to iterate. */ + JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count); + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + saved_captures_p[i] = group_p[i].begin_p; + group_p[i].begin_p = NULL; + } + + group_p->iterator++; + group_p->begin_p = str_curr_p; + + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + /* Failed to iterate again, backtrack to current match, and try to run tail bytecode. */ + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + group_p[i].begin_p = saved_captures_p[i]; + } + + group_p->iterator--; + group_p->end_p = str_curr_p; + } + + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + goto fail; + } + case RE_OP_GREEDY_NON_CAPTURING_GROUP_END: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_non_capture_t *const group_p = re_ctx_p->non_captures_p + group_idx; + const uint32_t qmin = re_get_value (&bc_p); + + if (group_p->iterator < qmin) + { + /* No need to save begin_p but we have to clear nested capturing groups. */ + group_p->begin_p = str_curr_p; + + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start; + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + capture_p[i].begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + group_p->iterator--; + goto fail; + } + + /* Empty matches are not allowed after reaching the minimum number of iterations. */ + if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin)) + { + goto fail; + } + + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + if (JERRY_UNLIKELY (group_p->iterator >= qmax)) + { + /* Reached maximum number of iterations, try to match tail bytecode. */ + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + goto fail; + } + + { + /* Save and clear all nested capturing groups, and try to iterate. */ + JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count); + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i; + saved_captures_p[i] = capture_p->begin_p; + capture_p->begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p; + group_p->begin_p = str_curr_p; + + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + /* Failed to iterate again, backtrack to current match, and try to run tail bytecode. */ + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i; + capture_p->begin_p = saved_captures_p[i]; + } + + group_p->iterator--; + group_p->begin_p = saved_begin_p; + } + + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + goto fail; + } + case RE_OP_LAZY_CAPTURING_GROUP_END: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_capture_t *const group_p = re_ctx_p->captures_p + group_idx; + const uint32_t qmin = re_get_value (&bc_p); + + if (group_p->iterator < qmin) + { + /* No need to save begin_p but we have to clear nested capturing groups. */ + group_p->begin_p = str_curr_p; + for (uint32_t i = 1; i < group_p->subcapture_count; ++i) + { + group_p[i].begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + group_p->iterator--; + goto fail; + } + + /* Empty matches are not allowed after reaching the minimum number of iterations. */ + if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin)) + { + goto fail; + } + + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + group_p->end_p = str_curr_p; + + /* Try to match tail bytecode. */ + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + if (JERRY_UNLIKELY (group_p->iterator >= qmax)) + { + /* Reached maximum number of iterations and tail bytecode did not match. */ + goto fail; + } + + { + /* Save and clear all nested capturing groups, and try to iterate. */ + JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count); + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + saved_captures_p[i] = group_p[i].begin_p; + group_p[i].begin_p = NULL; + } + + group_p->iterator++; + group_p->begin_p = str_curr_p; + + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + /* Backtrack to current match. */ + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + group_p[i].begin_p = saved_captures_p[i]; + } + + group_p->iterator--; + } + + goto fail; + } + case RE_OP_LAZY_NON_CAPTURING_GROUP_END: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_non_capture_t *const group_p = re_ctx_p->non_captures_p + group_idx; + const uint32_t qmin = re_get_value (&bc_p); + + if (group_p->iterator < qmin) + { + /* Clear nested captures. */ + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start; + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + capture_p[i].begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + group_p->iterator--; + goto fail; + } + + /* Empty matches are not allowed after reaching the minimum number of iterations. */ + if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin)) + { + goto fail; + } + + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + + /* Try to match tail bytecode. */ + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + if (JERRY_UNLIKELY (group_p->iterator >= qmax)) + { + /* Reached maximum number of iterations and tail bytecode did not match. */ + goto fail; + } + + { + /* Save and clear all nested capturing groups, and try to iterate. */ + JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count); + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i; + saved_captures_p[i] = capture_p->begin_p; + capture_p->begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p; + group_p->begin_p = str_curr_p; + + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + /* Backtrack to current match. */ + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i; + capture_p->begin_p = saved_captures_p[i]; + } + + group_p->iterator--; + group_p->begin_p = saved_begin_p; + } + + goto fail; + } + case RE_OP_GREEDY_ITERATOR: + { + const uint32_t qmin = re_get_value (&bc_p); + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + const uint32_t end_offset = re_get_value (&bc_p); + + uint32_t iterator = 0; + while (iterator < qmin) + { + str_curr_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (str_curr_p == NULL) + { + goto fail; + } + + if (ECMA_RE_STACK_LIMIT_REACHED (str_curr_p)) + { + return str_curr_p; + } + + iterator++; + } + + while (iterator < qmax) + { + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (matched_p == NULL) + { + break; + } + + if (ECMA_RE_STACK_LIMIT_REACHED (str_curr_p)) + { + return str_curr_p; + } + + str_curr_p = matched_p; + iterator++; + } + + const uint8_t *const tail_bc_p = bc_p + end_offset; + while (true) + { + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, tail_bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + if (JERRY_UNLIKELY (iterator <= qmin)) + { + goto fail; + } + + iterator--; + JERRY_ASSERT (str_curr_p > re_ctx_p->input_start_p); + str_curr_p = ecma_regexp_step_back (re_ctx_p, str_curr_p); + } + + JERRY_UNREACHABLE (); + } + case RE_OP_LAZY_ITERATOR: + { + const uint32_t qmin = re_get_value (&bc_p); + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + const uint32_t end_offset = re_get_value (&bc_p); + + uint32_t iterator = 0; + while (iterator < qmin) + { + str_curr_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (str_curr_p == NULL) + { + goto fail; + } + + if (ECMA_RE_STACK_LIMIT_REACHED (str_curr_p)) + { + return str_curr_p; + } + + iterator++; + } + + const uint8_t *const tail_bc_p = bc_p + end_offset; + while (true) + { + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, tail_bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + if (JERRY_UNLIKELY (iterator >= qmax)) + { + goto fail; + } + + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (matched_p == NULL) + { + goto fail; + } + + if (ECMA_RE_STACK_LIMIT_REACHED (matched_p)) + { + return matched_p; + } + + iterator++; + str_curr_p = matched_p; + } + + JERRY_UNREACHABLE (); + } + case RE_OP_BACKREFERENCE: + { + const uint32_t backref_idx = re_get_value (&bc_p); + JERRY_ASSERT (backref_idx >= 1 && backref_idx < re_ctx_p->captures_count); + const ecma_regexp_capture_t *capture_p = re_ctx_p->captures_p + backref_idx; + + if (!ECMA_RE_IS_CAPTURE_DEFINED (capture_p) || capture_p->end_p <= capture_p->begin_p) + { + /* Undefined or zero length captures always match. */ + continue; + } + + const lit_utf8_size_t capture_size = (lit_utf8_size_t) (capture_p->end_p - capture_p->begin_p); + + if (str_curr_p + capture_size > re_ctx_p->input_end_p || memcmp (str_curr_p, capture_p->begin_p, capture_size)) + { + goto fail; + } + + str_curr_p += capture_size; + continue; + } + case RE_OP_ASSERT_LINE_START: + { + if (str_curr_p <= re_ctx_p->input_start_p) + { + continue; + } + + if (!(re_ctx_p->flags & RE_FLAG_MULTILINE) || !lit_char_is_line_terminator (lit_cesu8_peek_prev (str_curr_p))) + { + goto fail; + } + + continue; + } + case RE_OP_ASSERT_LINE_END: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + continue; + } + + if (!(re_ctx_p->flags & RE_FLAG_MULTILINE) || !lit_char_is_line_terminator (lit_cesu8_peek_next (str_curr_p))) + { + goto fail; + } + + continue; + } + case RE_OP_ASSERT_WORD_BOUNDARY: + { + if (!ecma_regexp_is_word_boundary (re_ctx_p, str_curr_p)) + { + goto fail; + } + + continue; + } + case RE_OP_ASSERT_NOT_WORD_BOUNDARY: + { + if (ecma_regexp_is_word_boundary (re_ctx_p, str_curr_p)) + { + goto fail; + } + + continue; + } + case RE_OP_ASSERT_LOOKAHEAD_POS: + { + const uint8_t qmin = re_get_byte (&bc_p); + const uint32_t capture_start = re_get_value (&bc_p); + const uint32_t capture_count = re_get_value (&bc_p); + const uint32_t end_offset = re_get_value (&bc_p); + + /* If qmin is zero, the assertion implicitly matches. */ + if (qmin == 0) + { + bc_p += end_offset; + continue; + } + + /* Capture end pointers might get clobbered and need to be restored after a tail match fail. */ + JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, capture_count); + for (uint32_t i = 0; i < capture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + capture_start + i; + saved_captures_p[i] = capture_p->end_p; + } + + /* The first iteration will decide whether the assertion matches depending on whether + * the iteration matched or not. */ + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (ECMA_RE_STACK_LIMIT_REACHED (matched_p)) + { + return matched_p; + } + + if (matched_p == NULL) + { + goto fail; + } + + const lit_utf8_byte_t *tail_match_p = ecma_regexp_run (re_ctx_p, bc_p + end_offset, str_curr_p); + + if (tail_match_p == NULL) + { + for (uint32_t i = 0; i < capture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + capture_start + i; + capture_p->begin_p = NULL; + capture_p->end_p = saved_captures_p[i]; + } + + goto fail; + } + + return tail_match_p; + } + case RE_OP_ASSERT_LOOKAHEAD_NEG: + { + const uint8_t qmin = re_get_byte (&bc_p); + uint32_t capture_idx = re_get_value (&bc_p); + const uint32_t capture_count = re_get_value (&bc_p); + const uint32_t end_offset = re_get_value (&bc_p); + + /* If qmin is zero, the assertion implicitly matches. */ + if (qmin > 0) + { + /* The first iteration will decide whether the assertion matches depending on whether + * the iteration matched or not. */ + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (ECMA_RE_STACK_LIMIT_REACHED (matched_p)) + { + return matched_p; + } + + if (matched_p != NULL) + { + /* Nested capturing groups inside a negative lookahead can never capture, so we clear their results. */ + const uint32_t capture_end = capture_idx + capture_count; + while (capture_idx < capture_end) + { + re_ctx_p->captures_p[capture_idx++].begin_p = NULL; + } + + goto fail; + } + } + + bc_p += end_offset; + continue; + } + case RE_OP_CLASS_ESCAPE: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + goto fail; + } + + const lit_code_point_t cp = ecma_regexp_advance (re_ctx_p, &str_curr_p); + + const ecma_class_escape_t escape = (ecma_class_escape_t) re_get_byte (&bc_p); + if (!ecma_regexp_check_class_escape (cp, escape)) + { + goto fail; + } + + continue; + } + case RE_OP_CHAR_CLASS: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + goto fail; + } + + uint8_t flags = re_get_byte (&bc_p); + uint32_t char_count = (flags & RE_CLASS_HAS_CHARS) ? re_get_value (&bc_p) : 0; + uint32_t range_count = (flags & RE_CLASS_HAS_RANGES) ? re_get_value (&bc_p) : 0; + + const lit_code_point_t cp = ecma_regexp_advance (re_ctx_p, &str_curr_p); + + uint8_t escape_count = flags & RE_CLASS_ESCAPE_COUNT_MASK; + while (escape_count > 0) + { + escape_count--; + const ecma_class_escape_t escape = (ecma_class_escape_t) re_get_byte (&bc_p); + if (ecma_regexp_check_class_escape (cp, escape)) + { + goto class_found; + } + } + + while (char_count > 0) + { + char_count--; + const lit_code_point_t curr = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE); + if (cp == curr) + { + goto class_found; + } + } + + while (range_count > 0) + { + range_count--; + const lit_code_point_t begin = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE); + + if (cp < begin) + { + bc_p += re_ctx_p->char_size; + continue; + } + + const lit_code_point_t end = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE); + if (cp <= end) + { + goto class_found; + } + } + + /* Not found */ + if (flags & RE_CLASS_INVERT) + { + continue; + } + + goto fail; + +class_found: + if (flags & RE_CLASS_INVERT) + { + goto fail; + } + + const uint32_t chars_size = char_count * re_ctx_p->char_size; + const uint32_t ranges_size = range_count * re_ctx_p->char_size * 2; + bc_p = bc_p + escape_count + chars_size + ranges_size; + continue; + } + case RE_OP_UNICODE_PERIOD: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + goto fail; + } + + const lit_code_point_t cp = ecma_regexp_unicode_advance (&str_curr_p, re_ctx_p->input_end_p); + + if (!(re_ctx_p->flags & RE_FLAG_DOTALL) + && JERRY_UNLIKELY (cp <= LIT_UTF16_CODE_UNIT_MAX && lit_char_is_line_terminator ((ecma_char_t) cp))) + { + goto fail; + } + + continue; + } + case RE_OP_PERIOD: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + goto fail; + } + + const ecma_char_t ch = lit_cesu8_read_next (&str_curr_p); + + if (!(re_ctx_p->flags & RE_FLAG_DOTALL) && lit_char_is_line_terminator (ch)) + { + goto fail; + } + + continue; + } + case RE_OP_CHAR: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + goto fail; + } + + const lit_code_point_t ch1 = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE); + const lit_code_point_t ch2 = ecma_regexp_advance (re_ctx_p, &str_curr_p); + + if (ch1 != ch2) + { + goto fail; + } + + continue; + } + default: + { + JERRY_ASSERT (op == RE_OP_BYTE); + + if (str_curr_p >= re_ctx_p->input_end_p || *bc_p++ != *str_curr_p++) + { + goto fail; + } + + continue; + } + } + + JERRY_UNREACHABLE (); +fail: + bc_p = next_alternative_p; + + if (bc_p == NULL || *bc_p++ != RE_OP_ALTERNATIVE_NEXT) + { + /* None of the alternatives matched. */ + return NULL; + } + + /* Get the end of the new alternative and continue execution. */ + str_curr_p = str_start_p; + const uint32_t offset = re_get_value (&bc_p); + next_alternative_p = bc_p + offset; + } +} /* ecma_regexp_run */ + +/** + * Match a RegExp at a specific position in the input string. + * + * @return pointer to the end of the matched sub-string + * NULL, if pattern did not match + */ +static const lit_utf8_byte_t * +ecma_regexp_match (ecma_regexp_ctx_t *re_ctx_p, /**< RegExp matcher context */ + const uint8_t *bc_p, /**< pointer to the current RegExp bytecode */ + const lit_utf8_byte_t *str_curr_p) /**< input string pointer */ +{ + re_ctx_p->captures_p[RE_GLOBAL_CAPTURE].begin_p = str_curr_p; + + for (uint32_t i = 1; i < re_ctx_p->captures_count; ++i) + { + re_ctx_p->captures_p[i].begin_p = NULL; + } + + return ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); +} /* ecma_regexp_match */ + +/* + * Helper function to get the result of a capture + * + * @return string value, if capture is defined + * undefined, otherwise + */ +ecma_value_t +ecma_regexp_get_capture_value (const ecma_regexp_capture_t *const capture_p) /**< capture */ +{ + if (ECMA_RE_IS_CAPTURE_DEFINED (capture_p)) + { + JERRY_ASSERT (capture_p->end_p >= capture_p->begin_p); + const lit_utf8_size_t capture_size = (lit_utf8_size_t) (capture_p->end_p - capture_p->begin_p); + ecma_string_t *const capture_str_p = ecma_new_ecma_string_from_utf8 (capture_p->begin_p, capture_size); + return ecma_make_string_value (capture_str_p); + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_regexp_get_capture_value */ + +/** + * Helper function to create a result array from the captures in a regexp context + * + * @return ecma value containing the created array object + */ +static ecma_value_t +ecma_regexp_create_result_object (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */ + ecma_string_t *input_string_p, /**< input ecma string */ + uint32_t index) /**< match index */ +{ + ecma_object_t *result_p = ecma_op_new_array_object (0); + + for (uint32_t i = 0; i < re_ctx_p->captures_count; i++) + { + ecma_value_t capture_value = ecma_regexp_get_capture_value (re_ctx_p->captures_p + i); + ecma_builtin_helper_def_prop_by_index (result_p, i, capture_value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_free_value (capture_value); + } + + ecma_builtin_helper_def_prop (result_p, + ecma_get_magic_string (LIT_MAGIC_STRING_INDEX), + ecma_make_uint32_value (index), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + ecma_builtin_helper_def_prop (result_p, + ecma_get_magic_string (LIT_MAGIC_STRING_INPUT), + ecma_make_string_value (input_string_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + return ecma_make_object_value (result_p); +} /* ecma_regexp_create_result_object */ + +/** + * Helper function to initialize a regexp match context + */ +static void +ecma_regexp_initialize_context (ecma_regexp_ctx_t *ctx_p, /**< regexp context */ + const re_compiled_code_t *bc_p, /**< regexp bytecode */ + const lit_utf8_byte_t *input_start_p, /**< pointer to input string */ + const lit_utf8_byte_t *input_end_p) /**< pointer to end of input string */ +{ + JERRY_ASSERT (ctx_p != NULL); + JERRY_ASSERT (bc_p != NULL); + JERRY_ASSERT (input_start_p != NULL); + JERRY_ASSERT (input_end_p >= input_start_p); + + ctx_p->flags = bc_p->header.status_flags; + ctx_p->char_size = (ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t); + + ctx_p->input_start_p = input_start_p; + ctx_p->input_end_p = input_end_p; + + ctx_p->captures_count = bc_p->captures_count; + ctx_p->non_captures_count = bc_p->non_captures_count; + + ctx_p->captures_p = (ecma_regexp_capture_t *) jmem_heap_alloc_block (ctx_p->captures_count * sizeof (ecma_regexp_capture_t)); + + if (ctx_p->non_captures_count > 0) + { + ctx_p->non_captures_p = (ecma_regexp_non_capture_t *) jmem_heap_alloc_block (ctx_p->non_captures_count * sizeof (ecma_regexp_non_capture_t)); + } +} /* ecma_regexp_initialize_context */ + +/** + * Helper function to clean up a regexp context + */ +static void +ecma_regexp_cleanup_context (ecma_regexp_ctx_t *ctx_p) /**< regexp context */ +{ + JERRY_ASSERT (ctx_p != NULL); + jmem_heap_free_block (ctx_p->captures_p, ctx_p->captures_count * sizeof (ecma_regexp_capture_t)); + + if (ctx_p->non_captures_count > 0) + { + jmem_heap_free_block (ctx_p->non_captures_p, ctx_p->non_captures_count * sizeof (ecma_regexp_non_capture_t)); + } +} /* ecma_regexp_cleanup_context */ + +/** + * RegExp helper function to start the recursive matching algorithm + * and create the result Array object + * + * See also: + * ECMA-262 v5, 15.10.6.2 + * ECMA-262 v11, 21.2.5.2.2 + * + * @return array object - if matched + * null - otherwise + * + * May raise error. + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_regexp_exec_helper (ecma_object_t *regexp_object_p, /**< RegExp object */ + ecma_string_t *input_string_p) /**< input string */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + lit_utf8_byte_t *matched_p; + uint8_t *bc_start_p; + + /* 1. */ + JERRY_ASSERT (ecma_object_is_regexp_object (ecma_make_object_value (regexp_object_p))); + + /* 9. */ + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) regexp_object_p; + re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, ext_object_p->u.cls.u3.value); + + /* 3. */ + lit_utf8_size_t input_size; + lit_utf8_size_t input_length; + uint8_t input_flags = ECMA_STRING_FLAG_IS_ASCII; + const lit_utf8_byte_t *input_buffer_p = + ecma_string_get_chars (input_string_p, &input_size, &input_length, NULL, &input_flags); + + const lit_utf8_byte_t *input_curr_p = input_buffer_p; + const lit_utf8_byte_t *input_end_p = input_buffer_p + input_size; + + ecma_regexp_ctx_t re_ctx; + ecma_regexp_initialize_context (&re_ctx, bc_p, input_buffer_p, input_end_p); + + /* 4. */ + ecma_length_t index = 0; + ecma_value_t lastindex_value = ecma_op_object_get_by_magic_id (regexp_object_p, LIT_MAGIC_STRING_LASTINDEX_UL); + + ret_value = ecma_op_to_length (lastindex_value, &index); + ecma_free_value (lastindex_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + goto cleanup_context; + } + + if (re_ctx.flags & (RE_FLAG_GLOBAL | RE_FLAG_STICKY)) + { + /* 12.a */ + if (index > input_length) + { + goto fail_put_lastindex; + } + + if (index > 0) + { + if (input_flags & ECMA_STRING_FLAG_IS_ASCII) + { + input_curr_p += index; + } + else + { + for (uint32_t i = 0; i < index; i++) + { + lit_utf8_incr (&input_curr_p); + } + } + } + } + /* 8. */ + else + { + index = 0; + } + + /* 9. */ + bc_start_p = (uint8_t *) (bc_p + 1); + + /* 11. */ + matched_p = NULL; + + /* 12. */ + JERRY_ASSERT (index <= input_length); + while (true) + { + matched_p = (lit_utf8_byte_t *) ecma_regexp_match (&re_ctx, bc_start_p, input_curr_p); + + if (matched_p != NULL) + { + goto match_found; + } + + /* 12.c.i */ + if (re_ctx.flags & RE_FLAG_STICKY) + { + goto fail_put_lastindex; + } + + /* 12.a */ + if (input_curr_p >= input_end_p) + { + if (re_ctx.flags & RE_FLAG_GLOBAL) + { + goto fail_put_lastindex; + } + + goto match_failed; + } + + JERRY_ASSERT (input_curr_p < input_end_p); + + /* 12.c.ii */ + index++; + + if (re_ctx.flags & RE_FLAG_UNICODE) + { + const lit_code_point_t cp = ecma_regexp_unicode_advance (&input_curr_p, input_end_p); + + if (cp > LIT_UTF16_CODE_UNIT_MAX) + { + index++; + } + + continue; + } + + lit_utf8_incr (&input_curr_p); + } + + JERRY_UNREACHABLE (); + +fail_put_lastindex: + /* We should only get here if the regexp is global or sticky */ + JERRY_ASSERT ((re_ctx.flags & (RE_FLAG_GLOBAL | RE_FLAG_STICKY)) != 0); + + ret_value = ecma_op_object_put (regexp_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_integer_value (0), + true); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + goto cleanup_context; + } + + JERRY_ASSERT (ecma_is_value_boolean (ret_value)); + +match_failed: + /* 12.a.ii */ + ret_value = ECMA_VALUE_NULL; + goto cleanup_context; + +match_found: + JERRY_ASSERT (matched_p != NULL); + + if (ECMA_RE_STACK_LIMIT_REACHED (matched_p)) + { + ret_value = ecma_raise_range_error (ECMA_ERR_STACK_LIMIT_EXCEEDED); + goto cleanup_context; + } + + JERRY_ASSERT (index <= input_length); + + /* 15. */ + if (re_ctx.flags & (RE_FLAG_GLOBAL | RE_FLAG_STICKY)) + { + /* 13-14. */ + lit_utf8_size_t match_length; + const lit_utf8_byte_t *match_begin_p = re_ctx.captures_p[0].begin_p; + const lit_utf8_byte_t *match_end_p = re_ctx.captures_p[0].end_p; + + if (input_flags & ECMA_STRING_FLAG_IS_ASCII) + { + match_length = (lit_utf8_size_t) (match_end_p - match_begin_p); + } + else + { + match_length = lit_utf8_string_length (match_begin_p, (lit_utf8_size_t) (match_end_p - match_begin_p)); + } + + ret_value = ecma_op_object_put (regexp_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value ((uint32_t) index + match_length), + true); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + goto cleanup_context; + } + + JERRY_ASSERT (ecma_is_value_boolean (ret_value)); + } + + /* 16-27. */ + ret_value = ecma_regexp_create_result_object (&re_ctx, input_string_p, (uint32_t) index); + +cleanup_context: + ecma_regexp_cleanup_context (&re_ctx); + + if (input_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) input_buffer_p, input_size); + } + + return ret_value; +} /* ecma_regexp_exec_helper */ + +/** + * Helper function for converting a RegExp pattern parameter to string. + * + * See also: + * RegExp.compile + * RegExp dispatch call + * + * @return empty value if success, error value otherwise + * Returned value must be freed with ecma_free_value. + */ +ecma_string_t * +ecma_regexp_read_pattern_str_helper (ecma_value_t pattern_arg) /**< the RegExp pattern */ +{ + if (!ecma_is_value_undefined (pattern_arg)) + { + ecma_string_t *pattern_string_p = ecma_op_to_string (pattern_arg); + if (JERRY_UNLIKELY (pattern_string_p == NULL) || !ecma_string_is_empty (pattern_string_p)) + { + return pattern_string_p; + } + } + + return ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); +} /* ecma_regexp_read_pattern_str_helper */ + +/** + * Helper function for RegExp based string searches + * + * See also: + * ECMA-262 v6, 21.2.5.9 + * + * @return index of the match + */ +ecma_value_t +ecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */ + ecma_value_t string_arg) /**< string argument */ +{ + /* 2. */ + if (!ecma_is_value_object (regexp_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_value_t result = ECMA_VALUE_ERROR; + ecma_value_t current_last_index; + ecma_value_t match; + bool same_value; + + /* 3. */ + ecma_string_t *const string_p = ecma_op_to_string (string_arg); + if (string_p == NULL) + { + return result; + } + + ecma_object_t *const regexp_object_p = ecma_get_object_from_value (regexp_arg); + + /* 4. */ + ecma_string_t *const last_index_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); + const ecma_value_t prev_last_index = ecma_op_object_get (regexp_object_p, last_index_str_p); + if (ECMA_IS_VALUE_ERROR (prev_last_index)) + { + goto cleanup_string; + } + + /* 5. */ + if (prev_last_index != ecma_make_uint32_value (0)) + { + const ecma_value_t status = + ecma_op_object_put (regexp_object_p, last_index_str_p, ecma_make_uint32_value (0), true); + + if (ECMA_IS_VALUE_ERROR (status)) + { + goto cleanup_prev_last_index; + } + + JERRY_ASSERT (ecma_is_value_boolean (status)); + } + + /* 6. */ + match = ecma_op_regexp_exec (regexp_arg, string_p); + if (ECMA_IS_VALUE_ERROR (match)) + { + goto cleanup_prev_last_index; + } + + /* 7. */ + current_last_index = ecma_op_object_get (regexp_object_p, last_index_str_p); + if (ECMA_IS_VALUE_ERROR (current_last_index)) + { + ecma_free_value (match); + goto cleanup_prev_last_index; + } + + same_value = ecma_op_same_value (prev_last_index, current_last_index); + + ecma_free_value (current_last_index); + + /* 8. */ + if (!same_value) + { + result = ecma_op_object_put (regexp_object_p, last_index_str_p, prev_last_index, true); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_free_value (match); + goto cleanup_prev_last_index; + } + + JERRY_ASSERT (ecma_is_value_boolean (result)); + } + + /* 9-10. */ + if (ecma_is_value_null (match)) + { + result = ecma_make_int32_value (-1); + } + else + { + ecma_object_t *const match_p = ecma_get_object_from_value (match); + result = ecma_op_object_get_by_magic_id (match_p, LIT_MAGIC_STRING_INDEX); + ecma_deref_object (match_p); + } + +cleanup_prev_last_index: + ecma_free_value (prev_last_index); + +cleanup_string: + ecma_deref_ecma_string (string_p); + return result; +} /* ecma_regexp_search_helper */ + +/** + * Helper function for RegExp based string split operation + * + * See also: + * ECMA-262 v6, 21.2.5.11 + * + * @return array of split and captured strings + */ +ecma_value_t +ecma_regexp_split_helper (ecma_value_t this_arg, /**< this value */ + ecma_value_t string_arg, /**< string value */ + ecma_value_t limit_arg) /**< limit value */ +{ + /* 2. */ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_value_t result = ECMA_VALUE_ERROR; + ecma_length_t current_index; + ecma_length_t previous_index; + ecma_object_t *constructor_obj_p; + ecma_value_t flags; + ecma_string_t *flags_str_p; + lit_utf8_size_t flags_size; + uint8_t flags_str_flags; + lit_utf8_byte_t *flags_buffer_p; + lit_utf8_byte_t *flags_end_p; + ecma_value_t arguments[2]; + ecma_value_t splitter; + ecma_object_t *splitter_obj_p; + ecma_object_t *array_p; + ecma_value_t array; + ecma_string_t *end_str_p; + ecma_string_t *lastindex_str_p; + lit_utf8_size_t string_length; + uint32_t array_length; + uint32_t limit; + bool unicode; + bool sticky; + + /* 3-4. */ + ecma_string_t *const string_p = ecma_op_to_string (string_arg); + if (string_p == NULL) + { + return result; + } + + /* 5-6. */ + ecma_object_t *const regexp_obj_p = ecma_get_object_from_value (this_arg); + ecma_value_t constructor = ecma_op_species_constructor (regexp_obj_p, ECMA_BUILTIN_ID_REGEXP); + if (ECMA_IS_VALUE_ERROR (constructor)) + { + goto cleanup_string; + } + + constructor_obj_p = ecma_get_object_from_value (constructor); + + /* 7-8. */ + flags = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_FLAGS); + if (ECMA_IS_VALUE_ERROR (flags)) + { + ecma_deref_object (constructor_obj_p); + goto cleanup_string; + } + + flags_str_p = ecma_op_to_string (flags); + ecma_free_value (flags); + + if (JERRY_UNLIKELY (flags_str_p == NULL)) + { + ecma_deref_object (constructor_obj_p); + goto cleanup_string; + } + + flags_str_flags = ECMA_STRING_FLAG_IS_ASCII; + flags_buffer_p = (lit_utf8_byte_t *) ecma_string_get_chars (flags_str_p, &flags_size, NULL, NULL, &flags_str_flags); + + unicode = false; + sticky = false; + + /* 9-11. */ + flags_end_p = flags_buffer_p + flags_size; + for (const lit_utf8_byte_t *current_p = flags_buffer_p; current_p < flags_end_p; ++current_p) + { + switch (*current_p) + { + case LIT_CHAR_LOWERCASE_U: + { + unicode = true; + break; + } + case LIT_CHAR_LOWERCASE_Y: + { + sticky = true; + break; + } + } + } + + if (flags_str_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) flags_buffer_p, flags_size); + } + + /* 12. */ + if (!sticky) + { + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (flags_str_p); + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_LOWERCASE_Y); + + ecma_deref_ecma_string (flags_str_p); + flags_str_p = ecma_stringbuilder_finalize (&builder); + } + + /* 13-14. */ + arguments[0] = this_arg; + arguments[1] = ecma_make_string_value (flags_str_p); + splitter = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, arguments, 2); + + ecma_deref_ecma_string (flags_str_p); + ecma_deref_object (constructor_obj_p); + + if (ECMA_IS_VALUE_ERROR (splitter)) + { + goto cleanup_string; + } + + splitter_obj_p = ecma_get_object_from_value (splitter); + + /* 17. */ + limit = UINT32_MAX - 1; + if (!ecma_is_value_undefined (limit_arg)) + { + /* ECMA-262 v11, 21.2.5.13 13 */ + ecma_number_t num; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (limit_arg, &num))) + { + goto cleanup_splitter; + } + limit = ecma_number_to_uint32 (num); + } + + /* 15. */ + array_p = ecma_op_new_array_object (0); + array = ecma_make_object_value (array_p); + + /* 21. */ + if (limit == 0) + { + result = array; + goto cleanup_splitter; + } + + string_length = ecma_string_get_length (string_p); + array_length = 0; + + /* 22. */ + if (string_length == 0) + { + const ecma_value_t match = ecma_op_regexp_exec (splitter, string_p); + + if (ECMA_IS_VALUE_ERROR (match)) + { + goto cleanup_array; + } + + if (ecma_is_value_null (match)) + { + result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length, + ecma_make_string_value (string_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (result)); + } + + ecma_free_value (match); + result = array; + goto cleanup_splitter; + } + + /* 23. */ + current_index = 0; + previous_index = 0; + + lastindex_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); + + /* 24. */ + while (current_index < string_length) + { + /* 24.a-b. */ + ecma_value_t index_value = ecma_make_length_value (current_index); + result = ecma_op_object_put (splitter_obj_p, lastindex_str_p, index_value, true); + + ecma_free_value (index_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_array; + } + + JERRY_ASSERT (ecma_is_value_true (result)); + + /* 24.c-d. */ + result = ecma_op_regexp_exec (splitter, string_p); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_array; + } + + /* 24.e. */ + if (ecma_is_value_null (result)) + { + current_index = ecma_op_advance_string_index (string_p, current_index, unicode); + continue; + } + + ecma_object_t *const match_array_p = ecma_get_object_from_value (result); + + /* 24.f.i. */ + result = ecma_op_object_get (splitter_obj_p, lastindex_str_p); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (match_array_p); + goto cleanup_array; + } + + ecma_length_t end_index; + const ecma_value_t length_value = ecma_op_to_length (result, &end_index); + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (length_value)) + { + result = ECMA_VALUE_ERROR; + ecma_deref_object (match_array_p); + goto cleanup_array; + } + + /* ECMA-262 v11, 21.2.5.11 19.d.ii */ + if (end_index > string_length) + { + end_index = string_length; + } + + /* 24.f.iii. */ + if (previous_index == end_index) + { + ecma_deref_object (match_array_p); + current_index = ecma_op_advance_string_index (string_p, current_index, unicode); + continue; + } + + /* 24.f.iv.1-4. */ + JERRY_ASSERT (previous_index <= string_length && current_index <= string_length); + ecma_string_t *const split_str_p = + ecma_string_substr (string_p, (lit_utf8_size_t) previous_index, (lit_utf8_size_t) current_index); + + result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length++, + ecma_make_string_value (split_str_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (result)); + ecma_deref_ecma_string (split_str_p); + + /* 24.f.iv.5. */ + if (array_length == limit) + { + ecma_deref_object (match_array_p); + result = array; + goto cleanup_splitter; + } + + /* 24.f.iv.6. */ + previous_index = end_index; + + /* 24.f.iv.7-8. */ + ecma_length_t match_length; + result = ecma_op_object_get_length (match_array_p, &match_length); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (match_array_p); + goto cleanup_array; + } + + /* 24.f.iv.9. */ + match_length = (match_length > 0) ? match_length - 1 : match_length; + + ecma_length_t match_index = 1; + while (match_index <= match_length) + { + /* 24.f.iv.11.a-b. */ + result = ecma_op_object_get_by_index (match_array_p, match_index++); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (match_array_p); + goto cleanup_array; + } + + const ecma_value_t capture = result; + + /* 24.f.iv.11.c. */ + result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length++, + capture, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (result)); + + ecma_free_value (capture); + + if (array_length == limit) + { + ecma_deref_object (match_array_p); + result = array; + goto cleanup_splitter; + } + } + + /* 24.f.iv.12. */ + JERRY_ASSERT (end_index <= UINT32_MAX); + current_index = (uint32_t) end_index; + + ecma_deref_object (match_array_p); + } + + JERRY_ASSERT (previous_index <= string_length); + end_str_p = ecma_string_substr (string_p, (lit_utf8_size_t) previous_index, string_length); + result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length++, + ecma_make_string_value (end_str_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (result)); + ecma_deref_ecma_string (end_str_p); + + result = array; + goto cleanup_splitter; + +cleanup_array: + ecma_deref_object (array_p); +cleanup_splitter: + ecma_deref_object (splitter_obj_p); +cleanup_string: + ecma_deref_ecma_string (string_p); + + return result; +} /* ecma_regexp_split_helper */ + +/** + * Fast path for RegExp based replace operation + * + * This method assumes the following: + * - The RegExp object is a built-in RegExp + * - The 'exec' method of the RegExp object is the built-in 'exec' method + * - The 'lastIndex' property is writable + * + * The standard would normally require us to first execute the regexp and collect the results, + * and after that iterate over the collected results and replace them. + * The assumptions above guarantee that during the matching phase there will be no exceptions thrown, + * which means we can do the match/replace in a single loop, without collecting the results. + * + * @return string value if successful + * thrown value otherwise + */ +static ecma_value_t +ecma_regexp_replace_helper_fast (ecma_replace_context_t *ctx_p, /**u.cls.u3.value); + ecma_bytecode_ref ((ecma_compiled_code_t *) bc_p); + + JERRY_ASSERT (bc_p != NULL); + + uint8_t string_flags = ECMA_STRING_FLAG_IS_ASCII; + lit_utf8_size_t string_length; + ctx_p->string_p = ecma_string_get_chars (string_p, &(ctx_p->string_size), &string_length, NULL, &string_flags); + + const lit_utf8_byte_t *const string_end_p = ctx_p->string_p + ctx_p->string_size; + const uint8_t *const bc_start_p = (const uint8_t *) (bc_p + 1); + const lit_utf8_byte_t *matched_p = NULL; + const lit_utf8_byte_t *current_p = ctx_p->string_p; + const lit_utf8_byte_t *last_append_p = current_p; + ecma_length_t index; + lit_utf8_size_t trailing_size; + + ecma_regexp_ctx_t re_ctx; + ecma_regexp_initialize_context (&re_ctx, bc_p, ctx_p->string_p, string_end_p); + + /* lastIndex must be accessed to remain consistent with the standard, even though we may not need the value. */ + ecma_value_t lastindex_value = + ecma_op_object_get_by_magic_id ((ecma_object_t *) re_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); + ecma_value_t result = ecma_op_to_length (lastindex_value, &index); + ecma_free_value (lastindex_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_context; + } + + /* Only non-global sticky matches use the lastIndex value, otherwise the starting index is 0. */ + if (JERRY_UNLIKELY ((ctx_p->flags & RE_FLAG_GLOBAL) == 0 && (re_ctx.flags & RE_FLAG_STICKY) != 0)) + { + if (index > string_length) + { + result = ecma_op_object_put ((ecma_object_t *) re_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + true); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + JERRY_ASSERT (ecma_is_value_true (result)); + ecma_ref_ecma_string (string_p); + result = ecma_make_string_value (string_p); + } + + goto cleanup_context; + } + + if (string_flags & ECMA_STRING_FLAG_IS_ASCII) + { + current_p += index; + } + else + { + ecma_length_t counter = index; + while (counter--) + { + lit_utf8_incr (¤t_p); + } + } + } + else + { + index = 0; + } + + ctx_p->builder = ecma_stringbuilder_create (); + ctx_p->capture_count = re_ctx.captures_count; + ctx_p->u.captures_p = re_ctx.captures_p; + + while (true) + { + matched_p = ecma_regexp_match (&re_ctx, bc_start_p, current_p); + + if (matched_p != NULL) + { + if (ECMA_RE_STACK_LIMIT_REACHED (matched_p)) + { + result = ecma_raise_range_error (ECMA_ERR_STACK_LIMIT_EXCEEDED); + goto cleanup_builder; + } + + const lit_utf8_size_t remaining_size = (lit_utf8_size_t) (current_p - last_append_p); + ecma_stringbuilder_append_raw (&(ctx_p->builder), last_append_p, remaining_size); + + if (ctx_p->replace_str_p != NULL) + { + ctx_p->matched_p = current_p; + const ecma_regexp_capture_t *const global_capture_p = re_ctx.captures_p; + ctx_p->matched_size = (lit_utf8_size_t) (global_capture_p->end_p - global_capture_p->begin_p); + ctx_p->match_byte_pos = (lit_utf8_size_t) (current_p - re_ctx.input_start_p); + + ecma_builtin_replace_substitute (ctx_p); + } + else + { + ecma_collection_t *arguments_p = ecma_new_collection (); + + for (uint32_t i = 0; i < re_ctx.captures_count; i++) + { + ecma_value_t capture = ecma_regexp_get_capture_value (re_ctx.captures_p + i); + ecma_collection_push_back (arguments_p, capture); + } + + ecma_collection_push_back (arguments_p, ecma_make_length_value (index)); + ecma_ref_ecma_string (string_p); + ecma_collection_push_back (arguments_p, ecma_make_string_value (string_p)); + ecma_object_t *function_p = ecma_get_object_from_value (replace_arg); + + result = + ecma_op_function_call (function_p, ECMA_VALUE_UNDEFINED, arguments_p->buffer_p, arguments_p->item_count); + + ecma_collection_free (arguments_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + + /* 16.m.v */ + ecma_string_t *const replace_result_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (replace_result_p == NULL) + { + result = ECMA_VALUE_ERROR; + goto cleanup_builder; + } + + ecma_stringbuilder_append (&(ctx_p->builder), replace_result_p); + ecma_deref_ecma_string (replace_result_p); + } + + const ecma_regexp_capture_t *global_capture_p = re_ctx.captures_p; + last_append_p = global_capture_p->end_p; + + const lit_utf8_size_t matched_size = (lit_utf8_size_t) (global_capture_p->end_p - global_capture_p->begin_p); + + const bool is_ascii = (string_flags & ECMA_STRING_FLAG_IS_ASCII) != 0; + index += is_ascii ? matched_size : lit_utf8_string_length (current_p, matched_size); + + if (!(ctx_p->flags & RE_FLAG_GLOBAL)) + { + if (JERRY_UNLIKELY ((re_ctx.flags & RE_FLAG_STICKY) != 0)) + { + ecma_value_t index_value = ecma_make_length_value (index); + result = ecma_op_object_put ((ecma_object_t *) re_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + index_value, + true); + + ecma_free_value (index_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + } + + break; + } + + if (matched_size > 0) + { + current_p = last_append_p; + continue; + } + } + else if (JERRY_UNLIKELY ((re_ctx.flags & RE_FLAG_STICKY) != 0)) + { + result = ecma_op_object_put ((ecma_object_t *) re_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + true); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + + break; + } + + if (current_p >= string_end_p) + { + break; + } + + if ((ctx_p->flags & RE_FLAG_UNICODE) != 0) + { + index++; + const lit_code_point_t cp = ecma_regexp_unicode_advance (¤t_p, string_end_p); + + if (cp > LIT_UTF16_CODE_UNIT_MAX) + { + index++; + } + + continue; + } + + index++; + lit_utf8_incr (¤t_p); + } + + trailing_size = (lit_utf8_size_t) (string_end_p - last_append_p); + ecma_stringbuilder_append_raw (&(ctx_p->builder), last_append_p, trailing_size); + + result = ecma_make_string_value (ecma_stringbuilder_finalize (&(ctx_p->builder))); + goto cleanup_context; + +cleanup_builder: + ecma_stringbuilder_destroy (&(ctx_p->builder)); + +cleanup_context: + ecma_regexp_cleanup_context (&re_ctx); + ecma_bytecode_deref ((ecma_compiled_code_t *) bc_p); + + if (string_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) ctx_p->string_p, ctx_p->string_size); + } + + return result; +} /* ecma_regexp_replace_helper_fast */ + +/** + * Helper function for RegExp based replacing + * + * See also: + * String.prototype.replace + * RegExp.prototype[@@replace] + * + * @return result string of the replacement, if successful + * error value, otherwise + */ +ecma_value_t +ecma_regexp_replace_helper (ecma_value_t this_arg, /**< this argument */ + ecma_value_t string_arg, /**< source string */ + ecma_value_t replace_arg) /**< replace string */ +{ + /* 2. */ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + lit_utf8_size_t index; + uint8_t string_flags; + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); + ecma_replace_context_t replace_ctx; + ecma_collection_t *results_p; + lit_utf8_size_t string_length; + lit_utf8_byte_t *source_position_p; + lit_utf8_byte_t *string_end_p; + + replace_ctx.flags = RE_FLAG_EMPTY; + + /* 3. */ + ecma_string_t *string_p = ecma_op_to_string (string_arg); + if (string_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ECMA_VALUE_ERROR; + + /* 6. */ + replace_ctx.replace_str_p = NULL; + if (!ecma_op_is_callable (replace_arg)) + { + replace_ctx.replace_str_p = ecma_op_to_string (replace_arg); + + if (replace_ctx.replace_str_p == NULL) + { + goto cleanup_string; + } + } + + /* 8 */ + result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_GLOBAL); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_replace; + } + + if (ecma_op_to_boolean (result)) + { + replace_ctx.flags |= RE_FLAG_GLOBAL; + } + + ecma_free_value (result); + + string_length = ecma_string_get_length (string_p); + + /* 10. */ + if (replace_ctx.flags & RE_FLAG_GLOBAL) + { + result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_UNICODE); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_replace; + } + + if (ecma_op_to_boolean (result)) + { + replace_ctx.flags |= RE_FLAG_UNICODE; + } + + ecma_free_value (result); + + result = ecma_op_object_put (this_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + true); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_replace; + } + + JERRY_ASSERT (ecma_is_value_boolean (result)); + } + + result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_EXEC); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_replace; + } + + /* Check for fast path. */ + if (ecma_op_is_callable (result)) + { + ecma_extended_object_t *function_p = (ecma_extended_object_t *) ecma_get_object_from_value (result); + if (ecma_object_class_is (this_obj_p, ECMA_OBJECT_CLASS_REGEXP) && ecma_builtin_is_regexp_exec (function_p)) + { + ecma_deref_object ((ecma_object_t *) function_p); + + result = + ecma_regexp_replace_helper_fast (&replace_ctx, (ecma_extended_object_t *) this_obj_p, string_p, replace_arg); + + goto cleanup_replace; + } + } + + results_p = ecma_new_collection (); + + while (true) + { + /* 13.a */ + if (ecma_op_is_callable (result)) + { + ecma_object_t *const function_p = ecma_get_object_from_value (result); + + ecma_value_t arguments[] = { ecma_make_string_value (string_p) }; + result = ecma_op_function_call (function_p, this_arg, arguments, 1); + + ecma_deref_object (function_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + + if (!ecma_is_value_object (result) && !ecma_is_value_null (result)) + { + ecma_free_value (result); + result = ecma_raise_type_error (ECMA_ERR_RETURN_VALUE_OF_EXEC_MUST_BE_AN_OBJECT_OR_NULL); + goto cleanup_results; + } + } + else + { + ecma_free_value (result); + + if (!ecma_object_class_is (this_obj_p, ECMA_OBJECT_CLASS_REGEXP)) + { + result = ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP_OBJECT); + goto cleanup_results; + } + + result = ecma_regexp_exec_helper (this_obj_p, string_p); + } + + /* 13.c */ + if (ecma_is_value_null (result)) + { + break; + } + + /* 13.d.i */ + ecma_collection_push_back (results_p, result); + + if ((replace_ctx.flags & RE_FLAG_GLOBAL) == 0) + { + break; + } + + /* 13.d.iii.1 */ + result = ecma_op_object_get_by_index (ecma_get_object_from_value (result), 0); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + + ecma_string_t *match_str_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (match_str_p == NULL) + { + result = ECMA_VALUE_ERROR; + goto cleanup_results; + } + + const bool is_empty = ecma_string_is_empty (match_str_p); + ecma_deref_ecma_string (match_str_p); + + /* 13.d.iii.3 */ + if (is_empty) + { + result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + + ecma_value_t last_index = result; + + ecma_length_t index; + result = ecma_op_to_length (last_index, &index); + ecma_free_value (last_index); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + + index = ecma_op_advance_string_index (string_p, index, (replace_ctx.flags & RE_FLAG_UNICODE) != 0); + last_index = ecma_make_length_value (index); + + /* 10.d.iii.3.c */ + result = ecma_op_object_put (this_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), last_index, true); + + ecma_free_value (last_index); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + + JERRY_ASSERT (ecma_is_value_boolean (result)); + } + + result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_EXEC); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + } + + string_flags = ECMA_STRING_FLAG_IS_ASCII; + replace_ctx.string_p = ecma_string_get_chars (string_p, &(replace_ctx.string_size), NULL, NULL, &string_flags); + + /* 14. */ + replace_ctx.builder = ecma_stringbuilder_create (); + replace_ctx.matched_p = NULL; + replace_ctx.capture_count = 0; + index = 0; + + /* 15. */ + source_position_p = (lit_utf8_byte_t*) replace_ctx.string_p; + string_end_p = (lit_utf8_byte_t*) replace_ctx.string_p + replace_ctx.string_size; + + /* 16. */ + for (ecma_value_t *current_p = results_p->buffer_p; current_p < results_p->buffer_p + results_p->item_count; + current_p++) + { + /* 16.a */ + ecma_object_t *current_object_p = ecma_get_object_from_value (*current_p); + + ecma_length_t capture_count; + result = ecma_op_object_get_length (current_object_p, &capture_count); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + + /* 16.c */ + capture_count = (capture_count > 0) ? capture_count - 1 : capture_count; + + /* 16.d */ + result = ecma_op_object_get_by_index (current_object_p, 0); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + + ecma_string_t *matched_str_p = ecma_op_to_string (result); + ecma_free_value (result); + + /* 16.e */ + if (matched_str_p == NULL) + { + result = ECMA_VALUE_ERROR; + goto cleanup_builder; + } + + /* 16.g */ + result = ecma_op_object_get_by_magic_id (current_object_p, LIT_MAGIC_STRING_INDEX); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_ecma_string (matched_str_p); + goto cleanup_builder; + } + + const ecma_value_t index_value = result; + + ecma_number_t position_num; + result = ecma_op_to_integer (index_value, &position_num); + ecma_free_value (index_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_ecma_string (matched_str_p); + goto cleanup_builder; + } + + /* 16.i */ + lit_utf8_size_t position = JERRY_MIN ((lit_utf8_size_t) JERRY_MAX (position_num, 0.0f), string_length); + + /* 16.k */ + ecma_collection_t *arguments_p = ecma_new_collection (); + ecma_collection_push_back (arguments_p, ecma_make_string_value (matched_str_p)); + + /* 16.j, l */ + ecma_length_t n = 1; + while (n <= capture_count) + { + result = ecma_op_object_get_by_index (current_object_p, n); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_collection_free (arguments_p); + goto cleanup_builder; + } + + /* 16.l.iii */ + if (!ecma_is_value_undefined (result)) + { + ecma_string_t *capture_str_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (capture_str_p == NULL) + { + ecma_collection_free (arguments_p); + result = ECMA_VALUE_ERROR; + goto cleanup_builder; + } + + result = ecma_make_string_value (capture_str_p); + } + + /* 16.l.iv */ + ecma_collection_push_back (arguments_p, result); + n++; + } + + const bool should_replace = (position >= index); + /* 16.p */ + if (should_replace) + { + const lit_utf8_byte_t *match_position_p; + const lit_utf8_size_t matched_str_size = ecma_string_get_size (matched_str_p); + const lit_utf8_size_t matched_str_length = ecma_string_get_length (matched_str_p); + + if (string_flags & ECMA_STRING_FLAG_IS_ASCII) + { + match_position_p = replace_ctx.string_p + position; + } + else + { + match_position_p = source_position_p; + lit_utf8_size_t distance = position - index; + while (distance--) + { + lit_utf8_incr (&match_position_p); + } + } + + ecma_stringbuilder_append_raw (&replace_ctx.builder, + source_position_p, + (lit_utf8_size_t) (match_position_p - source_position_p)); + replace_ctx.match_byte_pos = (lit_utf8_size_t) (match_position_p - replace_ctx.string_p); + + if ((string_flags & ECMA_STRING_FLAG_IS_ASCII) && matched_str_size == matched_str_length) + { + source_position_p = (lit_utf8_byte_t*) JERRY_MIN (match_position_p + matched_str_size, string_end_p); + } + else + { + lit_utf8_size_t code_unit_count = matched_str_length; + + while (code_unit_count-- > 0 && JERRY_LIKELY (match_position_p < string_end_p)) + { + lit_utf8_incr (&match_position_p); + } + + source_position_p = (lit_utf8_byte_t*) match_position_p; + } + + index = JERRY_MIN (position + matched_str_length, string_length); + } + + /* 16.m */ + if (replace_ctx.replace_str_p == NULL) + { + /* 16.m.i-ii. + * arguments_p already contains <> */ + + /* 16.m.iii */ + ecma_collection_push_back (arguments_p, ecma_make_uint32_value (position)); + ecma_ref_ecma_string (string_p); + ecma_collection_push_back (arguments_p, ecma_make_string_value (string_p)); + + result = ecma_op_function_call (ecma_get_object_from_value (replace_arg), + ECMA_VALUE_UNDEFINED, + arguments_p->buffer_p, + arguments_p->item_count); + + ecma_collection_free (arguments_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + + /* 16.m.v */ + ecma_string_t *const replace_result_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (replace_result_p == NULL) + { + result = ECMA_VALUE_ERROR; + goto cleanup_builder; + } + + /* 16.m/p */ + if (should_replace) + { + ecma_stringbuilder_append (&replace_ctx.builder, replace_result_p); + } + + ecma_deref_ecma_string (replace_result_p); + } + else + { + /* 16.n/p */ + if (should_replace) + { + replace_ctx.u.collection_p = arguments_p; + ecma_builtin_replace_substitute (&replace_ctx); + } + + ecma_collection_free (arguments_p); + } + } + + /* 18. */ + JERRY_ASSERT (index <= string_length); + ecma_stringbuilder_append_raw (&(replace_ctx.builder), + source_position_p, + (lit_utf8_size_t) (string_end_p - source_position_p)); + + result = ecma_make_string_value (ecma_stringbuilder_finalize (&replace_ctx.builder)); + goto cleanup_chars; + +cleanup_builder: + ecma_stringbuilder_destroy (&replace_ctx.builder); + +cleanup_chars: + if (string_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) replace_ctx.string_p, replace_ctx.string_size); + } + +cleanup_results: + ecma_collection_free (results_p); + +cleanup_replace: + if (replace_ctx.replace_str_p != NULL) + { + ecma_deref_ecma_string (replace_ctx.replace_str_p); + } + +cleanup_string: + ecma_deref_ecma_string (string_p); + + return result; +} /* ecma_regexp_replace_helper */ + +/** + * Helper function for RegExp based matching + * + * See also: + * String.prototype.match + * RegExp.prototype[@@match] + * + * @return ecma_value_t + */ +ecma_value_t +ecma_regexp_match_helper (ecma_value_t this_arg, /**< this argument */ + ecma_value_t string_arg) /**< source string */ +{ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_string_t *str_p = ecma_op_to_string (string_arg); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); + + ecma_value_t global_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_GLOBAL); + + if (ECMA_IS_VALUE_ERROR (global_value)) + { + ecma_deref_ecma_string (str_p); + return global_value; + } + + bool global = ecma_op_to_boolean (global_value); + + ecma_free_value (global_value); + + if (!global) + { + ecma_value_t result = ecma_op_regexp_exec (this_arg, str_p); + ecma_deref_ecma_string (str_p); + return result; + } + + ecma_value_t full_unicode_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_UNICODE); + + if (ECMA_IS_VALUE_ERROR (full_unicode_value)) + { + ecma_deref_ecma_string (str_p); + return full_unicode_value; + } + + bool full_unicode = ecma_op_to_boolean (full_unicode_value); + + ecma_free_value (full_unicode_value); + + ecma_value_t set_status = + ecma_op_object_put (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), ecma_make_uint32_value (0), true); + + if (ECMA_IS_VALUE_ERROR (set_status)) + { + ecma_deref_ecma_string (str_p); + return set_status; + } + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + ecma_object_t *result_array_p = ecma_op_new_array_object (0); + uint32_t n = 0; + + while (true) + { + ecma_value_t result_value = ecma_op_regexp_exec (this_arg, str_p); + + if (ECMA_IS_VALUE_ERROR (result_value)) + { + goto result_cleanup; + } + + if (ecma_is_value_null (result_value)) + { + if (n == 0) + { + ret_value = ECMA_VALUE_NULL; + goto result_cleanup; + } + + ecma_deref_ecma_string (str_p); + return ecma_make_object_value (result_array_p); + } + + ecma_object_t *result_value_p = ecma_get_object_from_value (result_value); + ecma_value_t match_value = ecma_op_object_get_by_index (result_value_p, 0); + + ecma_deref_object (result_value_p); + + if (ECMA_IS_VALUE_ERROR (match_value)) + { + goto result_cleanup; + } + + ecma_string_t *match_str_p = ecma_op_to_string (match_value); + ecma_free_value (match_value); + + if (JERRY_UNLIKELY (match_str_p == NULL)) + { + goto result_cleanup; + } + + ecma_value_t new_prop = ecma_builtin_helper_def_prop_by_index (result_array_p, + n, + ecma_make_string_value (match_str_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_prop)); + + const bool is_match_empty = ecma_string_is_empty (match_str_p); + ecma_deref_ecma_string (match_str_p); + + if (is_match_empty) + { + ecma_value_t last_index = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); + + if (ECMA_IS_VALUE_ERROR (last_index)) + { + goto result_cleanup; + } + + ecma_length_t index; + ecma_value_t length_value = ecma_op_to_length (last_index, &index); + + ecma_free_value (last_index); + + if (ECMA_IS_VALUE_ERROR (length_value)) + { + goto result_cleanup; + } + + index = ecma_op_advance_string_index (str_p, index, full_unicode); + + last_index = ecma_make_length_value (index); + ecma_value_t next_set_status = + ecma_op_object_put (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), last_index, true); + + ecma_free_value (last_index); + + if (ECMA_IS_VALUE_ERROR (next_set_status)) + { + goto result_cleanup; + } + } + + n++; + } + +result_cleanup: + ecma_deref_ecma_string (str_p); + ecma_deref_object (result_array_p); + return ret_value; +} /* ecma_regexp_match_helper */ + +/** + * RegExpExec operation + * + * See also: + * ECMA-262 v6.0, 21.2.5.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_regexp_exec (ecma_value_t this_arg, /**< this argument */ + ecma_string_t *str_p) /**< input string */ +{ + ecma_object_t *arg_obj_p = ecma_get_object_from_value (this_arg); + + ecma_value_t exec = ecma_op_object_get_by_magic_id (arg_obj_p, LIT_MAGIC_STRING_EXEC); + + if (ECMA_IS_VALUE_ERROR (exec)) + { + return exec; + } + + if (ecma_op_is_callable (exec)) + { + ecma_object_t *function_p = ecma_get_object_from_value (exec); + ecma_value_t arguments[] = { ecma_make_string_value (str_p) }; + + ecma_value_t result = ecma_op_function_call (function_p, this_arg, arguments, 1); + + ecma_deref_object (function_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (!ecma_is_value_object (result) && !ecma_is_value_null (result)) + { + ecma_free_value (result); + return ecma_raise_type_error (ECMA_ERR_RETURN_VALUE_OF_EXEC_MUST_BE_AN_OBJECT_OR_NULL); + } + + return result; + } + else + { + ecma_free_value (exec); + } + + if (!ecma_object_is_regexp_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP); + } + + return ecma_regexp_exec_helper (arg_obj_p, str_p); +} /* ecma_op_regexp_exec */ + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.h new file mode 100644 index 00000000..89815897 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.h @@ -0,0 +1,191 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_REGEXP_OBJECT_H +#define ECMA_REGEXP_OBJECT_H + +#include "ecma-globals.h" + +#include "re-compiler.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaregexpobject ECMA RegExp object related routines + * @{ + */ + +/** + * RegExp flags + * Note: + * This enum has to be kept in sync with jerry_regexp_flags_t. + */ +typedef enum +{ + RE_FLAG_EMPTY = 0u, /* Empty RegExp flags */ + RE_FLAG_GLOBAL = (1u << 1), /**< ECMA-262 v5, 15.10.7.2 */ + RE_FLAG_IGNORE_CASE = (1u << 2), /**< ECMA-262 v5, 15.10.7.3 */ + RE_FLAG_MULTILINE = (1u << 3), /**< ECMA-262 v5, 15.10.7.4 */ + RE_FLAG_STICKY = (1u << 4), /**< ECMA-262 v6, 21.2.5.12 */ + RE_FLAG_UNICODE = (1u << 5), /**< ECMA-262 v6, 21.2.5.15 */ + RE_FLAG_DOTALL = (1u << 6) /**< ECMA-262 v9, 21.2.5.3 */ + + /* Bits from bit 13 is reserved for function types (see CBC_FUNCTION_TYPE_SHIFT). */ +} ecma_regexp_flags_t; + +/** + * Class escapes + */ +typedef enum +{ + RE_ESCAPE__START, /**< escapes start */ + RE_ESCAPE_DIGIT = RE_ESCAPE__START, /**< digit */ + RE_ESCAPE_NOT_DIGIT, /**< not digit */ + RE_ESCAPE_WORD_CHAR, /**< word char */ + RE_ESCAPE_NOT_WORD_CHAR, /**< not word char */ + RE_ESCAPE_WHITESPACE, /**< whitespace */ + RE_ESCAPE_NOT_WHITESPACE, /**< not whitespace */ + RE_ESCAPE__COUNT, /**< escape count */ +} ecma_class_escape_t; + +/** + * Character class flags escape count mask size. + */ +#define RE_CLASS_ESCAPE_COUNT_MASK_SIZE (3u) + +/** + * Character class flags escape count mask. + */ +#define RE_CLASS_ESCAPE_COUNT_MASK ((1 << RE_CLASS_ESCAPE_COUNT_MASK_SIZE) - 1u) + +/** + * Character class flags that are present in the upper bits of the class flags byte, while the 3 least significant bits + * hold a value that contains the number of class escapes present in the character class. + */ +typedef enum +{ + RE_CLASS_HAS_CHARS = (1 << 5), /**< contains individual characters */ + RE_CLASS_HAS_RANGES = (1 << 6), /**< contains character ranges */ + RE_CLASS_INVERT = (1 << 7), /**< inverted */ +} ecma_char_class_flags_t; + +/** + * Structure for matching capturing groups and storing their result + */ +typedef struct +{ + const lit_utf8_byte_t *begin_p; /**< capture start pointer */ + const lit_utf8_byte_t *end_p; /**< capture end pointer */ + const uint8_t *bc_p; /**< group bytecode pointer */ + uint32_t iterator; /**< iteration counter */ + uint32_t subcapture_count; /**< number of nested capturing groups */ +} ecma_regexp_capture_t; + +/** + * Structure for matching non-capturing groups + */ +typedef struct +{ + const lit_utf8_byte_t *begin_p; /**< substring start pointer */ + const uint8_t *bc_p; /**< group bytecode pointer */ + uint32_t iterator; /**< iteration counter */ + uint32_t subcapture_start; /**< first nested capturing group index */ + uint32_t subcapture_count; /**< number of nested capturing groups */ +} ecma_regexp_non_capture_t; + +/** + * Check if an ecma_regexp_capture_t contains a defined capture + */ +#define ECMA_RE_IS_CAPTURE_DEFINED(c) ((c)->begin_p != NULL) + +ecma_value_t ecma_regexp_get_capture_value (const ecma_regexp_capture_t *const capture_p); + +#if (JERRY_STACK_LIMIT != 0) +/** + * Value used ase result when stack limit is reached + */ +#define ECMA_RE_OUT_OF_STACK ((const lit_utf8_byte_t *) UINTPTR_MAX) + +/** + * Checks if the stack limit has been reached during regexp matching + */ +#define ECMA_RE_STACK_LIMIT_REACHED(p) (JERRY_UNLIKELY (p == ECMA_RE_OUT_OF_STACK)) +#else /* JERRY_STACK_LIMIT == 0 */ +#define ECMA_RE_STACK_LIMIT_REACHED(p) (false) +#endif /* JERRY_STACK_LIMIT != 0 */ + +/** + * Offset applied to qmax when encoded into the bytecode. + * + * It's common for qmax to be Infinity, which is represented a UINT32_MAX. By applying the offset we are able to store + * it in a single byte az zero. + */ +#define RE_QMAX_OFFSET 1 + +/** + * RegExp executor context + */ +typedef struct +{ + const lit_utf8_byte_t *input_start_p; /**< start of input string */ + const lit_utf8_byte_t *input_end_p; /**< end of input string */ + uint32_t captures_count; /**< number of capture groups */ + uint32_t non_captures_count; /**< number of non-capture groups */ + ecma_regexp_capture_t *captures_p; /**< capturing groups */ + ecma_regexp_non_capture_t *non_captures_p; /**< non-capturing groups */ + uint16_t flags; /**< RegExp flags */ + uint8_t char_size; /**< size of encoded characters */ +} ecma_regexp_ctx_t; + +/** + * RegExpStringIterator object internal slots + * + * See also: + * ECMA-262 v11, 21.2.7.2 + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object part */ + ecma_value_t iterating_regexp; /**< [[IteratingRegExp]] internal slot */ + ecma_value_t iterated_string; /**< [[IteratedString]] internal slot */ +} ecma_regexp_string_iterator_t; + +lit_code_point_t ecma_regexp_unicode_advance (const lit_utf8_byte_t **str_p, const lit_utf8_byte_t *end_p); +ecma_object_t *ecma_op_regexp_alloc (ecma_object_t *new_target_obj_p); +ecma_value_t ecma_regexp_exec_helper (ecma_object_t *regexp_object_p, ecma_string_t *input_string_p); +ecma_string_t *ecma_regexp_read_pattern_str_helper (ecma_value_t pattern_arg); +lit_code_point_t ecma_regexp_canonicalize_char (lit_code_point_t ch, bool unicode); +ecma_value_t ecma_regexp_parse_flags (ecma_string_t *flags_str_p, uint16_t *flags_p); +void ecma_regexp_create_and_initialize_props (ecma_object_t *re_object_p, ecma_string_t *source_p, uint16_t flags); +ecma_value_t ecma_regexp_replace_helper (ecma_value_t this_arg, ecma_value_t string_arg, ecma_value_t replace_arg); +ecma_value_t ecma_regexp_search_helper (ecma_value_t regexp_arg, ecma_value_t string_arg); +ecma_value_t ecma_regexp_split_helper (ecma_value_t this_arg, ecma_value_t string_arg, ecma_value_t limit_arg); +ecma_value_t ecma_regexp_match_helper (ecma_value_t this_arg, ecma_value_t string_arg); + +ecma_value_t ecma_op_regexp_exec (ecma_value_t this_arg, ecma_string_t *str_p); + +ecma_value_t ecma_op_create_regexp_from_bytecode (ecma_object_t *regexp_obj_p, re_compiled_code_t *bc_p); +ecma_value_t +ecma_op_create_regexp_from_pattern (ecma_object_t *regexp_obj_p, ecma_value_t pattern_value, ecma_value_t flags_value); +ecma_value_t ecma_op_create_regexp_with_flags (ecma_object_t *regexp_obj_p, ecma_value_t pattern_value, uint16_t flags); +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !ECMA_REGEXP_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.cpp new file mode 100644 index 00000000..658af2de --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.cpp @@ -0,0 +1,161 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-shared-arraybuffer-object.h" + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmasharedarraybufferobject ECMA SharedArrayBuffer object related routines + * @{ + */ + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +/** + * Creating SharedArrayBuffer objects based on the array length + * + * @return new SharedArrayBuffer object + */ +ecma_object_t * +ecma_shared_arraybuffer_new_object (uint32_t length) /**< length of the SharedArrayBuffer */ +{ + if (length > 0) + { + return ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, length); + } + + return ecma_arraybuffer_create_object (ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, length); +} /* ecma_shared_arraybuffer_new_object */ + +/** + * SharedArrayBuffer object creation operation. + * + * See also: ES11 24.1.1.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_shared_arraybuffer_object (const ecma_value_t *arguments_list_p, /**< list of arguments that + * are passed to String constructor */ + uint32_t arguments_list_len) /**< length of the arguments' list */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t length_num = 0; + + if (arguments_list_len > 0) + { + if (ecma_is_value_number (arguments_list_p[0])) + { + length_num = ecma_get_number_from_value (arguments_list_p[0]); + } + else + { + ecma_value_t to_number_value = ecma_op_to_number (arguments_list_p[0], &length_num); + + if (ECMA_IS_VALUE_ERROR (to_number_value)) + { + ecma_deref_object (proto_p); + return to_number_value; + } + } + + if (ecma_number_is_nan (length_num)) + { + length_num = 0; + } + + const uint32_t maximum_size_in_byte = UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1; + + if (length_num <= -1.0 || length_num > (ecma_number_t) maximum_size_in_byte + 0.5) + { + ecma_deref_object (proto_p); + return ecma_raise_range_error (ECMA_ERR_INVALID_SHARED_ARRAYBUFFER_LENGTH); + } + } + + uint32_t length_uint32 = ecma_number_to_uint32 (length_num); + ecma_object_t *shared_array_buffer = ecma_shared_arraybuffer_new_object (length_uint32); + ECMA_SET_NON_NULL_POINTER (shared_array_buffer->u2.prototype_cp, proto_p); + ecma_deref_object (proto_p); + + return ecma_make_object_value (shared_array_buffer); +} /* ecma_op_create_shared_arraybuffer_object */ + +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + +/** + * Helper function: check if the target is SharedArrayBuffer + * + * See also: ES11 24.1.1.4 + * + * @return true - if value is a SharedArrayBuffer object + * false - otherwise + */ +bool +ecma_is_shared_arraybuffer (ecma_value_t target) /**< the target value */ +{ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + return (ecma_is_value_object (target) + && ecma_object_class_is (ecma_get_object_from_value (target), ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER)); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_UNUSED (target); + return false; +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +} /* ecma_is_shared_arraybuffer */ + +/** + * Helper function: check if the target is SharedArrayBuffer Object + * + * @return true - if value is a SharedArrayBuffer object + * false - otherwise + */ +bool +ecma_object_is_shared_arraybuffer (ecma_object_t *object_p) /**< the target object */ +{ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + return ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_UNUSED (object_p); + return false; +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +} /* ecma_object_is_shared_arraybuffer */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.h new file mode 100644 index 00000000..65b480ed --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.h @@ -0,0 +1,45 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_SHARED_ARRAYBUFFER_OBJECT_H +#define ECMA_SHARED_ARRAYBUFFER_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmasharedarraybufferobject ECMA SharedArrayBuffer object related routines + * @{ + */ + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +ecma_value_t ecma_op_create_shared_arraybuffer_object (const ecma_value_t *, uint32_t); + +/** + * Helper functions for SharedArrayBuffer. + */ +ecma_object_t *ecma_shared_arraybuffer_new_object (uint32_t lengh); +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +bool ecma_is_shared_arraybuffer (ecma_value_t val); +bool ecma_object_is_shared_arraybuffer (ecma_object_t *val); + +/** + * @} + * @} + */ + +#endif /* !ECMA_SHARED_ARRAYBUFFER_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.cpp new file mode 100644 index 00000000..95b78c9a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.cpp @@ -0,0 +1,140 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-string-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmastringobject ECMA String object related routines + * @{ + */ + +/** + * String object creation operation. + * + * See also: ECMA-262 v5, 15.5.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of arguments that + are passed to String constructor */ + uint32_t arguments_list_len) /**< length of the arguments' list */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t prim_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + + if (arguments_list_len > 0) + { + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + prim_value = ecma_make_string_value (str_p); + } + + ecma_builtin_id_t proto_id; +#if JERRY_BUILTIN_STRING + proto_id = ECMA_BUILTIN_ID_STRING_PROTOTYPE; +#else /* !JERRY_BUILTIN_STRING */ + proto_id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; +#endif /* JERRY_BUILTIN_STRING */ + ecma_object_t *prototype_obj_p = ecma_builtin_get (proto_id); + + ecma_object_t *new_target = JERRY_CONTEXT (current_new_target_p); + if (new_target) + { + prototype_obj_p = ecma_op_get_prototype_from_constructor (new_target, proto_id); + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + } + + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_STRING; + ext_object_p->u.cls.u3.value = prim_value; + + if (new_target) + { + ecma_deref_object (prototype_obj_p); + } + + return ecma_make_object_value (object_p); +} /* ecma_op_create_string_object */ + +/** + * List names of a String object's lazy instantiated properties + */ +void +ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + JERRY_ASSERT (ecma_get_object_base_type (obj_p) == ECMA_OBJECT_BASE_TYPE_CLASS); + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + JERRY_ASSERT (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_STRING); + + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (ext_object_p->u.cls.u3.value); + + lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); + + for (lit_utf8_size_t i = 0; i < length; i++) + { + ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); + + /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */ + ecma_collection_push_back (prop_names_p, ecma_make_string_value (name_p)); + } + + prop_counter_p->array_index_named_props += length; + } + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } +} /* ecma_op_string_list_lazy_property_names */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.h new file mode 100644 index 00000000..0ebb2c12 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.h @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_STRING_OBJECT_H +#define ECMA_STRING_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmastringobject ECMA String object related routines + * @{ + */ + +ecma_value_t ecma_op_create_string_object (const ecma_value_t *arguments_list_p, uint32_t arguments_list_len); + +void ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +/** + * @} + * @} + */ + +#endif /* !ECMA_STRING_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.cpp new file mode 100644 index 00000000..adf84367 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.cpp @@ -0,0 +1,177 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-symbol-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "lit-char-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmasymbolobject ECMA Symbol object related routines + * @{ + */ + +/** + * Symbol creation operation. + * + * See also: ECMA-262 v6, 6.1.5.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_symbol (const ecma_value_t *arguments_list_p, /**< list of arguments */ + uint32_t arguments_list_len) /**< length of the arguments' list */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t string_desc; + + /* 1-3. */ + if (arguments_list_len == 0 || ecma_is_value_undefined (arguments_list_p[0])) + { + string_desc = ECMA_VALUE_UNDEFINED; + } + else + { + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + + /* 4. */ + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + string_desc = ecma_make_string_value (str_p); + } + + /* 5. */ + return ecma_make_symbol_value (ecma_new_symbol_from_descriptor_string (string_desc)); +} /* ecma_op_create_symbol */ + +/** + * Symbol object creation operation. + * + * See also: ECMA-262 v6, 19.4.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_symbol_object (const ecma_value_t value) /**< symbol value */ +{ + JERRY_ASSERT (ecma_is_value_symbol (value)); + + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE); + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_SYMBOL; + ext_object_p->u.cls.u3.value = ecma_copy_value (value); + + return ecma_make_object_value (object_p); +} /* ecma_op_create_symbol_object */ + +/** + * Get the symbol descriptor ecma-string from an ecma-symbol + * + * @return pointer to ecma-string descriptor + */ +ecma_value_t +ecma_get_symbol_description (ecma_string_t *symbol_p) /**< ecma-symbol */ +{ + JERRY_ASSERT (symbol_p != NULL); + JERRY_ASSERT (ecma_prop_name_is_symbol (symbol_p)); + + return ((ecma_extended_string_t *) symbol_p)->u.symbol_descriptor; +} /* ecma_get_symbol_description */ + +/** + * Get the descriptive string of the Symbol. + * + * See also: ECMA-262 v6, 19.4.3.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_get_symbol_descriptive_string (ecma_value_t symbol_value) /**< symbol to stringify */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_symbol (symbol_value)); + + /* 2 - 3. */ + ecma_string_t *symbol_p = ecma_get_symbol_from_value (symbol_value); + ecma_value_t string_desc = ecma_get_symbol_description (symbol_p); + ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) ("Symbol("), 7); + + if (!ecma_is_value_undefined (string_desc)) + { + ecma_string_t *string_desc_p = ecma_get_string_from_value (string_desc); + ecma_stringbuilder_append (&builder, string_desc_p); + } + + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_RIGHT_PAREN); + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_get_symbol_descriptive_string */ + +/** + * thisSymbolValue abstract operation + * + * See also: + * ECMA-262 v11, 19.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_symbol_this_value (ecma_value_t this_arg) /**< this argument value */ +{ + /* 1. */ + if (ecma_is_value_symbol (this_arg)) + { + return this_arg; + } + + /* 2. */ + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_SYMBOL)) + { + return ((ecma_extended_object_t *) object_p)->u.cls.u3.value; + } + } + + /* 3. */ + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_SYMBOL); +} /* ecma_symbol_this_value */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.h new file mode 100644 index 00000000..4f27e02a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.h @@ -0,0 +1,45 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_SYMBOL_H +#define ECMA_SYMBOL_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmasymbolobject ECMA Symbol object related routines + * @{ + */ + +ecma_value_t ecma_op_create_symbol (const ecma_value_t *arguments_list_p, uint32_t arguments_list_len); + +ecma_value_t ecma_op_create_symbol_object (const ecma_value_t value); + +bool ecma_prop_name_is_symbol (ecma_string_t *string_p); + +ecma_value_t ecma_get_symbol_description (ecma_string_t *symbol_p); + +ecma_value_t ecma_symbol_this_value (ecma_value_t this_arg); + +ecma_value_t ecma_get_symbol_descriptive_string (ecma_value_t symbol_value); + +/** + * @} + * @} + */ + +#endif /* !ECMA_SYMBOL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.cpp new file mode 100644 index 00000000..d3500350 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.cpp @@ -0,0 +1,2119 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-typedarray-object.h" + +#include + +#include "ecma-arraybuffer-object.h" +#include "ecma-big-uint.h" +#include "ecma-bigint.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-shared-arraybuffer-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmatypedarrayobject ECMA TypedArray object related routines + * @{ + */ + +/** + * Read and copy a number from a given buffer to a value. + **/ +#define ECMA_TYPEDARRAY_GET_ELEMENT(src_p, num, type) \ + do \ + { \ + if (JERRY_LIKELY ((((uintptr_t) (src_p)) & (sizeof (type) - 1)) == 0)) \ + { \ + num = *(type *) ((void *) src_p); \ + } \ + else \ + { \ + memcpy (&num, (void *) src_p, sizeof (type)); \ + } \ + } while (0) + +/** + * Copy a number from a value to the given buffer + **/ +#define ECMA_TYPEDARRAY_SET_ELEMENT(src_p, num, type) \ + do \ + { \ + if (JERRY_LIKELY ((((uintptr_t) (src_p)) & (sizeof (type) - 1)) == 0)) \ + { \ + *(type *) ((void *) src_p) = num; \ + } \ + else \ + { \ + memcpy ((void *) src_p, &num, sizeof (type)); \ + } \ + } while (0) + +/** + * Read an int8_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_int8_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + int8_t num = (int8_t) *src; + return ecma_make_integer_value (num); +} /* ecma_typedarray_get_int8_element */ + +/** + * Read an uint8_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_uint8_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + uint8_t num = (uint8_t) *src; + return ecma_make_integer_value (num); +} /* ecma_typedarray_get_uint8_element */ + +/** + * Read an int16_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_int16_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + int16_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, int16_t); + return ecma_make_integer_value (num); +} /* ecma_typedarray_get_int16_element */ + +/** + * Read an uint16_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_uint16_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + uint16_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, uint16_t); + return ecma_make_integer_value (num); +} /* ecma_typedarray_get_uint16_element */ + +/** + * Read an int32_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_int32_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + int32_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, int32_t); + return ecma_make_number_value (num); +} /* ecma_typedarray_get_int32_element */ + +/** + * Read an uint32_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_uint32_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + uint32_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, uint32_t); + return ecma_make_number_value (num); +} /* ecma_typedarray_get_uint32_element */ + +/** + * Read a float value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_float_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + float num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, float); + return ecma_make_number_value (num); +} /* ecma_typedarray_get_float_element */ + +/** + * Read a double value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_double_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + double num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, double); + return ecma_make_number_value (num); +} /* ecma_typedarray_get_double_element */ + +#if JERRY_BUILTIN_BIGINT +/** + * Read a bigint64 value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_bigint64_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + uint64_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, uint64_t); + bool sign = (num >> 63) != 0; + + if (sign) + { + num = (uint64_t) (-(int64_t) num); + } + + return ecma_bigint_create_from_digits (&num, 1, sign); +} /* ecma_typedarray_get_bigint64_element */ + +/** + * Read a biguint64 value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_biguint64_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + uint64_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, uint64_t); + return ecma_bigint_create_from_digits (&num, 1, false); +} /* ecma_typedarray_get_biguint64_element */ +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Normalize the given ecma_number_t to an uint32_t value + */ +static uint32_t +ecma_typedarray_setter_number_to_uint32 (ecma_number_t value) /**< the number value to normalize */ +{ + uint32_t uint32_value = 0; + + if (!ecma_number_is_nan (value) && !ecma_number_is_infinity (value)) + { + bool is_negative = false; + + if (value < 0) + { + is_negative = true; + value = -value; + } + + if (value > ((ecma_number_t) 0xffffffff)) + { + value = (ecma_number_t) (fmod (value, (ecma_number_t) 0x100000000)); + } + + uint32_value = (uint32_t) value; + + if (is_negative) + { + uint32_value = (uint32_t) (-(int32_t) uint32_value); + } + } + + return uint32_value; +} /* ecma_typedarray_setter_number_to_uint32 */ + +/** + * Write an int8_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_int8_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t result_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + int8_t num = (int8_t) ecma_typedarray_setter_number_to_uint32 (result_num); + *dst_p = (lit_utf8_byte_t) num; + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_int8_element */ + +/** + * Write an uint8_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_uint8_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t result_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + uint8_t num = (uint8_t) ecma_typedarray_setter_number_to_uint32 (result_num); + *dst_p = (lit_utf8_byte_t) num; + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_uint8_element */ + +/** + * Write an uint8_t clamped value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_uint8_clamped_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t result_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + uint8_t clamped; + + if (result_num > 255) + { + clamped = 255; + } + else if (result_num <= 0) + { + clamped = 0; + } + else + { + clamped = (uint8_t) result_num; + + if (clamped + 0.5 < result_num || (clamped + 0.5 == result_num && (clamped % 2) == 1)) + { + clamped++; + } + } + + *dst_p = (lit_utf8_byte_t) clamped; + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_uint8_clamped_element */ + +/** + * Write an int16_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_int16_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t resut_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &resut_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + int16_t num = (int16_t) ecma_typedarray_setter_number_to_uint32 (resut_num); + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, int16_t); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_int16_element */ + +/** + * Write an uint8_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_uint16_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t resut_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &resut_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + uint16_t num = (uint16_t) ecma_typedarray_setter_number_to_uint32 (resut_num); + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, uint16_t); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_uint16_element */ + +/** + * Write an int32_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_int32_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t resut_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &resut_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + int32_t num = (int32_t) ecma_typedarray_setter_number_to_uint32 (resut_num); + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, int32_t); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_int32_element */ + +/** + * Write an uint32_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_uint32_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t resut_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &resut_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + uint32_t num = (uint32_t) ecma_typedarray_setter_number_to_uint32 (resut_num); + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, uint32_t); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_uint32_element */ + +/** + * Write a float value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_float_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t result_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + float num = (float) result_num; + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, float); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_float_element */ + +#if JERRY_NUMBER_TYPE_FLOAT64 +/** + * Write a double value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_double_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t result_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + double num = (double) result_num; + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, double); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_double_element */ +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +#if JERRY_BUILTIN_BIGINT +/** + * Write a bigint64/biguint64 value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToBigInt operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_bigint_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the bigint value to set */ +{ + ecma_value_t bigint = ecma_bigint_to_bigint (value, false); + + if (ECMA_IS_VALUE_ERROR (bigint)) + { + return bigint; + } + + uint64_t num; + bool sign; + ecma_bigint_get_digits_and_sign (bigint, &num, 1, &sign); + + if (sign) + { + num = (uint64_t) (-(int64_t) num); + } + + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, uint64_t); + + ecma_free_value (bigint); + + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_bigint_element */ +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Builtin id of the first %TypedArray% builtin routine intrinsic object + */ +#define ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_INT8ARRAY + +#if JERRY_BUILTIN_BIGINT +/** + * Builtin id of the last %TypedArray% builtin routine intrinsic object + */ +#define ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_BIGUINT64ARRAY +#elif !JERRY_BUILTIN_BIGINT && JERRY_NUMBER_TYPE_FLOAT64 +/** + * Builtin id of the last %TypedArray% builtin routine intrinsic object + */ +#define ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_FLOAT64ARRAY +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +/** + * Builtin id of the last %TypedArray% builtin routine intrinsic object + */ +#define ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_FLOAT32ARRAY +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Builtin id of the first %TypedArray% builtin prototype intrinsic object + */ +#define ECMA_FIRST_TYPEDARRAY_BUILTIN_PROTOTYPE_ID ECMA_BUILTIN_ID_INT8ARRAY_PROTOTYPE + +/** + * List of typedarray getters based on their builtin id + */ +static const ecma_typedarray_getter_fn_t ecma_typedarray_getters[] = { + ecma_typedarray_get_int8_element, /**< Int8Array */ + ecma_typedarray_get_uint8_element, /**< Uint8Array */ + ecma_typedarray_get_uint8_element, /**< Uint8ClampedArray */ + ecma_typedarray_get_int16_element, /**< Int16Array */ + ecma_typedarray_get_uint16_element, /**< Int32Array */ + ecma_typedarray_get_int32_element, /**< Uint32Array */ + ecma_typedarray_get_uint32_element, /**< Uint32Array */ + ecma_typedarray_get_float_element, /**< Float32Array */ +#if JERRY_NUMBER_TYPE_FLOAT64 + ecma_typedarray_get_double_element, /**< Float64Array */ +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + ecma_typedarray_get_bigint64_element, /**< BigInt64Array*/ + ecma_typedarray_get_biguint64_element, /**< BigUint64Array */ +#endif /* JERRY_BUILTIN_BIGINT */ +}; + +/** + * List of typedarray setters based on their builtin id + */ +static const ecma_typedarray_setter_fn_t ecma_typedarray_setters[] = { + ecma_typedarray_set_int8_element, /**< Int8Array */ + ecma_typedarray_set_uint8_element, /**< Uint8Array */ + ecma_typedarray_set_uint8_clamped_element, /**< Uint8ClampedArray */ + ecma_typedarray_set_int16_element, /**< Int16Array */ + ecma_typedarray_set_uint16_element, /**< Int32Array */ + ecma_typedarray_set_int32_element, /**< Uint32Array */ + ecma_typedarray_set_uint32_element, /**< Uint32Array */ + ecma_typedarray_set_float_element, /**< Float32Array */ +#if JERRY_NUMBER_TYPE_FLOAT64 + ecma_typedarray_set_double_element, /**< Float64Array */ +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + ecma_typedarray_set_bigint_element, /**< BigInt64Array */ + ecma_typedarray_set_bigint_element, /**< BigUInt64Array */ +#endif /* JERRY_BUILTIN_BIGINT */ +}; + +/** + * List of typedarray element shift sizes based on their builtin id + */ +static const uint8_t ecma_typedarray_element_shift_sizes[] = { + 0, /**< Int8Array */ + 0, /**< Uint8Array */ + 0, /**< Uint8ClampedArray */ + 1, /**< Int16Array */ + 1, /**< Uint16Array */ + 2, /**< Int32Array */ + 2, /**< Uint32Array */ + 2, /**< Float32Array */ +#if JERRY_NUMBER_TYPE_FLOAT64 + 3, /**< Float64Array */ +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + 3, /**< BigInt64Array */ + 3, /**< BigUInt64Array */ +#endif /* JERRY_BUILTIN_BIGINT */ +}; + +/** + * List of typedarray class magic strings based on their builtin id + */ +static const uint16_t ecma_typedarray_magic_string_list[] = { + (uint16_t) LIT_MAGIC_STRING_INT8_ARRAY_UL, /**< Int8Array */ + (uint16_t) LIT_MAGIC_STRING_UINT8_ARRAY_UL, /**< Uint8Array */ + (uint16_t) LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL, /**< Uint8ClampedArray */ + (uint16_t) LIT_MAGIC_STRING_INT16_ARRAY_UL, /**< Int16Array */ + (uint16_t) LIT_MAGIC_STRING_UINT16_ARRAY_UL, /**< Uint16Array */ + (uint16_t) LIT_MAGIC_STRING_INT32_ARRAY_UL, /**< Int32Array */ + (uint16_t) LIT_MAGIC_STRING_UINT32_ARRAY_UL, /**< Uint32Array */ + (uint16_t) LIT_MAGIC_STRING_FLOAT32_ARRAY_UL, /**< Float32Array */ +#if JERRY_NUMBER_TYPE_FLOAT64 + (uint16_t) LIT_MAGIC_STRING_FLOAT64_ARRAY_UL, /**< Float64Array */ +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + (uint16_t) LIT_MAGIC_STRING_BIGINT64_ARRAY_UL, /**< BigInt64Array */ + (uint16_t) LIT_MAGIC_STRING_BIGUINT64_ARRAY_UL, /**< BigUInt64Array */ +#endif /* JERRY_BUILTIN_BIGINT */ +}; + +/** + * Get the magic string id of a typedarray + * + * @return magic string + */ +lit_magic_string_id_t +ecma_get_typedarray_magic_string_id (ecma_typedarray_type_t typedarray_id) +{ + return (lit_magic_string_id_t) ecma_typedarray_magic_string_list[typedarray_id]; +} /* ecma_get_typedarray_magic_string_id */ + +/** + * Get typedarray's getter function callback + * + * @return ecma_typedarray_getter_fn_t: the getter function for the given builtin TypedArray id + */ +ecma_typedarray_getter_fn_t +ecma_get_typedarray_getter_fn (ecma_typedarray_type_t typedarray_id) /**< typedarray id */ +{ + return ecma_typedarray_getters[typedarray_id]; +} /* ecma_get_typedarray_getter_fn */ + +/** + * Get element from a TypedArray + * + * @return the value of the element + */ +ecma_value_t +ecma_get_typedarray_element (ecma_typedarray_info_t *info_p, /**< typedarray info */ + uint32_t index) /**< element index */ +{ + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info_p->array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p) || index >= info_p->length) + { + return ECMA_VALUE_UNDEFINED; + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + return ecma_typedarray_getters[info_p->id](buffer_p + (index << info_p->shift)); +} /* ecma_get_typedarray_element */ + +/** + * Get typedarray's setter function callback + * + * @return ecma_typedarray_setter_fn_t: the setter function for the given builtin TypedArray id + */ +ecma_typedarray_setter_fn_t +ecma_get_typedarray_setter_fn (ecma_typedarray_type_t typedarray_id) /**< typedarray id */ +{ + return ecma_typedarray_setters[typedarray_id]; +} /* ecma_get_typedarray_setter_fn */ + +/** + * set typedarray's element value + */ +ecma_value_t +ecma_set_typedarray_element (ecma_typedarray_info_t *info_p, /**< typedarray info */ + ecma_value_t value, /**< value to be set */ + uint32_t index) /**< element index */ +{ + ecma_value_t to_num; + if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id)) + { + to_num = ecma_bigint_to_bigint (value, false); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + } + else + { + ecma_number_t result_num; + to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + } + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info_p->array_buffer_p)) + { + ecma_free_value (to_num); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p) || index >= info_p->length) + { + ecma_free_value (to_num); + return ECMA_VALUE_FALSE; + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + ecma_free_value (to_num); + + return ecma_typedarray_setters[info_p->id](buffer_p + (index << info_p->shift), value); +} /* ecma_set_typedarray_element */ + +/** + * Get the element shift size of a TypedArray type. + * + * @return uint8_t + */ +uint8_t +ecma_typedarray_helper_get_shift_size (ecma_typedarray_type_t typedarray_id) +{ + return ecma_typedarray_element_shift_sizes[typedarray_id]; +} /* ecma_typedarray_helper_get_shift_size */ + +/** + * Check if the builtin is a TypedArray type. + * + * @return bool: - true if based on the given id it is a TypedArray + * - false if based on the given id it is not a TypedArray + */ +bool +ecma_typedarray_helper_is_typedarray (ecma_builtin_id_t builtin_id) /**< the builtin id of a type **/ +{ + return ((builtin_id >= ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID) + && (builtin_id <= ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID)); +} /* ecma_typedarray_helper_is_typedarray */ + +/** + * Get the prototype ID of a TypedArray type. + * + * @return ecma_builtin_id_t + */ +ecma_builtin_id_t +ecma_typedarray_helper_get_prototype_id (ecma_typedarray_type_t typedarray_id) /**< the id of the typedarray **/ +{ + return (ecma_builtin_id_t) (ECMA_FIRST_TYPEDARRAY_BUILTIN_PROTOTYPE_ID + typedarray_id); +} /* ecma_typedarray_helper_get_prototype_id */ + +/** + * Get the constructor ID of a TypedArray type. + * + * @return ecma_builtin_id_t + */ +ecma_builtin_id_t +ecma_typedarray_helper_get_constructor_id (ecma_typedarray_type_t typedarray_id) /**< the id of the typedarray **/ +{ + return (ecma_builtin_id_t) (ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID + typedarray_id); +} /* ecma_typedarray_helper_get_constructor_id */ + +/** + * Get the built-in TypedArray type of the given object. + * + * @return ecma_typedarray_type_t + */ +ecma_typedarray_type_t +ecma_get_typedarray_id (ecma_object_t *obj_p) /**< typedarray object **/ +{ + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + return (ecma_typedarray_type_t) ext_object_p->u.cls.u1.typedarray_type; +} /* ecma_get_typedarray_id */ + +/** + * Get the built-in TypedArray type of the given object. + * + * @return ecma_typedarray_type_t + */ +ecma_typedarray_type_t +ecma_typedarray_helper_builtin_to_typedarray_id (ecma_builtin_id_t builtin_id) +{ + JERRY_ASSERT (ecma_typedarray_helper_is_typedarray (builtin_id)); + + return (ecma_typedarray_type_t) (builtin_id - ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID); +} /* ecma_typedarray_helper_builtin_to_typedarray_id */ + +/** + * Create a TypedArray object by given array_length + * + * See also: ES2015 22.2.1.2.1 + * + * @return ecma value of the new typedarray object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_typedarray_create_object_with_length (uint32_t array_length, /**< length of the typedarray */ + ecma_object_t *src_buffer_p, /**< source buffer */ + ecma_object_t *proto_p, /**< prototype object */ + uint8_t element_size_shift, /**< the size shift of the element length */ + ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ +{ + uint32_t byte_length = UINT32_MAX; + + if (array_length <= (UINT32_MAX >> element_size_shift)) + { + byte_length = array_length << element_size_shift; + } + + if (byte_length > UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1) + { +#if JERRY_ERROR_MESSAGES + ecma_value_t array_length_value = ecma_make_number_value (array_length); + + ecma_value_t result = + ecma_raise_standard_error_with_format (JERRY_ERROR_RANGE, "Invalid typed array length: %", array_length_value); + ecma_free_value (array_length_value); + return result; +#else /* !JERRY_ERROR_MESSAGES */ + return ecma_raise_range_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + } + + ecma_object_t *new_arraybuffer_p = NULL; + if (src_buffer_p == NULL) + { + new_arraybuffer_p = ecma_arraybuffer_new_object (byte_length); + } + else + { + ecma_value_t ctor_proto = ecma_op_species_constructor (src_buffer_p, ECMA_BUILTIN_ID_ARRAYBUFFER); + + if (ECMA_IS_VALUE_ERROR (ctor_proto)) + { + return ctor_proto; + } + + ecma_object_t *ctor_proto_p = ecma_get_object_from_value (ctor_proto); + + ecma_object_t *prototype_p = + ecma_op_get_prototype_from_constructor (ctor_proto_p, ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE); + + ecma_deref_object (ctor_proto_p); + + if (JERRY_UNLIKELY (prototype_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + new_arraybuffer_p = ecma_arraybuffer_new_object (byte_length); + + ECMA_SET_NON_NULL_POINTER (new_arraybuffer_p->u2.prototype_cp, prototype_p); + + ecma_deref_object (prototype_p); + + if (ecma_arraybuffer_is_detached (src_buffer_p)) + { + ecma_deref_object (new_arraybuffer_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + } + + ecma_object_t *object_p = ecma_create_object (proto_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_TYPEDARRAY; + ext_object_p->u.cls.u1.typedarray_type = (uint8_t) typedarray_id; + ext_object_p->u.cls.u2.typedarray_flags = 0; + ext_object_p->u.cls.u3.arraybuffer = ecma_make_object_value (new_arraybuffer_p); + + ecma_deref_object (new_arraybuffer_p); + + return ecma_make_object_value (object_p); +} /* ecma_typedarray_create_object_with_length */ + +/** + * Create a TypedArray object by given another TypedArray object + * + * See also: ES2015 22.2.1.3 + * + * @return ecma value of the new typedarray object + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**< a typedarray object */ + ecma_object_t *proto_p, /**< prototype object */ + uint8_t element_size_shift, /**< the size shift of the element length */ + ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ +{ + uint32_t array_length = ecma_typedarray_get_length (typedarray_p); + ecma_object_t *src_arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (src_arraybuffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (src_arraybuffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (array_length, + src_arraybuffer_p, + proto_p, + element_size_shift, + typedarray_id); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + return new_typedarray; + } + + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); + ecma_object_t *dst_arraybuffer_p = ecma_typedarray_get_arraybuffer (new_typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (dst_arraybuffer_p)) + { + ecma_deref_object (new_typedarray_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (dst_arraybuffer_p)) + { + ecma_deref_object (new_typedarray_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + lit_utf8_byte_t *src_buf_p = ecma_arraybuffer_get_buffer (src_arraybuffer_p); + lit_utf8_byte_t *dst_buf_p = ecma_arraybuffer_get_buffer (dst_arraybuffer_p); + + src_buf_p += ecma_typedarray_get_offset (typedarray_p); + + ecma_typedarray_type_t src_id = ecma_get_typedarray_id (typedarray_p); + + if (src_id == typedarray_id) + { + memcpy (dst_buf_p, src_buf_p, array_length << element_size_shift); + } + else + { +#if JERRY_BUILTIN_BIGINT + if ((ECMA_TYPEDARRAY_IS_BIGINT_TYPE (src_id) ^ ECMA_TYPEDARRAY_IS_BIGINT_TYPE (typedarray_id)) == 1) + { + ecma_deref_object (new_typedarray_p); + return ecma_raise_type_error (ECMA_ERR_INCOMPATIBLE_TYPEDARRAY_TYPES); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + uint32_t src_element_size = 1u << ecma_typedarray_get_element_size_shift (typedarray_p); + uint32_t dst_element_size = 1u << element_size_shift; + ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (src_id); + ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (typedarray_id); + + for (uint32_t i = 0; i < array_length; i++) + { + /* Convert values from source to destination format. */ + ecma_value_t tmp = src_typedarray_getter_cb (src_buf_p); + ecma_value_t set_element = target_typedarray_setter_cb (dst_buf_p, tmp); + + ecma_free_value (tmp); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_deref_object (new_typedarray_p); + return set_element; + } + + src_buf_p += src_element_size; + dst_buf_p += dst_element_size; + } + } + + return new_typedarray; +} /* ecma_typedarray_create_object_with_typedarray */ + +/** + * Helper method for ecma_op_typedarray_from + * + * @return ECMA_VALUE_TRUE - if setting the given value to the new typedarray was successful + * ECMA_VALUE_ERROR - otherwise + */ +static ecma_value_t +ecma_op_typedarray_from_helper (ecma_value_t this_val, /**< this_arg for the above from function */ + ecma_value_t current_value, /**< given value to set */ + uint32_t index, /**< currrent index */ + ecma_object_t *func_object_p, /**< map function object */ + uint8_t *buffer_p, /**< target buffer */ + ecma_typedarray_setter_fn_t setter_cb) /**< setter callback function */ +{ + ecma_value_t mapped_value = current_value; + + if (func_object_p != NULL) + { + /* 17.d 17.f */ + ecma_value_t current_index = ecma_make_uint32_value (index); + ecma_value_t call_args[] = { current_value, current_index }; + + ecma_value_t cb_value = ecma_op_function_call (func_object_p, this_val, call_args, 2); + + ecma_free_value (current_value); + ecma_free_value (current_index); + + if (ECMA_IS_VALUE_ERROR (cb_value)) + { + return cb_value; + } + + mapped_value = cb_value; + } + + ecma_value_t set_element = setter_cb (buffer_p, mapped_value); + ecma_free_value (mapped_value); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + return set_element; + } + + return ECMA_VALUE_TRUE; +} /* ecma_op_typedarray_from_helper */ + +/** + * Create a TypedArray object by transforming from an array-like object or iterable object + * + * See also: ES11 22.2.4.4 + * + * @return ecma value of the new typedarray object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_typedarray_create_object_with_object (ecma_value_t items_val, /**< the source array-like object */ + ecma_object_t *proto_p, /**< prototype object */ + uint8_t element_size_shift, /**< the size shift of the element length */ + ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ +{ + /* 5 */ + ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (items_val, LIT_GLOBAL_SYMBOL_ITERATOR); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + ecma_object_t *new_typedarray_p; + ecma_typedarray_info_t info; + ecma_value_t *next_value_p; + + uint8_t *buffer_p; + ecma_typedarray_setter_fn_t setter_cb; + uint8_t *limit_p; + + if (ECMA_IS_VALUE_ERROR (using_iterator)) + { + return using_iterator; + } + + /* 6 */ + if (!ecma_is_value_undefined (using_iterator)) + { + /* 6.a */ + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (items_val, using_iterator, &next_method); + ecma_free_value (using_iterator); + + if (ECMA_IS_VALUE_ERROR (iterator)) + { + return iterator; + } + + ecma_collection_t *values_p = ecma_new_collection (); + + while (true) + { + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (next)) + { + ret_value = next; + break; + } + + if (next == ECMA_VALUE_FALSE) + { + break; + } + + ecma_value_t next_value = ecma_op_iterator_value (next); + ecma_free_value (next); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + ret_value = next_value; + break; + } + + ecma_collection_push_back (values_p, next_value); + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_collection_free (values_p); + return ret_value; + } + + /* 8.c */ + ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (values_p->item_count, + NULL, + proto_p, + element_size_shift, + typedarray_id); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + ecma_collection_free (values_p); + return new_typedarray; + } + + new_typedarray_p = ecma_get_object_from_value (new_typedarray); + info = ecma_typedarray_get_info (new_typedarray_p); + next_value_p = values_p->buffer_p; + + ret_value = ECMA_VALUE_ERROR; + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + goto free_collection; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto free_collection; + } + + buffer_p = ecma_typedarray_get_buffer (&info); + setter_cb = ecma_get_typedarray_setter_fn (info.id); + limit_p = buffer_p + (values_p->item_count << info.shift); + ret_value = ecma_make_object_value (new_typedarray_p); + + /* 8.e */ + while (buffer_p < limit_p) + { + ecma_value_t value = *next_value_p++; + ecma_value_t set_value = setter_cb (buffer_p, value); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (set_value)) + { + ret_value = set_value; + break; + } + + buffer_p += info.element_size; + } + +free_collection: + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_value_t *last_value_p = values_p->buffer_p + values_p->item_count; + + while (next_value_p < last_value_p) + { + ecma_free_value (*next_value_p++); + } + + ecma_deref_object (new_typedarray_p); + } + + ecma_collection_destroy (values_p); + return ret_value; + } + + /* 8 */ + ecma_value_t arraylike_object_val = ecma_op_to_object (items_val); + + if (ECMA_IS_VALUE_ERROR (arraylike_object_val)) + { + return arraylike_object_val; + } + + ecma_object_t *arraylike_object_p = ecma_get_object_from_value (arraylike_object_val); + + /* 9 */ + ecma_length_t length_index; + ecma_value_t len_value = ecma_op_object_get_length (arraylike_object_p, &length_index); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (arraylike_object_p); + return len_value; + } + + if (length_index >= UINT32_MAX) + { + ecma_deref_object (arraylike_object_p); + return ecma_raise_range_error (ECMA_ERR_INVALID_TYPEDARRAY_LENGTH); + } + + uint32_t len = (uint32_t) length_index; + + /* 10 */ + ecma_value_t new_typedarray = + ecma_typedarray_create_object_with_length (len, NULL, proto_p, element_size_shift, typedarray_id); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + ecma_deref_object (arraylike_object_p); + return new_typedarray; + } + + new_typedarray_p = ecma_get_object_from_value (new_typedarray); + info = ecma_typedarray_get_info (new_typedarray_p); + ret_value = ECMA_VALUE_ERROR; + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + goto free_object; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto free_object; + } + + buffer_p = ecma_typedarray_get_buffer (&info); + setter_cb = ecma_get_typedarray_setter_fn (info.id); + ret_value = ecma_make_object_value (new_typedarray_p); + + /* 12 */ + for (uint32_t index = 0; index < len; index++) + { + ecma_value_t value = ecma_op_object_find_by_index (arraylike_object_p, index); + + if (ECMA_IS_VALUE_ERROR (value)) + { + ret_value = value; + break; + } + + if (!ecma_is_value_found (value)) + { + value = ECMA_VALUE_UNDEFINED; + } + + ecma_value_t set_value = setter_cb (buffer_p, value); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (set_value)) + { + ret_value = set_value; + break; + } + + buffer_p += info.element_size; + } + +free_object: + ecma_deref_object (arraylike_object_p); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_object (new_typedarray_p); + } + + return ret_value; +} /* ecma_typedarray_create_object_with_object */ + +/** + * Create a TypedArray object by transforming from an array-like object or iterable object + * + * See also: ES11 22.2.2.1 + * + * @return ecma value of the new typedarray object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_typedarray_from (ecma_value_t this_val, /**< this value */ + ecma_value_t source_val, /**< source value */ + ecma_value_t map_fn_val, /**< mapped function value */ + ecma_value_t this_arg) /**< this argument */ +{ + JERRY_UNUSED (this_arg); + /* 3 */ + JERRY_ASSERT (ecma_op_is_callable (map_fn_val) || ecma_is_value_undefined (map_fn_val)); + + /* 4 */ + ecma_object_t *func_object_p = NULL; + + if (!ecma_is_value_undefined (map_fn_val)) + { + func_object_p = ecma_get_object_from_value (map_fn_val); + } + + /* 5 */ + ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (source_val, LIT_GLOBAL_SYMBOL_ITERATOR); + + if (ECMA_IS_VALUE_ERROR (using_iterator)) + { + return using_iterator; + } + + /* 6 */ + if (!ecma_is_value_undefined (using_iterator)) + { + /* 6.a */ + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (source_val, using_iterator, &next_method); + ecma_free_value (using_iterator); + + /* 6.b */ + if (ECMA_IS_VALUE_ERROR (iterator)) + { + return iterator; + } + + /* 6.c */ + ecma_collection_t *values_p = ecma_new_collection (); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 6.e */ + while (true) + { + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (next)) + { + ret_value = next; + break; + } + + if (next == ECMA_VALUE_FALSE) + { + break; + } + + ecma_value_t next_value = ecma_op_iterator_value (next); + ecma_free_value (next); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + ret_value = next_value; + break; + } + + ecma_collection_push_back (values_p, next_value); + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_collection_free (values_p); + return ret_value; + } + + /* 6.c */ + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (this_val); + ecma_value_t len_val = ecma_make_uint32_value (values_p->item_count); + ecma_value_t new_typedarray = ecma_typedarray_create (constructor_obj_p, &len_val, 1); + ecma_free_value (len_val); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + ecma_collection_free (values_p); + return new_typedarray; + } + + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); + ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p); + ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id); + ecma_value_t *next_value_p = values_p->buffer_p; + uint8_t *buffer_p; + + ret_value = ECMA_VALUE_ERROR; + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + goto free_collection; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto free_collection; + } + + buffer_p = ecma_typedarray_get_buffer (&info); + ret_value = ecma_make_object_value (new_typedarray_p); + + /* 6.e */ + for (uint32_t index = 0; index < values_p->item_count; index++) + { + ecma_value_t set_value = + ecma_op_typedarray_from_helper (this_arg, *next_value_p++, index, func_object_p, buffer_p, setter_cb); + + if (ECMA_IS_VALUE_ERROR (set_value)) + { + ret_value = set_value; + break; + } + + buffer_p += info.element_size; + } + +free_collection: + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_value_t *last_value_p = values_p->buffer_p + values_p->item_count; + + while (next_value_p < last_value_p) + { + ecma_free_value (*next_value_p++); + } + + ecma_deref_object (new_typedarray_p); + } + + ecma_collection_destroy (values_p); + return ret_value; + } + + /* 8 */ + ecma_value_t arraylike_object_val = ecma_op_to_object (source_val); + + if (ECMA_IS_VALUE_ERROR (arraylike_object_val)) + { + return arraylike_object_val; + } + + ecma_object_t *arraylike_object_p = ecma_get_object_from_value (arraylike_object_val); + + /* 9 */ + ecma_length_t length_index; + ecma_value_t len_value = ecma_op_object_get_length (arraylike_object_p, &length_index); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (arraylike_object_p); + return len_value; + } + + if (length_index >= UINT32_MAX) + { + ecma_deref_object (arraylike_object_p); + return ecma_raise_range_error (ECMA_ERR_INVALID_TYPEDARRAY_LENGTH); + } + + uint32_t len = (uint32_t) length_index; + + /* 10 */ + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (this_val); + ecma_value_t len_val = ecma_make_uint32_value (len); + ecma_value_t new_typedarray = ecma_typedarray_create (constructor_obj_p, &len_val, 1); + ecma_free_value (len_val); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + ecma_deref_object (arraylike_object_p); + return new_typedarray; + } + + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); + ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + uint8_t *buffer_p; + + ecma_typedarray_setter_fn_t setter_cb; + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + goto free_object; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto free_object; + } + + buffer_p = ecma_typedarray_get_buffer (&info); + setter_cb = ecma_get_typedarray_setter_fn (info.id); + ret_value = ecma_make_object_value (new_typedarray_p); + + /* 12 */ + for (uint32_t index = 0; index < len; index++) + { + ecma_value_t value = ecma_op_object_find_by_index (arraylike_object_p, index); + + if (ECMA_IS_VALUE_ERROR (value)) + { + ret_value = value; + break; + } + + if (!ecma_is_value_found (value)) + { + value = ECMA_VALUE_UNDEFINED; + } + + ecma_value_t set_value = + ecma_op_typedarray_from_helper (this_arg, value, index, func_object_p, buffer_p, setter_cb); + + if (ECMA_IS_VALUE_ERROR (set_value)) + { + ret_value = set_value; + break; + } + + buffer_p += info.element_size; + } + +free_object: + ecma_deref_object (arraylike_object_p); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_object (new_typedarray_p); + } + + return ret_value; +} /* ecma_op_typedarray_from */ + +/** + * Get the arraybuffer of the typedarray object + * + * @return the pointer to the internal arraybuffer + */ +ecma_object_t * +ecma_typedarray_get_arraybuffer (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p; + + return ecma_get_object_from_value (ext_object_p->u.cls.u3.arraybuffer); +} /* ecma_typedarray_get_arraybuffer */ + +/** + * Get the element size shift in the typedarray object + * + * @return the size shift of the element, size is 1 << shift + */ +uint8_t +ecma_typedarray_get_element_size_shift (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); + + return ecma_typedarray_helper_get_shift_size (ecma_get_typedarray_id (typedarray_p)); +} /* ecma_typedarray_get_element_size_shift */ + +/** + * Get the array length of the typedarray object + * + * @return the array length + */ +uint32_t +ecma_typedarray_get_length (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p; + + if (!(ext_object_p->u.cls.u2.typedarray_flags & ECMA_TYPEDARRAY_IS_EXTENDED)) + { + ecma_object_t *arraybuffer_p = ecma_get_object_from_value (ext_object_p->u.cls.u3.arraybuffer); + ecma_extended_object_t *arraybuffer_object_p = (ecma_extended_object_t *) arraybuffer_p; + uint32_t buffer_length = arraybuffer_object_p->u.cls.u3.length; + uint8_t shift = ecma_typedarray_get_element_size_shift (typedarray_p); + + return buffer_length >> shift; + } + + ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (ecma_arraybuffer_is_detached (arraybuffer_p)) + { + return 0; + } + + ecma_extended_typedarray_object_t *info_p = (ecma_extended_typedarray_object_t *) ext_object_p; + + return info_p->array_length; +} /* ecma_typedarray_get_length */ + +/** + * Get the offset of the internal arraybuffer + * + * @return the offset + */ +uint32_t +ecma_typedarray_get_offset (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p; + + if (!(ext_object_p->u.cls.u2.typedarray_flags & ECMA_TYPEDARRAY_IS_EXTENDED)) + { + return 0; + } + + ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (ecma_arraybuffer_is_detached (arraybuffer_p)) + { + return 0; + } + + ecma_extended_typedarray_object_t *info_p = (ecma_extended_typedarray_object_t *) ext_object_p; + + return info_p->byte_offset; +} /* ecma_typedarray_get_offset */ + +/** + * Utility function: return the pointer of the data buffer referenced by the typedarray info + * + * @return pointer to the data buffer if successfull, + * NULL otherwise + */ +uint8_t * +ecma_typedarray_get_buffer (ecma_typedarray_info_t *info_p) /**< typedarray info */ +{ + return ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; +} /* ecma_typedarray_get_buffer */ + +/** + * Create a new typedarray object. + * + * The struct of the typedarray object + * ecma_object_t + * extend_part + * typedarray_info + * + * @return ecma value of the new typedarray object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg list passed to typedarray construct */ + uint32_t arguments_list_len, /**< the length of the arguments_list_p */ + ecma_object_t *proto_p, /**< prototype object */ + uint8_t element_size_shift, /**< the size shift of the element length */ + ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len == 0) + { + /* 22.2.1.1 */ + return ecma_typedarray_create_object_with_length (0, NULL, proto_p, element_size_shift, typedarray_id); + } + + if (!ecma_is_value_object (arguments_list_p[0])) + { + ecma_number_t num = 0; + + if (!ecma_is_value_undefined (arguments_list_p[0]) + && ECMA_IS_VALUE_ERROR (ecma_op_to_index (arguments_list_p[0], &num))) + { + return ECMA_VALUE_ERROR; + } + + JERRY_ASSERT (num >= 0 && num <= ECMA_NUMBER_MAX_SAFE_INTEGER); + + if (num > UINT32_MAX) + { +#if JERRY_ERROR_MESSAGES + return ecma_raise_standard_error_with_format (JERRY_ERROR_RANGE, + "Invalid typed array length: %", + arguments_list_p[0]); +#else /* !JERRY_ERROR_MESSAGES */ + return ecma_raise_range_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + } + + return ecma_typedarray_create_object_with_length ((uint32_t) num, NULL, proto_p, element_size_shift, typedarray_id); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list_p[0]); + + if (ecma_object_is_typedarray (obj_p)) + { + /* 22.2.1.3 */ + ecma_object_t *typedarray_p = obj_p; + return ecma_typedarray_create_object_with_typedarray (typedarray_p, proto_p, element_size_shift, typedarray_id); + } + + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) && !ecma_object_is_shared_arraybuffer (obj_p)) + { + /* 22.2.1.4 */ + return ecma_typedarray_create_object_with_object (arguments_list_p[0], proto_p, element_size_shift, typedarray_id); + } + + /* 22.2.1.5 */ + ecma_object_t *arraybuffer_p = obj_p; + ecma_value_t byte_offset_value = ((arguments_list_len > 1) ? arguments_list_p[1] : ECMA_VALUE_UNDEFINED); + + ecma_value_t length_value = ((arguments_list_len > 2) ? arguments_list_p[2] : ECMA_VALUE_UNDEFINED); + + ecma_number_t offset; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_index (byte_offset_value, &offset))) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_number_is_negative (offset) || fmod (offset, (1 << element_size_shift)) != 0) + { + /* ES2015 22.2.1.5: 9 - 10. */ + if (ecma_number_is_zero (offset)) + { + offset = 0; + } + else + { + return ecma_raise_range_error (ECMA_ERR_INVALID_OFFSET); + } + } + + ecma_number_t new_length = 0; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_index (length_value, &new_length))) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (arraybuffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + if (offset > UINT32_MAX) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_LENGTH); + } + + uint32_t byte_offset = (uint32_t) offset; + + uint32_t buf_byte_length = ecma_arraybuffer_get_length (arraybuffer_p); + uint32_t new_byte_length = 0; + + if (ecma_is_value_undefined (length_value)) + { + if ((buf_byte_length % (uint32_t) (1 << element_size_shift) != 0) || (buf_byte_length < byte_offset)) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_LENGTH); + } + + new_byte_length = (uint32_t) (buf_byte_length - byte_offset); + } + else + { + if (new_length > (UINT32_MAX >> element_size_shift)) + { + return ecma_raise_range_error (ECMA_ERR_MAXIMUM_TYPEDARRAY_SIZE_IS_REACHED); + } + + new_byte_length = (uint32_t) new_length << element_size_shift; + + if (byte_offset > buf_byte_length || new_byte_length > (buf_byte_length - byte_offset)) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_LENGTH); + } + } + + bool needs_ext_typedarray_obj = (byte_offset != 0 || new_byte_length != buf_byte_length); + + size_t object_size = + (needs_ext_typedarray_obj ? sizeof (ecma_extended_typedarray_object_t) : sizeof (ecma_extended_object_t)); + + ecma_object_t *object_p = ecma_create_object (proto_p, object_size, ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_TYPEDARRAY; + ext_object_p->u.cls.u1.typedarray_type = (uint8_t) typedarray_id; + ext_object_p->u.cls.u2.typedarray_flags = 0; + ext_object_p->u.cls.u3.arraybuffer = ecma_make_object_value (arraybuffer_p); + + if (needs_ext_typedarray_obj) + { + ext_object_p->u.cls.u2.typedarray_flags |= ECMA_TYPEDARRAY_IS_EXTENDED; + + ecma_extended_typedarray_object_t *typedarray_info_p = (ecma_extended_typedarray_object_t *) object_p; + typedarray_info_p->array_length = new_byte_length >> element_size_shift; + typedarray_info_p->byte_offset = byte_offset; + } + + return ecma_make_object_value (object_p); +} /* ecma_op_create_typedarray */ + +/** + * Helper function for typedArray.prototype object's {'keys', 'values', 'entries', '@@iterator'} + * routines common parts. + * + * See also: + * ECMA-262 v6, 22.2.3.15 + * ECMA-262 v6, 22.2.3.29 + * ECMA-262 v6, 22.2.3.6 + * ECMA-262 v6, 22.1.3.30 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +ecma_value_t +ecma_typedarray_iterators_helper (ecma_value_t this_arg, /**< this argument */ + ecma_iterator_kind_t kind) /**< iterator kind */ +{ + JERRY_ASSERT (ecma_is_typedarray (this_arg)); + + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE); + + return ecma_op_create_iterator_object (this_arg, prototype_obj_p, ECMA_OBJECT_CLASS_ARRAY_ITERATOR, kind); +} /* ecma_typedarray_iterators_helper */ + +/** + * Check if the object is typedarray + * + * @return true - if object is a TypedArray object + * false - otherwise + */ +bool +ecma_object_is_typedarray (ecma_object_t *obj_p) /**< the target object need to be checked */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + + return ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_TYPEDARRAY); +} /* ecma_object_is_typedarray */ + +/** + * Check if the value is typedarray + * + * @return true - if value is a TypedArray object + * false - otherwise + */ +bool +ecma_is_typedarray (ecma_value_t value) /**< the target need to be checked */ +{ + if (!ecma_is_value_object (value)) + { + return false; + } + + return ecma_object_is_typedarray (ecma_get_object_from_value (value)); +} /* ecma_is_typedarray */ + +/** + * Checks whether the property name is a valid element index + * + * @return true, if valid + * false, otherwise + */ +bool +ecma_typedarray_is_element_index (ecma_string_t *property_name_p) /**< property name */ +{ + ecma_number_t num = ecma_string_to_number (property_name_p); + + if (num == 0) + { + return true; + } + + ecma_string_t *num_to_str = ecma_new_ecma_string_from_number (num); + bool is_same = ecma_compare_ecma_strings (property_name_p, num_to_str); + ecma_deref_ecma_string (num_to_str); + return is_same; +} /* ecma_typedarray_is_element_index */ + +/** + * List names of a TypedArray object's integer indexed properties + */ +void +ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, /**< a TypedArray object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES) + { + return; + } + + uint32_t array_length = ecma_typedarray_get_length (obj_p); + + for (uint32_t i = 0; i < array_length; i++) + { + ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); + ecma_collection_push_back (prop_names_p, ecma_make_string_value (name_p)); + } + + prop_counter_p->array_index_named_props += array_length; +} /* ecma_op_typedarray_list_lazy_property_names */ + +/** + * [[DefineOwnProperty]] operation for TypedArray objects + * + * See also: ES2015 9.4.5.3 + * + * @return ECMA_VALUE_TRUE - if the property is successfully defined + * ECMA_VALUE_FALSE - if is JERRY_PROP_SHOULD_THROW is not set + * raised TypeError - otherwise + */ +ecma_value_t +ecma_op_typedarray_define_own_property (ecma_object_t *obj_p, /**< TypedArray object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property descriptor */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); + + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX && !ecma_typedarray_is_element_index (property_name_p)) + { + return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p); + } + + if ((property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + || ((property_desc_p->flags & (JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE)) + == (JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE)) + || ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + && !(property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)) + || ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + && !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE))) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p); + + if (index >= info.length || ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + return ECMA_VALUE_FALSE; + } + + if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + ecma_value_t set_element = ecma_set_typedarray_element (&info, property_desc_p->value, index); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + return set_element; + } + } + + return ECMA_VALUE_TRUE; +} /* ecma_op_typedarray_define_own_property */ + +/** + * Specify the creation of a new TypedArray + * object using a constructor function. + * + * See also: ES11 22.2.4.6 + * + * Used by: + * - ecma_typedarray_species_create + * + * @return ecma_value_t function object from created from constructor_p argument + */ + +ecma_value_t +ecma_typedarray_create (ecma_object_t *constructor_p, /**< constructor function */ + ecma_value_t *arguments_list_p, /**< argument list */ + uint32_t arguments_list_len) /**< length of argument list */ +{ + ecma_value_t ret_val = + ecma_op_function_construct (constructor_p, constructor_p, arguments_list_p, arguments_list_len); + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + return ret_val; + } + + if (!ecma_is_typedarray (ret_val)) + { + ecma_free_value (ret_val); + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTED_OBJECT_IS_NOT_TYPEDARRAY); + } + + ecma_object_t *typedarray_p = ecma_get_object_from_value (ret_val); + ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + ecma_deref_object (typedarray_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_deref_object (typedarray_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + if ((arguments_list_len == 1) && (ecma_is_value_number (arguments_list_p[0]))) + { + ecma_number_t num = ecma_get_number_from_value (arguments_list_p[0]); + + if (info.length < num) + { + ecma_free_value (ret_val); + return ecma_raise_type_error (ECMA_ERR_TYPEDARRAY_SMALLER_THAN_FILTER_CALL_RESULT); + } + } + return ret_val; +} /* ecma_typedarray_create */ + +/* Specify the creation of a new TypedArray object + * using a constructor function that is derived from this_arg. + * + * See also: ES11 22.2.4.7 + * + * @return ecma value of the new typedarray object, constructed by default or species constructor + */ +ecma_value_t +ecma_typedarray_species_create (ecma_value_t this_arg, /**< this argument */ + ecma_value_t *arguments_list_p, /**< the arg list passed to typedarray construct */ + uint32_t arguments_list_len) /**< length of the the arg list */ +{ + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); + + JERRY_ASSERT (ecma_is_typedarray (this_arg)); + + ecma_builtin_id_t default_constructor = ecma_typedarray_helper_get_constructor_id (info.id); + + ecma_value_t constructor = ecma_op_species_constructor (typedarray_p, default_constructor); + + if (ECMA_IS_VALUE_ERROR (constructor)) + { + return constructor; + } + + ecma_object_t *constructor_proto_p = ecma_get_object_from_value (constructor); + + ecma_value_t result = ecma_typedarray_create (constructor_proto_p, arguments_list_p, arguments_list_len); + ecma_deref_object (constructor_proto_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + +#if JERRY_BUILTIN_BIGINT + ecma_object_t *result_p = ecma_get_object_from_value (result); + ecma_typedarray_info_t result_info = ecma_typedarray_get_info (result_p); + /* + * Check result_info.id to to be either bigint type if info.id is one + * or be neither of them is info.id is none of them as well. + */ + if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info.id) ^ ECMA_TYPEDARRAY_IS_BIGINT_TYPE (result_info.id)) + { + ecma_free_value (result); + return ecma_raise_type_error (ECMA_ERR_CONTENTTYPE_RETURNED_TYPEDARRAY_NOT_MATCH_SOURCE); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + return result; +} /* ecma_typedarray_species_create */ + +/** + * Create a typedarray object based on the "type" and arraylength + * The "type" is same with arg1 + * + * @return ecma_value_t + */ +ecma_value_t +ecma_op_create_typedarray_with_type_and_length (ecma_typedarray_type_t typedarray_id, /** TypedArray id */ + uint32_t array_length) /**< length of the typedarray */ +{ + // TODO: assert validate typedarray_id + ecma_object_t *proto_p = ecma_builtin_get (ecma_typedarray_helper_get_prototype_id (typedarray_id)); + uint8_t element_size_shift = ecma_typedarray_helper_get_shift_size (typedarray_id); + + ecma_value_t new_obj = + ecma_typedarray_create_object_with_length (array_length, NULL, proto_p, element_size_shift, typedarray_id); + + return new_obj; +} /* ecma_op_create_typedarray_with_type_and_length */ + +/** + * Method for getting the additional typedArray informations. + */ +ecma_typedarray_info_t +ecma_typedarray_get_info (ecma_object_t *typedarray_p) +{ + ecma_typedarray_info_t info; + + info.id = ecma_get_typedarray_id (typedarray_p); + info.length = ecma_typedarray_get_length (typedarray_p); + info.shift = ecma_typedarray_get_element_size_shift (typedarray_p); + info.element_size = (uint8_t) (1 << info.shift); + info.offset = ecma_typedarray_get_offset (typedarray_p); + info.array_buffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + return info; +} /* ecma_typedarray_get_info */ + +/** + * @} + * @} + */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.h new file mode 100644 index 00000000..ab004265 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.h @@ -0,0 +1,89 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_TYPEDARRAY_OBJECT_H +#define ECMA_TYPEDARRAY_OBJECT_H + +#include "ecma-builtins.h" +#include "ecma-globals.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmatypedarrayobject ECMA TypedArray object related routines + * @{ + */ + +uint8_t ecma_typedarray_helper_get_shift_size (ecma_typedarray_type_t typedarray_id); +lit_magic_string_id_t ecma_get_typedarray_magic_string_id (ecma_typedarray_type_t typedarray_id); +ecma_typedarray_getter_fn_t ecma_get_typedarray_getter_fn (ecma_typedarray_type_t typedarray_id); +ecma_typedarray_setter_fn_t ecma_get_typedarray_setter_fn (ecma_typedarray_type_t typedarray_id); +ecma_value_t ecma_get_typedarray_element (ecma_typedarray_info_t *info_p, uint32_t index); +ecma_value_t ecma_set_typedarray_element (ecma_typedarray_info_t *info_p, ecma_value_t value, uint32_t index); +bool ecma_typedarray_helper_is_typedarray (ecma_builtin_id_t builtin_id); +ecma_typedarray_type_t ecma_get_typedarray_id (ecma_object_t *obj_p); +ecma_builtin_id_t ecma_typedarray_helper_get_prototype_id (ecma_typedarray_type_t typedarray_id); +ecma_builtin_id_t ecma_typedarray_helper_get_constructor_id (ecma_typedarray_type_t typedarray_id); +ecma_typedarray_type_t ecma_typedarray_helper_builtin_to_typedarray_id (ecma_builtin_id_t builtin_id); + +ecma_value_t +ecma_op_typedarray_from (ecma_value_t this_val, ecma_value_t source_val, ecma_value_t mapfn_val, ecma_value_t this_arg); +uint32_t ecma_typedarray_get_length (ecma_object_t *typedarray_p); +uint32_t ecma_typedarray_get_offset (ecma_object_t *typedarray_p); +uint8_t *ecma_typedarray_get_buffer (ecma_typedarray_info_t *info_p); +uint8_t ecma_typedarray_get_element_size_shift (ecma_object_t *typedarray_p); +ecma_object_t *ecma_typedarray_get_arraybuffer (ecma_object_t *typedarray_p); +ecma_value_t ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len, + ecma_object_t *proto_p, + uint8_t element_size_shift, + ecma_typedarray_type_t typedarray_id); +ecma_value_t ecma_typedarray_iterators_helper (ecma_value_t this_arg, ecma_iterator_kind_t kind); + +bool ecma_object_is_typedarray (ecma_object_t *obj_p); +bool ecma_is_typedarray (ecma_value_t target); +bool ecma_typedarray_is_element_index (ecma_string_t *property_name_p); +void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +ecma_value_t ecma_op_typedarray_define_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); +ecma_value_t ecma_op_create_typedarray_with_type_and_length (ecma_typedarray_type_t typedarray_id, + uint32_t array_length); +ecma_typedarray_info_t ecma_typedarray_get_info (ecma_object_t *typedarray_p); +ecma_value_t ecma_typedarray_create_object_with_length (uint32_t array_length, + ecma_object_t *src_arraybuffer_p, + ecma_object_t *proto_p, + uint8_t element_size_shift, + ecma_typedarray_type_t typedarray_id); +ecma_value_t ecma_typedarray_create_object_with_object (ecma_value_t items_val, + ecma_object_t *proto_p, + uint8_t element_size_shift, + ecma_typedarray_type_t typedarray_id); +ecma_value_t +ecma_typedarray_create (ecma_object_t *constructor_p, ecma_value_t *arguments_list_p, uint32_t arguments_list_len); +ecma_value_t ecma_typedarray_species_create (ecma_value_t this_arg, ecma_value_t *length, uint32_t arguments_list_len); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#endif /* !ECMA_TYPEDARRAY_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/meson.build b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/meson.build new file mode 100644 index 00000000..aa9fe30d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/meson.build @@ -0,0 +1,68 @@ +source_file = [ + 'ecma-arguments-object.h', + 'ecma-array-object.h', + 'ecma-arraybuffer-object.h', + 'ecma-async-generator-object.h', + 'ecma-atomics-object.h', + 'ecma-big-uint.h', + 'ecma-bigint-object.h', + 'ecma-bigint.h', + 'ecma-boolean-object.h', + 'ecma-comparison.h', + 'ecma-container-object.h', + 'ecma-conversion.h', + 'ecma-dataview-object.h', + 'ecma-eval.h', + 'ecma-exceptions.h', + 'ecma-function-object.h', + 'ecma-iterator-object.h', + 'ecma-jobqueue.h', + 'ecma-lex-env.h', + 'ecma-number-object.h', + 'ecma-objects-general.h', + 'ecma-objects.h', + 'ecma-promise-object.h', + 'ecma-proxy-object.h', + 'ecma-reference.h', + 'ecma-regexp-object.h', + 'ecma-shared-arraybuffer-object.h', + 'ecma-string-object.h', + 'ecma-symbol-object.h', + 'ecma-typedarray-object.h', + 'ecma-arguments-object.cpp', + 'ecma-array-object.cpp', + 'ecma-arraybuffer-object.cpp', + 'ecma-async-generator-object.cpp', + 'ecma-atomics-object.cpp', + 'ecma-big-uint.cpp', + 'ecma-bigint-object.cpp', + 'ecma-bigint.cpp', + 'ecma-boolean-object.cpp', + 'ecma-comparison.cpp', + 'ecma-container-object.cpp', + 'ecma-conversion.cpp', + 'ecma-dataview-object.cpp', + 'ecma-eval.cpp', + 'ecma-exceptions.cpp', + 'ecma-function-object.cpp', + 'ecma-get-put-value.cpp', + 'ecma-iterator-object.cpp', + 'ecma-jobqueue.cpp', + 'ecma-lex-env.cpp', + 'ecma-number-object.cpp', + 'ecma-objects-general.cpp', + 'ecma-objects.cpp', + 'ecma-promise-object.cpp', + 'ecma-proxy-object.cpp', + 'ecma-reference.cpp', + 'ecma-regexp-object.cpp', + 'ecma-shared-arraybuffer-object.cpp', + 'ecma-string-object.cpp', + 'ecma-symbol-object.cpp', + 'ecma-typedarray-object.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerry-config.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerry-config.h new file mode 100644 index 00000000..ff48a6c0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerry-config.h @@ -0,0 +1,632 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_CONFIG_H +#define JERRYSCRIPT_CONFIG_H + +// @JERRY_BUILD_CFG@ + +/** + * Built-in configurations + * + * Allowed values for built-in defines: + * 0: Disable the given built-in. + * 1: Enable the given built-in. + */ +/* + * By default all built-ins are enabled if they are not defined. + */ +#ifndef JERRY_BUILTINS +#define JERRY_BUILTINS 1 +#endif /* !defined (JERRY_BUILTINS) */ + +#ifndef JERRY_BUILTIN_ANNEXB +#define JERRY_BUILTIN_ANNEXB JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_ANNEXB) */ + +#ifndef JERRY_BUILTIN_ARRAY +#define JERRY_BUILTIN_ARRAY JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_ARRAY) */ + +#ifndef JERRY_BUILTIN_BOOLEAN +#define JERRY_BUILTIN_BOOLEAN JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_BOOLEAN) */ + +#ifndef JERRY_BUILTIN_DATE +#define JERRY_BUILTIN_DATE JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_DATE) */ + +#ifndef JERRY_BUILTIN_ERRORS +#define JERRY_BUILTIN_ERRORS JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_ERRORS) */ + +#ifndef JERRY_BUILTIN_MATH +#define JERRY_BUILTIN_MATH JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_MATH) */ + +#ifndef JERRY_BUILTIN_NUMBER +#define JERRY_BUILTIN_NUMBER JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_NUMBER) */ + +#ifndef JERRY_BUILTIN_REGEXP +#define JERRY_BUILTIN_REGEXP JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_REGEXP) */ + +#ifndef JERRY_BUILTIN_STRING +#define JERRY_BUILTIN_STRING JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_STRING) */ + +#ifndef JERRY_BUILTIN_BIGINT +#define JERRY_BUILTIN_BIGINT JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_BIGINT) */ + +#ifndef JERRY_BUILTIN_CONTAINER +#define JERRY_BUILTIN_CONTAINER JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_CONTAINER) */ + +#ifndef JERRY_BUILTIN_DATAVIEW +#define JERRY_BUILTIN_DATAVIEW JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_DATAVIEW) */ + +#ifndef JERRY_BUILTIN_GLOBAL_THIS +#define JERRY_BUILTIN_GLOBAL_THIS JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_GLOBAL_THIS) */ + +#ifndef JERRY_BUILTIN_REALMS +#define JERRY_BUILTIN_REALMS JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_REALMS) */ + +#ifndef JERRY_BUILTIN_TYPEDARRAY +#define JERRY_BUILTIN_TYPEDARRAY JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_TYPEDARRAY) */ + +#ifndef JERRY_BUILTIN_SHAREDARRAYBUFFER +#define JERRY_BUILTIN_SHAREDARRAYBUFFER JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_SHAREDARRAYBUFFER) */ + +#ifndef JERRY_BUILTIN_WEAKREF +#define JERRY_BUILTIN_WEAKREF JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_WEAKREF) */ + +/** + * Engine internal and misc configurations. + */ + +/** + * Specifies the compressed pointer representation + * + * Allowed values: + * 0: use 16 bit representation + * 1: use 32 bit representation + * + * Default value: 0 + * For more details see: jmem/jmem.h + */ +#ifndef JERRY_CPOINTER_32_BIT +#define JERRY_CPOINTER_32_BIT 0 +#endif /* !defined (JERRY_CPOINTER_32_BIT) */ + +/** + * Enable/Disable built-in error messages for error objects. + * + * Allowed values: + * 0: Disable error messages. + * 1: Enable error message. + * + * Default value: 0 + */ +#ifndef JERRY_ERROR_MESSAGES +#define JERRY_ERROR_MESSAGES 0 +#endif /* !defined (JERRY_ERROR_MESSAGES) */ + +/** + * Enable/Disable external context. + * + * Allowed values: + * 0: Disable external context. + * 1: Enable external context support. + * + * Default value: 0 + */ +#ifndef JERRY_EXTERNAL_CONTEXT +#define JERRY_EXTERNAL_CONTEXT 0 +#endif /* !defined (JERRY_EXTERNAL_CONTEXT) */ + +/** + * Maximum size of heap in kilobytes + * + * Default value: 512 KiB + */ +#ifndef JERRY_GLOBAL_HEAP_SIZE +#define JERRY_GLOBAL_HEAP_SIZE (512) +#endif /* !defined (JERRY_GLOBAL_HEAP_SIZE) */ + +/** + * The allowed heap usage limit until next garbage collection, in bytes. + * + * If value is 0, the default is 1/32 of JERRY_HEAP_SIZE + */ +#ifndef JERRY_GC_LIMIT +#define JERRY_GC_LIMIT 0 +#endif /* !defined (JERRY_GC_LIMIT) */ + +/** + * Maximum stack usage size in kilobytes + * + * Note: This feature cannot be used when 'detect_stack_use_after_return=1' ASAN option is enabled. + * For more detailed description: + * - https://github.com/google/sanitizers/wiki/AddressSanitizerUseAfterReturn#compatibility + * + * Default value: 0, unlimited + */ +#ifndef JERRY_STACK_LIMIT +#define JERRY_STACK_LIMIT (0) +#endif /* !defined (JERRY_STACK_LIMIT) */ + +/** + * Maximum depth of recursion during GC mark phase + * + * Default value: 8 + */ +#ifndef JERRY_GC_MARK_LIMIT +#define JERRY_GC_MARK_LIMIT (8) +#endif /* !defined (JERRY_GC_MARK_LIMIT) */ + +/** + * Enable/Disable property lookup cache. + * + * Allowed values: + * 0: Disable lookup cache. + * 1: Enable lookup cache. + * + * Default value: 1 + */ +#ifndef JERRY_LCACHE +#define JERRY_LCACHE 1 +#endif /* !defined (JERRY_LCACHE) */ + +/** + * Enable/Disable function toString operation. + * + * Allowed values: + * 0: Disable function toString operation. + * 1: Enable function toString operation. + * + * Default value: 0 + */ +#ifndef JERRY_FUNCTION_TO_STRING +#define JERRY_FUNCTION_TO_STRING 0 +#endif /* !defined (JERRY_FUNCTION_TO_STRING) */ + +/** + * Enable/Disable line-info management inside the engine. + * + * Allowed values: + * 0: Disable line-info in the engine. + * 1: Enable line-info management. + * + * Default value: 0 + */ +#ifndef JERRY_LINE_INFO +#define JERRY_LINE_INFO 0 +#endif /* !defined (JERRY_LINE_INFO) */ + +/** + * Enable/Disable logging inside the engine. + * + * Allowed values: + * 0: Disable internal logging. + * 1: Enable internal logging. + * + * Default value: 0 + */ +#ifndef JERRY_LOGGING +#define JERRY_LOGGING 0 +#endif /* !defined (JERRY_LOGGING) */ + +/** + * Enable/Disable gc call before every allocation. + * + * Allowed values: + * 0: Disable gc call before each allocation. + * 1: Enable and force gc call before each allocation. + * + * Default value: 0 + * Warning!: This is an advanced option and will slow down the engine! + * Only enable it for debugging purposes. + */ +#ifndef JERRY_MEM_GC_BEFORE_EACH_ALLOC +#define JERRY_MEM_GC_BEFORE_EACH_ALLOC 0 +#endif /* !defined (JERRY_MEM_GC_BEFORE_EACH_ALLOC) */ + +/** + * Use 32-bit/64-bit float for ecma-numbers + * This option is for expert use only! + * + * Allowed values: + * 1: use 64-bit floating point number mode + * 0: use 32-bit floating point number mode + * + * Default value: 1 + */ +#ifndef JERRY_NUMBER_TYPE_FLOAT64 +#define JERRY_NUMBER_TYPE_FLOAT64 1 +#endif /* !defined (JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Enable/Disable the JavaScript parser. + * + * Allowed values: + * 0: Disable the JavaScript parser and all related functionallity. + * 1: Enable the JavaScript parser. + * + * Default value: 1 + */ +#ifndef JERRY_PARSER +#define JERRY_PARSER 1 +#endif /* !defined (JERRY_PARSER) */ + +/** + * Enable/Disable JerryScript byte code dump functions during parsing. + * To dump the JerryScript byte code the engine must be initialized with opcodes + * display flag. This option does not influence RegExp byte code dumps. + * + * Allowed values: + * 0: Disable all bytecode dump functions. + * 1: Enable bytecode dump functions. + * + * Default value: 0 + */ +#ifndef JERRY_PARSER_DUMP_BYTE_CODE +#define JERRY_PARSER_DUMP_BYTE_CODE 0 +#endif /* defined (JERRY_PARSER_DUMP_BYTE_CODE) */ + +/** + * Enable/Disable ECMA property hashmap. + * + * Allowed values: + * 0: Disable property hasmap. + * 1: Enable property hashmap. + * + * Default value: 1 + */ +#ifndef JERRY_PROPERTY_HASHMAP +#define JERRY_PROPERTY_HASHMAP 1 +#endif /* !defined (JERRY_PROPERTY_HASHMAP) */ + +/** + * Enables/disables the Promise event callbacks + * + * Default value: 0 + */ +#ifndef JERRY_PROMISE_CALLBACK +#define JERRY_PROMISE_CALLBACK 0 +#endif /* !defined (JERRY_PROMISE_CALLBACK) */ + +/** + * Enable/Disable byte code dump functions for RegExp objects. + * To dump the RegExp byte code the engine must be initialized with + * regexp opcodes display flag. This option does not influence the + * JerryScript byte code dumps. + * + * Allowed values: + * 0: Disable all bytecode dump functions. + * 1: Enable bytecode dump functions. + * + * Default value: 0 + */ +#ifndef JERRY_REGEXP_DUMP_BYTE_CODE +#define JERRY_REGEXP_DUMP_BYTE_CODE 0 +#endif /* !defined (JERRY_REGEXP_DUMP_BYTE_CODE) */ + +/** + * Enables/disables the RegExp strict mode + * + * Default value: 0 + */ +#ifndef JERRY_REGEXP_STRICT_MODE +#define JERRY_REGEXP_STRICT_MODE 0 +#endif /* !defined (JERRY_REGEXP_STRICT_MODE) */ + +/** + * Enable/Disable the snapshot execution functions. + * + * Allowed values: + * 0: Disable snapshot execution. + * 1: Enable snapshot execution. + * + * Default value: 0 + */ +#ifndef JERRY_SNAPSHOT_EXEC +#define JERRY_SNAPSHOT_EXEC 0 +#endif /* !defined (JERRY_SNAPSHOT_EXEC) */ + +/** + * Enable/Disable the snapshot save functions. + * + * Allowed values: + * 0: Disable snapshot save functions. + * 1: Enable snapshot save functions. + */ +#ifndef JERRY_SNAPSHOT_SAVE +#define JERRY_SNAPSHOT_SAVE 0 +#endif /* !defined (JERRY_SNAPSHOT_SAVE) */ + +/** + * Enable/Disable usage of system allocator. + * + * Allowed values: + * 0: Disable usage of system allocator. + * 1: Enable usage of system allocator. + * + * Default value: 0 + */ +#ifndef JERRY_SYSTEM_ALLOCATOR +#define JERRY_SYSTEM_ALLOCATOR 0 +#endif /* !defined (JERRY_SYSTEM_ALLOCATOR) */ + +/** + * Enables/disables the unicode case conversion in the engine. + * By default Unicode case conversion is enabled. + */ +#ifndef JERRY_UNICODE_CASE_CONVERSION +#define JERRY_UNICODE_CASE_CONVERSION 1 +#endif /* !defined (JERRY_UNICODE_CASE_CONVERSION) */ + +/** + * Configures if the internal memory allocations are exposed to Valgrind or not. + * + * Allowed values: + * 0: Disable the Valgrind specific memory allocation notifications. + * 1: Enable the Valgrind specific allocation notifications. + */ +#ifndef JERRY_VALGRIND +#define JERRY_VALGRIND 0 +#endif /* !defined (JERRY_VALGRIND) */ + +/** + * Enable/Disable the vm execution stop callback function. + * + * Allowed values: + * 0: Disable vm exec stop callback support. + * 1: Enable vm exec stop callback support. + */ +#ifndef JERRY_VM_HALT +#define JERRY_VM_HALT 0 +#endif /* !defined (JERRY_VM_HALT) */ + +/** + * Enable/Disable the vm throw callback function. + * + * Allowed values: + * 0: Disable vm throw callback support. + * 1: Enable vm throw callback support. + */ +#ifndef JERRY_VM_THROW +#define JERRY_VM_THROW 0 +#endif /* !defined (JERRY_VM_THROW) */ + +/** + * Advanced section configurations. + */ + +/** + * Allow configuring attributes on a few constant data inside the engine. + * + * One of the main usages: + * Normally compilers store const(ant)s in ROM. Thus saving RAM. + * But if your compiler does not support it then the directive below can force it. + * + * For the moment it is mainly meant for the following targets: + * - ESP8266 + * + * Example configuration for moving (some) constatns into a given section: + * # define JERRY_ATTR_CONST_DATA __attribute__((section(".rodata.const"))) + */ +#ifndef JERRY_ATTR_CONST_DATA +#define JERRY_ATTR_CONST_DATA +#endif /* !defined (JERRY_ATTR_CONST_DATA) */ + +/** + * The JERRY_ATTR_GLOBAL_HEAP allows adding extra attributes for the Jerry global heap. + * + * Example on how to move the global heap into it's own section: + * #define JERRY_ATTR_GLOBAL_HEAP __attribute__((section(".text.globalheap"))) + */ +#ifndef JERRY_ATTR_GLOBAL_HEAP +#define JERRY_ATTR_GLOBAL_HEAP +#endif /* !defined (JERRY_ATTR_GLOBAL_HEAP) */ + +/** + * Sanity check for macros to see if the values are 0 or 1 + * + * If a new feature is added this should be updated. + */ +/** + * Check base builtins. + */ +#if (JERRY_BUILTIN_ANNEXB != 0) && (JERRY_BUILTIN_ANNEXB != 1) +#error "Invalid value for JERRY_BUILTIN_ANNEXB macro." +#endif /* (JERRY_BUILTIN_ANNEXB != 0) && (JERRY_BUILTIN_ANNEXB != 1) */ +#if (JERRY_BUILTIN_ARRAY != 0) && (JERRY_BUILTIN_ARRAY != 1) +#error "Invalid value for JERRY_BUILTIN_ARRAY macro." +#endif /* (JERRY_BUILTIN_ARRAY != 0) && (JERRY_BUILTIN_ARRAY != 1) */ +#if (JERRY_BUILTIN_BOOLEAN != 0) && (JERRY_BUILTIN_BOOLEAN != 1) +#error "Invalid value for JERRY_BUILTIN_BOOLEAN macro." +#endif /* (JERRY_BUILTIN_BOOLEAN != 0) && (JERRY_BUILTIN_BOOLEAN != 1) */ +#if (JERRY_BUILTIN_DATE != 0) && (JERRY_BUILTIN_DATE != 1) +#error "Invalid value for JERRY_BUILTIN_DATE macro." +#endif /* (JERRY_BUILTIN_DATE != 0) && (JERRY_BUILTIN_DATE != 1) */ +#if (JERRY_BUILTIN_ERRORS != 0) && (JERRY_BUILTIN_ERRORS != 1) +#error "Invalid value for JERRY_BUILTIN_ERRORS macro." +#endif /* (JERRY_BUILTIN_ERRORS != 0) && (JERRY_BUILTIN_ERRORS != 1) */ +#if (JERRY_BUILTIN_MATH != 0) && (JERRY_BUILTIN_MATH != 1) +#error "Invalid value for JERRY_BUILTIN_MATH macro." +#endif /* (JERRY_BUILTIN_MATH != 0) && (JERRY_BUILTIN_MATH != 1) */ +#if (JERRY_BUILTIN_NUMBER != 0) && (JERRY_BUILTIN_NUMBER != 1) +#error "Invalid value for JERRY_BUILTIN_NUMBER macro." +#endif /* (JERRY_BUILTIN_NUMBER != 0) && (JERRY_BUILTIN_NUMBER != 1) */ +#if (JERRY_BUILTIN_REGEXP != 0) && (JERRY_BUILTIN_REGEXP != 1) +#error "Invalid value for JERRY_BUILTIN_REGEXP macro." +#endif /* (JERRY_BUILTIN_REGEXP != 0) && (JERRY_BUILTIN_REGEXP != 1) */ +#if (JERRY_BUILTIN_STRING != 0) && (JERRY_BUILTIN_STRING != 1) +#error "Invalid value for JERRY_BUILTIN_STRING macro." +#endif /* (JERRY_BUILTIN_STRING != 0) && (JERRY_BUILTIN_STRING != 1) */ +#if (JERRY_BUILTINS != 0) && (JERRY_BUILTINS != 1) +#error "Invalid value for JERRY_BUILTINS macro." +#endif /* (JERRY_BUILTINS != 0) && (JERRY_BUILTINS != 1) */ +#if (JERRY_BUILTIN_REALMS != 0) && (JERRY_BUILTIN_REALMS != 1) +#error "Invalid value for JERRY_BUILTIN_REALMS macro." +#endif /* (JERRY_BUILTIN_REALMS != 0) && (JERRY_BUILTIN_REALMS != 1) */ +#if (JERRY_BUILTIN_DATAVIEW != 0) && (JERRY_BUILTIN_DATAVIEW != 1) +#error "Invalid value for JERRY_BUILTIN_DATAVIEW macro." +#endif /* (JERRY_BUILTIN_DATAVIEW != 0) && (JERRY_BUILTIN_DATAVIEW != 1) */ +#if (JERRY_BUILTIN_GLOBAL_THIS != 0) && (JERRY_BUILTIN_GLOBAL_THIS != 1) +#error "Invalid value for JERRY_BUILTIN_GLOBAL_THIS macro." +#endif /* (JERRY_BUILTIN_GLOBAL_THIS != 0) && (JERRY_BUILTIN_GLOBAL_THIS != 1) */ +#if (JERRY_BUILTIN_REFLECT != 0) && (JERRY_BUILTIN_REFLECT != 1) +#error "Invalid value for JERRY_BUILTIN_REFLECT macro." +#endif /* (JERRY_BUILTIN_REFLECT != 0) && (JERRY_BUILTIN_REFLECT != 1) */ +#if (JERRY_BUILTIN_WEAKREF != 0) && (JERRY_BUILTIN_WEAKREF != 1) +#error "Invalid value for JERRY_BUILTIN_WEAKREF macro." +#endif /* (JERRY_BUILTIN_WEAKREF != 0) && (JERRY_BUILTIN_WEAKREF != 1) */ +#if (JERRY_BUILTIN_PROXY != 0) && (JERRY_BUILTIN_PROXY != 1) +#error "Invalid value for JERRY_BUILTIN_PROXY macro." +#endif /* (JERRY_BUILTIN_PROXY != 0) && (JERRY_BUILTIN_PROXY != 1) */ +#if (JERRY_BUILTIN_TYPEDARRAY != 0) && (JERRY_BUILTIN_TYPEDARRAY != 1) +#error "Invalid value for JERRY_BUILTIN_TYPEDARRAY macro." +#endif /* (JERRY_BUILTIN_TYPEDARRAY != 0) && (JERRY_BUILTIN_TYPEDARRAY != 1) */ +#if (JERRY_BUILTIN_SHAREDARRAYBUFFER != 0) && (JERRY_BUILTIN_SHAREDARRAYBUFFER != 1) +#error "Invalid value for JERRY_BUILTIN_SHAREDARRAYBUFFER macro." +#endif /* (JERRY_BUILTIN_SHAREDARRAYBUFFER != 0) && (JERRY_BUILTIN_SHAREDARRAYBUFFER != 1) */ +#if (JERRY_BUILTIN_ATOMICS != 0) && (JERRY_BUILTIN_ATOMICS != 1) +#error "Invalid value for JERRY_BUILTIN_ATOMICS macro." +#endif /* (JERRY_BUILTIN_ATOMICS != 0) && (JERRY_BUILTIN_ATOMICS != 1) */ +#if (JERRY_BUILTIN_BIGINT != 0) && (JERRY_BUILTIN_BIGINT != 1) +#error "Invalid value for JERRY_BUILTIN_BIGINT macro." +#endif /* (JERRY_BUILTIN_BIGINT != 0) && (JERRY_BUILTIN_BIGINT != 1) */ +#if (JERRY_MODULE_SYSTEM != 0) && (JERRY_MODULE_SYSTEM != 1) +#error "Invalid value for JERRY_MODULE_SYSTEM macro." +#endif /* (JERRY_MODULE_SYSTEM != 0) && (JERRY_MODULE_SYSTEM != 1) */ +#if (JERRY_BUILTIN_TYPEDARRAY == 0) && (JERRY_BUILTIN_SHAREDARRAYBUFFER == 1) +#error "JERRY_BUILTIN_TYPEDARRAY should be enabled too to enable JERRY_BUILTIN_SHAREDARRAYBUFFER macro." +#endif /* (JERRY_BUILTIN_TYPEDARRAY == 0) && (JERRY_BUILTIN_SHAREDARRAYBUFFER == 1) */ +#if (JERRY_BUILTIN_SHAREDARRAYBUFFER == 0) && (JERRY_BUILTIN_ATOMICS == 1) +#error "JERRY_BUILTIN_SHAREDARRAYBUFFER should be enabled too to enable JERRY_BUILTIN_ATOMICS macro." +#endif /* (JERRY_BUILTIN_SHAREDARRAYBUFFER == 0) && (JERRY_BUILTIN_ATOMICS == 1) */ + +/** + * Internal options. + */ +#if (JERRY_CPOINTER_32_BIT != 0) && (JERRY_CPOINTER_32_BIT != 1) +#error "Invalid value for 'JERRY_CPOINTER_32_BIT' macro." +#endif /* (JERRY_CPOINTER_32_BIT != 0) && (JERRY_CPOINTER_32_BIT != 1) */ +#if (JERRY_ERROR_MESSAGES != 0) && (JERRY_ERROR_MESSAGES != 1) +#error "Invalid value for 'JERRY_ERROR_MESSAGES' macro." +#endif /* (JERRY_ERROR_MESSAGES != 0) && (JERRY_ERROR_MESSAGES != 1) */ +#if (JERRY_EXTERNAL_CONTEXT != 0) && (JERRY_EXTERNAL_CONTEXT != 1) +#error "Invalid value for 'JERRY_EXTERNAL_CONTEXT' macro." +#endif /* (JERRY_EXTERNAL_CONTEXT != 0) && (JERRY_EXTERNAL_CONTEXT != 1) */ +#if JERRY_GLOBAL_HEAP_SIZE <= 0 +#error "Invalid value for 'JERRY_GLOBAL_HEAP_SIZE' macro." +#endif /* JERRY_GLOBAL_HEAP_SIZE <= 0 */ +#if JERRY_GC_LIMIT < 0 +#error "Invalid value for 'JERRY_GC_LIMIT' macro." +#endif /* JERRY_GC_LIMIT < 0 */ +#if JERRY_STACK_LIMIT < 0 +#error "Invalid value for 'JERRY_STACK_LIMIT' macro." +#endif /* JERRY_STACK_LIMIT < 0 */ +#if JERRY_GC_MARK_LIMIT < 0 +#error "Invalid value for 'JERRY_GC_MARK_LIMIT' macro." +#endif /* JERRY_GC_MARK_LIMIT < 0 */ +#if (JERRY_LCACHE != 0) && (JERRY_LCACHE != 1) +#error "Invalid value for 'JERRY_LCACHE' macro." +#endif /* (JERRY_LCACHE != 0) && (JERRY_LCACHE != 1) */ +#if (JERRY_FUNCTION_TO_STRING != 0) && (JERRY_FUNCTION_TO_STRING != 1) +#error "Invalid value for 'JERRY_FUNCTION_TO_STRING' macro." +#endif /* (JERRY_FUNCTION_TO_STRING != 0) && (JERRY_FUNCTION_TO_STRING != 1) */ +#if (JERRY_LINE_INFO != 0) && (JERRY_LINE_INFO != 1) +#error "Invalid value for 'JERRY_LINE_INFO' macro." +#endif /* (JERRY_LINE_INFO != 0) && (JERRY_LINE_INFO != 1) */ +#if (JERRY_LOGGING != 0) && (JERRY_LOGGING != 1) +#error "Invalid value for 'JERRY_LOGGING' macro." +#endif /* (JERRY_LOGGING != 0) && (JERRY_LOGGING != 1) */ +#if (JERRY_MEM_GC_BEFORE_EACH_ALLOC != 0) && (JERRY_MEM_GC_BEFORE_EACH_ALLOC != 1) +#error "Invalid value for 'JERRY_MEM_GC_BEFORE_EACH_ALLOC' macro." +#endif /* (JERRY_MEM_GC_BEFORE_EACH_ALLOC != 0) && (JERRY_MEM_GC_BEFORE_EACH_ALLOC != 1) */ +#if (JERRY_NUMBER_TYPE_FLOAT64 != 0) && (JERRY_NUMBER_TYPE_FLOAT64 != 1) +#error "Invalid value for 'JERRY_NUMBER_TYPE_FLOAT64' macro." +#endif /* (JERRY_NUMBER_TYPE_FLOAT64 != 0) && (JERRY_NUMBER_TYPE_FLOAT64 != 1) */ +#if (JERRY_PARSER != 0) && (JERRY_PARSER != 1) +#error "Invalid value for 'JERRY_PARSER' macro." +#endif /* (JERRY_PARSER != 0) && (JERRY_PARSER != 1) */ +#if (JERRY_PARSER_DUMP_BYTE_CODE != 0) && (JERRY_PARSER_DUMP_BYTE_CODE != 1) +#error "Invalid value for 'JERRY_PARSER_DUMP_BYTE_CODE' macro." +#endif /* (JERRY_PARSER_DUMP_BYTE_CODE != 0) && (JERRY_PARSER_DUMP_BYTE_CODE != 1) */ +#if (JERRY_PROPERTY_HASHMAP != 0) && (JERRY_PROPERTY_HASHMAP != 1) +#error "Invalid value for 'JERRY_PROPERTY_HASHMAP' macro." +#endif /* (JERRY_PROPERTY_HASHMAP != 0) && (JERRY_PROPERTY_HASHMAP != 1) */ +#if (JERRY_PROMISE_CALLBACK != 0) && (JERRY_PROMISE_CALLBACK != 1) +#error "Invalid value for 'JERRY_PROMISE_CALLBACK' macro." +#endif /* (JERRY_PROMISE_CALLBACK != 0) && (JERRY_PROMISE_CALLBACK != 1) */ +#if (JERRY_REGEXP_DUMP_BYTE_CODE != 0) && (JERRY_REGEXP_DUMP_BYTE_CODE != 1) +#error "Invalid value for 'JERRY_REGEXP_DUMP_BYTE_CODE' macro." +#endif /* (JERRY_REGEXP_DUMP_BYTE_CODE != 0) && (JERRY_REGEXP_DUMP_BYTE_CODE != 1) */ +#if (JERRY_REGEXP_STRICT_MODE != 0) && (JERRY_REGEXP_STRICT_MODE != 1) +#error "Invalid value for 'JERRY_REGEXP_STRICT_MODE' macro." +#endif /* (JERRY_REGEXP_STRICT_MODE != 0) && (JERRY_REGEXP_STRICT_MODE != 1) */ +#if (JERRY_SNAPSHOT_EXEC != 0) && (JERRY_SNAPSHOT_EXEC != 1) +#error "Invalid value for 'JERRY_SNAPSHOT_EXEC' macro." +#endif /* (JERRY_SNAPSHOT_EXEC != 0) && (JERRY_SNAPSHOT_EXEC != 1) */ +#if (JERRY_SNAPSHOT_SAVE != 0) && (JERRY_SNAPSHOT_SAVE != 1) +#error "Invalid value for 'JERRY_SNAPSHOT_SAVE' macro." +#endif /* (JERRY_SNAPSHOT_SAVE != 0) && (JERRY_SNAPSHOT_SAVE != 1) */ +#if (JERRY_SYSTEM_ALLOCATOR != 0) && (JERRY_SYSTEM_ALLOCATOR != 1) +#error "Invalid value for 'JERRY_SYSTEM_ALLOCATOR' macro." +#endif /* (JERRY_SYSTEM_ALLOCATOR != 0) && (JERRY_SYSTEM_ALLOCATOR != 1) */ +#if (JERRY_UNICODE_CASE_CONVERSION != 0) && (JERRY_UNICODE_CASE_CONVERSION != 1) +#error "Invalid value for 'JERRY_UNICODE_CASE_CONVERSION' macro." +#endif /* (JERRY_UNICODE_CASE_CONVERSION != 0) && (JERRY_UNICODE_CASE_CONVERSION != 1) */ +#if (JERRY_VALGRIND != 0) && (JERRY_VALGRIND != 1) +#error "Invalid value for 'JERRY_VALGRIND' macro." +#endif /* (JERRY_VALGRIND != 0) && (JERRY_VALGRIND != 1) */ +#if (JERRY_VM_HALT != 0) && (JERRY_VM_HALT != 1) +#error "Invalid value for 'JERRY_VM_HALT' macro." +#endif /* (JERRY_VM_HALT != 0) && (JERRY_VM_HALT != 1) */ +#if (JERRY_VM_THROW != 0) && (JERRY_VM_THROW != 1) +#error "Invalid value for 'JERRY_VM_THROW' macro." +#endif /* (JERRY_VM_THROW != 0) && (JERRY_VM_THROW != 1) */ + +/** + * Cross component requirements check. + */ + +/** + * The date module can only use the float 64 number types. + */ +#if JERRY_BUILTIN_DATE && !JERRY_NUMBER_TYPE_FLOAT64 +#error "Date does not support float32" +#endif /* JERRY_BUILTIN_DATE && !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Source name related types into a single guard + */ +#if JERRY_LINE_INFO || JERRY_ERROR_MESSAGES || JERRY_MODULE_SYSTEM +#define JERRY_SOURCE_NAME 1 +#else /* !(JERRY_LINE_INFO || JERRY_ERROR_MESSAGES || JERRY_MODULE_SYSTEM) */ +#define JERRY_SOURCE_NAME 0 +#endif /* JERRY_LINE_INFO || JERRY_ERROR_MESSAGES || JERRY_MODULE_SYSTEM */ + +#endif /* !JERRYSCRIPT_CONFIG_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-compiler.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-compiler.h new file mode 100644 index 00000000..071ad0bf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-compiler.h @@ -0,0 +1,187 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_COMPILER_H +#define JERRYSCRIPT_COMPILER_H + +#ifdef __cplusplus +#define JERRY_C_API_BEGIN extern "C" { +#define JERRY_C_API_END } +#else /* !__cplusplus */ +#define JERRY_C_API_BEGIN +#define JERRY_C_API_END +#endif /* __cplusplus */ + +JERRY_C_API_BEGIN + +/** \addtogroup jerry-compiler Jerry compiler compatibility components + * @{ + */ + +#ifdef __GNUC__ + +/* + * Compiler-specific macros relevant for GCC. + */ +#define JERRY_ATTR_ALIGNED(ALIGNMENT) __attribute__ ((aligned (ALIGNMENT))) +#define JERRY_ATTR_CONST __attribute__ ((const)) +#define JERRY_ATTR_DEPRECATED __attribute__ ((deprecated)) +#define JERRY_ATTR_FORMAT(...) __attribute__ ((format (__VA_ARGS__))) +#define JERRY_ATTR_HOT __attribute__ ((hot)) +#define JERRY_ATTR_NOINLINE __attribute__ ((noinline)) +#define JERRY_ATTR_NORETURN __attribute__ ((noreturn)) +#define JERRY_ATTR_PURE __attribute__ ((pure)) +#define JERRY_ATTR_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result)) +#define JERRY_ATTR_WEAK __attribute__ ((weak)) + +#define JERRY_WEAK_SYMBOL_SUPPORT + +#ifndef JERRY_LIKELY +#define JERRY_LIKELY(x) __builtin_expect (!!(x), 1) +#endif /* !JERRY_LIKELY */ + +#ifndef JERRY_UNLIKELY +#define JERRY_UNLIKELY(x) __builtin_expect (!!(x), 0) +#endif /* !JERRY_UNLIKELY */ + +#endif /* __GNUC__ */ + +#ifdef _MSC_VER + +/* + * Compiler-specific macros relevant for Microsoft Visual C/C++ Compiler. + */ +#define JERRY_ATTR_DEPRECATED __declspec (deprecated) +#define JERRY_ATTR_NOINLINE __declspec (noinline) +#define JERRY_ATTR_NORETURN __declspec (noreturn) + +/* + * Microsoft Visual C/C++ Compiler doesn't support for VLA, using _alloca + * instead. + */ +void *__cdecl _alloca (size_t _Size); +#define JERRY_VLA(type, name, size) type *name = (type *) (_alloca (sizeof (type) * (size))) + +#endif /* _MSC_VER */ + +/* + * Default empty definitions for all compiler-specific macros. Define any of + * these in a guarded block above (e.g., as for GCC) to fine tune compilation + * for your own compiler. */ + +/** + * Function attribute to align function to given number of bytes. + */ +#ifndef JERRY_ATTR_ALIGNED +#define JERRY_ATTR_ALIGNED(ALIGNMENT) +#endif /* !JERRY_ATTR_ALIGNED */ + + +/** + * Function attribute to declare that function has no effect except the return + * value and it only depends on parameters. + */ +#ifndef JERRY_ATTR_CONST +#define JERRY_ATTR_CONST +#endif /* !JERRY_ATTR_CONST */ + +/** + * Function attribute to trigger warning if deprecated function is called. + */ +#ifndef JERRY_ATTR_DEPRECATED +#define JERRY_ATTR_DEPRECATED +#endif /* !JERRY_ATTR_DEPRECATED */ + +/** + * Function attribute to declare that function is variadic and takes a format + * string and some arguments as parameters. + */ +#ifndef JERRY_ATTR_FORMAT +#define JERRY_ATTR_FORMAT(...) +#endif /* !JERRY_ATTR_FORMAT */ + +/** + * Function attribute to predict that function is a hot spot, and therefore + * should be optimized aggressively. + */ +#ifndef JERRY_ATTR_HOT +#define JERRY_ATTR_HOT +#endif /* !JERRY_ATTR_HOT */ + +/** + * Function attribute not to inline function ever. + */ +#ifndef JERRY_ATTR_NOINLINE +#define JERRY_ATTR_NOINLINE +#endif /* !JERRY_ATTR_NOINLINE */ + +/** + * Function attribute to declare that function never returns. + */ +#ifndef JERRY_ATTR_NORETURN +#define JERRY_ATTR_NORETURN +#endif /* !JERRY_ATTR_NORETURN */ + +/** + * Function attribute to declare that function has no effect except the return + * value and it only depends on parameters and global variables. + */ +#ifndef JERRY_ATTR_PURE +#define JERRY_ATTR_PURE +#endif /* !JERRY_ATTR_PURE */ + +/** + * Function attribute to trigger warning if function's caller doesn't use (e.g., + * check) the return value. + */ +#ifndef JERRY_ATTR_WARN_UNUSED_RESULT +#define JERRY_ATTR_WARN_UNUSED_RESULT +#endif /* !JERRY_ATTR_WARN_UNUSED_RESULT */ + +/** + * Function attribute to declare a function a weak symbol + */ +#ifndef JERRY_ATTR_WEAK +#define JERRY_ATTR_WEAK +#endif /* !JERRY_ATTR_WEAK */ + +/** + * Helper to predict that a condition is likely. + */ +#ifndef JERRY_LIKELY +#define JERRY_LIKELY(x) (x) +#endif /* !JERRY_LIKELY */ + +/** + * Helper to predict that a condition is unlikely. + */ +#ifndef JERRY_UNLIKELY +#define JERRY_UNLIKELY(x) (x) +#endif /* !JERRY_UNLIKELY */ + +/** + * Helper to declare (or mimic) a C99 variable-length array. + */ +#ifndef JERRY_VLA +#define JERRY_VLA(type, name, size) type name[size] +#endif /* !JERRY_VLA */ + +/** + * @} + */ + +JERRY_C_API_END + +#endif /* !JERRYSCRIPT_COMPILER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-core.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-core.h new file mode 100644 index 00000000..b034b109 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-core.h @@ -0,0 +1,1209 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_CORE_H +#define JERRYSCRIPT_CORE_H + +#include "jerryscript-types.h" + +JERRY_C_API_BEGIN + +/** + * @defgroup jerry-api JerryScript public API + * @{ + */ + +/** + * @defgroup jerry-api-general General functions + * @{ + */ + +/** + * @defgroup jerry-api-general-conext Context management + * @{ + */ +void jerry_init (jerry_init_flag_t flags); +void jerry_cleanup (void); + +void *jerry_context_data (const jerry_context_data_manager_t *manager_p); + +jerry_value_t jerry_current_realm (void); +jerry_value_t jerry_set_realm (jerry_value_t realm); +/** + * jerry-api-general-conext @} + */ + +/** + * @defgroup jerry-api-general-heap Heap management + * @{ + */ +void *jerry_heap_alloc (jerry_size_t size); +void jerry_heap_free (void *mem_p, jerry_size_t size); + +bool jerry_heap_stats (jerry_heap_stats_t *out_stats_p); +void jerry_heap_gc (jerry_gc_mode_t mode); + +bool jerry_foreach_live_object (jerry_foreach_live_object_cb_t callback, void *user_data); +bool jerry_foreach_live_object_with_info (const jerry_object_native_info_t *native_info_p, + jerry_foreach_live_object_with_info_cb_t callback, + void *user_data_p); +/** + * jerry-api-general-heap @} + */ + +/** + * @defgroup jerry-api-general-misc Miscellaneous + * @{ + */ + +void JERRY_ATTR_FORMAT (printf, 2, 3) jerry_log (jerry_log_level_t level, const char *format_p, ...); +void jerry_log_set_level (jerry_log_level_t level); +bool jerry_validate_string (const jerry_char_t *buffer_p, jerry_size_t buffer_size, jerry_encoding_t encoding); +bool JERRY_ATTR_CONST jerry_feature_enabled (const jerry_feature_t feature); +void jerry_register_magic_strings (const jerry_char_t *const *ext_strings_p, + uint32_t count, + const jerry_length_t *str_lengths_p); +/** + * jerry-api-general-misc @} + */ + +/** + * jerry-api-general @} + */ + +/** + * @defgroup jerry-api-code Scripts and Executables + * @{ + */ + +/** + * @defgroup jerry-api-code-parse Parsing + * @{ + */ +jerry_value_t jerry_parse (const jerry_char_t *source_p, size_t source_size, const jerry_parse_options_t *options_p); +jerry_value_t jerry_parse_value (const jerry_value_t source, const jerry_parse_options_t *options_p); +/** + * jerry-api-code-parse @} + */ + +/** + * @defgroup jerry-api-code-exec Execution + * @{ + */ +jerry_value_t jerry_eval (const jerry_char_t *source_p, size_t source_size, uint32_t flags); +jerry_value_t jerry_run (const jerry_value_t script); +jerry_value_t jerry_run_jobs (void); +/** + * jerry-api-code-exec @} + */ + +/** + * @defgroup jerry-api-code-sourceinfo Source information + * @{ + */ +jerry_value_t jerry_source_name (const jerry_value_t value); +jerry_value_t jerry_source_user_value (const jerry_value_t value); +jerry_source_info_t *jerry_source_info (const jerry_value_t value); +void jerry_source_info_free (jerry_source_info_t *source_info_p); +/** + * jerry-api-code-sourceinfo @} + */ + +/** + * @defgroup jerry-api-code-cb Callbacks + * @{ + */ +void jerry_halt_handler (uint32_t interval, jerry_halt_cb_t callback, void *user_p); +/** + * jerry-api-code-cb @} + */ + +/** + * jerry-api-code @} + */ + +/** + * @defgroup jerry-api-backtrace Backtraces + * @{ + */ + +/** + * @defgroup jerry-api-backtrace-capture Capturing + * @{ + */ +jerry_value_t jerry_backtrace (uint32_t max_depth); +void jerry_backtrace_capture (jerry_backtrace_cb_t callback, void *user_p); +/** + * jerry-api-backtrace-capture @} + */ + +/** + * @defgroup jerry-api-backtrace-frame Frames + * @{ + */ +jerry_frame_type_t jerry_frame_type (const jerry_frame_t *frame_p); +const jerry_value_t *jerry_frame_callee (jerry_frame_t *frame_p); +const jerry_value_t *jerry_frame_this (jerry_frame_t *frame_p); +const jerry_frame_location_t *jerry_frame_location (jerry_frame_t *frame_p); +bool jerry_frame_is_strict (jerry_frame_t *frame_p); +/** + * jerry-api-backtrace-frame @} + */ + +/** + * jerry-api-backtrace @} + */ + +/** + * @defgroup jerry-api-value Values + * @{ + */ + +/* Reference management */ +jerry_value_t JERRY_ATTR_WARN_UNUSED_RESULT jerry_value_copy (const jerry_value_t value); +void jerry_value_free (jerry_value_t value); + +/** + * @defgroup jerry-api-value-checks Type inspection + * @{ + */ +jerry_type_t jerry_value_type (const jerry_value_t value); +bool jerry_value_is_exception (const jerry_value_t value); +bool jerry_value_is_abort (const jerry_value_t value); + +bool jerry_value_is_undefined (const jerry_value_t value); +bool jerry_value_is_null (const jerry_value_t value); +bool jerry_value_is_boolean (const jerry_value_t value); +bool jerry_value_is_true (const jerry_value_t value); +bool jerry_value_is_false (const jerry_value_t value); + +bool jerry_value_is_number (const jerry_value_t value); +bool jerry_value_is_bigint (const jerry_value_t value); + +bool jerry_value_is_string (const jerry_value_t value); +bool jerry_value_is_symbol (const jerry_value_t value); + +bool jerry_value_is_object (const jerry_value_t value); +bool jerry_value_is_array (const jerry_value_t value); +bool jerry_value_is_promise (const jerry_value_t value); +bool jerry_value_is_proxy (const jerry_value_t value); +bool jerry_value_is_arraybuffer (const jerry_value_t value); +bool jerry_value_is_shared_arraybuffer (const jerry_value_t value); +bool jerry_value_is_dataview (const jerry_value_t value); +bool jerry_value_is_typedarray (const jerry_value_t value); + +bool jerry_value_is_constructor (const jerry_value_t value); +bool jerry_value_is_function (const jerry_value_t value); +bool jerry_value_is_async_function (const jerry_value_t value); + +bool jerry_value_is_error (const jerry_value_t value); +/** + * jerry-api-value-checks @} + */ + +/** + * @defgroup jerry-api-value-coerce Coercion + * @{ + */ +bool jerry_value_to_boolean (const jerry_value_t value); +jerry_value_t jerry_value_to_number (const jerry_value_t value); +jerry_value_t jerry_value_to_object (const jerry_value_t value); +jerry_value_t jerry_value_to_primitive (const jerry_value_t value); +jerry_value_t jerry_value_to_string (const jerry_value_t value); +jerry_value_t jerry_value_to_bigint (const jerry_value_t value); + +double jerry_value_as_number (const jerry_value_t value); +double jerry_value_as_integer (const jerry_value_t value); +int32_t jerry_value_as_int32 (const jerry_value_t value); +uint32_t jerry_value_as_uint32 (const jerry_value_t value); +/** + * jerry-api-value-coerce @} + */ + +/** + * @defgroup jerry-api-value-op Operations + * @{ + */ +jerry_value_t jerry_binary_op (jerry_binary_op_t operation, const jerry_value_t lhs, const jerry_value_t rhs); + +/** + * jerry-api-value-op @} + */ + +/** + * jerry-api-value @} + */ + +/** + * @defgroup jerry-api-exception Exceptions + * @{ + */ + +/** + * @defgroup jerry-api-exception-ctor Constructors + * @{ + */ +jerry_value_t jerry_throw (jerry_error_t type, const jerry_value_t message); +jerry_value_t jerry_throw_sz (jerry_error_t type, const char *message_p); +jerry_value_t jerry_throw_value (jerry_value_t value, bool take_ownership); +jerry_value_t jerry_throw_abort (jerry_value_t value, bool take_ownership); +/** + * jerry-api-exception-ctor @} + */ + +/** + * @defgroup jerry-api-exception-op Operations + * @{ + */ +void jerry_exception_allow_capture (jerry_value_t value, bool allow_capture); +/** + * jerry-api-exception-op @} + */ + +/** + * @defgroup jerry-api-exception-get Getters + * @{ + */ +jerry_value_t jerry_exception_value (jerry_value_t value, bool free_exception); +bool jerry_exception_is_captured (const jerry_value_t value); +/** + * jerry-api-exception-get @} + */ + +/** + * @defgroup jerry-api-exception-cb Callbacks + * @{ + */ +void jerry_on_throw (jerry_throw_cb_t callback, void *user_p); +/** + * jerry-api-exception-cb @} + */ + +/** + * jerry-api-error @} + */ + +/** + * @defgroup jerry-api-primitives Primitive types + * @{ + */ + +/** + * @defgroup jerry-api-undefined Undefined + * @{ + */ + +/** + * @defgroup jerry-api-undefined-ctor Constructors + * @{ + */ + +jerry_value_t JERRY_ATTR_CONST jerry_undefined (void); + +/** + * jerry-api-undefined-ctor @} + */ + +/** + * jerry-api-undefined @} + */ + +/** + * @defgroup jerry-api-null Null + * @{ + */ + +/** + * @defgroup jerry-api-null-ctor Constructors + * @{ + */ + +jerry_value_t JERRY_ATTR_CONST jerry_null (void); + +/** + * jerry-api-null-ctor @} + */ + +/** + * jerry-api-null @} + */ + +/** + * @defgroup jerry-api-boolean Boolean + * @{ + */ + +/** + * @defgroup jerry-api-boolean-ctor Constructors + * @{ + */ + +jerry_value_t JERRY_ATTR_CONST jerry_boolean (bool value); + +/** + * jerry-api-boolean-ctor @} + */ + +/** + * jerry-api-boolean @} + */ + +/** + * @defgroup jerry-api-number Number + * @{ + */ + +/** + * @defgroup jerry-api-number-ctor Number + * @{ + */ + +jerry_value_t jerry_number (double value); +jerry_value_t jerry_infinity (bool sign); +jerry_value_t jerry_nan (void); + +/** + * jerry-api-number-ctor @} + */ + +/** + * jerry-api-number @} + */ + +/** + * @defgroup jerry-api-bigint BigInt + * @{ + */ + +/** + * @defgroup jerry-api-bigint-ctor Constructors + * @{ + */ +jerry_value_t jerry_bigint (const uint64_t *digits_p, uint32_t digit_count, bool sign); +/** + * jerry-api-bigint-ctor @} + */ + +/** + * @defgroup jerry-api-bigint-get Getters + * @{ + */ +uint32_t jerry_bigint_digit_count (const jerry_value_t value); +/** + * jerry-api-bigint-get @} + */ + +/** + * @defgroup jerry-api-bigint-op Operations + * @{ + */ +void jerry_bigint_to_digits (const jerry_value_t value, uint64_t *digits_p, uint32_t digit_count, bool *sign_p); +/** + * jerry-api-bigint-get @} + */ + +/** + * jerry-api-bigint @} + */ + +/** + * @defgroup jerry-api-string String + * @{ + */ + +/** + * @defgroup jerry-api-string-ctor Constructors + * @{ + */ +jerry_value_t jerry_string (const jerry_char_t *buffer_p, jerry_size_t buffer_size, jerry_encoding_t encoding); +jerry_value_t jerry_string_sz (const char *str_p); +jerry_value_t jerry_string_external (const jerry_char_t *buffer_p, jerry_size_t buffer_size, void *user_p); +jerry_value_t jerry_string_external_sz (const char *str_p, void *user_p); +/** + * jerry-api-string-cotr @} + */ + +/** + * @defgroup jerry-api-string-get Getters + * @{ + */ +jerry_size_t jerry_string_size (const jerry_value_t value, jerry_encoding_t encoding); +jerry_length_t jerry_string_length (const jerry_value_t value); +void *jerry_string_user_ptr (const jerry_value_t value, bool *is_external); +/** + * jerry-api-string-get @} + */ + +/** + * @defgroup jerry-api-string-op Operations + * @{ + */ +jerry_size_t jerry_string_substr (const jerry_value_t value, jerry_length_t start, jerry_length_t end); +jerry_size_t jerry_string_to_buffer (const jerry_value_t value, + jerry_encoding_t encoding, + jerry_char_t *buffer_p, + jerry_size_t buffer_size); +void jerry_string_iterate (const jerry_value_t value, + jerry_encoding_t encoding, + jerry_string_iterate_cb_t callback, + void *user_p); +/** + * jerry-api-string-op @} + */ + +/** + * @defgroup jerry-api-string-cb Callbacks + * @{ + */ +void jerry_string_external_on_free (jerry_external_string_free_cb_t callback); +/** + * jerry-api-string-cb @} + */ + +/** + * jerry-api-string @} + */ + +/** + * @defgroup jerry-api-symbol Symbol + * @{ + */ + +/** + * @defgroup jerry-api-symbol-ctor Constructors + * @{ + */ +jerry_value_t jerry_symbol (jerry_well_known_symbol_t symbol); +jerry_value_t jerry_symbol_with_description (const jerry_value_t value); +/** + * jerry-api-symbol-ctor @} + */ + +/** + * @defgroup jerry-api-symbol-get Getters + * @{ + */ +jerry_value_t jerry_symbol_description (const jerry_value_t symbol); +jerry_value_t jerry_symbol_descriptive_string (const jerry_value_t symbol); +/** + * jerry-api-symbol-get @} + */ + +/** + * jerry-api-symbol @} + */ + +/** + * jerry-api-primitives @} + */ + +/** + * @defgroup jerry-api-objects Objects + * @{ + */ + +/** + * @defgroup jerry-api-object-ctor Constructors + * @{ + */ +jerry_value_t jerry_object (void); +/** + * jerry-api-object-ctor @} + */ + +/** + * @defgroup jerry-api-object-get Getters + * @{ + */ + +jerry_object_type_t jerry_object_type (const jerry_value_t object); +jerry_value_t jerry_object_proto (const jerry_value_t object); +jerry_value_t jerry_object_keys (const jerry_value_t object); +jerry_value_t jerry_object_property_names (const jerry_value_t object, jerry_property_filter_t filter); + +/** + * jerry-api-object-get @} + */ + +/** + * @defgroup jerry-api-object-op Operations + * @{ + */ + +jerry_value_t jerry_object_set_proto (jerry_value_t object, const jerry_value_t proto); +bool jerry_object_foreach (const jerry_value_t object, jerry_object_property_foreach_cb_t foreach_p, void *user_data_p); + +/** + * @defgroup jerry-api-object-op-set Set + * @{ + */ +jerry_value_t jerry_object_set (jerry_value_t object, const jerry_value_t key, const jerry_value_t value); +jerry_value_t jerry_object_set_sz (jerry_value_t object, const char *key_p, const jerry_value_t value); +jerry_value_t jerry_object_set_index (jerry_value_t object, uint32_t index, const jerry_value_t value); +jerry_value_t jerry_object_define_own_prop (jerry_value_t object, + const jerry_value_t key, + const jerry_property_descriptor_t *prop_desc_p); +bool jerry_object_set_internal (jerry_value_t object, const jerry_value_t key, const jerry_value_t value); +void jerry_object_set_native_ptr (jerry_value_t object, + const jerry_object_native_info_t *native_info_p, + void *native_pointer_p); +/** + * jerry-api-object-op-set @} + */ + +/** + * @defgroup jerry-api-object-op-has Has + * @{ + */ +jerry_value_t jerry_object_has (const jerry_value_t object, const jerry_value_t key); +jerry_value_t jerry_object_has_sz (const jerry_value_t object, const char *key_p); +jerry_value_t jerry_object_has_own (const jerry_value_t object, const jerry_value_t key); +bool jerry_object_has_internal (const jerry_value_t object, const jerry_value_t key); +bool jerry_object_has_native_ptr (const jerry_value_t object, const jerry_object_native_info_t *native_info_p); +/** + * jerry-api-object-op-has @} + */ + +/** + * @defgroup jerry-api-object-op-get Get + * @{ + */ +jerry_value_t jerry_object_get (const jerry_value_t object, const jerry_value_t key); +jerry_value_t jerry_object_get_sz (const jerry_value_t object, const char *key_p); +jerry_value_t jerry_object_get_index (const jerry_value_t object, uint32_t index); +jerry_value_t jerry_object_get_own_prop (const jerry_value_t object, + const jerry_value_t key, + jerry_property_descriptor_t *prop_desc_p); +jerry_value_t jerry_object_get_internal (const jerry_value_t object, const jerry_value_t key); +void *jerry_object_get_native_ptr (const jerry_value_t object, const jerry_object_native_info_t *native_info_p); + +jerry_value_t jerry_object_find_own (const jerry_value_t object, + const jerry_value_t key, + const jerry_value_t receiver, + bool *found_p); +/** + * jerry-api-object-op-get @} + */ + +/** + * @defgroup jerry-api-object-op-del Delete + * @{ + */ +jerry_value_t jerry_object_delete (jerry_value_t object, const jerry_value_t key); +jerry_value_t jerry_object_delete_sz (const jerry_value_t object, const char *key_p); +jerry_value_t jerry_object_delete_index (jerry_value_t object, uint32_t index); +bool jerry_object_delete_internal (jerry_value_t object, const jerry_value_t key); +bool jerry_object_delete_native_ptr (jerry_value_t object, const jerry_object_native_info_t *native_info_p); +/** + * jerry-api-object-op-del @} + */ + +/** + * jerry-api-object-op @} + */ + +/** + * @defgroup jerry-api-object-prop-desc Property descriptors + * @{ + */ + +/** + * @defgroup jerry-api-object-prop-desc-ctor Constructors + * @{ + */ +jerry_property_descriptor_t jerry_property_descriptor (void); +jerry_value_t jerry_property_descriptor_from_object (const jerry_value_t obj_value, + jerry_property_descriptor_t *out_prop_desc_p); +/** + * jerry-api-object-prop-desc-ctor @} + */ + +/** + * @defgroup jerry-api-object-prop-desc-op Operations + * @{ + */ +void jerry_property_descriptor_free (jerry_property_descriptor_t *prop_desc_p); +jerry_value_t jerry_property_descriptor_to_object (const jerry_property_descriptor_t *src_prop_desc_p); +/** + * jerry-api-object-prop-desc-op @} + */ + +/** + * jerry-api-object-prop-desc @} + */ + +/** + * @defgroup jerry-api-object-native-ptr Native pointers + * @{ + */ + +/** + * @defgroup jerry-api-object-native-ptr-op Operations + * @{ + */ +void jerry_native_ptr_init (void *native_pointer_p, const jerry_object_native_info_t *native_info_p); +void jerry_native_ptr_free (void *native_pointer_p, const jerry_object_native_info_t *native_info_p); +void jerry_native_ptr_set (jerry_value_t *reference_p, const jerry_value_t value); +/** + * jerry-api-object-native-ptr-op @} + */ + +/** + * jerry-api-object-native-ptr @} + */ + +/** + * @defgroup jerry-api-array Array + * @{ + */ + +/** + * @defgroup jerry-api-array-ctor Constructors + * @{ + */ +jerry_value_t jerry_array (jerry_length_t length); +/** + * jerry-api-array-ctor @} + */ + +/** + * @defgroup jerry-api-array-get Getters + * @{ + */ +jerry_length_t jerry_array_length (const jerry_value_t value); +/** + * jerry-api-array-get @} + */ + +/** + * jerry-api-array @} + */ + +/** + * @defgroup jerry-api-arraybuffer ArrayBuffer + * @{ + */ + +/** + * @defgroup jerry-api-arraybuffer-ctor Constructors + * @{ + */ +jerry_value_t jerry_arraybuffer (const jerry_length_t size); +jerry_value_t jerry_arraybuffer_external (uint8_t *buffer_p, jerry_length_t size, void *user_p); +/** + * jerry-api-arraybuffer-ctor @} + */ + +/** + * @defgroup jerry-api-arraybuffer-get Getters + * @{ + */ +jerry_size_t jerry_arraybuffer_size (const jerry_value_t value); +uint8_t *jerry_arraybuffer_data (const jerry_value_t value); +bool jerry_arraybuffer_is_detachable (const jerry_value_t value); +bool jerry_arraybuffer_has_buffer (const jerry_value_t value); +/** + * jerry-api-arraybuffer-get @} + */ + +/** + * @defgroup jerry-api-arraybuffer-op Operations + * @{ + */ +jerry_size_t +jerry_arraybuffer_read (const jerry_value_t value, jerry_size_t offset, uint8_t *buffer_p, jerry_size_t buffer_size); +jerry_size_t +jerry_arraybuffer_write (jerry_value_t value, jerry_size_t offset, const uint8_t *buffer_p, jerry_size_t buffer_size); +jerry_value_t jerry_arraybuffer_detach (jerry_value_t value); +void jerry_arraybuffer_heap_allocation_limit (jerry_size_t limit); +/** + * jerry-api-arraybuffer-op @} + */ + +/** + * @defgroup jerry-api-arraybuffer-cb Callbacks + * @{ + */ +void jerry_arraybuffer_allocator (jerry_arraybuffer_allocate_cb_t allocate_callback, + jerry_arraybuffer_free_cb_t free_callback, + void *user_p); +/** + * jerry-api-arraybuffer-cb @} + */ + +/** + * jerry-api-arraybuffer @} + */ + +/** + * @defgroup jerry-api-sharedarraybuffer SharedArrayBuffer + * @{ + */ + +/** + * @defgroup jerry-api-sharedarraybuffer-ctor Constructors + * @{ + */ +jerry_value_t jerry_shared_arraybuffer (jerry_size_t size); +jerry_value_t jerry_shared_arraybuffer_external (uint8_t *buffer_p, jerry_size_t buffer_size, void *user_p); +/** + * jerry-api-sharedarraybuffer-ctor @} + */ + +/** + * jerry-api-sharedarraybuffer @} + */ + +/** + * @defgroup jerry-api-dataview DataView + * @{ + */ + +/** + * @defgroup jerry-api-dataview-ctor Constructors + * @{ + */ +jerry_value_t jerry_dataview (const jerry_value_t value, jerry_size_t byte_offset, jerry_size_t byte_length); +/** + * jerry-api-dataview-ctr @} + */ + +/** + * @defgroup jerry-api-dataview-get Getters + * @{ + */ +jerry_value_t +jerry_dataview_buffer (const jerry_value_t dataview, jerry_size_t *byte_offset, jerry_size_t *byte_length); +/** + * jerry-api-dataview-get @} + */ + +/** + * jerry-api-dataview @} + */ + +/** + * @defgroup jerry-api-typedarray TypedArray + * @{ + */ + +/** + * @defgroup jerry-api-typedarray-ctor Constructors + * @{ + */ +jerry_value_t jerry_typedarray (jerry_typedarray_type_t type, jerry_length_t length); +jerry_value_t jerry_typedarray_with_buffer (jerry_typedarray_type_t type, const jerry_value_t arraybuffer); +jerry_value_t jerry_typedarray_with_buffer_span (jerry_typedarray_type_t type, + const jerry_value_t arraybuffer, + jerry_size_t byte_offset, + jerry_size_t byte_length); +/** + * jerry-api-typedarray-ctor @} + */ + +/** + * @defgroup jerry-api-typedarray-get Getters + * @{ + */ +jerry_typedarray_type_t jerry_typedarray_type (const jerry_value_t value); +jerry_length_t jerry_typedarray_length (const jerry_value_t value); +jerry_value_t jerry_typedarray_buffer (const jerry_value_t value, jerry_size_t *byte_offset, jerry_size_t *byte_length); +/** + * jerry-api-typedarray-get @} + */ + +/** + * jerry-api-typedarray @} + */ + +/** + * @defgroup jerry-api-iterator Iterator + * @{ + */ + +/** + * @defgroup jerry-api-iterator-get Getters + * @{ + */ +jerry_iterator_type_t jerry_iterator_type (const jerry_value_t value); +/** + * jerry-api-iterator-get @} + */ + +/** + * jerry-api-iterator @} + */ + +/** + * @defgroup jerry-api-function Function + * @{ + */ + +/** + * @defgroup jerry-api-function-ctor Constructors + * @{ + */ +jerry_value_t jerry_function_external (jerry_external_handler_t handler); +/** + * jerry-api-function-ctor @} + */ + +/** + * @defgroup jerry-api-function-get Getters + * @{ + */ +jerry_function_type_t jerry_function_type (const jerry_value_t value); +bool jerry_function_is_dynamic (const jerry_value_t value); +/** + * jerry-api-function-get @} + */ + +/** + * @defgroup jerry-api-function-op Operations + * @{ + */ +jerry_value_t jerry_call (const jerry_value_t function, + const jerry_value_t this_value, + const jerry_value_t *args_p, + jerry_size_t args_count); +jerry_value_t jerry_construct (const jerry_value_t function, const jerry_value_t *args_p, jerry_size_t args_count); +/** + * jerry-api-function-op @} + */ + +/** + * jerry-api-function @} + */ + +/** + * @defgroup jerry-api-proxy Proxy + * @{ + */ + +/** + * @defgroup jerry-api-proxy-ctor Constructors + * @{ + */ +jerry_value_t jerry_proxy (const jerry_value_t target, const jerry_value_t handler); +jerry_value_t jerry_proxy_custom (const jerry_value_t target, const jerry_value_t handler, uint32_t flags); +/** + * jerry-api-function-proxy-ctor @} + */ + +/** + * @defgroup jerry-api-proxy-get Getters + * @{ + */ +jerry_value_t jerry_proxy_target (const jerry_value_t value); +jerry_value_t jerry_proxy_handler (const jerry_value_t value); +/** + * jerry-api-function-proxy-get @} + */ + +/** + * jerry-api-proxy @} + */ + +/** + * @defgroup jerry-api-promise Promise + * @{ + */ + +/** + * @defgroup jerry-api-promise-ctor Constructors + * @{ + */ +jerry_value_t jerry_promise (void); +/** + * jerry-api-promise-ctor @} + */ + +/** + * @defgroup jerry-api-promise-get Getters + * @{ + */ +jerry_value_t jerry_promise_result (const jerry_value_t promise); +jerry_promise_state_t jerry_promise_state (const jerry_value_t promise); +/** + * jerry-api-promise-get @} + */ + +/** + * @defgroup jerry-api-promise-op Operations + * @{ + */ +jerry_value_t jerry_promise_resolve (jerry_value_t promise, const jerry_value_t argument); +jerry_value_t jerry_promise_reject (jerry_value_t promise, const jerry_value_t argument); +/** + * jerry-api-promise-op @} + */ + +/** + * @defgroup jerry-api-promise-cb Callbacks + * @{ + */ +void jerry_promise_on_event (jerry_promise_event_filter_t filters, jerry_promise_event_cb_t callback, void *user_p); +/** + * jerry-api-promise-cb @} + */ + +/** + * jerry-api-promise @} + */ + +/** + * @defgroup jerry-api-container Map, Set, WeakMap, WeakSet + * @{ + */ + +/** + * @defgroup jerry-api-container-ctor Constructors + * @{ + */ +jerry_value_t jerry_container (jerry_container_type_t container_type, + const jerry_value_t *arguments_p, + jerry_length_t argument_count); +/** + * jerry-api-promise-ctor @} + */ + +/** + * @defgroup jerry-api-container-get Getters + * @{ + */ +jerry_container_type_t jerry_container_type (const jerry_value_t value); +/** + * jerry-api-container-get @} + */ + +/** + * @defgroup jerry-api-container-op Operations + * @{ + */ +jerry_value_t jerry_container_to_array (const jerry_value_t value, bool *is_key_value_p); +jerry_value_t jerry_container_op (jerry_container_op_t operation, + jerry_value_t container, + const jerry_value_t *arguments, + uint32_t argument_count); +/** + * jerry-api-container-op @} + */ + +/** + * jerry-api-container @} + */ + +/** + * @defgroup jerry-api-regexp RegExp + * @{ + */ + +/** + * @defgroup jerry-api-regexp-ctor Constructors + * @{ + */ +jerry_value_t jerry_regexp (const jerry_value_t pattern, uint16_t flags); +jerry_value_t jerry_regexp_sz (const char *pattern_p, uint16_t flags); +/** + * jerry-api-regexp-ctor @} + */ + +/** + * jerry-api-regexp @} + */ + +/** + * @defgroup jerry-api-error Error + * @{ + */ + +/** + * @defgroup jerry-api-error-ctor Constructors + * @{ + */ +jerry_value_t jerry_error (jerry_error_t type, const jerry_value_t message); +jerry_value_t jerry_error_sz (jerry_error_t type, const char *message_p); +/** + * jerry-api-error-ctor @} + */ + +/** + * @defgroup jerry-api-error-get Getters + * @{ + */ +jerry_error_t jerry_error_type (jerry_value_t value); +/** + * jerry-api-error-get @} + */ + +/** + * @defgroup jerry-api-error-cb Callbacks + * @{ + */ +void jerry_error_on_created (jerry_error_object_created_cb_t callback, void *user_p); +/** + * jerry-api-error-cb @} + */ + +/** + * jerry-api-error @} + */ + +/** + * jerry-api-objects @} + */ + +/** + * @defgroup jerry-api-json JSON + * @{ + */ + +/** + * @defgroup jerry-api-json-op Operations + * @{ + */ +jerry_value_t jerry_json_parse (const jerry_char_t *string_p, jerry_size_t string_size); +jerry_value_t jerry_json_stringify (const jerry_value_t object); +/** + * jerry-api-json-op @} + */ + +/** + * jerry-api-json @} + */ + +/** + * @defgroup jerry-api-module Modules + * @{ + */ + +/** + * @defgroup jerry-api-module-get Getters + * @{ + */ +jerry_module_state_t jerry_module_state (const jerry_value_t module); +size_t jerry_module_request_count (const jerry_value_t module); +jerry_value_t jerry_module_request (const jerry_value_t module, size_t request_index); +jerry_value_t jerry_module_namespace (const jerry_value_t module); +/** + * jerry-api-module-get @} + */ + +/** + * @defgroup jerry-api-module-op Operations + * @{ + */ + +/** + * Resolve and parse a module file + * + * @param specifier: module request specifier string. + * @param referrer: parent module. + * @param user_p: user specified pointer. + * + * @return module object if resolving is successful, error otherwise. + */ +jerry_value_t jerry_module_resolve (const jerry_value_t specifier, const jerry_value_t referrer, void *user_p); + +jerry_value_t jerry_module_link (const jerry_value_t module, jerry_module_resolve_cb_t callback, void *user_p); +jerry_value_t jerry_module_evaluate (const jerry_value_t module); + +/** + * Release known modules in the current context. If realm parameter is supplied, cleans up modules native to that realm + * only. This function should be called by the user application when the module database in the current context is no + * longer needed. + * + * @param realm: release only those modules which realm value is equal to this argument. + */ +void jerry_module_cleanup (const jerry_value_t realm); + +/** + * jerry-api-module-op @} + */ + +/** + * @defgroup jerry-api-module-native Native modules + * @{ + */ +jerry_value_t jerry_native_module (jerry_native_module_evaluate_cb_t callback, + const jerry_value_t *const exports_p, + size_t export_count); +jerry_value_t jerry_native_module_get (const jerry_value_t native_module, const jerry_value_t export_name); +jerry_value_t +jerry_native_module_set (jerry_value_t native_module, const jerry_value_t export_name, const jerry_value_t value); +/** + * jerry-api-module-native @} + */ + +/** + * @defgroup jerry-api-module-cb Callbacks + * @{ + */ +void jerry_module_on_state_changed (jerry_module_state_changed_cb_t callback, void *user_p); +void jerry_module_on_import_meta (jerry_module_import_meta_cb_t callback, void *user_p); +void jerry_module_on_import (jerry_module_import_cb_t callback, void *user_p); +/** + * jerry-api-module-cb @} + */ + +/** + * jerry-api-module @} + */ + +/** + * @defgroup jerry-api-realm Realms + * @{ + */ + +/** + * @defgroup jerry-api-realm-ctor Constructors + * @{ + */ +jerry_value_t jerry_realm (void); +/** + * jerry-api-realm-ctor @} + */ + +/** + * @defgroup jerry-api-realm-get Getters + * @{ + */ +jerry_value_t jerry_realm_this (jerry_value_t realm); +/** + * jerry-api-realm-ctor @} + */ + +/** + * @defgroup jerry-api-realm-op Operation + * @{ + */ +jerry_value_t jerry_realm_set_this (jerry_value_t realm, jerry_value_t this_value); +/** + * jerry-api-realm-op @} + */ + +/** + * jerry-api-realm @} + */ + +/** + * jerry-api @} + */ + +JERRY_C_API_END + +#endif /* !JERRYSCRIPT_CORE_H */ + +/* vim: set fdm=marker fmr=@{,@}: */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-port.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-port.h new file mode 100644 index 00000000..1b882488 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-port.h @@ -0,0 +1,313 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_PORT_H +#define JERRYSCRIPT_PORT_H + +#include "jerryscript-types.h" + +JERRY_C_API_BEGIN + +/** + * @defgroup jerry-port JerryScript Port API + * @{ + */ + +/** + * @defgroup jerry-port-process Process management API + * + * It is questionable whether a library should be able to terminate an + * application. However, as of now, we only have the concept of completion + * code around jerry_parse and jerry_run. Most of the other API functions + * have no way of signaling an error. So, we keep the termination approach + * with this port function. + * + * @{ + */ + +/** + * Error codes that can be passed by the engine when calling jerry_port_fatal + */ +typedef enum +{ + JERRY_FATAL_OUT_OF_MEMORY = 10, /**< Out of memory */ + JERRY_FATAL_REF_COUNT_LIMIT = 12, /**< Reference count limit reached */ + JERRY_FATAL_DISABLED_BYTE_CODE = 13, /**< Executed disabled instruction */ + JERRY_FATAL_UNTERMINATED_GC_LOOPS = 14, /**< Garbage collection loop limit reached */ + JERRY_FATAL_FAILED_ASSERTION = 120 /**< Assertion failed */ +} jerry_fatal_code_t; + +/** + * Signal the port that the process experienced a fatal failure from which it cannot + * recover. + * + * A libc-based port may implement this with exit() or abort(), or both. + * + * @param code: the cause of the error. + * @return This function is expected to not return. + */ +void JERRY_ATTR_NORETURN jerry_port_fatal (jerry_fatal_code_t code); + +/** + * Make the process sleep for a given time. + * + * This port function can be called by jerry-core when JERRY_DEBUGGER is enabled. + * Otherwise this function is not used. + * + * @param sleep_time: milliseconds to sleep. + */ +void jerry_port_sleep (uint32_t sleep_time); + +/** + * jerry-port-process @} + */ + +/** + * @defgroup jerry-port-context External Context API + * @{ + */ + +/** + * Allocate a new context for the engine. + * + * This port function is called by jerry_init when JERRY_EXTERNAL_CONTEXT is enabled. Otherwise this function is not + * used. + * + * The engine will pass the size required for the context structure. An implementation must make sure to + * allocate at least this amount. + * + * Excess allocated space will be used as the engine heap when JerryScript is configured to use it's internal allocator, + * this can be used to control the internal heap size. + * + * NOTE: The allocated memory must be pointer-aligned, otherwise the behavior is undefined. + * + * @param context_size: the size of the internal context structure + * + * @return total size of the allocated buffer + */ +size_t jerry_port_context_alloc (size_t context_size); + +/** + * Get the currently active context of the engine. + * + * This port function is called by jerry-core when JERRY_EXTERNAL_CONTEXT is enabled. + * Otherwise this function is not used. + * + * @return the pointer to the currently used engine context. + */ +struct jerry_context_t *jerry_port_context_get (void); + +/** + * Free the currently used context. + * + * This port function is called by jerry_cleanup when JERRY_EXTERNAL_CONTEXT is enabled. + * Otherwise this function is not used. + */ +void jerry_port_context_free (void); + +/** + * jerry-port-context @} + */ + +/** + * @defgroup jerry-port-io I/O API + * @{ + */ + +/** + * Display or log a debug/error message. + * + * The message is passed as a zero-terminated string. Messages may be logged in parts, which + * will result in multiple calls to this functions. The implementation should consider + * this before appending or prepending strings to the argument. + * + * This function is called with messages coming from the jerry engine as + * the result of some abnormal operation or describing its internal operations + * (e.g., data structure dumps or tracing info). + * + * The implementation can decide whether error and debug messages are logged to + * the console, or saved to a database or to a file. + */ +void jerry_port_log (const char *message_p); + +/** + * Print a single character to standard output. + * + * This port function is never called from jerry-core directly, it is only used by jerry-ext components to print + * information. + * + * @param byte: the byte to print. + */ +void jerry_port_print_byte (jerry_char_t byte); + +/** + * Print a buffer to standard output + * + * This port function is never called from jerry-core directly, it is only used by jerry-ext components to print + * information. + * + * @param buffer_p: input buffer + * @param buffer_size: data size + */ +void jerry_port_print_buffer (const jerry_char_t *buffer_p, jerry_size_t buffer_size); + +/** + * Read a line from standard input. + * + * The implementation should allocate storage necessary for the string. The result string should include the ending line + * terminator character(s) and should be zero terminated. + * + * An implementation may return NULL to signal that the end of input is reached, or an error occured. + * + * When a non-NULL value is returned, the caller will pass the returned value to `jerry_port_line_free` when the line is + * no longer needed. This can be used to finalize dynamically allocated buffers if necessary. + * + * This port function is never called from jerry-core directly, it is only used by some jerry-ext components that + * require user input. + * + * @param out_size_p: size of the input string in bytes, excluding terminating zero byte + * + * @return pointer to the buffer storing the string, + * or NULL if end of input + */ +jerry_char_t *jerry_port_line_read (jerry_size_t *out_size_p); + +/** + * Free a line buffer allocated by jerry_port_line_read + * + * @param buffer_p: buffer returned by jerry_port_line_read + */ +void jerry_port_line_free (jerry_char_t *buffer_p); + +/** + * jerry-port-io @} + */ + +/** + * @defgroup jerry-port-fd Filesystem API + * @{ + */ + +/** + * Canonicalize a file path. + * + * If possible, the implementation should resolve symbolic links and other directory references found in the input path, + * and create a fully canonicalized file path as the result. + * + * The function may return with NULL in case an error is encountered, in which case the calling operation will not + * proceed. + * + * The implementation should allocate storage for the result path as necessary. Non-NULL return values will be passed + * to `jerry_port_path_free` when the result is no longer needed by the caller, which can be used to finalize + * dynamically allocated buffers. + * + * NOTE: The implementation must not return directly with the input, as the input buffer is released after the call. + * + * @param path_p: zero-terminated string containing the input path + * @param path_size: size of the input path string in bytes, excluding terminating zero + * + * @return buffer with the normalized path if the operation is successful, + * NULL otherwise + */ +jerry_char_t *jerry_port_path_normalize (const jerry_char_t *path_p, jerry_size_t path_size); + +/** + * Free a path buffer returned by jerry_port_path_normalize. + * + * @param path_p: the path buffer to free + */ +void jerry_port_path_free (jerry_char_t *path_p); + +/** + * Get the offset of the basename component in the input path. + * + * The implementation should return the offset of the first character after the last path separator found in the path. + * This is used by the caller to split the path into a directory name and a file name. + * + * @param path_p: input zero-terminated path string + * + * @return offset of the basename component in the input path + */ +jerry_size_t jerry_port_path_base (const jerry_char_t *path_p); + +/** + * Open a source file and read the content into a buffer. + * + * When the source file is no longer needed by the caller, the returned pointer will be passed to + * `jerry_port_source_free`, which can be used to finalize the buffer. + * + * @param file_name_p: Path that points to the source file in the filesystem. + * @param out_size_p: The opened file's size in bytes. + * + * @return pointer to the buffer which contains the content of the file. + */ +jerry_char_t *jerry_port_source_read (const char *file_name_p, jerry_size_t *out_size_p); + +/** + * Free a source file buffer. + * + * @param buffer_p: buffer returned by jerry_port_source_read + */ +void jerry_port_source_free (jerry_char_t *buffer_p); + +/** + * jerry-port-fs @} + */ + +/** + * @defgroup jerry-port-date Date API + * @{ + */ + +/** + * Get local time zone adjustment in milliseconds for the given input time. + * + * The argument is a time value representing milliseconds since unix epoch. + * + * Ideally, this function should satisfy the stipulations applied to LocalTZA + * in section 21.4.1.7 of the ECMAScript version 12.0, as if called with isUTC true. + * + * This port function can be called by jerry-core when JERRY_BUILTIN_DATE is enabled. + * Otherwise this function is not used. + * + * @param unix_ms: time value in milliseconds since unix epoch + * + * @return local time offset in milliseconds applied to UTC for the given time value + */ +int32_t jerry_port_local_tza (double unix_ms); + +/** + * Get the current system time in UTC. + * + * This port function is called by jerry-core when JERRY_BUILTIN_DATE is enabled. + * It can also be used in the implementing application to initialize the random number generator. + * + * @return milliseconds since Unix epoch + */ +double jerry_port_current_time (void); + +/** + * jerry-port-date @} + */ + +/** + * jerry-port @} + */ + +JERRY_C_API_END + +#endif /* !JERRYSCRIPT_PORT_H */ + +/* vim: set fdm=marker fmr=@{,@}: */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-types.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-types.h new file mode 100644 index 00000000..4f0b98f0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-types.h @@ -0,0 +1,865 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_TYPES_H +#define JERRYSCRIPT_TYPES_H + +#include +#include +#include + +#include "jerryscript-compiler.h" + +JERRY_C_API_BEGIN + +/** + * @defgroup jerry-api-types JerryScript public API types + * @{ + */ + +/** + * JerryScript init flags. + */ +typedef enum +{ + JERRY_INIT_EMPTY = (0u), /**< empty flag set */ + JERRY_INIT_SHOW_OPCODES = (1u << 0), /**< dump byte-code to log after parse */ + JERRY_INIT_SHOW_REGEXP_OPCODES = (1u << 1), /**< dump regexp byte-code to log after compilation */ + JERRY_INIT_MEM_STATS = (1u << 2), /**< dump memory statistics */ +} jerry_init_flag_t; + +/** + * Jerry log levels. The levels are in severity order + * where the most serious levels come first. + */ +typedef enum +{ + JERRY_LOG_LEVEL_ERROR = 0u, /**< the engine will terminate after the message is printed */ + JERRY_LOG_LEVEL_WARNING = 1u, /**< a request is aborted, but the engine continues its operation */ + JERRY_LOG_LEVEL_DEBUG = 2u, /**< debug messages from the engine, low volume */ + JERRY_LOG_LEVEL_TRACE = 3u /**< detailed info about engine internals, potentially high volume */ +} jerry_log_level_t; + +/** + * JerryScript API Error object types. + */ +typedef enum +{ + JERRY_ERROR_NONE = 0, /**< No Error */ + + JERRY_ERROR_COMMON, /**< Error */ + JERRY_ERROR_EVAL, /**< EvalError */ + JERRY_ERROR_RANGE, /**< RangeError */ + JERRY_ERROR_REFERENCE, /**< ReferenceError */ + JERRY_ERROR_SYNTAX, /**< SyntaxError */ + JERRY_ERROR_TYPE, /**< TypeError */ + JERRY_ERROR_URI, /**< URIError */ + JERRY_ERROR_AGGREGATE /**< AggregateError */ +} jerry_error_t; + +/** + * JerryScript feature types. + */ +typedef enum +{ + JERRY_FEATURE_CPOINTER_32_BIT, /**< 32 bit compressed pointers */ + JERRY_FEATURE_ERROR_MESSAGES, /**< error messages */ + JERRY_FEATURE_JS_PARSER, /**< js-parser */ + JERRY_FEATURE_HEAP_STATS, /**< memory statistics */ + JERRY_FEATURE_PARSER_DUMP, /**< parser byte-code dumps */ + JERRY_FEATURE_REGEXP_DUMP, /**< regexp byte-code dumps */ + JERRY_FEATURE_SNAPSHOT_SAVE, /**< saving snapshot files */ + JERRY_FEATURE_SNAPSHOT_EXEC, /**< executing snapshot files */ + JERRY_FEATURE_DEBUGGER, /**< debugging */ + JERRY_FEATURE_VM_EXEC_STOP, /**< stopping ECMAScript execution */ + JERRY_FEATURE_VM_THROW, /**< capturing ECMAScript throws */ + JERRY_FEATURE_JSON, /**< JSON support */ + JERRY_FEATURE_PROMISE, /**< promise support */ + JERRY_FEATURE_TYPEDARRAY, /**< Typedarray support */ + JERRY_FEATURE_DATE, /**< Date support */ + JERRY_FEATURE_REGEXP, /**< Regexp support */ + JERRY_FEATURE_LINE_INFO, /**< line info available */ + JERRY_FEATURE_LOGGING, /**< logging */ + JERRY_FEATURE_SYMBOL, /**< symbol support */ + JERRY_FEATURE_DATAVIEW, /**< DataView support */ + JERRY_FEATURE_PROXY, /**< Proxy support */ + JERRY_FEATURE_MAP, /**< Map support */ + JERRY_FEATURE_SET, /**< Set support */ + JERRY_FEATURE_WEAKMAP, /**< WeakMap support */ + JERRY_FEATURE_WEAKSET, /**< WeakSet support */ + JERRY_FEATURE_BIGINT, /**< BigInt support */ + JERRY_FEATURE_REALM, /**< realm support */ + JERRY_FEATURE_GLOBAL_THIS, /**< GlobalThisValue support */ + JERRY_FEATURE_PROMISE_CALLBACK, /**< Promise callback support */ + JERRY_FEATURE_MODULE, /**< Module support */ + JERRY_FEATURE_WEAKREF, /**< WeakRef support */ + JERRY_FEATURE_FUNCTION_TO_STRING, /**< function toString support */ + JERRY_FEATURE__COUNT /**< number of features. NOTE: must be at the end of the list */ +} jerry_feature_t; + +/** + * GC operational modes. + */ +typedef enum +{ + JERRY_GC_PRESSURE_LOW, /**< free unused objects, but keep memory + * allocated for performance improvements + * such as property hash tables for large objects */ + JERRY_GC_PRESSURE_HIGH /**< free as much memory as possible */ +} jerry_gc_mode_t; + +/** + * Jerry regexp flags. + */ +typedef enum +{ + JERRY_REGEXP_FLAG_GLOBAL = (1u << 1), /**< Globally scan string */ + JERRY_REGEXP_FLAG_IGNORE_CASE = (1u << 2), /**< Ignore case */ + JERRY_REGEXP_FLAG_MULTILINE = (1u << 3), /**< Multiline string scan */ + JERRY_REGEXP_FLAG_STICKY = (1u << 4), /**< ECMAScript v11, 21.2.5.14 */ + JERRY_REGEXP_FLAG_UNICODE = (1u << 5), /**< ECMAScript v11, 21.2.5.17 */ + JERRY_REGEXP_FLAG_DOTALL = (1u << 6) /**< ECMAScript v11, 21.2.5.3 */ +} jerry_regexp_flags_t; + +/** + * Character type of JerryScript. + */ +typedef uint8_t jerry_char_t; + +/** + * Size type of JerryScript. + */ +typedef uint32_t jerry_size_t; + +/** + * Length type of JerryScript. + */ +typedef uint32_t jerry_length_t; + +/** + * Description of a JerryScript value. + */ +typedef uint32_t jerry_value_t; + +/** + * Option bits for jerry_parse_options_t. + */ +typedef enum +{ + JERRY_PARSE_NO_OPTS = 0, /**< no options passed */ + JERRY_PARSE_STRICT_MODE = (1 << 0), /**< enable strict mode */ + JERRY_PARSE_MODULE = (1 << 1), /**< parse source as an ECMAScript module */ + JERRY_PARSE_HAS_ARGUMENT_LIST = (1 << 2), /**< argument_list field is valid, + * this also means that function parsing will be done */ + JERRY_PARSE_HAS_SOURCE_NAME = (1 << 3), /**< source_name field is valid */ + JERRY_PARSE_HAS_START = (1 << 4), /**< start_line and start_column fields are valid */ + JERRY_PARSE_HAS_USER_VALUE = (1 << 5), /**< user_value field is valid */ +} jerry_parse_option_enable_feature_t; + +/** + * Various configuration options for parsing functions such as jerry_parse or jerry_parse_function. + */ +typedef struct +{ + uint32_t options; /**< combination of jerry_parse_option_enable_feature_t values */ + jerry_value_t argument_list; /**< function argument list if JERRY_PARSE_HAS_ARGUMENT_LIST is set in options + * Note: must be string value */ + jerry_value_t source_name; /**< source name string (usually a file name) + * if JERRY_PARSE_HAS_SOURCE_NAME is set in options + * Note: must be string value */ + uint32_t start_line; /**< start line of the source code if JERRY_PARSE_HAS_START is set in options */ + uint32_t start_column; /**< start column of the source code if JERRY_PARSE_HAS_START is set in options */ + jerry_value_t user_value; /**< user value assigned to all functions created by this script including eval + * calls executed by the script if JERRY_PARSE_HAS_USER_VALUE is set in options */ +} jerry_parse_options_t; + +/** + * Description of ECMA property descriptor. + */ +typedef enum +{ + JERRY_PROP_NO_OPTS = (0), /**< empty property descriptor */ + JERRY_PROP_IS_CONFIGURABLE = (1 << 0), /**< [[Configurable]] */ + JERRY_PROP_IS_ENUMERABLE = (1 << 1), /**< [[Enumerable]] */ + JERRY_PROP_IS_WRITABLE = (1 << 2), /**< [[Writable]] */ + + JERRY_PROP_IS_CONFIGURABLE_DEFINED = (1 << 3), /**< is [[Configurable]] defined? */ + JERRY_PROP_IS_ENUMERABLE_DEFINED = (1 << 4), /**< is [[Enumerable]] defined? */ + JERRY_PROP_IS_WRITABLE_DEFINED = (1 << 5), /**< is [[Writable]] defined? */ + + JERRY_PROP_IS_VALUE_DEFINED = (1 << 6), /**< is [[Value]] defined? */ + JERRY_PROP_IS_GET_DEFINED = (1 << 7), /**< is [[Get]] defined? */ + JERRY_PROP_IS_SET_DEFINED = (1 << 8), /**< is [[Set]] defined? */ + + JERRY_PROP_SHOULD_THROW = (1 << 9), /**< should throw on error, instead of returning with false */ +} jerry_property_descriptor_flags_t; + +/** + * Description of ECMA property descriptor. + */ +typedef struct +{ + uint16_t flags; /**< any combination of jerry_property_descriptor_flags_t bits */ + jerry_value_t value; /**< [[Value]] */ + jerry_value_t getter; /**< [[Get]] */ + jerry_value_t setter; /**< [[Set]] */ +} jerry_property_descriptor_t; + +/** + * JerryScript object property filter options. + */ +typedef enum +{ + JERRY_PROPERTY_FILTER_ALL = 0, /**< List all property keys independently + * from key type or property value attributes + * (equivalent to Reflect.ownKeys call) */ + JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN = (1 << 0), /**< Include keys from the objects's + * prototype chain as well */ + JERRY_PROPERTY_FILTER_EXCLUDE_NON_CONFIGURABLE = (1 << 1), /**< Exclude property key if + * the property is non-configurable */ + JERRY_PROPERTY_FILTER_EXCLUDE_NON_ENUMERABLE = (1 << 2), /**< Exclude property key if + * the property is non-enumerable */ + JERRY_PROPERTY_FILTER_EXCLUDE_NON_WRITABLE = (1 << 3), /**< Exclude property key if + * the property is non-writable */ + JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS = (1 << 4), /**< Exclude property key if it is a string */ + JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS = (1 << 5), /**< Exclude property key if it is a symbol */ + JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES = (1 << 6), /**< Exclude property key if it is an integer index */ + JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER = (1 << 7), /**< By default integer index property keys are + * converted to string. Enabling this flags keeps + * integer index property keys as numbers. */ +} jerry_property_filter_t; + +/** + * String encoding. + */ +typedef enum +{ + JERRY_ENCODING_CESU8, /**< cesu-8 encoding */ + JERRY_ENCODING_UTF8, /**< utf-8 encoding */ +} jerry_encoding_t; + +/** + * Description of JerryScript heap memory stats. + * It is for memory profiling. + */ +typedef struct +{ + size_t version; /**< the version of the stats struct */ + size_t size; /**< heap total size */ + size_t allocated_bytes; /**< currently allocated bytes */ + size_t peak_allocated_bytes; /**< peak allocated bytes */ + size_t reserved[4]; /**< padding for future extensions */ +} jerry_heap_stats_t; + +/** + * Call related information passed to jerry_external_handler_t. + */ +typedef struct jerry_call_info_t +{ + jerry_value_t function; /**< invoked function object */ + jerry_value_t this_value; /**< this value passed to the function */ + jerry_value_t new_target; /**< current new target value, undefined for non-constructor calls */ +} jerry_call_info_t; + +/** + * Type of an external function handler. + */ +typedef jerry_value_t (*jerry_external_handler_t) (const jerry_call_info_t *call_info_p, + const jerry_value_t args_p[], + const jerry_length_t args_count); + +/** + * Native free callback of generic value types. + */ +typedef void (*jerry_value_free_cb_t) (void *native_p); + +/** + * Forward definition of jerry_object_native_info_t. + */ +struct jerry_object_native_info_t; + +/** + * Native free callback of an object. + */ +typedef void (*jerry_object_native_free_cb_t) (void *native_p, struct jerry_object_native_info_t *info_p); + +/** + * Free callback for external strings. + */ +typedef void (*jerry_external_string_free_cb_t) (jerry_char_t *string_p, jerry_size_t string_size, void *user_p); + +/** + * Decorator callback for Error objects. The decorator can create + * or update any properties of the newly created Error object. + */ +typedef void (*jerry_error_object_created_cb_t) (const jerry_value_t error_object, void *user_p); + +/** + * Callback which tells whether the ECMAScript execution should be stopped. + * + * As long as the function returns with undefined the execution continues. + * When a non-undefined value is returned the execution stops and the value + * is thrown by the engine as an exception. + * + * Note: if the function returns with a non-undefined value it + * must return with the same value for future calls. + */ +typedef jerry_value_t (*jerry_halt_cb_t) (void *user_p); + +/** + * Callback function which is called when an exception is thrown in an ECMAScript code. + * The callback should not change the exception_value. The callback is not called again + * until the value is caught. + * + * Note: the engine considers exceptions thrown by external functions as never caught. + */ +typedef void (*jerry_throw_cb_t) (const jerry_value_t exception_value, void *user_p); + +/** + * Function type applied to each unit of encoding when iterating over a string. + */ +typedef void (*jerry_string_iterate_cb_t) (uint32_t value, void *user_p); + +/** + * Function type applied for each data property of an object. + */ +typedef bool (*jerry_object_property_foreach_cb_t) (const jerry_value_t property_name, + const jerry_value_t property_value, + void *user_data_p); + +/** + * Function type applied for each object in the engine. + */ +typedef bool (*jerry_foreach_live_object_cb_t) (const jerry_value_t object, void *user_data_p); + +/** + * Function type applied for each matching object in the engine. + */ +typedef bool (*jerry_foreach_live_object_with_info_cb_t) (const jerry_value_t object, + void *object_data_p, + void *user_data_p); + +/** + * User context item manager + */ +typedef struct +{ + /** + * Callback responsible for initializing a context item, or NULL to zero out the memory. This is called lazily, the + * first time jerry_context_data () is called with this manager. + * + * @param [in] data The buffer that JerryScript allocated for the manager. The buffer is zeroed out. The size is + * determined by the bytes_needed field. The buffer is kept alive until jerry_cleanup () is called. + */ + void (*init_cb) (void *data); + + /** + * Callback responsible for deinitializing a context item, or NULL. This is called as part of jerry_cleanup (), + * right *before* the VM has been cleaned up. This is a good place to release strong references to jerry_value_t's + * that the manager may be holding. + * Note: because the VM has not been fully cleaned up yet, jerry_object_native_info_t free_cb's can still get called + * *after* all deinit_cb's have been run. See finalize_cb for a callback that is guaranteed to run *after* all + * free_cb's have been run. + * + * @param [in] data The buffer that JerryScript allocated for the manager. + */ + void (*deinit_cb) (void *data); + + /** + * Callback responsible for finalizing a context item, or NULL. This is called as part of jerry_cleanup (), + * right *after* the VM has been cleaned up and destroyed and jerry_... APIs cannot be called any more. At this point, + * all values in the VM have been cleaned up. This is a good place to clean up native state that can only be cleaned + * up at the very end when there are no more VM values around that may need to access that state. + * + * @param [in] data The buffer that JerryScript allocated for the manager. After returning from this callback, + * the data pointer may no longer be used. + */ + void (*finalize_cb) (void *data); + + /** + * Number of bytes to allocate for this manager. This is the size of the buffer that JerryScript will allocate on + * behalf of the manager. The pointer to this buffer is passed into init_cb, deinit_cb and finalize_cb. It is also + * returned from the jerry_context_data () API. + */ + size_t bytes_needed; +} jerry_context_data_manager_t; + +/** + * Function type for allocating buffer for JerryScript context. + */ +typedef void *(*jerry_context_alloc_cb_t) (size_t size, void *cb_data_p); + +/** + * Type information of a native pointer. + */ +typedef struct jerry_object_native_info_t +{ + jerry_object_native_free_cb_t free_cb; /**< the free callback of the native pointer */ + uint16_t number_of_references; /**< the number of value references which are marked by the garbage collector */ + uint16_t offset_of_references; /**< byte offset indicating the start offset of value + * references in the user allocated buffer */ +} jerry_object_native_info_t; + +/** + * An opaque declaration of the JerryScript context structure. + */ +typedef struct jerry_context_t jerry_context_t; + +/** + * Enum that contains the supported binary operation types + */ +typedef enum +{ + JERRY_BIN_OP_EQUAL = 0u, /**< equal comparison (==) */ + JERRY_BIN_OP_STRICT_EQUAL, /**< strict equal comparison (===) */ + JERRY_BIN_OP_LESS, /**< less relation (<) */ + JERRY_BIN_OP_LESS_EQUAL, /**< less or equal relation (<=) */ + JERRY_BIN_OP_GREATER, /**< greater relation (>) */ + JERRY_BIN_OP_GREATER_EQUAL, /**< greater or equal relation (>=)*/ + JERRY_BIN_OP_INSTANCEOF, /**< instanceof operation */ + JERRY_BIN_OP_ADD, /**< addition operator (+) */ + JERRY_BIN_OP_SUB, /**< subtraction operator (-) */ + JERRY_BIN_OP_MUL, /**< multiplication operator (*) */ + JERRY_BIN_OP_DIV, /**< division operator (/) */ + JERRY_BIN_OP_REM, /**< remainder operator (%) */ +} jerry_binary_op_t; + +/** + * Backtrace related types. + */ + +/** + * List of backtrace frame types returned by jerry_frame_type. + */ +typedef enum +{ + JERRY_BACKTRACE_FRAME_JS, /**< indicates that the frame is created for a JavaScript function/method */ +} jerry_frame_type_t; + +/** + * Location info retrieved by jerry_frame_location. + */ +typedef struct +{ + jerry_value_t source_name; /**< source name */ + jerry_size_t line; /**< line index */ + jerry_size_t column; /**< column index */ +} jerry_frame_location_t; + +/* + * Internal data structure for jerry_frame_t definition. + */ +struct jerry_frame_internal_t; + +/** + * Backtrace frame data passed to the jerry_backtrace_cb_t handler. + */ +typedef struct jerry_frame_internal_t jerry_frame_t; + +/** + * Callback function which is called by jerry_backtrace for each stack frame. + */ +typedef bool (*jerry_backtrace_cb_t) (jerry_frame_t *frame_p, void *user_p); + +/** + * Detailed value type related types. + */ + +/** + * JerryScript API value type information. + */ +typedef enum +{ + JERRY_TYPE_NONE = 0u, /**< no type information */ + JERRY_TYPE_UNDEFINED, /**< undefined type */ + JERRY_TYPE_NULL, /**< null type */ + JERRY_TYPE_BOOLEAN, /**< boolean type */ + JERRY_TYPE_NUMBER, /**< number type */ + JERRY_TYPE_STRING, /**< string type */ + JERRY_TYPE_OBJECT, /**< object type */ + JERRY_TYPE_FUNCTION, /**< function type */ + JERRY_TYPE_EXCEPTION, /**< exception/abort type */ + JERRY_TYPE_SYMBOL, /**< symbol type */ + JERRY_TYPE_BIGINT, /**< bigint type */ +} jerry_type_t; + +/** + * JerryScript object type information. + */ +typedef enum +{ + JERRY_OBJECT_TYPE_NONE = 0u, /**< Non object type */ + JERRY_OBJECT_TYPE_GENERIC, /**< Generic JavaScript object without any internal property */ + JERRY_OBJECT_TYPE_MODULE_NAMESPACE, /**< Namespace object */ + JERRY_OBJECT_TYPE_ARRAY, /**< Array object */ + JERRY_OBJECT_TYPE_PROXY, /**< Proxy object */ + JERRY_OBJECT_TYPE_SCRIPT, /**< Script object (see jerry_parse) */ + JERRY_OBJECT_TYPE_MODULE, /**< Module object (see jerry_parse) */ + JERRY_OBJECT_TYPE_PROMISE, /**< Promise object */ + JERRY_OBJECT_TYPE_DATAVIEW, /**< Dataview object */ + JERRY_OBJECT_TYPE_FUNCTION, /**< Function object (see jerry_function_type) */ + JERRY_OBJECT_TYPE_TYPEDARRAY, /**< %TypedArray% object (see jerry_typedarray_type) */ + JERRY_OBJECT_TYPE_ITERATOR, /**< Iterator object (see jerry_iterator_type) */ + JERRY_OBJECT_TYPE_CONTAINER, /**< Container object (see jerry_container_get_type) */ + JERRY_OBJECT_TYPE_ERROR, /**< Error object */ + JERRY_OBJECT_TYPE_ARRAYBUFFER, /**< Array buffer object */ + JERRY_OBJECT_TYPE_SHARED_ARRAY_BUFFER, /**< Shared Array Buffer object */ + + JERRY_OBJECT_TYPE_ARGUMENTS, /**< Arguments object */ + JERRY_OBJECT_TYPE_BOOLEAN, /**< Boolean object */ + JERRY_OBJECT_TYPE_DATE, /**< Date object */ + JERRY_OBJECT_TYPE_NUMBER, /**< Number object */ + JERRY_OBJECT_TYPE_REGEXP, /**< RegExp object */ + JERRY_OBJECT_TYPE_STRING, /**< String object */ + JERRY_OBJECT_TYPE_SYMBOL, /**< Symbol object */ + JERRY_OBJECT_TYPE_GENERATOR, /**< Generator object */ + JERRY_OBJECT_TYPE_BIGINT, /**< BigInt object */ + JERRY_OBJECT_TYPE_WEAKREF, /**< WeakRef object */ +} jerry_object_type_t; + +/** + * JerryScript function object type information. + */ +typedef enum +{ + JERRY_FUNCTION_TYPE_NONE = 0u, /**< Non function type */ + JERRY_FUNCTION_TYPE_GENERIC, /**< Generic JavaScript function */ + JERRY_FUNCTION_TYPE_ACCESSOR, /**< Accessor function */ + JERRY_FUNCTION_TYPE_BOUND, /**< Bound function */ + JERRY_FUNCTION_TYPE_ARROW, /**< Arrow function */ + JERRY_FUNCTION_TYPE_GENERATOR, /**< Generator function */ +} jerry_function_type_t; + +/** + * JerryScript iterator object type information. + */ +typedef enum +{ + JERRY_ITERATOR_TYPE_NONE = 0u, /**< Non iterator type */ + JERRY_ITERATOR_TYPE_ARRAY, /**< Array iterator */ + JERRY_ITERATOR_TYPE_STRING, /**< String iterator */ + JERRY_ITERATOR_TYPE_MAP, /**< Map iterator */ + JERRY_ITERATOR_TYPE_SET, /**< Set iterator */ +} jerry_iterator_type_t; + +/** + * Module related types. + */ + +/** + * An enum representing the current status of a module + */ +typedef enum +{ + JERRY_MODULE_STATE_INVALID = 0, /**< return value for jerry_module_state when its argument is not a module */ + JERRY_MODULE_STATE_UNLINKED = 1, /**< module is currently unlinked */ + JERRY_MODULE_STATE_LINKING = 2, /**< module is currently being linked */ + JERRY_MODULE_STATE_LINKED = 3, /**< module has been linked (its dependencies has been resolved) */ + JERRY_MODULE_STATE_EVALUATING = 4, /**< module is currently being evaluated */ + JERRY_MODULE_STATE_EVALUATED = 5, /**< module has been evaluated (its source code has been executed) */ + JERRY_MODULE_STATE_ERROR = 6, /**< an error has been encountered before the evaluated state is reached */ +} jerry_module_state_t; + +/** + * Callback which is called by jerry_module_link to get the referenced module. + */ +typedef jerry_value_t (*jerry_module_resolve_cb_t) (const jerry_value_t specifier, + const jerry_value_t referrer, + void *user_p); + +/** + * Callback which is called when an import is resolved dynamically to get the referenced module. + */ +typedef jerry_value_t (*jerry_module_import_cb_t) (const jerry_value_t specifier, + const jerry_value_t user_value, + void *user_p); + +/** + * Callback which is called after the module enters into linked, evaluated or error state. + */ +typedef void (*jerry_module_state_changed_cb_t) (jerry_module_state_t new_state, + const jerry_value_t module, + const jerry_value_t value, + void *user_p); + +/** + * Callback which is called when an import.meta expression of a module is evaluated the first time. + */ +typedef void (*jerry_module_import_meta_cb_t) (const jerry_value_t module, + const jerry_value_t meta_object, + void *user_p); + +/** + * Callback which is called by jerry_module_evaluate to evaluate the native module. + */ +typedef jerry_value_t (*jerry_native_module_evaluate_cb_t) (const jerry_value_t native_module); + +/** + * Proxy related types. + */ + +/** + * JerryScript special Proxy object options. + */ +typedef enum +{ + JERRY_PROXY_SKIP_RESULT_VALIDATION = (1u << 0), /**< skip result validation for [[GetPrototypeOf]], + * [[SetPrototypeOf]], [[IsExtensible]], + * [[PreventExtensions]], [[GetOwnProperty]], + * [[DefineOwnProperty]], [[HasProperty]], [[Get]], + * [[Set]], [[Delete]] and [[OwnPropertyKeys]] */ +} jerry_proxy_custom_behavior_t; + +/** + * Promise related types. + */ + +/** + * Enum values representing various Promise states. + */ +typedef enum +{ + JERRY_PROMISE_STATE_NONE = 0u, /**< Invalid/Unknown state (possibly called on a non-promise object). */ + JERRY_PROMISE_STATE_PENDING, /**< Promise is in "Pending" state. */ + JERRY_PROMISE_STATE_FULFILLED, /**< Promise is in "Fulfilled" state. */ + JERRY_PROMISE_STATE_REJECTED, /**< Promise is in "Rejected" state. */ +} jerry_promise_state_t; + +/** + * Event types for jerry_promise_event_cb_t callback function. + * The description of the 'object' and 'value' arguments are provided for each type. + */ +typedef enum +{ + JERRY_PROMISE_EVENT_CREATE = 0u, /**< a new Promise object is created + * object: the new Promise object + * value: parent Promise for `then` chains, undefined otherwise */ + JERRY_PROMISE_EVENT_RESOLVE, /**< called when a Promise is about to be resolved + * object: the Promise object + * value: value for resolving */ + JERRY_PROMISE_EVENT_REJECT, /**< called when a Promise is about to be rejected + * object: the Promise object + * value: value for rejecting */ + JERRY_PROMISE_EVENT_RESOLVE_FULFILLED, /**< called when a resolve is called on a fulfilled Promise + * object: the Promise object + * value: value for resolving */ + JERRY_PROMISE_EVENT_REJECT_FULFILLED, /**< called when a reject is called on a fulfilled Promise + * object: the Promise object + * value: value for rejecting */ + JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER, /**< called when a Promise is rejected without a handler + * object: the Promise object + * value: value for rejecting */ + JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED, /**< called when a catch handler is added to a rejected + * Promise which did not have a catch handler before + * object: the Promise object + * value: undefined */ + JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB, /**< called before executing a Promise reaction job + * object: the Promise object + * value: undefined */ + JERRY_PROMISE_EVENT_AFTER_REACTION_JOB, /**< called after a Promise reaction job is completed + * object: the Promise object + * value: undefined */ + JERRY_PROMISE_EVENT_ASYNC_AWAIT, /**< called when an async function awaits the result of a Promise object + * object: internal object representing the execution status + * value: the Promise object */ + JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE, /**< called when an async function is continued with resolve + * object: internal object representing the execution status + * value: value for resolving */ + JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT, /**< called when an async function is continued with reject + * object: internal object representing the execution status + * value: value for rejecting */ + JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE, /**< called when an async function resolve is completed + * object: internal object representing the execution status + * value: value for resolving */ + JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT, /**< called when an async function reject is completed + * object: internal object representing the execution status + * value: value for rejecting */ +} jerry_promise_event_type_t; + +/** + * Filter types for jerry_promise_on_event callback function. + * The callback is only called for those events which are enabled by the filters. + */ +typedef enum +{ + JERRY_PROMISE_EVENT_FILTER_DISABLE = 0, /**< disable reporting of all events */ + JERRY_PROMISE_EVENT_FILTER_CREATE = (1 << 0), /**< enables the following event: + * JERRY_PROMISE_EVENT_CREATE */ + JERRY_PROMISE_EVENT_FILTER_RESOLVE = (1 << 1), /**< enables the following event: + * JERRY_PROMISE_EVENT_RESOLVE */ + JERRY_PROMISE_EVENT_FILTER_REJECT = (1 << 2), /**< enables the following event: + * JERRY_PROMISE_EVENT_REJECT */ + JERRY_PROMISE_EVENT_FILTER_ERROR = (1 << 3), /**< enables the following events: + * JERRY_PROMISE_EVENT_RESOLVE_FULFILLED + * JERRY_PROMISE_EVENT_REJECT_FULFILLED + * JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER + * JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED */ + JERRY_PROMISE_EVENT_FILTER_REACTION_JOB = (1 << 4), /**< enables the following events: + * JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB + * JERRY_PROMISE_EVENT_AFTER_REACTION_JOB */ + JERRY_PROMISE_EVENT_FILTER_ASYNC_MAIN = (1 << 5), /**< enables the following event: + * JERRY_PROMISE_EVENT_ASYNC_AWAIT */ + JERRY_PROMISE_EVENT_FILTER_ASYNC_REACTION_JOB = (1 << 6), /**< enables the following events: + * JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE + * JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT + * JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE + * JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT */ +} jerry_promise_event_filter_t; + +/** + * Notification callback for tracking Promise and async function operations. + */ +typedef void (*jerry_promise_event_cb_t) (jerry_promise_event_type_t event_type, + const jerry_value_t object, + const jerry_value_t value, + void *user_p); + +/** + * Symbol related types. + */ + +/** + * List of well-known symbols. + */ +typedef enum +{ + JERRY_SYMBOL_ASYNC_ITERATOR, /**< @@asyncIterator well-known symbol */ + JERRY_SYMBOL_HAS_INSTANCE, /**< @@hasInstance well-known symbol */ + JERRY_SYMBOL_IS_CONCAT_SPREADABLE, /**< @@isConcatSpreadable well-known symbol */ + JERRY_SYMBOL_ITERATOR, /**< @@iterator well-known symbol */ + JERRY_SYMBOL_MATCH, /**< @@match well-known symbol */ + JERRY_SYMBOL_REPLACE, /**< @@replace well-known symbol */ + JERRY_SYMBOL_SEARCH, /**< @@search well-known symbol */ + JERRY_SYMBOL_SPECIES, /**< @@species well-known symbol */ + JERRY_SYMBOL_SPLIT, /**< @@split well-known symbol */ + JERRY_SYMBOL_TO_PRIMITIVE, /**< @@toPrimitive well-known symbol */ + JERRY_SYMBOL_TO_STRING_TAG, /**< @@toStringTag well-known symbol */ + JERRY_SYMBOL_UNSCOPABLES, /**< @@unscopables well-known symbol */ + JERRY_SYMBOL_MATCH_ALL, /**< @@matchAll well-known symbol */ +} jerry_well_known_symbol_t; + +/** + * TypedArray related types. + */ + +/** + * TypedArray types. + */ +typedef enum +{ + JERRY_TYPEDARRAY_INVALID = 0, + JERRY_TYPEDARRAY_UINT8, + JERRY_TYPEDARRAY_UINT8CLAMPED, + JERRY_TYPEDARRAY_INT8, + JERRY_TYPEDARRAY_UINT16, + JERRY_TYPEDARRAY_INT16, + JERRY_TYPEDARRAY_UINT32, + JERRY_TYPEDARRAY_INT32, + JERRY_TYPEDARRAY_FLOAT32, + JERRY_TYPEDARRAY_FLOAT64, + JERRY_TYPEDARRAY_BIGINT64, + JERRY_TYPEDARRAY_BIGUINT64, +} jerry_typedarray_type_t; + +/** + * Container types. + */ +typedef enum +{ + JERRY_CONTAINER_TYPE_INVALID = 0, /**< Invalid container */ + JERRY_CONTAINER_TYPE_MAP, /**< Map type */ + JERRY_CONTAINER_TYPE_SET, /**< Set type */ + JERRY_CONTAINER_TYPE_WEAKMAP, /**< WeakMap type */ + JERRY_CONTAINER_TYPE_WEAKSET, /**< WeakSet type */ +} jerry_container_type_t; + +/** + * Container operations + */ +typedef enum +{ + JERRY_CONTAINER_OP_ADD, /**< Set/WeakSet add operation */ + JERRY_CONTAINER_OP_GET, /**< Map/WeakMap get operation */ + JERRY_CONTAINER_OP_SET, /**< Map/WeakMap set operation */ + JERRY_CONTAINER_OP_HAS, /**< Set/WeakSet/Map/WeakMap has operation */ + JERRY_CONTAINER_OP_DELETE, /**< Set/WeakSet/Map/WeakMap delete operation */ + JERRY_CONTAINER_OP_SIZE, /**< Set/WeakSet/Map/WeakMap size operation */ + JERRY_CONTAINER_OP_CLEAR, /**< Set/Map clear operation */ +} jerry_container_op_t; + +/** + * Miscellaneous types. + */ + +/** + * Enabled fields of jerry_source_info_t. + */ +typedef enum +{ + JERRY_SOURCE_INFO_HAS_SOURCE_CODE = (1 << 0), /**< source_code field is valid */ + JERRY_SOURCE_INFO_HAS_FUNCTION_ARGUMENTS = (1 << 1), /**< function_arguments field is valid */ + JERRY_SOURCE_INFO_HAS_SOURCE_RANGE = (1 << 2), /**< both source_range_start and source_range_length + * fields are valid */ +} jerry_source_info_enabled_fields_t; + +/** + * Source related information of a script/module/function. + */ +typedef struct +{ + uint32_t enabled_fields; /**< combination of jerry_source_info_enabled_fields_t values */ + jerry_value_t source_code; /**< script source code or function body */ + jerry_value_t function_arguments; /**< function arguments */ + uint32_t source_range_start; /**< start position of the function in the source code */ + uint32_t source_range_length; /**< source length of the function in the source code */ +} jerry_source_info_t; + +/** + * Array buffer types. + */ + +/** + * Type of an array buffer. + */ +typedef enum +{ + JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER, /**< the object is an array buffer object */ + JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER, /**< the object is a shared array buffer object */ +} jerry_arraybuffer_type_t; + +/** + * Callback for allocating the backing store of array buffer or shared array buffer objects. + */ +typedef uint8_t *(*jerry_arraybuffer_allocate_cb_t) (jerry_arraybuffer_type_t buffer_type, + uint32_t buffer_size, + void **arraybuffer_user_p, + void *user_p); + +/** + * Callback for freeing the backing store of array buffer or shared array buffer objects. + */ +typedef void (*jerry_arraybuffer_free_cb_t) (jerry_arraybuffer_type_t buffer_type, + uint8_t *buffer_p, + uint32_t buffer_size, + void *arraybuffer_user_p, + void *user_p); + +/** + * @} + */ + +JERRY_C_API_END + +#endif /* !JERRYSCRIPT_TYPES_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript.h new file mode 100644 index 00000000..5a38ad0b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript.h @@ -0,0 +1,36 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_H +#define JERRYSCRIPT_H + +/** + * Major version of JerryScript API. + */ +#define JERRY_API_MAJOR_VERSION 3 + +/** + * Minor version of JerryScript API. + */ +#define JERRY_API_MINOR_VERSION 0 + +/** + * Patch version of JerryScript API. + */ +#define JERRY_API_PATCH_VERSION 0 + +#include "jerryscript-core.h" + +#endif /* !JERRYSCRIPT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/meson.build b/src/loaders/lottie/jerryscript/jerry-core/include/meson.build new file mode 100644 index 00000000..36caacaa --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/meson.build @@ -0,0 +1,13 @@ +source_file = [ + 'jerry-config.h', + 'jerryscript-compiler.h', + 'jerryscript-core.h', + 'jerryscript-port.h', + 'jerryscript-types.h', + 'jerryscript.h' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.cpp b/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.cpp new file mode 100644 index 00000000..7a7a4290 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.cpp @@ -0,0 +1,156 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jcontext.h" + +/** \addtogroup context Context + * @{ + */ + +/** + * Check the existence of the ECMA_STATUS_EXCEPTION flag. + * + * @return true - if the flag is set + * false - otherwise + */ +bool +jcontext_has_pending_exception (void) +{ + return JERRY_CONTEXT (status_flags) & ECMA_STATUS_EXCEPTION; +} /* jcontext_has_pending_exception */ + +/** + * Check the existence of the ECMA_STATUS_ABORT flag. + * + * @return true - if the flag is set + * false - otherwise + */ +bool +jcontext_has_pending_abort (void) +{ + return JERRY_CONTEXT (status_flags) & ECMA_STATUS_ABORT; +} /* jcontext_has_pending_abort */ + +/** + * Set the abort flag for the context. + * + * @return void + */ +void +jcontext_set_abort_flag (bool is_abort) /**< true - if the abort flag should be set + * false - if the abort flag should be removed */ +{ + JERRY_ASSERT (jcontext_has_pending_exception ()); + + if (is_abort) + { + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_ABORT; + } + else + { + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_ABORT; + } +} /* jcontext_set_abort_flag */ + +/** + * Set the exception flag for the context. + * + * @return void + */ +void +jcontext_set_exception_flag (bool is_exception) /**< true - if the exception flag should be set + * false - if the exception flag should be removed */ +{ + if (is_exception) + { + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_EXCEPTION; + } + else + { + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_EXCEPTION; + } +} /* jcontext_set_exception_flag */ + +/** + * Raise exception from the given error value. + * + * @return void + */ +void +jcontext_raise_exception (ecma_value_t error) /**< error to raise */ +{ + JERRY_ASSERT (!jcontext_has_pending_exception ()); + JERRY_ASSERT (!jcontext_has_pending_abort ()); + + JERRY_CONTEXT (error_value) = error; + jcontext_set_exception_flag (true); +} /* jcontext_raise_exception */ + +/** + * Release the current exception/abort of the context. + */ +void +jcontext_release_exception (void) +{ + JERRY_ASSERT (jcontext_has_pending_exception ()); + + ecma_free_value (jcontext_take_exception ()); +} /* jcontext_release_exception */ + +/** + * Take the current exception/abort of context. + * + * @return current exception as an ecma-value + */ +ecma_value_t +jcontext_take_exception (void) +{ + JERRY_ASSERT (jcontext_has_pending_exception ()); + + JERRY_CONTEXT (status_flags) &= (uint32_t) ~(ECMA_STATUS_EXCEPTION +#if JERRY_VM_THROW + | ECMA_STATUS_ERROR_THROWN +#endif /* JERRY_VM_THROW */ + | ECMA_STATUS_ABORT); + return JERRY_CONTEXT (error_value); +} /* jcontext_take_exception */ + +#if !JERRY_EXTERNAL_CONTEXT + +/** + * Global context. + */ +jerry_context_t jerry_global_context; + +#if !JERRY_SYSTEM_ALLOCATOR + +/** + * Check size of heap is corresponding to configuration + */ +JERRY_STATIC_ASSERT ((sizeof (jmem_heap_t) <= JMEM_HEAP_SIZE), + size_of_mem_heap_must_be_less_than_or_equal_to_JMEM_HEAP_SIZE); + +/** + * Global heap. + */ +jmem_heap_t jerry_global_heap JERRY_ATTR_ALIGNED (JMEM_ALIGNMENT) JERRY_ATTR_GLOBAL_HEAP; + +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +#endif /* !JERRY_EXTERNAL_CONTEXT */ + +/** + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.h b/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.h new file mode 100644 index 00000000..1bf35d56 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.h @@ -0,0 +1,322 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Engine context for JerryScript + */ +#ifndef JCONTEXT_H +#define JCONTEXT_H + +#include "ecma-builtins.h" +#include "ecma-helpers.h" +#include "ecma-jobqueue.h" + +#include "jmem.h" +#include "js-parser-internal.h" +#include "re-bytecode.h" +#include "vm-defines.h" + +/** \addtogroup context Context + * @{ + */ + +/** + * Advanced allocator configurations. + */ +/** + * Maximum global heap size in bytes + */ +#define CONFIG_MEM_HEAP_SIZE (JERRY_GLOBAL_HEAP_SIZE * 1024) + +/** + * Maximum stack usage size in bytes + */ +#define CONFIG_MEM_STACK_LIMIT (JERRY_STACK_LIMIT * 1024) + +/** + * Max heap usage limit + */ +#define CONFIG_MAX_GC_LIMIT 8192 + +/** + * Allowed heap usage limit until next garbage collection + * + * Whenever the total allocated memory size reaches the current heap limit, garbage collection will be triggered + * to try and reduce clutter from unreachable objects. If the allocated memory can't be reduced below the limit, + * then the current limit will be incremented by CONFIG_MEM_HEAP_LIMIT. + */ +#if defined(JERRY_GC_LIMIT) && (JERRY_GC_LIMIT != 0) +#define CONFIG_GC_LIMIT JERRY_GC_LIMIT +#else /* !(defined(JERRY_GC_LIMIT) && (JERRY_GC_LIMIT != 0)) */ +#define CONFIG_GC_LIMIT (JERRY_MIN (CONFIG_MEM_HEAP_SIZE / 32, CONFIG_MAX_GC_LIMIT)) +#endif /* defined(JERRY_GC_LIMIT) && (JERRY_GC_LIMIT != 0) */ + +/** + * Amount of newly allocated objects since the last GC run, represented as a fraction of all allocated objects, + * which when reached will trigger garbage collection to run with a low pressure setting. + * + * The fraction is calculated as: + * 1.0 / CONFIG_ECMA_GC_NEW_OBJECTS_FRACTION + */ +#define CONFIG_ECMA_GC_NEW_OBJECTS_FRACTION (16) + +#if !JERRY_SYSTEM_ALLOCATOR +/** + * Heap structure + * + * Memory blocks returned by the allocator must not start from the + * beginning of the heap area because offset 0 is reserved for + * JMEM_CP_NULL. This special constant is used in several places, + * e.g. it marks the end of the property chain list, so it cannot + * be eliminated from the project. Although the allocator cannot + * use the first 8 bytes of the heap, nothing prevents to use it + * for other purposes. Currently the free region start is stored + * there. + */ +typedef struct jmem_heap_t jmem_heap_t; +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +/** + * User context item + */ +typedef struct jerry_context_data_header +{ + struct jerry_context_data_header *next_p; /**< pointer to next context item */ + const jerry_context_data_manager_t *manager_p; /**< manager responsible for deleting this item */ +} jerry_context_data_header_t; + +#define JERRY_CONTEXT_DATA_HEADER_USER_DATA(item_p) ((uint8_t *) (item_p + 1)) + +/** + * JerryScript context + * + * The purpose of this header is storing + * all global variables for Jerry + */ +struct jerry_context_t +{ + /* The value of external context members must be preserved across initializations and cleanups. */ +#if JERRY_EXTERNAL_CONTEXT +#if !JERRY_SYSTEM_ALLOCATOR + jmem_heap_t *heap_p; /**< point to the heap aligned to JMEM_ALIGNMENT. */ + uint32_t heap_size; /**< size of the heap */ +#endif /* !JERRY_SYSTEM_ALLOCATOR */ +#endif /* JERRY_EXTERNAL_CONTEXT */ + + ecma_global_object_t *global_object_p; /**< current global object */ + jmem_heap_free_t *jmem_heap_list_skip_p; /**< improves deallocation performance */ + jmem_pools_chunk_t *jmem_free_8_byte_chunk_p; /**< list of free eight byte pool chunks */ +#if JERRY_BUILTIN_REGEXP + re_compiled_code_t *re_cache[RE_CACHE_SIZE]; /**< regex cache */ +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_CPOINTER_32_BIT + jmem_pools_chunk_t *jmem_free_16_byte_chunk_p; /**< list of free sixteen byte pool chunks */ +#endif /* JERRY_CPOINTER_32_BIT */ + const lit_utf8_byte_t *const *lit_magic_string_ex_array; /**< array of external magic strings */ + const lit_utf8_size_t *lit_magic_string_ex_sizes; /**< external magic string lengths */ + jmem_cpointer_t ecma_gc_objects_cp; /**< List of currently alive objects. */ + jmem_cpointer_t string_list_first_cp; /**< first item of the literal string list */ + jmem_cpointer_t symbol_list_first_cp; /**< first item of the global symbol list */ + jmem_cpointer_t number_list_first_cp; /**< first item of the literal number list */ +#if JERRY_BUILTIN_BIGINT + jmem_cpointer_t bigint_list_first_cp; /**< first item of the literal bigint list */ +#endif /* JERRY_BUILTIN_BIGINT */ + jmem_cpointer_t global_symbols_cp[ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT]; /**< global symbols */ + +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_current_p; /**< current module context */ + jerry_module_state_changed_cb_t module_state_changed_callback_p; /**< callback which is called after the + * state of a module is changed */ + void *module_state_changed_callback_user_p; /**< user pointer for module_state_changed_callback_p */ + jerry_module_import_meta_cb_t module_import_meta_callback_p; /**< callback which is called when an + * import.meta expression of a module + * is evaluated the first time */ + void *module_import_meta_callback_user_p; /**< user pointer for module_import_meta_callback_p */ + jerry_module_import_cb_t module_import_callback_p; /**< callback for dynamic module import */ + void *module_import_callback_user_p; /**< user pointer for module_import_callback_p */ +#endif /* JERRY_MODULE_SYSTEM */ + + vm_frame_ctx_t *vm_top_context_p; /**< top (current) interpreter context */ + jerry_context_data_header_t *context_data_p; /**< linked list of user-provided context-specific pointers */ + jerry_external_string_free_cb_t external_string_free_callback_p; /**< free callback for external strings */ + void *error_object_created_callback_user_p; /**< user pointer for error_object_update_callback_p */ + jerry_error_object_created_cb_t error_object_created_callback_p; /**< decorator callback for Error objects */ + size_t ecma_gc_objects_number; /**< number of currently allocated objects */ + size_t ecma_gc_new_objects; /**< number of newly allocated objects since last GC session */ + size_t jmem_heap_allocated_size; /**< size of allocated regions */ + size_t jmem_heap_limit; /**< current limit of heap usage, that is upon being reached, + * causes call of "try give memory back" callbacks */ + ecma_value_t error_value; /**< currently thrown error value */ + uint32_t lit_magic_string_ex_count; /**< external magic strings count */ + uint32_t jerry_init_flags; /**< run-time configuration flags */ + uint32_t status_flags; /**< run-time flags (the top 8 bits are used for passing class parsing options) */ + +#if (JERRY_GC_MARK_LIMIT != 0) + uint32_t ecma_gc_mark_recursion_limit; /**< GC mark recursion limit */ +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + +#if JERRY_PROPERTY_HASHMAP + uint8_t ecma_prop_hashmap_alloc_state; /**< property hashmap allocation state: 0-4, + * if !0 property hashmap allocation is disabled */ +#endif /* JERRY_PROPERTY_HASHMAP */ + +#if JERRY_BUILTIN_REGEXP + uint8_t re_cache_idx; /**< evicted item index when regex cache is full (round-robin) */ +#endif /* JERRY_BUILTIN_REGEXP */ + ecma_job_queue_item_t *job_queue_head_p; /**< points to the head item of the job queue */ + ecma_job_queue_item_t *job_queue_tail_p; /**< points to the tail item of the job queue */ +#if JERRY_PROMISE_CALLBACK + uint32_t promise_callback_filters; /**< reported event types for promise callback */ + void *promise_callback_user_p; /**< user pointer for promise callback */ + jerry_promise_event_cb_t promise_callback; /**< user function for tracking Promise object operations */ +#endif /* JERRY_PROMISE_CALLBACK */ + +#if JERRY_BUILTIN_TYPEDARRAY + uint32_t arraybuffer_compact_allocation_limit; /**< maximum size of compact allocation */ + jerry_arraybuffer_allocate_cb_t arraybuffer_allocate_callback; /**< callback for allocating + * arraybuffer memory */ + jerry_arraybuffer_free_cb_t arraybuffer_free_callback; /**< callback for freeing arraybuffer memory */ + void *arraybuffer_allocate_callback_user_p; /**< user pointer passed to arraybuffer_allocate_callback + * and arraybuffer_free_callback functions */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#if JERRY_VM_HALT + uint32_t vm_exec_stop_frequency; /**< reset value for vm_exec_stop_counter */ + uint32_t vm_exec_stop_counter; /**< down counter for reducing the calls of vm_exec_stop_cb */ + void *vm_exec_stop_user_p; /**< user pointer for vm_exec_stop_cb */ + ecma_vm_exec_stop_callback_t vm_exec_stop_cb; /**< user function which returns whether the + * ECMAScript execution should be stopped */ +#endif /* JERRY_VM_HALT */ + +#if JERRY_VM_THROW + void *vm_throw_callback_user_p; /**< user pointer for vm_throw_callback_p */ + jerry_throw_cb_t vm_throw_callback_p; /**< callback for capturing throws */ +#endif /* JERRY_VM_THROW */ + +#if (JERRY_STACK_LIMIT != 0) + uintptr_t stack_base; /**< stack base marker */ +#endif /* (JERRY_STACK_LIMIT != 0) */ + + /* This must be at the end of the context for performance reasons */ +#if JERRY_LCACHE + /** hash table for caching the last access of properties */ + ecma_lcache_hash_entry_t lcache[ECMA_LCACHE_HASH_ROWS_COUNT][ECMA_LCACHE_HASH_ROW_LENGTH]; +#endif /* JERRY_LCACHE */ + + /** + * Allowed values and it's meaning: + * * NULL (0x0): the current "new.target" is undefined, that is the execution is inside a normal method. + * * Any other valid function object pointer: the current "new.target" is valid and it is constructor call. + */ + ecma_object_t *current_new_target_p; +}; + +#if JERRY_EXTERNAL_CONTEXT + +/* + * This part is for JerryScript which uses external context. + */ + +#define JERRY_CONTEXT_STRUCT (*jerry_port_context_get ()) +#define JERRY_CONTEXT(field) (jerry_port_context_get ()->field) + +#if !JERRY_SYSTEM_ALLOCATOR + +#define JMEM_HEAP_SIZE (JERRY_CONTEXT (heap_size)) + +#define JMEM_HEAP_AREA_SIZE (JMEM_HEAP_SIZE - JMEM_ALIGNMENT) + +struct jmem_heap_t +{ + jmem_heap_free_t first; /**< first node in free region list */ + uint8_t area[]; /**< heap area */ +}; + +#define JERRY_HEAP_CONTEXT(field) (JERRY_CONTEXT (heap_p)->field) + +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +#else /* !JERRY_EXTERNAL_CONTEXT */ + +/* + * This part is for JerryScript which uses default context. + */ + +/** + * Global context. + */ +extern jerry_context_t jerry_global_context; + +/** + * Config-independent name for context. + */ +#define JERRY_CONTEXT_STRUCT (jerry_global_context) + +/** + * Provides a reference to a field in the current context. + */ +#define JERRY_CONTEXT(field) (jerry_global_context.field) + +#if !JERRY_SYSTEM_ALLOCATOR + +/** + * Size of heap + */ +#define JMEM_HEAP_SIZE ((size_t) (CONFIG_MEM_HEAP_SIZE)) + +/** + * Calculate heap area size, leaving space for a pointer to the free list + */ +#define JMEM_HEAP_AREA_SIZE (JMEM_HEAP_SIZE - JMEM_ALIGNMENT) + +struct jmem_heap_t +{ + jmem_heap_free_t first; /**< first node in free region list */ + uint8_t area[JMEM_HEAP_AREA_SIZE]; /**< heap area */ +}; + +/** + * Global heap. + */ +extern jmem_heap_t jerry_global_heap; + +/** + * Provides a reference to a field of the heap. + */ +#define JERRY_HEAP_CONTEXT(field) (jerry_global_heap.field) + +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +#endif /* JERRY_EXTERNAL_CONTEXT */ + +void jcontext_set_exception_flag (bool is_exception); + +void jcontext_set_abort_flag (bool is_abort); + +bool jcontext_has_pending_exception (void); + +bool jcontext_has_pending_abort (void); + +void jcontext_raise_exception (ecma_value_t error); + +void jcontext_release_exception (void); + +ecma_value_t jcontext_take_exception (void); + +/** + * @} + */ + +#endif /* !JCONTEXT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jcontext/meson.build b/src/loaders/lottie/jerryscript/jerry-core/jcontext/meson.build new file mode 100644 index 00000000..ca41b816 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jcontext/meson.build @@ -0,0 +1,9 @@ +source_file = [ + 'jcontext.h', + 'jcontext.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator-internal.h b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator-internal.h new file mode 100644 index 00000000..f71d9eac --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator-internal.h @@ -0,0 +1,78 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JMEM_ALLOCATOR_INTERNAL_H +#define JMEM_ALLOCATOR_INTERNAL_H + +#ifndef JMEM_ALLOCATOR_INTERNAL +#error "The header is for internal routines of memory allocator component. Please, don't use the routines directly." +#endif /* !JMEM_ALLOCATOR_INTERNAL */ + +/** \addtogroup mem Memory allocation + * @{ + */ + +/** + * @{ + * Valgrind-related options and headers + */ +#if JERRY_VALGRIND +#include "memcheck.h" + +#define JMEM_VALGRIND_NOACCESS_SPACE(p, s) VALGRIND_MAKE_MEM_NOACCESS ((p), (s)) +#define JMEM_VALGRIND_UNDEFINED_SPACE(p, s) VALGRIND_MAKE_MEM_UNDEFINED ((p), (s)) +#define JMEM_VALGRIND_DEFINED_SPACE(p, s) VALGRIND_MAKE_MEM_DEFINED ((p), (s)) +#define JMEM_VALGRIND_MALLOCLIKE_SPACE(p, s) VALGRIND_MALLOCLIKE_BLOCK ((p), (s), 0, 0) +#define JMEM_VALGRIND_RESIZE_SPACE(p, o, n) VALGRIND_RESIZEINPLACE_BLOCK ((p), (o), (n), 0) +#define JMEM_VALGRIND_FREELIKE_SPACE(p) VALGRIND_FREELIKE_BLOCK ((p), 0) +#else /* !JERRY_VALGRIND */ +#define JMEM_VALGRIND_NOACCESS_SPACE(p, s) +#define JMEM_VALGRIND_UNDEFINED_SPACE(p, s) +#define JMEM_VALGRIND_DEFINED_SPACE(p, s) +#define JMEM_VALGRIND_MALLOCLIKE_SPACE(p, s) +#define JMEM_VALGRIND_RESIZE_SPACE(p, o, n) +#define JMEM_VALGRIND_FREELIKE_SPACE(p) +#endif /* JERRY_VALGRIND */ +/** @} */ + +void jmem_heap_init (void); +void jmem_heap_finalize (void); +bool jmem_is_heap_pointer (const void *pointer); +void *jmem_heap_alloc_block_internal (const size_t size); +void jmem_heap_free_block_internal (void *ptr, const size_t size); + +/** + * \addtogroup poolman Memory pool manager + * @{ + */ + +void jmem_pools_finalize (void); + +/** + * @} + * @} + */ + +/** + * @{ + * Jerry mem-stat definitions + */ +#define JMEM_HEAP_STAT_INIT() +#define JMEM_HEAP_STAT_ALLOC(v1) JERRY_UNUSED (v1) +#define JMEM_HEAP_STAT_FREE(v1) JERRY_UNUSED (v1) + +/** @} */ + +#endif /* !JMEM_ALLOCATOR_INTERNAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator.cpp b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator.cpp new file mode 100644 index 00000000..d56f5a36 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator.cpp @@ -0,0 +1,107 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Allocator implementation + */ +#include "ecma-globals.h" + +#include "jcontext.h" +#include "jmem.h" +#include "jrt-libc-includes.h" + +#define JMEM_ALLOCATOR_INTERNAL +#include "jmem-allocator-internal.h" + +/** + * Initialize memory allocators. + */ +void +jmem_init (void) +{ + jmem_heap_init (); +} /* jmem_init */ + +/** + * Finalize memory allocators. + */ +void +jmem_finalize (void) +{ + jmem_pools_finalize (); + jmem_heap_finalize (); +} /* jmem_finalize */ + +/** + * Compress pointer + * + * @return packed pointer + */ +jmem_cpointer_t JERRY_ATTR_PURE +jmem_compress_pointer (const void *pointer_p) /**< pointer to compress */ +{ + JERRY_ASSERT (pointer_p != NULL); + JERRY_ASSERT (jmem_is_heap_pointer (pointer_p)); + + uintptr_t uint_ptr = (uintptr_t) pointer_p; + + JERRY_ASSERT (uint_ptr % JMEM_ALIGNMENT == 0); + +#if defined(ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY) && JERRY_CPOINTER_32_BIT + JERRY_ASSERT (((jmem_cpointer_t) uint_ptr) == uint_ptr); +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY || !JERRY_CPOINTER_32_BIT */ + const uintptr_t heap_start = (uintptr_t) &JERRY_HEAP_CONTEXT (first); + + uint_ptr -= heap_start; + uint_ptr >>= JMEM_ALIGNMENT_LOG; + +#if JERRY_CPOINTER_32_BIT + JERRY_ASSERT (uint_ptr <= UINT32_MAX); +#else /* !JERRY_CPOINTER_32_BIT */ + JERRY_ASSERT (uint_ptr <= UINT16_MAX); +#endif /* JERRY_CPOINTER_32_BIT */ + JERRY_ASSERT (uint_ptr != JMEM_CP_NULL); +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY && JERRY_CPOINTER_32_BIT */ + + return (jmem_cpointer_t) uint_ptr; +} /* jmem_compress_pointer */ + +/** + * Decompress pointer + * + * @return unpacked pointer + */ +void *JERRY_ATTR_PURE +jmem_decompress_pointer (uintptr_t compressed_pointer) /**< pointer to decompress */ +{ + JERRY_ASSERT (compressed_pointer != JMEM_CP_NULL); + + uintptr_t uint_ptr = compressed_pointer; + + JERRY_ASSERT (((jmem_cpointer_t) uint_ptr) == uint_ptr); + +#if defined(ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY) && JERRY_CPOINTER_32_BIT + JERRY_ASSERT (uint_ptr % JMEM_ALIGNMENT == 0); +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY || !JERRY_CPOINTER_32_BIT */ + const uintptr_t heap_start = (uintptr_t) &JERRY_HEAP_CONTEXT (first); + + uint_ptr <<= JMEM_ALIGNMENT_LOG; + uint_ptr += heap_start; + + JERRY_ASSERT (jmem_is_heap_pointer ((void *) uint_ptr)); +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY && JERRY_CPOINTER_32_BIT */ + + return (void *) uint_ptr; +} /* jmem_decompress_pointer */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-heap.cpp b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-heap.cpp new file mode 100644 index 00000000..1d3b1f4f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-heap.cpp @@ -0,0 +1,731 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Heap implementation + */ + +#include "ecma-gc.h" + +#include "jcontext.h" +#include "jmem.h" +#include "jrt-bit-fields.h" +#include "jrt-libc-includes.h" + +#define JMEM_ALLOCATOR_INTERNAL +#include "jmem-allocator-internal.h" + +/** \addtogroup mem Memory allocation + * @{ + * + * \addtogroup heap Heap + * @{ + */ + +#if !JERRY_SYSTEM_ALLOCATOR +/** + * End of list marker. + */ +#define JMEM_HEAP_END_OF_LIST ((uint32_t) 0xffffffff) + +/** + * @{ + */ +#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY +/* In this case we simply store the pointer, since it fits anyway. */ +#define JMEM_HEAP_GET_OFFSET_FROM_ADDR(p) ((uint32_t) (p)) +#define JMEM_HEAP_GET_ADDR_FROM_OFFSET(u) ((jmem_heap_free_t *) (u)) +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ +/** + * Get heap offset from address + */ +#define JMEM_HEAP_GET_OFFSET_FROM_ADDR(p) ((uint32_t) ((uint8_t *) (p) -JERRY_HEAP_CONTEXT (area))) + +/** + * Get heap address from offset + */ +#define JMEM_HEAP_GET_ADDR_FROM_OFFSET(u) ((jmem_heap_free_t *) (JERRY_HEAP_CONTEXT (area) + (u))) +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ +/** + * @} + */ + +/** + * Get end of region + * + * @return pointer to the end of the region + */ +static inline jmem_heap_free_t * JERRY_ATTR_PURE +jmem_heap_get_region_end (jmem_heap_free_t *curr_p) /**< current region */ +{ + return (jmem_heap_free_t *) ((uint8_t *) curr_p + curr_p->size); +} /* jmem_heap_get_region_end */ +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +/** + * Startup initialization of heap + */ +void +jmem_heap_init (void) +{ +#if !JERRY_SYSTEM_ALLOCATOR +#if !JERRY_CPOINTER_32_BIT + /* the maximum heap size for 16bit compressed pointers should be 512K */ + JERRY_ASSERT (((UINT16_MAX + 1) << JMEM_ALIGNMENT_LOG) >= JMEM_HEAP_SIZE); +#endif /* !JERRY_CPOINTER_32_BIT */ + JERRY_ASSERT ((uintptr_t) JERRY_HEAP_CONTEXT (area) % JMEM_ALIGNMENT == 0); + + JERRY_CONTEXT (jmem_heap_limit) = CONFIG_GC_LIMIT; + + jmem_heap_free_t *const region_p = (jmem_heap_free_t *) JERRY_HEAP_CONTEXT (area); + + region_p->size = JMEM_HEAP_AREA_SIZE; + region_p->next_offset = JMEM_HEAP_END_OF_LIST; + + JERRY_HEAP_CONTEXT (first).size = 0; + JERRY_HEAP_CONTEXT (first).next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (region_p); + + JERRY_CONTEXT (jmem_heap_list_skip_p) = &JERRY_HEAP_CONTEXT (first); + + JMEM_VALGRIND_NOACCESS_SPACE (&JERRY_HEAP_CONTEXT (first), sizeof (jmem_heap_free_t)); + JMEM_VALGRIND_NOACCESS_SPACE (JERRY_HEAP_CONTEXT (area), JMEM_HEAP_AREA_SIZE); + +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + JMEM_HEAP_STAT_INIT (); +} /* jmem_heap_init */ + +/** + * Finalize heap + */ +void +jmem_heap_finalize (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (jmem_heap_allocated_size) == 0); +#if !JERRY_SYSTEM_ALLOCATOR + JMEM_VALGRIND_NOACCESS_SPACE (&JERRY_HEAP_CONTEXT (first), JMEM_HEAP_SIZE); +#endif /* !JERRY_SYSTEM_ALLOCATOR */ +} /* jmem_heap_finalize */ + +/** + * Allocation of memory region. + * + * See also: + * jmem_heap_alloc_block + * + * @return pointer to allocated memory block - if allocation is successful, + * NULL - if there is not enough memory. + */ +static void *JERRY_ATTR_HOT +jmem_heap_alloc (const size_t size) /**< size of requested block */ +{ +#if !JERRY_SYSTEM_ALLOCATOR + /* Align size. */ + const size_t required_size = ((size + JMEM_ALIGNMENT - 1) / JMEM_ALIGNMENT) * JMEM_ALIGNMENT; + jmem_heap_free_t *data_space_p = NULL; + + JMEM_VALGRIND_DEFINED_SPACE (&JERRY_HEAP_CONTEXT (first), sizeof (jmem_heap_free_t)); + + /* Fast path for 8 byte chunks, first region is guaranteed to be sufficient. */ + if (required_size == JMEM_ALIGNMENT && JERRY_LIKELY (JERRY_HEAP_CONTEXT (first).next_offset != JMEM_HEAP_END_OF_LIST)) + { + data_space_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (JERRY_HEAP_CONTEXT (first).next_offset); + JERRY_ASSERT (jmem_is_heap_pointer (data_space_p)); + + JMEM_VALGRIND_DEFINED_SPACE (data_space_p, sizeof (jmem_heap_free_t)); + JERRY_CONTEXT (jmem_heap_allocated_size) += JMEM_ALIGNMENT; + + if (JERRY_CONTEXT (jmem_heap_allocated_size) >= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) += CONFIG_GC_LIMIT; + } + + if (data_space_p->size == JMEM_ALIGNMENT) + { + JERRY_HEAP_CONTEXT (first).next_offset = data_space_p->next_offset; + } + else + { + JERRY_ASSERT (data_space_p->size > JMEM_ALIGNMENT); + + jmem_heap_free_t *remaining_p; + remaining_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (JERRY_HEAP_CONTEXT (first).next_offset) + 1; + + JMEM_VALGRIND_DEFINED_SPACE (remaining_p, sizeof (jmem_heap_free_t)); + remaining_p->size = data_space_p->size - JMEM_ALIGNMENT; + remaining_p->next_offset = data_space_p->next_offset; + JMEM_VALGRIND_NOACCESS_SPACE (remaining_p, sizeof (jmem_heap_free_t)); + + JERRY_HEAP_CONTEXT (first).next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (remaining_p); + } + + JMEM_VALGRIND_NOACCESS_SPACE (data_space_p, sizeof (jmem_heap_free_t)); + + if (JERRY_UNLIKELY (data_space_p == JERRY_CONTEXT (jmem_heap_list_skip_p))) + { + JERRY_CONTEXT (jmem_heap_list_skip_p) = JMEM_HEAP_GET_ADDR_FROM_OFFSET (JERRY_HEAP_CONTEXT (first).next_offset); + } + } + /* Slow path for larger regions. */ + else + { + uint32_t current_offset = JERRY_HEAP_CONTEXT (first).next_offset; + jmem_heap_free_t *prev_p = &JERRY_HEAP_CONTEXT (first); + + while (JERRY_LIKELY (current_offset != JMEM_HEAP_END_OF_LIST)) + { + jmem_heap_free_t *current_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (current_offset); + JERRY_ASSERT (jmem_is_heap_pointer (current_p)); + JMEM_VALGRIND_DEFINED_SPACE (current_p, sizeof (jmem_heap_free_t)); + + const uint32_t next_offset = current_p->next_offset; + JERRY_ASSERT (next_offset == JMEM_HEAP_END_OF_LIST + || jmem_is_heap_pointer (JMEM_HEAP_GET_ADDR_FROM_OFFSET (next_offset))); + + if (current_p->size >= required_size) + { + /* Region is sufficiently big, store address. */ + data_space_p = current_p; + + /* Region was larger than necessary. */ + if (current_p->size > required_size) + { + /* Get address of remaining space. */ + jmem_heap_free_t *const remaining_p = (jmem_heap_free_t *) ((uint8_t *) current_p + required_size); + + /* Update metadata. */ + JMEM_VALGRIND_DEFINED_SPACE (remaining_p, sizeof (jmem_heap_free_t)); + remaining_p->size = current_p->size - (uint32_t) required_size; + remaining_p->next_offset = next_offset; + JMEM_VALGRIND_NOACCESS_SPACE (remaining_p, sizeof (jmem_heap_free_t)); + + /* Update list. */ + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + prev_p->next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (remaining_p); + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + } + /* Block is an exact fit. */ + else + { + /* Remove the region from the list. */ + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + prev_p->next_offset = next_offset; + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + } + + JERRY_CONTEXT (jmem_heap_list_skip_p) = prev_p; + + /* Found enough space. */ + JERRY_CONTEXT (jmem_heap_allocated_size) += required_size; + + while (JERRY_CONTEXT (jmem_heap_allocated_size) >= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) += CONFIG_GC_LIMIT; + } + + break; + } + + JMEM_VALGRIND_NOACCESS_SPACE (current_p, sizeof (jmem_heap_free_t)); + /* Next in list. */ + prev_p = current_p; + current_offset = next_offset; + } + } + + JMEM_VALGRIND_NOACCESS_SPACE (&JERRY_HEAP_CONTEXT (first), sizeof (jmem_heap_free_t)); + + JERRY_ASSERT ((uintptr_t) data_space_p % JMEM_ALIGNMENT == 0); + JMEM_VALGRIND_MALLOCLIKE_SPACE (data_space_p, size); + + return (void *) data_space_p; +#else /* JERRY_SYSTEM_ALLOCATOR */ + JERRY_CONTEXT (jmem_heap_allocated_size) += size; + + while (JERRY_CONTEXT (jmem_heap_allocated_size) >= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) += CONFIG_GC_LIMIT; + } + + return malloc (size); +#endif /* !JERRY_SYSTEM_ALLOCATOR */ +} /* jmem_heap_alloc */ + +/** + * Allocation of memory block, reclaiming memory if the request cannot be fulfilled. + * + * Note: + * Each failed allocation attempt tries to reclaim memory with an increasing pressure, + * up to 'max_pressure', or until a sufficient memory block is found. When JMEM_PRESSURE_FULL + * is reached, the engine is terminated with JERRY_FATAL_OUT_OF_MEMORY. The `max_pressure` argument + * can be used to limit the maximum pressure, and prevent the engine from terminating. + * + * @return NULL, if the required memory size is 0 or not enough memory + * pointer to the allocated memory block, if allocation is successful + */ +static void * +jmem_heap_gc_and_alloc_block (const size_t size, /**< required memory size */ + jmem_pressure_t max_pressure) /**< pressure limit */ +{ + if (JERRY_UNLIKELY (size == 0)) + { + return NULL; + } + + jmem_pressure_t pressure = JMEM_PRESSURE_NONE; + +#if !JERRY_MEM_GC_BEFORE_EACH_ALLOC + if (JERRY_CONTEXT (jmem_heap_allocated_size) + size >= JERRY_CONTEXT (jmem_heap_limit)) + { + pressure = JMEM_PRESSURE_LOW; + ecma_free_unused_memory (pressure); + } +#else /* !JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + ecma_gc_run (); +#endif /* JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + + void *data_space_p = jmem_heap_alloc (size); + + while (JERRY_UNLIKELY (data_space_p == NULL) && JERRY_LIKELY (pressure < max_pressure)) + { + auto v = (int)(pressure); + pressure = (jmem_pressure_t)(++v); + ecma_free_unused_memory (pressure); + data_space_p = jmem_heap_alloc (size); + } + + return data_space_p; +} /* jmem_heap_gc_and_alloc_block */ + +/** + * Internal method for allocating a memory block. + * + * @return NULL, if the required memory size is 0 or not enough memory, or + * pointer to the allocated memory block, if allocation is successful + */ +void *JERRY_ATTR_HOT +jmem_heap_alloc_block_internal (const size_t size) /**< required memory size */ +{ + return jmem_heap_gc_and_alloc_block (size, JMEM_PRESSURE_FULL); +} /* jmem_heap_alloc_block_internal */ + +/** + * Allocation of memory block, reclaiming unused memory if there is not enough. + * + * Note: + * If a sufficiently sized block can't be found, the engine will be terminated with JERRY_FATAL_OUT_OF_MEMORY. + * + * @return NULL, if the required memory is 0 + * pointer to allocated memory block, otherwise + */ +void *JERRY_ATTR_HOT +jmem_heap_alloc_block (const size_t size) /**< required memory size */ +{ + void *block_p = jmem_heap_gc_and_alloc_block (size, JMEM_PRESSURE_FULL); + JMEM_HEAP_STAT_ALLOC (size); + return block_p; +} /* jmem_heap_alloc_block */ + +/** + * Allocation of memory block, reclaiming unused memory if there is not enough. + * + * Note: + * If a sufficiently sized block can't be found, NULL will be returned. + * + * @return NULL, if the required memory size is 0 + * also NULL, if the allocation has failed + * pointer to the allocated memory block, otherwise + */ +void *JERRY_ATTR_HOT +jmem_heap_alloc_block_null_on_error (const size_t size) /**< required memory size */ +{ + void *block_p = jmem_heap_gc_and_alloc_block (size, JMEM_PRESSURE_HIGH); + + return block_p; +} /* jmem_heap_alloc_block_null_on_error */ + +#if !JERRY_SYSTEM_ALLOCATOR +/** + * Finds the block in the free block list which preceeds the argument block + * + * @return pointer to the preceeding block + */ +static jmem_heap_free_t * +jmem_heap_find_prev (const jmem_heap_free_t *const block_p) /**< which memory block's predecessor we're looking for */ +{ + const jmem_heap_free_t *prev_p; + + if (block_p > JERRY_CONTEXT (jmem_heap_list_skip_p)) + { + prev_p = JERRY_CONTEXT (jmem_heap_list_skip_p); + } + else + { + prev_p = &JERRY_HEAP_CONTEXT (first); + } + + JERRY_ASSERT (jmem_is_heap_pointer (block_p)); + const uint32_t block_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (block_p); + + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + /* Find position of region in the list. */ + while (prev_p->next_offset < block_offset) + { + const jmem_heap_free_t *const next_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (prev_p->next_offset); + JERRY_ASSERT (jmem_is_heap_pointer (next_p)); + + JMEM_VALGRIND_DEFINED_SPACE (next_p, sizeof (jmem_heap_free_t)); + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + prev_p = next_p; + } + + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + return (jmem_heap_free_t *) prev_p; +} /* jmem_heap_find_prev */ + +/** + * Inserts the block into the free chain after a specified block. + * + * Note: + * 'jmem_heap_find_prev' can and should be used to find the previous free block + */ +static void +jmem_heap_insert_block (jmem_heap_free_t *block_p, /**< block to insert */ + jmem_heap_free_t *prev_p, /**< the free block after which to insert 'block_p' */ + const size_t size) /**< size of the inserted block */ +{ + JERRY_ASSERT ((uintptr_t) block_p % JMEM_ALIGNMENT == 0); + JERRY_ASSERT (size % JMEM_ALIGNMENT == 0); + + JMEM_VALGRIND_NOACCESS_SPACE (block_p, size); + + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + jmem_heap_free_t *next_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (prev_p->next_offset); + JMEM_VALGRIND_DEFINED_SPACE (block_p, sizeof (jmem_heap_free_t)); + JMEM_VALGRIND_DEFINED_SPACE (next_p, sizeof (jmem_heap_free_t)); + + const uint32_t block_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (block_p); + + /* Update prev. */ + if (jmem_heap_get_region_end (prev_p) == block_p) + { + /* Can be merged. */ + prev_p->size += (uint32_t) size; + JMEM_VALGRIND_NOACCESS_SPACE (block_p, sizeof (jmem_heap_free_t)); + block_p = prev_p; + } + else + { + block_p->size = (uint32_t) size; + prev_p->next_offset = block_offset; + } + + /* Update next. */ + if (jmem_heap_get_region_end (block_p) == next_p) + { + /* Can be merged. */ + block_p->size += next_p->size; + block_p->next_offset = next_p->next_offset; + } + else + { + block_p->next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (next_p); + } + + JERRY_CONTEXT (jmem_heap_list_skip_p) = prev_p; + + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + JMEM_VALGRIND_NOACCESS_SPACE (block_p, sizeof (jmem_heap_free_t)); + JMEM_VALGRIND_NOACCESS_SPACE (next_p, sizeof (jmem_heap_free_t)); +} /* jmem_heap_insert_block */ +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +/** + * Internal method for freeing a memory block. + * + * @return void + */ +void JERRY_ATTR_HOT +jmem_heap_free_block_internal (void *ptr, /**< pointer to beginning of data space of the block */ + const size_t size /**< size of allocated region */) +{ + JERRY_ASSERT (size > 0); + JERRY_ASSERT (JERRY_CONTEXT (jmem_heap_limit) >= JERRY_CONTEXT (jmem_heap_allocated_size)); + JERRY_ASSERT (JERRY_CONTEXT (jmem_heap_allocated_size) > 0); + +#if !JERRY_SYSTEM_ALLOCATOR + /* checking that ptr points to the heap */ + JERRY_ASSERT (jmem_is_heap_pointer (ptr)); + JERRY_ASSERT ((uintptr_t) ptr % JMEM_ALIGNMENT == 0); + + const size_t aligned_size = (size + JMEM_ALIGNMENT - 1) / JMEM_ALIGNMENT * JMEM_ALIGNMENT; + + jmem_heap_free_t *const block_p = (jmem_heap_free_t *) ptr; + jmem_heap_free_t *const prev_p = jmem_heap_find_prev (block_p); + jmem_heap_insert_block (block_p, prev_p, aligned_size); + + JERRY_CONTEXT (jmem_heap_allocated_size) -= aligned_size; + + JMEM_VALGRIND_FREELIKE_SPACE (ptr); +#else /* JERRY_SYSTEM_ALLOCATOR */ + JERRY_CONTEXT (jmem_heap_allocated_size) -= size; + free (ptr); +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + while (JERRY_CONTEXT (jmem_heap_allocated_size) + CONFIG_GC_LIMIT <= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) -= CONFIG_GC_LIMIT; + } + + JERRY_ASSERT (JERRY_CONTEXT (jmem_heap_limit) >= JERRY_CONTEXT (jmem_heap_allocated_size)); +} /* jmem_heap_free_block_internal */ + +/** + * Reallocates the memory region pointed to by 'ptr', changing the size of the allocated region. + * + * @return pointer to the reallocated region + */ +void *JERRY_ATTR_HOT +jmem_heap_realloc_block (void *ptr, /**< memory region to reallocate */ + const size_t old_size, /**< current size of the region */ + const size_t new_size) /**< desired new size */ +{ +#if !JERRY_SYSTEM_ALLOCATOR + JERRY_ASSERT (jmem_is_heap_pointer (ptr)); + JERRY_ASSERT ((uintptr_t) ptr % JMEM_ALIGNMENT == 0); + JERRY_ASSERT (old_size != 0); + JERRY_ASSERT (new_size != 0); + + jmem_heap_free_t *const block_p = (jmem_heap_free_t *) ptr; + const size_t aligned_new_size = (new_size + JMEM_ALIGNMENT - 1) / JMEM_ALIGNMENT * JMEM_ALIGNMENT; + const size_t aligned_old_size = (old_size + JMEM_ALIGNMENT - 1) / JMEM_ALIGNMENT * JMEM_ALIGNMENT; + + if (aligned_old_size == aligned_new_size) + { + JMEM_VALGRIND_RESIZE_SPACE (block_p, old_size, new_size); + JMEM_HEAP_STAT_FREE (old_size); + JMEM_HEAP_STAT_ALLOC (new_size); + return block_p; + } + + if (aligned_new_size < aligned_old_size) + { + JMEM_VALGRIND_RESIZE_SPACE (block_p, old_size, new_size); + JMEM_HEAP_STAT_FREE (old_size); + JMEM_HEAP_STAT_ALLOC (new_size); + jmem_heap_insert_block ((jmem_heap_free_t *) ((uint8_t *) block_p + aligned_new_size), + jmem_heap_find_prev (block_p), + aligned_old_size - aligned_new_size); + + JERRY_CONTEXT (jmem_heap_allocated_size) -= (aligned_old_size - aligned_new_size); + while (JERRY_CONTEXT (jmem_heap_allocated_size) + CONFIG_GC_LIMIT <= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) -= CONFIG_GC_LIMIT; + } + + return block_p; + } + + void *ret_block_p = NULL; + const size_t required_size = aligned_new_size - aligned_old_size; + +#if !JERRY_MEM_GC_BEFORE_EACH_ALLOC + if (JERRY_CONTEXT (jmem_heap_allocated_size) + required_size >= JERRY_CONTEXT (jmem_heap_limit)) + { + ecma_free_unused_memory (JMEM_PRESSURE_LOW); + } +#else /* !JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + ecma_gc_run (); +#endif /* JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + + jmem_heap_free_t *prev_p = jmem_heap_find_prev (block_p); + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + jmem_heap_free_t *const next_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (prev_p->next_offset); + + /* Check if block can be extended at the end */ + if (((jmem_heap_free_t *) ((uint8_t *) block_p + aligned_old_size)) == next_p) + { + JMEM_VALGRIND_DEFINED_SPACE (next_p, sizeof (jmem_heap_free_t)); + + if (required_size <= next_p->size) + { + /* Block can be extended, update the list. */ + if (required_size == next_p->size) + { + prev_p->next_offset = next_p->next_offset; + } + else + { + jmem_heap_free_t *const new_next_p = (jmem_heap_free_t *) ((uint8_t *) next_p + required_size); + JMEM_VALGRIND_DEFINED_SPACE (new_next_p, sizeof (jmem_heap_free_t)); + new_next_p->next_offset = next_p->next_offset; + new_next_p->size = (uint32_t) (next_p->size - required_size); + JMEM_VALGRIND_NOACCESS_SPACE (new_next_p, sizeof (jmem_heap_free_t)); + prev_p->next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (new_next_p); + } + + /* next_p will be marked as undefined space. */ + JMEM_VALGRIND_RESIZE_SPACE (block_p, old_size, new_size); + ret_block_p = block_p; + } + else + { + JMEM_VALGRIND_NOACCESS_SPACE (next_p, sizeof (jmem_heap_free_t)); + } + + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + } + /* + * Check if block can be extended at the front. + * This is less optimal because we need to copy the data, but still better than allocting a new block. + */ + else if (jmem_heap_get_region_end (prev_p) == block_p) + { + if (required_size <= prev_p->size) + { + if (required_size == prev_p->size) + { + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + prev_p = jmem_heap_find_prev (prev_p); + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + prev_p->next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (next_p); + } + else + { + prev_p->size = (uint32_t) (prev_p->size - required_size); + } + + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + + ret_block_p = (uint8_t *) block_p - required_size; + + /* Mark the the new block as undefined so that we are able to write to it. */ + JMEM_VALGRIND_UNDEFINED_SPACE (ret_block_p, old_size); + /* The blocks are likely to overlap, so mark the old block as defined memory again. */ + JMEM_VALGRIND_DEFINED_SPACE (block_p, old_size); + memmove (ret_block_p, block_p, old_size); + + JMEM_VALGRIND_FREELIKE_SPACE (block_p); + JMEM_VALGRIND_MALLOCLIKE_SPACE (ret_block_p, new_size); + JMEM_VALGRIND_DEFINED_SPACE (ret_block_p, old_size); + } + else + { + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + } + } + + if (ret_block_p != NULL) + { + /* Managed to extend the block. Update memory usage and the skip pointer. */ + JERRY_CONTEXT (jmem_heap_list_skip_p) = prev_p; + JERRY_CONTEXT (jmem_heap_allocated_size) += required_size; + + while (JERRY_CONTEXT (jmem_heap_allocated_size) >= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) += CONFIG_GC_LIMIT; + } + } + else + { + /* Could not extend block. Allocate new region and copy the data. */ + /* jmem_heap_alloc_block_internal will adjust the allocated_size, but insert_block will not, + so we reduce it here first, so that the limit calculation remains consistent. */ + JERRY_CONTEXT (jmem_heap_allocated_size) -= aligned_old_size; + ret_block_p = jmem_heap_alloc_block_internal (new_size); + + /* jmem_heap_alloc_block_internal may trigger garbage collection, which can create new free blocks + * in the heap structure, so we need to look up the previous block again. */ + prev_p = jmem_heap_find_prev (block_p); + + memcpy (ret_block_p, block_p, old_size); + jmem_heap_insert_block (block_p, prev_p, aligned_old_size); + /* jmem_heap_alloc_block_internal will call JMEM_VALGRIND_MALLOCLIKE_SPACE */ + JMEM_VALGRIND_FREELIKE_SPACE (block_p); + } + + JMEM_HEAP_STAT_FREE (old_size); + JMEM_HEAP_STAT_ALLOC (new_size); + return ret_block_p; +#else /* JERRY_SYSTEM_ALLOCATOR */ + const size_t required_size = new_size - old_size; + +#if !JERRY_MEM_GC_BEFORE_EACH_ALLOC + if (JERRY_CONTEXT (jmem_heap_allocated_size) + required_size >= JERRY_CONTEXT (jmem_heap_limit)) + { + ecma_free_unused_memory (JMEM_PRESSURE_LOW); + } +#else /* !JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + ecma_gc_run (); +#endif /* JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + + JERRY_CONTEXT (jmem_heap_allocated_size) += required_size; + + while (JERRY_CONTEXT (jmem_heap_allocated_size) >= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) += CONFIG_GC_LIMIT; + } + + while (JERRY_CONTEXT (jmem_heap_allocated_size) + CONFIG_GC_LIMIT <= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) -= CONFIG_GC_LIMIT; + } + + JMEM_HEAP_STAT_FREE (old_size); + JMEM_HEAP_STAT_ALLOC (new_size); + return realloc (ptr, new_size); +#endif /* !JERRY_SYSTEM_ALLOCATOR */ +} /* jmem_heap_realloc_block */ + +/** + * Free memory block + * + * @return void + */ +void JERRY_ATTR_HOT +jmem_heap_free_block (void *ptr, /**< pointer to beginning of data space of the block */ + const size_t size) /**< size of allocated region */ +{ + jmem_heap_free_block_internal (ptr, size); + JMEM_HEAP_STAT_FREE (size); + return; +} /* jmem_heap_free_block */ + +#ifndef JERRY_NDEBUG +/** + * Check whether the pointer points to the heap + * + * Note: + * the routine should be used only for assertion checks + * + * @return true - if pointer points to the heap, + * false - otherwise + */ +bool +jmem_is_heap_pointer (const void *pointer) /**< pointer */ +{ +#if !JERRY_SYSTEM_ALLOCATOR + return ((uint8_t *) pointer >= JERRY_HEAP_CONTEXT (area) + && (uint8_t *) pointer <= (JERRY_HEAP_CONTEXT (area) + JMEM_HEAP_AREA_SIZE)); +#else /* JERRY_SYSTEM_ALLOCATOR */ + JERRY_UNUSED (pointer); + return true; +#endif /* !JERRY_SYSTEM_ALLOCATOR */ +} /* jmem_is_heap_pointer */ +#endif /* !JERRY_NDEBUG */ + + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-poolman.cpp b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-poolman.cpp new file mode 100644 index 00000000..c45c774a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-poolman.cpp @@ -0,0 +1,193 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Memory pool manager implementation + */ + +#include "jcontext.h" +#include "jmem.h" +#include "jrt-libc-includes.h" + +#define JMEM_ALLOCATOR_INTERNAL +#include "jmem-allocator-internal.h" + +#if JERRY_MEM_GC_BEFORE_EACH_ALLOC +#include "ecma-gc.h" +#endif /* JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + +/** \addtogroup mem Memory allocation + * @{ + * + * \addtogroup poolman Memory pool manager + * @{ + */ + +/** + * Finalize pool manager + */ +void +jmem_pools_finalize (void) +{ + jmem_pools_collect_empty (); + + JERRY_ASSERT (JERRY_CONTEXT (jmem_free_8_byte_chunk_p) == NULL); +#if JERRY_CPOINTER_32_BIT + JERRY_ASSERT (JERRY_CONTEXT (jmem_free_16_byte_chunk_p) == NULL); +#endif /* JERRY_CPOINTER_32_BIT */ +} /* jmem_pools_finalize */ + +/** + * Allocate a chunk of specified size + * + * @return pointer to allocated chunk, if allocation was successful, + * or NULL - if not enough memory. + */ +void *JERRY_ATTR_HOT +jmem_pools_alloc (size_t size) /**< size of the chunk */ +{ +#if JERRY_MEM_GC_BEFORE_EACH_ALLOC + ecma_gc_run (); +#endif /* JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + +#if JERRY_CPOINTER_32_BIT + if (size <= 8) + { +#else /* !JERRY_CPOINTER_32_BIT */ + JERRY_ASSERT (size <= 8); +#endif /* JERRY_CPOINTER_32_BIT */ + + if (JERRY_CONTEXT (jmem_free_8_byte_chunk_p) != NULL) + { + const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p); + + JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_p->next_p; + JMEM_VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + + JMEM_HEAP_STAT_ALLOC (8); + return (void *) chunk_p; + } + else + { + void *chunk_p = jmem_heap_alloc_block_internal (8); + JMEM_HEAP_STAT_ALLOC (8); + return chunk_p; + } + +#if JERRY_CPOINTER_32_BIT + } + + JERRY_ASSERT (size <= 16); + + if (JERRY_CONTEXT (jmem_free_16_byte_chunk_p) != NULL) + { + const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p); + + JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_p->next_p; + JMEM_VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + + JMEM_HEAP_STAT_ALLOC (16); + return (void *) chunk_p; + } + else + { + void *chunk_p = jmem_heap_alloc_block_internal (16); + JMEM_HEAP_STAT_ALLOC (16); + return chunk_p; + } +#endif /* JERRY_CPOINTER_32_BIT */ +} /* jmem_pools_alloc */ + +/** + * Free the chunk + * + * @return void + */ +void JERRY_ATTR_HOT +jmem_pools_free (void *chunk_p, /**< pointer to the chunk */ + size_t size) /**< size of the chunk */ +{ + JERRY_ASSERT (chunk_p != NULL); + JMEM_HEAP_STAT_FREE (size); + + jmem_pools_chunk_t *const chunk_to_free_p = (jmem_pools_chunk_t *) chunk_p; + + JMEM_VALGRIND_DEFINED_SPACE (chunk_to_free_p, size); + +#if JERRY_CPOINTER_32_BIT + if (size <= 8) + { +#else /* !JERRY_CPOINTER_32_BIT */ + JERRY_ASSERT (size <= 8); +#endif /* JERRY_CPOINTER_32_BIT */ + + chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p); + JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_to_free_p; + +#if JERRY_CPOINTER_32_BIT + } + else + { + JERRY_ASSERT (size <= 16); + + chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p); + JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_to_free_p; + } +#endif /* JERRY_CPOINTER_32_BIT */ + + JMEM_VALGRIND_NOACCESS_SPACE (chunk_to_free_p, size); +} /* jmem_pools_free */ + +/** + * Collect empty pool chunks + */ +void +jmem_pools_collect_empty (void) +{ + jmem_pools_chunk_t *chunk_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p); + JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = NULL; + + while (chunk_p) + { + JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + jmem_pools_chunk_t *const next_p = chunk_p->next_p; + JMEM_VALGRIND_NOACCESS_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + + jmem_heap_free_block_internal (chunk_p, 8); + chunk_p = next_p; + } + +#if JERRY_CPOINTER_32_BIT + chunk_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p); + JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = NULL; + + while (chunk_p) + { + JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + jmem_pools_chunk_t *const next_p = chunk_p->next_p; + JMEM_VALGRIND_NOACCESS_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + + jmem_heap_free_block_internal (chunk_p, 16); + chunk_p = next_p; + } +#endif /* JERRY_CPOINTER_32_BIT */ +} /* jmem_pools_collect_empty */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem.h b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem.h new file mode 100644 index 00000000..e7b7c180 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem.h @@ -0,0 +1,282 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JMEM_H +#define JMEM_H + +#include "jrt.h" + +/** \addtogroup mem Memory allocation + * @{ + * + * \addtogroup heap Heap + * @{ + */ + +/** + * Logarithm of required alignment for allocated units/blocks + */ +#define JMEM_ALIGNMENT_LOG 3 + +/** + * Representation of NULL value for compressed pointers + */ +#define JMEM_CP_NULL ((jmem_cpointer_t) 0) + +/** + * Required alignment for allocated units/blocks + */ +#define JMEM_ALIGNMENT (1u << JMEM_ALIGNMENT_LOG) + +/** + * Pointer value can be directly stored without compression + */ +#if UINTPTR_MAX <= UINT32_MAX +#define JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY +#endif /* UINTPTR_MAX <= UINT32_MAX */ + +/** + * Mask for tag part in jmem_cpointer_tag_t + */ +#define JMEM_TAG_MASK 0x7u + +/** + * Shift for tag part in jmem_cpointer_tag_t + */ +#if defined(JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY) && JERRY_CPOINTER_32_BIT +#define JMEM_TAG_SHIFT 0 +#else /* !JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY || !JERRY_CPOINTER_32_BIT */ +#define JMEM_TAG_SHIFT 3 +#endif /* JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY && JERRY_CPOINTER_32_BIT */ + +/** + * Bit mask for tag part in jmem_cpointer_tag_t + */ +enum +{ + JMEM_FIRST_TAG_BIT_MASK = (1u << 0), /**< first tag bit mask **/ + JMEM_SECOND_TAG_BIT_MASK = (1u << 1), /**< second tag bit mask **/ + JMEM_THIRD_TAG_BIT_MASK = (1u << 2), /**< third tag bit mask **/ +}; + +/** + * Compressed pointer representations + * + * 16 bit representation: + * The jmem_cpointer_t is defined as uint16_t + * and it can contain any sixteen bit value. + * + * 32 bit representation: + * The jmem_cpointer_t is defined as uint32_t. + * The lower JMEM_ALIGNMENT_LOG bits must be zero. + * The other bits can have any value. + * + * The 16 bit representation always encodes an offset from + * a heap base. The 32 bit representation currently encodes + * raw 32 bit JMEM_ALIGNMENT aligned pointers on 32 bit systems. + * This can be extended to encode a 32 bit offset from a heap + * base on 64 bit systems in the future. There are no plans + * to support more than 4G address space for JerryScript. + */ + +/** + * Compressed pointer + */ +#if JERRY_CPOINTER_32_BIT +typedef uint32_t jmem_cpointer_t; +#else /* !JERRY_CPOINTER_32_BIT */ +typedef uint16_t jmem_cpointer_t; +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Compressed pointer with tag value + */ +typedef uint32_t jmem_cpointer_tag_t; + +/** + * Memory usage pressure for reclaiming unused memory. + * + * Each failed allocation will try to reclaim memory with increasing pressure, + * until enough memory is freed to fulfill the allocation request. + * + * If not enough memory is freed and JMEM_PRESSURE_FULL is reached, + * then the engine is shut down with JERRY_FATAL_OUT_OF_MEMORY. + */ +typedef enum +{ + JMEM_PRESSURE_NONE, /**< no memory pressure */ + JMEM_PRESSURE_LOW, /**< low memory pressure */ + JMEM_PRESSURE_HIGH, /**< high memory pressure */ + JMEM_PRESSURE_FULL, /**< memory full */ +} jmem_pressure_t; + +/** + * Node for free chunk list + */ +typedef struct jmem_pools_chunk_t +{ + struct jmem_pools_chunk_t *next_p; /**< pointer to next pool chunk */ +} jmem_pools_chunk_t; + +/** + * Free region node + */ +typedef struct +{ + uint32_t next_offset; /**< Offset of next region in list */ + uint32_t size; /**< Size of region */ +} jmem_heap_free_t; + +void jmem_init (void); +void jmem_finalize (void); + +void *jmem_heap_alloc_block (const size_t size); +void *jmem_heap_alloc_block_null_on_error (const size_t size); +void *jmem_heap_realloc_block (void *ptr, const size_t old_size, const size_t new_size); +void jmem_heap_free_block (void *ptr, const size_t size); + + +jmem_cpointer_t JERRY_ATTR_PURE jmem_compress_pointer (const void *pointer_p); +void *JERRY_ATTR_PURE jmem_decompress_pointer (uintptr_t compressed_pointer); + +/** + * Define a local array variable and allocate memory for the array on the heap. + * + * If requested number of elements is zero, assign NULL to the variable. + * + * Warning: + * if there is not enough memory on the heap, shutdown engine with JERRY_FATAL_OUT_OF_MEMORY. + */ +#define JMEM_DEFINE_LOCAL_ARRAY(var_name, number, type) \ + { \ + size_t var_name##___size = (size_t) (number) * sizeof (type); \ + type *var_name = (type *) (jmem_heap_alloc_block (var_name##___size)); + +/** + * Free the previously defined local array variable, freeing corresponding block on the heap, + * if it was allocated (i.e. if the array's size was non-zero). + */ +#define JMEM_FINALIZE_LOCAL_ARRAY(var_name) \ + if (var_name != NULL) \ + { \ + JERRY_ASSERT (var_name##___size != 0); \ + \ + jmem_heap_free_block (var_name, var_name##___size); \ + } \ + else \ + { \ + JERRY_ASSERT (var_name##___size == 0); \ + } \ + } + +/** + * Get value of pointer from specified non-null compressed pointer value + */ +#define JMEM_CP_GET_NON_NULL_POINTER(type, cp_value) ((type *) (jmem_decompress_pointer (cp_value))) + +/** + * Get value of pointer from specified compressed pointer value + */ +#define JMEM_CP_GET_POINTER(type, cp_value) \ + (((JERRY_UNLIKELY ((cp_value) == JMEM_CP_NULL)) ? NULL : JMEM_CP_GET_NON_NULL_POINTER (type, cp_value))) + +/** + * Set value of non-null compressed pointer so that it will correspond + * to specified non_compressed_pointer + */ +#define JMEM_CP_SET_NON_NULL_POINTER(cp_value, non_compressed_pointer) \ + (cp_value) = jmem_compress_pointer (non_compressed_pointer) + +/** + * Set value of compressed pointer so that it will correspond + * to specified non_compressed_pointer + */ +#define JMEM_CP_SET_POINTER(cp_value, non_compressed_pointer) \ + do \ + { \ + void *ptr_value = (void *) non_compressed_pointer; \ + \ + if (JERRY_UNLIKELY ((ptr_value) == NULL)) \ + { \ + (cp_value) = JMEM_CP_NULL; \ + } \ + else \ + { \ + JMEM_CP_SET_NON_NULL_POINTER (cp_value, ptr_value); \ + } \ + } while (false); + +/** + * Set value of pointer-tag value so that it will correspond + * to specified non_compressed_pointer along with tag + */ +#define JMEM_CP_SET_NON_NULL_POINTER_TAG(cp_value, pointer, tag) \ + do \ + { \ + JERRY_ASSERT ((uintptr_t) tag < (uintptr_t) (JMEM_ALIGNMENT)); \ + jmem_cpointer_tag_t compressed_ptr = jmem_compress_pointer (pointer); \ + (cp_value) = (jmem_cpointer_tag_t) ((compressed_ptr << JMEM_TAG_SHIFT) | tag); \ + } while (false); + +/** + * Extract value of pointer from specified pointer-tag value + */ +#define JMEM_CP_GET_NON_NULL_POINTER_FROM_POINTER_TAG(type, cp_value) \ + ((type *) (jmem_decompress_pointer ((cp_value & ~JMEM_TAG_MASK) >> JMEM_TAG_SHIFT))) + +/** + * Extract tag bits from pointer-tag value + */ +#define JMEM_CP_GET_POINTER_TAG_BITS(cp_value) \ + (cp_value & (JMEM_FIRST_TAG_BIT_MASK | JMEM_SECOND_TAG_BIT_MASK | JMEM_THIRD_TAG_BIT_MASK)) + +/** + * Get value of each tag from specified pointer-tag value + */ +#define JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG(cp_value) \ + (cp_value & JMEM_FIRST_TAG_BIT_MASK) /**< get first tag bit \ + **/ +#define JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG(cp_value) \ + (cp_value & JMEM_SECOND_TAG_BIT_MASK) /**< get second tag bit **/ +#define JMEM_CP_GET_THIRD_BIT_FROM_POINTER_TAG(cp_value) \ + (cp_value & JMEM_THIRD_TAG_BIT_MASK) /**< get third tag bit \ + **/ + +/** + * Set value of each tag to specified pointer-tag value + */ +#define JMEM_CP_SET_FIRST_BIT_TO_POINTER_TAG(cp_value) \ + (cp_value) = (cp_value | JMEM_FIRST_TAG_BIT_MASK) /**< set first tag bit **/ +#define JMEM_CP_SET_SECOND_BIT_TO_POINTER_TAG(cp_value) \ + (cp_value) = (cp_value | JMEM_SECOND_TAG_BIT_MASK) /**< set second tag bit **/ +#define JMEM_CP_SET_THIRD_BIT_TO_POINTER_TAG(cp_value) \ + (cp_value) = (cp_value | JMEM_THIRD_TAG_BIT_MASK) /**< set third tag bit **/ + +/** + * @} + * \addtogroup poolman Memory pool manager + * @{ + */ + +void *jmem_pools_alloc (size_t size); +void jmem_pools_free (void *chunk_p, size_t size); +void jmem_pools_collect_empty (void); + +/** + * @} + * @} + */ + +#endif /* !JMEM_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/meson.build b/src/loaders/lottie/jerryscript/jerry-core/jmem/meson.build new file mode 100644 index 00000000..b95f6dde --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/meson.build @@ -0,0 +1,12 @@ +source_file = [ + 'jmem-allocator-internal.h', + 'jmem.h', + 'jmem-allocator.cpp', + 'jmem-heap.cpp', + 'jmem-poolman.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-bit-fields.h b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-bit-fields.h new file mode 100644 index 00000000..53ea31b2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-bit-fields.h @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JRT_BIT_FIELDS_H +#define JRT_BIT_FIELDS_H + +/** + * Extract a bit-field. + * + * @param type type of container + * @param container container to extract bit-field from + * @param lsb least significant bit of the value to be extracted + * @param width width of the bit-field to be extracted + * @return bit-field's value + */ +#define JRT_EXTRACT_BIT_FIELD(type, container, lsb, width) (((container) >> lsb) & ((((type) 1) << (width)) - 1)) + +/** + * Set a bit-field. + * + * @param type type of container + * @param container container to insert bit-field to + * @param new_bit_field_value value of bit-field to insert + * @param lsb least significant bit of the value to be inserted + * @param width width of the bit-field to be inserted + * @return bit-field's value + */ +#define JRT_SET_BIT_FIELD_VALUE(type, container, new_bit_field_value, lsb, width) \ + (((container) & ~(((((type) 1) << (width)) - 1) << (lsb))) | (((type) new_bit_field_value) << (lsb))) + +#endif /* !JRT_BIT_FIELDS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-fatals.cpp b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-fatals.cpp new file mode 100644 index 00000000..4ce37293 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-fatals.cpp @@ -0,0 +1,96 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of exit with specified status code. + */ + +#include "jrt-libc-includes.h" +#include "jrt.h" + +/* + * Exit with specified status code. + * + * If !JERRY_NDEBUG and code != 0, print status code with description + * and call assertion fail handler. + */ +void JERRY_ATTR_NORETURN +jerry_fatal (jerry_fatal_code_t code) /**< status code */ +{ +#ifndef JERRY_NDEBUG + switch (code) + { + case JERRY_FATAL_OUT_OF_MEMORY: + { + JERRY_ERROR_MSG ("Error: JERRY_FATAL_OUT_OF_MEMORY\n"); + break; + } + case JERRY_FATAL_REF_COUNT_LIMIT: + { + JERRY_ERROR_MSG ("Error: JERRY_FATAL_REF_COUNT_LIMIT\n"); + break; + } + case JERRY_FATAL_UNTERMINATED_GC_LOOPS: + { + JERRY_ERROR_MSG ("Error: JERRY_FATAL_UNTERMINATED_GC_LOOPS\n"); + break; + } + case JERRY_FATAL_DISABLED_BYTE_CODE: + { + JERRY_ERROR_MSG ("Error: JERRY_FATAL_DISABLED_BYTE_CODE\n"); + break; + } + case JERRY_FATAL_FAILED_ASSERTION: + { + JERRY_ERROR_MSG ("Error: JERRY_FATAL_FAILED_ASSERTION\n"); + break; + } + } +#endif /* !JERRY_NDEBUG */ + + /* to make compiler happy for some RTOS: 'control reaches end of non-void function' */ + while (true) + { + } +} /* jerry_fatal */ + +#ifndef JERRY_NDEBUG +/** + * Handle failed assertion + */ +void JERRY_ATTR_NORETURN +jerry_assert_fail (const char *assertion, /**< assertion condition string */ + const char *file, /**< file name */ + const char *function, /**< function name */ + const uint32_t line) /**< line */ +{ + JERRY_ERROR_MSG ("ICE: Assertion '%s' failed at %s(%s):%u.\n", assertion, file, function, line); + + jerry_fatal (JERRY_FATAL_FAILED_ASSERTION); +} /* jerry_assert_fail */ + +/** + * Handle execution of control path that should be unreachable + */ +void JERRY_ATTR_NORETURN +jerry_unreachable (const char *file, /**< file name */ + const char *function, /**< function name */ + const uint32_t line) /**< line */ +{ + JERRY_ERROR_MSG ("ICE: Unreachable control path at %s(%s):%u was executed.\n", file, function, line); + + jerry_fatal (JERRY_FATAL_FAILED_ASSERTION); +} /* jerry_unreachable */ +#endif /* !JERRY_NDEBUG */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-libc-includes.h b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-libc-includes.h new file mode 100644 index 00000000..bf87a86b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-libc-includes.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JRT_LIBC_INCLUDES_H +#define JRT_LIBC_INCLUDES_H + +#include +#include +#include +#include +#include +#include + +#endif /* !JRT_LIBC_INCLUDES_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-logging.cpp b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-logging.cpp new file mode 100644 index 00000000..512abb6b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-logging.cpp @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jrt.h" + +static jerry_log_level_t jerry_log_level = JERRY_LOG_LEVEL_ERROR; + +/** + * Get current log level + * + * @return log level + */ +jerry_log_level_t +jerry_jrt_get_log_level (void) +{ + return jerry_log_level; +} /* jerry_jrt_get_log_level */ + +/** + * Set log level + * + * @param level: new log level + */ +void +jerry_jrt_set_log_level (jerry_log_level_t level) +{ + jerry_log_level = level; +} /* jerry_jrt_set_log_level */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-types.h b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-types.h new file mode 100644 index 00000000..16d444e2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-types.h @@ -0,0 +1,24 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JRT_TYPES_H +#define JRT_TYPES_H + +#include +#include +#include +#include + +#endif /* !JRT_TYPES_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt.h b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt.h new file mode 100644 index 00000000..119914ba --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt.h @@ -0,0 +1,229 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JRT_H +#define JRT_H + +#include +#include + +#include "jerryscript-core.h" +#include "jerryscript-port.h" + +#include "jrt-types.h" + +/* + * Constants + */ +#define JERRY_BITSINBYTE 8 + +/* + * Make sure unused parameters, variables, or expressions trigger no compiler warning. + */ +#define JERRY_UNUSED(x) ((void) (x)) + +#define JERRY_UNUSED_1(_1) JERRY_UNUSED (_1) +#define JERRY_UNUSED_2(_1, _2) JERRY_UNUSED (_1), JERRY_UNUSED_1 (_2) +#define JERRY_UNUSED_3(_1, _2, _3) JERRY_UNUSED (_1), JERRY_UNUSED_2 (_2, _3) +#define JERRY_UNUSED_4(_1, _2, _3, _4) JERRY_UNUSED (_1), JERRY_UNUSED_3 (_2, _3, _4) +#define JERRY_UNUSED_5(_1, _2, _3, _4, _5) JERRY_UNUSED (_1), JERRY_UNUSED_4 (_2, _3, _4, _5) +#define JERRY_UNUSED_6(_1, _2, _3, _4, _5, _6) JERRY_UNUSED (_1), JERRY_UNUSED_5 (_2, _3, _4, _5, _6) +#define JERRY_UNUSED_7(_1, _2, _3, _4, _5, _6, _7) JERRY_UNUSED (_1), JERRY_UNUSED_6 (_2, _3, _4, _5, _6, _7) +#define JERRY_UNUSED_8(_1, _2, _3, _4, _5, _6, _7, _8) JERRY_UNUSED (_1), JERRY_UNUSED_7 (_2, _3, _4, _5, _6, _7, _8) + +#define JERRY_VA_ARGS_NUM_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N +#define JERRY_VA_ARGS_NUM(...) JERRY_VA_ARGS_NUM_IMPL (__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +#define JERRY_UNUSED_ALL_IMPL_(nargs) JERRY_UNUSED_##nargs +#define JERRY_UNUSED_ALL_IMPL(nargs) JERRY_UNUSED_ALL_IMPL_ (nargs) +#define JERRY_UNUSED_ALL(...) JERRY_UNUSED_ALL_IMPL (JERRY_VA_ARGS_NUM (__VA_ARGS__)) (__VA_ARGS__) + +/* + * Asserts + * + * Warning: + * Don't use JERRY_STATIC_ASSERT in headers, because + * __LINE__ may be the same for asserts in a header + * and in an implementation file. + */ +#define JERRY_STATIC_ASSERT_GLUE_(a, b, c) a##b##_##c +#define JERRY_STATIC_ASSERT_GLUE(a, b, c) JERRY_STATIC_ASSERT_GLUE_ (a, b, c) +#define JERRY_STATIC_ASSERT(x, msg) \ + enum \ + { \ + JERRY_STATIC_ASSERT_GLUE (static_assertion_failed_, __LINE__, msg) = (!!x) \ + } + +#ifndef JERRY_NDEBUG +void JERRY_ATTR_NORETURN jerry_assert_fail (const char *assertion, + const char *file, + const char *function, + const uint32_t line); +void JERRY_ATTR_NORETURN jerry_unreachable (const char *file, const char *function, const uint32_t line); + +#define JERRY_ASSERT(x) \ + do \ + { \ + if (JERRY_UNLIKELY (!(x))) \ + { \ + jerry_assert_fail (#x, __FILE__, __func__, __LINE__); \ + } \ + } while (0) + +#define JERRY_UNREACHABLE() \ + do \ + { \ + jerry_unreachable (__FILE__, __func__, __LINE__); \ + } while (0) +#else /* JERRY_NDEBUG */ +#define JERRY_ASSERT(x) \ + do \ + { \ + if (false) \ + { \ + JERRY_UNUSED (x); \ + } \ + } while (0) + +#ifdef __GNUC__ +#define JERRY_UNREACHABLE() __builtin_unreachable () +#endif /* __GNUC__ */ + +#ifdef _MSC_VER +#define JERRY_UNREACHABLE() _assume (0) +#endif /* _MSC_VER */ + +#ifndef JERRY_UNREACHABLE +#define JERRY_UNREACHABLE() +#endif /* !JERRY_UNREACHABLE */ + +#endif /* !JERRY_NDEBUG */ + +/** + * Exit on fatal error + */ +void JERRY_ATTR_NORETURN jerry_fatal (jerry_fatal_code_t code); + +jerry_log_level_t jerry_jrt_get_log_level (void); +void jerry_jrt_set_log_level (jerry_log_level_t level); + +/* + * Logging + */ +#if JERRY_LOGGING +#define JERRY_ERROR_MSG(...) jerry_log (JERRY_LOG_LEVEL_ERROR, __VA_ARGS__) +#define JERRY_WARNING_MSG(...) jerry_log (JERRY_LOG_LEVEL_WARNING, __VA_ARGS__) +#define JERRY_DEBUG_MSG(...) jerry_log (JERRY_LOG_LEVEL_DEBUG, __VA_ARGS__) +#define JERRY_TRACE_MSG(...) jerry_log (JERRY_LOG_LEVEL_TRACE, __VA_ARGS__) +#else /* !JERRY_LOGGING */ +#define JERRY_ERROR_MSG(...) \ + do \ + { \ + if (false) \ + { \ + JERRY_UNUSED_ALL (__VA_ARGS__); \ + } \ + } while (0) +#define JERRY_WARNING_MSG(...) \ + do \ + { \ + if (false) \ + { \ + JERRY_UNUSED_ALL (__VA_ARGS__); \ + } \ + } while (0) +#define JERRY_DEBUG_MSG(...) \ + do \ + { \ + if (false) \ + { \ + JERRY_UNUSED_ALL (__VA_ARGS__); \ + } \ + } while (0) +#define JERRY_TRACE_MSG(...) \ + do \ + { \ + if (false) \ + { \ + JERRY_UNUSED_ALL (__VA_ARGS__); \ + } \ + } while (0) +#endif /* JERRY_LOGGING */ + +/** + * Size of struct member + */ +#define JERRY_SIZE_OF_STRUCT_MEMBER(struct_name, member_name) sizeof (((struct_name *) NULL)->member_name) + +/** + * Aligns @a value to @a alignment. @a must be the power of 2. + * + * Returns minimum positive value, that divides @a alignment and is more than or equal to @a value + */ +#define JERRY_ALIGNUP(value, alignment) (((value) + ((alignment) -1)) & ~((alignment) -1)) + +/** + * Align value down + */ +#define JERRY_ALIGNDOWN(value, alignment) ((value) & ~((alignment) -1)) + +/* + * min, max + */ +#define JERRY_MIN(v1, v2) (((v1) < (v2)) ? (v1) : (v2)) +#define JERRY_MAX(v1, v2) (((v1) < (v2)) ? (v2) : (v1)) + +/** + * Calculate the index of the first non-zero bit of a 32 bit integer value + */ +#define JERRY__LOG2_1(n) (((n) >= 2) ? 1 : 0) +#define JERRY__LOG2_2(n) (((n) >= 1 << 2) ? (2 + JERRY__LOG2_1 ((n) >> 2)) : JERRY__LOG2_1 (n)) +#define JERRY__LOG2_4(n) (((n) >= 1 << 4) ? (4 + JERRY__LOG2_2 ((n) >> 4)) : JERRY__LOG2_2 (n)) +#define JERRY__LOG2_8(n) (((n) >= 1 << 8) ? (8 + JERRY__LOG2_4 ((n) >> 8)) : JERRY__LOG2_4 (n)) +#define JERRY_LOG2(n) (((n) >= 1 << 16) ? (16 + JERRY__LOG2_8 ((n) >> 16)) : JERRY__LOG2_8 (n)) + +/** + * JERRY_BLOCK_TAIL_CALL_OPTIMIZATION + * + * Adapted from abseil ( https://github.com/abseil/ ) + * + * Instructs the compiler to avoid optimizing tail-call recursion. This macro is + * useful when you wish to preserve the existing function order within a stack + * trace for logging, debugging, or profiling purposes. + * + * Example: + * + * int f() { + * int result = g(); + * JERRY_BLOCK_TAIL_CALL_OPTIMIZATION(); + * return result; + * } + * + * This macro is intentionally here as jerryscript-compiler.h is a public header and + * it does not make sense to expose this macro to the public. + */ +#if defined(__clang__) || defined(__GNUC__) +/* Clang/GCC will not tail call given inline volatile assembly. */ +#define JERRY_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__ ("") +#else /* !defined(__clang__) && !defined(__GNUC__) */ +/* On GCC 10.x this version also works. */ +#define JERRY_BLOCK_TAIL_CALL_OPTIMIZATION() \ + do \ + { \ + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_API_ENABLED; \ + } while (0) +#endif /* defined(__clang__) || defined (__GNUC__) */ + +#endif /* !JRT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/meson.build b/src/loaders/lottie/jerryscript/jerry-core/jrt/meson.build new file mode 100644 index 00000000..08b94cf3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/meson.build @@ -0,0 +1,13 @@ +source_file = [ + 'jrt-bit-fields.h', + 'jrt-libc-includes.h', + 'jrt-types.h', + 'jrt.h', + 'jrt-fatals.cpp', + 'jrt-logging.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.cpp b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.cpp new file mode 100644 index 00000000..fc15f987 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.cpp @@ -0,0 +1,995 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lit-char-helpers.h" + +#include "ecma-helpers.h" + +#include "jerry-config.h" +#include "lit-strings.h" +#include "lit-unicode-ranges-sup.inc.h" +#include "lit-unicode-ranges.inc.h" + +#if JERRY_UNICODE_CASE_CONVERSION +#include "lit-unicode-conversions-sup.inc.h" +#include "lit-unicode-conversions.inc.h" +#include "lit-unicode-folding.inc.h" +#endif /* JERRY_UNICODE_CASE_CONVERSION */ + +#define NUM_OF_ELEMENTS(array) (sizeof (array) / sizeof ((array)[0])) + +/** + * Binary search algorithm that searches the a + * character in the given char array. + * + * @return true - if the character is in the given array + * false - otherwise + */ +#define LIT_SEARCH_CHAR_IN_ARRAY_FN(function_name, char_type, array_type) \ + static bool function_name (char_type c, /**< code unit */ \ + const array_type *array, /**< array */ \ + int size_of_array) /**< length of the array */ \ + { \ + int bottom = 0; \ + int top = size_of_array - 1; \ + \ + while (bottom <= top) \ + { \ + int middle = (bottom + top) / 2; \ + char_type current = array[middle]; \ + \ + if (current == c) \ + { \ + return true; \ + } \ + \ + if (c < current) \ + { \ + top = middle - 1; \ + } \ + else \ + { \ + bottom = middle + 1; \ + } \ + } \ + \ + return false; \ + } /* __function_name */ + +LIT_SEARCH_CHAR_IN_ARRAY_FN (lit_search_char_in_array, ecma_char_t, uint16_t) + +LIT_SEARCH_CHAR_IN_ARRAY_FN (lit_search_codepoint_in_array, lit_code_point_t, uint32_t) + +/** + * Binary search algorithm that searches a character in the given intervals. + * Intervals specifed by two arrays. The first one contains the starting points + * of the intervals, the second one contains the length of them. + * + * @return true - if the the character is included (inclusively) in one of the intervals in the given array + * false - otherwise + */ +#define LIT_SEARCH_CHAR_IN_INTERVAL_ARRAY_FN(function_name, char_type, array_type, interval_type) \ + static bool function_name (char_type c, /**< code unit */ \ + const array_type *array_sp, /**< array of interval starting points */ \ + const interval_type *lengths, /**< array of interval lengths */ \ + int size_of_array) /**< length of the array */ \ + { \ + int bottom = 0; \ + int top = size_of_array - 1; \ + \ + while (bottom <= top) \ + { \ + int middle = (bottom + top) / 2; \ + char_type current_sp = array_sp[middle]; \ + \ + if (current_sp <= c && c <= current_sp + lengths[middle]) \ + { \ + return true; \ + } \ + \ + if (c > current_sp) \ + { \ + bottom = middle + 1; \ + } \ + else \ + { \ + top = middle - 1; \ + } \ + } \ + \ + return false; \ + } /* function_name */ + +LIT_SEARCH_CHAR_IN_INTERVAL_ARRAY_FN (lit_search_char_in_interval_array, ecma_char_t, uint16_t, uint8_t) + +LIT_SEARCH_CHAR_IN_INTERVAL_ARRAY_FN (lit_search_codepoint_in_interval_array, lit_code_point_t, uint32_t, uint16_t) + +/** + * Check if specified character is one of the Whitespace characters including those that fall into + * "Space, Separator" ("Zs") Unicode character category or one of the Line Terminator characters. + * + * @return true - if the character is one of characters, listed in ECMA-262 v5, Table 2, + * false - otherwise + */ +bool +lit_char_is_white_space (lit_code_point_t c) /**< code point */ +{ + if (c <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + return (c == LIT_CHAR_SP || (c >= LIT_CHAR_TAB && c <= LIT_CHAR_CR)); + } + + if (c == LIT_CHAR_BOM || c == LIT_CHAR_LS || c == LIT_CHAR_PS) + { + return true; + } + + return (c <= LIT_UTF16_CODE_UNIT_MAX + && ((c >= lit_unicode_white_space_interval_starts[0] + && c <= lit_unicode_white_space_interval_starts[0] + lit_unicode_white_space_interval_lengths[0]) + || lit_search_char_in_array ((ecma_char_t) c, + lit_unicode_white_space_chars, + NUM_OF_ELEMENTS (lit_unicode_white_space_chars)))); +} /* lit_char_is_white_space */ + +/** + * Check if specified character is one of LineTerminator characters + * + * @return true - if the character is one of characters, listed in ECMA-262 v5, Table 3, + * false - otherwise + */ +bool +lit_char_is_line_terminator (ecma_char_t c) /**< code unit */ +{ + return (c == LIT_CHAR_LF || c == LIT_CHAR_CR || c == LIT_CHAR_LS || c == LIT_CHAR_PS); +} /* lit_char_is_line_terminator */ + +/** + * Check if specified character is a Unicode ID_Start + * + * See also: + * ECMA-262 v1, 11.6: UnicodeIDStart + * + * @return true - if the codepoint has Unicode property "ID_Start" + * false - otherwise + */ +static bool +lit_char_is_unicode_id_start (lit_code_point_t code_point) /**< code unit */ +{ + if (JERRY_UNLIKELY (code_point >= LIT_UTF8_4_BYTE_CODE_POINT_MIN)) + { + return (lit_search_codepoint_in_interval_array (code_point, + lit_unicode_id_start_interval_starts_sup, + lit_unicode_id_start_interval_lengths_sup, + NUM_OF_ELEMENTS (lit_unicode_id_start_interval_starts_sup)) + || lit_search_codepoint_in_array (code_point, + lit_unicode_id_start_chars_sup, + NUM_OF_ELEMENTS (lit_unicode_id_start_chars_sup))); + } + ecma_char_t c = (ecma_char_t) code_point; + + return (lit_search_char_in_interval_array (c, + lit_unicode_id_start_interval_starts, + lit_unicode_id_start_interval_lengths, + NUM_OF_ELEMENTS (lit_unicode_id_start_interval_starts)) + || lit_search_char_in_array (c, lit_unicode_id_start_chars, NUM_OF_ELEMENTS (lit_unicode_id_start_chars))); +} /* lit_char_is_unicode_id_start */ + +/** + * Check if specified character is a Unicode ID_Continue + * + * See also: + * ECMA-262 v1, 11.6: UnicodeIDContinue + * + * @return true - if the codepoint has Unicode property "ID_Continue" + * false - otherwise + */ +static bool +lit_char_is_unicode_id_continue (lit_code_point_t code_point) /**< code unit */ +{ + /* Each ID_Start codepoint is ID_Continue as well. */ + if (lit_char_is_unicode_id_start (code_point)) + { + return true; + } + + if (JERRY_UNLIKELY (code_point >= LIT_UTF8_4_BYTE_CODE_POINT_MIN)) + { + return (lit_search_codepoint_in_interval_array (code_point, + lit_unicode_id_continue_interval_starts_sup, + lit_unicode_id_continue_interval_lengths_sup, + NUM_OF_ELEMENTS (lit_unicode_id_continue_interval_starts_sup)) + || lit_search_codepoint_in_array (code_point, + lit_unicode_id_continue_chars_sup, + NUM_OF_ELEMENTS (lit_unicode_id_continue_chars_sup))); + } + ecma_char_t c = (ecma_char_t) code_point; + + return ( + lit_search_char_in_interval_array (c, + lit_unicode_id_continue_interval_starts, + lit_unicode_id_continue_interval_lengths, + NUM_OF_ELEMENTS (lit_unicode_id_continue_interval_starts)) + || lit_search_char_in_array (c, lit_unicode_id_continue_chars, NUM_OF_ELEMENTS (lit_unicode_id_continue_chars))); +} /* lit_char_is_unicode_id_continue */ + +/** + * Checks whether the character is a valid identifier start. + * + * @return true if it is. + */ +bool +lit_code_point_is_identifier_start (lit_code_point_t code_point) /**< code point */ +{ + /* Fast path for ASCII-defined letters. */ + if (code_point <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + return ((LEXER_TO_ASCII_LOWERCASE (code_point) >= LIT_CHAR_LOWERCASE_A + && LEXER_TO_ASCII_LOWERCASE (code_point) <= LIT_CHAR_LOWERCASE_Z) + || code_point == LIT_CHAR_DOLLAR_SIGN || code_point == LIT_CHAR_UNDERSCORE); + } + + return lit_char_is_unicode_id_start (code_point); +} /* lit_code_point_is_identifier_start */ + +/** + * Checks whether the character is a valid identifier part. + * + * @return true if it is. + */ +bool +lit_code_point_is_identifier_part (lit_code_point_t code_point) /**< code point */ +{ + /* Fast path for ASCII-defined letters. */ + if (code_point <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + return ((LEXER_TO_ASCII_LOWERCASE (code_point) >= LIT_CHAR_LOWERCASE_A + && LEXER_TO_ASCII_LOWERCASE (code_point) <= LIT_CHAR_LOWERCASE_Z) + || (code_point >= LIT_CHAR_0 && code_point <= LIT_CHAR_9) || code_point == LIT_CHAR_DOLLAR_SIGN + || code_point == LIT_CHAR_UNDERSCORE); + } + + return lit_char_is_unicode_id_continue (code_point); +} /* lit_code_point_is_identifier_part */ + +/** + * Check if specified character is one of OctalDigit characters (ECMA-262 v5, B.1.2) + * + * @return true / false + */ +bool +lit_char_is_octal_digit (ecma_char_t c) /**< code unit */ +{ + return (c >= LIT_CHAR_ASCII_OCTAL_DIGITS_BEGIN && c <= LIT_CHAR_ASCII_OCTAL_DIGITS_END); +} /* lit_char_is_octal_digit */ + +/** + * Check if specified character is one of DecimalDigit characters (ECMA-262 v5, 7.8.3) + * + * @return true / false + */ +bool +lit_char_is_decimal_digit (ecma_char_t c) /**< code unit */ +{ + return (c >= LIT_CHAR_ASCII_DIGITS_BEGIN && c <= LIT_CHAR_ASCII_DIGITS_END); +} /* lit_char_is_decimal_digit */ + +/** + * Check if specified character is one of HexDigit characters (ECMA-262 v5, 7.8.3) + * + * @return true / false + */ +bool +lit_char_is_hex_digit (ecma_char_t c) /**< code unit */ +{ + return ((c >= LIT_CHAR_ASCII_DIGITS_BEGIN && c <= LIT_CHAR_ASCII_DIGITS_END) + || (LEXER_TO_ASCII_LOWERCASE (c) >= LIT_CHAR_ASCII_LOWERCASE_LETTERS_HEX_BEGIN + && LEXER_TO_ASCII_LOWERCASE (c) <= LIT_CHAR_ASCII_LOWERCASE_LETTERS_HEX_END)); +} /* lit_char_is_hex_digit */ + +/** + * Check if specified character is one of BinaryDigits characters (ECMA-262 v6, 11.8.3) + * + * @return true / false + */ +bool +lit_char_is_binary_digit (ecma_char_t c) /** code unit */ +{ + return (c == LIT_CHAR_0 || c == LIT_CHAR_1); +} /* lit_char_is_binary_digit */ + +/** + * @return radix value + */ +uint8_t +lit_char_to_radix (lit_utf8_byte_t c) /** code unit */ +{ + switch (LEXER_TO_ASCII_LOWERCASE (c)) + { + case LIT_CHAR_LOWERCASE_X: + { + return 16; + } + case LIT_CHAR_LOWERCASE_O: + { + return 8; + } + case LIT_CHAR_LOWERCASE_B: + { + return 2; + } + default: + { + return 10; + } + } +} /* lit_char_to_radix */ + +/** + * UnicodeEscape abstract method + * + * See also: ECMA-262 v10, 24.5.2.3 + */ +void +lit_char_unicode_escape (ecma_stringbuilder_t *builder_p, /**< stringbuilder to append */ + ecma_char_t c) /**< code unit to convert */ +{ + ecma_stringbuilder_append_raw (builder_p, (lit_utf8_byte_t *) "\\u", 2); + + for (int8_t i = 3; i >= 0; i--) + { + int32_t result_char = (c >> (i * 4)) & 0xF; + ecma_stringbuilder_append_byte ( + builder_p, + (lit_utf8_byte_t) (result_char + (result_char <= 9 ? LIT_CHAR_0 : (LIT_CHAR_LOWERCASE_A - 10)))); + } +} /* lit_char_unicode_escape */ + +/** + * Convert a HexDigit character to its numeric value, as defined in ECMA-262 v5, 7.8.3 + * + * @return digit value, corresponding to the hex char + */ +uint32_t +lit_char_hex_to_int (ecma_char_t c) /**< code unit, corresponding to + * one of HexDigit characters */ +{ + JERRY_ASSERT (lit_char_is_hex_digit (c)); + + if (c >= LIT_CHAR_ASCII_DIGITS_BEGIN && c <= LIT_CHAR_ASCII_DIGITS_END) + { + return (uint32_t) (c - LIT_CHAR_ASCII_DIGITS_BEGIN); + } + + const uint32_t hex_offset = 10 - (LIT_CHAR_LOWERCASE_A % 32); + return (c % 32) + hex_offset; +} /* lit_char_hex_to_int */ + +/** + * Converts a character to UTF8 bytes. + * + * @return length of the UTF8 representation. + */ +size_t +lit_code_point_to_cesu8_bytes (uint8_t *dst_p, /**< destination buffer */ + lit_code_point_t code_point) /**< code point */ +{ + if (code_point < LIT_UTF8_2_BYTE_CODE_POINT_MIN) + { + /* 00000000 0xxxxxxx -> 0xxxxxxx */ + dst_p[0] = (uint8_t) code_point; + return 1; + } + + if (code_point < LIT_UTF8_3_BYTE_CODE_POINT_MIN) + { + /* 00000yyy yyxxxxxx -> 110yyyyy 10xxxxxx */ + dst_p[0] = (uint8_t) (LIT_UTF8_2_BYTE_MARKER | ((code_point >> 6) & LIT_UTF8_LAST_5_BITS_MASK)); + dst_p[1] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | (code_point & LIT_UTF8_LAST_6_BITS_MASK)); + return 2; + } + + if (code_point < LIT_UTF8_4_BYTE_CODE_POINT_MIN) + { + /* zzzzyyyy yyxxxxxx -> 1110zzzz 10yyyyyy 10xxxxxx */ + dst_p[0] = (uint8_t) (LIT_UTF8_3_BYTE_MARKER | ((code_point >> 12) & LIT_UTF8_LAST_4_BITS_MASK)); + dst_p[1] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | ((code_point >> 6) & LIT_UTF8_LAST_6_BITS_MASK)); + dst_p[2] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | (code_point & LIT_UTF8_LAST_6_BITS_MASK)); + return 3; + } + + JERRY_ASSERT (code_point <= LIT_UNICODE_CODE_POINT_MAX); + + code_point -= LIT_UTF8_4_BYTE_CODE_POINT_MIN; + + dst_p[0] = (uint8_t) (LIT_UTF8_3_BYTE_MARKER | 0xd); + dst_p[1] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | 0x20 | ((code_point >> 16) & LIT_UTF8_LAST_4_BITS_MASK)); + dst_p[2] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | ((code_point >> 10) & LIT_UTF8_LAST_6_BITS_MASK)); + + dst_p[3] = (uint8_t) (LIT_UTF8_3_BYTE_MARKER | 0xd); + dst_p[4] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | 0x30 | ((code_point >> 6) & LIT_UTF8_LAST_4_BITS_MASK)); + dst_p[5] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | (code_point & LIT_UTF8_LAST_6_BITS_MASK)); + + return 3 * 2; +} /* lit_code_point_to_cesu8_bytes */ + +/** + * Returns the length of the UTF8 representation of a character. + * + * @return length of the UTF8 representation. + */ +size_t +lit_code_point_get_cesu8_length (lit_code_point_t code_point) /**< code point */ +{ + if (code_point < LIT_UTF8_2_BYTE_CODE_POINT_MIN) + { + /* 00000000 0xxxxxxx */ + return 1; + } + + if (code_point < LIT_UTF8_3_BYTE_CODE_POINT_MIN) + { + /* 00000yyy yyxxxxxx */ + return 2; + } + + if (code_point < LIT_UTF8_4_BYTE_CODE_POINT_MIN) + { + /* zzzzyyyy yyxxxxxx */ + return 3; + } + + /* high + low surrogate */ + return 2 * 3; +} /* lit_code_point_get_cesu8_length */ + +/** + * Convert a four byte long utf8 character to two three byte long cesu8 characters + */ +void +lit_four_byte_utf8_char_to_cesu8 (uint8_t *dst_p, /**< destination buffer */ + const uint8_t *source_p) /**< source buffer */ +{ + lit_code_point_t code_point = ((((uint32_t) source_p[0]) & LIT_UTF8_LAST_3_BITS_MASK) << 18); + code_point |= ((((uint32_t) source_p[1]) & LIT_UTF8_LAST_6_BITS_MASK) << 12); + code_point |= ((((uint32_t) source_p[2]) & LIT_UTF8_LAST_6_BITS_MASK) << 6); + code_point |= (((uint32_t) source_p[3]) & LIT_UTF8_LAST_6_BITS_MASK); + + lit_code_point_to_cesu8_bytes (dst_p, code_point); +} /* lit_four_byte_utf8_char_to_cesu8 */ + +/** + * Lookup hex digits in a buffer + * + * @return UINT32_MAX - if next 'lookup' number of characters do not form a valid hex number + * value of hex number, otherwise + */ +uint32_t +lit_char_hex_lookup (const lit_utf8_byte_t *buf_p, /**< buffer */ + const lit_utf8_byte_t *const buf_end_p, /**< buffer end */ + uint32_t lookup) /**< size of lookup */ +{ + JERRY_ASSERT (lookup <= 4); + + if (JERRY_UNLIKELY (buf_p + lookup > buf_end_p)) + { + return UINT32_MAX; + } + + uint32_t value = 0; + + while (lookup--) + { + lit_utf8_byte_t ch = *buf_p++; + if (!lit_char_is_hex_digit (ch)) + { + return UINT32_MAX; + } + + value <<= 4; + value += lit_char_hex_to_int (ch); + } + + JERRY_ASSERT (value <= LIT_UTF16_CODE_UNIT_MAX); + return value; +} /* lit_char_hex_lookup */ + +/** + * Parse a decimal number with the value clamped to UINT32_MAX. + * + * @returns uint32_t number + */ +uint32_t +lit_parse_decimal (const lit_utf8_byte_t **buffer_p, /**< [in/out] character buffer */ + const lit_utf8_byte_t *buffer_end_p) /**< buffer end */ +{ + const lit_utf8_byte_t *current_p = *buffer_p; + JERRY_ASSERT (lit_char_is_decimal_digit (*current_p)); + + uint32_t value = (uint32_t) (*current_p++ - LIT_CHAR_0); + + while (current_p < buffer_end_p && lit_char_is_decimal_digit (*current_p)) + { + const uint32_t digit = (uint32_t) (*current_p++ - LIT_CHAR_0); + uint32_t new_value = value * 10 + digit; + + if (JERRY_UNLIKELY (value > UINT32_MAX / 10) || JERRY_UNLIKELY (new_value < value)) + { + value = UINT32_MAX; + continue; + } + + value = new_value; + } + + *buffer_p = current_p; + return value; +} /* lit_parse_decimal */ + +/** + * Check if specified character is a word character (part of IsWordChar abstract operation) + * + * See also: ECMA-262 v5, 15.10.2.6 (IsWordChar) + * + * @return true - if the character is a word character + * false - otherwise + */ +bool +lit_char_is_word_char (lit_code_point_t c) /**< code point */ +{ + return ((c >= LIT_CHAR_ASCII_LOWERCASE_LETTERS_BEGIN && c <= LIT_CHAR_ASCII_LOWERCASE_LETTERS_END) + || (c >= LIT_CHAR_ASCII_UPPERCASE_LETTERS_BEGIN && c <= LIT_CHAR_ASCII_UPPERCASE_LETTERS_END) + || (c >= LIT_CHAR_ASCII_DIGITS_BEGIN && c <= LIT_CHAR_ASCII_DIGITS_END) || c == LIT_CHAR_UNDERSCORE); +} /* lit_char_is_word_char */ + +#if JERRY_UNICODE_CASE_CONVERSION + +/** + * Check if the specified character is in one of those tables which contain bidirectional conversions. + * + * @return codepoint of the converted character if it is found the the tables + * LIT_INVALID_CP - otherwise. + */ +static lit_code_point_t +lit_search_in_bidirectional_conversion_tables (lit_code_point_t cp, /**< code point */ + bool is_lowercase) /**< is lowercase conversion */ +{ + /* 1, Check if the specified character is part of the lit_unicode_character_case_ranges_{sup} table. */ + int number_of_case_ranges; + bool is_supplementary = cp > LIT_UTF16_CODE_UNIT_MAX; + + if (is_supplementary) + { + number_of_case_ranges = NUM_OF_ELEMENTS (lit_unicode_character_case_ranges_sup); + } + else + { + number_of_case_ranges = NUM_OF_ELEMENTS (lit_unicode_character_case_ranges); + } + + int conv_counter = 0; + + for (int i = 0; i < number_of_case_ranges; i++) + { + if (i % 2 == 0 && i > 0) + { + conv_counter++; + } + + size_t range_length; + lit_code_point_t start_point; + + if (is_supplementary) + { + range_length = lit_unicode_character_case_range_lengths_sup[conv_counter]; + start_point = lit_unicode_character_case_ranges_sup[i]; + } + else + { + range_length = lit_unicode_character_case_range_lengths[conv_counter]; + start_point = lit_unicode_character_case_ranges[i]; + } + + if (start_point > cp || cp >= start_point + range_length) + { + continue; + } + + uint32_t char_dist = (uint32_t) cp - start_point; + int offset; + if (i % 2 == 0) + { + if (!is_lowercase) + { + return cp; + } + + offset = i + 1; + } + else + { + if (is_lowercase) + { + return cp; + } + + offset = i - 1; + } + + if (is_supplementary) + { + start_point = lit_unicode_character_case_ranges_sup[offset]; + } + else + { + start_point = lit_unicode_character_case_ranges[offset]; + } + + return (lit_code_point_t) (start_point + char_dist); + } + + /* Note: After this point based on the latest unicode standard(13.0.0.6) no conversion characters are + defined for supplementary planes */ + if (is_supplementary) + { + return cp; + } + + /* 2, Check if the specified character is part of the character_pair_ranges table. */ + int bottom = 0; + int top = NUM_OF_ELEMENTS (lit_unicode_character_pair_ranges) - 1; + + while (bottom <= top) + { + int middle = (bottom + top) / 2; + lit_code_point_t current_sp = lit_unicode_character_pair_ranges[middle]; + + if (current_sp <= cp && cp < current_sp + lit_unicode_character_pair_range_lengths[middle]) + { + uint32_t char_dist = (uint32_t) (cp - current_sp); + + if ((cp - current_sp) % 2 == 0) + { + return is_lowercase ? (lit_code_point_t) (current_sp + char_dist + 1) : cp; + } + + return is_lowercase ? cp : (lit_code_point_t) (current_sp + char_dist - 1); + } + + if (cp > current_sp) + { + bottom = middle + 1; + } + else + { + top = middle - 1; + } + } + + /* 3, Check if the specified character is part of the character_pairs table. */ + int number_of_character_pairs = NUM_OF_ELEMENTS (lit_unicode_character_pairs); + + for (int i = 0; i < number_of_character_pairs; i++) + { + if (cp != lit_unicode_character_pairs[i]) + { + continue; + } + + if (i % 2 == 0) + { + return is_lowercase ? lit_unicode_character_pairs[i + 1] : cp; + } + + return is_lowercase ? cp : lit_unicode_character_pairs[i - 1]; + } + + return LIT_INVALID_CP; +} /* lit_search_in_bidirectional_conversion_tables */ + +/** + * Check if the specified character is in the given conversion table. + * + * @return LIT_MULTIPLE_CU if the converted character consist more than a single code unit + * converted code point - otherwise + */ +static lit_code_point_t +lit_search_in_conversion_table (ecma_char_t character, /**< code unit */ + ecma_stringbuilder_t *builder_p, /**< string builder */ + const ecma_char_t *array, /**< array */ + const uint8_t *counters) /**< case_values counter */ +{ + int end_point = 0; + + for (int i = 0; i < 3; i++) + { + int start_point = end_point; + int size_of_case_value = i + 1; + end_point += counters[i] * (size_of_case_value + 1); + + int bottom = start_point; + int top = end_point - size_of_case_value; + + while (bottom <= top) + { + int middle = (bottom + top) / 2; + + middle -= ((middle - bottom) % (size_of_case_value + 1)); + + ecma_char_t current = array[middle]; + + if (current == character) + { + if (builder_p != NULL) + { + ecma_stringbuilder_append_char (builder_p, array[middle + 1]); + + if (size_of_case_value > 1) + { + ecma_stringbuilder_append_char (builder_p, array[middle + 2]); + } + if (size_of_case_value > 2) + { + ecma_stringbuilder_append_char (builder_p, array[middle + 3]); + } + } + + return size_of_case_value == 1 ? array[middle + 1] : LIT_MULTIPLE_CU; + } + + if (character < current) + { + top = middle - (size_of_case_value + 1); + } + else + { + bottom = middle + (size_of_case_value + 1); + } + } + } + + if (builder_p != NULL) + { + ecma_stringbuilder_append_char (builder_p, character); + } + + return (lit_code_point_t) character; +} /* lit_search_in_conversion_table */ +#endif /* JERRY_UNICODE_CASE_CONVERSION */ + +/** + * Append the converted lowercase codeunit sequence of an a given codepoint into the stringbuilder if it is present. + * + * @return LIT_MULTIPLE_CU if the converted codepoint consist more than a single code unit + * converted code point - otherwise + */ +lit_code_point_t +lit_char_to_lower_case (lit_code_point_t cp, /**< code point */ + ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + if (cp <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + if (cp >= LIT_CHAR_UPPERCASE_A && cp <= LIT_CHAR_UPPERCASE_Z) + { + cp = (lit_utf8_byte_t) (cp + (LIT_CHAR_LOWERCASE_A - LIT_CHAR_UPPERCASE_A)); + } + + if (builder_p != NULL) + { + ecma_stringbuilder_append_byte (builder_p, (lit_utf8_byte_t) cp); + } + + return cp; + } + +#if JERRY_UNICODE_CASE_CONVERSION + lit_code_point_t lowercase_cp = lit_search_in_bidirectional_conversion_tables (cp, true); + + if (lowercase_cp != LIT_INVALID_CP) + { + if (builder_p != NULL) + { + ecma_stringbuilder_append_codepoint (builder_p, lowercase_cp); + } + + return lowercase_cp; + } + + JERRY_ASSERT (cp < LIT_UTF8_4_BYTE_CODE_POINT_MIN); + + int num_of_lowercase_ranges = NUM_OF_ELEMENTS (lit_unicode_lower_case_ranges); + + for (int i = 0, j = 0; i < num_of_lowercase_ranges; i += 2, j++) + { + JERRY_ASSERT (lit_unicode_lower_case_range_lengths[j] > 0); + uint32_t range_length = (uint32_t) (lit_unicode_lower_case_range_lengths[j] - 1); + lit_code_point_t start_point = lit_unicode_lower_case_ranges[i]; + + if (start_point <= cp && cp <= start_point + range_length) + { + lowercase_cp = lit_unicode_lower_case_ranges[i + 1] + (cp - start_point); + if (builder_p != NULL) + { + ecma_stringbuilder_append_codepoint (builder_p, lowercase_cp); + } + + return lowercase_cp; + } + } + + return lit_search_in_conversion_table ((ecma_char_t) cp, + builder_p, + lit_unicode_lower_case_conversions, + lit_unicode_lower_case_conversion_counters); +#else /* !JERRY_UNICODE_CASE_CONVERSION */ + if (builder_p != NULL) + { + ecma_stringbuilder_append_codepoint (builder_p, cp); + } + + return cp; +#endif /* JERRY_UNICODE_CASE_CONVERSION */ +} /* lit_char_to_lower_case */ + +/** + * Append the converted uppercase codeunit sequence of an a given codepoint into the stringbuilder if it is present. + * + * @return LIT_MULTIPLE_CU if the converted codepoint consist more than a single code unit + * converted code point - otherwise + */ +lit_code_point_t +lit_char_to_upper_case (lit_code_point_t cp, /**< code point */ + ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + if (cp <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + if (cp >= LIT_CHAR_LOWERCASE_A && cp <= LIT_CHAR_LOWERCASE_Z) + { + cp = (lit_utf8_byte_t) (cp - (LIT_CHAR_LOWERCASE_A - LIT_CHAR_UPPERCASE_A)); + } + + if (builder_p != NULL) + { + ecma_stringbuilder_append_byte (builder_p, (lit_utf8_byte_t) cp); + } + + return cp; + } + +#if JERRY_UNICODE_CASE_CONVERSION + lit_code_point_t uppercase_cp = lit_search_in_bidirectional_conversion_tables (cp, false); + + if (uppercase_cp != LIT_INVALID_CP) + { + if (builder_p != NULL) + { + ecma_stringbuilder_append_codepoint (builder_p, uppercase_cp); + } + + return uppercase_cp; + } + + int num_of_upper_case_special_ranges = NUM_OF_ELEMENTS (lit_unicode_upper_case_special_ranges); + + for (int i = 0, j = 0; i < num_of_upper_case_special_ranges; i += 3, j++) + { + uint32_t range_length = lit_unicode_upper_case_special_range_lengths[j]; + ecma_char_t start_point = lit_unicode_upper_case_special_ranges[i]; + + if (start_point <= cp && cp <= start_point + range_length) + { + if (builder_p != NULL) + { + uppercase_cp = lit_unicode_upper_case_special_ranges[i + 1] + (cp - start_point); + ecma_stringbuilder_append_codepoint (builder_p, uppercase_cp); + ecma_stringbuilder_append_codepoint (builder_p, lit_unicode_upper_case_special_ranges[i + 2]); + } + + return LIT_MULTIPLE_CU; + } + } + + return lit_search_in_conversion_table ((ecma_char_t) cp, + builder_p, + lit_unicode_upper_case_conversions, + lit_unicode_upper_case_conversion_counters); +#else /* !JERRY_UNICODE_CASE_CONVERSION */ + if (builder_p != NULL) + { + ecma_stringbuilder_append_codepoint (builder_p, cp); + } + + return cp; +#endif /* JERRY_UNICODE_CASE_CONVERSION */ +} /* lit_char_to_upper_case */ + +/* + * Look up whether the character should be folded to the lowercase variant. + * + * @return true, if character should be lowercased + * false, otherwise + */ +bool +lit_char_fold_to_lower (lit_code_point_t cp) /**< code point */ +{ +#if JERRY_UNICODE_CASE_CONVERSION + return (cp <= LIT_UTF8_1_BYTE_CODE_POINT_MAX || cp > LIT_UTF16_CODE_UNIT_MAX + || (!lit_search_char_in_interval_array ((ecma_char_t) cp, + lit_unicode_folding_skip_to_lower_interval_starts, + lit_unicode_folding_skip_to_lower_interval_lengths, + NUM_OF_ELEMENTS (lit_unicode_folding_skip_to_lower_interval_starts)) + && !lit_search_char_in_array ((ecma_char_t) cp, + lit_unicode_folding_skip_to_lower_chars, + NUM_OF_ELEMENTS (lit_unicode_folding_skip_to_lower_chars)))); +#else /* !JERRY_UNICODE_CASE_CONVERSION */ + return true; +#endif /* JERRY_UNICODE_CASE_CONVERSION */ +} /* lit_char_fold_to_lower */ + +/* + * Look up whether the character should be folded to the uppercase variant. + * + * @return true, if character should be uppercased + * false, otherwise + */ +bool +lit_char_fold_to_upper (lit_code_point_t cp) /**< code point */ +{ +#if JERRY_UNICODE_CASE_CONVERSION + return (cp > LIT_UTF8_1_BYTE_CODE_POINT_MAX && cp <= LIT_UTF16_CODE_UNIT_MAX + && (lit_search_char_in_interval_array ((ecma_char_t) cp, + lit_unicode_folding_to_upper_interval_starts, + lit_unicode_folding_to_upper_interval_lengths, + NUM_OF_ELEMENTS (lit_unicode_folding_to_upper_interval_starts)) + || lit_search_char_in_array ((ecma_char_t) cp, + lit_unicode_folding_to_upper_chars, + NUM_OF_ELEMENTS (lit_unicode_folding_to_upper_chars)))); +#else /* !JERRY_UNICODE_CASE_CONVERSION */ + return false; +#endif /* JERRY_UNICODE_CASE_CONVERSION */ +} /* lit_char_fold_to_upper */ + +/** + * Helper method to find a specific character in a string + * + * Used by: + * ecma_builtin_string_prototype_object_replace_helper + * + * @return true - if the given character is in the string + * false - otherwise + */ +bool +lit_find_char_in_string (ecma_string_t *str_p, /**< source string */ + lit_utf8_byte_t c) /**< character to find*/ +{ + ECMA_STRING_TO_UTF8_STRING (str_p, start_p, start_size); + + const lit_utf8_byte_t *str_curr_p = start_p; + const lit_utf8_byte_t *str_end_p = start_p + start_size; + bool have_char = false; + + while (str_curr_p < str_end_p) + { + if (*str_curr_p++ == c) + { + have_char = true; + break; + } + } + + ECMA_FINALIZE_UTF8_STRING (start_p, start_size); + + return have_char; +} /* lit_find_char_in_string */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.h new file mode 100644 index 00000000..9b696177 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.h @@ -0,0 +1,260 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIT_CHAR_HELPERS_H +#define LIT_CHAR_HELPERS_H + +#include "ecma-globals.h" + +#include "lit-globals.h" + +/** + * Invalid character code point + */ +#define LIT_INVALID_CP 0xFFFFFFFF + +/** + * Result of lit_char_to_lower_case/lit_char_to_upper_case consist more than of a single code unit + */ +#define LIT_MULTIPLE_CU 0xFFFFFFFE + +/* + * Format control characters (ECMA-262 v5, Table 1) + */ +#define LIT_CHAR_ZWNJ ((ecma_char_t) 0x200C) /* zero width non-joiner */ +#define LIT_CHAR_ZWJ ((ecma_char_t) 0x200D) /* zero width joiner */ +#define LIT_CHAR_BOM ((ecma_char_t) 0xFEFF) /* byte order mark */ + +/* + * Whitespace characters (ECMA-262 v5, Table 2) + */ +#define LIT_CHAR_TAB ((ecma_char_t) 0x0009) /* tab */ +#define LIT_CHAR_VTAB ((ecma_char_t) 0x000B) /* vertical tab */ +#define LIT_CHAR_FF ((ecma_char_t) 0x000C) /* form feed */ +#define LIT_CHAR_SP ((ecma_char_t) 0x0020) /* space */ +#define LIT_CHAR_NBSP ((ecma_char_t) 0x00A0) /* no-break space */ +#define LIT_CHAR_MVS ((ecma_char_t) 0x180E) /* mongolian vowel separator */ +/* LIT_CHAR_BOM is defined above */ + +bool lit_char_is_white_space (lit_code_point_t c); + +/* + * Line terminator characters (ECMA-262 v5, Table 3) + */ +#define LIT_CHAR_LF ((ecma_char_t) 0x000A) /* line feed */ +#define LIT_CHAR_CR ((ecma_char_t) 0x000D) /* carriage return */ +#define LIT_CHAR_LS ((ecma_char_t) 0x2028) /* line separator */ +#define LIT_CHAR_PS ((ecma_char_t) 0x2029) /* paragraph separator */ + +bool lit_char_is_line_terminator (ecma_char_t c); + +/* + * String Single Character Escape Sequences (ECMA-262 v5, Table 4) + */ +#define LIT_CHAR_BS ((ecma_char_t) 0x0008) /* backspace */ +/* LIT_CHAR_TAB is defined above */ +/* LIT_CHAR_LF is defined above */ +/* LIT_CHAR_VTAB is defined above */ +/* LIT_CHAR_FF is defined above */ +/* LIT_CHAR_CR is defined above */ +#define LIT_CHAR_DOUBLE_QUOTE ((ecma_char_t) '"') /* double quote */ +#define LIT_CHAR_SINGLE_QUOTE ((ecma_char_t) '\'') /* single quote */ +#define LIT_CHAR_BACKSLASH ((ecma_char_t) '\\') /* reverse solidus (backslash) */ + +/* + * Comment characters (ECMA-262 v5, 7.4) + */ +#define LIT_CHAR_SLASH ((ecma_char_t) '/') /* solidus */ +#define LIT_CHAR_ASTERISK ((ecma_char_t) '*') /* asterisk */ + +/* + * Identifier name characters (ECMA-262 v5, 7.6) + */ +#define LIT_CHAR_DOLLAR_SIGN ((ecma_char_t) '$') /* dollar sign */ +#define LIT_CHAR_UNDERSCORE ((ecma_char_t) '_') /* low line (underscore) */ +/* LIT_CHAR_BACKSLASH defined above */ + +bool lit_code_point_is_identifier_start (lit_code_point_t code_point); +bool lit_code_point_is_identifier_part (lit_code_point_t code_point); + +/* + * Punctuator characters (ECMA-262 v5, 7.7) + */ +#define LIT_CHAR_LEFT_BRACE ((ecma_char_t) '{') /* left curly bracket */ +#define LIT_CHAR_RIGHT_BRACE ((ecma_char_t) '}') /* right curly bracket */ +#define LIT_CHAR_LEFT_PAREN ((ecma_char_t) '(') /* left parenthesis */ +#define LIT_CHAR_RIGHT_PAREN ((ecma_char_t) ')') /* right parenthesis */ +#define LIT_CHAR_LEFT_SQUARE ((ecma_char_t) '[') /* left square bracket */ +#define LIT_CHAR_RIGHT_SQUARE ((ecma_char_t) ']') /* right square bracket */ +#define LIT_CHAR_DOT ((ecma_char_t) '.') /* dot */ +#define LIT_CHAR_SEMICOLON ((ecma_char_t) ';') /* semicolon */ +#define LIT_CHAR_COMMA ((ecma_char_t) ',') /* comma */ +#define LIT_CHAR_LESS_THAN ((ecma_char_t) '<') /* less-than sign */ +#define LIT_CHAR_GREATER_THAN ((ecma_char_t) '>') /* greater-than sign */ +#define LIT_CHAR_EQUALS ((ecma_char_t) '=') /* equals sign */ +#define LIT_CHAR_PLUS ((ecma_char_t) '+') /* plus sign */ +#define LIT_CHAR_MINUS ((ecma_char_t) '-') /* hyphen-minus */ +/* LIT_CHAR_ASTERISK is defined above */ +#define LIT_CHAR_PERCENT ((ecma_char_t) '%') /* percent sign */ +#define LIT_CHAR_AMPERSAND ((ecma_char_t) '&') /* ampersand */ +#define LIT_CHAR_VLINE ((ecma_char_t) '|') /* vertical line */ +#define LIT_CHAR_CIRCUMFLEX ((ecma_char_t) '^') /* circumflex accent */ +#define LIT_CHAR_EXCLAMATION ((ecma_char_t) '!') /* exclamation mark */ +#define LIT_CHAR_TILDE ((ecma_char_t) '~') /* tilde */ +#define LIT_CHAR_QUESTION ((ecma_char_t) '?') /* question mark */ +#define LIT_CHAR_COLON ((ecma_char_t) ':') /* colon */ +#define LIT_CHAR_HASHMARK ((ecma_char_t) '#') /* hashmark */ + +/* + * Special characters for String.prototype.replace. + */ +#define LIT_CHAR_GRAVE_ACCENT ((ecma_char_t) '`') /* grave accent */ + +/** + * Uppercase ASCII letters + */ +#define LIT_CHAR_UPPERCASE_A ((ecma_char_t) 'A') +#define LIT_CHAR_UPPERCASE_B ((ecma_char_t) 'B') +#define LIT_CHAR_UPPERCASE_C ((ecma_char_t) 'C') +#define LIT_CHAR_UPPERCASE_D ((ecma_char_t) 'D') +#define LIT_CHAR_UPPERCASE_E ((ecma_char_t) 'E') +#define LIT_CHAR_UPPERCASE_F ((ecma_char_t) 'F') +#define LIT_CHAR_UPPERCASE_G ((ecma_char_t) 'G') +#define LIT_CHAR_UPPERCASE_H ((ecma_char_t) 'H') +#define LIT_CHAR_UPPERCASE_I ((ecma_char_t) 'I') +#define LIT_CHAR_UPPERCASE_J ((ecma_char_t) 'J') +#define LIT_CHAR_UPPERCASE_K ((ecma_char_t) 'K') +#define LIT_CHAR_UPPERCASE_L ((ecma_char_t) 'L') +#define LIT_CHAR_UPPERCASE_M ((ecma_char_t) 'M') +#define LIT_CHAR_UPPERCASE_N ((ecma_char_t) 'N') +#define LIT_CHAR_UPPERCASE_O ((ecma_char_t) 'O') +#define LIT_CHAR_UPPERCASE_P ((ecma_char_t) 'P') +#define LIT_CHAR_UPPERCASE_Q ((ecma_char_t) 'Q') +#define LIT_CHAR_UPPERCASE_R ((ecma_char_t) 'R') +#define LIT_CHAR_UPPERCASE_S ((ecma_char_t) 'S') +#define LIT_CHAR_UPPERCASE_T ((ecma_char_t) 'T') +#define LIT_CHAR_UPPERCASE_U ((ecma_char_t) 'U') +#define LIT_CHAR_UPPERCASE_V ((ecma_char_t) 'V') +#define LIT_CHAR_UPPERCASE_W ((ecma_char_t) 'W') +#define LIT_CHAR_UPPERCASE_X ((ecma_char_t) 'X') +#define LIT_CHAR_UPPERCASE_Y ((ecma_char_t) 'Y') +#define LIT_CHAR_UPPERCASE_Z ((ecma_char_t) 'Z') + +/** + * Lowercase ASCII letters + */ +#define LIT_CHAR_LOWERCASE_A ((ecma_char_t) 'a') +#define LIT_CHAR_LOWERCASE_B ((ecma_char_t) 'b') +#define LIT_CHAR_LOWERCASE_C ((ecma_char_t) 'c') +#define LIT_CHAR_LOWERCASE_D ((ecma_char_t) 'd') +#define LIT_CHAR_LOWERCASE_E ((ecma_char_t) 'e') +#define LIT_CHAR_LOWERCASE_F ((ecma_char_t) 'f') +#define LIT_CHAR_LOWERCASE_G ((ecma_char_t) 'g') +#define LIT_CHAR_LOWERCASE_H ((ecma_char_t) 'h') +#define LIT_CHAR_LOWERCASE_I ((ecma_char_t) 'i') +#define LIT_CHAR_LOWERCASE_J ((ecma_char_t) 'j') +#define LIT_CHAR_LOWERCASE_K ((ecma_char_t) 'k') +#define LIT_CHAR_LOWERCASE_L ((ecma_char_t) 'l') +#define LIT_CHAR_LOWERCASE_M ((ecma_char_t) 'm') +#define LIT_CHAR_LOWERCASE_N ((ecma_char_t) 'n') +#define LIT_CHAR_LOWERCASE_O ((ecma_char_t) 'o') +#define LIT_CHAR_LOWERCASE_P ((ecma_char_t) 'p') +#define LIT_CHAR_LOWERCASE_Q ((ecma_char_t) 'q') +#define LIT_CHAR_LOWERCASE_R ((ecma_char_t) 'r') +#define LIT_CHAR_LOWERCASE_S ((ecma_char_t) 's') +#define LIT_CHAR_LOWERCASE_T ((ecma_char_t) 't') +#define LIT_CHAR_LOWERCASE_U ((ecma_char_t) 'u') +#define LIT_CHAR_LOWERCASE_V ((ecma_char_t) 'v') +#define LIT_CHAR_LOWERCASE_W ((ecma_char_t) 'w') +#define LIT_CHAR_LOWERCASE_X ((ecma_char_t) 'x') +#define LIT_CHAR_LOWERCASE_Y ((ecma_char_t) 'y') +#define LIT_CHAR_LOWERCASE_Z ((ecma_char_t) 'z') + +/** + * ASCII decimal digits + */ +#define LIT_CHAR_0 ((ecma_char_t) '0') +#define LIT_CHAR_1 ((ecma_char_t) '1') +#define LIT_CHAR_2 ((ecma_char_t) '2') +#define LIT_CHAR_3 ((ecma_char_t) '3') +#define LIT_CHAR_4 ((ecma_char_t) '4') +#define LIT_CHAR_5 ((ecma_char_t) '5') +#define LIT_CHAR_6 ((ecma_char_t) '6') +#define LIT_CHAR_7 ((ecma_char_t) '7') +#define LIT_CHAR_8 ((ecma_char_t) '8') +#define LIT_CHAR_9 ((ecma_char_t) '9') + +/** + * ASCII character ranges + */ +#define LIT_CHAR_ASCII_UPPERCASE_LETTERS_BEGIN LIT_CHAR_UPPERCASE_A /* uppercase letters range */ +#define LIT_CHAR_ASCII_UPPERCASE_LETTERS_END LIT_CHAR_UPPERCASE_Z + +#define LIT_CHAR_ASCII_LOWERCASE_LETTERS_BEGIN LIT_CHAR_LOWERCASE_A /* lowercase letters range */ +#define LIT_CHAR_ASCII_LOWERCASE_LETTERS_END LIT_CHAR_LOWERCASE_Z + +#define LIT_CHAR_ASCII_UPPERCASE_LETTERS_HEX_BEGIN \ + LIT_CHAR_UPPERCASE_A /* uppercase letters for \ + * hexadecimal digits range */ +#define LIT_CHAR_ASCII_UPPERCASE_LETTERS_HEX_END LIT_CHAR_UPPERCASE_F + +#define LIT_CHAR_ASCII_LOWERCASE_LETTERS_HEX_BEGIN \ + LIT_CHAR_LOWERCASE_A /* lowercase letters for \ + * hexadecimal digits range */ +#define LIT_CHAR_ASCII_LOWERCASE_LETTERS_HEX_END LIT_CHAR_LOWERCASE_F + +#define LIT_CHAR_ASCII_OCTAL_DIGITS_BEGIN LIT_CHAR_0 /* octal digits range */ +#define LIT_CHAR_ASCII_OCTAL_DIGITS_END LIT_CHAR_7 + +#define LIT_CHAR_ASCII_DIGITS_BEGIN LIT_CHAR_0 /* decimal digits range */ +#define LIT_CHAR_ASCII_DIGITS_END LIT_CHAR_9 + +#define LEXER_TO_ASCII_LOWERCASE(character) ((character) | LIT_CHAR_SP) + +bool lit_char_is_octal_digit (ecma_char_t c); +bool lit_char_is_decimal_digit (ecma_char_t c); +bool lit_char_is_hex_digit (ecma_char_t c); +bool lit_char_is_binary_digit (ecma_char_t c); +uint8_t lit_char_to_radix (lit_utf8_byte_t c); +void lit_char_unicode_escape (ecma_stringbuilder_t *builder_p, ecma_char_t c); +uint32_t lit_char_hex_to_int (ecma_char_t c); +size_t lit_code_point_to_cesu8_bytes (uint8_t *dst_p, lit_code_point_t code_point); +size_t lit_code_point_get_cesu8_length (lit_code_point_t code_point); +void lit_four_byte_utf8_char_to_cesu8 (uint8_t *dst_p, const uint8_t *source_p); +uint32_t lit_char_hex_lookup (const lit_utf8_byte_t *buf_p, const lit_utf8_byte_t *const buf_end_p, uint32_t lookup); +uint32_t lit_parse_decimal (const lit_utf8_byte_t **buffer_p, const lit_utf8_byte_t *const buffer_end_p); +bool lit_find_char_in_string (ecma_string_t *str_p, lit_utf8_byte_t c); + +/** + * Null character + */ +#define LIT_CHAR_NULL ((ecma_char_t) '\0') + +/* + * Part of IsWordChar abstract operation (ECMA-262 v5, 15.10.2.6, step 3) + */ +bool lit_char_is_word_char (lit_code_point_t c); + +/* + * Utility functions for uppercasing / lowercasing + */ + +lit_code_point_t lit_char_to_lower_case (lit_code_point_t cp, ecma_stringbuilder_t *builder_p); +lit_code_point_t lit_char_to_upper_case (lit_code_point_t cp, ecma_stringbuilder_t *builder_p); + +bool lit_char_fold_to_lower (lit_code_point_t cp); +bool lit_char_fold_to_upper (lit_code_point_t cp); + +#endif /* !LIT_CHAR_HELPERS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-globals.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-globals.h new file mode 100644 index 00000000..a970eee1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-globals.h @@ -0,0 +1,121 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIT_GLOBALS_H +#define LIT_GLOBALS_H + +#include "jrt.h" + +/** + * ECMAScript standard defines terms "code unit" and "character" as 16-bit unsigned value + * used to represent 16-bit unit of text, this is the same as code unit in UTF-16 (See ECMA-262 5.1 Chapter 6). + * + * The term "code point" or "Unicode character" is used to refer a single Unicode scalar value (may be longer + * than 16 bits: 0x0 - 0x10FFFFF). One code point could be represented with one ore two 16-bit code units. + * + * According to the standard all strings and source text are assumed to be a sequence of code units. + * Length of a string equals to number of code units in the string, which is not the same as number of Unicode + * characters in a string. + * + * Internally JerryScript engine uses UTF-8 representation of strings to reduce memory overhead. Unicode character + * occupies from one to four bytes in UTF-8 representation. + * + * Unicode scalar value | Bytes in UTF-8 | Bytes in UTF-16 + * | (internal representation) | + * ---------------------------------------------------------------------- + * 0x0 - 0x7F | 1 byte | 2 bytes + * 0x80 - 0x7FF | 2 bytes | 2 bytes + * 0x800 - 0xFFFF | 3 bytes | 2 bytes + * 0x10000 - 0x10FFFF | 4 bytes | 4 bytes + * + * Scalar values from 0xD800 to 0xDFFF are permanently reserved by Unicode standard to encode high and low + * surrogates in UTF-16 (Code points 0x10000 - 0x10FFFF are encoded via pair of surrogates in UTF-16). + * Despite that the official Unicode standard says that no UTF forms can encode these code points, we allow + * them to be encoded inside strings. The reason for that is compatibility with ECMA standard. + * + * For example, assume a string which consists one Unicode character: 0x1D700 (Mathematical Italic Small Epsilon). + * It has the following representation in UTF-16: 0xD835 0xDF00. + * + * ECMA standard allows extracting a substring from this string: + * > var str = String.fromCharCode (0xD835, 0xDF00); // Create a string containing one character: 0x1D700 + * > str.length; // 2 + * > var str1 = str.substring (0, 1); + * > str1.length; // 1 + * > str1.charCodeAt (0); // 55349 (this equals to 0xD835) + * + * Internally original string would be represented in UTF-8 as the following byte sequence: 0xF0 0x9D 0x9C 0x80. + * After substring extraction high surrogate 0xD835 should be encoded via UTF-8: 0xED 0xA0 0xB5. + * + * Pair of low and high surrogates encoded separately should never occur in internal string representation, + * it should be encoded as any code point and occupy 4 bytes. So, when constructing a string from two surrogates, + * it should be processed gracefully; + * > var str1 = String.fromCharCode (0xD835); // 0xED 0xA0 0xB5 - internal representation + * > var str2 = String.fromCharCode (0xDF00); // 0xED 0xBC 0x80 - internal representation + * > var str = str1 + str2; // 0xF0 0x9D 0x9C 0x80 - internal representation, + * // !!! not 0xED 0xA0 0xB5 0xED 0xBC 0x80 + */ + +/** + * Description of an ecma-character, which represents 16-bit code unit, + * which is equal to UTF-16 character (see Chapter 6 from ECMA-262 5.1) + */ +typedef uint16_t ecma_char_t; + +/** + * Max bytes needed to represent a code unit (utf-16 char) via utf-8 encoding + */ +#define LIT_UTF8_MAX_BYTES_IN_CODE_UNIT (3) + +/** + * Max bytes needed to represent a code point (Unicode character) via utf-8 encoding + */ +#define LIT_UTF8_MAX_BYTES_IN_CODE_POINT (4) + +/** + * Max bytes needed to represent a code unit (utf-16 char) via cesu-8 encoding + */ +#define LIT_CESU8_MAX_BYTES_IN_CODE_UNIT (3) + +/** + * Max bytes needed to represent a code point (Unicode character) via cesu-8 encoding + */ +#define LIT_CESU8_MAX_BYTES_IN_CODE_POINT (6) + +/** + * A byte of utf-8 string + */ +typedef uint8_t lit_utf8_byte_t; + +/** + * Size of a utf-8 string in bytes + */ +typedef uint32_t lit_utf8_size_t; + +/** + * Size of a magic string in bytes + */ +typedef uint8_t lit_magic_size_t; + +/** + * Unicode code point + */ +typedef uint32_t lit_code_point_t; + +/** + * ECMA string hash + */ +typedef uint32_t lit_string_hash_t; + +#endif /* !LIT_GLOBALS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.cpp b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.cpp new file mode 100644 index 00000000..cc2b09de --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.cpp @@ -0,0 +1,432 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jerry-config.h" +#include "lit-magic-strings.h" + +#include "jcontext.h" +#include "lit-strings.h" + +/** + * Maximum number of external magic strings that can be registered. + */ +#define LIT_EXTERNAL_MAGIC_STRING_LIMIT (UINT32_MAX / 2) + +/** + * Get number of external magic strings + * + * @return number of the strings, if there were registered, + * zero - otherwise. + */ +uint32_t +lit_get_magic_string_ex_count (void) +{ + return JERRY_CONTEXT (lit_magic_string_ex_count); +} /* lit_get_magic_string_ex_count */ + +/** + * Get specified magic string as zero-terminated string + * + * @return pointer to zero-terminated magic string + */ +const lit_utf8_byte_t * +lit_get_magic_string_utf8 (uint32_t id) /**< magic string id */ +{ + static const lit_utf8_byte_t *const lit_magic_strings[] JERRY_ATTR_CONST_DATA = { +/** @cond doxygen_suppress */ +#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) +#define LIT_MAGIC_STRING_DEF(id, utf8_string) (const lit_utf8_byte_t *) utf8_string, +#include "lit-magic-strings.inc.h" +#undef LIT_MAGIC_STRING_DEF +#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE + /** @endcond */ + }; + + JERRY_ASSERT (id < LIT_NON_INTERNAL_MAGIC_STRING__COUNT); + + return lit_magic_strings[id]; +} /* lit_get_magic_string_utf8 */ + +/** + * Get size of specified magic string + * + * @return size in bytes + */ +lit_utf8_size_t +lit_get_magic_string_size (uint32_t id) /**< magic string id */ +{ + static const lit_magic_size_t lit_magic_string_sizes[] JERRY_ATTR_CONST_DATA = { +/** @cond doxygen_suppress */ +#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) +#define LIT_MAGIC_STRING_DEF(id, utf8_string) sizeof (utf8_string) - 1, +#include "lit-magic-strings.inc.h" +#undef LIT_MAGIC_STRING_DEF +#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE + /** @endcond */ + }; + + JERRY_ASSERT (id < LIT_NON_INTERNAL_MAGIC_STRING__COUNT); + + return lit_magic_string_sizes[id]; +} /* lit_get_magic_string_size */ + +/** + * Get the block start element with the given size from + * the list of ECMA and implementation-defined magic string constants + * + * @return magic string id + */ +static lit_magic_string_id_t +lit_get_magic_string_size_block_start (lit_utf8_size_t size) /**< magic string size */ +{ + static const lit_magic_string_id_t lit_magic_string_size_block_starts[] JERRY_ATTR_CONST_DATA = { +/** @cond doxygen_suppress */ +#define LIT_MAGIC_STRING_DEF(id, utf8_string) +#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) id, +#include "lit-magic-strings.inc.h" + LIT_NON_INTERNAL_MAGIC_STRING__COUNT +#undef LIT_MAGIC_STRING_DEF +#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE + /** @endcond */ + }; + + JERRY_ASSERT (size <= (sizeof (lit_magic_string_size_block_starts) / sizeof (lit_magic_string_id_t))); + + return lit_magic_string_size_block_starts[size]; +} /* lit_get_magic_string_size_block_start */ + +/** + * Get specified magic string as zero-terminated string from external table + * + * @return pointer to zero-terminated magic string + */ +const lit_utf8_byte_t * +lit_get_magic_string_ex_utf8 (uint32_t id) /**< extern magic string id */ +{ + JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_array) && id < JERRY_CONTEXT (lit_magic_string_ex_count)); + + return JERRY_CONTEXT (lit_magic_string_ex_array)[id]; +} /* lit_get_magic_string_ex_utf8 */ + +/** + * Get size of specified external magic string + * + * @return size in bytes + */ +lit_utf8_size_t +lit_get_magic_string_ex_size (uint32_t id) /**< external magic string id */ +{ + return JERRY_CONTEXT (lit_magic_string_ex_sizes)[id]; +} /* lit_get_magic_string_ex_size */ + +/** + * Register external magic strings + */ +void +lit_magic_strings_ex_set (const lit_utf8_byte_t *const *ex_str_items, /**< character arrays, representing + * external magic strings' contents */ + uint32_t count, /**< number of the strings */ + const lit_utf8_size_t *ex_str_sizes) /**< sizes of the strings */ +{ + JERRY_ASSERT (ex_str_items != NULL); + JERRY_ASSERT (count > 0); + JERRY_ASSERT (ex_str_sizes != NULL); + + JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_array) == NULL); + JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_count) == 0); + JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_sizes) == NULL); + + /* Limit the number of external magic strings */ + if (count > LIT_EXTERNAL_MAGIC_STRING_LIMIT) + { + count = LIT_EXTERNAL_MAGIC_STRING_LIMIT; + } + + /* Set external magic strings information */ + JERRY_CONTEXT (lit_magic_string_ex_array) = ex_str_items; + JERRY_CONTEXT (lit_magic_string_ex_count) = count; + JERRY_CONTEXT (lit_magic_string_ex_sizes) = ex_str_sizes; + +#ifndef JERRY_NDEBUG + for (lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) 0; id < JERRY_CONTEXT (lit_magic_string_ex_count); + id = (lit_magic_string_ex_id_t) (id + 1)) + { + lit_utf8_size_t string_size = JERRY_CONTEXT (lit_magic_string_ex_sizes)[id]; + + /** + * Check whether the strings are sorted by size and lexicographically, + * e.g., "Bb" < "aa" < "aaa" < "xyz0". + */ + if (id > 0) + { + const lit_magic_string_ex_id_t prev_id = id - 1; + const lit_utf8_size_t prev_string_size = lit_get_magic_string_ex_size (prev_id); + JERRY_ASSERT (lit_is_valid_cesu8_string (lit_get_magic_string_ex_utf8 (id), string_size)); + JERRY_ASSERT (prev_string_size <= string_size); + + if (prev_string_size == string_size) + { + const lit_utf8_byte_t *prev_ex_string_p = lit_get_magic_string_ex_utf8 (prev_id); + const lit_utf8_byte_t *curr_ex_string_p = lit_get_magic_string_ex_utf8 (id); + JERRY_ASSERT (memcmp (prev_ex_string_p, curr_ex_string_p, string_size) < 0); + } + } + } +#endif /* !JERRY_NDEBUG */ +} /* lit_magic_strings_ex_set */ + +/** + * Returns the magic string id of the argument string if it is available. + * + * @return id - if magic string id is found, + * LIT_MAGIC_STRING__COUNT - otherwise. + */ +lit_magic_string_id_t +lit_is_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size) /**< string size in bytes */ +{ + if (string_size > lit_get_magic_string_size (LIT_NON_INTERNAL_MAGIC_STRING__COUNT - 1)) + { + return LIT_MAGIC_STRING__COUNT; + } + + /**< The string must be in this id range. */ + lit_utf8_size_t first = lit_get_magic_string_size_block_start (string_size); + lit_utf8_size_t last = lit_get_magic_string_size_block_start (string_size + 1); + + while (first < last) + { + lit_utf8_size_t middle = ((first + last) / 2); /**< mid point of search */ + int compare = memcmp (lit_get_magic_string_utf8 ((lit_magic_string_id_t) middle), string_p, string_size); + + if (compare == 0) + { + return (lit_magic_string_id_t) middle; + } + else if (compare > 0) + { + last = middle; + } + else + { + first = middle + 1; + } + } + + return LIT_MAGIC_STRING__COUNT; +} /* lit_is_utf8_string_magic */ + +/** + * Returns the magic string id of the argument string pair if it is available. + * + * @return id - if magic string id is found, + * LIT_MAGIC_STRING__COUNT - otherwise. + */ +lit_magic_string_id_t +lit_is_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, /**< first utf-8 string */ + lit_utf8_size_t string1_size, /**< first string size in bytes */ + const lit_utf8_byte_t *string2_p, /**< second utf-8 string */ + lit_utf8_size_t string2_size) /**< second string size in bytes */ +{ + lit_utf8_size_t total_string_size = string1_size + string2_size; + + if (total_string_size > lit_get_magic_string_size (LIT_NON_INTERNAL_MAGIC_STRING__COUNT - 1)) + { + return LIT_MAGIC_STRING__COUNT; + } + + /**< The string must be in this id range. */ + lit_utf8_size_t first = lit_get_magic_string_size_block_start (total_string_size); + lit_utf8_size_t last = lit_get_magic_string_size_block_start (total_string_size + 1); + + while (first < last) + { + lit_utf8_size_t middle = ((first + last) / 2); /**< mid point of search */ + const lit_utf8_byte_t *middle_string_p = lit_get_magic_string_utf8 ((lit_magic_string_id_t) middle); + + int compare = memcmp (middle_string_p, string1_p, string1_size); + + if (compare == 0) + { + compare = memcmp (middle_string_p + string1_size, string2_p, string2_size); + } + + if (compare == 0) + { + return (lit_magic_string_id_t) middle; + } + else if (compare > 0) + { + last = middle; + } + else + { + first = middle + 1; + } + } + + return LIT_MAGIC_STRING__COUNT; +} /* lit_is_utf8_string_pair_magic */ + +/** + * Returns the ex magic string id of the argument string if it is available. + * + * @return id - if magic string id is found, + * lit_get_magic_string_ex_count () - otherwise. + */ +lit_magic_string_ex_id_t +lit_is_ex_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size) /**< string size in bytes */ +{ + const uint32_t magic_string_ex_count = lit_get_magic_string_ex_count (); + + if (magic_string_ex_count == 0 || string_size > lit_get_magic_string_ex_size (magic_string_ex_count - 1)) + { + return (lit_magic_string_ex_id_t) magic_string_ex_count; + } + + lit_magic_string_ex_id_t first = 0; + lit_magic_string_ex_id_t last = (lit_magic_string_ex_id_t) magic_string_ex_count; + + while (first < last) + { + const lit_magic_string_ex_id_t middle = (first + last) / 2; + const lit_utf8_byte_t *ext_string_p = lit_get_magic_string_ex_utf8 (middle); + const lit_utf8_size_t ext_string_size = lit_get_magic_string_ex_size (middle); + + if (string_size == ext_string_size) + { + const int string_compare = memcmp (ext_string_p, string_p, string_size); + + if (string_compare == 0) + { + return middle; + } + else if (string_compare < 0) + { + first = middle + 1; + } + else + { + last = middle; + } + } + else if (string_size > ext_string_size) + { + first = middle + 1; + } + else + { + last = middle; + } + } + + return (lit_magic_string_ex_id_t) magic_string_ex_count; +} /* lit_is_ex_utf8_string_magic */ + +/** + * Returns the ex magic string id of the argument string pair if it is available. + * + * @return id - if magic string id is found, + * lit_get_magic_string_ex_count () - otherwise. + */ +lit_magic_string_ex_id_t +lit_is_ex_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, /**< first utf-8 string */ + lit_utf8_size_t string1_size, /**< first string size in bytes */ + const lit_utf8_byte_t *string2_p, /**< second utf-8 string */ + lit_utf8_size_t string2_size) /**< second string size in bytes */ +{ + const uint32_t magic_string_ex_count = lit_get_magic_string_ex_count (); + const lit_utf8_size_t total_string_size = string1_size + string2_size; + + if (magic_string_ex_count == 0 || total_string_size > lit_get_magic_string_ex_size (magic_string_ex_count - 1)) + { + return (lit_magic_string_ex_id_t) magic_string_ex_count; + } + + lit_magic_string_ex_id_t first = 0; + lit_magic_string_ex_id_t last = (lit_magic_string_ex_id_t) magic_string_ex_count; + + while (first < last) + { + const lit_magic_string_ex_id_t middle = (first + last) / 2; + const lit_utf8_byte_t *ext_string_p = lit_get_magic_string_ex_utf8 (middle); + const lit_utf8_size_t ext_string_size = lit_get_magic_string_ex_size (middle); + + if (total_string_size == ext_string_size) + { + int string_compare = memcmp (ext_string_p, string1_p, string1_size); + + if (string_compare == 0) + { + string_compare = memcmp (ext_string_p + string1_size, string2_p, string2_size); + } + + if (string_compare == 0) + { + return middle; + } + else if (string_compare < 0) + { + first = middle + 1; + } + else + { + last = middle; + } + } + else if (total_string_size > ext_string_size) + { + first = middle + 1; + } + else + { + last = middle; + } + } + + return (lit_magic_string_ex_id_t) magic_string_ex_count; +} /* lit_is_ex_utf8_string_pair_magic */ + +/** + * Copy magic string to buffer + * + * Warning: + * the routine requires that buffer size is enough + * + * @return pointer to the byte next to the last copied in the buffer + */ +lit_utf8_byte_t * +lit_copy_magic_string_to_buffer (lit_magic_string_id_t id, /**< magic string id */ + lit_utf8_byte_t *buffer_p, /**< destination buffer */ + lit_utf8_size_t buffer_size) /**< size of buffer */ +{ + const lit_utf8_byte_t *magic_string_bytes_p = lit_get_magic_string_utf8 (id); + lit_utf8_size_t magic_string_bytes_count = lit_get_magic_string_size (id); + + const lit_utf8_byte_t *str_iter_p = magic_string_bytes_p; + lit_utf8_byte_t *buf_iter_p = buffer_p; + lit_utf8_size_t bytes_copied = 0; + + while (magic_string_bytes_count--) + { + bytes_copied++; + JERRY_ASSERT (bytes_copied <= buffer_size); + + *buf_iter_p++ = *str_iter_p++; + } + + return buf_iter_p; +} /* lit_copy_magic_string_to_buffer */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.h new file mode 100644 index 00000000..a079396c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.h @@ -0,0 +1,118 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIT_MAGIC_STRINGS_H +#define LIT_MAGIC_STRINGS_H + +#include "lit-globals.h" + +/** + * Identifiers of ECMA and implementation-defined magic string constants + */ +typedef enum +{ +/** @cond doxygen_suppress */ +#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) +#define LIT_MAGIC_STRING_DEF(id, ascii_zt_string) id, +#include "lit-magic-strings.inc.h" +#undef LIT_MAGIC_STRING_DEF +#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE + /** @endcond */ + LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< number of non-internal magic strings */ + LIT_INTERNAL_MAGIC_API_INTERNAL = LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< Used to add non-visible JS properties + * from the public API */ + LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX, /**< [[%Iterator%NextIndex]] property */ + LIT_INTERNAL_MAGIC_STRING_MAP_KEY, /**< Property key used when an object is a key in a map object */ + LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, /**< %ArrayProto_values% intrinsic routine */ + LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES, /**< %TypedArray%.prototype values and [@@iterator] routine */ + LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, /**< Set.prototype values, keys and [@@iterator] routines */ + LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES, /**< Map.prototype entries and [@@iterator] routines */ + /* List of well known symbols */ + LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, /**< @@asyncIterator well known symbol */ + LIT_GLOBAL_SYMBOL__FIRST = LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, /**< first global symbol */ + LIT_GLOBAL_SYMBOL_HAS_INSTANCE, /**< @@hasInstance well known symbol */ + LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE, /**< @@isConcatSpreadable well known symbol */ + LIT_GLOBAL_SYMBOL_ITERATOR, /**< @@iterator well known symbol */ + LIT_GLOBAL_SYMBOL_MATCH, /**< @@match well known symbol */ + LIT_GLOBAL_SYMBOL_REPLACE, /**< @@replace well known symbol */ + LIT_GLOBAL_SYMBOL_SEARCH, /**< @@search well known symbol */ + LIT_GLOBAL_SYMBOL_SPECIES, /**< @@species well known symbol */ + LIT_GLOBAL_SYMBOL_SPLIT, /**< @@split well known symbol */ + LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, /**< @@toPrimitive well known symbol */ + LIT_GLOBAL_SYMBOL_TO_STRING_TAG, /**< @@toStringTag well known symbol */ + LIT_GLOBAL_SYMBOL_UNSCOPABLES, /**< @@unscopables well known symbol */ + LIT_GLOBAL_SYMBOL_MATCH_ALL, /**< @@matchAll well known symbol */ + LIT_GLOBAL_SYMBOL__LAST = LIT_GLOBAL_SYMBOL_MATCH_ALL, /**< last global symbol */ + + LIT_INTERNAL_MAGIC_STRING_DELETED, /**< special value for deleted properties */ + LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT, /**< function which initializes properties */ + + LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER, /**< native pointer info associated with an object */ + LIT_INTERNAL_MAGIC_STRING_FIRST_DATA = LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER, /**< first index of special + * data properties */ + LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES, /**< native pointer info associated with an object + * which contains references to other values */ + LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD, /**< dynamic environment record needed by class constructors */ + LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED, /**< computed class field name list */ + LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS, /**< internal collection for storing private elements */ + LIT_INTERNAL_MAGIC_STRING_CONTAINER_WEAK_REFS, /**< Weak references to the current container object */ + LIT_INTERNAL_MAGIC_STRING_WEAK_REFS, /**< Weak references to the current object */ + LIT_MAGIC_STRING__COUNT /**< number of magic strings */ +} lit_magic_string_id_t; + +/** + * Properties that are need to be ignored for opfunc_set_class_attributes + */ +#define LIT_INTERNAL_MAGIC_STRING_IGNORED(id) \ + ((id) >= LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED && (id) <= LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS) + +/** + * Checks whether the given id corresponds to a global symbol + */ +#define LIT_IS_GLOBAL_SYMBOL(id) ((id) >= LIT_GLOBAL_SYMBOL__FIRST && (id) <= LIT_GLOBAL_SYMBOL__LAST) + +/** + * Identifiers of implementation-defined external magic string constants + */ +typedef uint32_t lit_magic_string_ex_id_t; + +uint32_t lit_get_magic_string_ex_count (void); + +const lit_utf8_byte_t *lit_get_magic_string_utf8 (uint32_t id); +lit_utf8_size_t lit_get_magic_string_size (uint32_t id); + +const lit_utf8_byte_t *lit_get_magic_string_ex_utf8 (uint32_t id); +lit_utf8_size_t lit_get_magic_string_ex_size (uint32_t id); + +void lit_magic_strings_ex_set (const lit_utf8_byte_t *const *ex_str_items, + uint32_t count, + const lit_utf8_size_t *ex_str_sizes); + +lit_magic_string_id_t lit_is_utf8_string_magic (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); +lit_magic_string_id_t lit_is_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, + lit_utf8_size_t string1_size, + const lit_utf8_byte_t *string2_p, + lit_utf8_size_t string2_size); + +lit_magic_string_ex_id_t lit_is_ex_utf8_string_magic (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); +lit_magic_string_ex_id_t lit_is_ex_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, + lit_utf8_size_t string1_size, + const lit_utf8_byte_t *string2_p, + lit_utf8_size_t string2_size); + +lit_utf8_byte_t * +lit_copy_magic_string_to_buffer (lit_magic_string_id_t id, lit_utf8_byte_t *buffer_p, lit_utf8_size_t buffer_size); + +#endif /* !LIT_MAGIC_STRINGS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.inc.h new file mode 100644 index 00000000..2d1519c7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.inc.h @@ -0,0 +1,985 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-strings.py script + * from lit-magic-strings.ini. Do not edit! */ + +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING__EMPTY, "") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPACE_CHAR, " ") +#if JERRY_MODULE_SYSTEM +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASTERIX_CHAR, "*") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMMA_CHAR, ",") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_E_U, "E") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, "[") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR, "]") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PI_U, "PI") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_AT, "at") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS, "is") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OF, "of") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_OR, "or") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LN2_U, "LN2") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAP_UL, "Map") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NAN, "NaN") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UL, "Set") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UTC_U, "UTC") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ABS, "abs") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ADD, "add") +#endif /* JERRY_BUILTIN_ATOMICS \ +|| JERRY_BUILTIN_CONTAINER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ALL, "all") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_AND, "and") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ANY, "any") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COS, "cos") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EXP, "exp") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FOR, "for") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET, "get") +#if JERRY_BUILTIN_CONTAINER || JERRY_BUILTIN_PROXY || JERRY_BUILTIN_REFLECT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS, "has") +#endif /* JERRY_BUILTIN_CONTAINER \ +|| JERRY_BUILTIN_PROXY \ +|| JERRY_BUILTIN_REFLECT */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG, "log") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAP, "map") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAX, "max") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MIN, "min") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NOW, "now") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_POP, "pop") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_POW, "pow") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RAW, "raw") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET, "set") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SIN, "sin") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_SUB, "sub") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TAN, "tan") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_XOR, "xor") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP, "(?:)") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DATE_UL, "Date") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LN10_U, "LN10") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MATH_UL, "Math") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NULL_UL, "Null") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ACOS, "acos") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASIN, "asin") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATAN, "atan") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIND, "bind") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CALL, "call") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CBRT, "cbrt") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CEIL, "ceil") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COSH, "cosh") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DONE, "done") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EVAL, "eval") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EXEC, "exec") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FILL, "fill") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FIND, "find") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLAT, "flat") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FROM, "from") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IMUL, "imul") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_JOIN, "join") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_KEYS, "keys") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_LOAD, "load") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG2, "log2") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NAME, "name") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NEXT, "next") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NULL, "null") +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PUSH, "push") +#endif /* JERRY_BUILTIN_ARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RACE, "race") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SEAL, "seal") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SIGN, "sign") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SINH, "sinh") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SIZE, "size") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SOME, "some") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SORT, "sort") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT, "sqrt") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TANH, "tanh") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TEST, "test") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_THEN, "then") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM, "trim") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRUE, "true") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_WAIT, "wait") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARRAY_UL, "Array") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ERROR_UL, "Error") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG2E_U, "LOG2E") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_PROXY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROXY_UL, "Proxy") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT2_U, "SQRT2") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ACOSH, "acosh") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_APPLY, "apply") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASINH, "asinh") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATAN2, "atan2") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATANH, "atanh") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CATCH, "catch") +#if JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CLEAR, "clear") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CLZ32, "clz32") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_WEAKREF +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEREF, "deref") +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EVERY, "every") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EXPM1, "expm1") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FALSE, "false") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLAGS, "flags") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLOOR, "floor") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HYPOT, "hypot") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INDEX, "index") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INPUT, "input") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_NAN, "isNaN") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG10, "log10") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG1P, "log1p") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MATCH, "match") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE, "parse") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_PROXY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROXY, "proxy") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ROUND, "round") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SHIFT, "shift") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_SHAREDARRAYBUFFER || JERRY_BUILTIN_STRING || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SLICE, "slice") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_SHAREDARRAYBUFFER \ +|| JERRY_BUILTIN_STRING \ +|| JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPLIT, "split") +#if JERRY_LINE_INFO +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STACK, "stack") +#endif /* JERRY_LINE_INFO */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_STORE, "store") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_THROW, "throw") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRUNC, "trunc") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUE, "value") +#if JERRY_PARSER && JERRY_SOURCE_NAME +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SOURCE_NAME_EVAL, "") +#endif /* JERRY_PARSER && JERRY_SOURCE_NAME */ +#if JERRY_BUILTIN_BIGINT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIGINT_UL, "BigInt") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG10E_U, "LOG10E") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_MODULE_SYSTEM +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MODULE_UL, "Module") +#endif /* JERRY_MODULE_SYSTEM */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NUMBER_UL, "Number") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT_UL, "Object") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REGEXP_UL, "RegExp") +#if JERRY_PARSER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SCRIPT_UL, "Script") +#endif /* JERRY_PARSER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRING_UL, "String") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL_UL, "Symbol") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASSIGN, "assign") +#if JERRY_BUILTIN_BIGINT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIGINT, "bigint") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_DATAVIEW || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BUFFER, "buffer") +#endif /* JERRY_BUILTIN_DATAVIEW \ +|| JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CALLEE, "callee") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CALLER, "caller") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CHAR_AT_UL, "charAt") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CONCAT, "concat") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CREATE, "create") +#if JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DELETE, "delete") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DOTALL, "dotAll") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ERRORS_UL, "errors") +#if JERRY_BUILTIN_ANNEXB +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ESCAPE, "escape") +#endif /* JERRY_BUILTIN_ANNEXB */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FILTER, "filter") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FREEZE, "freeze") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FROUND, "fround") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_DAY_UL, "getDay") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GLOBAL, "global") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS_OWN_UL, "hasOwn") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_VIEW_UL, "isView") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_KEY_FOR, "keyFor") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LENGTH, "length") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_NOTIFY, "notify") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NUMBER, "number") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT, "object") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PAD_END, "padEnd") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RANDOM, "random") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REASON, "reason") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REDUCE, "reduce") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REJECT, "reject") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REPEAT, "repeat") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RETURN, "return") +#if JERRY_BUILTIN_PROXY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REVOKE, "revoke") +#endif /* JERRY_BUILTIN_PROXY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SEARCH, "search") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SOURCE, "source") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPLICE, "splice") +#endif /* JERRY_BUILTIN_ARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STATUS, "status") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STICKY, "sticky") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRING, "string") +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBSTR, "substr") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL, "symbol") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_JSON_UL, "toJSON") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUES, "values") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_U, "Atomics") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN_UL, "Boolean") +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EPSILON_U, "EPSILON") +#endif /* JERRY_BUILTIN_NUMBER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROMISE_UL, "Promise") +#if JERRY_BUILTIN_REFLECT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REFLECT_UL, "Reflect") +#endif /* JERRY_BUILTIN_REFLECT */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT1_2_U, "SQRT1_2") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL_DOT_UL, "Symbol.") +#if JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_WEAKMAP_UL, "WeakMap") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_WEAKREF +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_WEAKREF_UL, "WeakRef") +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_WEAKSET_UL, "WeakSet") +#endif /* JERRY_BUILTIN_CONTAINER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN, "boolean") +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMPILE, "compile") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFAULT, "default") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENTRIES, "entries") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FINALLY, "finally") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLATMAP, "flatMap") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_CONTAINER || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FOR_EACH_UL, "forEach") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_CONTAINER \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_DATE_UL, "getDate") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_INT8_UL, "getInt8") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_TIME_UL, "getTime") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_YEAR_UL, "getYear") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_STRING || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INDEX_OF_UL, "indexOf") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_STRING \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_ARRAY_UL, "isArray") +#endif /* JERRY_BUILTIN_ARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MESSAGE, "message") +#if JERRY_BUILTIN_PROXY || JERRY_BUILTIN_REFLECT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OWN_KEYS_UL, "ownKeys") +#endif /* JERRY_BUILTIN_PROXY \ +|| JERRY_BUILTIN_REFLECT */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REPLACE, "replace") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RESOLVE, "resolve") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REVERSE, "reverse") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_DATE_UL, "setDate") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_INT8_UL, "setInt8") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_TIME_UL, "setTime") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_YEAR_UL, "setYear") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPECIES, "species") +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_FIXED_UL, "toFixed") +#endif /* JERRY_BUILTIN_NUMBER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_END, "trimEnd") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNICODE, "unicode") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNSHIFT, "unshift") +#endif /* JERRY_BUILTIN_ARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUE_OF_UL, "valueOf") +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DATAVIEW_UL, "DataView") +#endif /* JERRY_BUILTIN_DATAVIEW */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_UL, "Function") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INFINITY_UL, "Infinity") +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_URI_ERROR_UL, "URIError") +#endif /* JERRY_BUILTIN_ERRORS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT_TO_STRING_UL, "[object ") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENDS_WITH, "endsWith") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_EXCHANGE, "exchange") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION, "function") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_HOURS_UL, "getHours") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_INT16_UL, "getInt16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_INT32_UL, "getInt32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MONTH_UL, "getMonth") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT8_UL, "getUint8") +#endif /* JERRY_BUILTIN_DATAVIEW */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INCLUDES, "includes") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FINITE, "isFinite") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FROZEN_UL, "isFrozen") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_SEALED_UL, "isSealed") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ITERATOR, "iterator") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MATCH_ALL, "matchAll") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PAD_START, "padStart") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE_INT, "parseInt") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REJECTED, "rejected") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_HOURS_UL, "setHours") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_INT16_UL, "setInt16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_INT32_UL, "setInt32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_MONTH_UL, "setMonth") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UINT8_UL, "setUint8") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBARRAY, "subarray") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_STRING_UL, "toString") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_LEFT, "trimLeft") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_ANNEXB +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNESCAPE, "unescape") +#endif /* JERRY_BUILTIN_ANNEXB */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_WRITABLE, "writable") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL, "-Infinity") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARGUMENTS_UL, "Arguments") +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EVAL_ERROR_UL, "EvalError") +#endif /* JERRY_BUILTIN_ERRORS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GENERATOR_UL, "Generator") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INT8_ARRAY_UL, "Int8Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAX_VALUE_U, "MAX_VALUE") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MIN_VALUE_U, "MIN_VALUE") +#endif /* JERRY_BUILTIN_NUMBER */ +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TYPE_ERROR_UL, "TypeError") +#endif /* JERRY_BUILTIN_ERRORS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNDEFINED_UL, "Undefined") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING__PROTO__, "__proto__") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ANONYMOUS, "anonymous") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARGUMENTS, "arguments") +#if JERRY_BUILTIN_PROXY || JERRY_BUILTIN_REFLECT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CONSTRUCT, "construct") +#endif /* JERRY_BUILTIN_PROXY \ +|| JERRY_BUILTIN_REFLECT */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DECODE_URI, "decodeURI") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENCODE_URI, "encodeURI") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FIND_INDEX, "findIndex") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FULFILLED, "fulfilled") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_DAY_UL, "getUTCDay") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT16_UL, "getUint16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT32_UL, "getUint32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_INTEGER, "isInteger") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LASTINDEX_UL, "lastIndex") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MULTILINE, "multiline") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROTOTYPE, "prototype") +#if JERRY_BUILTIN_PROXY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REVOCABLE, "revocable") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UINT16_UL, "setUint16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UINT32_UL, "setUint32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBSTRING, "substring") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_RIGHT, "trimRight") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_START, "trimStart") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNDEFINED, "undefined") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INT16_ARRAY_UL, "Int16Array") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INT32_ARRAY_UL, "Int32Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RANGE_ERROR_UL, "RangeError") +#endif /* JERRY_BUILTIN_ERRORS */ +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TYPED_ARRAY_UL, "TypedArray") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT8_ARRAY_UL, "Uint8Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ALLSETTLED, "allSettled") +#if JERRY_BUILTIN_DATAVIEW || JERRY_BUILTIN_SHAREDARRAYBUFFER || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTE_LENGTH_UL, "byteLength") +#endif /* JERRY_BUILTIN_DATAVIEW \ +|| JERRY_BUILTIN_SHAREDARRAYBUFFER \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATAVIEW || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTE_OFFSET_UL, "byteOffset") +#endif /* JERRY_BUILTIN_DATAVIEW \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CHAR_CODE_AT_UL, "charCodeAt") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COPY_WITHIN, "copyWithin") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENUMERABLE, "enumerable") +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FLOAT_32_UL, "getFloat32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATAVIEW && JERRY_NUMBER_TYPE_FLOAT64 +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FLOAT_64_UL, "getFloat64") +#endif /* JERRY_BUILTIN_DATAVIEW && JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MINUTES_UL, "getMinutes") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_SECONDS_UL, "getSeconds") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_DATE_UL, "getUTCDate") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_GLOBAL_THIS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GLOBAL_THIS_UL, "globalThis") +#endif /* JERRY_BUILTIN_GLOBAL_THIS */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IGNORECASE_UL, "ignoreCase") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_ISLOCKFREE, "isLockFree") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE_FLOAT, "parseFloat") +#if JERRY_BUILTIN_REGEXP && JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REPLACE_ALL, "replaceAll") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_FLOAT_32_UL, "setFloat32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATAVIEW && JERRY_NUMBER_TYPE_FLOAT64 +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_FLOAT_64_UL, "setFloat64") +#endif /* JERRY_BUILTIN_DATAVIEW && JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_MINUTES_UL, "setMinutes") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_SECONDS_UL, "setSeconds") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_DATE_UL, "setUTCDate") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STARTS_WITH, "startsWith") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SOURCE_NAME_ANON, "") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARRAY_BUFFER_UL, "ArrayBuffer") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYNTAX_ERROR_UL, "SyntaxError") +#endif /* JERRY_BUILTIN_ERRORS */ +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT16_ARRAY_UL, "Uint16Array") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT32_ARRAY_UL, "Uint32Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CODE_POINT_AT, "codePointAt") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CONSTRUCTOR, "constructor") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DESCRIPTION, "description") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT_FROM_ENTRIES, "fromEntries") +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_BIGINT64, "getBigInt64") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FULL_YEAR_UL, "getFullYear") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_HOURS_UL, "getUTCHours") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_MONTH_UL, "getUTCMonth") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS_INSTANCE, "hasInstance") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_STRING || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, "lastIndexOf") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_STRING \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, "reduceRight") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_BIGINT64, "setBigInt64") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_FULL_YEAR_UL, "setFullYear") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_HOURS_UL, "setUTCHours") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_MONTH_UL, "setUTCMonth") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_GMT_STRING_UL, "toGMTString") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_ISO_STRING_UL, "toISOString") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOWER_CASE_UL, "toLowerCase") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_PRECISION_UL, "toPrecision") +#endif /* JERRY_BUILTIN_NUMBER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_PRIMITIVE, "toPrimitive") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_STRING_TAG, "toStringTag") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_UTC_STRING_UL, "toUTCString") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_UPPER_CASE_UL, "toUpperCase") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNSCOPABLES, "unscopables") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLOAT32_ARRAY_UL, "Float32Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY && JERRY_NUMBER_TYPE_FLOAT64 +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLOAT64_ARRAY_UL, "Float64Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY && JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INVALID_DATE_UL, "Invalid Date") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAP_ITERATOR_UL, "Map Iterator") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_ITERATOR_UL, "Set Iterator") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CONFIGURABLE, "configurable") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FROM_CHAR_CODE_UL, "fromCharCode") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_BIGUINT64, "getBigUint64") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_EXTENSIBLE, "isExtensible") +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_BIGUINT64, "setBigUint64") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_DATE_STRING_UL, "toDateString") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_TIME_STRING_UL, "toTimeString") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASYNC_FUNCTION_UL, "AsyncFunction") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIGINT64_ARRAY_UL, "BigInt64Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASYNC_ITERATOR, "asyncIterator") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FROM_CODE_POINT_UL, "fromCodePoint") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_MINUTES_UL, "getUTCMinutes") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_SECONDS_UL, "getUTCSeconds") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_PROTOTYPE_OF_UL, "isPrototypeOf") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_SAFE_INTEGER, "isSafeInteger") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOCALE_COMPARE_UL, "localeCompare") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_MINUTES_UL, "setUTCMinutes") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_SECONDS_UL, "setUTCSeconds") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_EXPONENTIAL_UL, "toExponential") +#endif /* JERRY_BUILTIN_NUMBER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_AGGREGATE_ERROR_UL, "AggregateError") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARRAY_ITERATOR_UL, "Array Iterator") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASYNC_GENERATOR_UL, "AsyncGenerator") +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIGUINT64_ARRAY_UL, "BigUint64Array") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REFERENCE_ERROR_UL, "ReferenceError") +#endif /* JERRY_BUILTIN_ERRORS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFINE_PROPERTY_UL, "defineProperty") +#if JERRY_BUILTIN_PROXY || JERRY_BUILTIN_REFLECT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DELETE_PROPERTY_UL, "deleteProperty") +#endif /* JERRY_BUILTIN_PROXY \ +|| JERRY_BUILTIN_REFLECT */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_PROTOTYPE_OF_UL, "getPrototypeOf") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_FULL_YEAR_UL, "getUTCFullYear") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS_OWN_PROPERTY_UL, "hasOwnProperty") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL, "setPrototypeOf") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_FULL_YEAR_UL, "setUTCFullYear") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, "toLocaleString") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRING_ITERATOR_UL, "String Iterator") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_COMPAREEXCHANGE, "compareExchange") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MILLISECONDS_UL, "getMilliseconds") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_MILLISECONDS_UL, "setMilliseconds") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAX_SAFE_INTEGER_U, "MAX_SAFE_INTEGER") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MIN_SAFE_INTEGER_U, "MIN_SAFE_INTEGER") +#endif /* JERRY_BUILTIN_NUMBER */ +#if JERRY_BUILTIN_ANNEXB +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFINE_GETTER, "__defineGetter__") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFINE_SETTER, "__defineSetter__") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOOKUP_GETTER, "__lookupGetter__") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOOKUP_SETTER, "__lookupSetter__") +#endif /* JERRY_BUILTIN_ANNEXB */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL, "defineProperties") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U, "BYTES_PER_ELEMENT") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL, "GeneratorFunction") +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NEGATIVE_INFINITY_U, "NEGATIVE_INFINITY") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_POSITIVE_INFINITY_U, "POSITIVE_INFINITY") +#endif /* JERRY_BUILTIN_NUMBER */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SHARED_ARRAY_BUFFER_UL, "SharedArrayBuffer") +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL, "Uint8ClampedArray") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_TIMEZONE_OFFSET_UL, "getTimezoneOffset") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL, "preventExtensions") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_LOWER_CASE_UL, "toLocaleLowerCase") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_UPPER_CASE_UL, "toLocaleUpperCase") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DECODE_URI_COMPONENT, "decodeURIComponent") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENCODE_URI_COMPONENT, "encodeURIComponent") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_MILLISECONDS_UL, "getUTCMilliseconds") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, "isConcatSpreadable") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_MILLISECONDS_UL, "setUTCMilliseconds") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_DATE_STRING_UL, "toLocaleDateString") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_TIME_STRING_UL, "toLocaleTimeString") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON, "function anonymous(") +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL, "getOwnPropertyNames") +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_GENERATOR, "function* anonymous(") +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL, "propertyIsEnumerable") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL, "getOwnPropertySymbols") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASYNC_GENERATOR_FUNCTION_UL, "AsyncGeneratorFunction") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REGEXP_STRING_ITERATOR_UL, "RegExp String Iterator") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL, "getOwnPropertyDescriptor") +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC, "async function anonymous(") +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTORS_UL, "getOwnPropertyDescriptors") +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR, "async function* anonymous(") +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE, "function () { [native code] }") +#if JERRY_SNAPSHOT_EXEC || !(JERRY_FUNCTION_TO_STRING) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA, "function () { /* ecmascript */ }") +#endif /* JERRY_SNAPSHOT_EXEC \ +|| !(JERRY_FUNCTION_TO_STRING) */ + +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (0, LIT_MAGIC_STRING__EMPTY) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (1, LIT_MAGIC_STRING_SPACE_CHAR) +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (2, LIT_MAGIC_STRING_PI_U) +#else /* !(JERRY_BUILTIN_MATH) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (2, LIT_MAGIC_STRING_AT) +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (3, LIT_MAGIC_STRING_LN2_U) +#else /* !(JERRY_BUILTIN_MATH) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (3, LIT_MAGIC_STRING_MAP_UL) +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (4, LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP) +#else /* !(JERRY_BUILTIN_REGEXP) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (4, LIT_MAGIC_STRING_DATE_UL) +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (5, LIT_MAGIC_STRING_ARRAY_UL) +#if JERRY_PARSER && JERRY_SOURCE_NAME +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_SOURCE_NAME_EVAL) +#elif JERRY_BUILTIN_BIGINT +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_BIGINT_UL) +#elif JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_LOG10E_U) +#elif JERRY_MODULE_SYSTEM +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_MODULE_UL) +#else /* !(JERRY_MODULE_SYSTEM) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_NUMBER_UL) +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (7, LIT_MAGIC_STRING_ATOMICS_U) +#else /* !(JERRY_BUILTIN_ATOMICS) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (7, LIT_MAGIC_STRING_BOOLEAN_UL) +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (8, LIT_MAGIC_STRING_DATAVIEW_UL) +#else /* !(JERRY_BUILTIN_DATAVIEW) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (8, LIT_MAGIC_STRING_FUNCTION_UL) +#endif /* JERRY_BUILTIN_DATAVIEW */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (9, LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL) +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_INT16_ARRAY_UL) +#elif JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_RANGE_ERROR_UL) +#elif JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_TYPED_ARRAY_UL) +#else /* !(JERRY_BUILTIN_TYPEDARRAY) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_ALLSETTLED) +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (11, LIT_MAGIC_STRING_SOURCE_NAME_ANON) +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (12, LIT_MAGIC_STRING_FLOAT32_ARRAY_UL) +#elif JERRY_BUILTIN_TYPEDARRAY && JERRY_NUMBER_TYPE_FLOAT64 +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (12, LIT_MAGIC_STRING_FLOAT64_ARRAY_UL) +#elif JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (12, LIT_MAGIC_STRING_INVALID_DATE_UL) +#else /* !(JERRY_BUILTIN_DATE) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (12, LIT_MAGIC_STRING_MAP_ITERATOR_UL) +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (13, LIT_MAGIC_STRING_ASYNC_FUNCTION_UL) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (14, LIT_MAGIC_STRING_AGGREGATE_ERROR_UL) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (15, LIT_MAGIC_STRING_STRING_ITERATOR_UL) +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (16, LIT_MAGIC_STRING_MAX_SAFE_INTEGER_U) +#elif JERRY_BUILTIN_ANNEXB +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (16, LIT_MAGIC_STRING_DEFINE_GETTER) +#else /* !(JERRY_BUILTIN_ANNEXB) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (16, LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL) +#endif /* JERRY_BUILTIN_ANNEXB */ +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (17, LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U) +#else /* !(JERRY_BUILTIN_TYPEDARRAY) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (17, LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL) +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (18, LIT_MAGIC_STRING_DECODE_URI_COMPONENT) +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (19, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON) +#else /* !(JERRY_FUNCTION_TO_STRING) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (19, LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL) +#endif /* JERRY_FUNCTION_TO_STRING */ +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (20, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_GENERATOR) +#else /* !(JERRY_FUNCTION_TO_STRING) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (20, LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL) +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (21, LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (22, LIT_MAGIC_STRING_ASYNC_GENERATOR_FUNCTION_UL) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (23, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (24, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL) +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (25, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC) +#else /* !(JERRY_FUNCTION_TO_STRING) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (25, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTORS_UL) +#endif /* JERRY_FUNCTION_TO_STRING */ +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (26, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR) +#else /* !(JERRY_FUNCTION_TO_STRING) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (26, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE) +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (27, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (28, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (29, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE) +#if JERRY_SNAPSHOT_EXEC || !(JERRY_FUNCTION_TO_STRING) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (30, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA) +#endif /* JERRY_SNAPSHOT_EXEC \ +|| !(JERRY_FUNCTION_TO_STRING) */ +#if JERRY_SNAPSHOT_EXEC || !(JERRY_FUNCTION_TO_STRING) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (31, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA) +#endif /* JERRY_SNAPSHOT_EXEC \ +|| !(JERRY_FUNCTION_TO_STRING) */ +#if JERRY_SNAPSHOT_EXEC || !(JERRY_FUNCTION_TO_STRING) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (32, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA) +#endif /* JERRY_SNAPSHOT_EXEC \ +|| !(JERRY_FUNCTION_TO_STRING) */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.cpp b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.cpp new file mode 100644 index 00000000..948b4ff1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.cpp @@ -0,0 +1,934 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lit-strings.h" + +#include "jrt-libc-includes.h" + +#define LIT_UTF8_SURROGATE_MARKER 0xed /**< utf8 surrogate marker */ +#define LIT_UTF8_HIGH_SURROGATE_MIN 0xa0 /**< utf8 high surrogate minimum */ +#define LIT_UTF8_HIGH_SURROGATE_MAX 0xaf /**< utf8 high surrogate maximum */ +#define LIT_UTF8_LOW_SURROGATE_MIN 0xb0 /**< utf8 low surrogate minimum */ +#define LIT_UTF8_LOW_SURROGATE_MAX 0xbf /**< utf8 low surrogate maximum */ +#define LIT_UTF8_1_BYTE_MAX 0xf4 /**< utf8 one byte max */ +#define LIT_UTF8_2_BYTE_MAX 0x8f /**< utf8 two byte max */ +#define LIT_UTF8_VALID_TWO_BYTE_START 0xc2 /**< utf8 two byte start */ + +/** + * Validate utf-8 string + * + * NOTE: + * Isolated surrogates are allowed. + * + * @return true if utf-8 string is well-formed + * false otherwise + */ +bool +lit_is_valid_utf8_string (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 string */ + lit_utf8_size_t buf_size, /**< string size */ + bool is_strict) /**< true if surrogate pairs are not allowed */ +{ + const unsigned char *end = buf_size + utf8_buf_p; + + const unsigned char *idx = (const unsigned char *) utf8_buf_p; + + while (idx < end) + { + const uint8_t first_byte = *idx++; + + if (first_byte < LIT_UTF8_EXTRA_BYTE_MARKER) + { + continue; + } + + if (first_byte < LIT_UTF8_VALID_TWO_BYTE_START || idx >= end) + { + return false; + } + + const uint8_t second_byte = *idx++; + + if ((second_byte & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) + { + return false; + } + + if (first_byte < LIT_UTF8_3_BYTE_MARKER) + { + continue; + } + + if (idx >= end || (*idx++ & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) + { + return false; + } + + if (first_byte < LIT_UTF8_4_BYTE_MARKER) + { + if (first_byte == LIT_UTF8_3_BYTE_MARKER && (second_byte & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_EXTRA_BYTE_MARKER) + { + return false; + } + + if (is_strict && first_byte == LIT_UTF8_SURROGATE_MARKER && second_byte >= LIT_UTF8_HIGH_SURROGATE_MIN + && second_byte <= LIT_UTF8_HIGH_SURROGATE_MAX && idx + 3 <= end && idx[0] == LIT_UTF8_SURROGATE_MARKER + && idx[1] >= LIT_UTF8_LOW_SURROGATE_MIN && idx[1] <= LIT_UTF8_LOW_SURROGATE_MAX) + { + return false; + } + continue; + } + + if (idx >= end || first_byte > LIT_UTF8_1_BYTE_MAX + || (first_byte == LIT_UTF8_4_BYTE_MARKER && second_byte <= LIT_UTF8_EXTRA_BYTE_MARKER) + || (first_byte == LIT_UTF8_1_BYTE_MAX && second_byte > LIT_UTF8_2_BYTE_MAX) + || (*idx++ & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) + { + return false; + } + } + + return true; +} /* lit_is_valid_utf8_string */ + +/** + * Validate cesu-8 string + * + * @return true if cesu-8 string is well-formed + * false otherwise + */ +bool +lit_is_valid_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, /**< cesu-8 string */ + lit_utf8_size_t buf_size) /**< string size */ +{ + lit_utf8_size_t idx = 0; + + while (idx < buf_size) + { + lit_utf8_byte_t c = cesu8_buf_p[idx++]; + if ((c & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER) + { + continue; + } + + lit_code_point_t code_point = 0; + lit_code_point_t min_code_point = 0; + lit_utf8_size_t extra_bytes_count; + if ((c & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + extra_bytes_count = 1; + min_code_point = LIT_UTF8_2_BYTE_CODE_POINT_MIN; + code_point = ((uint32_t) (c & LIT_UTF8_LAST_5_BITS_MASK)); + } + else if ((c & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER) + { + extra_bytes_count = 2; + min_code_point = LIT_UTF8_3_BYTE_CODE_POINT_MIN; + code_point = ((uint32_t) (c & LIT_UTF8_LAST_4_BITS_MASK)); + } + else + { + return false; + } + + if (idx + extra_bytes_count > buf_size) + { + /* cesu-8 string breaks in the middle */ + return false; + } + + for (lit_utf8_size_t offset = 0; offset < extra_bytes_count; ++offset) + { + c = cesu8_buf_p[idx + offset]; + if ((c & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) + { + /* invalid continuation byte */ + return false; + } + code_point <<= LIT_UTF8_BITS_IN_EXTRA_BYTES; + code_point |= (c & LIT_UTF8_LAST_6_BITS_MASK); + } + + if (code_point < min_code_point) + { + /* cesu-8 string doesn't encode valid unicode code point */ + return false; + } + + idx += extra_bytes_count; + } + + return true; +} /* lit_is_valid_cesu8_string */ + +/** + * Check if the code point is UTF-16 low surrogate + * + * @return true / false + */ +bool +lit_is_code_point_utf16_low_surrogate (lit_code_point_t code_point) /**< code point */ +{ + return LIT_UTF16_LOW_SURROGATE_MIN <= code_point && code_point <= LIT_UTF16_LOW_SURROGATE_MAX; +} /* lit_is_code_point_utf16_low_surrogate */ + +/** + * Check if the code point is UTF-16 high surrogate + * + * @return true / false + */ +bool +lit_is_code_point_utf16_high_surrogate (lit_code_point_t code_point) /**< code point */ +{ + return LIT_UTF16_HIGH_SURROGATE_MIN <= code_point && code_point <= LIT_UTF16_HIGH_SURROGATE_MAX; +} /* lit_is_code_point_utf16_high_surrogate */ + +/** + * Represents code point (>0xFFFF) as surrogate pair and returns its lower part + * + * @return lower code_unit of the surrogate pair + */ +static ecma_char_t +convert_code_point_to_low_surrogate (lit_code_point_t code_point) /**< code point, should be > 0xFFFF */ +{ + JERRY_ASSERT (code_point > LIT_UTF16_CODE_UNIT_MAX); + + ecma_char_t code_unit_bits; + code_unit_bits = (ecma_char_t) (code_point & LIT_UTF16_LAST_10_BITS_MASK); + + return (ecma_char_t) (LIT_UTF16_LOW_SURROGATE_MARKER | code_unit_bits); +} /* convert_code_point_to_low_surrogate */ + +/** + * Represents code point (>0xFFFF) as surrogate pair and returns its higher part + * + * @return higher code_unit of the surrogate pair + */ +static ecma_char_t +convert_code_point_to_high_surrogate (lit_code_point_t code_point) /**< code point, should be > 0xFFFF */ +{ + JERRY_ASSERT (code_point > LIT_UTF16_CODE_UNIT_MAX); + JERRY_ASSERT (code_point <= LIT_UNICODE_CODE_POINT_MAX); + + ecma_char_t code_unit_bits; + code_unit_bits = (ecma_char_t) ((code_point - LIT_UTF16_FIRST_SURROGATE_CODE_POINT) >> LIT_UTF16_BITS_IN_SURROGATE); + + return (LIT_UTF16_HIGH_SURROGATE_MARKER | code_unit_bits); +} /* convert_code_point_to_high_surrogate */ + +/** + * UTF16 Encoding method for a code point + * + * See also: + * ECMA-262 v6, 10.1.1 + * + * @return uint8_t, the number of returning code points + */ +uint8_t +lit_utf16_encode_code_point (lit_code_point_t cp, /**< the code point we encode */ + ecma_char_t *cu_p) /**< result of the encoding */ +{ + if (cp <= LIT_UTF16_CODE_UNIT_MAX) + { + cu_p[0] = (ecma_char_t) cp; + return 1; + } + + cu_p[0] = convert_code_point_to_high_surrogate (cp); + cu_p[1] = convert_code_point_to_low_surrogate (cp); + return 2; +} /* lit_utf16_encode_code_point */ + +/** + * Calculate size of a zero-terminated utf-8 string + * + * NOTE: + * - string cannot be NULL + * - string should not contain zero characters in the middle + * + * @return size of a string + */ +lit_utf8_size_t +lit_zt_utf8_string_size (const lit_utf8_byte_t *utf8_str_p) /**< zero-terminated utf-8 string */ +{ + JERRY_ASSERT (utf8_str_p != NULL); + return (lit_utf8_size_t) strlen ((const char *) utf8_str_p); +} /* lit_zt_utf8_string_size */ + +/** + * Calculate length of a cesu-8 encoded string + * + * @return UTF-16 code units count + */ +lit_utf8_size_t +lit_utf8_string_length (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 string */ + lit_utf8_size_t utf8_buf_size) /**< string size */ +{ + lit_utf8_size_t length = 0; + lit_utf8_size_t size = 0; + + while (size < utf8_buf_size) + { + size += lit_get_unicode_char_size_by_utf8_first_byte (*(utf8_buf_p + size)); + length++; + } + + JERRY_ASSERT (size == utf8_buf_size); + + return length; +} /* lit_utf8_string_length */ + +/** + * Calculate the required size of an utf-8 encoded string from cesu-8 encoded string + * + * @return size of an utf-8 encoded string + */ +lit_utf8_size_t +lit_get_utf8_size_of_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, /**< cesu-8 string */ + lit_utf8_size_t cesu8_buf_size) /**< string size */ +{ + lit_utf8_size_t offset = 0; + lit_utf8_size_t utf8_buf_size = cesu8_buf_size; + ecma_char_t prev_ch = 0; + + while (offset < cesu8_buf_size) + { + ecma_char_t ch; + offset += lit_read_code_unit_from_cesu8 (cesu8_buf_p + offset, &ch); + + if (lit_is_code_point_utf16_low_surrogate (ch) && lit_is_code_point_utf16_high_surrogate (prev_ch)) + { + utf8_buf_size -= 2; + } + + prev_ch = ch; + } + + JERRY_ASSERT (offset == cesu8_buf_size); + + return utf8_buf_size; +} /* lit_get_utf8_size_of_cesu8_string */ + +/** + * Calculate length of an utf-8 encoded string from cesu-8 encoded string + * + * @return length of an utf-8 encoded string + */ +lit_utf8_size_t +lit_get_utf8_length_of_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, /**< cesu-8 string */ + lit_utf8_size_t cesu8_buf_size) /**< string size */ +{ + lit_utf8_size_t offset = 0; + lit_utf8_size_t utf8_length = 0; + ecma_char_t prev_ch = 0; + + while (offset < cesu8_buf_size) + { + ecma_char_t ch; + offset += lit_read_code_unit_from_cesu8 (cesu8_buf_p + offset, &ch); + + if (!lit_is_code_point_utf16_low_surrogate (ch) || !lit_is_code_point_utf16_high_surrogate (prev_ch)) + { + utf8_length++; + } + + prev_ch = ch; + } + + JERRY_ASSERT (offset == cesu8_buf_size); + + return utf8_length; +} /* lit_get_utf8_length_of_cesu8_string */ + +/** + * Decodes a unicode code point from non-empty utf-8-encoded buffer + * + * @return number of bytes occupied by code point in the string + */ +lit_utf8_size_t +lit_read_code_point_from_utf8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */ + lit_utf8_size_t buf_size, /**< size of the buffer in bytes */ + lit_code_point_t *code_point) /**< [out] code point */ +{ + JERRY_ASSERT (buf_p && buf_size); + + lit_utf8_byte_t c = buf_p[0]; + if ((c & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER) + { + *code_point = (lit_code_point_t) (c & LIT_UTF8_LAST_7_BITS_MASK); + return 1; + } + + lit_code_point_t ret = LIT_UNICODE_CODE_POINT_NULL; + lit_utf8_size_t bytes_count = 0; + if ((c & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + bytes_count = 2; + ret = ((lit_code_point_t) (c & LIT_UTF8_LAST_5_BITS_MASK)); + } + else if ((c & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER) + { + bytes_count = 3; + ret = ((lit_code_point_t) (c & LIT_UTF8_LAST_4_BITS_MASK)); + } + else + { + JERRY_ASSERT ((c & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER); + bytes_count = 4; + ret = ((lit_code_point_t) (c & LIT_UTF8_LAST_3_BITS_MASK)); + } + + JERRY_ASSERT (buf_size >= bytes_count); + + for (uint32_t i = 1; i < bytes_count; ++i) + { + ret <<= LIT_UTF8_BITS_IN_EXTRA_BYTES; + ret |= (buf_p[i] & LIT_UTF8_LAST_6_BITS_MASK); + } + + *code_point = ret; + return bytes_count; +} /* lit_read_code_point_from_utf8 */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return number of bytes occupied by code point in the string + */ +lit_utf8_size_t +lit_read_code_unit_from_cesu8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */ + ecma_char_t *code_unit) /**< [out] code unit */ +{ + JERRY_ASSERT (buf_p); + + lit_utf8_byte_t c = buf_p[0]; + if ((c & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER) + { + *code_unit = (ecma_char_t) (c & LIT_UTF8_LAST_7_BITS_MASK); + return 1; + } + + lit_code_point_t ret = LIT_UNICODE_CODE_POINT_NULL; + lit_utf8_size_t bytes_count; + + if ((c & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + bytes_count = 2; + ret = ((lit_code_point_t) (c & LIT_UTF8_LAST_5_BITS_MASK)); + } + else + { + JERRY_ASSERT ((c & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER); + bytes_count = 3; + ret = ((lit_code_point_t) (c & LIT_UTF8_LAST_4_BITS_MASK)); + } + + for (uint32_t i = 1; i < bytes_count; ++i) + { + ret <<= LIT_UTF8_BITS_IN_EXTRA_BYTES; + ret |= (buf_p[i] & LIT_UTF8_LAST_6_BITS_MASK); + } + + JERRY_ASSERT (ret <= LIT_UTF16_CODE_UNIT_MAX); + *code_unit = (ecma_char_t) ret; + return bytes_count; +} /* lit_read_code_unit_from_cesu8 */ + +/** + * Decodes a unicode code point from non-empty cesu-8-encoded buffer + * + * @return number of bytes occupied by code point in the string + */ +lit_utf8_size_t +lit_read_code_point_from_cesu8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */ + const lit_utf8_byte_t *buf_end_p, /**< buffer end */ + lit_code_point_t *code_point) /**< [out] code point */ +{ + ecma_char_t code_unit; + lit_utf8_size_t size = lit_read_code_unit_from_cesu8 (buf_p, &code_unit); + + JERRY_ASSERT (buf_p + size <= buf_end_p); + + if (lit_is_code_point_utf16_high_surrogate (code_unit)) + { + buf_p += size; + + if (buf_p < buf_end_p) + { + ecma_char_t next_code_unit; + lit_utf8_size_t next_size = lit_read_code_unit_from_cesu8 (buf_p, &next_code_unit); + + if (lit_is_code_point_utf16_low_surrogate (next_code_unit)) + { + JERRY_ASSERT (buf_p + next_size <= buf_end_p); + + *code_point = lit_convert_surrogate_pair_to_code_point (code_unit, next_code_unit); + return size + next_size; + } + } + } + + *code_point = code_unit; + return size; +} /* lit_read_code_point_from_cesu8 */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return number of bytes occupied by code point in the string + */ +lit_utf8_size_t +lit_read_prev_code_unit_from_utf8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */ + ecma_char_t *code_point) /**< [out] code point */ +{ + JERRY_ASSERT (buf_p); + + lit_utf8_decr (&buf_p); + return lit_read_code_unit_from_cesu8 (buf_p, code_point); +} /* lit_read_prev_code_unit_from_utf8 */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return next code unit + */ +ecma_char_t +lit_cesu8_read_next (const lit_utf8_byte_t **buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (*buf_p); + ecma_char_t ch; + + *buf_p += lit_read_code_unit_from_cesu8 (*buf_p, &ch); + + return ch; +} /* lit_cesu8_read_next */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return previous code unit + */ +ecma_char_t +lit_cesu8_read_prev (const lit_utf8_byte_t **buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (*buf_p); + ecma_char_t ch; + + lit_utf8_decr (buf_p); + lit_read_code_unit_from_cesu8 (*buf_p, &ch); + + return ch; +} /* lit_cesu8_read_prev */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return next code unit + */ +ecma_char_t JERRY_ATTR_NOINLINE +lit_cesu8_peek_next (const lit_utf8_byte_t *buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (buf_p != NULL); + ecma_char_t ch; + + lit_read_code_unit_from_cesu8 (buf_p, &ch); + + return ch; +} /* lit_cesu8_peek_next */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return previous code unit + */ +ecma_char_t JERRY_ATTR_NOINLINE +lit_cesu8_peek_prev (const lit_utf8_byte_t *buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (buf_p != NULL); + ecma_char_t ch; + + lit_read_prev_code_unit_from_utf8 (buf_p, &ch); + + return ch; +} /* lit_cesu8_peek_prev */ + +/** + * Increase cesu-8 encoded string pointer by one code unit. + */ +void +lit_utf8_incr (const lit_utf8_byte_t **buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (*buf_p); + + *buf_p += lit_get_unicode_char_size_by_utf8_first_byte (**buf_p); +} /* lit_utf8_incr */ + +/** + * Decrease cesu-8 encoded string pointer by one code unit. + */ +void +lit_utf8_decr (const lit_utf8_byte_t **buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (*buf_p); + const lit_utf8_byte_t *current_p = *buf_p; + + do + { + current_p--; + } while ((*current_p & LIT_UTF8_EXTRA_BYTE_MASK) == LIT_UTF8_EXTRA_BYTE_MARKER); + + *buf_p = current_p; +} /* lit_utf8_decr */ + +/** + * Calc hash using the specified hash_basis. + * + * NOTE: + * This is implementation of FNV-1a hash function, which is released into public domain. + * Constants used, are carefully picked primes by the authors. + * More info: http://www.isthe.com/chongo/tech/comp/fnv/ + * + * @return ecma-string's hash + */ +lit_string_hash_t +lit_utf8_string_hash_combine (lit_string_hash_t hash_basis, /**< hash to be combined with */ + const lit_utf8_byte_t *utf8_buf_p, /**< characters buffer */ + lit_utf8_size_t utf8_buf_size) /**< number of characters in the buffer */ +{ + JERRY_ASSERT (utf8_buf_p != NULL || utf8_buf_size == 0); + + uint32_t hash = hash_basis; + + for (uint32_t i = 0; i < utf8_buf_size; i++) + { + /* 16777619 is 32 bit FNV_prime = 2^24 + 2^8 + 0x93 = 16777619 */ + hash = (hash ^ utf8_buf_p[i]) * 16777619; + } + + return (lit_string_hash_t) hash; +} /* lit_utf8_string_hash_combine */ + +/** + * Calculate hash from the buffer. + * + * @return ecma-string's hash + */ +lit_string_hash_t +lit_utf8_string_calc_hash (const lit_utf8_byte_t *utf8_buf_p, /**< characters buffer */ + lit_utf8_size_t utf8_buf_size) /**< number of characters in the buffer */ +{ + JERRY_ASSERT (utf8_buf_p != NULL || utf8_buf_size == 0); + + /* 32 bit offset_basis for FNV = 2166136261 */ + return lit_utf8_string_hash_combine ((lit_string_hash_t) 2166136261, utf8_buf_p, utf8_buf_size); +} /* lit_utf8_string_calc_hash */ + +/** + * Return code unit at the specified position in string + * + * NOTE: + * code_unit_offset should be less then string's length + * + * @return code unit value + */ +ecma_char_t +lit_utf8_string_code_unit_at (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 string */ + lit_utf8_size_t utf8_buf_size, /**< string size in bytes */ + lit_utf8_size_t code_unit_offset) /**< ofset of a code_unit */ +{ + lit_utf8_byte_t *current_p = (lit_utf8_byte_t *) utf8_buf_p; + ecma_char_t code_unit; + + do + { + JERRY_ASSERT (current_p < utf8_buf_p + utf8_buf_size); + current_p += lit_read_code_unit_from_cesu8 (current_p, &code_unit); + } while (code_unit_offset--); + + return code_unit; +} /* lit_utf8_string_code_unit_at */ + +/** + * Get CESU-8 encoded size of character + * + * @return number of bytes occupied in CESU-8 + */ +lit_utf8_size_t +lit_get_unicode_char_size_by_utf8_first_byte (const lit_utf8_byte_t first_byte) /**< buffer with characters */ +{ + if ((first_byte & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER) + { + return 1; + } + else if ((first_byte & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + return 2; + } + else + { + JERRY_ASSERT ((first_byte & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER); + return 3; + } +} /* lit_get_unicode_char_size_by_utf8_first_byte */ + +/** + * Convert code unit to cesu-8 representation + * + * @return byte count required to represent the code unit + */ +lit_utf8_size_t +lit_code_unit_to_utf8 (ecma_char_t code_unit, /**< code unit */ + lit_utf8_byte_t *buf_p) /**< buffer where to store the result and its size + * should be at least LIT_UTF8_MAX_BYTES_IN_CODE_UNIT */ +{ + if (code_unit <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + buf_p[0] = (lit_utf8_byte_t) code_unit; + return 1; + } + else if (code_unit <= LIT_UTF8_2_BYTE_CODE_POINT_MAX) + { + uint32_t code_unit_bits = code_unit; + lit_utf8_byte_t second_byte_bits = (lit_utf8_byte_t) (code_unit_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_unit_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t first_byte_bits = (lit_utf8_byte_t) (code_unit_bits & LIT_UTF8_LAST_5_BITS_MASK); + JERRY_ASSERT (first_byte_bits == code_unit_bits); + + buf_p[0] = LIT_UTF8_2_BYTE_MARKER | first_byte_bits; + buf_p[1] = LIT_UTF8_EXTRA_BYTE_MARKER | second_byte_bits; + return 2; + } + else + { + uint32_t code_unit_bits = code_unit; + lit_utf8_byte_t third_byte_bits = (lit_utf8_byte_t) (code_unit_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_unit_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t second_byte_bits = (lit_utf8_byte_t) (code_unit_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_unit_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t first_byte_bits = (lit_utf8_byte_t) (code_unit_bits & LIT_UTF8_LAST_4_BITS_MASK); + JERRY_ASSERT (first_byte_bits == code_unit_bits); + + buf_p[0] = LIT_UTF8_3_BYTE_MARKER | first_byte_bits; + buf_p[1] = LIT_UTF8_EXTRA_BYTE_MARKER | second_byte_bits; + buf_p[2] = LIT_UTF8_EXTRA_BYTE_MARKER | third_byte_bits; + return 3; + } +} /* lit_code_unit_to_utf8 */ + +/** + * Convert code point to cesu-8 representation + * + * @return byte count required to represent the code point + */ +lit_utf8_size_t +lit_code_point_to_cesu8 (lit_code_point_t code_point, /**< code point */ + lit_utf8_byte_t *buf) /**< buffer where to store the result, + * its size should be at least 6 bytes */ +{ + if (code_point <= LIT_UTF16_CODE_UNIT_MAX) + { + return lit_code_unit_to_utf8 ((ecma_char_t) code_point, buf); + } + else + { + lit_utf8_size_t offset = lit_code_unit_to_utf8 (convert_code_point_to_high_surrogate (code_point), buf); + offset += lit_code_unit_to_utf8 (convert_code_point_to_low_surrogate (code_point), buf + offset); + return offset; + } +} /* lit_code_point_to_cesu8 */ + +/** + * Convert code point to utf-8 representation + * + * @return byte count required to represent the code point + */ +lit_utf8_size_t +lit_code_point_to_utf8 (lit_code_point_t code_point, /**< code point */ + lit_utf8_byte_t *buf) /**< buffer where to store the result, + * its size should be at least 4 bytes */ +{ + if (code_point <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + buf[0] = (lit_utf8_byte_t) code_point; + return 1; + } + else if (code_point <= LIT_UTF8_2_BYTE_CODE_POINT_MAX) + { + uint32_t code_point_bits = code_point; + lit_utf8_byte_t second_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t first_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_5_BITS_MASK); + JERRY_ASSERT (first_byte_bits == code_point_bits); + + buf[0] = LIT_UTF8_2_BYTE_MARKER | first_byte_bits; + buf[1] = LIT_UTF8_EXTRA_BYTE_MARKER | second_byte_bits; + return 2; + } + else if (code_point <= LIT_UTF8_3_BYTE_CODE_POINT_MAX) + { + uint32_t code_point_bits = code_point; + lit_utf8_byte_t third_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t second_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t first_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_4_BITS_MASK); + JERRY_ASSERT (first_byte_bits == code_point_bits); + + buf[0] = LIT_UTF8_3_BYTE_MARKER | first_byte_bits; + buf[1] = LIT_UTF8_EXTRA_BYTE_MARKER | second_byte_bits; + buf[2] = LIT_UTF8_EXTRA_BYTE_MARKER | third_byte_bits; + return 3; + } + else + { + JERRY_ASSERT (code_point <= LIT_UTF8_4_BYTE_CODE_POINT_MAX); + + uint32_t code_point_bits = code_point; + lit_utf8_byte_t fourth_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t third_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t second_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t first_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_3_BITS_MASK); + JERRY_ASSERT (first_byte_bits == code_point_bits); + + buf[0] = LIT_UTF8_4_BYTE_MARKER | first_byte_bits; + buf[1] = LIT_UTF8_EXTRA_BYTE_MARKER | second_byte_bits; + buf[2] = LIT_UTF8_EXTRA_BYTE_MARKER | third_byte_bits; + buf[3] = LIT_UTF8_EXTRA_BYTE_MARKER | fourth_byte_bits; + return 4; + } +} /* lit_code_point_to_utf8 */ + +/** + * Convert cesu-8 string to an utf-8 string and put it into the buffer. + * String will be truncated to fit the buffer. + * + * @return number of bytes copied to the buffer. + */ +lit_utf8_size_t +lit_convert_cesu8_string_to_utf8_string (const lit_utf8_byte_t *cesu8_string_p, /**< cesu-8 string */ + lit_utf8_size_t cesu8_size, /**< size of cesu-8 string */ + lit_utf8_byte_t *utf8_string_p, /**< destination utf-8 buffer pointer + * (can be NULL if buffer_size == 0) */ + lit_utf8_size_t utf8_size) /**< size of utf-8 buffer */ +{ + const lit_utf8_byte_t *cesu8_cursor_p = cesu8_string_p; + const lit_utf8_byte_t *cesu8_end_p = cesu8_string_p + cesu8_size; + + lit_utf8_byte_t *utf8_cursor_p = utf8_string_p; + lit_utf8_byte_t *utf8_end_p = utf8_string_p + utf8_size; + + while (cesu8_cursor_p < cesu8_end_p) + { + lit_code_point_t cp; + lit_utf8_size_t read_size = lit_read_code_point_from_cesu8 (cesu8_cursor_p, cesu8_end_p, &cp); + lit_utf8_size_t encoded_size = (cp >= LIT_UTF16_FIRST_SURROGATE_CODE_POINT) ? 4 : read_size; + + if (utf8_cursor_p + encoded_size > utf8_end_p) + { + break; + } + + if (cp >= LIT_UTF16_FIRST_SURROGATE_CODE_POINT) + { + lit_code_point_to_utf8 (cp, utf8_cursor_p); + } + else + { + memcpy (utf8_cursor_p, cesu8_cursor_p, encoded_size); + } + + utf8_cursor_p += encoded_size; + cesu8_cursor_p += read_size; + } + + JERRY_ASSERT (cesu8_cursor_p <= cesu8_end_p); + JERRY_ASSERT (utf8_cursor_p <= utf8_end_p); + + return (lit_utf8_byte_t) (utf8_cursor_p - utf8_string_p); +} /* lit_convert_cesu8_string_to_utf8_string */ + +/** + * Convert surrogate pair to code point + * + * @return code point + */ +lit_code_point_t +lit_convert_surrogate_pair_to_code_point (ecma_char_t high_surrogate, /**< high surrogate code point */ + ecma_char_t low_surrogate) /**< low surrogate code point */ +{ + JERRY_ASSERT (lit_is_code_point_utf16_high_surrogate (high_surrogate)); + JERRY_ASSERT (lit_is_code_point_utf16_low_surrogate (low_surrogate)); + + lit_code_point_t code_point; + code_point = (uint16_t) (high_surrogate - LIT_UTF16_HIGH_SURROGATE_MIN); + code_point <<= LIT_UTF16_BITS_IN_SURROGATE; + + code_point += LIT_UTF16_FIRST_SURROGATE_CODE_POINT; + + code_point |= (uint16_t) (low_surrogate - LIT_UTF16_LOW_SURROGATE_MIN); + return code_point; +} /* lit_convert_surrogate_pair_to_code_point */ + +/** + * Relational compare of cesu-8 strings + * + * First string is less than second string if: + * - strings are not equal; + * - first string is prefix of second or is lexicographically less than second. + * + * @return true - if first string is less than second string, + * false - otherwise + */ +bool +lit_compare_utf8_strings_relational (const lit_utf8_byte_t *string1_p, /**< utf-8 string */ + lit_utf8_size_t string1_size, /**< string size */ + const lit_utf8_byte_t *string2_p, /**< utf-8 string */ + lit_utf8_size_t string2_size) /**< string size */ +{ + lit_utf8_byte_t *string1_pos = (lit_utf8_byte_t *) string1_p; + lit_utf8_byte_t *string2_pos = (lit_utf8_byte_t *) string2_p; + const lit_utf8_byte_t *string1_end_p = string1_p + string1_size; + const lit_utf8_byte_t *string2_end_p = string2_p + string2_size; + + while (string1_pos < string1_end_p && string2_pos < string2_end_p) + { + ecma_char_t ch1, ch2; + string1_pos += lit_read_code_unit_from_cesu8 (string1_pos, &ch1); + string2_pos += lit_read_code_unit_from_cesu8 (string2_pos, &ch2); + + if (ch1 < ch2) + { + return true; + } + else if (ch1 > ch2) + { + return false; + } + } + + return (string1_pos >= string1_end_p && string2_pos < string2_end_p); +} /* lit_compare_utf8_strings_relational */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.h new file mode 100644 index 00000000..d00480e6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.h @@ -0,0 +1,150 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIT_STRINGS_H +#define LIT_STRINGS_H + +#include "jrt.h" +#include "lit-globals.h" + +/** + * Null character (used in few cases as utf-8 string end marker) + */ +#define LIT_BYTE_NULL (0) + +/** + * For the formal definition of Unicode transformation formats (UTF) see Section 3.9, Unicode Encoding Forms in The + * Unicode Standard (http://www.unicode.org/versions/Unicode3.0.0/ch03.pdf#G7404). + */ +#define LIT_UNICODE_CODE_POINT_NULL (0x0) +#define LIT_UNICODE_CODE_POINT_MAX (0x10FFFF) + +#define LIT_UTF16_CODE_UNIT_MAX (0xFFFF) +#define LIT_UTF16_FIRST_SURROGATE_CODE_POINT (0x10000) +#define LIT_UTF16_LOW_SURROGATE_MARKER (0xDC00) +#define LIT_UTF16_HIGH_SURROGATE_MARKER (0xD800) +#define LIT_UTF16_HIGH_SURROGATE_MIN (0xD800) +#define LIT_UTF16_HIGH_SURROGATE_MAX (0xDBFF) +#define LIT_UTF16_LOW_SURROGATE_MIN (0xDC00) +#define LIT_UTF16_LOW_SURROGATE_MAX (0xDFFF) +#define LIT_UTF16_BITS_IN_SURROGATE (10) +#define LIT_UTF16_LAST_10_BITS_MASK (0x3FF) + +#define LIT_UTF8_1_BYTE_MARKER (0x00) +#define LIT_UTF8_2_BYTE_MARKER (0xC0) +#define LIT_UTF8_3_BYTE_MARKER (0xE0) +#define LIT_UTF8_4_BYTE_MARKER (0xF0) +#define LIT_UTF8_EXTRA_BYTE_MARKER (0x80) + +#define LIT_UTF8_1_BYTE_MASK (0x80) +#define LIT_UTF8_2_BYTE_MASK (0xE0) +#define LIT_UTF8_3_BYTE_MASK (0xF0) +#define LIT_UTF8_4_BYTE_MASK (0xF8) +#define LIT_UTF8_EXTRA_BYTE_MASK (0xC0) + +#define LIT_UTF8_LAST_7_BITS_MASK (0x7F) +#define LIT_UTF8_LAST_6_BITS_MASK (0x3F) +#define LIT_UTF8_LAST_5_BITS_MASK (0x1F) +#define LIT_UTF8_LAST_4_BITS_MASK (0x0F) +#define LIT_UTF8_LAST_3_BITS_MASK (0x07) +#define LIT_UTF8_LAST_2_BITS_MASK (0x03) +#define LIT_UTF8_LAST_1_BIT_MASK (0x01) + +#define LIT_UTF8_BITS_IN_EXTRA_BYTES (6) + +#define LIT_UTF8_1_BYTE_CODE_POINT_MAX (0x7F) +#define LIT_UTF8_2_BYTE_CODE_POINT_MIN (0x80) +#define LIT_UTF8_2_BYTE_CODE_POINT_MAX (0x7FF) +#define LIT_UTF8_3_BYTE_CODE_POINT_MIN (0x800) +#define LIT_UTF8_3_BYTE_CODE_POINT_MAX (LIT_UTF16_CODE_UNIT_MAX) +#define LIT_UTF8_4_BYTE_CODE_POINT_MIN (0x10000) +#define LIT_UTF8_4_BYTE_CODE_POINT_MAX (LIT_UNICODE_CODE_POINT_MAX) + +/** + * Differnce between byte count needed to represent code point greater than 0xFFFF + * in common UTF-8 (4 bytes required) and CESU-8 (6 bytes required) + */ +#define LIT_UTF8_CESU8_SURROGATE_SIZE_DIF (2 * LIT_UTF8_MAX_BYTES_IN_CODE_UNIT - LIT_UTF8_MAX_BYTES_IN_CODE_POINT) + +/** + * Byte values >= LIT_UTF8_FIRST_BYTE_MAX are not allowed in internal strings + */ +#define LIT_UTF8_FIRST_BYTE_MAX (0xF8) + +/* validation */ +bool lit_is_valid_utf8_string (const lit_utf8_byte_t *utf8_buf_p, lit_utf8_size_t buf_size, bool strict); +bool lit_is_valid_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, lit_utf8_size_t buf_size); + +/* checks */ +bool lit_is_code_point_utf16_low_surrogate (lit_code_point_t code_point); +bool lit_is_code_point_utf16_high_surrogate (lit_code_point_t code_point); + +/* size */ +lit_utf8_size_t lit_zt_utf8_string_size (const lit_utf8_byte_t *utf8_str_p); +lit_utf8_size_t lit_get_utf8_size_of_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, lit_utf8_size_t cesu8_buf_size); + +/* length */ +lit_utf8_size_t lit_utf8_string_length (const lit_utf8_byte_t *utf8_buf_p, lit_utf8_size_t utf8_buf_size); +lit_utf8_size_t lit_get_utf8_length_of_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, + lit_utf8_size_t cesu8_buf_size); + +/* hash */ +lit_string_hash_t lit_utf8_string_calc_hash (const lit_utf8_byte_t *utf8_buf_p, lit_utf8_size_t utf8_buf_size); +lit_string_hash_t lit_utf8_string_hash_combine (lit_string_hash_t hash_basis, + const lit_utf8_byte_t *utf8_buf_p, + lit_utf8_size_t utf8_buf_size); + +/* code unit access */ +ecma_char_t lit_utf8_string_code_unit_at (const lit_utf8_byte_t *utf8_buf_p, + lit_utf8_size_t utf8_buf_size, + lit_utf8_size_t code_unit_offset); +lit_utf8_size_t lit_get_unicode_char_size_by_utf8_first_byte (const lit_utf8_byte_t first_byte); + +/* conversion */ +lit_utf8_size_t lit_code_unit_to_utf8 (ecma_char_t code_unit, lit_utf8_byte_t *buf_p); +lit_utf8_size_t lit_code_point_to_utf8 (lit_code_point_t code_point, lit_utf8_byte_t *buf); +lit_utf8_size_t lit_code_point_to_cesu8 (lit_code_point_t code_point, lit_utf8_byte_t *buf); +lit_utf8_size_t lit_convert_cesu8_string_to_utf8_string (const lit_utf8_byte_t *cesu8_string_p, + lit_utf8_size_t cesu8_size, + lit_utf8_byte_t *utf8_string_p, + lit_utf8_size_t utf8_size); +lit_code_point_t lit_convert_surrogate_pair_to_code_point (ecma_char_t high_surrogate, ecma_char_t low_surrogate); + +bool lit_compare_utf8_strings_relational (const lit_utf8_byte_t *string1_p, + lit_utf8_size_t string1_size, + const lit_utf8_byte_t *string2_p, + lit_utf8_size_t string2_size); + +uint8_t lit_utf16_encode_code_point (lit_code_point_t cp, ecma_char_t *cu_p); + +/* read code point from buffer */ +lit_utf8_size_t +lit_read_code_point_from_utf8 (const lit_utf8_byte_t *buf_p, lit_utf8_size_t buf_size, lit_code_point_t *code_point); + +lit_utf8_size_t lit_read_code_unit_from_cesu8 (const lit_utf8_byte_t *buf_p, ecma_char_t *code_unit); +lit_utf8_size_t lit_read_code_point_from_cesu8 (const lit_utf8_byte_t *buf_p, + const lit_utf8_byte_t *buf_end_p, + lit_code_point_t *code_point); + +lit_utf8_size_t lit_read_prev_code_unit_from_utf8 (const lit_utf8_byte_t *buf_p, ecma_char_t *code_point); + +ecma_char_t lit_cesu8_read_next (const lit_utf8_byte_t **buf_p); +ecma_char_t lit_cesu8_read_prev (const lit_utf8_byte_t **buf_p); +ecma_char_t lit_cesu8_peek_next (const lit_utf8_byte_t *buf_p); +ecma_char_t lit_cesu8_peek_prev (const lit_utf8_byte_t *buf_p); +void lit_utf8_incr (const lit_utf8_byte_t **buf_p); +void lit_utf8_decr (const lit_utf8_byte_t **buf_p); + +#endif /* !LIT_STRINGS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions-sup.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions-sup.inc.h new file mode 100644 index 00000000..5a12a334 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions-sup.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-unicode.py script + * from UnicodeData.txt and SpecialCasing.txt files. Do not edit! */ + +/* Contains start points of character case ranges (these are bidirectional conversions). */ +static const uint32_t lit_unicode_character_case_ranges_sup[] JERRY_ATTR_CONST_DATA = { + 0x010400, 0x010428, 0x0104b0, 0x0104d8, 0x010c80, 0x010cc0, 0x0118a0, 0x0118c0, 0x016e40, 0x016e60, 0x01e900, 0x01e922 +}; + +/* Interval lengths of start points in `character_case_ranges` table. */ +static const uint16_t lit_unicode_character_case_range_lengths_sup[] JERRY_ATTR_CONST_DATA = { 0x000028, 0x000024, + 0x000033, 0x000020, + 0x000020, 0x000022 }; diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions.inc.h new file mode 100644 index 00000000..7c6279b2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions.inc.h @@ -0,0 +1,119 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-unicode.py script + * from UnicodeData.txt and SpecialCasing.txt files. Do not edit! */ + +/* Contains start points of character case ranges (these are bidirectional conversions). */ +static const uint16_t lit_unicode_character_case_ranges[] JERRY_ATTR_CONST_DATA = { + 0x00c0, 0x00e0, 0x00d8, 0x00f8, 0x0189, 0x0256, 0x01b1, 0x028a, 0x0388, 0x03ad, 0x038e, 0x03cd, 0x0391, + 0x03b1, 0x03a3, 0x03c3, 0x03fd, 0x037b, 0x0400, 0x0450, 0x0410, 0x0430, 0x0531, 0x0561, 0x10a0, 0x2d00, + 0x13a0, 0xab70, 0x13f0, 0x13f8, 0x1c90, 0x10d0, 0x1cbd, 0x10fd, 0x1f08, 0x1f00, 0x1f18, 0x1f10, 0x1f28, + 0x1f20, 0x1f38, 0x1f30, 0x1f48, 0x1f40, 0x1f68, 0x1f60, 0x1fb8, 0x1fb0, 0x1fba, 0x1f70, 0x1fc8, 0x1f72, + 0x1fd8, 0x1fd0, 0x1fda, 0x1f76, 0x1fe8, 0x1fe0, 0x1fea, 0x1f7a, 0x1ff8, 0x1f78, 0x1ffa, 0x1f7c, 0x2160, + 0x2170, 0x24b6, 0x24d0, 0x2c00, 0x2c30, 0x2c7e, 0x023f, 0xff21, 0xff41 +}; + +/* Interval lengths of start points in `character_case_ranges` table. */ +static const uint8_t lit_unicode_character_case_range_lengths[] JERRY_ATTR_CONST_DATA = { + 0x0017, 0x0007, 0x0002, 0x0002, 0x0003, 0x0002, 0x0011, 0x0009, 0x0003, 0x0010, 0x0020, 0x0026, 0x0026, + 0x0050, 0x0006, 0x002b, 0x0003, 0x0008, 0x0006, 0x0008, 0x0008, 0x0006, 0x0008, 0x0002, 0x0002, 0x0004, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0010, 0x001a, 0x002f, 0x0002, 0x001a +}; + +/* Contains the start points of bidirectional conversion ranges. */ +static const uint16_t lit_unicode_character_pair_ranges[] JERRY_ATTR_CONST_DATA = { + 0x0100, 0x0132, 0x0139, 0x014a, 0x0179, 0x0182, 0x0187, 0x018b, 0x0191, 0x0198, 0x01a0, 0x01a7, + 0x01ac, 0x01af, 0x01b3, 0x01b8, 0x01bc, 0x01cd, 0x01de, 0x01f4, 0x01f8, 0x0222, 0x023b, 0x0241, + 0x0246, 0x0370, 0x0376, 0x03d8, 0x03f7, 0x03fa, 0x0460, 0x048a, 0x04c1, 0x04d0, 0x1e00, 0x1ea0, + 0x2183, 0x2c60, 0x2c67, 0x2c72, 0x2c75, 0x2c80, 0x2ceb, 0x2cf2, 0xa640, 0xa680, 0xa722, 0xa732, + 0xa779, 0xa77e, 0xa78b, 0xa790, 0xa796, 0xa7b4, 0xa7c2, 0xa7c7, 0xa7f5 +}; + +/* Interval lengths of start points in `character_pair_ranges` table. */ +static const uint8_t lit_unicode_character_pair_range_lengths[] JERRY_ATTR_CONST_DATA = { + 0x0030, 0x0006, 0x0010, 0x002e, 0x0006, 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0006, 0x0002, + 0x0002, 0x0002, 0x0004, 0x0002, 0x0002, 0x0010, 0x0012, 0x0002, 0x0028, 0x0012, 0x0002, 0x0002, + 0x000a, 0x0004, 0x0002, 0x0018, 0x0002, 0x0002, 0x0022, 0x0036, 0x000e, 0x0060, 0x0096, 0x0060, + 0x0002, 0x0002, 0x0006, 0x0002, 0x0002, 0x0064, 0x0004, 0x0002, 0x002e, 0x001c, 0x000e, 0x003e, + 0x0004, 0x000a, 0x0002, 0x0004, 0x0014, 0x000c, 0x0002, 0x0004, 0x0002 +}; + +/* Contains lower/upper case bidirectional conversion pairs. */ +static const uint16_t lit_unicode_character_pairs[] JERRY_ATTR_CONST_DATA = { + 0x0178, 0x00ff, 0x0181, 0x0253, 0x0186, 0x0254, 0x018e, 0x01dd, 0x018f, 0x0259, 0x0190, 0x025b, 0x0193, + 0x0260, 0x0194, 0x0263, 0x0196, 0x0269, 0x0197, 0x0268, 0x019c, 0x026f, 0x019d, 0x0272, 0x019f, 0x0275, + 0x01a6, 0x0280, 0x01a9, 0x0283, 0x01ae, 0x0288, 0x01b7, 0x0292, 0x01c4, 0x01c6, 0x01c7, 0x01c9, 0x01ca, + 0x01cc, 0x01f1, 0x01f3, 0x01f6, 0x0195, 0x01f7, 0x01bf, 0x0220, 0x019e, 0x023a, 0x2c65, 0x023d, 0x019a, + 0x023e, 0x2c66, 0x0243, 0x0180, 0x0244, 0x0289, 0x0245, 0x028c, 0x037f, 0x03f3, 0x0386, 0x03ac, 0x038c, + 0x03cc, 0x03cf, 0x03d7, 0x03f9, 0x03f2, 0x04c0, 0x04cf, 0x10c7, 0x2d27, 0x10cd, 0x2d2d, 0x1f59, 0x1f51, + 0x1f5b, 0x1f53, 0x1f5d, 0x1f55, 0x1f5f, 0x1f57, 0x1fec, 0x1fe5, 0x2132, 0x214e, 0x2c62, 0x026b, 0x2c63, + 0x1d7d, 0x2c64, 0x027d, 0x2c6d, 0x0251, 0x2c6e, 0x0271, 0x2c6f, 0x0250, 0x2c70, 0x0252, 0xa77d, 0x1d79, + 0xa78d, 0x0265, 0xa7aa, 0x0266, 0xa7ab, 0x025c, 0xa7ac, 0x0261, 0xa7ad, 0x026c, 0xa7ae, 0x026a, 0xa7b0, + 0x029e, 0xa7b1, 0x0287, 0xa7b2, 0x029d, 0xa7b3, 0xab53, 0xa7c4, 0xa794, 0xa7c5, 0x0282, 0xa7c6, 0x1d8e +}; + +/* Contains start points of one-to-two uppercase ranges where the second character + * is always the same. + */ +static const uint16_t lit_unicode_upper_case_special_ranges[] JERRY_ATTR_CONST_DATA = { + 0x1f80, 0x1f08, 0x0399, 0x1f88, 0x1f08, 0x0399, 0x1f90, 0x1f28, 0x0399, + 0x1f98, 0x1f28, 0x0399, 0x1fa0, 0x1f68, 0x0399, 0x1fa8, 0x1f68, 0x0399 +}; + +/* Interval lengths for start points in `upper_case_special_ranges` table. */ +static const uint8_t lit_unicode_upper_case_special_range_lengths[] JERRY_ATTR_CONST_DATA = { 0x0007, 0x0007, 0x0007, + 0x0007, 0x0007, 0x0007 }; + +/* Contains start points of lowercase ranges. */ +static const uint16_t lit_unicode_lower_case_ranges[] JERRY_ATTR_CONST_DATA = { 0x1f88, 0x1f80, 0x1f98, + 0x1f90, 0x1fa8, 0x1fa0 }; + +/* Interval lengths for start points in `lower_case_ranges` table. */ +static const uint8_t lit_unicode_lower_case_range_lengths[] JERRY_ATTR_CONST_DATA = { 0x0008, 0x0008, 0x0008 }; + +/* The remaining lowercase conversions. The lowercase variant can be one-to-three character long. */ +static const uint16_t lit_unicode_lower_case_conversions[] JERRY_ATTR_CONST_DATA = { + 0x01c5, 0x01c6, 0x01c8, 0x01c9, 0x01cb, 0x01cc, 0x01f2, 0x01f3, 0x03f4, 0x03b8, 0x1e9e, 0x00df, 0x1fbc, 0x1fb3, + 0x1fcc, 0x1fc3, 0x1ffc, 0x1ff3, 0x2126, 0x03c9, 0x212a, 0x006b, 0x212b, 0x00e5, 0x0130, 0x0069, 0x0307 +}; + +/* Number of one-to-one, one-to-two, and one-to-three lowercase conversions. */ +static const uint8_t lit_unicode_lower_case_conversion_counters[] JERRY_ATTR_CONST_DATA = { 0x000c, 0x0001, 0x0000 }; + +/* The remaining uppercase conversions. The uppercase variant can be one-to-three character long. */ +static const uint16_t lit_unicode_upper_case_conversions[] JERRY_ATTR_CONST_DATA = { + 0x00b5, 0x039c, 0x0131, 0x0049, 0x017f, 0x0053, 0x01c5, 0x01c4, 0x01c8, 0x01c7, 0x01cb, 0x01ca, 0x01f2, 0x01f1, + 0x0345, 0x0399, 0x03c2, 0x03a3, 0x03d0, 0x0392, 0x03d1, 0x0398, 0x03d5, 0x03a6, 0x03d6, 0x03a0, 0x03f0, 0x039a, + 0x03f1, 0x03a1, 0x03f5, 0x0395, 0x1c80, 0x0412, 0x1c81, 0x0414, 0x1c82, 0x041e, 0x1c83, 0x0421, 0x1c84, 0x0422, + 0x1c85, 0x0422, 0x1c86, 0x042a, 0x1c87, 0x0462, 0x1c88, 0xa64a, 0x1e9b, 0x1e60, 0x1fbe, 0x0399, 0x00df, 0x0053, + 0x0053, 0x0149, 0x02bc, 0x004e, 0x01f0, 0x004a, 0x030c, 0x0587, 0x0535, 0x0552, 0x1e96, 0x0048, 0x0331, 0x1e97, + 0x0054, 0x0308, 0x1e98, 0x0057, 0x030a, 0x1e99, 0x0059, 0x030a, 0x1e9a, 0x0041, 0x02be, 0x1f50, 0x03a5, 0x0313, + 0x1f87, 0x1f0f, 0x0399, 0x1f8f, 0x1f0f, 0x0399, 0x1f97, 0x1f2f, 0x0399, 0x1f9f, 0x1f2f, 0x0399, 0x1fa7, 0x1f6f, + 0x0399, 0x1faf, 0x1f6f, 0x0399, 0x1fb2, 0x1fba, 0x0399, 0x1fb3, 0x0391, 0x0399, 0x1fb4, 0x0386, 0x0399, 0x1fb6, + 0x0391, 0x0342, 0x1fbc, 0x0391, 0x0399, 0x1fc2, 0x1fca, 0x0399, 0x1fc3, 0x0397, 0x0399, 0x1fc4, 0x0389, 0x0399, + 0x1fc6, 0x0397, 0x0342, 0x1fcc, 0x0397, 0x0399, 0x1fd6, 0x0399, 0x0342, 0x1fe4, 0x03a1, 0x0313, 0x1fe6, 0x03a5, + 0x0342, 0x1ff2, 0x1ffa, 0x0399, 0x1ff3, 0x03a9, 0x0399, 0x1ff4, 0x038f, 0x0399, 0x1ff6, 0x03a9, 0x0342, 0x1ffc, + 0x03a9, 0x0399, 0xfb00, 0x0046, 0x0046, 0xfb01, 0x0046, 0x0049, 0xfb02, 0x0046, 0x004c, 0xfb05, 0x0053, 0x0054, + 0xfb06, 0x0053, 0x0054, 0xfb13, 0x0544, 0x0546, 0xfb14, 0x0544, 0x0535, 0xfb15, 0x0544, 0x053b, 0xfb16, 0x054e, + 0x0546, 0xfb17, 0x0544, 0x053d, 0x0390, 0x0399, 0x0308, 0x0301, 0x03b0, 0x03a5, 0x0308, 0x0301, 0x1f52, 0x03a5, + 0x0313, 0x0300, 0x1f54, 0x03a5, 0x0313, 0x0301, 0x1f56, 0x03a5, 0x0313, 0x0342, 0x1fb7, 0x0391, 0x0342, 0x0399, + 0x1fc7, 0x0397, 0x0342, 0x0399, 0x1fd2, 0x0399, 0x0308, 0x0300, 0x1fd3, 0x0399, 0x0308, 0x0301, 0x1fd7, 0x0399, + 0x0308, 0x0342, 0x1fe2, 0x03a5, 0x0308, 0x0300, 0x1fe3, 0x03a5, 0x0308, 0x0301, 0x1fe7, 0x03a5, 0x0308, 0x0342, + 0x1ff7, 0x03a9, 0x0342, 0x0399, 0xfb03, 0x0046, 0x0046, 0x0049, 0xfb04, 0x0046, 0x0046, 0x004c +}; + +/* Number of one-to-one, one-to-two, and one-to-three uppercase conversions. */ +static const uint8_t lit_unicode_upper_case_conversion_counters[] JERRY_ATTR_CONST_DATA = { 0x001b, 0x002c, 0x0010 }; diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-folding.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-folding.inc.h new file mode 100644 index 00000000..d9cd46f1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-folding.inc.h @@ -0,0 +1,54 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-unicode.py script + * from the CaseFolding.txt file. Do not edit! */ + +/** + * Character interval starting points for folding_skip_to_lower. + */ +static const uint16_t lit_unicode_folding_skip_to_lower_interval_starts[] JERRY_ATTR_CONST_DATA = { 0x13a0, + 0x13f8, + 0xab70 }; + +/** + * Character interval lengths for folding_skip_to_lower. + */ +static const uint8_t lit_unicode_folding_skip_to_lower_interval_lengths[] JERRY_ATTR_CONST_DATA = { 0x0055, + 0x0005, + 0x004f }; + +/** + * Non-interval characters for folding_skip_to_lower. + */ +static const uint16_t lit_unicode_folding_skip_to_lower_chars[] JERRY_ATTR_CONST_DATA = { 0x0130 }; + +/** + * Character interval starting points for folding_to_upper. + */ +static const uint16_t lit_unicode_folding_to_upper_interval_starts[] JERRY_ATTR_CONST_DATA = { 0x03d0, 0x03d5, 0x03f0, + 0x13f8, 0x1c80, 0xab70 }; + +/** + * Character interval lengths for folding_to_upper. + */ +static const uint8_t lit_unicode_folding_to_upper_interval_lengths[] JERRY_ATTR_CONST_DATA = { 0x0001, 0x0001, 0x0001, + 0x0005, 0x0008, 0x004f }; + +/** + * Non-interval characters for folding_to_upper. + */ +static const uint16_t lit_unicode_folding_to_upper_chars[] JERRY_ATTR_CONST_DATA = { 0x00b5, 0x017f, 0x0345, 0x03c2, + 0x03f5, 0x1e9b, 0x1fbe }; diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges-sup.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges-sup.inc.h new file mode 100644 index 00000000..2e034faa --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges-sup.inc.h @@ -0,0 +1,116 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-unicode.py script + * from DerivedCoreProperties.txt. Do not edit! */ + +/** + * Character interval starting points for ID_Start. + */ +static const uint32_t lit_unicode_id_start_interval_starts_sup[] JERRY_ATTR_CONST_DATA = { + 0x010000, 0x01000d, 0x010028, 0x01003c, 0x01003f, 0x010050, 0x010080, 0x010140, 0x010280, 0x0102a0, 0x010300, + 0x01032d, 0x010350, 0x010380, 0x0103a0, 0x0103c8, 0x0103d1, 0x010400, 0x0104b0, 0x0104d8, 0x010500, 0x010530, + 0x010600, 0x010740, 0x010760, 0x010800, 0x01080a, 0x010837, 0x01083f, 0x010860, 0x010880, 0x0108e0, 0x0108f4, + 0x010900, 0x010920, 0x010980, 0x0109be, 0x010a10, 0x010a15, 0x010a19, 0x010a60, 0x010a80, 0x010ac0, 0x010ac9, + 0x010b00, 0x010b40, 0x010b60, 0x010b80, 0x010c00, 0x010c80, 0x010cc0, 0x010d00, 0x010e80, 0x010eb0, 0x010f00, + 0x010f30, 0x010fb0, 0x010fe0, 0x011003, 0x011083, 0x0110d0, 0x011103, 0x011150, 0x011183, 0x0111c1, 0x011200, + 0x011213, 0x011280, 0x01128a, 0x01128f, 0x01129f, 0x0112b0, 0x011305, 0x01130f, 0x011313, 0x01132a, 0x011332, + 0x011335, 0x01135d, 0x011400, 0x011447, 0x01145f, 0x011480, 0x0114c4, 0x011580, 0x0115d8, 0x011600, 0x011680, + 0x011700, 0x011800, 0x0118a0, 0x0118ff, 0x01190c, 0x011915, 0x011918, 0x0119a0, 0x0119aa, 0x011a0b, 0x011a5c, + 0x011ac0, 0x011c00, 0x011c0a, 0x011c72, 0x011d00, 0x011d08, 0x011d0b, 0x011d60, 0x011d67, 0x011d6a, 0x011ee0, + 0x012000, 0x012400, 0x012480, 0x013000, 0x014400, 0x016800, 0x016a40, 0x016ad0, 0x016b00, 0x016b40, 0x016b63, + 0x016b7d, 0x016e40, 0x016f00, 0x016f93, 0x016fe0, 0x017000, 0x018800, 0x018d00, 0x01b000, 0x01b150, 0x01b164, + 0x01b170, 0x01bc00, 0x01bc70, 0x01bc80, 0x01bc90, 0x01d400, 0x01d456, 0x01d49e, 0x01d4a5, 0x01d4a9, 0x01d4ae, + 0x01d4bd, 0x01d4c5, 0x01d507, 0x01d50d, 0x01d516, 0x01d51e, 0x01d53b, 0x01d540, 0x01d54a, 0x01d552, 0x01d6a8, + 0x01d6c2, 0x01d6dc, 0x01d6fc, 0x01d716, 0x01d736, 0x01d750, 0x01d770, 0x01d78a, 0x01d7aa, 0x01d7c4, 0x01e100, + 0x01e137, 0x01e2c0, 0x01e800, 0x01e900, 0x01ee00, 0x01ee05, 0x01ee21, 0x01ee29, 0x01ee34, 0x01ee4d, 0x01ee51, + 0x01ee61, 0x01ee67, 0x01ee6c, 0x01ee74, 0x01ee79, 0x01ee80, 0x01ee8b, 0x01eea1, 0x01eea5, 0x01eeab, 0x020000, + 0x02a700, 0x02b740, 0x02b820, 0x02ceb0, 0x02f800, 0x030000 +}; + +/** + * Character interval lengths for ID_Start. + */ +static const uint16_t lit_unicode_id_start_interval_lengths_sup[] JERRY_ATTR_CONST_DATA = { + 0x00000b, 0x000019, 0x000012, 0x000001, 0x00000e, 0x00000d, 0x00007a, 0x000034, 0x00001c, 0x000030, 0x00001f, + 0x00001d, 0x000025, 0x00001d, 0x000023, 0x000007, 0x000004, 0x00009d, 0x000023, 0x000023, 0x000027, 0x000033, + 0x000136, 0x000015, 0x000007, 0x000005, 0x00002b, 0x000001, 0x000016, 0x000016, 0x00001e, 0x000012, 0x000001, + 0x000015, 0x000019, 0x000037, 0x000001, 0x000003, 0x000002, 0x00001c, 0x00001c, 0x00001c, 0x000007, 0x00001b, + 0x000035, 0x000015, 0x000012, 0x000011, 0x000048, 0x000032, 0x000032, 0x000023, 0x000029, 0x000001, 0x00001c, + 0x000015, 0x000014, 0x000016, 0x000034, 0x00002c, 0x000018, 0x000023, 0x000022, 0x00002f, 0x000003, 0x000011, + 0x000018, 0x000006, 0x000003, 0x00000e, 0x000009, 0x00002e, 0x000007, 0x000001, 0x000015, 0x000006, 0x000001, + 0x000004, 0x000004, 0x000034, 0x000003, 0x000002, 0x00002f, 0x000001, 0x00002e, 0x000003, 0x00002f, 0x00002a, + 0x00001a, 0x00002b, 0x00003f, 0x000007, 0x000007, 0x000001, 0x000017, 0x000007, 0x000026, 0x000027, 0x00002d, + 0x000038, 0x000008, 0x000024, 0x00001d, 0x000006, 0x000001, 0x000025, 0x000005, 0x000001, 0x00001f, 0x000012, + 0x000399, 0x00006e, 0x0000c3, 0x00042e, 0x000246, 0x000238, 0x00001e, 0x00001d, 0x00002f, 0x000003, 0x000014, + 0x000012, 0x00003f, 0x00004a, 0x00000c, 0x000001, 0x0017f7, 0x0004d5, 0x000008, 0x00011e, 0x000002, 0x000003, + 0x00018b, 0x00006a, 0x00000c, 0x000008, 0x000009, 0x000054, 0x000046, 0x000001, 0x000001, 0x000003, 0x00000b, + 0x000006, 0x000040, 0x000003, 0x000007, 0x000006, 0x00001b, 0x000003, 0x000004, 0x000006, 0x000153, 0x000018, + 0x000018, 0x00001e, 0x000018, 0x00001e, 0x000018, 0x00001e, 0x000018, 0x00001e, 0x000018, 0x000007, 0x00002c, + 0x000006, 0x00002b, 0x0000c4, 0x000043, 0x000003, 0x00001a, 0x000001, 0x000009, 0x000003, 0x000002, 0x000001, + 0x000001, 0x000003, 0x000006, 0x000003, 0x000003, 0x000009, 0x000010, 0x000002, 0x000004, 0x000010, 0x00a6dd, + 0x001034, 0x0000dd, 0x001681, 0x001d30, 0x00021d, 0x00134a +}; + +/** + * Non-interval characters for ID_Start. + */ +static const uint32_t lit_unicode_id_start_chars_sup[] JERRY_ATTR_CONST_DATA = { + 0x010808, 0x01083c, 0x010a00, 0x010f27, 0x011144, 0x011147, 0x011176, 0x0111da, 0x0111dc, 0x011288, 0x01133d, + 0x011350, 0x0114c7, 0x011644, 0x0116b8, 0x011909, 0x01193f, 0x011941, 0x0119e1, 0x0119e3, 0x011a00, 0x011a3a, + 0x011a50, 0x011a9d, 0x011c40, 0x011d46, 0x011d98, 0x011fb0, 0x016f50, 0x016fe3, 0x01d4a2, 0x01d4bb, 0x01d546, + 0x01e14e, 0x01e94b, 0x01ee24, 0x01ee27, 0x01ee39, 0x01ee3b, 0x01ee42, 0x01ee47, 0x01ee49, 0x01ee4b, 0x01ee54, + 0x01ee57, 0x01ee59, 0x01ee5b, 0x01ee5d, 0x01ee5f, 0x01ee64, 0x01ee7e +}; + +/** + * Character interval starting points for ID_Continue. + */ +static const uint32_t lit_unicode_id_continue_interval_starts_sup[] JERRY_ATTR_CONST_DATA = { + 0x010376, 0x0104a0, 0x010a01, 0x010a05, 0x010a0c, 0x010a38, 0x010ae5, 0x010d24, 0x010d30, 0x010eab, 0x010f46, + 0x011000, 0x011038, 0x011066, 0x01107f, 0x0110b0, 0x0110f0, 0x011100, 0x011127, 0x011136, 0x011145, 0x011180, + 0x0111b3, 0x0111c9, 0x0111ce, 0x01122c, 0x0112df, 0x0112f0, 0x011300, 0x01133b, 0x01133e, 0x011347, 0x01134b, + 0x011362, 0x011366, 0x011370, 0x011435, 0x011450, 0x0114b0, 0x0114d0, 0x0115af, 0x0115b8, 0x0115dc, 0x011630, + 0x011650, 0x0116ab, 0x0116c0, 0x01171d, 0x011730, 0x01182c, 0x0118e0, 0x011930, 0x011937, 0x01193b, 0x011942, + 0x011950, 0x0119d1, 0x0119da, 0x011a01, 0x011a33, 0x011a3b, 0x011a51, 0x011a8a, 0x011c2f, 0x011c38, 0x011c50, + 0x011c92, 0x011ca9, 0x011d31, 0x011d3c, 0x011d3f, 0x011d50, 0x011d8a, 0x011d90, 0x011d93, 0x011da0, 0x011ef3, + 0x016a60, 0x016af0, 0x016b30, 0x016b50, 0x016f51, 0x016f8f, 0x016ff0, 0x01bc9d, 0x01d165, 0x01d16d, 0x01d17b, + 0x01d185, 0x01d1aa, 0x01d242, 0x01d7ce, 0x01da00, 0x01da3b, 0x01da9b, 0x01daa1, 0x01e000, 0x01e008, 0x01e01b, + 0x01e023, 0x01e026, 0x01e130, 0x01e140, 0x01e2ec, 0x01e8d0, 0x01e944, 0x01e950, 0x01fbf0, 0x0e0100 +}; + +/** + * Character interval lengths for ID_Continue. + */ +static const uint16_t lit_unicode_id_continue_interval_lengths_sup[] JERRY_ATTR_CONST_DATA = { + 0x000004, 0x000009, 0x000002, 0x000001, 0x000003, 0x000002, 0x000001, 0x000003, 0x000009, 0x000001, 0x00000a, + 0x000002, 0x00000e, 0x000009, 0x000003, 0x00000a, 0x000009, 0x000002, 0x00000d, 0x000009, 0x000001, 0x000002, + 0x00000d, 0x000003, 0x00000b, 0x00000b, 0x00000b, 0x000009, 0x000003, 0x000001, 0x000006, 0x000001, 0x000002, + 0x000001, 0x000006, 0x000004, 0x000011, 0x000009, 0x000013, 0x000009, 0x000006, 0x000008, 0x000001, 0x000010, + 0x000009, 0x00000c, 0x000009, 0x00000e, 0x000009, 0x00000e, 0x000009, 0x000005, 0x000001, 0x000003, 0x000001, + 0x000009, 0x000006, 0x000006, 0x000009, 0x000006, 0x000003, 0x00000a, 0x00000f, 0x000007, 0x000007, 0x000009, + 0x000015, 0x00000d, 0x000005, 0x000001, 0x000006, 0x000009, 0x000004, 0x000001, 0x000004, 0x000009, 0x000003, + 0x000009, 0x000004, 0x000006, 0x000009, 0x000036, 0x000003, 0x000001, 0x000001, 0x000004, 0x000005, 0x000007, + 0x000006, 0x000003, 0x000002, 0x000031, 0x000036, 0x000031, 0x000004, 0x00000e, 0x000006, 0x000010, 0x000006, + 0x000001, 0x000004, 0x000006, 0x000009, 0x00000d, 0x000006, 0x000006, 0x000009, 0x000009, 0x0000ef +}; + +/** + * Non-interval characters for ID_Continue. + */ +static const uint32_t lit_unicode_id_continue_chars_sup[] JERRY_ATTR_CONST_DATA = { + 0x0101fd, 0x0102e0, 0x010a3f, 0x011173, 0x01123e, 0x011357, 0x01145e, 0x011940, + 0x0119e4, 0x011a47, 0x011d3a, 0x011d47, 0x016f4f, 0x016fe4, 0x01da75, 0x01da84 +}; diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges.inc.h new file mode 100644 index 00000000..75022dd2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges.inc.h @@ -0,0 +1,176 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-unicode.py script + * from DerivedCoreProperties.txt. Do not edit! */ + +/** + * Character interval starting points for ID_Start. + */ +static const uint16_t lit_unicode_id_start_interval_starts[] JERRY_ATTR_CONST_DATA = { + 0x00c0, 0x00d8, 0x00f8, 0x01f8, 0x02c6, 0x02e0, 0x0370, 0x0376, 0x037a, 0x0388, 0x038e, 0x03a3, 0x03f7, 0x048a, + 0x0531, 0x0560, 0x05d0, 0x05ef, 0x0620, 0x066e, 0x0671, 0x06e5, 0x06ee, 0x06fa, 0x0712, 0x074d, 0x07ca, 0x07f4, + 0x0800, 0x0840, 0x0860, 0x08a0, 0x08b6, 0x0904, 0x0958, 0x0971, 0x0985, 0x098f, 0x0993, 0x09aa, 0x09b6, 0x09dc, + 0x09df, 0x09f0, 0x0a05, 0x0a0f, 0x0a13, 0x0a2a, 0x0a32, 0x0a35, 0x0a38, 0x0a59, 0x0a72, 0x0a85, 0x0a8f, 0x0a93, + 0x0aaa, 0x0ab2, 0x0ab5, 0x0ae0, 0x0b05, 0x0b0f, 0x0b13, 0x0b2a, 0x0b32, 0x0b35, 0x0b5c, 0x0b5f, 0x0b85, 0x0b8e, + 0x0b92, 0x0b99, 0x0b9e, 0x0ba3, 0x0ba8, 0x0bae, 0x0c05, 0x0c0e, 0x0c12, 0x0c2a, 0x0c58, 0x0c60, 0x0c85, 0x0c8e, + 0x0c92, 0x0caa, 0x0cb5, 0x0ce0, 0x0cf1, 0x0d04, 0x0d0e, 0x0d12, 0x0d54, 0x0d5f, 0x0d7a, 0x0d85, 0x0d9a, 0x0db3, + 0x0dc0, 0x0e01, 0x0e32, 0x0e40, 0x0e81, 0x0e86, 0x0e8c, 0x0ea7, 0x0eb2, 0x0ec0, 0x0edc, 0x0f40, 0x0f49, 0x0f88, + 0x1000, 0x1050, 0x105a, 0x1065, 0x106e, 0x1075, 0x10a0, 0x10d0, 0x10fc, 0x11fc, 0x124a, 0x1250, 0x125a, 0x1260, + 0x128a, 0x1290, 0x12b2, 0x12b8, 0x12c2, 0x12c8, 0x12d8, 0x1312, 0x1318, 0x1380, 0x13a0, 0x13f8, 0x1401, 0x1501, + 0x1601, 0x166f, 0x1681, 0x16a0, 0x16ee, 0x1700, 0x170e, 0x1720, 0x1740, 0x1760, 0x176e, 0x1780, 0x1820, 0x1880, + 0x18b0, 0x1900, 0x1950, 0x1970, 0x1980, 0x19b0, 0x1a00, 0x1a20, 0x1b05, 0x1b45, 0x1b83, 0x1bae, 0x1bba, 0x1c00, + 0x1c4d, 0x1c5a, 0x1c80, 0x1c90, 0x1cbd, 0x1ce9, 0x1cee, 0x1cf5, 0x1d00, 0x1e00, 0x1f00, 0x1f18, 0x1f20, 0x1f48, + 0x1f50, 0x1f5f, 0x1f80, 0x1fb6, 0x1fc2, 0x1fc6, 0x1fd0, 0x1fd6, 0x1fe0, 0x1ff2, 0x1ff6, 0x2090, 0x210a, 0x2118, + 0x212a, 0x213c, 0x2145, 0x2160, 0x2c00, 0x2c30, 0x2c60, 0x2ceb, 0x2cf2, 0x2d00, 0x2d30, 0x2d80, 0x2da0, 0x2da8, + 0x2db0, 0x2db8, 0x2dc0, 0x2dc8, 0x2dd0, 0x2dd8, 0x3005, 0x3021, 0x3031, 0x3038, 0x3041, 0x309b, 0x30a1, 0x30fc, + 0x3105, 0x3131, 0x31a0, 0x31f0, 0x3400, 0x3500, 0x3600, 0x3700, 0x3800, 0x3900, 0x3a00, 0x3b00, 0x3c00, 0x3d00, + 0x3e00, 0x3f00, 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4a00, 0x4b00, + 0x4c00, 0x4d00, 0x4e00, 0x4f00, 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, 0x5800, 0x5900, + 0x5a00, 0x5b00, 0x5c00, 0x5d00, 0x5e00, 0x5f00, 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500, 0x6600, 0x6700, + 0x6800, 0x6900, 0x6a00, 0x6b00, 0x6c00, 0x6d00, 0x6e00, 0x6f00, 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500, + 0x7600, 0x7700, 0x7800, 0x7900, 0x7a00, 0x7b00, 0x7c00, 0x7d00, 0x7e00, 0x7f00, 0x8000, 0x8100, 0x8200, 0x8300, + 0x8400, 0x8500, 0x8600, 0x8700, 0x8800, 0x8900, 0x8a00, 0x8b00, 0x8c00, 0x8d00, 0x8e00, 0x8f00, 0x9000, 0x9100, + 0x9200, 0x9300, 0x9400, 0x9500, 0x9600, 0x9700, 0x9800, 0x9900, 0x9a00, 0x9b00, 0x9c00, 0x9d00, 0x9e00, 0x9f00, + 0xa000, 0xa100, 0xa200, 0xa300, 0xa400, 0xa4d0, 0xa500, 0xa600, 0xa610, 0xa62a, 0xa640, 0xa67f, 0xa6a0, 0xa717, + 0xa722, 0xa78b, 0xa7c2, 0xa7f5, 0xa803, 0xa807, 0xa80c, 0xa840, 0xa882, 0xa8f2, 0xa8fd, 0xa90a, 0xa930, 0xa960, + 0xa984, 0xa9e0, 0xa9e6, 0xa9fa, 0xaa00, 0xaa40, 0xaa44, 0xaa60, 0xaa7e, 0xaab5, 0xaab9, 0xaadb, 0xaae0, 0xaaf2, + 0xab01, 0xab09, 0xab11, 0xab20, 0xab28, 0xab30, 0xab5c, 0xab70, 0xac00, 0xad00, 0xae00, 0xaf00, 0xb000, 0xb100, + 0xb200, 0xb300, 0xb400, 0xb500, 0xb600, 0xb700, 0xb800, 0xb900, 0xba00, 0xbb00, 0xbc00, 0xbd00, 0xbe00, 0xbf00, + 0xc000, 0xc100, 0xc200, 0xc300, 0xc400, 0xc500, 0xc600, 0xc700, 0xc800, 0xc900, 0xca00, 0xcb00, 0xcc00, 0xcd00, + 0xce00, 0xcf00, 0xd000, 0xd100, 0xd200, 0xd300, 0xd400, 0xd500, 0xd600, 0xd700, 0xd7b0, 0xd7cb, 0xf900, 0xfa00, + 0xfa70, 0xfb00, 0xfb13, 0xfb1f, 0xfb2a, 0xfb38, 0xfb40, 0xfb43, 0xfb46, 0xfbd3, 0xfcd3, 0xfd50, 0xfd92, 0xfdf0, + 0xfe70, 0xfe76, 0xff21, 0xff41, 0xff66, 0xffc2, 0xffca, 0xffd2, 0xffda +}; + +/** + * Character interval lengths for ID_Start. + */ +static const uint8_t lit_unicode_id_start_interval_lengths[] JERRY_ATTR_CONST_DATA = { + 0x0016, 0x001e, 0x00ff, 0x00c9, 0x000b, 0x0004, 0x0004, 0x0001, 0x0003, 0x0002, 0x0013, 0x0052, 0x008a, 0x00a5, + 0x0025, 0x0028, 0x001a, 0x0003, 0x002a, 0x0001, 0x0062, 0x0001, 0x0001, 0x0002, 0x001d, 0x0058, 0x0020, 0x0001, + 0x0015, 0x0018, 0x000a, 0x0014, 0x0011, 0x0035, 0x0009, 0x000f, 0x0007, 0x0001, 0x0015, 0x0006, 0x0003, 0x0001, + 0x0002, 0x0001, 0x0005, 0x0001, 0x0015, 0x0006, 0x0001, 0x0001, 0x0001, 0x0003, 0x0002, 0x0008, 0x0002, 0x0015, + 0x0006, 0x0001, 0x0004, 0x0001, 0x0007, 0x0001, 0x0015, 0x0006, 0x0001, 0x0004, 0x0001, 0x0002, 0x0005, 0x0002, + 0x0003, 0x0001, 0x0001, 0x0001, 0x0002, 0x000b, 0x0007, 0x0002, 0x0016, 0x000f, 0x0002, 0x0001, 0x0007, 0x0002, + 0x0016, 0x0009, 0x0004, 0x0001, 0x0001, 0x0008, 0x0002, 0x0028, 0x0002, 0x0002, 0x0005, 0x0011, 0x0017, 0x0008, + 0x0006, 0x002f, 0x0001, 0x0006, 0x0001, 0x0004, 0x0017, 0x0009, 0x0001, 0x0004, 0x0003, 0x0007, 0x0023, 0x0004, + 0x002a, 0x0005, 0x0003, 0x0001, 0x0002, 0x000c, 0x0025, 0x002a, 0x00ff, 0x004c, 0x0003, 0x0006, 0x0003, 0x0028, + 0x0003, 0x0020, 0x0003, 0x0006, 0x0003, 0x000e, 0x0038, 0x0003, 0x0042, 0x000f, 0x0055, 0x0005, 0x00ff, 0x00ff, + 0x006b, 0x0010, 0x0019, 0x004a, 0x000a, 0x000c, 0x0003, 0x0011, 0x0011, 0x000c, 0x0002, 0x0033, 0x0058, 0x0028, + 0x0045, 0x001e, 0x001d, 0x0004, 0x002b, 0x0019, 0x0016, 0x0034, 0x002e, 0x0006, 0x001d, 0x0001, 0x002b, 0x0023, + 0x0002, 0x0023, 0x0008, 0x002a, 0x0002, 0x0003, 0x0005, 0x0001, 0x00bf, 0x00ff, 0x0015, 0x0005, 0x0025, 0x0005, + 0x0007, 0x001e, 0x0034, 0x0006, 0x0002, 0x0006, 0x0003, 0x0005, 0x000c, 0x0002, 0x0006, 0x000c, 0x0009, 0x0005, + 0x000f, 0x0003, 0x0004, 0x0028, 0x002e, 0x002e, 0x0084, 0x0003, 0x0001, 0x0025, 0x0037, 0x0016, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0002, 0x0008, 0x0004, 0x0004, 0x0055, 0x0004, 0x0059, 0x0003, + 0x002a, 0x005d, 0x001f, 0x000f, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00bf, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00fc, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x008c, 0x002d, 0x00ff, 0x000c, 0x000f, 0x0001, 0x002e, 0x001e, 0x004f, 0x0008, + 0x0066, 0x0034, 0x0008, 0x000c, 0x0002, 0x0003, 0x0016, 0x0033, 0x0031, 0x0005, 0x0001, 0x001b, 0x0016, 0x001c, + 0x002e, 0x0004, 0x0009, 0x0004, 0x0028, 0x0002, 0x0007, 0x0016, 0x0031, 0x0001, 0x0004, 0x0002, 0x000a, 0x0002, + 0x0005, 0x0005, 0x0005, 0x0006, 0x0006, 0x002a, 0x000d, 0x0072, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00a3, 0x0016, 0x0030, 0x00ff, 0x006d, + 0x0069, 0x0006, 0x0004, 0x0009, 0x000c, 0x0004, 0x0001, 0x0001, 0x006b, 0x00ff, 0x006a, 0x003f, 0x0035, 0x000b, + 0x0004, 0x0086, 0x0019, 0x0019, 0x0058, 0x0005, 0x0005, 0x0005, 0x0002 +}; + +/** + * Non-interval characters for ID_Start. + */ +static const uint16_t lit_unicode_id_start_chars[] JERRY_ATTR_CONST_DATA = { + 0x00aa, 0x00b5, 0x00ba, 0x02ec, 0x02ee, 0x037f, 0x0386, 0x038c, 0x0559, 0x06d5, 0x06ff, 0x0710, 0x07b1, 0x07fa, + 0x081a, 0x0824, 0x0828, 0x093d, 0x0950, 0x09b2, 0x09bd, 0x09ce, 0x09fc, 0x0a5e, 0x0abd, 0x0ad0, 0x0af9, 0x0b3d, + 0x0b71, 0x0b83, 0x0b9c, 0x0bd0, 0x0c3d, 0x0c80, 0x0cbd, 0x0cde, 0x0d3d, 0x0d4e, 0x0dbd, 0x0e84, 0x0ea5, 0x0ebd, + 0x0ec6, 0x0f00, 0x103f, 0x1061, 0x108e, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1cfa, + 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f, 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2d27, + 0x2d2d, 0x2d6f, 0xa8fb, 0xa9cf, 0xaa7a, 0xaab1, 0xaac0, 0xaac2, 0xfb1d, 0xfb3e +}; + +/** + * Character interval starting points for ID_Continue. + */ +static const uint16_t lit_unicode_id_continue_interval_starts[] JERRY_ATTR_CONST_DATA = { + 0x0300, 0x0483, 0x0591, 0x05c1, 0x05c4, 0x0610, 0x064b, 0x06d6, 0x06df, 0x06e7, 0x06ea, 0x06f0, 0x0730, 0x07a6, + 0x07c0, 0x07eb, 0x0816, 0x081b, 0x0825, 0x0829, 0x0859, 0x08d3, 0x08e3, 0x093a, 0x093e, 0x0951, 0x0962, 0x0966, + 0x0981, 0x09be, 0x09c7, 0x09cb, 0x09e2, 0x09e6, 0x0a01, 0x0a3e, 0x0a47, 0x0a4b, 0x0a66, 0x0a81, 0x0abe, 0x0ac7, + 0x0acb, 0x0ae2, 0x0ae6, 0x0afa, 0x0b01, 0x0b3e, 0x0b47, 0x0b4b, 0x0b55, 0x0b62, 0x0b66, 0x0bbe, 0x0bc6, 0x0bca, + 0x0be6, 0x0c00, 0x0c3e, 0x0c46, 0x0c4a, 0x0c55, 0x0c62, 0x0c66, 0x0c81, 0x0cbe, 0x0cc6, 0x0cca, 0x0cd5, 0x0ce2, + 0x0ce6, 0x0d00, 0x0d3b, 0x0d3e, 0x0d46, 0x0d4a, 0x0d62, 0x0d66, 0x0d81, 0x0dcf, 0x0dd8, 0x0de6, 0x0df2, 0x0e34, + 0x0e47, 0x0e50, 0x0eb4, 0x0ec8, 0x0ed0, 0x0f18, 0x0f20, 0x0f3e, 0x0f71, 0x0f86, 0x0f8d, 0x0f99, 0x102b, 0x1040, + 0x1056, 0x105e, 0x1062, 0x1067, 0x1071, 0x1082, 0x108f, 0x135d, 0x1369, 0x1712, 0x1732, 0x1752, 0x1772, 0x17b4, + 0x17e0, 0x180b, 0x1810, 0x1920, 0x1930, 0x1946, 0x19d0, 0x1a17, 0x1a55, 0x1a60, 0x1a7f, 0x1a90, 0x1ab0, 0x1abf, + 0x1b00, 0x1b34, 0x1b50, 0x1b6b, 0x1b80, 0x1ba1, 0x1bb0, 0x1be6, 0x1c24, 0x1c40, 0x1c50, 0x1cd0, 0x1cd4, 0x1cf7, + 0x1dc0, 0x1dfb, 0x200c, 0x203f, 0x20d0, 0x20e5, 0x2cef, 0x2de0, 0x302a, 0x3099, 0xa620, 0xa674, 0xa69e, 0xa6f0, + 0xa823, 0xa880, 0xa8b4, 0xa8d0, 0xa8e0, 0xa8ff, 0xa926, 0xa947, 0xa980, 0xa9b3, 0xa9d0, 0xa9f0, 0xaa29, 0xaa4c, + 0xaa50, 0xaa7b, 0xaab2, 0xaab7, 0xaabe, 0xaaeb, 0xaaf5, 0xabe3, 0xabec, 0xabf0, 0xfe00, 0xfe20, 0xfe33, 0xfe4d, + 0xff10 +}; + +/** + * Character interval lengths for ID_Continue. + */ +static const uint8_t lit_unicode_id_continue_interval_lengths[] JERRY_ATTR_CONST_DATA = { + 0x006f, 0x0004, 0x002c, 0x0001, 0x0001, 0x000a, 0x001e, 0x0006, 0x0005, 0x0001, 0x0003, 0x0009, 0x001a, 0x000a, + 0x0009, 0x0008, 0x0003, 0x0008, 0x0002, 0x0004, 0x0002, 0x000e, 0x0020, 0x0002, 0x0011, 0x0006, 0x0001, 0x0009, + 0x0002, 0x0006, 0x0001, 0x0002, 0x0001, 0x0009, 0x0002, 0x0004, 0x0001, 0x0002, 0x000b, 0x0002, 0x0007, 0x0002, + 0x0002, 0x0001, 0x0009, 0x0005, 0x0002, 0x0006, 0x0001, 0x0002, 0x0002, 0x0001, 0x0009, 0x0004, 0x0002, 0x0003, + 0x0009, 0x0004, 0x0006, 0x0002, 0x0003, 0x0001, 0x0001, 0x0009, 0x0002, 0x0006, 0x0002, 0x0003, 0x0001, 0x0001, + 0x0009, 0x0003, 0x0001, 0x0006, 0x0002, 0x0003, 0x0001, 0x0009, 0x0002, 0x0005, 0x0007, 0x0009, 0x0001, 0x0006, + 0x0007, 0x0009, 0x0008, 0x0005, 0x0009, 0x0001, 0x0009, 0x0001, 0x0013, 0x0001, 0x000a, 0x0023, 0x0013, 0x0009, + 0x0003, 0x0002, 0x0002, 0x0006, 0x0003, 0x000b, 0x000e, 0x0002, 0x0008, 0x0002, 0x0002, 0x0001, 0x0001, 0x001f, + 0x0009, 0x0002, 0x0009, 0x000b, 0x000b, 0x0009, 0x000a, 0x0004, 0x0009, 0x001c, 0x000a, 0x0009, 0x000d, 0x0001, + 0x0004, 0x0010, 0x0009, 0x0008, 0x0002, 0x000c, 0x0009, 0x000d, 0x0013, 0x0009, 0x0009, 0x0002, 0x0014, 0x0002, + 0x0039, 0x0004, 0x0001, 0x0001, 0x000c, 0x000b, 0x0002, 0x001f, 0x0005, 0x0001, 0x0009, 0x0009, 0x0001, 0x0001, + 0x0004, 0x0001, 0x0011, 0x0009, 0x0011, 0x000a, 0x0007, 0x000c, 0x0003, 0x000d, 0x0009, 0x0009, 0x000d, 0x0001, + 0x0009, 0x0002, 0x0002, 0x0001, 0x0001, 0x0004, 0x0001, 0x0007, 0x0001, 0x0009, 0x000f, 0x000f, 0x0001, 0x0002, + 0x0009 +}; + +/** + * Non-interval characters for ID_Continue. + */ +static const uint16_t lit_unicode_id_continue_chars[] JERRY_ATTR_CONST_DATA = { + 0x00b7, 0x0387, 0x05bf, 0x05c7, 0x0670, 0x0711, 0x07fd, 0x09bc, 0x09d7, 0x09fe, 0x0a3c, 0x0a51, + 0x0a75, 0x0abc, 0x0b3c, 0x0b82, 0x0bd7, 0x0cbc, 0x0d57, 0x0dca, 0x0dd6, 0x0e31, 0x0eb1, 0x0f35, + 0x0f37, 0x0f39, 0x0fc6, 0x17dd, 0x18a9, 0x1ced, 0x1cf4, 0x2054, 0x20e1, 0x2d7f, 0xa66f, 0xa802, + 0xa806, 0xa80b, 0xa82c, 0xa9e5, 0xaa43, 0xaab0, 0xaac1, 0xfb1e, 0xff3f +}; + +/** + * Character interval starting points for White_Space. + */ +static const uint16_t lit_unicode_white_space_interval_starts[] JERRY_ATTR_CONST_DATA = { 0x2000 }; + +/** + * Character interval lengths for White_Space. + */ +static const uint8_t lit_unicode_white_space_interval_lengths[] JERRY_ATTR_CONST_DATA = { 0x000a }; + +/** + * Non-interval characters for White_Space. + */ +static const uint16_t lit_unicode_white_space_chars[] JERRY_ATTR_CONST_DATA = { 0x00a0, + 0x1680, + 0x202f, + 0x205f, + 0x3000 }; diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/meson.build b/src/loaders/lottie/jerryscript/jerry-core/lit/meson.build new file mode 100644 index 00000000..83faa5f2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/meson.build @@ -0,0 +1,20 @@ +source_file = [ + 'lit-char-helpers.h', + 'lit-globals.h', + 'lit-magic-strings.h', + 'lit-magic-strings.inc.h', + 'lit-strings.h', + 'lit-unicode-conversions-sup.inc.h', + 'lit-unicode-conversions.inc.h', + 'lit-unicode-folding.inc.h', + 'lit-unicode-ranges-sup.inc.h', + 'lit-unicode-ranges.inc.h', + 'lit-char-helpers.cpp', + 'lit-magic-strings.cpp', + 'lit-strings.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/meson.build b/src/loaders/lottie/jerryscript/jerry-core/meson.build new file mode 100644 index 00000000..adbbffbb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/meson.build @@ -0,0 +1,9 @@ +subdir('api') +subdir('include') +subdir('ecma') +subdir('jcontext') +subdir('jmem') +subdir('jrt') +subdir('lit') +subdir('parser') +subdir('vm') diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.cpp new file mode 100644 index 00000000..d2c4fc10 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.cpp @@ -0,0 +1,86 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" + +/* These two checks only checks the compiler, they have no effect on the code. */ +JERRY_STATIC_ASSERT ((sizeof (cbc_uint8_arguments_t) == 16), sizeof_cbc_uint8_arguments_t_must_be_16_byte_long); + +JERRY_STATIC_ASSERT ((sizeof (cbc_uint16_arguments_t) == 24), sizeof_cbc_uint16_arguments_t_must_be_24_byte_long); + +JERRY_STATIC_ASSERT ((offsetof (cbc_uint8_arguments_t, script_value) == offsetof (cbc_uint16_arguments_t, script_value)), + script_value_in_cbc_uint8_arguments_and_cbc_uint16_arguments_must_be_in_the_same_offset); + +/** + * The reason of these two static asserts to notify the developer to increase the JERRY_SNAPSHOT_VERSION + * whenever new bytecodes are introduced or existing ones have been deleted. + */ +JERRY_STATIC_ASSERT ((((int) CBC_END) == 238), number_of_cbc_opcodes_changed); +JERRY_STATIC_ASSERT ((((int) CBC_EXT_END) == 167), number_of_cbc_ext_opcodes_changed); + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_bytecode Bytecode + * @{ + */ + +#if JERRY_PARSER || JERRY_PARSER_DUMP_BYTE_CODE + +/** + * Compact bytecode definition + */ +#define CBC_OPCODE(arg1, arg2, arg3, arg4) ((arg2) | (((arg3) + CBC_STACK_ADJUST_BASE) << CBC_STACK_ADJUST_SHIFT)), + +/** + * Flags of the opcodes. + */ +const uint8_t cbc_flags[] JERRY_ATTR_CONST_DATA = { CBC_OPCODE_LIST }; + +/** + * Flags of the extended opcodes. + */ +const uint8_t cbc_ext_flags[] = { CBC_EXT_OPCODE_LIST }; + +#undef CBC_OPCODE + +#endif /* JERRY_PARSER || JERRY_PARSER_DUMP_BYTE_CODE */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + +#define CBC_OPCODE(arg1, arg2, arg3, arg4) #arg1, + +/** + * Names of the opcodes. + */ +const char* const cbc_names[] = { CBC_OPCODE_LIST }; + +/** + * Names of the extended opcodes. + */ +const char* const cbc_ext_names[] = { CBC_EXT_OPCODE_LIST }; + +#undef CBC_OPCODE + +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.h new file mode 100644 index 00000000..0c627ec7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.h @@ -0,0 +1,1054 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BYTE_CODE_H +#define BYTE_CODE_H + +#include "ecma-globals.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_bytecode Bytecode + * @{ + */ + +/** + * Compact byte code (CBC) is a byte code representation + * of EcmaScript which is designed for low memory + * environments. Most opcodes are only one or sometimes + * two byte long so the CBC provides a small binary size. + * + * The execution engine of CBC is a stack machine, where + * the maximum stack size is known in advance for each + * function. + */ + +/** + * Byte code flags. Only the lower 5 bit can be used + * since the stack change is encoded in the upper + * three bits for each instruction between -4 and 3 + * (except for call / construct opcodes). + */ +#define CBC_STACK_ADJUST_BASE 4 +#define CBC_STACK_ADJUST_SHIFT 5 +#define CBC_STACK_ADJUST_VALUE(value) (((value) >> CBC_STACK_ADJUST_SHIFT) - CBC_STACK_ADJUST_BASE) + +#define CBC_NO_FLAG 0x00u +#define CBC_HAS_LITERAL_ARG 0x01u +#define CBC_HAS_LITERAL_ARG2 0x02u +#define CBC_HAS_BYTE_ARG 0x04u +#define CBC_HAS_BRANCH_ARG 0x08u + +/* These flags are shared */ +#define CBC_FORWARD_BRANCH_ARG 0x10u +#define CBC_POP_STACK_BYTE_ARG 0x10u + +#define CBC_ARG_TYPES (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2 | CBC_HAS_BYTE_ARG | CBC_HAS_BRANCH_ARG) + +#define CBC_HAS_POP_STACK_BYTE_ARG (CBC_HAS_BYTE_ARG | CBC_POP_STACK_BYTE_ARG) + +/** + * CBC_NO_RESULT_OPERATION for ext opcodes + */ +#define CBC_EXT_NO_RESULT_OPERATION(opcode) \ + ((opcode) >= PARSER_TO_EXT_OPCODE (CBC_EXT_ASSIGN_SUPER) \ + && (opcode) <= PARSER_TO_EXT_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK)) + +/* Debug macro. */ +#define CBC_ARGS_EQ(op, types) ((cbc_flags[op] & CBC_ARG_TYPES) == (types)) + +/* Debug macro. */ +#define CBC_SAME_ARGS(op1, op2) \ + (CBC_EXT_NO_RESULT_OPERATION (op1) ? ((cbc_ext_flags[PARSER_GET_EXT_OPCODE (op1)] & CBC_ARG_TYPES) \ + == (cbc_ext_flags[PARSER_GET_EXT_OPCODE (op2)] & CBC_ARG_TYPES)) \ + : ((cbc_flags[op1] & CBC_ARG_TYPES) == (cbc_flags[op2] & CBC_ARG_TYPES))) + +#define CBC_UNARY_OPERATION(name, group) \ + CBC_OPCODE (name, CBC_NO_FLAG, 0, (VM_OC_##group) | VM_OC_GET_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (name##_LITERAL, CBC_HAS_LITERAL_ARG, 1, (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_STACK) + +#define CBC_BINARY_OPERATION(name, group) \ + CBC_OPCODE (name, CBC_NO_FLAG, -1, (VM_OC_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (name##_RIGHT_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + (VM_OC_##group) | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (name##_TWO_LITERALS, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 1, \ + (VM_OC_##group) | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) + +#define CBC_UNARY_LVALUE_OPERATION(name, group) \ + CBC_OPCODE (name, CBC_NO_FLAG, -2, (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (name##_PUSH_RESULT, \ + CBC_NO_FLAG, \ + -1, \ + (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ + CBC_OPCODE (name##_BLOCK, \ + CBC_NO_FLAG, \ + -2, \ + (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (name##_IDENT, CBC_HAS_LITERAL_ARG, 0, (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \ + CBC_OPCODE (name##_IDENT_PUSH_RESULT, \ + CBC_HAS_LITERAL_ARG, \ + 1, \ + (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \ + CBC_OPCODE (name##_IDENT_BLOCK, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) + +#define CBC_UNARY_LVALUE_WITH_IDENT 3 + +#define CBC_BINARY_WITH_LITERAL 1 +#define CBC_BINARY_WITH_TWO_LITERALS 2 + +/** + * Several opcodes (mostly call and assignment opcodes) have + * two forms: one which does not push a return value onto + * the stack, and another which does. The reason is that + * the return value of these opcodes are often not used + * and the first form provides smaller byte code. + * + * The following rules must be kept by the code generator: + * - only the opcode without return value can be emitted + * by the code generator + * - the first form can be converted to the second form + * by adding 1 to the opcode + * - after the conversion the opcode must be immediately + * flushed, so no further changes are possible + * + * Hence CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode) + * cannot be true for an opcode which has a result + */ +#define CBC_NO_RESULT_OPERATION(opcode) \ + (((opcode) >= CBC_PRE_INCR && (opcode) < CBC_END) || CBC_EXT_NO_RESULT_OPERATION ((opcode))) + +/** + * Branch instructions are organized in group of 8 opcodes. + * - 1st opcode: unused, can be used for other purpose + * - 2nd opcode: forward branch with 1 byte offset + * - 3rd opcode: forward branch with 2 byte offset + * - 4th opcode: forward branch with 3 byte offset + * - 5th opcode: unused, can be used for other purpose + * - 6th opcode: backward branch with 1 byte offset + * - 7th opcode: backward branch with 2 byte offset + * - 8th opcode: backward branch with 3 byte offset + * + * Reasons: + * The branch_opcode & 0x3 tells the length in bytes of the offset + * If branch offset & 0x4 == 0, it is a forward branch. Otherwise + * it is backward. + * + * The offset bytes are encoded in higher to lower order. + */ + +#define CBC_FORWARD_BRANCH(name, stack, vm_oc) \ + CBC_OPCODE (name, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH) \ + CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH) \ + CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH) + +#define CBC_BACKWARD_BRANCH(name, stack, vm_oc) \ + CBC_OPCODE (name, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) \ + CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) \ + CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) + +#define CBC_BRANCH_OFFSET_LENGTH(opcode) ((opcode) &0x3) + +#define CBC_BRANCH_IS_BACKWARD(flags) (!((flags) &CBC_FORWARD_BRANCH_ARG)) + +#define CBC_BRANCH_IS_FORWARD(flags) ((flags) &CBC_FORWARD_BRANCH_ARG) + +/* Stack consumption of opcodes with context. */ + +/* PARSER_TRY_CONTEXT_STACK_ALLOCATION must be <= 3 */ +#define PARSER_TRY_CONTEXT_STACK_ALLOCATION 1 +/* PARSER_FINALLY_CONTEXT_STACK_ALLOCATION must be <= 3 */ +#define PARSER_FINALLY_CONTEXT_STACK_ALLOCATION 2 +/* PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION must be <= 4 */ +#define PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION 4 +/* PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION must be <= 4 */ +#define PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION 4 +/* PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION must be <= 4 */ +#define PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION 4 +/* PARSER_WITH_CONTEXT_STACK_ALLOCATION must be <= 4 */ +#define PARSER_WITH_CONTEXT_STACK_ALLOCATION 1 +/* PARSER_BLOCK_CONTEXT_STACK_ALLOCATION must be <= 3 */ +#define PARSER_BLOCK_CONTEXT_STACK_ALLOCATION 1 +/* PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION must be <= 3 */ +#define PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION 3 +/* PARSER_OBJECT_INITIALIZER_CONTEXT_STACK_ALLOCATION must be <= 2 */ +#define PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION 1 +/* PARSER_OBJECT_INITIALIZER_CONTEXT_STACK_ALLOCATION must be <= 2 */ +#define PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION 2 + +/** + * Extra stack consumption for finally context. + */ +#define PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION \ + (PARSER_FINALLY_CONTEXT_STACK_ALLOCATION - PARSER_TRY_CONTEXT_STACK_ALLOCATION) + +#define PARSER_STATIC_PRIVATE_TO_PRIVATE_OFFSET (CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD - CBC_EXT_COLLECT_PRIVATE_FIELD) + +/** + * Opcode definitions. + */ +#define CBC_OPCODE_LIST \ + /* Branch opcodes first. Some other opcodes are mixed. */ \ + CBC_OPCODE (CBC_EXT_OPCODE, CBC_NO_FLAG, 0, VM_OC_NONE) \ + CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD, 0, VM_OC_JUMP) \ + CBC_OPCODE (CBC_POP, CBC_NO_FLAG, -1, VM_OC_POP) \ + CBC_BACKWARD_BRANCH (CBC_JUMP_BACKWARD, 0, VM_OC_JUMP) \ + CBC_OPCODE (CBC_POP_BLOCK, CBC_NO_FLAG, -1, VM_OC_POP_BLOCK | VM_OC_PUT_BLOCK) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_TRUE_FORWARD, -1, VM_OC_BRANCH_IF_TRUE) \ + CBC_OPCODE (CBC_THROW, CBC_NO_FLAG, -1, VM_OC_THROW | VM_OC_GET_STACK) \ + CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_TRUE_BACKWARD, -1, VM_OC_BRANCH_IF_TRUE) \ + CBC_OPCODE (CBC_CONTEXT_END, CBC_NO_FLAG, 0, VM_OC_CONTEXT_END) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_FALSE_FORWARD, -1, VM_OC_BRANCH_IF_FALSE) \ + CBC_OPCODE (CBC_CREATE_OBJECT, CBC_NO_FLAG, 1, VM_OC_PUSH_OBJECT | VM_OC_PUT_STACK) \ + CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_FALSE_BACKWARD, -1, VM_OC_BRANCH_IF_FALSE) \ + CBC_OPCODE (CBC_SET_PROPERTY, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_SET_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \ + CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD_EXIT_CONTEXT, 0, VM_OC_JUMP_AND_EXIT_CONTEXT) \ + CBC_OPCODE (CBC_CREATE_ARRAY, CBC_NO_FLAG, 1, VM_OC_PUSH_ARRAY | VM_OC_PUT_STACK) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE, -1, VM_OC_BRANCH_IF_LOGICAL_TRUE) \ + CBC_OPCODE (CBC_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_APPEND_ARRAY) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE, -1, VM_OC_BRANCH_IF_LOGICAL_FALSE) \ + CBC_OPCODE (CBC_PUSH_ELISION, CBC_NO_FLAG, 1, VM_OC_PUSH_ELISON | VM_OC_PUT_STACK) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL, -1, VM_OC_BRANCH_IF_STRICT_EQUAL) \ + CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1, VM_OC_PUSH_NULL | VM_OC_PUT_STACK) \ + CBC_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION, VM_OC_BLOCK_CREATE_CONTEXT) \ + \ + /* Basic opcodes. Note: These 4 opcodes must me in this order */ \ + CBC_OPCODE (CBC_PUSH_LITERAL, CBC_HAS_LITERAL_ARG, 1, VM_OC_PUSH | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_PUSH_TWO_LITERALS, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 2, \ + VM_OC_PUSH_TWO | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_PUSH_THIS_LITERAL, CBC_HAS_LITERAL_ARG, 2, VM_OC_PUSH_TWO | VM_OC_GET_THIS_LITERAL) \ + CBC_OPCODE (CBC_PUSH_THREE_LITERALS, CBC_HAS_LITERAL_ARG2, 3, VM_OC_PUSH_THREE | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_PUSH_UNDEFINED, CBC_NO_FLAG, 1, VM_OC_PUSH_UNDEFINED | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_TRUE, CBC_NO_FLAG, 1, VM_OC_PUSH_TRUE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_FALSE, CBC_NO_FLAG, 1, VM_OC_PUSH_FALSE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_THIS, CBC_NO_FLAG, 1, VM_OC_PUSH_THIS | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_NUMBER_0, CBC_NO_FLAG, 1, VM_OC_PUSH_0 | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_NUMBER_POS_BYTE, CBC_HAS_BYTE_ARG, 1, VM_OC_PUSH_POS_BYTE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_NUMBER_NEG_BYTE, CBC_HAS_BYTE_ARG, 1, VM_OC_PUSH_NEG_BYTE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_0, CBC_HAS_LITERAL_ARG, 2, VM_OC_PUSH_LIT_0 | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, \ + 2, \ + VM_OC_PUSH_LIT_POS_BYTE | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, \ + 2, \ + VM_OC_PUSH_LIT_NEG_BYTE | VM_OC_GET_LITERAL) \ + /* Note: These 4 opcodes must me in this order */ \ + CBC_OPCODE (CBC_PUSH_PROP, CBC_NO_FLAG, -1, VM_OC_PROP_GET | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_PROP_GET | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 1, \ + VM_OC_PROP_GET | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 1, \ + VM_OC_PROP_GET | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_IDENT_REFERENCE, CBC_HAS_LITERAL_ARG, 3, VM_OC_IDENT_REFERENCE | VM_OC_PUT_STACK) \ + /* Note: These 4 opcodes must me in this order */ \ + CBC_OPCODE (CBC_PUSH_PROP_REFERENCE, CBC_NO_FLAG, 1, VM_OC_PROP_REFERENCE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL_REFERENCE, \ + CBC_HAS_LITERAL_ARG, \ + 2, \ + VM_OC_PROP_REFERENCE | VM_OC_GET_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 3, \ + VM_OC_PROP_REFERENCE | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE, \ + CBC_HAS_LITERAL_ARG, \ + 3, \ + VM_OC_PROP_REFERENCE | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_NEW | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_NEW0, CBC_NO_FLAG, 0, VM_OC_NEW | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_NEW1, CBC_NO_FLAG, -1, VM_OC_NEW | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EVAL, CBC_NO_FLAG, 0, VM_OC_EVAL) \ + CBC_OPCODE (CBC_CHECK_VAR, CBC_HAS_LITERAL_ARG, 0, VM_OC_CHECK_VAR) \ + CBC_OPCODE (CBC_CHECK_LET, CBC_HAS_LITERAL_ARG, 0, VM_OC_CHECK_LET) \ + CBC_OPCODE (CBC_CREATE_VAR, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ + CBC_OPCODE (CBC_CREATE_LET, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ + CBC_OPCODE (CBC_CREATE_CONST, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ + CBC_OPCODE (CBC_CREATE_LOCAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ + CBC_OPCODE (CBC_INIT_ARG_OR_CATCH, CBC_HAS_LITERAL_ARG, -1, VM_OC_INIT_BINDING) \ + CBC_OPCODE (CBC_INIT_LET, CBC_HAS_LITERAL_ARG, -1, VM_OC_INIT_BINDING) \ + CBC_OPCODE (CBC_INIT_CONST, CBC_HAS_LITERAL_ARG, -1, VM_OC_INIT_BINDING) \ + CBC_OPCODE (CBC_INIT_ARG_OR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, VM_OC_INIT_ARG_OR_FUNC) \ + CBC_OPCODE (CBC_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_VAR_EVAL) \ + CBC_OPCODE (CBC_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, VM_OC_VAR_EVAL) \ + CBC_OPCODE (CBC_SET_VAR_FUNC, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \ + CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0, VM_OC_SET_BYTECODE_PTR) \ + CBC_OPCODE (CBC_RETURN, CBC_NO_FLAG, -1, VM_OC_RETURN | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_RETURN_FUNCTION_END, CBC_NO_FLAG, 0, VM_OC_RETURN_FUNCTION_END) \ + CBC_OPCODE (CBC_RETURN_WITH_LITERAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_RETURN | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_SET_LITERAL_PROPERTY, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_COPY_TO_GLOBAL, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COPY_TO_GLOBAL | VM_OC_GET_LITERAL) \ + \ + /* Unary opcodes. */ \ + CBC_UNARY_OPERATION (CBC_PLUS, PLUS) \ + CBC_UNARY_OPERATION (CBC_NEGATE, MINUS) \ + CBC_UNARY_OPERATION (CBC_LOGICAL_NOT, NOT) \ + CBC_UNARY_OPERATION (CBC_BIT_NOT, BIT_NOT) \ + CBC_UNARY_OPERATION (CBC_VOID, VOID) \ + CBC_OPCODE (CBC_TYPEOF, CBC_NO_FLAG, 0, VM_OC_TYPEOF | VM_OC_GET_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_TYPEOF_IDENT, CBC_HAS_LITERAL_ARG, 1, VM_OC_TYPEOF_IDENT | VM_OC_PUT_STACK) \ + \ + /* Binary opcodes. */ \ + CBC_BINARY_OPERATION (CBC_BIT_OR, BIT_OR) \ + CBC_BINARY_OPERATION (CBC_BIT_XOR, BIT_XOR) \ + CBC_BINARY_OPERATION (CBC_BIT_AND, BIT_AND) \ + CBC_BINARY_OPERATION (CBC_EQUAL, EQUAL) \ + CBC_BINARY_OPERATION (CBC_NOT_EQUAL, NOT_EQUAL) \ + CBC_BINARY_OPERATION (CBC_STRICT_EQUAL, STRICT_EQUAL) \ + CBC_BINARY_OPERATION (CBC_STRICT_NOT_EQUAL, STRICT_NOT_EQUAL) \ + CBC_BINARY_OPERATION (CBC_LESS, LESS) \ + CBC_BINARY_OPERATION (CBC_GREATER, GREATER) \ + CBC_BINARY_OPERATION (CBC_LESS_EQUAL, LESS_EQUAL) \ + CBC_BINARY_OPERATION (CBC_GREATER_EQUAL, GREATER_EQUAL) \ + CBC_BINARY_OPERATION (CBC_IN, IN) \ + CBC_BINARY_OPERATION (CBC_INSTANCEOF, INSTANCEOF) \ + CBC_BINARY_OPERATION (CBC_LEFT_SHIFT, LEFT_SHIFT) \ + CBC_BINARY_OPERATION (CBC_RIGHT_SHIFT, RIGHT_SHIFT) \ + CBC_BINARY_OPERATION (CBC_UNS_RIGHT_SHIFT, UNS_RIGHT_SHIFT) \ + CBC_BINARY_OPERATION (CBC_ADD, ADD) \ + CBC_BINARY_OPERATION (CBC_SUBTRACT, SUB) \ + CBC_BINARY_OPERATION (CBC_MULTIPLY, MUL) \ + CBC_BINARY_OPERATION (CBC_DIVIDE, DIV) \ + CBC_BINARY_OPERATION (CBC_MODULO, MOD) \ + CBC_BINARY_OPERATION (CBC_EXPONENTIATION, EXP) \ + \ + /* Unary lvalue opcodes. */ \ + CBC_OPCODE (CBC_DELETE_PUSH_RESULT, CBC_NO_FLAG, -1, VM_OC_PROP_DELETE | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_DELETE_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 1, VM_OC_DELETE | VM_OC_PUT_STACK) \ + CBC_UNARY_LVALUE_OPERATION (CBC_PRE_INCR, PRE_INCR) \ + CBC_UNARY_LVALUE_OPERATION (CBC_PRE_DECR, PRE_DECR) \ + CBC_UNARY_LVALUE_OPERATION (CBC_POST_INCR, POST_INCR) \ + CBC_UNARY_LVALUE_OPERATION (CBC_POST_DECR, POST_DECR) \ + \ + /* Call opcodes. */ \ + CBC_OPCODE (CBC_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL0, CBC_NO_FLAG, -1, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL0_PUSH_RESULT, CBC_NO_FLAG, 0, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL0_BLOCK, CBC_NO_FLAG, -1, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL0_PROP, CBC_NO_FLAG, -3, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL0_PROP_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL0_PROP_BLOCK, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL1, CBC_NO_FLAG, -2, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL1_PUSH_RESULT, CBC_NO_FLAG, -1, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL1_BLOCK, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL1_PROP, CBC_NO_FLAG, -4, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL1_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL1_PROP_BLOCK, CBC_NO_FLAG, -4, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL2, CBC_NO_FLAG, -3, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL2_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL2_BLOCK, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL2_PROP, CBC_NO_FLAG, -4, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL2_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL2_PROP_BLOCK, CBC_NO_FLAG, -4, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + \ + /* Binary assignment opcodes. */ \ + CBC_OPCODE (CBC_ASSIGN, CBC_NO_FLAG, -3, VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (CBC_ASSIGN_PUSH_RESULT, \ + CBC_NO_FLAG, \ + -2, \ + VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_ASSIGN_BLOCK, \ + CBC_NO_FLAG, \ + -3, \ + VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_ASSIGN_SET_IDENT, CBC_HAS_LITERAL_ARG, -1, VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \ + CBC_OPCODE (CBC_ASSIGN_SET_IDENT_PUSH_RESULT, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_ASSIGN_SET_IDENT_BLOCK, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \ + CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_PUSH_RESULT, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 1, \ + VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_BLOCK, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + -2, \ + VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_PUSH_RESULT, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_BLOCK, \ + CBC_HAS_LITERAL_ARG, \ + -2, \ + VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_PUSH_RESULT, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_BLOCK, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_MOV_IDENT, CBC_HAS_LITERAL_ARG, -1, VM_OC_MOV_IDENT | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \ + CBC_OPCODE (CBC_ASSIGN_LET_CONST, CBC_HAS_LITERAL_ARG, -1, VM_OC_ASSIGN_LET_CONST | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_ASSIGN_LET_CONST_LITERAL, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_ASSIGN_LET_CONST | VM_OC_GET_LITERAL) \ + \ + /* Last opcode (not a real opcode). */ \ + CBC_OPCODE (CBC_END, CBC_NO_FLAG, 0, VM_OC_NONE) + +/* All EXT branches are statement block end + * marks, so they are always forward branches. */ + +#define CBC_EXT_OPCODE_LIST \ + /* Branch opcodes first. Some other opcodes are mixed. */ \ + CBC_OPCODE (CBC_EXT_NOP, CBC_NO_FLAG, 0, VM_OC_NONE) \ + CBC_FORWARD_BRANCH (CBC_EXT_WITH_CREATE_CONTEXT, -1 + PARSER_WITH_CONTEXT_STACK_ALLOCATION, VM_OC_WITH) \ + CBC_OPCODE (CBC_EXT_FOR_IN_GET_NEXT, CBC_NO_FLAG, 1, VM_OC_FOR_IN_GET_NEXT | VM_OC_PUT_STACK) \ + CBC_FORWARD_BRANCH (CBC_EXT_FOR_IN_INIT, -1 + PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION, VM_OC_FOR_IN_INIT) \ + CBC_OPCODE (CBC_EXT_SET_GETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \ + CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT, 0, VM_OC_FOR_IN_HAS_NEXT) \ + CBC_OPCODE (CBC_EXT_FOR_OF_GET_NEXT, CBC_NO_FLAG, 1, VM_OC_FOR_OF_GET_NEXT | VM_OC_PUT_STACK) \ + CBC_FORWARD_BRANCH (CBC_EXT_FOR_OF_INIT, -1 + PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION, VM_OC_FOR_OF_INIT) \ + CBC_OPCODE (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 1, \ + VM_OC_PUSH_NAMED_FUNC_EXPR | VM_OC_GET_LITERAL_LITERAL) \ + CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT, 0, VM_OC_FOR_OF_HAS_NEXT) \ + CBC_OPCODE (CBC_EXT_CLONE_CONTEXT, CBC_NO_FLAG, 0, VM_OC_CLONE_CONTEXT) \ + CBC_FORWARD_BRANCH (CBC_EXT_FOR_AWAIT_OF_INIT, \ + -1 + PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION, \ + VM_OC_FOR_AWAIT_OF_INIT) \ + CBC_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT, CBC_NO_FLAG, 0, VM_OC_CLONE_CONTEXT) \ + CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT, 0, VM_OC_FOR_AWAIT_OF_HAS_NEXT) \ + CBC_OPCODE (CBC_EXT_SET_SETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \ + CBC_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT, PARSER_TRY_CONTEXT_STACK_ALLOCATION, VM_OC_TRY) \ + CBC_OPCODE (CBC_EXT_TRY_CREATE_ENV, CBC_NO_FLAG, 0, VM_OC_BLOCK_CREATE_CONTEXT) \ + CBC_FORWARD_BRANCH (CBC_EXT_CATCH, 1, VM_OC_CATCH) \ + CBC_OPCODE (CBC_EXT_RESOLVE_BASE, CBC_NO_FLAG, 0, VM_OC_RESOLVE_BASE_FOR_CALL) \ + CBC_FORWARD_BRANCH (CBC_EXT_FINALLY, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION, VM_OC_FINALLY) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP, CBC_NO_FLAG, 0, VM_OC_INITIALIZER_PUSH_PROP) \ + CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, -1, VM_OC_DEFAULT_INITIALIZER) \ + CBC_OPCODE (CBC_EXT_ERROR, CBC_NO_FLAG, 0, VM_OC_ERROR) \ + CBC_FORWARD_BRANCH (CBC_EXT_BRANCH_IF_NULLISH, -1, VM_OC_BRANCH_IF_NULLISH) \ + \ + /* Basic opcodes. */ \ + CBC_OPCODE (CBC_EXT_POP_REFERENCE, CBC_NO_FLAG, -2, VM_OC_POP_REFERENCE) \ + CBC_OPCODE (CBC_EXT_CREATE_ARGUMENTS, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_ARGUMENTS) \ + CBC_OPCODE (CBC_EXT_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_EXT_VAR_EVAL) \ + CBC_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, VM_OC_EXT_VAR_EVAL) \ + CBC_OPCODE (CBC_EXT_COPY_FROM_ARG, CBC_HAS_LITERAL_ARG, 0, VM_OC_COPY_FROM_ARG) \ + CBC_OPCODE (CBC_EXT_PUSH_REST_OBJECT, CBC_NO_FLAG, 1, VM_OC_PUSH_REST_OBJECT) \ + CBC_OPCODE (CBC_EXT_MODULE_IMPORT, CBC_NO_FLAG, 0, VM_OC_MODULE_IMPORT) \ + CBC_OPCODE (CBC_EXT_MODULE_IMPORT_META, CBC_NO_FLAG, 1, VM_OC_MODULE_IMPORT_META) \ + CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1, VM_OC_STRING_CONCAT | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_STRING_CONCAT | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 1, \ + VM_OC_STRING_CONCAT | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, CBC_HAS_BYTE_ARG, 1, VM_OC_GET_TEMPLATE_OBJECT | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1, VM_OC_THROW_REFERENCE_ERROR) \ + CBC_OPCODE (CBC_EXT_THROW_ASSIGN_CONST_ERROR, CBC_NO_FLAG, 0, VM_OC_THROW_CONST_ERROR) \ + CBC_OPCODE (CBC_EXT_REQUIRE_OBJECT_COERCIBLE, CBC_NO_FLAG, 0, VM_OC_REQUIRE_OBJECT_COERCIBLE) \ + CBC_OPCODE (CBC_EXT_COPY_DATA_PROPERTIES, CBC_NO_FLAG, -1, VM_OC_COPY_DATA_PROPERTIES) \ + CBC_OPCODE (CBC_EXT_SET_FUNCTION_NAME, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FUNCTION_NAME | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_CLASS_NAME, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FUNCTION_NAME) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_FUNCTION_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME) \ + \ + /* Computed / class property related opcodes. */ \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY, \ + CBC_NO_FLAG, \ + -2, \ + VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER, \ + CBC_NO_FLAG, \ + -2, \ + VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER, \ + CBC_NO_FLAG, \ + -2, \ + VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY, CBC_HAS_LITERAL_ARG, -1, VM_OC_SET_PROPERTY | VM_OC_GET_STACK_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY, \ + CBC_NO_FLAG, \ + -2, \ + VM_OC_SET_COMPUTED_PROPERTY | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_GETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_GETTER | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_SETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_SETTER | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_GETTER, CBC_NO_FLAG, -2, VM_OC_SET_GETTER | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_NO_FLAG, -2, VM_OC_SET_SETTER | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET__PROTO__, CBC_NO_FLAG, -1, VM_OC_SET__PROTO__ | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_PUSH_STATIC_FIELD_FUNC, \ + CBC_HAS_LITERAL_ARG, \ + 1, \ + VM_OC_PUSH_STATIC_FIELD_FUNC | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_PUSH_STATIC_FIELD_FUNC | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_ADD_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_ADD_COMPUTED_FIELD | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_ADD_STATIC_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_ADD_COMPUTED_FIELD | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_CLASS_CALL_STATIC_BLOCK, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_CLASS_CALL_STATIC_BLOCK | VM_OC_GET_LITERAL) \ + /* Class private property related opcodes */ \ + CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE, \ + CBC_HAS_LITERAL_ARG, \ + 2, \ + VM_OC_PRIVATE_PROP_REFERENCE | VM_OC_GET_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_PRIVATE_PROP_GET | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_PRIVATE_IN | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_PRIVATE_FIELD_ADD, CBC_HAS_LITERAL_ARG, -1, VM_OC_PRIVATE_FIELD_ADD | VM_OC_GET_STACK_LITERAL) \ + /* These 8 opcodes must be in this order */ \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_FIELD, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_METHOD, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_GETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_SETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + /* Class related opcodes. */ \ + CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1, VM_OC_PUSH_CLASS_ENVIRONMENT) \ + CBC_OPCODE (CBC_EXT_DEFINE_FIELD, CBC_HAS_LITERAL_ARG, -1, VM_OC_DEFINE_FIELD | VM_OC_GET_STACK_LITERAL) \ + CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR, CBC_NO_FLAG, 1, VM_OC_PUSH_IMPLICIT_CTOR | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE, CBC_NO_FLAG, 1, VM_OC_PUSH_IMPLICIT_CTOR | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_INIT_CLASS, CBC_NO_FLAG, 0, VM_OC_INIT_CLASS | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_FINALIZE_NAMED_CLASS, CBC_HAS_LITERAL_ARG, -2, VM_OC_FINALIZE_CLASS) \ + CBC_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS, CBC_NO_FLAG, -2, VM_OC_FINALIZE_CLASS) \ + CBC_OPCODE (CBC_EXT_SET_FIELD_INIT, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FIELD_INIT | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_RUN_FIELD_INIT, CBC_NO_FLAG, 0, VM_OC_RUN_FIELD_INIT) \ + CBC_OPCODE (CBC_EXT_RUN_STATIC_FIELD_INIT, CBC_NO_FLAG, -1, VM_OC_RUN_STATIC_FIELD_INIT) \ + CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC, \ + CBC_NO_FLAG, \ + -1, \ + VM_OC_SET_NEXT_COMPUTED_FIELD | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_SET_NEXT_COMPUTED_FIELD | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER, CBC_NO_FLAG, 1, VM_OC_NONE) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR, CBC_NO_FLAG, 1, VM_OC_PUSH_SUPER_CONSTRUCTOR) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP, CBC_NO_FLAG, 0, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE, CBC_NO_FLAG, 2, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1, VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3, VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE, CBC_NO_FLAG, 1, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE, \ + CBC_HAS_LITERAL_ARG, \ + 2, \ + VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT, CBC_NO_FLAG, 0, VM_OC_SET_HOME_OBJECT) \ + CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED, CBC_NO_FLAG, 0, VM_OC_SET_HOME_OBJECT) \ + CBC_OPCODE (CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, 1, VM_OC_OBJECT_LITERAL_HOME_ENV) \ + CBC_OPCODE (CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, -1, VM_OC_OBJECT_LITERAL_HOME_ENV) \ + CBC_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS, CBC_NO_FLAG, 1, VM_OC_RESOLVE_LEXICAL_THIS | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_LOCAL_EVAL, CBC_HAS_BYTE_ARG, 0, VM_OC_LOCAL_EVAL) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER, CBC_NO_FLAG, -3, VM_OC_ASSIGN_SUPER) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_ASSIGN_SUPER | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_BLOCK, CBC_NO_FLAG, -3, VM_OC_ASSIGN_SUPER | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE, CBC_NO_FLAG, -3, VM_OC_ASSIGN_PRIVATE) \ + CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_ASSIGN_PRIVATE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_BLOCK, CBC_NO_FLAG, -3, VM_OC_ASSIGN_PRIVATE | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_EXT_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL) \ + CBC_OPCODE (CBC_EXT_SUPER_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_SUPER_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL) \ + CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_PUSH_RESULT, \ + CBC_HAS_POP_STACK_BYTE_ARG, \ + 0, \ + VM_OC_SUPER_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK) \ + \ + /* Spread / rest operation related opcodes. */ \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SPREAD_ARGUMENTS) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PUSH_RESULT, \ + CBC_HAS_POP_STACK_BYTE_ARG, \ + 0, \ + VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_SPREAD_ARGUMENTS) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_PUSH_RESULT, \ + CBC_HAS_POP_STACK_BYTE_ARG, \ + -2, \ + VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK, \ + CBC_HAS_POP_STACK_BYTE_ARG, \ + -3, \ + VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_EXT_PUSH_SPREAD_ELEMENT, CBC_NO_FLAG, 1, VM_OC_PUSH_SPREAD_ELEMENT) \ + CBC_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_APPEND_ARRAY) \ + CBC_OPCODE (CBC_EXT_REST_INITIALIZER, CBC_NO_FLAG, 1, VM_OC_REST_INITIALIZER) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 1, \ + VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_SPREAD_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \ + \ + /* Iterator related opcodes. */ \ + CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_CREATE, \ + CBC_NO_FLAG, \ + PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION, \ + VM_OC_ITERATOR_CONTEXT_CREATE) \ + CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_END, \ + CBC_NO_FLAG, \ + -PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION, \ + VM_OC_ITERATOR_CONTEXT_END) \ + CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1, VM_OC_ITERATOR_STEP) \ + \ + /* Object initializer related opcodes. */ \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_CREATE, \ + CBC_NO_FLAG, \ + PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION, \ + VM_OC_OBJ_INIT_CONTEXT_CREATE) \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE, \ + CBC_NO_FLAG, \ + PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION, \ + VM_OC_OBJ_INIT_CONTEXT_CREATE) \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_PUSH_REST, CBC_NO_FLAG, 1, VM_OC_OBJ_INIT_PUSH_REST) \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_END, \ + CBC_NO_FLAG, \ + -PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION, \ + VM_OC_OBJ_INIT_CONTEXT_END) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME, CBC_NO_FLAG, 0, VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 1, \ + VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_LITERAL) \ + \ + /* Executable object related opcodes. */ \ + CBC_OPCODE (CBC_EXT_CREATE_GENERATOR, CBC_NO_FLAG, 1, VM_OC_CREATE_GENERATOR) \ + CBC_OPCODE (CBC_EXT_YIELD, CBC_NO_FLAG, 0, VM_OC_YIELD) \ + CBC_OPCODE (CBC_EXT_YIELD_ITERATOR, CBC_NO_FLAG, 0, VM_OC_YIELD) \ + CBC_OPCODE (CBC_EXT_ASYNC_YIELD, CBC_NO_FLAG, 0, VM_OC_ASYNC_YIELD) \ + CBC_OPCODE (CBC_EXT_ASYNC_YIELD_ITERATOR, CBC_NO_FLAG, 0, VM_OC_ASYNC_YIELD_ITERATOR) \ + CBC_OPCODE (CBC_EXT_AWAIT, CBC_NO_FLAG, 0, VM_OC_AWAIT) \ + CBC_OPCODE (CBC_EXT_GENERATOR_AWAIT, CBC_NO_FLAG, 0, VM_OC_GENERATOR_AWAIT) \ + CBC_OPCODE (CBC_EXT_ASYNC_EXIT, CBC_NO_FLAG, 0, VM_OC_ASYNC_EXIT) \ + CBC_OPCODE (CBC_EXT_RETURN, CBC_NO_FLAG, -1, VM_OC_EXT_RETURN | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_RETURN_UNDEFINED, CBC_NO_FLAG, 0, VM_OC_EXT_RETURN) \ + CBC_OPCODE (CBC_EXT_PUSH_NEW_TARGET, CBC_NO_FLAG, 1, VM_OC_PUSH_NEW_TARGET | VM_OC_PUT_STACK) \ + \ + /* Last opcode (not a real opcode). */ \ + CBC_OPCODE (CBC_EXT_END, CBC_NO_FLAG, 0, VM_OC_NONE) + +#define CBC_MAXIMUM_BYTE_VALUE 255 +#define CBC_MAXIMUM_SMALL_VALUE 510 +#define CBC_MAXIMUM_FULL_VALUE 32767 + +#define CBC_PUSH_NUMBER_BYTE_RANGE_END 256 + +#define CBC_HIGHEST_BIT_MASK 0x80 +#define CBC_LOWER_SEVEN_BIT_MASK 0x7f + +/** + * Literal encoding limit when full literal encoding mode is enabled + */ +#define CBC_FULL_LITERAL_ENCODING_LIMIT 128 + +/** + * Literal encoding delta when full literal encoding mode is enabled + */ +#define CBC_FULL_LITERAL_ENCODING_DELTA 0x8000 + +/** + * Literal encoding limit when full literal encoding mode is disabled + */ +#define CBC_SMALL_LITERAL_ENCODING_LIMIT 255 + +/** + * Literal encoding delta when full literal encoding mode is disabled + */ +#define CBC_SMALL_LITERAL_ENCODING_DELTA 0xfe01 + +/** + * Literal indicies belong to one of the following groups: + * + * 0 <= index < argument_end : arguments + * argument_end <= index < register_end : registers + * register_end <= index < ident_end : identifiers + * ident_end <= index < const_literal_end : constant literals + * const_literal_end <= index < literal_end : template literals + */ + +/** + * Compiled byte code arguments. + */ +typedef struct +{ + ecma_compiled_code_t header; /**< compiled code header */ + uint8_t stack_limit; /**< maximum number of values stored on the stack */ + uint8_t argument_end; /**< number of arguments expected by the function */ + ecma_value_t script_value; /**< script value */ + uint8_t register_end; /**< end position of the register group */ + uint8_t ident_end; /**< end position of the identifier group */ + uint8_t const_literal_end; /**< end position of the const literal group */ + uint8_t literal_end; /**< end position of the literal group */ +} cbc_uint8_arguments_t; + +/** + * Compiled byte code arguments. + */ +typedef struct +{ + ecma_compiled_code_t header; /**< compiled code header */ + uint16_t stack_limit; /**< maximum number of values stored on the stack */ + ecma_value_t script_value; /**< script value */ + uint16_t argument_end; /**< number of arguments expected by the function */ + uint16_t register_end; /**< end position of the register group */ + uint16_t ident_end; /**< end position of the identifier group */ + uint16_t const_literal_end; /**< end position of the const literal group */ + uint16_t literal_end; /**< end position of the literal group */ + uint16_t padding; /**< an unused value */ +} cbc_uint16_arguments_t; + +/** + * Compact byte code status flags. + */ +typedef enum +{ + CBC_CODE_FLAGS_FULL_LITERAL_ENCODING = (1u << 0), /**< full literal encoding mode is enabled */ + CBC_CODE_FLAGS_UINT16_ARGUMENTS = (1u << 1), /**< compiled code data is cbc_uint16_arguments_t */ + CBC_CODE_FLAGS_STRICT_MODE = (1u << 2), /**< strict mode is enabled */ + CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED = (1u << 3), /**< mapped arguments object must be constructed */ + CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 4), /**< no need to create a lexical environment */ + CBC_CODE_FLAGS_HAS_EXTENDED_INFO = (1u << 5), /**< this function has extended info block */ + CBC_CODE_FLAGS_HAS_TAGGED_LITERALS = (1u << 6), /**< this function has tagged template literal list */ + CBC_CODE_FLAGS_HAS_LINE_INFO = (1u << 7), /**< this function has line info block */ + CBC_CODE_FLAGS_STATIC_FUNCTION = (1u << 8), /**< this function is a static snapshot function */ + CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 9), /**< this function should be ignored by debugger */ + CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED = (1u << 10), /**< compiled code needs a lexical block */ + + /* Bits from bit 12 is reserved for function types (see CBC_FUNCTION_TYPE_SHIFT). + * Note: the last bits are used for type flags because < and >= operators can be used to + check a range of types without decoding the actual type. */ +} cbc_code_flags_t; + +/** + * Optional byte code fields. These fields are stored in a reversed + * order from the end of the byte code data. + * + * Value fields: + * - when CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED is set: + * argument_end number of argument names encoded as strings + * - when function type is not CBC_FUNCTION_CONSTRUCTOR: + * function name encoded as string + * - when CBC_CODE_FLAGS_HAS_TAGGED_LITERALS is set: + * pointer to the tagged template collection encoded as value + * + * Byte fields when CBC_CODE_FLAGS_HAS_EXTENDED_INFO is set: + * - always available: + * a byte which contains a combination of CBC_EXTENDED_CODE_FLAGS bits + * - when CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH is set: + * a vlq encoded default value for function length + * - when CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE is set: + * a pair of vlq encoded values, representing the start and size of the range + */ + +/** + * Compact byte code function types. + */ +typedef enum +{ + /* The first type must be regular expression (see CBC_IS_FUNCTION) */ + CBC_REGULAR_EXPRESSION, /**< regular expression literal */ + CBC_FUNCTION_NORMAL, /**< function without special properties */ + CBC_FUNCTION_CONSTRUCTOR, /**< constructor function */ + + /* The following functions cannot be constructed (see CBC_FUNCTION_IS_CONSTRUCTABLE) */ + CBC_FUNCTION_SCRIPT, /**< script (global) function */ + CBC_FUNCTION_GENERATOR, /**< generator function */ + CBC_FUNCTION_ASYNC_GENERATOR, /**< async generator function */ + + /* The following functions has no prototype (see CBC_FUNCTION_HAS_PROTOTYPE) */ + CBC_FUNCTION_ACCESSOR, /**< property accessor function */ + CBC_FUNCTION_ASYNC, /**< async function */ + CBC_FUNCTION_METHOD, /**< method */ + + /* The following functions are arrow function (see CBC_FUNCTION_IS_ARROW) */ + CBC_FUNCTION_ARROW, /**< arrow function */ + CBC_FUNCTION_ASYNC_ARROW, /**< arrow function */ +} cbc_code_function_types_t; + +/** + * Shift for getting / setting the function type of a byte code. + */ +#define CBC_FUNCTION_TYPE_SHIFT 12 + +/** + * Compute function type bits in code flags. + */ +#define CBC_FUNCTION_TO_TYPE_BITS(name) ((name) << CBC_FUNCTION_TYPE_SHIFT) + +/** + * Get function type from code flags. + */ +#define CBC_FUNCTION_GET_TYPE(flags) ((uint16_t) ((flags) >> CBC_FUNCTION_TYPE_SHIFT)) + +/** + * Checks whether the byte code is a function or a regular expression. + */ +#define CBC_IS_FUNCTION(flags) ((flags) >= (CBC_FUNCTION_NORMAL << CBC_FUNCTION_TYPE_SHIFT)) + +/** + * Checks whether the function can be constructed with new operator. + */ +#define CBC_FUNCTION_IS_CONSTRUCTABLE(flags) ((flags) < (CBC_FUNCTION_GENERATOR << CBC_FUNCTION_TYPE_SHIFT)) + +/** + * Checks whether the function has prototype property. + */ +#define CBC_FUNCTION_HAS_PROTOTYPE(flags) ((flags) < (CBC_FUNCTION_ACCESSOR << CBC_FUNCTION_TYPE_SHIFT)) + +/** + * Checks whether the function is an arrow function. + */ +#define CBC_FUNCTION_IS_ARROW(flags) ((flags) >= (CBC_FUNCTION_ARROW << CBC_FUNCTION_TYPE_SHIFT)) + +/** + * Compact byte code extended status flags. + */ +typedef enum +{ + CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH = (1u << 0), /**< has argument length */ + CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE = (1u << 1), /**< has source code range (start, end) */ + CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS = (1u << 2), /**< source code range is inside + * the function arguments */ +} cbc_extended_code_flags_t; + +/** + * Shared script data. + */ +typedef enum +{ + CBC_SCRIPT_HAS_USER_VALUE = (1 << 0), /**< script has user value */ + CBC_SCRIPT_USER_VALUE_IS_OBJECT = (1 << 1), /**< user value is object */ + CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS = (1 << 2), /**< script is a function with arguments source code */ + CBC_SCRIPT_HAS_IMPORT_META = (1 << 3), /**< script is a module with import.meta object */ + CBC_SCRIPT_IS_EVAL_CODE = (1 << 4), /**< script is compiled by eval like (eval, new Function, etc.) expression */ +} cbc_script_type; + +/** + * Value for increasing or decreasing the script reference counter. + */ +#define CBC_SCRIPT_REF_ONE 0x20 + +/** + * Maximum value of script reference counter. + */ +#define CBC_SCRIPT_REF_MAX (UINT32_MAX - CBC_SCRIPT_REF_ONE + 1) + +/** + * Sets the type of a script using the user_value. + */ +#define CBC_SCRIPT_SET_TYPE(script_p, user_value, ref_count) \ + do \ + { \ + (script_p)->refs_and_type = (ref_count); \ + if ((user_value) != ECMA_VALUE_EMPTY) \ + { \ + (script_p)->refs_and_type |= CBC_SCRIPT_HAS_USER_VALUE; \ + if (ecma_is_value_object (user_value)) \ + { \ + (script_p)->refs_and_type |= CBC_SCRIPT_USER_VALUE_IS_OBJECT; \ + } \ + } \ + } while (false) + +/** + * Shared script data. + */ +typedef struct +{ +#if JERRY_BUILTIN_REALMS + ecma_object_t *realm_p; /**< realm object */ +#endif /* JERRY_BUILTIN_REALMS */ + uint32_t refs_and_type; /**< reference counter and type of the function */ +#if JERRY_SOURCE_NAME + ecma_value_t source_name; /**< source name */ +#endif /* JERRY_SOURCE_NAME */ +#if JERRY_FUNCTION_TO_STRING + ecma_value_t source_code; /**< source code */ +#endif /* JERRY_FUNCTION_TO_STRING */ +} cbc_script_t; + +/** + * Get the array of optional values assigned to a script. + * + * First value: user value + * Second value: function arguments value + */ +#define CBC_SCRIPT_GET_OPTIONAL_VALUES(script_p) ((ecma_value_t *) ((script_p) + 1)) + +/** + * Get user value. + */ +#define CBC_SCRIPT_GET_USER_VALUE(script_p) (CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[0]) + +/** + * Get function arguments. + */ +#define CBC_SCRIPT_GET_FUNCTION_ARGUMENTS(script_p, type) \ + (CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[((type) &CBC_SCRIPT_HAS_USER_VALUE) ? 1 : 0]) + +/** + * Get import.meta object. + */ +#define CBC_SCRIPT_GET_IMPORT_META(script_p, type) \ + (CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[((type) &CBC_SCRIPT_HAS_USER_VALUE) ? 1 : 0]) + +#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1, + +/** + * Opcode list. + */ +typedef enum +{ + CBC_OPCODE_LIST /**< list of opcodes */ +} cbc_opcode_t; + +/** + * Extended opcode list. + */ +typedef enum +{ + CBC_EXT_OPCODE_LIST /**< list extended opcodes */ +} cbc_ext_opcode_t; + +#undef CBC_OPCODE + +/** + * Opcode flags. + */ +extern const uint8_t cbc_flags[]; +extern const uint8_t cbc_ext_flags[]; + +#if JERRY_PARSER_DUMP_BYTE_CODE + +/** + * Opcode names for debugging. + */ +extern const char *const cbc_names[]; +extern const char *const cbc_ext_names[]; + +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ + +#endif /* !BYTE_CODE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.cpp new file mode 100644 index 00000000..eafd1677 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.cpp @@ -0,0 +1,550 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#include "ecma-big-uint.h" +#include "ecma-bigint.h" +#include "ecma-extended-info.h" +#include "ecma-helpers.h" + +#include "js-parser-internal.h" +#include "lit-char-helpers.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_utils Utility + * @{ + */ + +#if JERRY_PARSER + +/** + * Free literal. + */ +void +util_free_literal (lexer_literal_t *literal_p) /**< literal */ +{ + if (literal_p->type == LEXER_IDENT_LITERAL || literal_p->type == LEXER_STRING_LITERAL) + { + if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR)) + { + jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length); + } + } + else if ((literal_p->type == LEXER_FUNCTION_LITERAL) || (literal_p->type == LEXER_REGEXP_LITERAL)) + { + ecma_bytecode_deref (literal_p->u.bytecode_p); + } +} /* util_free_literal */ + +#endif /* JERRY_PARSER */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + +/** + * Debug utility to print a character sequence. + */ +static void +util_print_chars (const uint8_t *char_p, /**< character pointer */ + size_t size) /**< size */ +{ + while (size > 0) + { + JERRY_DEBUG_MSG ("%c", *char_p++); + size--; + } +} /* util_print_chars */ + +/** + * Debug utility to print a number. + */ +static void +util_print_number (ecma_number_t num_p) /**< number to print */ +{ + lit_utf8_byte_t str_buf[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; + lit_utf8_size_t str_size = ecma_number_to_utf8_string (num_p, str_buf, sizeof (str_buf)); + str_buf[str_size] = 0; + JERRY_DEBUG_MSG ("%s", str_buf); +} /* util_print_number */ + +#if JERRY_BUILTIN_BIGINT + +/** + * Debug utility to print a bigint. + */ +static void +util_print_bigint (ecma_value_t bigint) /**< bigint to print */ +{ + if (bigint == ECMA_BIGINT_ZERO) + { + JERRY_DEBUG_MSG ("0"); + return; + } + + ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (bigint); + uint32_t char_start_p, char_size_p; + lit_utf8_byte_t *string_buffer_p = ecma_big_uint_to_string (bigint_p, 10, &char_start_p, &char_size_p); + + if (JERRY_UNLIKELY (string_buffer_p == NULL)) + { + JERRY_DEBUG_MSG (""); + return; + } + + JERRY_ASSERT (char_start_p > 0); + + if (bigint_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + string_buffer_p[--char_start_p] = LIT_CHAR_MINUS; + } + + util_print_chars (string_buffer_p + char_start_p, char_size_p - char_start_p); + jmem_heap_free_block (string_buffer_p, char_size_p); +} /* util_print_bigint */ + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Print literal + */ +void +util_print_literal (lexer_literal_t *literal_p) /**< literal */ +{ + switch (literal_p->type) + { + case LEXER_IDENT_LITERAL: + { + JERRY_DEBUG_MSG ("ident("); + util_print_chars (literal_p->u.char_p, literal_p->prop.length); + break; + } + case LEXER_FUNCTION_LITERAL: + { + JERRY_DEBUG_MSG ("function"); + return; + } + case LEXER_STRING_LITERAL: + { + JERRY_DEBUG_MSG ("string("); + util_print_chars (literal_p->u.char_p, literal_p->prop.length); + break; + } + case LEXER_NUMBER_LITERAL: + { +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (literal_p->u.value)) + { + JERRY_DEBUG_MSG ("bigint("); + util_print_bigint (literal_p->u.value); + break; + } +#endif /* JERRY_BUILTIN_BIGINT */ + JERRY_DEBUG_MSG ("number("); + util_print_number (ecma_get_number_from_value (literal_p->u.value)); + break; + } + case LEXER_REGEXP_LITERAL: + { + JERRY_DEBUG_MSG ("regexp"); + return; + } + default: + { + JERRY_DEBUG_MSG ("unknown"); + return; + } + } + + JERRY_DEBUG_MSG (")"); +} /* util_print_literal */ + +/** + * Print literal. + */ +static void +util_print_literal_value (ecma_compiled_code_t *compiled_code_p, /**< compiled code */ + uint16_t literal_index) /**< literal index */ +{ + uint16_t argument_end; + uint16_t register_end; + uint16_t ident_end; + uint16_t const_literal_end; + ecma_value_t *literal_start_p; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p; + argument_end = args_p->argument_end; + register_end = args_p->register_end; + ident_end = args_p->ident_end; + const_literal_end = args_p->const_literal_end; + literal_start_p = (ecma_value_t *) (args_p + 1); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p; + argument_end = args_p->argument_end; + register_end = args_p->register_end; + ident_end = args_p->ident_end; + const_literal_end = args_p->const_literal_end; + literal_start_p = (ecma_value_t *) (args_p + 1); + } + + if (literal_index < argument_end) + { + JERRY_DEBUG_MSG (" arg:%d", literal_index); + return; + } + + if (literal_index < register_end) + { + JERRY_DEBUG_MSG (" reg:%d", literal_index); + return; + } + + if (literal_index >= const_literal_end) + { + JERRY_DEBUG_MSG (" lit:%d", literal_index); + return; + } + + if (literal_index < ident_end) + { + JERRY_DEBUG_MSG (" ident:%d->", literal_index); + } + else + { + JERRY_DEBUG_MSG (" const:%d->", literal_index); + } + + ecma_value_t value = literal_start_p[literal_index - register_end]; + + if (ecma_is_value_number (value)) + { + JERRY_DEBUG_MSG ("number("); + util_print_number (ecma_get_number_from_value (value)); + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (value)) + { + JERRY_DEBUG_MSG ("bigint("); + util_print_bigint (value); + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + ecma_string_t *literal_p = ecma_get_string_from_value (value); + + JERRY_DEBUG_MSG ("string("); + + ECMA_STRING_TO_UTF8_STRING (literal_p, chars_p, literal_size); + util_print_chars (chars_p, literal_size); + ECMA_FINALIZE_UTF8_STRING (chars_p, literal_size); + } + + JERRY_DEBUG_MSG (")"); +} /* util_print_literal_value */ + +#define PARSER_READ_IDENTIFIER_INDEX(name) \ + name = *byte_code_p++; \ + if (name >= encoding_limit) \ + { \ + name = (uint16_t) (((name << 8) | byte_code_p[0]) - encoding_delta); \ + byte_code_p++; \ + } + +/** + * Print byte code. + */ +void +util_print_cbc (ecma_compiled_code_t *compiled_code_p) /**< compiled code */ +{ + uint8_t flags; + uint8_t *byte_code_start_p; + uint8_t *byte_code_end_p; + uint8_t *byte_code_p; + uint16_t encoding_limit; + uint16_t encoding_delta; + uint16_t stack_limit; + uint16_t argument_end; + uint16_t register_end; + uint16_t ident_end; + uint16_t const_literal_end; + uint16_t literal_end; + size_t size = ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args = (cbc_uint16_arguments_t *) compiled_code_p; + stack_limit = args->stack_limit; + argument_end = args->argument_end; + register_end = args->register_end; + ident_end = args->ident_end; + const_literal_end = args->const_literal_end; + literal_end = args->literal_end; + } + else + { + cbc_uint8_arguments_t *args = (cbc_uint8_arguments_t *) compiled_code_p; + stack_limit = args->stack_limit; + argument_end = args->argument_end; + register_end = args->register_end; + ident_end = args->ident_end; + const_literal_end = args->const_literal_end; + literal_end = args->literal_end; + } + + JERRY_DEBUG_MSG ("\nByte code dump:\n\n Maximum stack depth: %d\n Flags: [", (int) (stack_limit + register_end)); + + if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) + { + JERRY_DEBUG_MSG ("small_lit_enc"); + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + else + { + JERRY_DEBUG_MSG ("full_lit_enc"); + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + JERRY_DEBUG_MSG (",uint16_arguments"); + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) + { + JERRY_DEBUG_MSG (",strict_mode"); + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + JERRY_DEBUG_MSG (",mapped_arguments_needed"); + size -= argument_end * sizeof (ecma_value_t); + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) + { + JERRY_DEBUG_MSG (",no_lexical_env"); + } + + switch (CBC_FUNCTION_GET_TYPE (compiled_code_p->status_flags)) + { + case CBC_FUNCTION_CONSTRUCTOR: + { + JERRY_DEBUG_MSG (",constructor"); + break; + } + case CBC_FUNCTION_GENERATOR: + { + JERRY_DEBUG_MSG (",generator"); + break; + } + case CBC_FUNCTION_ASYNC: + { + JERRY_DEBUG_MSG (",async"); + break; + } + case CBC_FUNCTION_ASYNC_GENERATOR: + { + JERRY_DEBUG_MSG (",async_generator"); + break; + } + case CBC_FUNCTION_ACCESSOR: + { + JERRY_DEBUG_MSG (",accessor"); + break; + } + case CBC_FUNCTION_ARROW: + { + JERRY_DEBUG_MSG (",arrow"); + break; + } + case CBC_FUNCTION_ASYNC_ARROW: + { + JERRY_DEBUG_MSG (",async_arrow"); + break; + } + } + + JERRY_DEBUG_MSG ("]\n"); + + JERRY_DEBUG_MSG (" Argument range end: %d\n", (int) argument_end); + JERRY_DEBUG_MSG (" Register range end: %d\n", (int) register_end); + JERRY_DEBUG_MSG (" Identifier range end: %d\n", (int) ident_end); + JERRY_DEBUG_MSG (" Const literal range end: %d\n", (int) const_literal_end); + JERRY_DEBUG_MSG (" Literal range end: %d\n\n", (int) literal_end); + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) + { + uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (compiled_code_p); + uint8_t *extended_info_start_p = extended_info_p + sizeof (uint8_t); + uint8_t extended_info = *extended_info_p; + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) + { + uint32_t argument_length = ecma_extended_info_decode_vlq (&extended_info_p); + JERRY_DEBUG_MSG (" [Extended] Argument length: %d\n", (int) argument_length); + } + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE) + { + uint32_t range_start = ecma_extended_info_decode_vlq (&extended_info_p); + uint32_t range_end = ecma_extended_info_decode_vlq (&extended_info_p) + range_start; + JERRY_DEBUG_MSG (" [Extended] Source code range: %d - %d\n", (int) range_start, (int) range_end); + } + + JERRY_DEBUG_MSG ("\n"); + + size -= (size_t) (extended_info_start_p - extended_info_p); + } + + byte_code_start_p = (uint8_t *) compiled_code_p; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + byte_code_start_p += sizeof (cbc_uint16_arguments_t); + } + else + { + byte_code_start_p += sizeof (cbc_uint8_arguments_t); + } + + byte_code_start_p += (unsigned int) (literal_end - register_end) * sizeof (ecma_value_t); + + if (CBC_FUNCTION_GET_TYPE (compiled_code_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR) + { + size -= sizeof (ecma_value_t); + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS) + { + size -= sizeof (ecma_value_t); + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO) + { + size -= sizeof (ecma_value_t); + } + + byte_code_end_p = ((uint8_t *) compiled_code_p) + size; + byte_code_p = byte_code_start_p; + + while (byte_code_p < byte_code_end_p) + { + cbc_opcode_t opcode = (cbc_opcode_t) *byte_code_p; + cbc_ext_opcode_t ext_opcode = CBC_EXT_NOP; + size_t cbc_offset = (size_t) (byte_code_p - byte_code_start_p); + + if (opcode != CBC_EXT_OPCODE) + { + flags = cbc_flags[opcode]; + JERRY_DEBUG_MSG (" %3d : %s", (int) cbc_offset, cbc_names[opcode]); + byte_code_p++; + } + else + { + if (byte_code_p + 1 >= byte_code_end_p) + { + break; + } + + ext_opcode = (cbc_ext_opcode_t) byte_code_p[1]; + + if (ext_opcode == CBC_EXT_NOP) + { + break; + } + + flags = cbc_ext_flags[ext_opcode]; + JERRY_DEBUG_MSG (" %3d : %s", (int) cbc_offset, cbc_ext_names[ext_opcode]); + byte_code_p += 2; + } + + if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)) + { + uint16_t literal_index; + + PARSER_READ_IDENTIFIER_INDEX (literal_index); + util_print_literal_value (compiled_code_p, literal_index); + } + + if (flags & CBC_HAS_LITERAL_ARG2) + { + uint16_t literal_index; + + PARSER_READ_IDENTIFIER_INDEX (literal_index); + util_print_literal_value (compiled_code_p, literal_index); + + if (!(flags & CBC_HAS_LITERAL_ARG)) + { + PARSER_READ_IDENTIFIER_INDEX (literal_index); + util_print_literal_value (compiled_code_p, literal_index); + } + } + + if (flags & CBC_HAS_BYTE_ARG) + { + if (opcode == CBC_PUSH_NUMBER_POS_BYTE || opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) + { + JERRY_DEBUG_MSG (" number:%d", (int) *byte_code_p + 1); + } + else if (opcode == CBC_PUSH_NUMBER_NEG_BYTE || opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE) + { + JERRY_DEBUG_MSG (" number:%d", -((int) *byte_code_p + 1)); + } + else + { + JERRY_DEBUG_MSG (" byte_arg:%d", *byte_code_p); + } + byte_code_p++; + } + + if (flags & CBC_HAS_BRANCH_ARG) + { + size_t branch_offset_length = + (opcode != CBC_EXT_OPCODE ? CBC_BRANCH_OFFSET_LENGTH (opcode) : CBC_BRANCH_OFFSET_LENGTH (ext_opcode)); + size_t offset = 0; + + do + { + offset = (offset << 8) | *byte_code_p++; + } while (--branch_offset_length > 0); + + JERRY_DEBUG_MSG (" offset:%d(->%d)", + (int) offset, + (int) (cbc_offset + (CBC_BRANCH_IS_FORWARD (flags) ? offset : -offset))); + } + + JERRY_DEBUG_MSG ("\n"); + } +} /* util_print_cbc */ + +#undef PARSER_READ_IDENTIFIER_INDEX + +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.h new file mode 100644 index 00000000..3ebdbbe4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.h @@ -0,0 +1,162 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_utils Utility + * @{ + */ + +#include "ecma-globals.h" +#include "ecma-regexp-object.h" + +#include "jerry-config.h" +#include "jmem.h" + +/* Immediate management. */ + +/** + * Literal types. + * + * The LEXER_UNUSED_LITERAL type is internal and + * used for various purposes. + */ +typedef enum +{ + /* The LEXER_IS_IDENT_OR_STRING macro must be updated if the order is changed. */ + LEXER_IDENT_LITERAL = 0, /**< identifier literal */ + LEXER_STRING_LITERAL = 1, /**< string literal */ + LEXER_NUMBER_LITERAL = 2, /**< number literal */ + LEXER_FUNCTION_LITERAL = 3, /**< function literal */ + LEXER_REGEXP_LITERAL = 4, /**< regexp literal */ + LEXER_UNUSED_LITERAL = 5, /**< unused literal, can only be + used by the byte code generator. */ + LEXER_NEW_IDENT_LITERAL = 6, /**< new local variable, can only be + used by the byte code generator. */ +} lexer_literal_type_t; + +/** + * Checks whether the literal type is identifier or string. + */ +#define LEXER_IS_IDENT_OR_STRING(literal_type) ((literal_type) <= LEXER_STRING_LITERAL) + +/** + * Flag bits for status_flags member of lexer_literal_t. + */ +typedef enum +{ + LEXER_FLAG_USED = (1 << 0), /**< this local identifier needs to be stored in the constant pool */ + LEXER_FLAG_FUNCTION_ARGUMENT = (1 << 1), /**< this local identifier is a function argument */ + LEXER_FLAG_SOURCE_PTR = (1 << 2), /**< the literal is directly referenced in the source code + * (no need to allocate memory) */ + LEXER_FLAG_LATE_INIT = (1 << 3), /**< initialize this variable after the byte code is freed */ + LEXER_FLAG_ASCII = (1 << 4), /**< the literal contains only ascii characters */ + LEXER_FLAG_GLOBAL = (1 << 5), /**< this local identifier is not a let or const declaration */ +} lexer_literal_status_flags_t; + +/** + * Type of property length. + */ +#if JERRY_CPOINTER_32_BIT +typedef uint32_t prop_length_t; +#else /* !JERRY_CPOINTER_32_BIT */ +typedef uint16_t prop_length_t; +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Literal data. + */ +typedef struct +{ + union + { + ecma_value_t value; /**< literal value (not processed by the parser) */ + const uint8_t *char_p; /**< character value */ + ecma_compiled_code_t *bytecode_p; /**< compiled function or regexp pointer */ + uint32_t source_data; /**< encoded source literal */ + } u; + +#if JERRY_PARSER_DUMP_BYTE_CODE + struct +#else /* !JERRY_PARSER_DUMP_BYTE_CODE */ + union +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + { + prop_length_t length; /**< length of ident / string literal */ + uint16_t index; /**< real index during post processing */ + } prop; + + uint8_t type; /**< type of the literal */ + uint8_t status_flags; /**< status flags */ +} lexer_literal_t; + +void util_free_literal (lexer_literal_t *literal_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE +void util_print_literal (lexer_literal_t *); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * Source code line counter type. + */ +typedef uint32_t parser_line_counter_t; + +/** + * Source code as character data. + */ +typedef struct +{ + const uint8_t *source_p; /**< valid UTF-8 source code */ + size_t source_size; /**< size of the source code */ +} parser_source_char_t; + +/* TRY/CATCH block */ + +#define PARSER_TRY_CONTEXT(context_name) jmp_buf context_name + +#define PARSER_THROW(context_name) longjmp (context_name, 1); + +#define PARSER_TRY(context_name) \ + { \ + if (!setjmp (context_name)) \ + { +#define PARSER_CATCH \ + } \ + else \ + { +#define PARSER_TRY_END \ + } \ + } + +/** + * @} + * @} + * @} + */ + +#endif /* !COMMON_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.cpp new file mode 100644 index 00000000..c6c2db64 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.cpp @@ -0,0 +1,3622 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-bigint.h" +#include "ecma-function-object.h" +#include "ecma-helpers.h" +#include "ecma-literal-storage.h" + +#include "jcontext.h" +#include "js-parser-internal.h" +#include "lit-char-helpers.h" + +#if JERRY_PARSER + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_lexer Lexer + * @{ + */ + +JERRY_STATIC_ASSERT (((int)LEXER_NUMBER_BINARY > (int)LEXER_NUMBER_OCTAL), + lexer_number_binary_must_be_greater_than_lexer_number_octal); + +/** + * Check whether the UTF-8 intermediate is an octet or not + */ +#define IS_UTF8_INTERMEDIATE_OCTET(byte) (((byte) &LIT_UTF8_EXTRA_BYTE_MASK) == LIT_UTF8_2_BYTE_CODE_POINT_MIN) + +/** + * Align column to the next tab position. + * + * @return aligned position + */ +static parser_line_counter_t +align_column_to_tab (parser_line_counter_t column) /**< current column */ +{ + /* Tab aligns to zero column start position. */ + return (parser_line_counter_t) (((column + (8u - 1u)) & ~ECMA_STRING_CONTAINER_MASK) + 1u); +} /* align_column_to_tab */ + +/** + * Parse hexadecimal character sequence + * + * @return character value or UINT32_MAX on error + */ +static lit_code_point_t +lexer_hex_to_code_point (const uint8_t *source_p, /**< current source position */ + parser_line_counter_t length) /**< source length */ +{ + lit_code_point_t result = 0; + + do + { + uint32_t byte = *source_p++; + + result <<= 4; + + if (byte >= LIT_CHAR_0 && byte <= LIT_CHAR_9) + { + result += byte - LIT_CHAR_0; + } + else + { + byte = LEXER_TO_ASCII_LOWERCASE (byte); + if (byte >= LIT_CHAR_LOWERCASE_A && byte <= LIT_CHAR_LOWERCASE_F) + { + result += byte - (LIT_CHAR_LOWERCASE_A - 10); + } + else + { + return UINT32_MAX; + } + } + } while (--length > 0); + + return result; +} /* lexer_hex_to_code_point */ + +/** + * Parse hexadecimal character sequence enclosed in braces + * + * @return character value or UINT32_MAX on error + */ +static lit_code_point_t +lexer_hex_in_braces_to_code_point (const uint8_t *source_p, /**< current source position */ + const uint8_t *source_end_p, /**< source end */ + uint32_t *length_p) /**< [out] length of the sequence */ +{ + lit_code_point_t result = 0; + /* Four is the size of \u{} sequence. */ + uint32_t length = 4; + + JERRY_ASSERT (source_p[-1] == LIT_CHAR_LEFT_BRACE); + JERRY_ASSERT (source_p < source_end_p); + + do + { + uint32_t byte = *source_p++; + + result <<= 4; + + if (byte >= LIT_CHAR_0 && byte <= LIT_CHAR_9) + { + result += byte - LIT_CHAR_0; + } + else + { + byte = LEXER_TO_ASCII_LOWERCASE (byte); + if (byte >= LIT_CHAR_LOWERCASE_A && byte <= LIT_CHAR_LOWERCASE_F) + { + result += byte - (LIT_CHAR_LOWERCASE_A - 10); + } + else + { + return UINT32_MAX; + } + } + + if (result >= (LIT_UNICODE_CODE_POINT_MAX + 1) || source_p >= source_end_p) + { + return UINT32_MAX; + } + length++; + } while (*source_p != LIT_CHAR_RIGHT_BRACE); + + *length_p = length; + return result; +} /* lexer_hex_in_braces_to_code_point */ + +/** + * Parse hexadecimal character sequence + * + * @return character value + */ +static lit_code_point_t +lexer_unchecked_hex_to_character (const uint8_t **source_p) /**< [in, out] current source position */ +{ + lit_code_point_t result = 0; + const uint8_t *char_p = *source_p; + uint32_t length = (char_p[-1] == LIT_CHAR_LOWERCASE_U) ? 4 : 2; + + if (char_p[0] == LIT_CHAR_LEFT_BRACE) + { + length = 0; + char_p++; + } + + while (true) + { + uint32_t byte = *char_p++; + + result <<= 4; + + if (byte >= LIT_CHAR_0 && byte <= LIT_CHAR_9) + { + result += byte - LIT_CHAR_0; + } + else + { + JERRY_ASSERT ((byte >= LIT_CHAR_LOWERCASE_A && byte <= LIT_CHAR_LOWERCASE_F) + || (byte >= LIT_CHAR_UPPERCASE_A && byte <= LIT_CHAR_UPPERCASE_F)); + + result += LEXER_TO_ASCII_LOWERCASE (byte) - (LIT_CHAR_LOWERCASE_A - 10); + } + + JERRY_ASSERT (result <= LIT_UNICODE_CODE_POINT_MAX); + + if (length == 0) + { + if (*char_p != LIT_CHAR_RIGHT_BRACE) + { + continue; + } + + *source_p = char_p + 1; + return result; + } + + if (--length == 0) + { + *source_p = char_p; + return result; + } + } +} /* lexer_unchecked_hex_to_character */ + +/** + * Skip space mode + */ +typedef enum +{ + LEXER_SKIP_SPACES, /**< skip spaces mode */ + LEXER_SKIP_SINGLE_LINE_COMMENT, /**< parse single line comment */ + LEXER_SKIP_MULTI_LINE_COMMENT, /**< parse multi line comment */ +} skip_mode_t; + +/** + * Skip spaces. + */ +static void +lexer_skip_spaces (parser_context_t *context_p) /**< context */ +{ + skip_mode_t mode = LEXER_SKIP_SPACES; + const uint8_t *source_end_p = context_p->source_end_p; + + if (context_p->token.flags & LEXER_NO_SKIP_SPACES) + { + context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES; + return; + } + + context_p->token.flags = 0; + + while (true) + { + if (context_p->source_p >= source_end_p) + { + if (mode == LEXER_SKIP_MULTI_LINE_COMMENT) + { + parser_raise_error (context_p, PARSER_ERR_UNTERMINATED_MULTILINE_COMMENT); + } + return; + } + + switch (context_p->source_p[0]) + { + case LIT_CHAR_CR: + { + if (context_p->source_p + 1 < source_end_p && context_p->source_p[1] == LIT_CHAR_LF) + { + context_p->source_p++; + } + /* FALLTHRU */ + } + + case LIT_CHAR_LF: + { + context_p->line++; + context_p->column = 0; + context_p->token.flags = LEXER_WAS_NEWLINE; + + if (mode == LEXER_SKIP_SINGLE_LINE_COMMENT) + { + mode = LEXER_SKIP_SPACES; + } + /* FALLTHRU */ + } + + case LIT_CHAR_VTAB: + case LIT_CHAR_FF: + case LIT_CHAR_SP: + { + context_p->source_p++; + context_p->column++; + continue; + } + + case LIT_CHAR_TAB: + { + context_p->column = align_column_to_tab (context_p->column); + context_p->source_p++; + continue; + } + + case LIT_CHAR_SLASH: + { + if (mode == LEXER_SKIP_SPACES && context_p->source_p + 1 < source_end_p) + { + if (context_p->source_p[1] == LIT_CHAR_SLASH) + { + mode = LEXER_SKIP_SINGLE_LINE_COMMENT; + } + else if (context_p->source_p[1] == LIT_CHAR_ASTERISK) + { + mode = LEXER_SKIP_MULTI_LINE_COMMENT; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + } + + if (mode != LEXER_SKIP_SPACES) + { + context_p->source_p += 2; + PARSER_PLUS_EQUAL_LC (context_p->column, 2); + continue; + } + } + break; + } + + case LIT_CHAR_ASTERISK: + { + if (mode == LEXER_SKIP_MULTI_LINE_COMMENT && context_p->source_p + 1 < source_end_p + && context_p->source_p[1] == LIT_CHAR_SLASH) + { + mode = LEXER_SKIP_SPACES; + context_p->source_p += 2; + PARSER_PLUS_EQUAL_LC (context_p->column, 2); + continue; + } + break; + } + + case 0xc2: + { + if (context_p->source_p + 1 < source_end_p && context_p->source_p[1] == 0xa0) + { + /* Codepoint \u00A0 */ + context_p->source_p += 2; + context_p->column++; + continue; + } + break; + } + + case LEXER_NEWLINE_LS_PS_BYTE_1: + { + JERRY_ASSERT (context_p->source_p + 2 < source_end_p); + if (LEXER_NEWLINE_LS_PS_BYTE_23 (context_p->source_p)) + { + /* Codepoint \u2028 and \u2029 */ + context_p->source_p += 3; + context_p->line++; + context_p->column = 1; + context_p->token.flags = LEXER_WAS_NEWLINE; + + if (mode == LEXER_SKIP_SINGLE_LINE_COMMENT) + { + mode = LEXER_SKIP_SPACES; + } + continue; + } + break; + } + + case 0xef: + { + if (context_p->source_p + 2 < source_end_p && context_p->source_p[1] == 0xbb && context_p->source_p[2] == 0xbf) + { + /* Codepoint \uFEFF */ + context_p->source_p += 3; + context_p->column++; + continue; + } + break; + } + + default: + { + break; + } + } + + if (mode == LEXER_SKIP_SPACES) + { + return; + } + + context_p->source_p++; + + if (context_p->source_p < source_end_p && !IS_UTF8_INTERMEDIATE_OCTET (context_p->source_p[0])) + { + context_p->column++; + } + } +} /* lexer_skip_spaces */ + +/** + * Skip all the continuous empty statements. + */ +void +lexer_skip_empty_statements (parser_context_t *context_p) /**< context */ +{ + lexer_skip_spaces (context_p); + + while (context_p->source_p < context_p->source_end_p && *context_p->source_p == LIT_CHAR_SEMICOLON) + { + lexer_consume_next_character (context_p); + lexer_skip_spaces (context_p); + } + + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); +} /* lexer_skip_empty_statements */ + +/** + * Checks whether the keyword has escape sequences. + */ +#define LEXER_CHECK_INVALID_KEYWORD(ident_start_p, buffer_p) \ + (JERRY_UNLIKELY ((ident_start_p) == (buffer_p)) \ + && !(context_p->global_status_flags & ECMA_PARSE_INTERNAL_PRE_SCANNING)) + +/** + * Keyword data. + */ +typedef struct +{ + const uint8_t *keyword_p; /**< keyword string */ + lexer_token_type_t type; /**< keyword token type */ +} keyword_string_t; + +/** + * @{ + * Keyword defines + */ +#define LEXER_KEYWORD(name, type) \ + { \ + (const uint8_t *) (name), (type) \ + } +#define LEXER_KEYWORD_LIST_LENGTH(name) (const uint8_t) (sizeof ((name)) / sizeof ((name)[0])) +/** @} */ + +/** + * Length of the shortest keyword. + */ +#define LEXER_KEYWORD_MIN_LENGTH 2 + +/** + * Length of the longest keyword. + */ +#define LEXER_KEYWORD_MAX_LENGTH 10 + +/** + * Keywords with 2 characters. + */ +static const keyword_string_t keywords_with_length_2[] = { + LEXER_KEYWORD ("do", LEXER_KEYW_DO), + LEXER_KEYWORD ("if", LEXER_KEYW_IF), + LEXER_KEYWORD ("in", LEXER_KEYW_IN), +}; + +/** + * Keywords with 3 characters. + */ +static const keyword_string_t keywords_with_length_3[] = { + LEXER_KEYWORD ("for", LEXER_KEYW_FOR), LEXER_KEYWORD ("let", LEXER_KEYW_LET), LEXER_KEYWORD ("new", LEXER_KEYW_NEW), + LEXER_KEYWORD ("try", LEXER_KEYW_TRY), LEXER_KEYWORD ("var", LEXER_KEYW_VAR), +}; + +/** + * Keywords with 4 characters. + */ +static const keyword_string_t keywords_with_length_4[] = { + LEXER_KEYWORD ("case", LEXER_KEYW_CASE), LEXER_KEYWORD ("else", LEXER_KEYW_ELSE), + LEXER_KEYWORD ("enum", LEXER_KEYW_ENUM), LEXER_KEYWORD ("eval", LEXER_KEYW_EVAL), +#if JERRY_MODULE_SYSTEM + LEXER_KEYWORD ("meta", LEXER_KEYW_META), +#endif /* JERRY_MODULE_SYSTEM */ + LEXER_KEYWORD ("null", LEXER_LIT_NULL), LEXER_KEYWORD ("this", LEXER_KEYW_THIS), + LEXER_KEYWORD ("true", LEXER_LIT_TRUE), LEXER_KEYWORD ("void", LEXER_KEYW_VOID), + LEXER_KEYWORD ("with", LEXER_KEYW_WITH), +}; + +/** + * Keywords with 5 characters. + */ +static const keyword_string_t keywords_with_length_5[] = { + LEXER_KEYWORD ("async", LEXER_KEYW_ASYNC), LEXER_KEYWORD ("await", LEXER_KEYW_AWAIT), + LEXER_KEYWORD ("break", LEXER_KEYW_BREAK), LEXER_KEYWORD ("catch", LEXER_KEYW_CATCH), + LEXER_KEYWORD ("class", LEXER_KEYW_CLASS), LEXER_KEYWORD ("const", LEXER_KEYW_CONST), + LEXER_KEYWORD ("false", LEXER_LIT_FALSE), LEXER_KEYWORD ("super", LEXER_KEYW_SUPER), + LEXER_KEYWORD ("throw", LEXER_KEYW_THROW), LEXER_KEYWORD ("while", LEXER_KEYW_WHILE), + LEXER_KEYWORD ("yield", LEXER_KEYW_YIELD), +}; + +/** + * Keywords with 6 characters. + */ +static const keyword_string_t keywords_with_length_6[] = { + LEXER_KEYWORD ("delete", LEXER_KEYW_DELETE), LEXER_KEYWORD ("export", LEXER_KEYW_EXPORT), + LEXER_KEYWORD ("import", LEXER_KEYW_IMPORT), LEXER_KEYWORD ("public", LEXER_KEYW_PUBLIC), + LEXER_KEYWORD ("return", LEXER_KEYW_RETURN), LEXER_KEYWORD ("static", LEXER_KEYW_STATIC), + LEXER_KEYWORD ("switch", LEXER_KEYW_SWITCH), LEXER_KEYWORD ("typeof", LEXER_KEYW_TYPEOF), +}; + +/** + * Keywords with 7 characters. + */ +static const keyword_string_t keywords_with_length_7[] = { + LEXER_KEYWORD ("default", LEXER_KEYW_DEFAULT), LEXER_KEYWORD ("extends", LEXER_KEYW_EXTENDS), + LEXER_KEYWORD ("finally", LEXER_KEYW_FINALLY), LEXER_KEYWORD ("package", LEXER_KEYW_PACKAGE), + LEXER_KEYWORD ("private", LEXER_KEYW_PRIVATE), +}; + +/** + * Keywords with 8 characters. + */ +static const keyword_string_t keywords_with_length_8[] = { + LEXER_KEYWORD ("continue", LEXER_KEYW_CONTINUE), + LEXER_KEYWORD ("debugger", LEXER_KEYW_DEBUGGER), + LEXER_KEYWORD ("function", LEXER_KEYW_FUNCTION), +}; + +/** + * Keywords with 9 characters. + */ +static const keyword_string_t keywords_with_length_9[] = { + LEXER_KEYWORD ("arguments", LEXER_KEYW_ARGUMENTS), + LEXER_KEYWORD ("interface", LEXER_KEYW_INTERFACE), + LEXER_KEYWORD ("protected", LEXER_KEYW_PROTECTED), +}; + +/** + * Keywords with 10 characters. + */ +static const keyword_string_t keywords_with_length_10[] = { + LEXER_KEYWORD ("implements", LEXER_KEYW_IMPLEMENTS), + LEXER_KEYWORD ("instanceof", LEXER_KEYW_INSTANCEOF), +}; + +/** + * List of the keyword groups. + */ +static const keyword_string_t *const keyword_strings_list[] = { keywords_with_length_2, keywords_with_length_3, + keywords_with_length_4, keywords_with_length_5, + keywords_with_length_6, keywords_with_length_7, + keywords_with_length_8, keywords_with_length_9, + keywords_with_length_10 }; + +JERRY_STATIC_ASSERT ((sizeof (keyword_strings_list) / sizeof (const keyword_string_t *) == (LEXER_KEYWORD_MAX_LENGTH - LEXER_KEYWORD_MIN_LENGTH) + 1), + keyword_strings_list_size_must_equal_to_keyword_max_length_difference); + +/** + * List of the keyword groups length. + */ +static const uint8_t keyword_lengths_list[] = { + LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_2), LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_3), + LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_4), LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_5), + LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_6), LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_7), + LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_8), LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_9), + LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_10) +}; + +#undef LEXER_KEYWORD +#undef LEXER_KEYWORD_LIST_LENGTH + +JERRY_STATIC_ASSERT (((int)LEXER_FIRST_NON_RESERVED_KEYWORD < (int)LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD), + lexer_first_non_reserved_keyword_must_be_before_lexer_first_future_strict_reserved_word); + +/** + * Parse identifier. + * + * @return true, if an identifier is parsed, false otherwise + */ +static bool +lexer_parse_identifier (parser_context_t *context_p, /**< context */ + lexer_parse_options_t options) /**< check keywords */ +{ + /* Only very few identifiers contains \u escape sequences. */ + const uint8_t *source_p = context_p->source_p; + /* Note: newline or tab cannot be part of an identifier. */ + parser_line_counter_t column = context_p->column; + const uint8_t *source_end_p = context_p->source_end_p; + size_t length = 0; + lexer_lit_location_flags_t status_flags = LEXER_LIT_LOCATION_IS_ASCII; + + do + { + if (*source_p == LIT_CHAR_BACKSLASH) + { + /* After a backslash an identifier must start. */ + lit_code_point_t code_point = UINT32_MAX; + uint32_t escape_length = 6; + + if (options & (LEXER_PARSE_CHECK_START_AND_RETURN | LEXER_PARSE_CHECK_PART_AND_RETURN)) + { + return true; + } + + status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE; + + if (source_p + 5 <= source_end_p && source_p[1] == LIT_CHAR_LOWERCASE_U) + { + if (source_p[2] == LIT_CHAR_LEFT_BRACE) + { + code_point = lexer_hex_in_braces_to_code_point (source_p + 3, source_end_p, &escape_length); + } + else if (source_p + 6 <= source_end_p) + { + code_point = lexer_hex_to_code_point (source_p + 2, 4); + } + } + + if (code_point == UINT32_MAX) + { + context_p->source_p = source_p; + context_p->token.column = column; + parser_raise_error (context_p, PARSER_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE); + } + + if (length == 0) + { + if (!lit_code_point_is_identifier_start (code_point)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_IDENTIFIER_START); + } + } + else + { + if (!lit_code_point_is_identifier_part (code_point)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_IDENTIFIER_PART); + } + } + + length += lit_code_point_get_cesu8_length (code_point); + source_p += escape_length; + PARSER_PLUS_EQUAL_LC (column, escape_length); + continue; + } + + lit_code_point_t code_point = *source_p; + lit_utf8_size_t utf8_length = 1, decoded_length = 1, char_count = 1; + + if (JERRY_UNLIKELY (code_point >= LIT_UTF8_2_BYTE_MARKER)) + { + status_flags = (lexer_lit_location_flags_t) ((uint32_t) status_flags & (uint32_t) ~LEXER_LIT_LOCATION_IS_ASCII); + + utf8_length = lit_read_code_point_from_utf8 (source_p, (lit_utf8_size_t) (source_end_p - source_p), &code_point); + decoded_length = utf8_length; + + /* Only ES2015+ supports code points outside of the basic plane which can be part of an identifier. */ + if ((code_point >= LIT_UTF16_HIGH_SURROGATE_MIN && code_point <= LIT_UTF16_HIGH_SURROGATE_MAX) + && source_p + 3 < source_end_p) + { + lit_code_point_t low_surrogate; + lit_read_code_point_from_utf8 (source_p + 3, (lit_utf8_size_t) (source_end_p - (source_p + 3)), &low_surrogate); + + if (low_surrogate >= LIT_UTF16_LOW_SURROGATE_MIN && low_surrogate <= LIT_UTF16_LOW_SURROGATE_MAX) + { + code_point = lit_convert_surrogate_pair_to_code_point ((ecma_char_t) code_point, (ecma_char_t) low_surrogate); + utf8_length = 2 * 3; + decoded_length = 2 * 3; + char_count = 2; + } + } + else if (source_p[0] >= LIT_UTF8_4_BYTE_MARKER) + { + decoded_length = 2 * 3; + status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE; +#if JERRY_FUNCTION_TO_STRING + context_p->global_status_flags |= ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER; +#endif /* JERRY_FUNCTION_TO_STRING */ + } + } + + if (length == 0) + { + if (JERRY_UNLIKELY (options & (LEXER_PARSE_CHECK_START_AND_RETURN | LEXER_PARSE_CHECK_PART_AND_RETURN))) + { + if (options & LEXER_PARSE_CHECK_START_AND_RETURN) + { + return lit_code_point_is_identifier_start (code_point); + } + else + { + return lit_code_point_is_identifier_part (code_point); + } + } + + if (!lit_code_point_is_identifier_start (code_point)) + { + return false; + } + } + else if (!lit_code_point_is_identifier_part (code_point)) + { + break; + } + + source_p += utf8_length; + length += decoded_length; + PARSER_PLUS_EQUAL_LC (column, char_count); + } while (source_p < source_end_p); + + JERRY_ASSERT (length > 0); + + context_p->token.type = LEXER_LITERAL; + context_p->token.lit_location.type = LEXER_IDENT_LITERAL; + context_p->token.lit_location.status_flags = (uint8_t) status_flags; + + context_p->token.column = context_p->column; + context_p->token.lit_location.char_p = context_p->source_p; + context_p->token.lit_location.length = (prop_length_t) length; + + if (JERRY_UNLIKELY (length > PARSER_MAXIMUM_IDENT_LENGTH)) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_TOO_LONG); + } + + /* Check keywords. */ + if ((options & LEXER_PARSE_CHECK_KEYWORDS) + && (length >= LEXER_KEYWORD_MIN_LENGTH && length <= LEXER_KEYWORD_MAX_LENGTH)) + { + const uint8_t *ident_start_p = context_p->source_p; + uint8_t buffer_p[LEXER_KEYWORD_MAX_LENGTH]; + + if (JERRY_UNLIKELY (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + lexer_convert_ident_to_cesu8 (buffer_p, ident_start_p, (prop_length_t) length); + ident_start_p = buffer_p; + } + + const keyword_string_t *keyword_list_p = keyword_strings_list[length - LEXER_KEYWORD_MIN_LENGTH]; + + int start = 0; + int end = keyword_lengths_list[length - LEXER_KEYWORD_MIN_LENGTH]; + int middle = end / 2; + + do + { + const keyword_string_t *keyword_p = keyword_list_p + middle; + int compare_result = ident_start_p[0] - keyword_p->keyword_p[0]; + + if (compare_result == 0) + { + compare_result = memcmp (ident_start_p, keyword_p->keyword_p, length); + + if (compare_result == 0) + { + context_p->token.keyword_type = (uint8_t) keyword_p->type; + + if (JERRY_LIKELY (keyword_p->type < LEXER_FIRST_NON_RESERVED_KEYWORD)) + { + if (JERRY_UNLIKELY (keyword_p->type == LEXER_KEYW_AWAIT)) + { + if (!(context_p->status_flags & (PARSER_IS_ASYNC_FUNCTION | PARSER_IS_CLASS_STATIC_BLOCK)) + && !(context_p->global_status_flags & ECMA_PARSE_MODULE)) + { + break; + } + + if (context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD) + { + if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + parser_raise_error (context_p, PARSER_ERR_AWAIT_NOT_ALLOWED); + } + + context_p->token.type = (uint8_t) LEXER_KEYW_AWAIT; + break; + } + + if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p)) + { + /* Escape sequences are not allowed in a keyword. */ + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + + context_p->token.type = (uint8_t) keyword_p->type; + break; + } + + if (keyword_p->type == LEXER_KEYW_LET && (context_p->status_flags & PARSER_IS_STRICT)) + { + if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + + context_p->token.type = (uint8_t) LEXER_KEYW_LET; + break; + } + + if (keyword_p->type == LEXER_KEYW_YIELD && (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)) + { + if (context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD) + { + if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + parser_raise_error (context_p, PARSER_ERR_YIELD_NOT_ALLOWED); + } + + context_p->token.type = (uint8_t) LEXER_KEYW_YIELD; + break; + } + + if (keyword_p->type == LEXER_KEYW_ARGUMENTS && (context_p->status_flags & PARSER_INSIDE_CLASS_FIELD)) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENTS_IN_CLASS_FIELD); + } + + if (keyword_p->type >= LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD && (context_p->status_flags & PARSER_IS_STRICT) + && !(options & LEXER_PARSE_NO_STRICT_IDENT_ERROR)) + { + parser_raise_error (context_p, PARSER_ERR_STRICT_IDENT_NOT_ALLOWED); + } + break; + } + } + + if (compare_result > 0) + { + start = middle + 1; + } + else + { + JERRY_ASSERT (compare_result < 0); + end = middle; + } + + middle = (start + end) / 2; + } while (start < end); + } + + context_p->source_p = source_p; + context_p->column = column; + return true; +} /* lexer_parse_identifier */ + +#undef LEXER_CHECK_INVALID_KEYWORD + +/** + * Parse string. + */ +void +lexer_parse_string (parser_context_t *context_p, /**< context */ + lexer_string_options_t opts) /**< options */ +{ + int32_t raw_length_adjust = 0; + + uint8_t str_end_character = context_p->source_p[0]; + const uint8_t *source_p = context_p->source_p + 1; + const uint8_t *string_start_p = source_p; + const uint8_t *source_end_p = context_p->source_end_p; + parser_line_counter_t line = context_p->line; + parser_line_counter_t column = (parser_line_counter_t) (context_p->column + 1); + parser_line_counter_t original_line = line; + parser_line_counter_t original_column = column; + size_t length = 0; + lexer_lit_location_flags_t status_flags = LEXER_LIT_LOCATION_IS_ASCII; + + if (str_end_character == LIT_CHAR_RIGHT_BRACE) + { + str_end_character = LIT_CHAR_GRAVE_ACCENT; + } + + while (true) + { + if (source_p >= source_end_p) + { + context_p->token.line = original_line; + context_p->token.column = (parser_line_counter_t) (original_column - 1); + parser_raise_error (context_p, PARSER_ERR_UNTERMINATED_STRING); + } + + if (*source_p == str_end_character) + { + break; + } + + if (*source_p == LIT_CHAR_BACKSLASH) + { + source_p++; + column++; + if (source_p >= source_end_p) + { + /* Will throw an unterminated string error. */ + continue; + } + + status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE; + + /* Newline is ignored. */ + if (*source_p == LIT_CHAR_CR) + { + source_p++; + if (source_p < source_end_p && *source_p == LIT_CHAR_LF) + { + raw_length_adjust--; + source_p++; + } + + line++; + column = 1; + continue; + } + else if (*source_p == LIT_CHAR_LF) + { + source_p++; + line++; + column = 1; + continue; + } + else if (*source_p == LEXER_NEWLINE_LS_PS_BYTE_1 && LEXER_NEWLINE_LS_PS_BYTE_23 (source_p)) + { + source_p += 3; + line++; + column = 1; + continue; + } + + if (opts & LEXER_STRING_RAW) + { + if ((*source_p == LIT_CHAR_GRAVE_ACCENT) || (*source_p == LIT_CHAR_BACKSLASH)) + { + source_p++; + column++; + length++; + } + continue; + } + + if (*source_p == LIT_CHAR_0 && source_p + 1 < source_end_p + && (*(source_p + 1) < LIT_CHAR_0 || *(source_p + 1) > LIT_CHAR_9)) + { + source_p++; + column++; + length++; + continue; + } + + /* Except \x, \u, and octal numbers, everything is + * converted to a character which has the same byte length. */ + if (*source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_3) + { + if (str_end_character == LIT_CHAR_GRAVE_ACCENT) + { + parser_raise_error (context_p, PARSER_ERR_TEMPLATE_STR_OCTAL_ESCAPE); + } + + if (context_p->status_flags & PARSER_IS_STRICT) + { + parser_raise_error (context_p, PARSER_ERR_OCTAL_ESCAPE_NOT_ALLOWED); + } + + source_p++; + column++; + + if (source_p < source_end_p && *source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + source_p++; + column++; + + if (source_p < source_end_p && *source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + /* Numbers >= 0x200 (0x80) requires + * two bytes for encoding in UTF-8. */ + if (source_p[-2] >= LIT_CHAR_2) + { + length++; + } + + source_p++; + column++; + } + } + + length++; + continue; + } + + if (*source_p >= LIT_CHAR_4 && *source_p <= LIT_CHAR_7) + { + if (context_p->status_flags & PARSER_IS_STRICT) + { + parser_raise_error (context_p, PARSER_ERR_OCTAL_ESCAPE_NOT_ALLOWED); + } + + source_p++; + column++; + + if (source_p < source_end_p && *source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + source_p++; + column++; + } + + /* The maximum number is 0x4d so the UTF-8 + * representation is always one byte. */ + length++; + continue; + } + + if (*source_p == LIT_CHAR_LOWERCASE_X || *source_p == LIT_CHAR_LOWERCASE_U) + { + uint32_t escape_length = (*source_p == LIT_CHAR_LOWERCASE_X) ? 3 : 5; + lit_code_point_t code_point = UINT32_MAX; + + if (source_p + 4 <= source_end_p && source_p[0] == LIT_CHAR_LOWERCASE_U && source_p[1] == LIT_CHAR_LEFT_BRACE) + { + code_point = lexer_hex_in_braces_to_code_point (source_p + 2, source_end_p, &escape_length); + escape_length--; + } + else + { + if (source_p + escape_length <= source_end_p) + { + code_point = lexer_hex_to_code_point (source_p + 1, escape_length - 1); + } + } + + if (code_point == UINT32_MAX) + { + context_p->token.line = line; + context_p->token.column = (parser_line_counter_t) (column - 1); + parser_raise_error (context_p, PARSER_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE); + } + + length += lit_code_point_get_cesu8_length (code_point); + + source_p += escape_length; + PARSER_PLUS_EQUAL_LC (column, escape_length); + continue; + } + } + else if (str_end_character == LIT_CHAR_GRAVE_ACCENT && source_p[0] == LIT_CHAR_DOLLAR_SIGN + && source_p + 1 < source_end_p && source_p[1] == LIT_CHAR_LEFT_BRACE) + { + raw_length_adjust--; + source_p++; + break; + } + + if (*source_p >= LIT_UTF8_4_BYTE_MARKER) + { + /* Processing 4 byte unicode sequence (even if it is + * after a backslash). Always converted to two 3 byte + * long sequence. */ + length += 2 * 3; + status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE; + source_p += 4; + raw_length_adjust += 2; + column++; +#if JERRY_FUNCTION_TO_STRING + context_p->global_status_flags |= ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER; +#endif /* JERRY_FUNCTION_TO_STRING */ + continue; + } + else if (*source_p == LIT_CHAR_TAB) + { + column = align_column_to_tab (column); + /* Subtract -1 because column is increased below. */ + column--; + } + else if (*source_p == LEXER_NEWLINE_LS_PS_BYTE_1 && LEXER_NEWLINE_LS_PS_BYTE_23 (source_p)) + { + source_p += 3; + length += 3; + line++; + column = 1; + continue; + } + else if (str_end_character == LIT_CHAR_GRAVE_ACCENT) + { + /* Newline (without backslash) is part of the string. + Note: ECMAScript v6, 11.8.6.1 or are both normalized to */ + if (*source_p == LIT_CHAR_CR) + { + status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE; + source_p++; + length++; + if (source_p < source_end_p && *source_p == LIT_CHAR_LF) + { + source_p++; + raw_length_adjust--; + } + line++; + column = 1; + continue; + } + else if (*source_p == LIT_CHAR_LF) + { + source_p++; + length++; + line++; + column = 1; + continue; + } + } + else if (*source_p == LIT_CHAR_CR || *source_p == LIT_CHAR_LF) + { + context_p->token.line = line; + context_p->token.column = column; + parser_raise_error (context_p, PARSER_ERR_NEWLINE_NOT_ALLOWED); + } + + source_p++; + column++; + length++; + + while (source_p < source_end_p && IS_UTF8_INTERMEDIATE_OCTET (*source_p)) + { + source_p++; + length++; + } + } + + if (opts & LEXER_STRING_RAW) + { + length = (size_t) ((source_p - string_start_p) + raw_length_adjust); + } + + if (length > PARSER_MAXIMUM_STRING_LENGTH) + { + parser_raise_error (context_p, PARSER_ERR_STRING_TOO_LONG); + } + + context_p->token.type = ((str_end_character != LIT_CHAR_GRAVE_ACCENT) ? LEXER_LITERAL : LEXER_TEMPLATE_LITERAL); + + /* Fill literal data. */ + context_p->token.lit_location.char_p = string_start_p; + context_p->token.lit_location.length = (prop_length_t) length; + context_p->token.lit_location.type = LEXER_STRING_LITERAL; + context_p->token.lit_location.status_flags = (uint8_t) status_flags; + + context_p->source_p = source_p + 1; + context_p->line = line; + context_p->column = (parser_line_counter_t) (column + 1); +} /* lexer_parse_string */ + +/** + * Check number + */ +static void +lexer_check_numbers (parser_context_t *context_p, /**< context */ + const uint8_t **source_p, /**< source_pointer */ + const uint8_t *source_end_p, /**< end of the source */ + const ecma_char_t digit_max, /**< maximum of the number range */ + const bool is_legacy) /**< is legacy octal number */ +{ + while (true) + { + while (*source_p < source_end_p && *source_p[0] >= LIT_CHAR_0 && *source_p[0] <= digit_max) + { + *source_p += 1; + } + if (*source_p != source_end_p && *source_p[0] == LIT_CHAR_UNDERSCORE) + { + *source_p += 1; + if (is_legacy || *source_p == source_end_p || *source_p[0] == LIT_CHAR_UNDERSCORE || *source_p[0] > digit_max + || *source_p[0] < LIT_CHAR_0) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER); + } + continue; + } + + break; + } +} /* lexer_check_numbers */ + +/** + * Parse number. + */ +static void +lexer_parse_number (parser_context_t *context_p) /**< context */ +{ + const uint8_t *source_p = context_p->source_p; + const uint8_t *source_end_p = context_p->source_end_p; + bool can_be_float = false; +#if JERRY_BUILTIN_BIGINT + bool can_be_bigint = true; +#endif /* JERRY_BUILTIN_BIGINT */ + size_t length; + + context_p->token.type = LEXER_LITERAL; + context_p->token.extra_value = LEXER_NUMBER_DECIMAL; + context_p->token.lit_location.char_p = source_p; + context_p->token.lit_location.type = LEXER_NUMBER_LITERAL; + context_p->token.lit_location.status_flags = LEXER_LIT_LOCATION_IS_ASCII; + + if (source_p[0] == LIT_CHAR_0 && source_p + 1 < source_end_p) + { + if (source_p[1] == LIT_CHAR_UNDERSCORE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER); + } + + if (LEXER_TO_ASCII_LOWERCASE (source_p[1]) == LIT_CHAR_LOWERCASE_X) + { + context_p->token.extra_value = LEXER_NUMBER_HEXADECIMAL; + source_p += 2; + + if (source_p >= source_end_p || !lit_char_is_hex_digit (source_p[0])) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_HEX_DIGIT); + } + + do + { + source_p++; + if (source_p < source_end_p && source_p[0] == LIT_CHAR_UNDERSCORE) + { + source_p++; + if (source_p == source_end_p || !lit_char_is_hex_digit (source_p[0])) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER); + } + } + } while (source_p < source_end_p && lit_char_is_hex_digit (source_p[0])); + } + else if (LEXER_TO_ASCII_LOWERCASE (source_p[1]) == LIT_CHAR_LOWERCASE_O) + { + context_p->token.extra_value = LEXER_NUMBER_OCTAL; + source_p += 2; + + if (source_p >= source_end_p || !lit_char_is_octal_digit (source_p[0])) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_OCTAL_DIGIT); + } + + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_7, false); + } + else if (source_p[1] >= LIT_CHAR_0 && source_p[1] <= LIT_CHAR_9) + { + context_p->token.extra_value = LEXER_NUMBER_OCTAL; +#if JERRY_BUILTIN_BIGINT + can_be_bigint = false; +#endif /* JERRY_BUILTIN_BIGINT */ + + if (context_p->status_flags & PARSER_IS_STRICT) + { + parser_raise_error (context_p, PARSER_ERR_OCTAL_NUMBER_NOT_ALLOWED); + } + + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_7, true); + + if (source_p < source_end_p && source_p[0] >= LIT_CHAR_8 && source_p[0] <= LIT_CHAR_9) + { + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_9, true); + context_p->token.extra_value = LEXER_NUMBER_DECIMAL; + } + } + + else if (LEXER_TO_ASCII_LOWERCASE (source_p[1]) == LIT_CHAR_LOWERCASE_B) + { + context_p->token.extra_value = LEXER_NUMBER_BINARY; + source_p += 2; + + if (source_p >= source_end_p || !lit_char_is_binary_digit (source_p[0])) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_BIN_DIGIT); + } + + do + { + source_p++; + if (source_p < source_end_p && source_p[0] == LIT_CHAR_UNDERSCORE) + { + source_p++; + if (source_p == source_end_p || source_p[0] > LIT_CHAR_9 || source_p[0] < LIT_CHAR_0) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER); + } + } + } while (source_p < source_end_p && lit_char_is_binary_digit (source_p[0])); + } + else + { + can_be_float = true; + source_p++; + } + } + else + { + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_9, false); + can_be_float = true; + } + + if (can_be_float) + { + if (source_p < source_end_p && source_p[0] == LIT_CHAR_DOT) + { + source_p++; +#if JERRY_BUILTIN_BIGINT + can_be_bigint = false; +#endif /* JERRY_BUILTIN_BIGINT */ + + if (source_p < source_end_p && source_p[0] == LIT_CHAR_UNDERSCORE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER); + } + + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_9, false); + } + + if (source_p < source_end_p && LEXER_TO_ASCII_LOWERCASE (source_p[0]) == LIT_CHAR_LOWERCASE_E) + { + source_p++; +#if JERRY_BUILTIN_BIGINT + can_be_bigint = false; +#endif /* JERRY_BUILTIN_BIGINT */ + + if (source_p < source_end_p && (source_p[0] == LIT_CHAR_PLUS || source_p[0] == LIT_CHAR_MINUS)) + { + source_p++; + } + + if (source_p >= source_end_p || source_p[0] < LIT_CHAR_0 || source_p[0] > LIT_CHAR_9) + { + parser_raise_error (context_p, PARSER_ERR_MISSING_EXPONENT); + } + + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_9, false); + } + } + +#if JERRY_BUILTIN_BIGINT + if (source_p < source_end_p && source_p[0] == LIT_CHAR_LOWERCASE_N) + { + if (!can_be_bigint) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_BIGINT); + } + context_p->token.extra_value = LEXER_NUMBER_BIGINT; + source_p++; + } +#endif /* JERRY_BUILTIN_BIGINT */ + + length = (size_t) (source_p - context_p->source_p); + if (length > PARSER_MAXIMUM_STRING_LENGTH) + { + parser_raise_error (context_p, PARSER_ERR_NUMBER_TOO_LONG); + } + + context_p->token.lit_location.length = (prop_length_t) length; + PARSER_PLUS_EQUAL_LC (context_p->column, length); + context_p->source_p = source_p; + + if (source_p < source_end_p && lexer_parse_identifier (context_p, LEXER_PARSE_CHECK_START_AND_RETURN)) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_AFTER_NUMBER); + } +} /* lexer_parse_number */ + +/** + * One character long token (e.g. comma). + * + * @param char1 character + * @param type1 type + */ +#define LEXER_TYPE_A_TOKEN(char1, type1) \ + case (uint8_t) (char1): \ + { \ + context_p->token.type = (type1); \ + length = 1; \ + break; \ + } + +/** + * Token pair, where the first token is prefix of the second (e.g. % and %=). + * + * @param char1 first character + * @param type1 type of the first character + * @param char2 second character + * @param type2 type of the second character + */ +#define LEXER_TYPE_B_TOKEN(char1, type1, char2, type2) \ + case (uint8_t) (char1): \ + { \ + if (length >= 2 && context_p->source_p[1] == (uint8_t) (char2)) \ + { \ + context_p->token.type = (type2); \ + length = 2; \ + break; \ + } \ + \ + context_p->token.type = (type1); \ + length = 1; \ + break; \ + } + +/** + * Three tokens, where the first is the prefix of the other two (e.g. &, &&, &=). + * + * @param char1 first character + * @param type1 type of the first character + * @param char2 second character + * @param type2 type of the second character + * @param char3 third character + * @param type3 type of the third character + */ +#define LEXER_TYPE_C_TOKEN(char1, type1, char2, type2, char3, type3) \ + case (uint8_t) (char1): \ + { \ + if (length >= 2) \ + { \ + if (context_p->source_p[1] == (uint8_t) (char2)) \ + { \ + context_p->token.type = (type2); \ + length = 2; \ + break; \ + } \ + \ + if (context_p->source_p[1] == (uint8_t) (char3)) \ + { \ + context_p->token.type = (type3); \ + length = 2; \ + break; \ + } \ + } \ + \ + context_p->token.type = (type1); \ + length = 1; \ + break; \ + } + +/** + * Four tokens, where the first is the prefix of the other three + * and the second is prefix of the fourth (e.g. &, &&, &=, &&= ). + * + * @param char1 first character + * @param type1 type of the first character + * @param char2 second character + * @param type2 type of the second character + * @param char3 third character + * @param type3 type of the third character + * @param char4 fourth character + * @param type4 type of the fourth character + */ +#define LEXER_TYPE_D_TOKEN(char1, type1, char2, type2, char3, type3, char4, type4) \ + case (uint8_t) (char1): \ + { \ + if (length >= 2) \ + { \ + if (context_p->source_p[1] == (uint8_t) (char2)) \ + { \ + context_p->token.type = (type2); \ + length = 2; \ + break; \ + } \ + \ + if (context_p->source_p[1] == (uint8_t) (char3)) \ + { \ + if (length >= 3 && context_p->source_p[2] == (uint8_t) (char4)) \ + { \ + context_p->token.type = (type4); \ + length = 3; \ + break; \ + } \ + context_p->token.type = (type3); \ + length = 2; \ + break; \ + } \ + } \ + \ + context_p->token.type = (type1); \ + length = 1; \ + break; \ + } + +/** + * Get next token. + */ +void +lexer_next_token (parser_context_t *context_p) /**< context */ +{ + size_t length; + +#if JERRY_FUNCTION_TO_STRING + /* Needed by arrow functions with expression body */ + context_p->function_end_p = context_p->source_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + + lexer_skip_spaces (context_p); + + context_p->token.keyword_type = LEXER_EOS; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + + length = (size_t) (context_p->source_end_p - context_p->source_p); + if (length == 0) + { + context_p->token.type = LEXER_EOS; + return; + } + + if (lexer_parse_identifier (context_p, LEXER_PARSE_CHECK_KEYWORDS)) + { + return; + } + + if (context_p->source_p[0] >= LIT_CHAR_0 && context_p->source_p[0] <= LIT_CHAR_9) + { + lexer_parse_number (context_p); + return; + } + + switch (context_p->source_p[0]) + { + LEXER_TYPE_A_TOKEN (LIT_CHAR_LEFT_BRACE, LEXER_LEFT_BRACE); + LEXER_TYPE_A_TOKEN (LIT_CHAR_LEFT_PAREN, LEXER_LEFT_PAREN); + LEXER_TYPE_A_TOKEN (LIT_CHAR_LEFT_SQUARE, LEXER_LEFT_SQUARE); + LEXER_TYPE_A_TOKEN (LIT_CHAR_RIGHT_BRACE, LEXER_RIGHT_BRACE); + LEXER_TYPE_A_TOKEN (LIT_CHAR_RIGHT_PAREN, LEXER_RIGHT_PAREN); + LEXER_TYPE_A_TOKEN (LIT_CHAR_RIGHT_SQUARE, LEXER_RIGHT_SQUARE); + LEXER_TYPE_A_TOKEN (LIT_CHAR_SEMICOLON, LEXER_SEMICOLON); + LEXER_TYPE_A_TOKEN (LIT_CHAR_COMMA, LEXER_COMMA); + LEXER_TYPE_A_TOKEN (LIT_CHAR_HASHMARK, LEXER_HASHMARK); + + case (uint8_t) LIT_CHAR_DOT: + { + if (length >= 2 && (context_p->source_p[1] >= LIT_CHAR_0 && context_p->source_p[1] <= LIT_CHAR_9)) + { + lexer_parse_number (context_p); + return; + } + + if (length >= 3 && context_p->source_p[1] == LIT_CHAR_DOT && context_p->source_p[2] == LIT_CHAR_DOT) + { + context_p->token.type = LEXER_THREE_DOTS; + length = 3; + break; + } + + context_p->token.type = LEXER_DOT; + length = 1; + break; + } + + case (uint8_t) LIT_CHAR_LESS_THAN: + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_LESS_EQUAL; + length = 2; + break; + } + + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_LESS_THAN) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_LEFT_SHIFT; + length = 3; + break; + } + + context_p->token.type = LEXER_LEFT_SHIFT; + length = 2; + break; + } + } + + context_p->token.type = LEXER_LESS; + length = 1; + break; + } + + case (uint8_t) LIT_CHAR_GREATER_THAN: + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_GREATER_EQUAL; + length = 2; + break; + } + + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_GREATER_THAN) + { + if (length >= 3) + { + if (context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_RIGHT_SHIFT; + length = 3; + break; + } + + if (context_p->source_p[2] == (uint8_t) LIT_CHAR_GREATER_THAN) + { + if (length >= 4 && context_p->source_p[3] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_UNS_RIGHT_SHIFT; + length = 4; + break; + } + + context_p->token.type = LEXER_UNS_RIGHT_SHIFT; + length = 3; + break; + } + } + + context_p->token.type = LEXER_RIGHT_SHIFT; + length = 2; + break; + } + } + + context_p->token.type = LEXER_GREATER; + length = 1; + break; + } + + case (uint8_t) LIT_CHAR_EQUALS: + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_STRICT_EQUAL; + length = 3; + break; + } + + context_p->token.type = LEXER_EQUAL; + length = 2; + break; + } + + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_GREATER_THAN) + { + context_p->token.type = LEXER_ARROW; + length = 2; + break; + } + } + + context_p->token.type = LEXER_ASSIGN; + length = 1; + break; + } + + case (uint8_t) LIT_CHAR_EXCLAMATION: + { + if (length >= 2 && context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_STRICT_NOT_EQUAL; + length = 3; + break; + } + + context_p->token.type = LEXER_NOT_EQUAL; + length = 2; + break; + } + + context_p->token.type = LEXER_LOGICAL_NOT; + length = 1; + break; + } + + LEXER_TYPE_C_TOKEN (LIT_CHAR_PLUS, LEXER_ADD, LIT_CHAR_EQUALS, LEXER_ASSIGN_ADD, LIT_CHAR_PLUS, LEXER_INCREASE) + LEXER_TYPE_C_TOKEN (LIT_CHAR_MINUS, + LEXER_SUBTRACT, + LIT_CHAR_EQUALS, + LEXER_ASSIGN_SUBTRACT, + LIT_CHAR_MINUS, + LEXER_DECREASE) + + case (uint8_t) LIT_CHAR_ASTERISK: + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_MULTIPLY; + length = 2; + break; + } + + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_ASTERISK) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_EXPONENTIATION; + length = 3; + break; + } + + context_p->token.type = LEXER_EXPONENTIATION; + length = 2; + break; + } + } + + context_p->token.type = LEXER_MULTIPLY; + length = 1; + break; + } + + LEXER_TYPE_B_TOKEN (LIT_CHAR_SLASH, LEXER_DIVIDE, LIT_CHAR_EQUALS, LEXER_ASSIGN_DIVIDE) + LEXER_TYPE_B_TOKEN (LIT_CHAR_PERCENT, LEXER_MODULO, LIT_CHAR_EQUALS, LEXER_ASSIGN_MODULO) + + LEXER_TYPE_D_TOKEN (LIT_CHAR_AMPERSAND, + LEXER_BIT_AND, + LIT_CHAR_EQUALS, + LEXER_ASSIGN_BIT_AND, + LIT_CHAR_AMPERSAND, + LEXER_LOGICAL_AND, + LIT_CHAR_EQUALS, + LEXER_ASSIGN_LOGICAL_AND) + LEXER_TYPE_D_TOKEN (LIT_CHAR_VLINE, + LEXER_BIT_OR, + LIT_CHAR_EQUALS, + LEXER_ASSIGN_BIT_OR, + LIT_CHAR_VLINE, + LEXER_LOGICAL_OR, + LIT_CHAR_EQUALS, + LEXER_ASSIGN_LOGICAL_OR) + + LEXER_TYPE_B_TOKEN (LIT_CHAR_CIRCUMFLEX, LEXER_BIT_XOR, LIT_CHAR_EQUALS, LEXER_ASSIGN_BIT_XOR) + + LEXER_TYPE_A_TOKEN (LIT_CHAR_TILDE, LEXER_BIT_NOT); + case (uint8_t) (LIT_CHAR_QUESTION): + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_QUESTION) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_NULLISH_COALESCING; + length = 3; + break; + } + context_p->token.type = LEXER_NULLISH_COALESCING; + length = 2; + break; + } + } + + context_p->token.type = LEXER_QUESTION_MARK; + length = 1; + break; + } + + LEXER_TYPE_A_TOKEN (LIT_CHAR_COLON, LEXER_COLON); + + case LIT_CHAR_SINGLE_QUOTE: + case LIT_CHAR_DOUBLE_QUOTE: + case LIT_CHAR_GRAVE_ACCENT: + { + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + return; + } + + default: + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); + } + } + + context_p->source_p += length; + PARSER_PLUS_EQUAL_LC (context_p->column, length); +} /* lexer_next_token */ + +#undef LEXER_TYPE_A_TOKEN +#undef LEXER_TYPE_B_TOKEN +#undef LEXER_TYPE_C_TOKEN +#undef LEXER_TYPE_D_TOKEN + +/** + * Checks whether the next token starts with the specified character. + * + * @return true - if the next is the specified character + * false - otherwise + */ +bool +lexer_check_next_character (parser_context_t *context_p, /**< context */ + lit_utf8_byte_t character) /**< specified character */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + return (context_p->source_p < context_p->source_end_p && context_p->source_p[0] == (uint8_t) character); +} /* lexer_check_next_character */ + +/** + * Checks whether the next token starts with either specified characters. + * + * @return true - if the next is the specified character + * false - otherwise + */ +bool +lexer_check_next_characters (parser_context_t *context_p, /**< context */ + lit_utf8_byte_t character1, /**< first alternative character */ + lit_utf8_byte_t character2) /**< second alternative character */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + return (context_p->source_p < context_p->source_end_p + && (context_p->source_p[0] == (uint8_t) character1 || context_p->source_p[0] == (uint8_t) character2)); +} /* lexer_check_next_characters */ + +/** + * Consumes the next character. The character cannot be a white space. + * + * @return consumed character + */ +uint8_t +lexer_consume_next_character (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->source_p < context_p->source_end_p); + + context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES; + + PARSER_PLUS_EQUAL_LC (context_p->column, 1); + return *context_p->source_p++; +} /* lexer_consume_next_character */ + +/** + * Checks whether the next character can be the start of a post primary expression + * + * Note: + * the result is not precise, but this inprecise result + * has no side effects for negating number literals + * + * @return true if the next character can be the start of a post primary expression + */ +bool +lexer_check_post_primary_exp (parser_context_t *context_p) /**< context */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + if (context_p->source_p >= context_p->source_end_p) + { + return false; + } + + switch (context_p->source_p[0]) + { + case LIT_CHAR_DOT: + case LIT_CHAR_LEFT_PAREN: + case LIT_CHAR_LEFT_SQUARE: + case LIT_CHAR_GRAVE_ACCENT: + { + return true; + } + case LIT_CHAR_PLUS: + case LIT_CHAR_MINUS: + { + return (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->source_p + 1 < context_p->source_end_p + && context_p->source_p[1] == context_p->source_p[0]); + } + case LIT_CHAR_ASTERISK: + { + return (context_p->source_p + 1 < context_p->source_end_p + && context_p->source_p[1] == (uint8_t) LIT_CHAR_ASTERISK); + } + } + + return false; +} /* lexer_check_post_primary_exp */ + +/** + * Checks whether the next token is a type used for detecting arrow functions. + * + * @return true if the next token is an arrow token + */ +bool +lexer_check_arrow (parser_context_t *context_p) /**< context */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + return (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->source_p + 2 <= context_p->source_end_p + && context_p->source_p[0] == (uint8_t) LIT_CHAR_EQUALS + && context_p->source_p[1] == (uint8_t) LIT_CHAR_GREATER_THAN); +} /* lexer_check_arrow */ + +/** + * Checks whether the next token is a comma or equal sign. + * + * @return true if the next token is a comma or equal sign + */ +bool +lexer_check_arrow_param (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.flags & LEXER_NO_SKIP_SPACES); + + if (context_p->source_p >= context_p->source_end_p) + { + return false; + } + + if (context_p->source_p[0] == LIT_CHAR_COMMA) + { + return true; + } + + if (context_p->source_p[0] != LIT_CHAR_EQUALS) + { + return false; + } + + return (context_p->source_p + 1 >= context_p->source_end_p || context_p->source_p[1] != LIT_CHAR_EQUALS); +} /* lexer_check_arrow_param */ + +/** + * Checks whether the yield expression has no argument. + * + * @return true if it has no argument + */ +bool +lexer_check_yield_no_arg (parser_context_t *context_p) /**< context */ +{ + if (context_p->token.flags & LEXER_WAS_NEWLINE) + { + return true; + } + + switch (context_p->token.type) + { + case LEXER_RIGHT_BRACE: + case LEXER_RIGHT_PAREN: + case LEXER_RIGHT_SQUARE: + case LEXER_COMMA: + case LEXER_COLON: + case LEXER_SEMICOLON: + case LEXER_EOS: + { + return true; + } + default: + { + return false; + } + } +} /* lexer_check_yield_no_arg */ + +/** + * Checks whether the next token is a multiply and consumes it. + * + * @return true if the next token is a multiply + */ +bool +lexer_consume_generator (parser_context_t *context_p) /**< context */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + if (context_p->source_p >= context_p->source_end_p || context_p->source_p[0] != LIT_CHAR_ASTERISK + || (context_p->source_p + 1 < context_p->source_end_p + && (context_p->source_p[1] == LIT_CHAR_EQUALS || context_p->source_p[1] == LIT_CHAR_ASTERISK))) + { + return false; + } + + lexer_consume_next_character (context_p); + context_p->token.type = LEXER_MULTIPLY; + return true; +} /* lexer_consume_generator */ + +/** + * Checks whether the next token is an equal sign and consumes it. + * + * @return true if the next token is an equal sign + */ +bool +lexer_consume_assign (parser_context_t *context_p) /**< context */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + if (context_p->source_p >= context_p->source_end_p || context_p->source_p[0] != LIT_CHAR_EQUALS + || (context_p->source_p + 1 < context_p->source_end_p + && (context_p->source_p[1] == LIT_CHAR_EQUALS || context_p->source_p[1] == LIT_CHAR_GREATER_THAN))) + { + return false; + } + + lexer_consume_next_character (context_p); + context_p->token.type = LEXER_ASSIGN; + return true; +} /* lexer_consume_assign */ + +/** + * Update await / yield keywords after an arrow function with expression. + */ +void +lexer_update_await_yield (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< parser status flags after restore */ +{ + if (!(status_flags & PARSER_IS_STRICT)) + { + if (status_flags & PARSER_IS_GENERATOR_FUNCTION) + { + if (context_p->token.type == LEXER_LITERAL && context_p->token.keyword_type == LEXER_KEYW_YIELD) + { + context_p->token.type = LEXER_KEYW_YIELD; + } + } + else + { + if (context_p->token.type == LEXER_KEYW_YIELD) + { + JERRY_ASSERT (context_p->token.keyword_type == LEXER_KEYW_YIELD); + context_p->token.type = LEXER_LITERAL; + } + } + } + + if (!(context_p->global_status_flags & ECMA_PARSE_MODULE)) + { + if (status_flags & PARSER_IS_ASYNC_FUNCTION) + { + if (context_p->token.type == LEXER_LITERAL && context_p->token.keyword_type == LEXER_KEYW_AWAIT) + { + context_p->token.type = LEXER_KEYW_AWAIT; + } + } + else + { + if (context_p->token.type == LEXER_KEYW_AWAIT) + { + JERRY_ASSERT (context_p->token.keyword_type == LEXER_KEYW_AWAIT); + context_p->token.type = LEXER_LITERAL; + } + } + } +} /* lexer_update_await_yield */ + +/** + * Read next token without skipping whitespaces and checking keywords + * + * @return true if the next literal is private identifier, false otherwise + */ +bool +lexer_scan_private_identifier (parser_context_t *context_p) /**< context */ +{ + context_p->token.keyword_type = LEXER_EOS; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + + return (context_p->source_p < context_p->source_end_p && lexer_parse_identifier (context_p, LEXER_PARSE_NO_OPTS)); +} /* lexer_scan_private_identifier */ + +/** + * Convert an ident with escapes to a utf8 string. + */ +void +lexer_convert_ident_to_cesu8 (uint8_t *destination_p, /**< destination string */ + const uint8_t *source_p, /**< source string */ + prop_length_t length) /**< length of destination string */ +{ + const uint8_t *destination_end_p = destination_p + length; + + JERRY_ASSERT (length <= PARSER_MAXIMUM_IDENT_LENGTH); + + do + { + if (*source_p == LIT_CHAR_BACKSLASH) + { + source_p += 2; + destination_p += lit_code_point_to_cesu8_bytes (destination_p, lexer_unchecked_hex_to_character (&source_p)); + continue; + } + + if (*source_p >= LIT_UTF8_4_BYTE_MARKER) + { + lit_four_byte_utf8_char_to_cesu8 (destination_p, source_p); + + destination_p += 6; + source_p += 4; + continue; + } + + *destination_p++ = *source_p++; + } while (destination_p < destination_end_p); +} /* lexer_convert_ident_to_cesu8 */ + +/** + * Convert literal to character sequence + */ +const uint8_t * +lexer_convert_literal_to_chars (parser_context_t *context_p, /**< context */ + const lexer_lit_location_t *literal_p, /**< literal location */ + uint8_t *local_byte_array_p, /**< local byte array to store chars */ + lexer_string_options_t opts) /**< options */ +{ + JERRY_ASSERT (context_p->u.allocated_buffer_p == NULL); + + if (!(literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + return literal_p->char_p; + } + + uint8_t *destination_start_p; + if (literal_p->length > LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE) + { + context_p->u.allocated_buffer_p = (uint8_t *) parser_malloc_local (context_p, literal_p->length); + context_p->allocated_buffer_size = literal_p->length; + destination_start_p = (uint8_t*) context_p->u.allocated_buffer_p; + } + else + { + destination_start_p = local_byte_array_p; + } + + if (literal_p->type == LEXER_IDENT_LITERAL) + { + lexer_convert_ident_to_cesu8 (destination_start_p, literal_p->char_p, literal_p->length); + return destination_start_p; + } + + const uint8_t *source_p = literal_p->char_p; + uint8_t *destination_p = destination_start_p; + + uint8_t str_end_character = source_p[-1]; + + if (str_end_character == LIT_CHAR_RIGHT_BRACE) + { + str_end_character = LIT_CHAR_GRAVE_ACCENT; + } + + bool is_raw = (opts & LEXER_STRING_RAW) != 0; + + while (true) + { + if (*source_p == str_end_character) + { + break; + } + + if (*source_p == LIT_CHAR_BACKSLASH && !is_raw) + { + uint8_t conv_character; + + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + + /* Newline is ignored. */ + if (*source_p == LIT_CHAR_CR) + { + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + + if (*source_p == LIT_CHAR_LF) + { + source_p++; + } + continue; + } + else if (*source_p == LIT_CHAR_LF) + { + source_p++; + continue; + } + else if (*source_p == LEXER_NEWLINE_LS_PS_BYTE_1 && LEXER_NEWLINE_LS_PS_BYTE_23 (source_p)) + { + source_p += 3; + continue; + } + + if (*source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_3) + { + lit_code_point_t octal_number = (uint32_t) (*source_p - LIT_CHAR_0); + + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + + if (*source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + octal_number = octal_number * 8 + (uint32_t) (*source_p - LIT_CHAR_0); + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + + if (*source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + octal_number = octal_number * 8 + (uint32_t) (*source_p - LIT_CHAR_0); + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + } + } + + destination_p += lit_code_point_to_cesu8_bytes (destination_p, octal_number); + continue; + } + + if (*source_p >= LIT_CHAR_4 && *source_p <= LIT_CHAR_7) + { + uint32_t octal_number = (uint32_t) (*source_p - LIT_CHAR_0); + + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + + if (*source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + octal_number = octal_number * 8 + (uint32_t) (*source_p - LIT_CHAR_0); + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + } + + *destination_p++ = (uint8_t) octal_number; + continue; + } + + if (*source_p == LIT_CHAR_LOWERCASE_X || *source_p == LIT_CHAR_LOWERCASE_U) + { + source_p++; + destination_p += lit_code_point_to_cesu8_bytes (destination_p, lexer_unchecked_hex_to_character (&source_p)); + continue; + } + + conv_character = *source_p; + switch (*source_p) + { + case LIT_CHAR_LOWERCASE_B: + { + conv_character = 0x08; + break; + } + case LIT_CHAR_LOWERCASE_T: + { + conv_character = 0x09; + break; + } + case LIT_CHAR_LOWERCASE_N: + { + conv_character = 0x0a; + break; + } + case LIT_CHAR_LOWERCASE_V: + { + conv_character = 0x0b; + break; + } + case LIT_CHAR_LOWERCASE_F: + { + conv_character = 0x0c; + break; + } + case LIT_CHAR_LOWERCASE_R: + { + conv_character = 0x0d; + break; + } + } + + if (conv_character != *source_p) + { + *destination_p++ = conv_character; + source_p++; + continue; + } + } + else if (str_end_character == LIT_CHAR_GRAVE_ACCENT) + { + if (source_p[0] == LIT_CHAR_DOLLAR_SIGN && source_p[1] == LIT_CHAR_LEFT_BRACE) + { + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + break; + } + if (*source_p == LIT_CHAR_CR) + { + *destination_p++ = LIT_CHAR_LF; + source_p++; + if (*source_p != str_end_character && *source_p == LIT_CHAR_LF) + { + source_p++; + } + continue; + } + if ((*source_p == LIT_CHAR_BACKSLASH) && is_raw) + { + JERRY_ASSERT (source_p + 1 < context_p->source_end_p); + if ((*(source_p + 1) == LIT_CHAR_GRAVE_ACCENT) || (*(source_p + 1) == LIT_CHAR_BACKSLASH)) + { + *destination_p++ = *source_p++; + *destination_p++ = *source_p++; + continue; + } + } + } + + if (*source_p >= LIT_UTF8_4_BYTE_MARKER) + { + /* Processing 4 byte unicode sequence (even if it is + * after a backslash). Always converted to two 3 byte + * long sequence. */ + lit_four_byte_utf8_char_to_cesu8 (destination_p, source_p); + + destination_p += 6; + source_p += 4; + continue; + } + + *destination_p++ = *source_p++; + + /* There is no need to check the source_end_p + * since the string is terminated by a quotation mark. */ + while (IS_UTF8_INTERMEDIATE_OCTET (*source_p)) + { + *destination_p++ = *source_p++; + } + } + + JERRY_ASSERT (destination_p == destination_start_p + literal_p->length); + + return destination_start_p; +} /* lexer_convert_literal_to_chars */ + +/** + * Construct an unused literal. + * + * @return a newly allocated literal + */ +lexer_literal_t * +lexer_construct_unused_literal (parser_context_t *context_p) /**< context */ +{ + lexer_literal_t *literal_p; + + if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->type = LEXER_UNUSED_LITERAL; + literal_p->status_flags = 0; + return literal_p; +} /* lexer_construct_unused_literal */ + +/** + * Construct a literal object from an identifier. + */ +void +lexer_construct_literal_object (parser_context_t *context_p, /**< context */ + const lexer_lit_location_t *lit_location_p, /**< literal location */ + uint8_t literal_type) /**< final literal type */ +{ + uint8_t local_byte_array[LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE]; + + const uint8_t *char_p = + lexer_convert_literal_to_chars (context_p, lit_location_p, local_byte_array, LEXER_STRING_NO_OPTS); + + size_t length = lit_location_p->length; + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + uint32_t literal_index = 0; + bool search_scope_stack = (literal_type == LEXER_IDENT_LITERAL); + + if (JERRY_UNLIKELY (literal_type == LEXER_NEW_IDENT_LITERAL)) + { + literal_type = LEXER_IDENT_LITERAL; + } + + JERRY_ASSERT (literal_type == LEXER_IDENT_LITERAL || literal_type == LEXER_STRING_LITERAL); + + JERRY_ASSERT (literal_type != LEXER_IDENT_LITERAL || length <= PARSER_MAXIMUM_IDENT_LENGTH); + JERRY_ASSERT (literal_type != LEXER_STRING_LITERAL || length <= PARSER_MAXIMUM_STRING_LENGTH); + + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (literal_p->type == literal_type && literal_p->prop.length == length + && memcmp (literal_p->u.char_p, char_p, length) == 0) + { + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = (uint16_t) literal_index; + + parser_free_allocated_buffer (context_p); + + if (search_scope_stack) + { + parser_scope_stack_t *scope_stack_start_p = context_p->scope_stack_p; + parser_scope_stack_t *scope_stack_p = scope_stack_start_p + context_p->scope_stack_top; + + while (scope_stack_p > scope_stack_start_p) + { + scope_stack_p--; + + if (scope_stack_p->map_from == literal_index) + { + JERRY_ASSERT (scanner_decode_map_to (scope_stack_p) >= PARSER_REGISTER_START + || (literal_p->status_flags & LEXER_FLAG_USED)); + context_p->lit_object.index = scanner_decode_map_to (scope_stack_p); + return; + } + } + + literal_p->status_flags |= LEXER_FLAG_USED; + } + return; + } + + literal_index++; + } + + JERRY_ASSERT (literal_index == context_p->literal_count); + + if (literal_index >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->prop.length = (prop_length_t) length; + literal_p->type = literal_type; + + uint8_t status_flags = LEXER_FLAG_SOURCE_PTR; + + if (length > 0 && char_p == local_byte_array) + { + literal_p->u.char_p = (uint8_t *) jmem_heap_alloc_block (length); + memcpy ((uint8_t *) literal_p->u.char_p, char_p, length); + status_flags = 0; + } + else + { + literal_p->u.char_p = char_p; + + /* Buffer is taken over when a new literal is constructed. */ + if (context_p->u.allocated_buffer_p != NULL) + { + JERRY_ASSERT (char_p == context_p->u.allocated_buffer_p); + + context_p->u.allocated_buffer_p = NULL; + status_flags = 0; + } + } + + if (search_scope_stack) + { + status_flags |= LEXER_FLAG_USED; + } + + if (lit_location_p->status_flags & LEXER_LIT_LOCATION_IS_ASCII) + { + literal_p->status_flags |= LEXER_FLAG_ASCII; + } + + literal_p->status_flags = status_flags; + + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = (uint16_t) literal_index; + context_p->literal_count++; + + JERRY_ASSERT (context_p->u.allocated_buffer_p == NULL); +} /* lexer_construct_literal_object */ + +/** + * Construct a number object. + * + * @return true if number is small number + */ +bool +lexer_construct_number_object (parser_context_t *context_p, /**< context */ + bool is_expr, /**< expression is parsed */ + bool is_negative_number) /**< sign is negative */ +{ + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + ecma_value_t lit_value; + uint32_t literal_index = 0; + prop_length_t length = context_p->token.lit_location.length; + +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (context_p->token.extra_value != LEXER_NUMBER_BIGINT)) + { +#endif /* JERRY_BUILTIN_BIGINT */ + ecma_number_t num; + uint32_t options = ECMA_CONVERSION_ALLOW_UNDERSCORE; + + if (context_p->token.extra_value == LEXER_NUMBER_OCTAL) + { + num = ecma_utf8_string_to_number_by_radix (context_p->token.lit_location.char_p, length, 8, options); + } + else + { + num = ecma_utf8_string_to_number (context_p->token.lit_location.char_p, length, options); + } + + if (is_expr) + { + int32_t int_num = (int32_t) num; + + if (int_num == num && int_num <= CBC_PUSH_NUMBER_BYTE_RANGE_END && (int_num != 0 || !is_negative_number)) + { + context_p->lit_object.index = (uint16_t) int_num; + return true; + } + } + + if (is_negative_number) + { + num = -num; + } + + lit_value = ecma_find_or_create_literal_number (num); +#if JERRY_BUILTIN_BIGINT + } + else + { + uint32_t options = (ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR | ECMA_BIGINT_PARSE_DISALLOW_MEMORY_ERROR + | ECMA_BIGINT_PARSE_ALLOW_UNDERSCORE); + + if (is_negative_number) + { + options |= ECMA_BIGINT_PARSE_SET_NEGATIVE; + } + + JERRY_ASSERT (length >= 2); + lit_value = + ecma_bigint_parse_string (context_p->token.lit_location.char_p, (lit_utf8_size_t) (length - 1), options); + + JERRY_ASSERT (lit_value != ECMA_VALUE_FALSE && !ECMA_IS_VALUE_ERROR (lit_value)); + + if (lit_value == ECMA_VALUE_NULL) + { + parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY); + } + + lit_value = ecma_find_or_create_literal_bigint (lit_value); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (literal_p->type == LEXER_NUMBER_LITERAL && literal_p->u.value == lit_value) + { + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = (uint16_t) literal_index; + return false; + } + + literal_index++; + } + + JERRY_ASSERT (literal_index == context_p->literal_count); + + if (literal_index >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->u.value = lit_value; + literal_p->prop.length = 0; /* Unused. */ + literal_p->type = LEXER_NUMBER_LITERAL; + literal_p->status_flags = 0; + + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = (uint16_t) literal_index; + + context_p->literal_count++; + return false; +} /* lexer_construct_number_object */ + +/** + * Convert a push number opcode to push literal opcode + */ +void +lexer_convert_push_number_to_push_literal (parser_context_t *context_p) /**< context */ +{ + ecma_integer_value_t value; + bool two_literals = context_p->last_cbc_opcode >= CBC_PUSH_LITERAL_PUSH_NUMBER_0; + + if (context_p->last_cbc_opcode == CBC_PUSH_NUMBER_0 || context_p->last_cbc_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_0) + { + value = 0; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_NUMBER_POS_BYTE + || context_p->last_cbc_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) + { + value = ((ecma_integer_value_t) context_p->last_cbc.value) + 1; + } + else + { + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_NUMBER_NEG_BYTE + || context_p->last_cbc_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE); + value = -((ecma_integer_value_t) context_p->last_cbc.value) - 1; + } + + ecma_value_t lit_value = ecma_make_integer_value (value); + + parser_list_iterator_t literal_iterator; + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + + context_p->last_cbc_opcode = two_literals ? CBC_PUSH_TWO_LITERALS : CBC_PUSH_LITERAL; + + uint32_t literal_index = 0; + lexer_literal_t *literal_p; + + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (literal_p->type == LEXER_NUMBER_LITERAL && literal_p->u.value == lit_value) + { + if (two_literals) + { + context_p->last_cbc.value = (uint16_t) literal_index; + } + else + { + context_p->last_cbc.literal_index = (uint16_t) literal_index; + } + return; + } + + literal_index++; + } + + JERRY_ASSERT (literal_index == context_p->literal_count); + + if (literal_index >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->u.value = lit_value; + literal_p->prop.length = 0; /* Unused. */ + literal_p->type = LEXER_NUMBER_LITERAL; + literal_p->status_flags = 0; + + context_p->literal_count++; + + if (two_literals) + { + context_p->last_cbc.value = (uint16_t) literal_index; + } + else + { + context_p->last_cbc.literal_index = (uint16_t) literal_index; + } +} /* lexer_convert_push_number_to_push_literal */ + +/** + * Construct a function literal object. + * + * @return function object literal index + */ +uint16_t +lexer_construct_function_object (parser_context_t *context_p, /**< context */ + uint32_t extra_status_flags) /**< extra status flags */ +{ +#if (JERRY_STACK_LIMIT != 0) + if (JERRY_UNLIKELY (ecma_get_current_stack_usage () > CONFIG_MEM_STACK_LIMIT)) + { + parser_raise_error (context_p, PARSER_ERR_STACK_OVERFLOW); + } +#endif /* JERRY_STACK_LIMIT != 0 */ + ecma_compiled_code_t *compiled_code_p; + lexer_literal_t *literal_p; + uint16_t result_index; + + if (context_p->status_flags & PARSER_INSIDE_WITH) + { + extra_status_flags |= PARSER_INSIDE_WITH; + } + + literal_p = lexer_construct_unused_literal (context_p); + result_index = context_p->literal_count; + context_p->literal_count++; + + parser_flush_cbc (context_p); + + if (JERRY_LIKELY (!(extra_status_flags & PARSER_IS_ARROW_FUNCTION))) + { + compiled_code_p = parser_parse_function (context_p, extra_status_flags); + } + else + { + compiled_code_p = parser_parse_arrow_function (context_p, extra_status_flags); + } + + literal_p->u.bytecode_p = compiled_code_p; + literal_p->type = LEXER_FUNCTION_LITERAL; + + return result_index; +} /* lexer_construct_function_object */ + +/** + * Construct a class static block function literal object. + * + * @return function object literal index + */ +uint16_t +lexer_construct_class_static_block_function (parser_context_t *context_p) /**< context */ +{ + ecma_compiled_code_t *compiled_code_p; + lexer_literal_t *literal_p; + uint16_t result_index; + + literal_p = lexer_construct_unused_literal (context_p); + result_index = context_p->literal_count; + context_p->literal_count++; + + parser_flush_cbc (context_p); + compiled_code_p = parser_parse_class_static_block (context_p); + + literal_p->u.bytecode_p = compiled_code_p; + literal_p->type = LEXER_FUNCTION_LITERAL; + + return result_index; +} /* lexer_construct_class_static_block_function */ + +/** + * Construct a regular expression object. + * + * Note: In ESNEXT the constructed literal's type can be LEXER_STRING_LITERAL which represents + * invalid pattern. In this case the lit_object's index contains the thrown error message literal. + * Otherwise a new literal is appended to the end of the literal pool. + */ +void +lexer_construct_regexp_object (parser_context_t *context_p, /**< context */ + bool parse_only) /**< parse only */ +{ +#if JERRY_BUILTIN_REGEXP + const uint8_t *source_p = context_p->source_p; + const uint8_t *regex_start_p = context_p->source_p; + const uint8_t *regex_end_p = regex_start_p; + const uint8_t *source_end_p = context_p->source_end_p; + parser_line_counter_t column = context_p->column; + bool in_class = false; + uint16_t current_flags; + lit_utf8_size_t length; + + JERRY_ASSERT (context_p->token.type == LEXER_DIVIDE || context_p->token.type == LEXER_ASSIGN_DIVIDE); + + if (context_p->token.type == LEXER_ASSIGN_DIVIDE) + { + regex_start_p--; + } + + while (true) + { + if (source_p >= source_end_p) + { + parser_raise_error (context_p, PARSER_ERR_UNTERMINATED_REGEXP); + } + + if (!in_class && source_p[0] == LIT_CHAR_SLASH) + { + regex_end_p = source_p; + source_p++; + column++; + break; + } + + switch (source_p[0]) + { + case LIT_CHAR_CR: + case LIT_CHAR_LF: + case LEXER_NEWLINE_LS_PS_BYTE_1: + { + if (source_p[0] != LEXER_NEWLINE_LS_PS_BYTE_1 || LEXER_NEWLINE_LS_PS_BYTE_23 (source_p)) + { + parser_raise_error (context_p, PARSER_ERR_NEWLINE_NOT_ALLOWED); + } + break; + } + case LIT_CHAR_TAB: + { + column = align_column_to_tab (column); + /* Subtract -1 because column is increased below. */ + column--; + break; + } + case LIT_CHAR_LEFT_SQUARE: + { + in_class = true; + break; + } + case LIT_CHAR_RIGHT_SQUARE: + { + in_class = false; + break; + } + case LIT_CHAR_BACKSLASH: + { + if (source_p + 1 >= source_end_p) + { + parser_raise_error (context_p, PARSER_ERR_UNTERMINATED_REGEXP); + } + + if (source_p[1] >= 0x20 && source_p[1] <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + source_p++; + column++; + } + } + } + + source_p++; + column++; + + while (source_p < source_end_p && IS_UTF8_INTERMEDIATE_OCTET (source_p[0])) + { + source_p++; + } + } + + current_flags = 0; + while (source_p < source_end_p) + { + uint32_t flag = 0; + + if (source_p[0] == LIT_CHAR_LOWERCASE_G) + { + flag = RE_FLAG_GLOBAL; + } + else if (source_p[0] == LIT_CHAR_LOWERCASE_I) + { + flag = RE_FLAG_IGNORE_CASE; + } + else if (source_p[0] == LIT_CHAR_LOWERCASE_M) + { + flag = RE_FLAG_MULTILINE; + } + else if (source_p[0] == LIT_CHAR_LOWERCASE_U) + { + flag = RE_FLAG_UNICODE; + } + else if (source_p[0] == LIT_CHAR_LOWERCASE_Y) + { + flag = RE_FLAG_STICKY; + } + else if (source_p[0] == LIT_CHAR_LOWERCASE_S) + { + flag = RE_FLAG_DOTALL; + } + + if (flag == 0) + { + break; + } + + if (current_flags & flag) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_REGEXP_FLAG); + } + + current_flags = (uint16_t) (current_flags | flag); + source_p++; + column++; + } + + context_p->source_p = source_p; + context_p->column = column; + + if (source_p < source_end_p && lexer_parse_identifier (context_p, LEXER_PARSE_CHECK_PART_AND_RETURN)) + { + parser_raise_error (context_p, PARSER_ERR_UNKNOWN_REGEXP_FLAG); + } + + length = (lit_utf8_size_t) (regex_end_p - regex_start_p); + if (length > PARSER_MAXIMUM_STRING_LENGTH) + { + parser_raise_error (context_p, PARSER_ERR_REGEXP_TOO_LONG); + } + + context_p->column = column; + context_p->source_p = source_p; + + if (parse_only) + { + return; + } + + if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + /* Compile the RegExp literal and store the RegExp bytecode pointer */ + ecma_string_t *pattern_str_p = NULL; + + if (lit_is_valid_cesu8_string (regex_start_p, length)) + { + pattern_str_p = ecma_new_ecma_string_from_utf8 (regex_start_p, length); + } + else + { + JERRY_ASSERT (lit_is_valid_utf8_string (regex_start_p, length, false)); + pattern_str_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (regex_start_p, length); + } + + re_compiled_code_t *re_bytecode_p = re_compile_bytecode (pattern_str_p, current_flags); + ecma_deref_ecma_string (pattern_str_p); + + if (JERRY_UNLIKELY (re_bytecode_p == NULL)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_REGEXP); + } + + lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->u.bytecode_p = (ecma_compiled_code_t *) re_bytecode_p; + literal_p->type = LEXER_REGEXP_LITERAL; + literal_p->prop.length = (prop_length_t) length; + literal_p->status_flags = 0; + + context_p->token.type = LEXER_LITERAL; + context_p->token.lit_location.type = LEXER_REGEXP_LITERAL; + + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = context_p->literal_count++; +#else /* !JERRY_BUILTIN_REGEXP */ + JERRY_UNUSED (parse_only); + parser_raise_error (context_p, PARSER_ERR_UNSUPPORTED_REGEXP); +#endif /* JERRY_BUILTIN_REGEXP */ +} /* lexer_construct_regexp_object */ + +/** + * Next token must be an identifier. + */ +void +lexer_expect_identifier (parser_context_t *context_p, /**< context */ + uint8_t literal_type) /**< literal type */ +{ + JERRY_ASSERT (literal_type == LEXER_STRING_LITERAL || literal_type == LEXER_IDENT_LITERAL + || literal_type == LEXER_NEW_IDENT_LITERAL); + + lexer_skip_spaces (context_p); + context_p->token.keyword_type = LEXER_EOS; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + + if (context_p->source_p < context_p->source_end_p + && lexer_parse_identifier ( + context_p, + (literal_type != LEXER_STRING_LITERAL ? LEXER_PARSE_CHECK_KEYWORDS : LEXER_PARSE_NO_OPTS))) + { + if (context_p->token.type == LEXER_LITERAL) + { + JERRY_ASSERT (context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, literal_type); + + if (literal_type != LEXER_STRING_LITERAL && (context_p->status_flags & PARSER_IS_STRICT)) + { + if (context_p->token.keyword_type == LEXER_KEYW_EVAL) + { + parser_raise_error (context_p, PARSER_ERR_EVAL_NOT_ALLOWED); + } + else if (context_p->token.keyword_type == LEXER_KEYW_ARGUMENTS) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENTS_NOT_ALLOWED); + } + } + return; + } + } +#if JERRY_MODULE_SYSTEM + else if (context_p->status_flags & PARSER_MODULE_DEFAULT_CLASS_OR_FUNC) + { + /* When parsing default exports for modules, it is not required by functions or classes to have identifiers. + * In this case we use a synthetic name for them. */ + context_p->token.type = LEXER_LITERAL; + context_p->token.lit_location = lexer_default_literal; + lexer_construct_literal_object (context_p, &context_p->token.lit_location, literal_type); + context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC); + return; + } +#endif /* JERRY_MODULE_SYSTEM */ + if (context_p->token.type == LEXER_KEYW_YIELD) + { + parser_raise_error (context_p, PARSER_ERR_YIELD_NOT_ALLOWED); + } + if (context_p->token.type == LEXER_KEYW_AWAIT) + { + parser_raise_error (context_p, PARSER_ERR_AWAIT_NOT_ALLOWED); + } + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); +} /* lexer_expect_identifier */ + +/** + * Next token must be an identifier. + */ +void +lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */ + uint32_t ident_opts) /**< lexer_obj_ident_opts_t option bits */ +{ + lexer_skip_spaces (context_p); + + if (context_p->source_p >= context_p->source_end_p) + { + parser_raise_error (context_p, PARSER_ERR_PROPERTY_IDENTIFIER_EXPECTED); + } + + context_p->token.keyword_type = LEXER_EOS; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + bool create_literal_object = false; + + JERRY_ASSERT ((ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER) || !(ident_opts & LEXER_OBJ_IDENT_CLASS_NO_STATIC)); + +#if JERRY_FUNCTION_TO_STRING + if (ident_opts & LEXER_OBJ_IDENT_SET_FUNCTION_START) + { + context_p->function_start_p = context_p->source_p; + } +#endif /* JERRY_FUNCTION_TO_STRING */ + + if (lexer_parse_identifier (context_p, LEXER_PARSE_NO_OPTS)) + { + if (!(ident_opts & (LEXER_OBJ_IDENT_ONLY_IDENTIFIERS | LEXER_OBJ_IDENT_OBJECT_PATTERN))) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + + if (context_p->source_p < context_p->source_end_p && context_p->source_p[0] != LIT_CHAR_COMMA + && context_p->source_p[0] != LIT_CHAR_RIGHT_BRACE && context_p->source_p[0] != LIT_CHAR_LEFT_PAREN + && context_p->source_p[0] != LIT_CHAR_SEMICOLON && context_p->source_p[0] != LIT_CHAR_EQUALS + && context_p->source_p[0] != LIT_CHAR_COLON) + { + if (lexer_compare_literal_to_string (context_p, "get", 3)) + { + context_p->token.type = LEXER_PROPERTY_GETTER; + return; + } + + if (lexer_compare_literal_to_string (context_p, "set", 3)) + { + context_p->token.type = LEXER_PROPERTY_SETTER; + return; + } + + if (lexer_compare_literal_to_string (context_p, "async", 5)) + { + context_p->token.type = LEXER_KEYW_ASYNC; + return; + } + + if (ident_opts & LEXER_OBJ_IDENT_CLASS_NO_STATIC) + { + if (lexer_compare_literal_to_string (context_p, "static", 6)) + { + context_p->token.type = LEXER_KEYW_STATIC; + } + return; + } + } + } + + create_literal_object = true; + } + else if (ident_opts & LEXER_OBJ_IDENT_CLASS_PRIVATE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); + } + else + { + switch (context_p->source_p[0]) + { + case LIT_CHAR_DOUBLE_QUOTE: + case LIT_CHAR_SINGLE_QUOTE: + { + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + create_literal_object = true; + break; + } + case LIT_CHAR_LEFT_SQUARE: + { +#if JERRY_FUNCTION_TO_STRING + const uint8_t *function_start_p = context_p->function_start_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + + lexer_consume_next_character (context_p); + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->token.type != LEXER_RIGHT_SQUARE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_SQUARE_EXPECTED); + } + +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = function_start_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + return; + } + case LIT_CHAR_ASTERISK: + { + if (ident_opts & (LEXER_OBJ_IDENT_ONLY_IDENTIFIERS | LEXER_OBJ_IDENT_OBJECT_PATTERN)) + { + break; + } + + context_p->token.type = LEXER_MULTIPLY; + lexer_consume_next_character (context_p); + return; + } + case LIT_CHAR_HASHMARK: + { + if (ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER) + { + context_p->token.type = LEXER_HASHMARK; + return; + } + + break; + } + case LIT_CHAR_LEFT_BRACE: + { + const uint32_t static_block_flags = + (LEXER_OBJ_IDENT_CLASS_NO_STATIC | LEXER_OBJ_IDENT_CLASS_PRIVATE | LEXER_OBJ_IDENT_CLASS_IDENTIFIER); + + if ((ident_opts & static_block_flags) == LEXER_OBJ_IDENT_CLASS_IDENTIFIER) + { + context_p->token.type = LEXER_LEFT_BRACE; + lexer_consume_next_character (context_p); + return; + } + + break; + } + case LIT_CHAR_RIGHT_BRACE: + { + if (ident_opts & LEXER_OBJ_IDENT_ONLY_IDENTIFIERS) + { + break; + } + + context_p->token.type = LEXER_RIGHT_BRACE; + lexer_consume_next_character (context_p); + return; + } + case LIT_CHAR_DOT: + { + if (!(context_p->source_p + 1 >= context_p->source_end_p || lit_char_is_decimal_digit (context_p->source_p[1]))) + { + if ((ident_opts & ((uint32_t) ~(LEXER_OBJ_IDENT_OBJECT_PATTERN | LEXER_OBJ_IDENT_SET_FUNCTION_START))) + || context_p->source_p + 2 >= context_p->source_end_p || context_p->source_p[1] != LIT_CHAR_DOT + || context_p->source_p[2] != LIT_CHAR_DOT) + { + break; + } + + context_p->token.type = LEXER_THREE_DOTS; + context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES; + PARSER_PLUS_EQUAL_LC (context_p->column, 3); + context_p->source_p += 3; + return; + } + /* FALLTHRU */ + } + default: + { + const uint8_t *char_p = context_p->source_p; + + if (char_p[0] == LIT_CHAR_DOT) + { + char_p++; + } + + if (char_p < context_p->source_end_p && char_p[0] >= LIT_CHAR_0 && char_p[0] <= LIT_CHAR_9) + { + lexer_parse_number (context_p); + + if (!(ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER)) + { + lexer_construct_number_object (context_p, false, false); + } + return; + } + break; + } + } + } + + if (create_literal_object) + { + if (ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER) + { + return; + } + + if (ident_opts & LEXER_OBJ_IDENT_CLASS_PRIVATE) + { + parser_resolve_private_identifier (context_p); + return; + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + return; + } + + parser_raise_error (context_p, PARSER_ERR_PROPERTY_IDENTIFIER_EXPECTED); +} /* lexer_expect_object_literal_id */ + +/** + * Read next token without checking keywords + * + * @return true if the next literal is identifier, false otherwise + */ +bool +lexer_scan_identifier (parser_context_t *context_p, /**< context */ + lexer_parse_options_t opts) /**< identifier parse options */ +{ + lexer_skip_spaces (context_p); + context_p->token.keyword_type = LEXER_EOS; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + + if (context_p->source_p < context_p->source_end_p && lexer_parse_identifier (context_p, opts)) + { + return true; + } + + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + lexer_next_token (context_p); + return false; +} /* lexer_scan_identifier */ + +/** + * Check whether the identifier is a modifier in a property definition. + */ +void +lexer_check_property_modifier (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)); + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + + if (context_p->source_p >= context_p->source_end_p || context_p->source_p[0] == LIT_CHAR_COMMA + || context_p->source_p[0] == LIT_CHAR_RIGHT_BRACE || context_p->source_p[0] == LIT_CHAR_LEFT_PAREN + || context_p->source_p[0] == LIT_CHAR_EQUALS || context_p->source_p[0] == LIT_CHAR_COLON) + { + return; + } + + if (lexer_compare_literal_to_string (context_p, "get", 3)) + { + context_p->token.type = LEXER_PROPERTY_GETTER; + return; + } + + if (lexer_compare_literal_to_string (context_p, "set", 3)) + { + context_p->token.type = LEXER_PROPERTY_SETTER; + return; + } + + if (lexer_compare_literal_to_string (context_p, "async", 5)) + { + context_p->token.type = LEXER_KEYW_ASYNC; + return; + } +} /* lexer_check_property_modifier */ + +/** + * Compares two identifiers. + * + * Note: + * Escape sequences are allowed in the left identifier, but not in the right + * + * @return true if the two identifiers are the same + */ +static bool +lexer_compare_identifier_to_chars (const uint8_t *left_p, /**< left identifier */ + const uint8_t *right_p, /**< right identifier string */ + size_t size) /**< byte size of the two identifiers */ +{ + uint8_t utf8_buf[6]; + + do + { + if (*left_p == *right_p) + { + left_p++; + right_p++; + size--; + continue; + } + + size_t escape_size; + + if (*left_p == LIT_CHAR_BACKSLASH) + { + left_p += 2; + lit_code_point_t code_point = lexer_unchecked_hex_to_character (&left_p); + + escape_size = lit_code_point_to_cesu8_bytes (utf8_buf, code_point); + } + else if (*left_p >= LIT_UTF8_4_BYTE_MARKER) + { + lit_four_byte_utf8_char_to_cesu8 (utf8_buf, left_p); + escape_size = 3 * 2; + left_p += 4; + } + else + { + return false; + } + + size -= escape_size; + + uint8_t *utf8_p = utf8_buf; + do + { + if (*right_p++ != *utf8_p++) + { + return false; + } + } while (--escape_size > 0); + } while (size > 0); + + return true; +} /* lexer_compare_identifier_to_chars */ + +/** + * Compares an identifier to a string. + * + * Note: + * Escape sequences are allowed in the left identifier, but not in the right + * + * @return true if the identifier equals to string + */ +bool +lexer_compare_identifier_to_string (const lexer_lit_location_t *left_p, /**< left literal */ + const uint8_t *right_p, /**< right identifier string */ + size_t size) /**< byte size of the right identifier */ +{ + if (left_p->length != size) + { + return false; + } + + if (!(left_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + return memcmp (left_p->char_p, right_p, size) == 0; + } + + return lexer_compare_identifier_to_chars (left_p->char_p, right_p, size); +} /* lexer_compare_identifier_to_string */ + +/** + * Compares two identifiers. + * + * Note: + * Escape sequences are allowed in both identifiers + * + * @return true if the two identifiers are the same + */ +bool +lexer_compare_identifiers (parser_context_t *context_p, /**< context */ + const lexer_lit_location_t *left_p, /**< left literal */ + const lexer_lit_location_t *right_p) /**< right literal */ +{ + prop_length_t length = left_p->length; + + if (length != right_p->length) + { + return false; + } + + if (!(left_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + return lexer_compare_identifier_to_chars (right_p->char_p, left_p->char_p, length); + } + + if (!(right_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + return lexer_compare_identifier_to_chars (left_p->char_p, right_p->char_p, length); + } + + if (length <= 64) + { + uint8_t buf_p[64]; + lexer_convert_ident_to_cesu8 (buf_p, left_p->char_p, length); + return lexer_compare_identifier_to_chars (right_p->char_p, buf_p, length); + } + + uint8_t *dynamic_buf_p = (uint8_t*) parser_malloc (context_p, length); + + lexer_convert_ident_to_cesu8 (dynamic_buf_p, left_p->char_p, length); + bool result = lexer_compare_identifier_to_chars (right_p->char_p, dynamic_buf_p, length); + parser_free (dynamic_buf_p, length); + + return result; +} /* lexer_compare_identifiers */ + +/** + * Compares the current identifier in the context to the parameter identifier + * + * Note: + * Escape sequences are allowed. + * + * @return true if the input identifiers are the same + */ +bool +lexer_current_is_literal (parser_context_t *context_p, /**< context */ + const lexer_lit_location_t *right_ident_p) /**< identifier */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_lit_location_t *left_ident_p = &context_p->token.lit_location; + + JERRY_ASSERT (left_ident_p->length > 0 && right_ident_p->length > 0); + + if (left_ident_p->length != right_ident_p->length) + { + return false; + } + + if (!((left_ident_p->status_flags | right_ident_p->status_flags) & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + return memcmp (left_ident_p->char_p, right_ident_p->char_p, left_ident_p->length) == 0; + } + + return lexer_compare_identifiers (context_p, left_ident_p, right_ident_p); +} /* lexer_current_is_literal */ + +/** + * Compares the current string token to "use strict". + * + * Note: + * Escape sequences are not allowed. + * + * @return true if "use strict" is found, false otherwise + */ +bool +lexer_string_is_use_strict (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL); + + return (context_p->token.lit_location.length == 10 + && !(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE) + && memcmp (context_p->token.lit_location.char_p, "use strict", 10) == 0); +} /* lexer_string_is_use_strict */ + +/** + * Checks whether the string before the current token is a directive or a string literal. + * + * @return true if the string is a directive, false otherwise + */ +bool +lexer_string_is_directive (parser_context_t *context_p) /**< context */ +{ + return (context_p->token.type == LEXER_SEMICOLON || context_p->token.type == LEXER_RIGHT_BRACE + || context_p->token.type == LEXER_EOS + || ((context_p->token.flags & LEXER_WAS_NEWLINE) && !LEXER_IS_BINARY_OP_TOKEN (context_p->token.type) + && context_p->token.type != LEXER_LEFT_PAREN && context_p->token.type != LEXER_LEFT_SQUARE + && context_p->token.type != LEXER_DOT)); +} /* lexer_string_is_directive */ + +/** + * Compares the current token to an expected identifier. + * + * Note: + * Escape sequences are not allowed. + * + * @return true if they are the same, false otherwise + */ +bool +lexer_token_is_identifier (parser_context_t *context_p, /**< context */ + const char *identifier_p, /**< identifier */ + size_t identifier_length) /**< identifier length */ +{ + /* Checking has_escape is unnecessary because memcmp will fail if escape sequences are present. */ + return (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL + && context_p->token.lit_location.length == identifier_length + && memcmp (context_p->token.lit_location.char_p, identifier_p, identifier_length) == 0); +} /* lexer_token_is_identifier */ + +/** + * Compares the current identifier token to "let". + * + * Note: + * Escape sequences are not allowed. + * + * @return true if "let" is found, false otherwise + */ +bool +lexer_token_is_let (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL); + + return (context_p->token.keyword_type == LEXER_KEYW_LET + && !(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)); +} /* lexer_token_is_let */ + +/** + * Compares the current identifier token to "async". + * + * Note: + * Escape sequences are not allowed. + * + * @return true if "async" is found, false otherwise + */ +bool +lexer_token_is_async (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL || context_p->token.type == LEXER_TEMPLATE_LITERAL); + + return (context_p->token.keyword_type == LEXER_KEYW_ASYNC + && !(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)); +} /* lexer_token_is_async */ + +/** + * Compares the current identifier or string to an expected string. + * + * Note: + * Escape sequences are not allowed. + * + * @return true if they are the same, false otherwise + */ +bool +lexer_compare_literal_to_string (parser_context_t *context_p, /**< context */ + const char *string_p, /**< string */ + size_t string_length) /**< string length */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && (context_p->token.lit_location.type == LEXER_IDENT_LITERAL + || context_p->token.lit_location.type == LEXER_STRING_LITERAL)); + + /* Checking has_escape is unnecessary because memcmp will fail if escape sequences are present. */ + return (context_p->token.lit_location.length == string_length + && memcmp (context_p->token.lit_location.char_p, string_p, string_length) == 0); +} /* lexer_compare_literal_to_string */ + +/** + * Initialize line info to its default value + */ +void +lexer_init_line_info (parser_context_t *context_p) /**< context */ +{ + context_p->line = 1; + context_p->column = 1; + + const jerry_parse_options_t *options_p = context_p->options_p; + + if (options_p != NULL && (options_p->options & JERRY_PARSE_HAS_START)) + { + if (options_p->start_line > 0) + { + context_p->line = options_p->start_line; + } + + if (options_p->start_column > 0) + { + context_p->column = options_p->start_column; + } + } +} /* lexer_init_line_info */ + +/** + * Convert binary lvalue token to binary token + * e.g. += -> + + * ^= -> ^ + * + * @return binary token + */ +uint8_t +lexer_convert_binary_lvalue_token_to_binary (uint8_t token) /**< binary lvalue token */ +{ + JERRY_ASSERT (LEXER_IS_BINARY_LVALUE_OP_TOKEN (token)); + JERRY_ASSERT (token != LEXER_ASSIGN); + + if (token <= LEXER_ASSIGN_EXPONENTIATION) + { + return (uint8_t) (LEXER_ADD + (token - LEXER_ASSIGN_ADD)); + } + + if (token <= LEXER_ASSIGN_UNS_RIGHT_SHIFT) + { + return (uint8_t) (LEXER_LEFT_SHIFT + (token - LEXER_ASSIGN_LEFT_SHIFT)); + } + + switch (token) + { + case LEXER_ASSIGN_BIT_AND: + { + return LEXER_BIT_AND; + } + case LEXER_ASSIGN_BIT_OR: + { + return LEXER_BIT_OR; + } + default: + { + JERRY_ASSERT (token == LEXER_ASSIGN_BIT_XOR); + return LEXER_BIT_XOR; + } + } +} /* lexer_convert_binary_lvalue_token_to_binary */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.h new file mode 100644 index 00000000..97e25d3d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.h @@ -0,0 +1,357 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_LEXER_H +#define JS_LEXER_H + +#include "ecma-globals.h" + +#include "common.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_lexer Lexer + * @{ + */ + +/** + * Flags for lexer_parse_identifier. + */ +typedef enum +{ + LEXER_PARSE_NO_OPTS = 0, /**< no options */ + LEXER_PARSE_CHECK_KEYWORDS = (1 << 0), /**< check keywords */ + LEXER_PARSE_NO_STRICT_IDENT_ERROR = (1 << 1), /**< do not throw exception for strict mode keywords */ + LEXER_PARSE_CHECK_START_AND_RETURN = (1 << 2), /**< check identifier start and return */ + LEXER_PARSE_CHECK_PART_AND_RETURN = (1 << 3), /**< check identifier part and return */ +} lexer_parse_options_t; + +/** + * Lexer token types. + */ +typedef enum +{ + LEXER_EOS, /**< end of source */ + + /* Primary expressions */ + LEXER_LITERAL, /**< literal token */ + LEXER_KEYW_THIS, /**< this */ + LEXER_LIT_TRUE, /**< true (not a keyword!) */ + LEXER_LIT_FALSE, /**< false (not a keyword!) */ + LEXER_LIT_NULL, /**< null (not a keyword!) */ + LEXER_TEMPLATE_LITERAL, /**< multi segment template literal */ + LEXER_THREE_DOTS, /**< ... (rest or spread operator) */ + +/* Unary operators + * IMPORTANT: update CBC_UNARY_OP_TOKEN_TO_OPCODE and + * CBC_UNARY_LVALUE_OP_TOKEN_TO_OPCODE after changes. */ +#define LEXER_IS_UNARY_OP_TOKEN(token_type) ((token_type) >= LEXER_PLUS && (token_type) <= LEXER_DECREASE) +#define LEXER_IS_UNARY_LVALUE_OP_TOKEN(token_type) ((token_type) >= LEXER_KEYW_DELETE && (token_type) <= LEXER_DECREASE) + + LEXER_PLUS, /**< "+" */ + LEXER_NEGATE, /**< "-" */ + LEXER_LOGICAL_NOT, /**< "!" */ + LEXER_BIT_NOT, /**< "~" */ + LEXER_KEYW_VOID, /**< void */ + LEXER_KEYW_TYPEOF, /**< typeof */ + LEXER_KEYW_AWAIT, /**< await */ + LEXER_KEYW_DELETE, /**< delete */ + LEXER_INCREASE, /**< "++" */ + LEXER_DECREASE, /**< "--" */ + +/* Binary operators + * IMPORTANT: update CBC_BINARY_OP_TOKEN_TO_OPCODE, + * CBC_BINARY_LVALUE_OP_TOKEN_TO_OPCODE and + * parser_binary_precedence_table after changes. */ +/** + * Index of first binary operation opcode. + */ +#define LEXER_FIRST_BINARY_OP LEXER_ASSIGN + +/** + * Index of last binary operation opcode. + */ +#define LEXER_LAST_BINARY_OP LEXER_EXPONENTIATION + +/** + * Checks whether the token is a binary operation token. + */ +#define LEXER_IS_BINARY_OP_TOKEN(token_type) \ + ((token_type) >= LEXER_FIRST_BINARY_OP && (token_type) <= LEXER_LAST_BINARY_OP) +/** + * Checks whether the token is an lvalue (assignment) operation token. + */ +#define LEXER_IS_BINARY_LVALUE_OP_TOKEN(token_type) \ + ((token_type) >= LEXER_ASSIGN && (token_type) <= LEXER_ASSIGN_BIT_XOR) +/** + * Checks whether the token is a non-lvalue (assignment) operation token. + */ +#define LEXER_IS_BINARY_NON_LVALUE_OP_TOKEN(token_type) \ + ((token_type) >= LEXER_QUESTION_MARK && (token_type) <= LEXER_LAST_BINARY_OP) + + LEXER_ASSIGN, /**< "=" (prec: 3) */ + LEXER_ASSIGN_ADD, /**< "+=" (prec: 3) */ + LEXER_ASSIGN_SUBTRACT, /**< "-=" (prec: 3) */ + LEXER_ASSIGN_MULTIPLY, /**< "*=" (prec: 3) */ + LEXER_ASSIGN_DIVIDE, /**< "/=" (prec: 3) */ + LEXER_ASSIGN_MODULO, /**< "%=" (prec: 3) */ + LEXER_ASSIGN_EXPONENTIATION, /**< "**=" (prec: 3) */ + LEXER_ASSIGN_NULLISH_COALESCING, /**< "??=" (prec: 3) */ + LEXER_ASSIGN_LOGICAL_OR, /**< "||=" (prec: 3) */ + LEXER_ASSIGN_LOGICAL_AND, /**< "&&=" (prec: 3) */ + LEXER_ASSIGN_LEFT_SHIFT, /**< "<<=" (prec: 3) */ + LEXER_ASSIGN_RIGHT_SHIFT, /**< ">>=" (prec: 3) */ + LEXER_ASSIGN_UNS_RIGHT_SHIFT, /**< ">>>=" (prec: 3) */ + LEXER_ASSIGN_BIT_AND, /**< "&=" (prec: 3) */ + LEXER_ASSIGN_BIT_OR, /**< "|=" (prec: 3) */ + LEXER_ASSIGN_BIT_XOR, /**< "^=" (prec: 3) */ + LEXER_QUESTION_MARK, /**< "?" (prec: 4) */ + LEXER_NULLISH_COALESCING, /**< "??" (prec: 5) */ + LEXER_LOGICAL_OR, /**< "||" (prec: 6) */ + LEXER_LOGICAL_AND, /**< "&&" (prec: 7) */ + LEXER_BIT_OR, /**< "|" (prec: 8) */ + LEXER_BIT_XOR, /**< "^" (prec: 9) */ + LEXER_BIT_AND, /**< "&" (prec: 10) */ + LEXER_EQUAL, /**< "==" (prec: 11) */ + LEXER_NOT_EQUAL, /**< "!=" (prec: 11) */ + LEXER_STRICT_EQUAL, /**< "===" (prec: 11) */ + LEXER_STRICT_NOT_EQUAL, /**< "!==" (prec: 11) */ + LEXER_LESS, /**< "<" (prec: 12) */ + LEXER_GREATER, /**< ">" (prec: 12) */ + LEXER_LESS_EQUAL, /**< "<=" (prec: 12) */ + LEXER_GREATER_EQUAL, /**< ">=" (prec: 12) */ + LEXER_KEYW_IN, /**< in (prec: 12) */ + LEXER_KEYW_INSTANCEOF, /**< instanceof (prec: 12) */ + LEXER_LEFT_SHIFT, /**< "<<" (prec: 13) */ + LEXER_RIGHT_SHIFT, /**< ">>" (prec: 13) */ + LEXER_UNS_RIGHT_SHIFT, /**< ">>>" (prec: 13) */ + LEXER_ADD, /**< "+" (prec: 14) */ + LEXER_SUBTRACT, /**< "-" (prec: 14) */ + LEXER_MULTIPLY, /**< "*" (prec: 15) */ + LEXER_DIVIDE, /**< "/" (prec: 15) */ + LEXER_MODULO, /**< "%" (prec: 15) */ + LEXER_EXPONENTIATION, /**< "**" (prec: 16) */ + LEXER_LEFT_BRACE, /**< "{" */ + LEXER_LEFT_PAREN, /**< "(" */ + LEXER_LEFT_SQUARE, /**< "[" */ + LEXER_RIGHT_BRACE, /**< "}" */ + LEXER_RIGHT_PAREN, /**< ")" */ + LEXER_RIGHT_SQUARE, /**< "]" */ + LEXER_DOT, /**< "." */ + LEXER_SEMICOLON, /**< ";" */ + LEXER_COLON, /**< ":" */ + LEXER_COMMA, /**< "," */ + LEXER_ARROW, /**< "=>" */ + LEXER_HASHMARK, /**< "#" */ + + LEXER_KEYW_BREAK, /**< break */ + LEXER_KEYW_DO, /**< do */ + LEXER_KEYW_CASE, /**< case */ + LEXER_KEYW_ELSE, /**< else */ + LEXER_KEYW_NEW, /**< new */ + LEXER_KEYW_VAR, /**< var */ + LEXER_KEYW_CATCH, /**< catch */ + LEXER_KEYW_FINALLY, /**< finally */ + LEXER_KEYW_RETURN, /**< return */ + LEXER_KEYW_CONTINUE, /**< continue */ + LEXER_KEYW_FOR, /**< for */ + LEXER_KEYW_SWITCH, /**< switch */ + LEXER_KEYW_WHILE, /**< while */ + LEXER_KEYW_DEBUGGER, /**< debugger */ + LEXER_KEYW_FUNCTION, /**< function */ + LEXER_KEYW_WITH, /**< with */ + LEXER_KEYW_DEFAULT, /**< default */ + LEXER_KEYW_IF, /**< if */ + LEXER_KEYW_THROW, /**< throw */ + LEXER_KEYW_TRY, /**< try */ + + LEXER_KEYW_CLASS, /**< class */ + LEXER_KEYW_EXTENDS, /**< extends */ + LEXER_KEYW_SUPER, /**< super */ + LEXER_KEYW_CONST, /**< const */ + LEXER_KEYW_EXPORT, /**< export */ + LEXER_KEYW_IMPORT, /**< import */ + LEXER_KEYW_ENUM, /**< enum */ + +#define LEXER_FIRST_NON_RESERVED_KEYWORD LEXER_EXPRESSION_START + + /* These are virtual tokens. */ + LEXER_EXPRESSION_START, /**< expression start */ + LEXER_PROPERTY_GETTER, /**< property getter function */ + LEXER_PROPERTY_SETTER, /**< property setter function */ + LEXER_COMMA_SEP_LIST, /**< comma separated bracketed expression list */ + LEXER_ASSIGN_GROUP_EXPR, /**< indetifier for the assignment is located in a group expression */ + LEXER_ASSIGN_CONST, /**< a const binding is reassigned */ + LEXER_INVALID_PATTERN, /**< special value for invalid destructuring pattern */ + LEXER_PRIVATE_PRIMARY_EXPR, /**< private field in primary expession position */ + LEXER_ASSIGN_REFERENCE, /**< special value for reference assignment */ + + /* Keywords which are not keyword tokens. */ + LEXER_KEYW_ASYNC, /**< async */ +#if JERRY_MODULE_SYSTEM + LEXER_KEYW_META, /**< meta */ +#endif /* JERRY_MODULE_SYSTEM */ + +/* Keywords which cannot be assigned in strict mode. */ +#define LEXER_FIRST_NON_STRICT_ARGUMENTS LEXER_KEYW_EVAL + LEXER_KEYW_EVAL, /**< eval */ + LEXER_KEYW_ARGUMENTS, /**< arguments */ + +/* Future strict reserved words: these keywords + * must form a group after non-reserved keywords. */ +#define LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD LEXER_KEYW_IMPLEMENTS + LEXER_KEYW_IMPLEMENTS, /**< implements */ + LEXER_KEYW_PRIVATE, /**< private */ + LEXER_KEYW_PUBLIC, /**< public */ + LEXER_KEYW_INTERFACE, /**< interface */ + LEXER_KEYW_PACKAGE, /**< package */ + LEXER_KEYW_PROTECTED, /**< protected */ + + /* Context dependent future strict reserved words: + * See also: ECMA-262 v6, 11.6.2.1 */ + LEXER_KEYW_LET, /**< let */ + LEXER_KEYW_YIELD, /**< yield */ + LEXER_KEYW_STATIC, /**< static */ +} lexer_token_type_t; + +#define LEXER_NEWLINE_LS_PS_BYTE_1 0xe2 +#define LEXER_NEWLINE_LS_PS_BYTE_23(source) \ + ((source)[1] == LIT_UTF8_2_BYTE_CODE_POINT_MIN && ((source)[2] | 0x1) == 0xa9) + +#define LEXER_IS_LEFT_BRACKET(type) \ + ((type) == LEXER_LEFT_BRACE || (type) == LEXER_LEFT_PAREN || (type) == LEXER_LEFT_SQUARE) + +#define LEXER_IS_RIGHT_BRACKET(type) \ + ((type) == LEXER_RIGHT_BRACE || (type) == LEXER_RIGHT_PAREN || (type) == LEXER_RIGHT_SQUARE) + +#define LEXER_UNARY_OP_TOKEN_TO_OPCODE(token_type) ((((token_type) -LEXER_PLUS) * 2) + CBC_PLUS) + +#define LEXER_UNARY_LVALUE_OP_TOKEN_TO_OPCODE(token_type) ((((token_type) -LEXER_INCREASE) * 6) + CBC_PRE_INCR) + +#define LEXER_BINARY_OP_TOKEN_TO_OPCODE(token_type) ((uint16_t) ((((token_type) -LEXER_BIT_OR) * 3) + CBC_BIT_OR)) + +#define LEXER_BINARY_LVALUE_OP_TOKEN_TO_OPCODE(token_type) \ + ((cbc_opcode_t) ((((token_type) -LEXER_ASSIGN_ADD) * 2) + CBC_ASSIGN_ADD)) + +/** + * Maximum local buffer size for identifiers which contains escape sequences. + */ +#define LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE 48 + +/** + * Lexer newline flags. + */ +typedef enum +{ + LEXER_WAS_NEWLINE = (1u << 0), /**< newline was seen */ + LEXER_NO_SKIP_SPACES = (1u << 1) /**< ignore skip spaces */ +} lexer_newline_flags_t; + +/** + * Lexer object identifier parse options. + */ +typedef enum +{ + LEXER_OBJ_IDENT_NO_OPTS = 0, /**< no options */ + LEXER_OBJ_IDENT_ONLY_IDENTIFIERS = (1u << 0), /**< only identifiers are accepted */ + LEXER_OBJ_IDENT_CLASS_IDENTIFIER = (1u << 1), /**< expect identifier inside a class body */ + LEXER_OBJ_IDENT_CLASS_NO_STATIC = (1u << 2), /**< static keyword was not present before the identifier */ + LEXER_OBJ_IDENT_OBJECT_PATTERN = (1u << 3), /**< parse "get"/"set" as string literal in object pattern */ + LEXER_OBJ_IDENT_CLASS_PRIVATE = (1u << 4), /**< static keyword was not present before the identifier */ +#if JERRY_FUNCTION_TO_STRING + LEXER_OBJ_IDENT_SET_FUNCTION_START = (1u << 5), /**< set function start */ +#else /* !JERRY_FUNCTION_TO_STRING */ + LEXER_OBJ_IDENT_SET_FUNCTION_START = 0, /**< set function start (disabled) */ +#endif /* JERRY_FUNCTION_TO_STRING */ +} lexer_obj_ident_opts_t; + +/** + * Lexer string options. + */ +typedef enum +{ + LEXER_STRING_NO_OPTS = (1u << 0), /**< no options */ + LEXER_STRING_RAW = (1u << 1), /**< raw string ECMAScript v6, 11.8.6.1: TVR */ +} lexer_string_options_t; + +/** + * Lexer number types. + */ +typedef enum +{ + LEXER_NUMBER_DECIMAL, /**< decimal number */ + LEXER_NUMBER_HEXADECIMAL, /**< hexadecimal number */ + LEXER_NUMBER_OCTAL, /**< octal number */ + LEXER_NUMBER_BINARY, /**< binary number */ +#if JERRY_BUILTIN_BIGINT + LEXER_NUMBER_BIGINT, /**< bigint number */ +#endif /* JERRY_BUILTIN_BIGINT */ +} lexer_number_type_t; + +/** + * Lexer literal flags. + **/ +typedef enum +{ + LEXER_LIT_LOCATION_NO_OPTS = 0, /**< no options */ + LEXER_LIT_LOCATION_HAS_ESCAPE = (1 << 0), /**< binding has escape */ + LEXER_LIT_LOCATION_IS_ASCII = (1 << 1), /**< all characters are ascii characters */ +} lexer_lit_location_flags_t; + +/** + * Lexer character (string / identifier) literal data. + */ +typedef struct +{ + const uint8_t *char_p; /**< start of identifier or string token */ + prop_length_t length; /**< length or index of a literal */ + uint8_t type; /**< type of the current literal */ + uint8_t status_flags; /**< any combination of lexer_lit_location_flags_t status bits */ +} lexer_lit_location_t; + +/** + * Lexer token. + */ +typedef struct +{ + uint8_t type; /**< token type */ + uint8_t keyword_type; /**< keyword type for identifiers */ + uint8_t extra_value; /**< helper value for different purposes */ + uint8_t flags; /**< flag bits for the current token */ + parser_line_counter_t line; /**< token start line */ + parser_line_counter_t column; /**< token start column */ + lexer_lit_location_t lit_location; /**< extra data for character literals */ +} lexer_token_t; + +/** + * Literal data set by lexer_construct_literal_object. + */ +typedef struct +{ + lexer_literal_t *literal_p; /**< pointer to the literal object */ + uint16_t index; /**< literal index */ +} lexer_lit_object_t; + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_LEXER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-expr.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-expr.cpp new file mode 100644 index 00000000..f30568a4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-expr.cpp @@ -0,0 +1,4182 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" + +#if JERRY_PARSER +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "js-parser-tagged-template-literal.h" +#include "lit-char-helpers.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_expr Expression parser + * @{ + */ + +/** + * Maximum precedence for right-to-left binary operation evaluation. + */ +#define PARSER_RIGHT_TO_LEFT_ORDER_MAX_PRECEDENCE 7 + +/** + * Precedence for ternary operation. + */ +#define PARSER_RIGHT_TO_LEFT_ORDER_TERNARY_PRECEDENCE 4 + +/** + * Precedence for exponentiation operation. + */ +#define PARSER_RIGHT_TO_LEFT_ORDER_EXPONENTIATION 16 + +/** + * Value of grouping level increase and decrease. + */ +#define PARSER_GROUPING_LEVEL_INCREASE 2 + +/** + * Precedence of the binary tokens. + * + * See also: + * lexer_token_type_t + */ +static const uint8_t parser_binary_precedence_table[] = { + 3, /**< "=" */ + 3, /**< "+=" */ + 3, /**< "-=" */ + 3, /**< "*=" */ + 3, /**< "/=" */ + 3, /**< "=" */ + 3, /**< "<<=" */ + 3, /**< ">>=" */ + 3, /**< ">>>=" */ + 3, /**< "&=" */ + 3, /**< "|=" */ + 3, /**< "^=" */ + 3, /**< "**=" */ + 3, /**< "??=" */ + 3, /**< "||=" */ + 3, /**< "&&=" */ + 4, /**< "?"*/ + 5, /**< "??" */ + 6, /**< "||" */ + 7, /**< "&&" */ + 8, /**< "|" */ + 9, /**< "^" */ + 10, /**< "&" */ + 11, /**< "==" */ + 11, /**< "!=" */ + 11, /**< "===" */ + 11, /**< "!==" */ + 12, /**< "<" */ + 12, /**< ">" */ + 12, /**< "<=" */ + 12, /**< ">=" */ + 12, /**< in */ + 12, /**< instanceof */ + 13, /**< "<<" */ + 13, /**< ">>" */ + 13, /**< ">>>" */ + 14, /**< "+" */ + 14, /**< "-" */ + 15, /**< "*" */ + 15, /**< "/" */ + 15, /**< "%" */ + 16, /**< "**" */ +}; + +JERRY_STATIC_ASSERT ((sizeof (parser_binary_precedence_table) == 42), + parser_binary_precedence_table_should_have_39_values_in_es2015); + +/** + * Generate byte code for operators with lvalue. + */ +static inline void +parser_push_result (parser_context_t *context_p) /**< context */ +{ + if (CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode)) + { + JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, context_p->last_cbc_opcode + 1)); + + if ((context_p->last_cbc_opcode == CBC_POST_INCR || context_p->last_cbc_opcode == CBC_POST_DECR) + && context_p->stack_depth >= context_p->stack_limit) + { + /* Stack limit is increased for CBC_POST_INCR_PUSH_RESULT + * and CBC_POST_DECR_PUSH_RESULT opcodes. Needed by vm.c. */ + JERRY_ASSERT (context_p->stack_depth == context_p->stack_limit); + + context_p->stack_limit++; + + if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + } + + context_p->last_cbc_opcode++; + parser_flush_cbc (context_p); + } +} /* parser_push_result */ + +/** + * Check for invalid assignment for "eval" and "arguments" + */ +static void +parser_check_invalid_assign (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL); + + if (JERRY_UNLIKELY (context_p->status_flags & PARSER_IS_STRICT)) + { + if (context_p->last_cbc.literal_keyword_type == LEXER_KEYW_EVAL) + { + parser_raise_error (context_p, PARSER_ERR_EVAL_CANNOT_ASSIGNED); + } + else if (context_p->last_cbc.literal_keyword_type == LEXER_KEYW_ARGUMENTS) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENTS_CANNOT_ASSIGNED); + } + } +} /* parser_check_invalid_assign */ + +/** + * Check and throw an error if the "new.target" is invalid as a left-hand side expression. + */ +static void +parser_check_invalid_new_target (parser_context_t *context_p, /**< parser context */ + cbc_opcode_t opcode) /**< current opcode under parsing */ +{ + /* new.target is an invalid left-hand side target */ + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_NEW_TARGET)) + { + /* Make sure that the call side is a post/pre increment or an assignment expression. + * There should be no other ways the "new.target" expression should be here. */ + JERRY_ASSERT ( + (opcode >= CBC_PRE_INCR && opcode <= CBC_POST_DECR) + || (opcode == CBC_ASSIGN + && (context_p->token.type == LEXER_ASSIGN || LEXER_IS_BINARY_LVALUE_OP_TOKEN (context_p->token.type)))); + + parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_NOT_ALLOWED); + } +} /* parser_check_invalid_new_target */ + +/** + * Emit identifier reference + */ +static void +parser_emit_ident_reference (parser_context_t *context_p, /**< context */ + uint16_t opcode) /* opcode */ +{ + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = opcode; + return; + } + + uint16_t literal_index; + + if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + literal_index = context_p->last_cbc.value; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_THIS_LITERAL) + { + context_p->last_cbc_opcode = CBC_PUSH_THIS; + literal_index = context_p->last_cbc.literal_index; + } + else + { + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS); + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + literal_index = context_p->last_cbc.third_literal_index; + } + + parser_emit_cbc_literal (context_p, opcode, literal_index); +} /* parser_emit_ident_reference */ + +/** + * Generate byte code for operators with lvalue. + */ +static void +parser_emit_unary_lvalue_opcode (parser_context_t *context_p, /**< context */ + cbc_opcode_t opcode) /**< opcode */ +{ + if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + parser_check_invalid_assign (context_p); + + uint16_t unary_opcode; + + if (opcode == CBC_DELETE_PUSH_RESULT) + { + if (JERRY_UNLIKELY (context_p->status_flags & PARSER_IS_STRICT)) + { + parser_raise_error (context_p, PARSER_ERR_DELETE_IDENT_NOT_ALLOWED); + } + + unary_opcode = CBC_DELETE_IDENT_PUSH_RESULT; + } + else + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_LITERAL, opcode + CBC_UNARY_LVALUE_WITH_IDENT)); + unary_opcode = (uint16_t) (opcode + CBC_UNARY_LVALUE_WITH_IDENT); + } + + parser_emit_ident_reference (context_p, unary_opcode); + + if (unary_opcode != CBC_DELETE_IDENT_PUSH_RESULT + && scanner_literal_is_const_reg (context_p, context_p->last_cbc.literal_index)) + { + /* The current value must be read, but it cannot be changed. */ + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + parser_emit_cbc_ext (context_p, CBC_EXT_THROW_ASSIGN_CONST_ERROR); + } + return; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_PROP) + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP, opcode)); + context_p->last_cbc_opcode = (uint16_t) opcode; + return; + } + + if (PARSER_IS_PUSH_PROP_LITERAL (context_p->last_cbc_opcode)) + { + context_p->last_cbc_opcode = PARSER_PUSH_PROP_LITERAL_TO_PUSH_LITERAL (context_p->last_cbc_opcode); + } + else + { + /* Invalid LeftHandSide expression. */ + if (opcode == CBC_DELETE_PUSH_RESULT) + { + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL)) + { + parser_raise_error (context_p, PARSER_ERR_DELETE_PRIVATE_FIELD); + } + + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL) + || context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_THROW_REFERENCE_ERROR); + parser_emit_cbc (context_p, CBC_POP); + return; + } + + parser_emit_cbc (context_p, CBC_POP); + parser_emit_cbc (context_p, CBC_PUSH_TRUE); + return; + } + + parser_check_invalid_new_target (context_p, opcode); + if (opcode == CBC_PRE_INCR || opcode == CBC_PRE_DECR) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_PREFIX_OP); + } + else + { + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_POSTFIX_OP); + } + } + + parser_emit_cbc (context_p, (uint16_t) opcode); +} /* parser_emit_unary_lvalue_opcode */ + +/** + * Parse array literal. + */ +static void +parser_parse_array_literal (parser_context_t *context_p) /**< context */ +{ + uint32_t pushed_items = 0; + uint16_t opcode = (uint16_t) CBC_ARRAY_APPEND; + + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_SQUARE); + + parser_emit_cbc (context_p, CBC_CREATE_ARRAY); + lexer_next_token (context_p); + + while (true) + { + if (context_p->token.type == LEXER_RIGHT_SQUARE) + { + if (pushed_items > 0) + { + parser_emit_cbc_call (context_p, opcode, pushed_items); + } + return; + } + + pushed_items++; + + if (context_p->token.type == LEXER_COMMA) + { + parser_emit_cbc (context_p, CBC_PUSH_ELISION); + lexer_next_token (context_p); + } + else + { + if (context_p->token.type == LEXER_THREE_DOTS) + { + opcode = (uint16_t) (PARSER_TO_EXT_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND)); + pushed_items++; + lexer_next_token (context_p); + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SPREAD_ELEMENT); + } + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->last_cbc_opcode == CBC_PUSH_THIS) + { + parser_flush_cbc (context_p); + } + + if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + } + else if (context_p->token.type != LEXER_RIGHT_SQUARE) + { + parser_raise_error (context_p, PARSER_ERR_ARRAY_ITEM_SEPARATOR_EXPECTED); + } + } + + if (pushed_items >= 64) + { + parser_emit_cbc_call (context_p, opcode, pushed_items); + opcode = (uint16_t) CBC_ARRAY_APPEND; + pushed_items = 0; + } + } +} /* parser_parse_array_literal */ + +/** Forward definition of parse array initializer. */ +static void parser_parse_array_initializer (parser_context_t *context_p, parser_pattern_flags_t flags); + +/** Forward definition of parse object initializer. */ +static void parser_parse_object_initializer (parser_context_t *context_p, parser_pattern_flags_t flags); + +/** + * Class literal parsing options. + */ +typedef enum +{ + PARSER_CLASS_LITERAL_NO_OPTS = 0, /**< no options are provided */ + PARSER_CLASS_LITERAL_CTOR_PRESENT = (1 << 0), /**< class constructor is present */ + PARSER_CLASS_LITERAL_HERTIAGE_PRESENT = (1 << 1), /**< class heritage is present */ +} parser_class_literal_opts_t; + +/** + * Checks whether the current string or identifier literal is constructor + * + * @return true, if constructor and false otherwise + */ +static inline bool +parser_is_constructor_literal (parser_context_t *context_p) /**< context */ +{ + return (LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type) + && lexer_compare_literal_to_string (context_p, "constructor", 11)); +} /* parser_is_constructor_literal */ + +/** + * Checks if current private field is already declared + */ +static void +parser_check_duplicated_private_field (parser_context_t *context_p, /**< context */ + uint8_t opts) /**< options */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL); + JERRY_ASSERT (context_p->private_context_p); + scanner_class_private_member_t *iter = context_p->private_context_p->members_p; + + bool search_for_property = (opts & SCANNER_PRIVATE_FIELD_PROPERTY); + + while (iter != NULL) + { + if (lexer_compare_identifiers (context_p, &context_p->token.lit_location, &iter->loc) && (iter->u8_arg & opts)) + { + if (iter->u8_arg & SCANNER_PRIVATE_FIELD_SEEN) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_PRIVATE_FIELD); + } + + iter->u8_arg |= SCANNER_PRIVATE_FIELD_SEEN; + + if (!search_for_property) + { + break; + } + } + + iter = iter->prev_p; + } +} /* parser_check_duplicated_private_field */ + +/** + * Parse class literal. + * + * @return true - if the class has static fields, false - otherwise + */ +static bool +parser_parse_class_body (parser_context_t *context_p, /**< context */ + parser_class_literal_opts_t opts, /**< class literal parsing options */ + uint16_t class_name_index) /**< class literal index */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE); + + lexer_literal_t *ctor_literal_p = NULL; + lexer_literal_t *static_fields_literal_p = NULL; + + if (opts & PARSER_CLASS_LITERAL_CTOR_PRESENT) + { + ctor_literal_p = lexer_construct_unused_literal (context_p); + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, (uint16_t) (context_p->literal_count++)); + } + else if (opts & PARSER_CLASS_LITERAL_HERTIAGE_PRESENT) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR); + } + + if (class_name_index != PARSER_INVALID_LITERAL_INDEX) + { + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, class_name_index); + } + + parser_emit_cbc_ext (context_p, CBC_EXT_INIT_CLASS); + + bool is_static = false; + bool is_private = false; + size_t fields_size = 0; + uint32_t computed_field_count = 0; + + while (true) + { + if (!is_static) + { + lexer_skip_empty_statements (context_p); + } + + uint32_t flags = (LEXER_OBJ_IDENT_CLASS_IDENTIFIER | LEXER_OBJ_IDENT_SET_FUNCTION_START); + + if (!is_static) + { + flags |= LEXER_OBJ_IDENT_CLASS_NO_STATIC; + } + + if (is_private) + { + flags |= LEXER_OBJ_IDENT_CLASS_PRIVATE; + } + + lexer_expect_object_literal_id (context_p, flags); + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + JERRY_ASSERT (!is_static); + break; + } + + if (context_p->token.type == LEXER_HASHMARK) + { + is_private = true; + lexer_next_token (context_p); + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + continue; + } + + if (context_p->token.type == LEXER_KEYW_STATIC) + { + JERRY_ASSERT (!is_static); + is_static = true; + continue; + } + + bool is_constructor_literal = false; + + if (context_p->token.type == LEXER_LITERAL) + { + is_constructor_literal = parser_is_constructor_literal (context_p); + + if (is_private) + { + if (is_constructor_literal && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + parser_raise_error (context_p, PARSER_ERR_CLASS_PRIVATE_CONSTRUCTOR); + } + + parser_check_duplicated_private_field (context_p, SCANNER_PRIVATE_FIELD_PROPERTY_GETTER_SETTER); + } + } + + if (!is_static && is_constructor_literal) + { + JERRY_ASSERT (!is_static); + JERRY_ASSERT (opts & PARSER_CLASS_LITERAL_CTOR_PRESENT); + JERRY_ASSERT (ctor_literal_p != NULL); + + if (ctor_literal_p->type == LEXER_FUNCTION_LITERAL) + { + /* 14.5.1 */ + parser_raise_error (context_p, PARSER_ERR_MULTIPLE_CLASS_CONSTRUCTORS); + } + + uint32_t constructor_status_flags = + (PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER | PARSER_CLASS_CONSTRUCTOR | PARSER_LEXICAL_ENV_NEEDED); + + if (opts & PARSER_CLASS_LITERAL_HERTIAGE_PRESENT) + { + constructor_status_flags |= PARSER_ALLOW_SUPER_CALL; + } + + if (context_p->status_flags & PARSER_INSIDE_WITH) + { + constructor_status_flags |= PARSER_INSIDE_WITH; + } + + parser_flush_cbc (context_p); + ecma_compiled_code_t *compiled_code_p = parser_parse_function (context_p, constructor_status_flags); + ctor_literal_p->u.bytecode_p = compiled_code_p; + ctor_literal_p->type = LEXER_FUNCTION_LITERAL; + continue; + } + + bool is_computed = false; + + if (context_p->token.type == LEXER_PROPERTY_GETTER || context_p->token.type == LEXER_PROPERTY_SETTER) + { + uint16_t literal_index, function_literal_index; + bool is_getter = (context_p->token.type == LEXER_PROPERTY_GETTER); + + uint32_t accessor_status_flags = PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER; + accessor_status_flags |= (is_getter ? PARSER_IS_PROPERTY_GETTER : PARSER_IS_PROPERTY_SETTER); + + uint8_t ident_opts = LEXER_OBJ_IDENT_ONLY_IDENTIFIERS; + + if (lexer_check_next_character (context_p, LIT_CHAR_HASHMARK)) + { + lexer_next_token (context_p); + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + ident_opts |= LEXER_OBJ_IDENT_CLASS_PRIVATE; + is_private = true; + } + + lexer_expect_object_literal_id (context_p, ident_opts); + + if (is_private) + { + parser_check_duplicated_private_field (context_p, + is_getter ? SCANNER_PRIVATE_FIELD_GETTER : SCANNER_PRIVATE_FIELD_SETTER); + } + + literal_index = context_p->lit_object.index; + + if (context_p->token.type == LEXER_RIGHT_SQUARE) + { + is_computed = true; + } + else if (is_static && !is_private) + { + if (LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type) + && lexer_compare_identifier_to_string (&context_p->token.lit_location, (uint8_t *) "prototype", 9)) + { + parser_raise_error (context_p, PARSER_ERR_CLASS_STATIC_PROTOTYPE); + } + } + else if (parser_is_constructor_literal (context_p)) + { + JERRY_ASSERT (!is_static || is_private); + parser_raise_error (context_p, PARSER_ERR_CLASS_CONSTRUCTOR_AS_ACCESSOR); + } + + function_literal_index = lexer_construct_function_object (context_p, accessor_status_flags); + + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, literal_index); + + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + cbc_ext_opcode_t opcode; + + if (is_computed) + { + context_p->last_cbc.literal_index = function_literal_index; + + if (is_getter) + { + opcode = is_static ? CBC_EXT_SET_STATIC_COMPUTED_GETTER : CBC_EXT_SET_COMPUTED_GETTER; + } + else + { + opcode = is_static ? CBC_EXT_SET_STATIC_COMPUTED_SETTER : CBC_EXT_SET_COMPUTED_SETTER; + } + } + else + { + context_p->last_cbc.value = function_literal_index; + + if (is_getter) + { + opcode = is_static ? (is_private ? CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER : CBC_EXT_SET_STATIC_GETTER) + : (is_private ? CBC_EXT_COLLECT_PRIVATE_GETTER : CBC_EXT_SET_GETTER); + } + else + { + opcode = is_static ? (is_private ? CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER : CBC_EXT_SET_STATIC_SETTER) + : (is_private ? CBC_EXT_COLLECT_PRIVATE_SETTER : CBC_EXT_SET_SETTER); + } + } + + if (is_computed) + { + parser_emit_cbc_ext (context_p, + is_getter ? CBC_EXT_SET_COMPUTED_GETTER_NAME : CBC_EXT_SET_COMPUTED_SETTER_NAME); + parser_emit_cbc_ext (context_p, opcode); + } + else + { + if (is_private) + { + accessor_status_flags |= PARSER_PRIVATE_FUNCTION_NAME; + } + parser_set_function_name (context_p, function_literal_index, literal_index, accessor_status_flags); + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (opcode); + } + + is_static = false; + is_private = false; + continue; + } + + uint32_t status_flags = PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER; + + if (context_p->token.type == LEXER_KEYW_ASYNC) + { + status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + + uint8_t ident_opts = LEXER_OBJ_IDENT_ONLY_IDENTIFIERS; + + if (lexer_check_next_character (context_p, LIT_CHAR_HASHMARK)) + { + lexer_next_token (context_p); + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + ident_opts |= LEXER_OBJ_IDENT_CLASS_PRIVATE; + is_private = true; + } + + if (!lexer_consume_generator (context_p)) + { + lexer_expect_object_literal_id (context_p, ident_opts); + } + + if (is_private && context_p->token.type == LEXER_LITERAL) + { + if (parser_is_constructor_literal (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_CLASS_PRIVATE_CONSTRUCTOR); + } + + parser_check_duplicated_private_field (context_p, SCANNER_PRIVATE_FIELD_PROPERTY_GETTER_SETTER); + } + } + + if (context_p->token.type == LEXER_MULTIPLY) + { + uint8_t ident_opts = LEXER_OBJ_IDENT_ONLY_IDENTIFIERS; + + if (lexer_check_next_character (context_p, LIT_CHAR_HASHMARK)) + { + lexer_next_token (context_p); + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + ident_opts |= LEXER_OBJ_IDENT_CLASS_PRIVATE; + is_private = true; + } + + lexer_expect_object_literal_id (context_p, ident_opts); + + status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + + if (is_private && context_p->token.type == LEXER_LITERAL) + { + if (parser_is_constructor_literal (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_CLASS_PRIVATE_CONSTRUCTOR); + } + + parser_check_duplicated_private_field (context_p, SCANNER_PRIVATE_FIELD_PROPERTY_GETTER_SETTER); + } + } + + bool is_static_block = context_p->token.type == LEXER_LEFT_BRACE; + + if (context_p->token.type == LEXER_RIGHT_SQUARE) + { + is_computed = true; + } + else if (!is_static_block && LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)) + { + if (is_static && !is_private) + { + if (lexer_compare_identifier_to_string (&context_p->token.lit_location, (uint8_t *) "prototype", 9)) + { + parser_raise_error (context_p, PARSER_ERR_CLASS_STATIC_PROTOTYPE); + } + } + else if ((status_flags & (PARSER_IS_ASYNC_FUNCTION | PARSER_IS_GENERATOR_FUNCTION)) + && lexer_compare_literal_to_string (context_p, "constructor", 11)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CLASS_CONSTRUCTOR); + } + } + + if (!(status_flags & (PARSER_IS_ASYNC_FUNCTION | PARSER_IS_GENERATOR_FUNCTION))) + { + if (is_static_block || !lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + /* Class field. */ + if (fields_size == 0) + { + parser_stack_push_uint8 (context_p, PARSER_CLASS_FIELD_END); + } + + scanner_range_t range; + uint8_t class_field_type = is_static ? PARSER_CLASS_FIELD_STATIC : 0; + + if (!is_computed) + { + if (is_private) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + uint8_t field_opcode = is_static ? CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD : CBC_EXT_COLLECT_PRIVATE_FIELD; + parser_emit_cbc_ext_literal_from_token (context_p, field_opcode); + } + + if (is_static && !is_static_block && parser_is_constructor_literal (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIST_EXPECTED); + } + + range.start_location.source_p = context_p->token.lit_location.char_p; + range.start_location.line = context_p->token.line; + range.start_location.column = context_p->token.column; + class_field_type |= PARSER_CLASS_FIELD_NORMAL; + + if (context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + range.start_location.source_p--; + } + } + else + { + if (++computed_field_count > ECMA_INTEGER_NUMBER_MAX) + { + parser_raise_error (context_p, PARSER_ERR_TOO_MANY_CLASS_FIELDS); + } + + if (is_static && static_fields_literal_p == NULL) + { + static_fields_literal_p = lexer_construct_unused_literal (context_p); + parser_emit_cbc_ext_literal (context_p, + CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC, + (uint16_t) (context_p->literal_count++)); + } + else + { + parser_emit_cbc_ext (context_p, + (is_static ? CBC_EXT_ADD_STATIC_COMPUTED_FIELD : CBC_EXT_ADD_COMPUTED_FIELD)); + } + } + + if (is_static_block) + { + class_field_type |= PARSER_CLASS_FIELD_STATIC_BLOCK; + + if (context_p->next_scanner_info_p->type != SCANNER_TYPE_CLASS_STATIC_BLOCK_END) + { + parser_flush_cbc (context_p); + parser_parse_class_static_block (context_p); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_CLASS_STATIC_BLOCK_END); + + scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location); + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + range.start_location.source_p = context_p->next_scanner_info_p->source_p - 1; + + scanner_seek (context_p); + + parser_stack_push (context_p, &range.start_location, sizeof (scanner_location_t)); + fields_size += sizeof (scanner_location_t); + + lexer_consume_next_character (context_p); + } + else if (lexer_consume_assign (context_p)) + { + class_field_type |= PARSER_CLASS_FIELD_INITIALIZED; + + if (context_p->next_scanner_info_p->source_p != context_p->source_p) + { + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + + if (is_computed) + { + scanner_get_location (&range.start_location, context_p); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END); + range.source_end_p = ((scanner_location_info_t *) context_p->next_scanner_info_p)->location.source_p; + + scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location); + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + scanner_seek (context_p); + + parser_stack_push (context_p, &range, sizeof (scanner_range_t)); + fields_size += sizeof (scanner_range_t); + } + else + { + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) + && !lexer_check_next_characters (context_p, LIT_CHAR_SEMICOLON, LIT_CHAR_RIGHT_BRACE)) + { + lexer_next_token (context_p); + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + + if (!is_computed) + { + parser_stack_push (context_p, &range.start_location, sizeof (scanner_location_t)); + fields_size += sizeof (scanner_location_t); + } + } + + parser_stack_push_uint8 (context_p, class_field_type); + fields_size++; + is_static = false; + is_private = false; + continue; + } + + if (!is_computed) + { + if (context_p->token.lit_location.type != LEXER_NUMBER_LITERAL) + { + JERRY_ASSERT (context_p->token.lit_location.type == LEXER_IDENT_LITERAL + || context_p->token.lit_location.type == LEXER_STRING_LITERAL); + if (is_private) + { + parser_resolve_private_identifier (context_p); + } + else + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + } + } + else + { + lexer_construct_number_object (context_p, false, false); + } + } + } + + uint16_t literal_index = context_p->lit_object.index; + uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags | PARSER_IS_METHOD); + + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, function_literal_index); + + if (is_computed) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + parser_emit_cbc_ext (context_p, is_static ? CBC_EXT_SET_STATIC_COMPUTED_PROPERTY : CBC_EXT_SET_COMPUTED_PROPERTY); + is_static = false; + continue; + } + + uint32_t function_name_status_flags = 0; + + if (is_private) + { + function_name_status_flags = PARSER_PRIVATE_FUNCTION_NAME; + } + + parser_set_function_name (context_p, function_literal_index, literal_index, function_name_status_flags); + + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + context_p->last_cbc.value = literal_index; + + if (is_static) + { + context_p->last_cbc_opcode = (is_private ? PARSER_TO_EXT_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD) + : PARSER_TO_EXT_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL)); + is_static = false; + } + else if (is_private) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_COLLECT_PRIVATE_METHOD); + } + else + { + context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; + } + + is_private = false; + } + + if (fields_size == 0) + { + return false; + } + + parser_reverse_class_fields (context_p, fields_size); + + /* Since PARSER_IS_ARROW_FUNCTION and PARSER_CLASS_CONSTRUCTOR bits cannot + * be set at the same time, this bit combination triggers class field parsing. */ + + if (!(context_p->stack_top_uint8 & PARSER_CLASS_FIELD_STATIC)) + { + lexer_literal_t *literal_p = lexer_construct_unused_literal (context_p); + + uint16_t function_literal_index = (uint16_t) (context_p->literal_count++); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_FIELD_INIT, function_literal_index); + parser_flush_cbc (context_p); + + literal_p->u.bytecode_p = parser_parse_class_fields (context_p); + literal_p->type = LEXER_FUNCTION_LITERAL; + } + + bool has_static_field = false; + + if (context_p->stack_top_uint8 & PARSER_CLASS_FIELD_STATIC) + { + if (static_fields_literal_p == NULL) + { + static_fields_literal_p = lexer_construct_unused_literal (context_p); + uint16_t function_literal_index = (uint16_t) (context_p->literal_count++); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_PUSH_STATIC_FIELD_FUNC, function_literal_index); + } + + parser_flush_cbc (context_p); + static_fields_literal_p->u.bytecode_p = parser_parse_class_fields (context_p); + static_fields_literal_p->type = LEXER_FUNCTION_LITERAL; + + has_static_field = true; + } + + parser_stack_pop_uint8 (context_p); + return has_static_field; +} /* parser_parse_class_body */ + +/** + * Parse class statement or expression. + */ +void +parser_parse_class (parser_context_t *context_p, /**< context */ + bool is_statement) /**< true - if class is parsed as a statement + * false - otherwise (as an expression) */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS); + + uint16_t class_ident_index = PARSER_INVALID_LITERAL_INDEX; + uint16_t class_name_index = PARSER_INVALID_LITERAL_INDEX; + parser_class_literal_opts_t opts = PARSER_CLASS_LITERAL_NO_OPTS; + scanner_info_t *scanner_info_p = context_p->next_scanner_info_p; + + scanner_class_info_t *class_info_p = (scanner_class_info_t *) scanner_info_p; + parser_private_context_t private_ctx; + + if (scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_CLASS_CONSTRUCTOR); + parser_save_private_context (context_p, &private_ctx, class_info_p); + + if (scanner_info_p->u8_arg & SCANNER_CONSTRUCTOR_EXPLICIT) + { + opts = (parser_class_literal_opts_t) ((int) opts | (int) PARSER_CLASS_LITERAL_CTOR_PRESENT); + } + + scanner_release_next (context_p, sizeof (scanner_class_info_t)); + } + + if (is_statement) + { + /* Class statement must contain an identifier. */ + lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL); + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + class_ident_index = context_p->lit_object.index; + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED; + class_name_index = context_p->lit_object.index; + +#if JERRY_MODULE_SYSTEM + parser_module_append_export_name (context_p); + context_p->status_flags &= (uint32_t) ~PARSER_MODULE_STORE_IDENT; +#endif /* JERRY_MODULE_SYSTEM */ + + lexer_next_token (context_p); + } + else + { + lexer_next_token (context_p); + + /* Class expression may contain an identifier. */ + if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED; + class_name_index = context_p->lit_object.index; + lexer_next_token (context_p); + } + } + + if (class_name_index != PARSER_INVALID_LITERAL_INDEX) + { + if (JERRY_UNLIKELY (context_p->scope_stack_top >= context_p->scope_stack_size)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + PARSER_PLUS_EQUAL_U16 (context_p->scope_stack_top, 1); + scope_stack_p->map_from = class_name_index; + scope_stack_p->map_to = 0; + + parser_emit_cbc_ext_literal (context_p, CBC_EXT_PUSH_NAMED_CLASS_ENV, class_name_index); + } + else + { + parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED); + } + + bool is_strict = (context_p->status_flags & PARSER_IS_STRICT) != 0; + + /* 14.5. A ClassBody is always strict code. */ + context_p->status_flags |= PARSER_IS_STRICT; + + if (context_p->token.type == LEXER_KEYW_EXTENDS) + { + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR | PARSE_EXPR_LEFT_HAND_SIDE); + opts = (parser_class_literal_opts_t) ((int) opts | (int) PARSER_CLASS_LITERAL_HERTIAGE_PRESENT); + } + else + { + /* Elisions represents that the classHeritage is not present */ + parser_emit_cbc (context_p, CBC_PUSH_ELISION); + } + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + + context_p->private_context_p->opts |= SCANNER_PRIVATE_FIELD_ACTIVE; + + /* ClassDeclaration is parsed. Continue with class body. */ + bool has_static_field = parser_parse_class_body (context_p, opts, class_name_index); + + if (class_name_index != PARSER_INVALID_LITERAL_INDEX) + { + parser_emit_cbc_ext_literal (context_p, CBC_EXT_FINALIZE_NAMED_CLASS, class_name_index); + PARSER_MINUS_EQUAL_U16 (context_p->scope_stack_top, 1); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_FINALIZE_ANONYMOUS_CLASS); + } + + if (has_static_field) + { + parser_emit_cbc_ext (context_p, CBC_EXT_RUN_STATIC_FIELD_INIT); + } + + if (is_statement) + { + cbc_opcode_t opcode = CBC_MOV_IDENT; + + if (class_ident_index < PARSER_REGISTER_START) + { + opcode = (scanner_literal_is_created (context_p, class_ident_index) ? CBC_ASSIGN_LET_CONST : CBC_INIT_LET); + } + + parser_emit_cbc_literal (context_p, (uint16_t) opcode, class_ident_index); + parser_flush_cbc (context_p); + } + + if (!is_strict) + { + /* Restore flag */ + context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT; + } + context_p->status_flags &= (uint32_t) ~PARSER_ALLOW_SUPER; + + parser_restore_private_context (context_p, &private_ctx); + + lexer_next_token (context_p); +} /* parser_parse_class */ + +/** + * Parse object initializer method definition. + * + * See also: ES2015 14.3 + */ +static void +parser_parse_object_method (parser_context_t *context_p) /**< context */ +{ + context_p->source_p--; + context_p->column--; + uint16_t function_literal_index = + lexer_construct_function_object (context_p, (PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER | PARSER_IS_METHOD)); + + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, function_literal_index); + + context_p->last_cbc.literal_type = LEXER_FUNCTION_LITERAL; + + lexer_next_token (context_p); +} /* parser_parse_object_method */ + +/** + * Reparse the current literal as a common identifier. + */ +static void +parser_reparse_as_common_identifier (parser_context_t *context_p, /**< context */ + parser_line_counter_t start_line, /**< start line */ + parser_line_counter_t start_column) /**< start column */ +{ + /* context_p->token.lit_location.char_p is showing the character after the string start, + so it is not suitable for reparsing as identifier. + e.g.: { 'foo' } */ + if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + context_p->source_p = context_p->token.lit_location.char_p; + context_p->line = start_line; + context_p->column = start_column; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + JERRY_ASSERT (context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL); + +} /* parser_reparse_as_common_identifier */ + +/** + * Parse object literal. + */ +static void +parser_parse_object_literal (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE); + + parser_emit_cbc (context_p, CBC_CREATE_OBJECT); + + bool proto_seen = false; + bool has_super_env = false; + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS); + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_SUPER) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT); + has_super_env = true; + } + + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + + while (true) + { + lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_SET_FUNCTION_START); + + switch (context_p->token.type) + { + case LEXER_RIGHT_BRACE: + { + break; + } + case LEXER_PROPERTY_GETTER: + case LEXER_PROPERTY_SETTER: + { + uint32_t status_flags; + cbc_ext_opcode_t opcode; + bool is_getter = context_p->token.type == LEXER_PROPERTY_GETTER; + + if (is_getter) + { + status_flags = PARSER_FUNCTION_CLOSURE | PARSER_IS_PROPERTY_GETTER; + opcode = CBC_EXT_SET_GETTER; + } + else + { + status_flags = PARSER_FUNCTION_CLOSURE | PARSER_IS_PROPERTY_SETTER; + opcode = CBC_EXT_SET_SETTER; + } + + status_flags |= PARSER_ALLOW_SUPER; + + lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS); + + /* This assignment is a nop for computed getters/setters. */ + uint16_t literal_index = context_p->lit_object.index; + + bool is_computed = context_p->token.type == LEXER_RIGHT_SQUARE; + + if (is_computed) + { + opcode = ((opcode == CBC_EXT_SET_GETTER) ? CBC_EXT_SET_COMPUTED_GETTER : CBC_EXT_SET_COMPUTED_SETTER); + } + + uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags); + + if (opcode >= CBC_EXT_SET_COMPUTED_GETTER) + { + literal_index = function_literal_index; + } + + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, literal_index); + + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + if (is_computed) + { + parser_emit_cbc_ext (context_p, + is_getter ? CBC_EXT_SET_COMPUTED_GETTER_NAME : CBC_EXT_SET_COMPUTED_SETTER_NAME); + + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED); + } + parser_emit_cbc_ext (context_p, opcode); + lexer_next_token (context_p); + break; + } + + parser_set_function_name (context_p, function_literal_index, literal_index, status_flags); + + if (has_super_env) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + context_p->last_cbc.value = function_literal_index; + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED); + parser_emit_cbc_ext (context_p, is_getter ? CBC_EXT_SET_COMPUTED_GETTER : CBC_EXT_SET_COMPUTED_SETTER); + } + else + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (opcode); + context_p->last_cbc.value = function_literal_index; + } + + lexer_next_token (context_p); + break; + } + case LEXER_RIGHT_SQUARE: + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + parser_parse_object_method (context_p); + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + if (parser_check_anonymous_function_declaration (context_p) < PARSER_NAMED_FUNCTION) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED); + } + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_PROPERTY); + } + else + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL); + } + + break; + } + + if (context_p->token.type != LEXER_COLON) + { + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (parser_check_anonymous_function_declaration (context_p) < PARSER_NAMED_FUNCTION) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_PROPERTY); + } + break; + } + case LEXER_THREE_DOTS: + { + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + parser_emit_cbc_ext (context_p, CBC_EXT_COPY_DATA_PROPERTIES); + break; + } + case LEXER_KEYW_ASYNC: + case LEXER_MULTIPLY: + { + uint32_t status_flags = PARSER_FUNCTION_CLOSURE; + + if (context_p->token.type == LEXER_KEYW_ASYNC) + { + status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + lexer_consume_generator (context_p); + } + + if (context_p->token.type == LEXER_MULTIPLY) + { + status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + } + + if (has_super_env) + { + status_flags |= PARSER_ALLOW_SUPER; + } + + lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS); + + uint16_t opcode = CBC_SET_LITERAL_PROPERTY; + /* This assignment is a nop for CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL. */ + uint16_t literal_index = context_p->lit_object.index; + bool is_computed = context_p->token.type == LEXER_RIGHT_SQUARE; + + if (is_computed) + { + opcode = CBC_EXT_SET_COMPUTED_PROPERTY; + } + + uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags); + + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, function_literal_index); + + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + if (is_computed) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED); + } + parser_emit_cbc_ext (context_p, opcode); + lexer_next_token (context_p); + break; + } + + parser_set_function_name (context_p, function_literal_index, literal_index, status_flags); + + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT); + parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, literal_index); + } + else + { + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.value = literal_index; + } + + lexer_next_token (context_p); + break; + } + default: + { + const lexer_lit_location_t *literal_p = (const lexer_lit_location_t *) context_p->lit_object.literal_p; + bool is_proto = ((context_p->token.lit_location.type == LEXER_IDENT_LITERAL + || context_p->token.lit_location.type == LEXER_STRING_LITERAL) + && lexer_compare_identifier_to_string (literal_p, (uint8_t *) "__proto__", 9) + && lexer_check_next_character (context_p, LIT_CHAR_COLON)); + if (is_proto) + { + if (proto_seen) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_PROTO); + } + + proto_seen = true; + } + + uint16_t literal_index = context_p->lit_object.index; + parser_line_counter_t start_line = context_p->token.line; + parser_line_counter_t start_column = context_p->token.column; + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_PAREN && !is_proto) + { + parser_parse_object_method (context_p); + + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + parser_set_function_name (context_p, context_p->last_cbc.literal_index, literal_index, 0); + + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT); + parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, literal_index); + break; + } + + context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; + context_p->last_cbc.value = literal_index; + break; + } + + if ((context_p->token.type == LEXER_RIGHT_BRACE || context_p->token.type == LEXER_COMMA) && !is_proto) + { + parser_reparse_as_common_identifier (context_p, start_line, start_column); + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + + context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; + context_p->last_cbc.value = literal_index; + + lexer_next_token (context_p); + break; + } + + if (context_p->token.type != LEXER_COLON) + { + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (is_proto) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET__PROTO__); + break; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + if (context_p->last_cbc.literal_type == LEXER_FUNCTION_LITERAL) + { + parser_set_function_name (context_p, context_p->last_cbc.literal_index, literal_index, 0); + } + context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; + context_p->last_cbc.value = literal_index; + } + else + { + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS)) + { + uint16_t name_index = scanner_save_literal (context_p, literal_index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + + parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, literal_index); + } + + break; + } + } + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + break; + } + else if (context_p->token.type != LEXER_COMMA) + { + parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED); + } + } + + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT); + } +} /* parser_parse_object_literal */ + +/** + * Parse function literal. + */ +static void +parser_parse_function_expression (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< function status flags */ +{ + int literals = 0; + uint16_t literal1 = 0; + uint16_t literal2 = 0; + uint16_t function_literal_index; + int32_t function_name_index = -1; + + if (status_flags & PARSER_IS_FUNC_EXPRESSION) + { + uint32_t parent_status_flags = context_p->status_flags; + + context_p->status_flags &= + (uint32_t) ~(PARSER_IS_ASYNC_FUNCTION | PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD); + + if (status_flags & PARSER_IS_ASYNC_FUNCTION) + { + /* The name of the function cannot be await. */ + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + } + + if (lexer_consume_generator (context_p)) + { + /* The name of the function cannot be yield. */ + context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + } + + if (!lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + /* The `await` keyword is interpreted as an IdentifierReference within function expressions */ + context_p->status_flags &= (uint32_t) ~PARSER_IS_CLASS_STATIC_BLOCK; + + lexer_next_token (context_p); + + context_p->status_flags |= parent_status_flags & PARSER_IS_CLASS_STATIC_BLOCK; + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + parser_flush_cbc (context_p); + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + + if (context_p->token.keyword_type >= LEXER_FIRST_NON_STRICT_ARGUMENTS) + { + status_flags |= PARSER_HAS_NON_STRICT_ARG; + } + + function_name_index = context_p->lit_object.index; + } + + context_p->status_flags = parent_status_flags; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + literals = 1; + literal1 = context_p->last_cbc.literal_index; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + literals = 2; + literal1 = context_p->last_cbc.literal_index; + literal2 = context_p->last_cbc.value; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + + function_literal_index = lexer_construct_function_object (context_p, status_flags); + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + if (function_name_index != -1) + { + parser_set_function_name (context_p, function_literal_index, (uint16_t) function_name_index, 0); + } + + if (literals == 1) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + context_p->last_cbc.literal_index = literal1; + context_p->last_cbc.value = function_literal_index; + } + else if (literals == 2) + { + context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS; + context_p->last_cbc.literal_index = literal1; + context_p->last_cbc.value = literal2; + context_p->last_cbc.third_literal_index = function_literal_index; + } + else + { + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, function_literal_index); + + if (function_name_index != -1) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION); + context_p->last_cbc.value = (uint16_t) function_name_index; + } + } + + context_p->last_cbc.literal_type = LEXER_FUNCTION_LITERAL; + context_p->last_cbc.literal_keyword_type = LEXER_EOS; +} /* parser_parse_function_expression */ + +/** + * Parse template literal. + */ +static void +parser_parse_template_literal (parser_context_t *context_p) /**< context */ +{ + bool is_empty_head = true; + + if (context_p->token.lit_location.length > 0) + { + is_empty_head = false; + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, context_p->token.lit_location.type); + + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + + if (!is_empty_head) + { + if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS); + } + else if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_STRING_CONCAT); + } + } + + context_p->source_p--; + context_p->column--; + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + + if (is_empty_head || context_p->token.lit_location.length > 0) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, context_p->token.lit_location.type); + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS); + context_p->last_cbc.value = context_p->lit_object.index; + context_p->last_cbc.literal_type = context_p->token.lit_location.type; + context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type; + } + else + { + parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_STRING_CONCAT_RIGHT_LITERAL); + } + } + + while (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT) + { + lexer_next_token (context_p); + + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_STRING_CONCAT); + } + + context_p->source_p--; + context_p->column--; + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + + if (context_p->token.lit_location.length > 0) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, context_p->token.lit_location.type); + + parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_STRING_CONCAT_RIGHT_LITERAL); + } + } +} /* parser_parse_template_literal */ + +/** + * Parse tagged template literal. + */ +static size_t +parser_parse_tagged_template_literal (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_TEMPLATE_LITERAL); + + uint32_t call_arguments = 0; + ecma_collection_t *collection_p; + + if (context_p->tagged_template_literal_cp == JMEM_CP_NULL) + { + collection_p = ecma_new_collection (); + ECMA_SET_INTERNAL_VALUE_POINTER (context_p->tagged_template_literal_cp, collection_p); + } + else + { + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, context_p->tagged_template_literal_cp); + if (collection_p->item_count > CBC_MAXIMUM_BYTE_VALUE) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED); + } + } + + const uint32_t tagged_id = collection_p->item_count; + uint32_t prop_idx = 0; + ecma_object_t *raw_strings_p; + ecma_object_t *template_obj_p = parser_new_tagged_template_literal (&raw_strings_p); + ecma_collection_push_back (collection_p, ecma_make_object_value (template_obj_p)); + + parser_tagged_template_literal_append_strings (context_p, template_obj_p, raw_strings_p, prop_idx++); + + call_arguments++; + parser_emit_cbc_ext_call (context_p, CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, tagged_id); + + while (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT) + { + JERRY_ASSERT (context_p->source_p[-1] == LIT_CHAR_LEFT_BRACE); + lexer_next_token (context_p); + + if (++call_arguments > CBC_MAXIMUM_BYTE_VALUE) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED); + } + + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + + context_p->source_p--; + context_p->column--; + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + + parser_tagged_template_literal_append_strings (context_p, template_obj_p, raw_strings_p, prop_idx++); + } + + parser_tagged_template_literal_finalize (template_obj_p, raw_strings_p); + + return call_arguments; +} /* parser_parse_tagged_template_literal */ + +/** + * Checks wheteher the current expression can be an assignment expression. + * + * @return true if the current expression can be an assignment expression, false otherwise + */ +static inline bool +parser_is_assignment_expr (parser_context_t *context_p) +{ + return (context_p->stack_top_uint8 == LEXER_EXPRESSION_START || context_p->stack_top_uint8 == LEXER_LEFT_PAREN + || context_p->stack_top_uint8 == LEXER_COMMA_SEP_LIST + || LEXER_IS_BINARY_LVALUE_OP_TOKEN (context_p->stack_top_uint8)); +} /* parser_is_assignment_expr */ + +/** + * Throws an error if the current expression is not an assignment expression. + */ +static inline void +parser_check_assignment_expr (parser_context_t *context_p) +{ + if (!parser_is_assignment_expr (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_ASSIGNMENT_EXPECTED); + } +} /* parser_check_assignment_expr */ + +/** + * Checks whether the next token is a valid continuation token after an AssignmentExpression. + */ +static inline bool +parser_abort_parsing_after_assignment_expression (parser_context_t *context_p) +{ + return (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_COMMA); +} /* parser_abort_parsing_after_assignment_expression */ + +/** + * Parse and record unary operators, and parse the primary literal. + * + * @return true if parsing should be aborted, true otherwise + */ +static bool +parser_parse_unary_expression (parser_context_t *context_p, /**< context */ + size_t *grouping_level_p) /**< grouping level */ +{ + bool new_was_seen = false; + + /* Collect unary operators. */ + while (true) + { + /* Convert plus and minus binary operators to unary operators. */ + switch (context_p->token.type) + { + case LEXER_ADD: + { + context_p->token.type = LEXER_PLUS; + break; + } + case LEXER_SUBTRACT: + { + context_p->token.type = LEXER_NEGATE; + break; + } + case LEXER_KEYW_AWAIT: + { +#if JERRY_MODULE_SYSTEM + if ((context_p->global_status_flags & ECMA_PARSE_MODULE) + && !(context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)) + { + parser_raise_error (context_p, PARSER_ERR_AWAIT_NOT_ALLOWED); + } +#endif /* JERRY_MODULE_SYSTEM */ + + if (JERRY_UNLIKELY (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + break; + } + } + + /* Bracketed expressions are primary expressions. At this + * point their left paren is pushed onto the stack and + * they are processed when their closing paren is reached. */ + if (context_p->token.type == LEXER_LEFT_PAREN) + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + break; + } + (*grouping_level_p) += PARSER_GROUPING_LEVEL_INCREASE; + new_was_seen = false; + } + else if (context_p->token.type == LEXER_KEYW_NEW) + { + /* After 'new' unary operators are not allowed. */ + new_was_seen = true; + + /* Check if "new.target" is written here. */ + if (scanner_try_scan_new_target (context_p)) + { + if (!(context_p->status_flags & PARSER_ALLOW_NEW_TARGET)) + { + parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_NOT_ALLOWED); + } + + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_NEW_TARGET); + lexer_next_token (context_p); + /* Found "new.target" return here */ + return false; + } + } + else if (new_was_seen || (*grouping_level_p == PARSE_EXPR_LEFT_HAND_SIDE) + || !LEXER_IS_UNARY_OP_TOKEN (context_p->token.type)) + { + break; + } + + parser_stack_push_uint8 (context_p, context_p->token.type); + lexer_next_token (context_p); + } + + /* Parse primary expression. */ + switch (context_p->token.type) + { + case LEXER_HASHMARK: + { + if (!lexer_scan_private_identifier (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); + } + + parser_resolve_private_identifier (context_p); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_KEYW_IN) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); + } + + parser_stack_push_uint16 (context_p, context_p->lit_object.index); + parser_stack_push_uint8 (context_p, LEXER_PRIVATE_PRIMARY_EXPR); + return false; + } + case LEXER_TEMPLATE_LITERAL: + { + if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT) + { + parser_parse_template_literal (context_p); + break; + } + + /* The string is a normal string literal. */ + /* FALLTHRU */ + } + case LEXER_LITERAL: + { + if (JERRY_UNLIKELY (context_p->next_scanner_info_p->source_p == context_p->source_p)) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = context_p->token.lit_location.char_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + + uint32_t arrow_status_flags = + (PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION + | (context_p->status_flags & (PARSER_INSIDE_CLASS_FIELD | PARSER_IS_CLASS_STATIC_BLOCK))); + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC) + { + JERRY_ASSERT (lexer_token_is_async (context_p)); + JERRY_ASSERT (!(context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_STATEMENT)); + + uint32_t saved_status_flags = context_p->status_flags; + + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + lexer_next_token (context_p); + context_p->status_flags = saved_status_flags; + + if (context_p->token.type == LEXER_KEYW_FUNCTION) + { + uint32_t status_flags = (PARSER_FUNCTION_CLOSURE | PARSER_IS_FUNC_EXPRESSION | PARSER_IS_ASYNC_FUNCTION + | PARSER_DISALLOW_AWAIT_YIELD); + parser_parse_function_expression (context_p, status_flags); + break; + } + + arrow_status_flags = + (PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION | PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD); + } + + parser_check_assignment_expr (context_p); + parser_parse_function_expression (context_p, arrow_status_flags); + return parser_abort_parsing_after_assignment_expression (context_p); + } + + uint8_t type = context_p->token.lit_location.type; + + if (type == LEXER_IDENT_LITERAL || type == LEXER_STRING_LITERAL) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, context_p->token.lit_location.type); + } + else if (type == LEXER_NUMBER_LITERAL) + { + bool is_negative_number = false; + + if ((context_p->stack_top_uint8 == LEXER_PLUS || context_p->stack_top_uint8 == LEXER_NEGATE) + && !lexer_check_post_primary_exp (context_p)) + { + do + { + if (context_p->stack_top_uint8 == LEXER_NEGATE) + { + is_negative_number = !is_negative_number; + } +#if JERRY_BUILTIN_BIGINT + else if (JERRY_LIKELY (context_p->token.extra_value == LEXER_NUMBER_BIGINT)) + { + break; + } +#endif /* JERRY_BUILTIN_BIGINT */ + parser_stack_pop_uint8 (context_p); + } while (context_p->stack_top_uint8 == LEXER_PLUS || context_p->stack_top_uint8 == LEXER_NEGATE); + } + + if (lexer_construct_number_object (context_p, true, is_negative_number)) + { + JERRY_ASSERT (context_p->lit_object.index <= CBC_PUSH_NUMBER_BYTE_RANGE_END); + + parser_emit_cbc_push_number (context_p, is_negative_number); + break; + } + } + + cbc_opcode_t opcode = CBC_PUSH_LITERAL; + + if (context_p->token.keyword_type != LEXER_KEYW_EVAL) + { + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + context_p->last_cbc.value = context_p->lit_object.index; + context_p->last_cbc.literal_type = context_p->token.lit_location.type; + context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type; + break; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS; + context_p->last_cbc.third_literal_index = context_p->lit_object.index; + context_p->last_cbc.literal_type = context_p->token.lit_location.type; + context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type; + break; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_THIS) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_PUSH_THIS_LITERAL; + } + } + + parser_emit_cbc_literal_from_token (context_p, (uint16_t) opcode); + break; + } + case LEXER_KEYW_FUNCTION: + { +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = context_p->token.lit_location.char_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + parser_parse_function_expression (context_p, PARSER_FUNCTION_CLOSURE | PARSER_IS_FUNC_EXPRESSION); + break; + } + case LEXER_LEFT_BRACE: + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER) + { + if (parser_is_assignment_expr (context_p)) + { + uint32_t flags = PARSER_PATTERN_NO_OPTS; + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags |= PARSER_PATTERN_HAS_REST_ELEMENT; + } + + parser_parse_object_initializer (context_p, (parser_pattern_flags_t) flags); + return parser_abort_parsing_after_assignment_expression (context_p); + } + + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + } + + parser_parse_object_literal (context_p); + break; + } + case LEXER_LEFT_SQUARE: + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER) + { + if (parser_is_assignment_expr (context_p)) + { + parser_parse_array_initializer (context_p, PARSER_PATTERN_NO_OPTS); + return parser_abort_parsing_after_assignment_expression (context_p); + } + + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + } + else + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS + && context_p->next_scanner_info_p->u8_arg == SCANNER_LITERAL_NO_DESTRUCTURING); + + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + } + + parser_parse_array_literal (context_p); + break; + } + case LEXER_DIVIDE: + case LEXER_ASSIGN_DIVIDE: + { + lexer_construct_regexp_object (context_p, false); + uint16_t literal_index = (uint16_t) (context_p->literal_count - 1); + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + context_p->last_cbc.value = literal_index; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS; + context_p->last_cbc.third_literal_index = literal_index; + } + else + { + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, literal_index); + } + + context_p->last_cbc.literal_type = LEXER_REGEXP_LITERAL; + context_p->last_cbc.literal_keyword_type = LEXER_EOS; + break; + } + case LEXER_KEYW_THIS: + { + if (context_p->status_flags & PARSER_ALLOW_SUPER_CALL) + { + parser_emit_cbc_ext (context_p, CBC_EXT_RESOLVE_LEXICAL_THIS); + } + else + { + parser_emit_cbc (context_p, CBC_PUSH_THIS); + } + + break; + } + case LEXER_LIT_TRUE: + { + parser_emit_cbc (context_p, CBC_PUSH_TRUE); + break; + } + case LEXER_LIT_FALSE: + { + parser_emit_cbc (context_p, CBC_PUSH_FALSE); + break; + } + case LEXER_LIT_NULL: + { + parser_emit_cbc (context_p, CBC_PUSH_NULL); + break; + } + case LEXER_KEYW_CLASS: + { + parser_parse_class (context_p, false); + return false; + } + case LEXER_KEYW_SUPER: + { + if (context_p->status_flags & PARSER_ALLOW_SUPER) + { + if (lexer_check_next_characters (context_p, LIT_CHAR_DOT, LIT_CHAR_LEFT_SQUARE)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SUPER); + break; + } + + if (lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN) + && (context_p->status_flags & PARSER_ALLOW_SUPER_CALL)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SUPER_CONSTRUCTOR); + break; + } + } + + parser_raise_error (context_p, PARSER_ERR_UNEXPECTED_SUPER_KEYWORD); + } + case LEXER_LEFT_PAREN: + { + JERRY_ASSERT (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + + parser_check_assignment_expr (context_p); + +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = context_p->source_p - 1; +#endif /* JERRY_FUNCTION_TO_STRING */ + + uint32_t arrow_status_flags = + (PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION + | (context_p->status_flags & (PARSER_INSIDE_CLASS_FIELD | PARSER_IS_CLASS_STATIC_BLOCK))); + parser_parse_function_expression (context_p, arrow_status_flags); + return parser_abort_parsing_after_assignment_expression (context_p); + } + case LEXER_KEYW_YIELD: + { + JERRY_ASSERT ((context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) + && !(context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD)); + + if (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + + parser_check_assignment_expr (context_p); + lexer_next_token (context_p); + + cbc_ext_opcode_t opcode = + ((context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) ? CBC_EXT_ASYNC_YIELD : CBC_EXT_YIELD); + if (!lexer_check_yield_no_arg (context_p)) + { + if (context_p->token.type == LEXER_MULTIPLY) + { + lexer_next_token (context_p); + opcode = ((context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) ? CBC_EXT_ASYNC_YIELD_ITERATOR + : CBC_EXT_YIELD_ITERATOR); + } + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + } + else + { + parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED); + } + + parser_emit_cbc_ext (context_p, opcode); + + return (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_COMMA); + } +#if JERRY_MODULE_SYSTEM + case LEXER_KEYW_IMPORT: + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_DOT) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL + || context_p->token.keyword_type != LEXER_KEYW_META + || (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + parser_raise_error (context_p, PARSER_ERR_META_EXPECTED); + } + + if (!(context_p->global_status_flags & ECMA_PARSE_MODULE)) + { + parser_raise_error (context_p, PARSER_ERR_IMPORT_META_REQUIRE_MODULE); + } + + JERRY_ASSERT (context_p->global_status_flags & ECMA_PARSE_INTERNAL_HAS_IMPORT_META); + + parser_emit_cbc_ext (context_p, CBC_EXT_MODULE_IMPORT_META); + break; + } + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED); + } + + if (new_was_seen) + { + parser_raise_error (context_p, PARSER_ERR_IMPORT_AFTER_NEW); + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + parser_emit_cbc_ext (context_p, CBC_EXT_MODULE_IMPORT); + break; + } +#endif /* JERRY_MODULE_SYSTEM */ + default: + { + bool is_left_hand_side = (*grouping_level_p == PARSE_EXPR_LEFT_HAND_SIDE); + parser_raise_error (context_p, + (is_left_hand_side ? PARSER_ERR_LEFT_HAND_SIDE_EXP_EXPECTED : PARSER_ERR_UNEXPECTED_END)); + break; + } + } + lexer_next_token (context_p); + return false; +} /* parser_parse_unary_expression */ + +/** + * Parse the postfix part of unary operators, and + * generate byte code for the whole expression. + */ +static void +parser_process_unary_expression (parser_context_t *context_p, /**< context */ + size_t grouping_level) /**< grouping level */ +{ + /* Parse postfix part of a primary expression. */ + while (true) + { + /* Since break would only break the switch, we use + * continue to continue this loop. Without continue, + * the code abandons the loop. */ + switch (context_p->token.type) + { + case LEXER_DOT: + { + parser_push_result (context_p); + + if (lexer_check_next_character (context_p, LIT_CHAR_HASHMARK)) + { + lexer_next_token (context_p); + + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER)) + { + parser_raise_error (context_p, PARSER_ERR_UNEXPECTED_PRIVATE_FIELD); + } + + if (!lexer_scan_private_identifier (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + parser_resolve_private_identifier (context_p); + + parser_emit_cbc_ext_literal (context_p, CBC_EXT_PUSH_PRIVATE_PROP_LITERAL, context_p->lit_object.index); + lexer_next_token (context_p); + continue; + } + + lexer_expect_identifier (context_p, LEXER_STRING_LITERAL); + + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && context_p->lit_object.literal_p->type == LEXER_STRING_LITERAL); + context_p->token.lit_location.type = LEXER_STRING_LITERAL; + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + JERRY_ASSERT (CBC_ARGS_EQ (CBC_PUSH_PROP_LITERAL_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)); + context_p->last_cbc_opcode = CBC_PUSH_PROP_LITERAL_LITERAL; + context_p->last_cbc.value = context_p->lit_object.index; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_THIS) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_PROP_THIS_LITERAL); + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL); + context_p->last_cbc.literal_index = context_p->lit_object.index; + } + else + { + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_PROP_LITERAL); + } + lexer_next_token (context_p); + continue; + } + + case LEXER_LEFT_SQUARE: + { + parser_push_result (context_p); + + uint16_t last_cbc_opcode = context_p->last_cbc_opcode; + + if (last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER)) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR); + if (context_p->token.type != LEXER_RIGHT_SQUARE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_SQUARE_EXPECTED); + } + lexer_next_token (context_p); + + if (last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SUPER_PROP); + continue; + } + + if (PARSER_IS_MUTABLE_PUSH_LITERAL (context_p->last_cbc_opcode)) + { + context_p->last_cbc_opcode = PARSER_PUSH_LITERAL_TO_PUSH_PROP_LITERAL (context_p->last_cbc_opcode); + } + else + { + parser_emit_cbc (context_p, CBC_PUSH_PROP); + } + continue; + } + case LEXER_TEMPLATE_LITERAL: + case LEXER_LEFT_PAREN: + { + size_t call_arguments = 0; + uint16_t opcode = CBC_CALL; + bool is_eval = false; + + parser_push_result (context_p); + + if (context_p->stack_top_uint8 == LEXER_KEYW_NEW) + { + if (context_p->token.type == LEXER_LEFT_PAREN) + { + parser_stack_pop_uint8 (context_p); + opcode = CBC_NEW; + } + } + else + { + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL + && context_p->last_cbc.literal_keyword_type == LEXER_KEYW_EVAL + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + is_eval = true; + } + + if (PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode)) + { + opcode = CBC_CALL_PROP; + context_p->last_cbc_opcode = PARSER_PUSH_PROP_TO_PUSH_PROP_REFERENCE (context_p->last_cbc_opcode); + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR)) + { + opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_CALL); + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE); + opcode = CBC_CALL_PROP; + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE); + opcode = CBC_CALL_PROP; + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE); + opcode = CBC_CALL_PROP; + } + else if (JERRY_UNLIKELY (context_p->status_flags & PARSER_INSIDE_WITH) + && PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + opcode = CBC_CALL_PROP; + parser_emit_ident_reference (context_p, CBC_PUSH_IDENT_REFERENCE); + parser_emit_cbc_ext (context_p, CBC_EXT_RESOLVE_BASE); + } + } + + bool has_spread_element = false; + + if (context_p->token.type == LEXER_TEMPLATE_LITERAL) + { + call_arguments = parser_parse_tagged_template_literal (context_p); + } + else + { + lexer_next_token (context_p); + + while (context_p->token.type != LEXER_RIGHT_PAREN) + { + if (++call_arguments > CBC_MAXIMUM_BYTE_VALUE) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED); + } + + if (context_p->token.type == LEXER_THREE_DOTS) + { + has_spread_element = true; + call_arguments++; + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SPREAD_ELEMENT); + lexer_next_token (context_p); + } + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + continue; + } + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + break; + } + } + + lexer_next_token (context_p); + + if (is_eval) + { + context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED; + + uint16_t eval_flags = PARSER_SAVE_STATUS_FLAGS (context_p->status_flags); + const uint32_t required_flags = PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED; + + if (context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS) + { + context_p->status_flags |= PARSER_LEXICAL_BLOCK_NEEDED; + } + else if (((context_p->status_flags & (required_flags | PARSER_IS_STRICT)) == required_flags) + || ((context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT) + && !(context_p->status_flags & PARSER_IS_FUNCTION))) + { + eval_flags |= PARSER_GET_EVAL_FLAG (ECMA_PARSE_FUNCTION_CONTEXT); + } + + if (eval_flags != 0) + { + parser_emit_cbc_ext_call (context_p, CBC_EXT_LOCAL_EVAL, eval_flags); + } + else + { + parser_emit_cbc (context_p, CBC_EVAL); + } + } + + if (has_spread_element) + { + uint16_t spread_opcode; + + if (opcode == CBC_CALL) + { + spread_opcode = CBC_EXT_SPREAD_CALL; + } + else if (opcode == CBC_CALL_PROP) + { + spread_opcode = CBC_EXT_SPREAD_CALL_PROP; + } + else if (opcode == CBC_NEW) + { + spread_opcode = CBC_EXT_SPREAD_NEW; + } + else + { + /* opcode is unchanged */ + JERRY_ASSERT (opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_CALL)); + spread_opcode = CBC_EXT_SPREAD_SUPER_CALL; + } + + parser_emit_cbc_ext_call (context_p, spread_opcode, call_arguments); + continue; + } + + if (call_arguments <= 1) + { + if (opcode == CBC_CALL) + { + parser_emit_cbc (context_p, (uint16_t) (CBC_CALL0 + (call_arguments * 6))); + continue; + } + if (opcode == CBC_CALL_PROP) + { + parser_emit_cbc (context_p, (uint16_t) (CBC_CALL0_PROP + (call_arguments * 6))); + continue; + } + if (opcode == CBC_NEW) + { + parser_emit_cbc (context_p, (uint16_t) (CBC_NEW0 + call_arguments)); + continue; + } + } + else if (call_arguments == 2) + { + if (opcode == CBC_CALL) + { + parser_emit_cbc (context_p, CBC_CALL2); + continue; + } + if (opcode == CBC_CALL_PROP) + { + parser_flush_cbc (context_p); + /* Manually adjusting stack usage. */ + JERRY_ASSERT (context_p->stack_depth > 0); + context_p->stack_depth--; + parser_emit_cbc (context_p, CBC_CALL2_PROP); + continue; + } + } + + parser_emit_cbc_call (context_p, opcode, call_arguments); + continue; + } + default: + { + if (context_p->stack_top_uint8 == LEXER_KEYW_NEW) + { + parser_push_result (context_p); + parser_emit_cbc (context_p, CBC_NEW0); + parser_stack_pop_uint8 (context_p); + continue; + } + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) + && (context_p->token.type == LEXER_INCREASE || context_p->token.type == LEXER_DECREASE) + && grouping_level != PARSE_EXPR_LEFT_HAND_SIDE) + { + cbc_opcode_t opcode = (context_p->token.type == LEXER_INCREASE) ? CBC_POST_INCR : CBC_POST_DECR; + parser_push_result (context_p); + parser_emit_unary_lvalue_opcode (context_p, opcode); + lexer_next_token (context_p); + } + break; + } + } + break; + } + + uint8_t last_unary_token = LEXER_INCREASE; + + /* Generate byte code for the unary operators. */ + while (true) + { + uint8_t token = context_p->stack_top_uint8; + if (!LEXER_IS_UNARY_OP_TOKEN (token)) + { + if (context_p->token.type == LEXER_EXPONENTIATION && last_unary_token != LEXER_INCREASE + && last_unary_token != LEXER_DECREASE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_EXPONENTIATION); + } + + break; + } + + last_unary_token = token; + parser_push_result (context_p); + parser_stack_pop_uint8 (context_p); + + if (LEXER_IS_UNARY_LVALUE_OP_TOKEN (token)) + { + if (token == LEXER_KEYW_DELETE) + { + token = CBC_DELETE_PUSH_RESULT; + } + else + { + token = (uint8_t) (LEXER_UNARY_LVALUE_OP_TOKEN_TO_OPCODE (token)); + } + parser_emit_unary_lvalue_opcode (context_p, (cbc_opcode_t) token); + } + else if (JERRY_UNLIKELY (token == LEXER_KEYW_AWAIT)) + { + cbc_ext_opcode_t opcode = + ((context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) ? CBC_EXT_GENERATOR_AWAIT : CBC_EXT_AWAIT); + parser_emit_cbc_ext (context_p, opcode); + } + else + { + token = (uint8_t) (LEXER_UNARY_OP_TOKEN_TO_OPCODE (token)); + + if (token == CBC_TYPEOF) + { + if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + parser_emit_ident_reference (context_p, CBC_TYPEOF_IDENT); + } + else + { + parser_emit_cbc (context_p, token); + } + } + else + { + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + /* It is not worth to combine with push multiple literals + * since the byte code size will not decrease. */ + JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, token + 1)); + context_p->last_cbc_opcode = (uint16_t) (token + 1); + } + else + { + parser_emit_cbc (context_p, token); + } + } + } + } +} /* parser_process_unary_expression */ + +/** + * Append a binary '=' token. + * + * @return - pushed assignment opcode onto the parser stack + */ +static void +parser_append_binary_single_assignment_token (parser_context_t *context_p, /**< context */ + uint32_t pattern_flags) /**< pattern flags */ +{ + JERRY_UNUSED (pattern_flags); + + /* Unlike other tokens, the whole byte code is saved for binary + * assignment, since it has multiple forms depending on the + * previous instruction. */ + + uint8_t assign_opcode = CBC_ASSIGN; + + if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + parser_check_invalid_assign (context_p); + + uint16_t literal_index; + + switch (context_p->last_cbc_opcode) + { + case CBC_PUSH_LITERAL: + { + literal_index = context_p->last_cbc.literal_index; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + break; + } + case CBC_PUSH_TWO_LITERALS: + { + literal_index = context_p->last_cbc.value; + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + break; + } + case CBC_PUSH_THIS_LITERAL: + { + literal_index = context_p->last_cbc.literal_index; + context_p->last_cbc_opcode = CBC_PUSH_THIS; + parser_flush_cbc (context_p); + break; + } + default: + { + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS); + literal_index = context_p->last_cbc.third_literal_index; + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + break; + } + } + + assign_opcode = CBC_ASSIGN_SET_IDENT; + + if (!(pattern_flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST | PARSER_PATTERN_LOCAL))) + { + if (scanner_literal_is_const_reg (context_p, literal_index)) + { + parser_stack_push_uint8 (context_p, LEXER_ASSIGN_CONST); + } + } + else if (literal_index < PARSER_REGISTER_START) + { + assign_opcode = CBC_INIT_LET; + + if (scanner_literal_is_created (context_p, literal_index)) + { + assign_opcode = CBC_ASSIGN_LET_CONST; + } + else if (pattern_flags & PARSER_PATTERN_CONST) + { + assign_opcode = CBC_INIT_CONST; + } + else if (pattern_flags & PARSER_PATTERN_LOCAL) + { + assign_opcode = CBC_INIT_ARG_OR_CATCH; + } + } + + parser_stack_push_uint16 (context_p, literal_index); + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_LITERAL, assign_opcode)); + } + else if (context_p->last_cbc_opcode == CBC_PUSH_PROP) + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP, CBC_ASSIGN)); + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL) + { + if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL) + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_LITERAL, CBC_ASSIGN_PROP_LITERAL)); + parser_stack_push_uint16 (context_p, context_p->last_cbc.literal_index); + assign_opcode = CBC_ASSIGN_PROP_LITERAL; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + else + { + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + } + } + else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL_LITERAL) + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_LITERAL_LITERAL, CBC_PUSH_TWO_LITERALS)); + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_THIS_LITERAL) + { + if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL) + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_THIS_LITERAL, CBC_ASSIGN_PROP_THIS_LITERAL)); + parser_stack_push_uint16 (context_p, context_p->last_cbc.literal_index); + assign_opcode = CBC_ASSIGN_PROP_THIS_LITERAL; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + else + { + context_p->last_cbc_opcode = CBC_PUSH_THIS_LITERAL; + } + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE); + parser_stack_push_uint8 (context_p, CBC_EXT_ASSIGN_SUPER); + assign_opcode = CBC_EXT_OPCODE; + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE); + parser_stack_push_uint8 (context_p, CBC_EXT_ASSIGN_SUPER); + assign_opcode = CBC_EXT_OPCODE; + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL)) + { + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + parser_stack_push_uint8 (context_p, CBC_EXT_ASSIGN_PRIVATE); + assign_opcode = CBC_EXT_OPCODE; + } + else + { + /* Invalid LeftHandSide expression. */ // 3820, 3815 + parser_check_invalid_new_target (context_p, CBC_ASSIGN); + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_ASSIGNMENT); + } + + parser_stack_push_uint8 (context_p, assign_opcode); + parser_stack_push_uint8 (context_p, LEXER_ASSIGN); +} /* parser_append_binary_single_assignment_token */ + +/** + * Check for invalid chain of logical operators + */ +static void +parser_check_invalid_logical_op (parser_context_t *context_p, /**< context */ + uint8_t invalid_token1, /**< token id of first invalid token */ + uint8_t invalid_token2) /**< token id of second invalid token */ +{ + parser_stack_iterator_t iterator; + parser_stack_iterator_init (context_p, &iterator); + + while (true) + { + uint8_t token = parser_stack_iterator_read_uint8 (&iterator); + + if (!LEXER_IS_BINARY_NON_LVALUE_OP_TOKEN (token)) + { + return; + } + + if (token == invalid_token1 || token == invalid_token2) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_NULLISH_COALESCING); + } + + /* If a logical operator is found, and there is no SyntaxError, the scan can be terminated + * since there was no SyntaxError when the logical operator was pushed onto the stack. */ + if (token == LEXER_LOGICAL_OR || token == LEXER_LOGICAL_AND || token == LEXER_NULLISH_COALESCING) + { + return; + } + + parser_stack_iterator_skip (&iterator, sizeof (uint8_t)); + } +} /* parser_check_invalid_logical_op */ + +/** + * Append a binary lvalue token. + */ +static void +parser_append_binary_lvalue_token (parser_context_t *context_p, /**< context */ + bool is_logical_assignment) /**< true - if form logical assignment reference + * false - otherwise */ +{ + if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + parser_check_invalid_assign (context_p); + + parser_emit_ident_reference (context_p, CBC_PUSH_IDENT_REFERENCE); + + if (!is_logical_assignment && scanner_literal_is_const_reg (context_p, context_p->last_cbc.literal_index)) + { + parser_stack_push_uint8 (context_p, LEXER_ASSIGN_CONST); + } + } + else if (PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode)) + { + context_p->last_cbc_opcode = PARSER_PUSH_PROP_TO_PUSH_PROP_REFERENCE (context_p->last_cbc_opcode); + } + else + { + /* Invalid LeftHandSide expression. */ + parser_check_invalid_new_target (context_p, CBC_ASSIGN); + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_ASSIGNMENT); + parser_emit_cbc (context_p, CBC_PUSH_PROP_REFERENCE); + } + + if (!is_logical_assignment) + { + parser_stack_push_uint8 (context_p, (uint8_t) context_p->token.type); + } +} /* parser_append_binary_lvalue_token */ + +/** + * Append a logical token. + */ +static void +parser_append_logical_token (parser_context_t *context_p, /**< context */ + uint16_t opcode) /**< opcode */ +{ + if (opcode != PARSER_TO_EXT_OPCODE (CBC_EXT_BRANCH_IF_NULLISH)) + { + parser_check_invalid_logical_op (context_p, LEXER_NULLISH_COALESCING, LEXER_NULLISH_COALESCING); + } + + parser_branch_t branch; + parser_emit_cbc_forward_branch (context_p, opcode, &branch); + parser_stack_push (context_p, &branch, sizeof (parser_branch_t)); + parser_stack_push_uint8 (context_p, (uint8_t) context_p->token.type); +} /* parser_append_logical_token */ + +/** + * Append a logical token. + */ +static void +parser_append_logical_assignment_token (parser_context_t *context_p, /**< context */ + uint16_t opcode) /**< opcode */ +{ + uint16_t last_cbc_opcode = context_p->last_cbc_opcode; + parser_append_binary_single_assignment_token (context_p, 0); + parser_stack_change_last_uint8 (context_p, LEXER_ASSIGN_REFERENCE); + context_p->last_cbc_opcode = last_cbc_opcode; + + parser_append_binary_lvalue_token (context_p, true); + parser_append_logical_token (context_p, opcode); +} /* parser_append_logical_assignment_token */ + +/** + * Append a binary token. + */ +static void +parser_append_binary_token (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (LEXER_IS_BINARY_OP_TOKEN (context_p->token.type)); + parser_push_result (context_p); + + switch (context_p->token.type) + { + case LEXER_ASSIGN: + { + parser_append_binary_single_assignment_token (context_p, 0); + break; + } + /* Binary lvalue-opcodes */ + case LEXER_ASSIGN_ADD: + case LEXER_ASSIGN_SUBTRACT: + case LEXER_ASSIGN_MULTIPLY: + case LEXER_ASSIGN_DIVIDE: + case LEXER_ASSIGN_MODULO: + case LEXER_ASSIGN_EXPONENTIATION: + case LEXER_ASSIGN_LEFT_SHIFT: + case LEXER_ASSIGN_RIGHT_SHIFT: + case LEXER_ASSIGN_UNS_RIGHT_SHIFT: + case LEXER_ASSIGN_BIT_AND: + case LEXER_ASSIGN_BIT_OR: + case LEXER_ASSIGN_BIT_XOR: + { + parser_append_binary_lvalue_token (context_p, false); + break; + } + case LEXER_ASSIGN_NULLISH_COALESCING: + { + parser_append_logical_assignment_token (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_BRANCH_IF_NULLISH)); + break; + } + case LEXER_ASSIGN_LOGICAL_OR: + { + parser_append_logical_assignment_token (context_p, CBC_BRANCH_IF_LOGICAL_TRUE); + break; + } + case LEXER_ASSIGN_LOGICAL_AND: + { + parser_append_logical_assignment_token (context_p, CBC_BRANCH_IF_LOGICAL_FALSE); + break; + } + case LEXER_NULLISH_COALESCING: + { + parser_append_logical_token (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_BRANCH_IF_NULLISH)); + break; + } + case LEXER_LOGICAL_OR: + { + parser_append_logical_token (context_p, CBC_BRANCH_IF_LOGICAL_TRUE); + break; + } + case LEXER_LOGICAL_AND: + { + parser_append_logical_token (context_p, CBC_BRANCH_IF_LOGICAL_FALSE); + break; + } + default: + { + parser_stack_push_uint8 (context_p, (uint8_t) context_p->token.type); + break; + } + } +} /* parser_append_binary_token */ + +/** + * Emit opcode for binary assignment token. + */ +static void +parser_process_binary_assignment_token (parser_context_t *context_p, /**< context */ + uint8_t token) /**< token */ +{ + uint16_t index = PARSER_INVALID_LITERAL_INDEX; + uint16_t opcode = context_p->stack_top_uint8; + + if (JERRY_UNLIKELY (opcode == CBC_EXT_OPCODE)) + { + parser_stack_pop_uint8 (context_p); + JERRY_ASSERT (context_p->stack_top_uint8 == CBC_EXT_ASSIGN_SUPER + || context_p->stack_top_uint8 == CBC_EXT_ASSIGN_PRIVATE); + opcode = PARSER_TO_EXT_OPCODE (context_p->stack_top_uint8); + parser_stack_pop_uint8 (context_p); + } + else + { + parser_stack_pop_uint8 (context_p); + + if (cbc_flags[opcode] & CBC_HAS_LITERAL_ARG) + { + JERRY_ASSERT (opcode == CBC_ASSIGN_SET_IDENT || opcode == CBC_ASSIGN_PROP_LITERAL + || opcode == CBC_ASSIGN_PROP_THIS_LITERAL || opcode == CBC_ASSIGN_LET_CONST + || opcode == CBC_INIT_ARG_OR_CATCH || opcode == CBC_INIT_LET || opcode == CBC_INIT_CONST); + + index = parser_stack_pop_uint16 (context_p); + } + } + + bool group_expr_assingment = false; + + if (JERRY_UNLIKELY (context_p->stack_top_uint8 == LEXER_ASSIGN_GROUP_EXPR)) + { + group_expr_assingment = true; + parser_stack_pop_uint8 (context_p); + } + + if (JERRY_UNLIKELY (context_p->stack_top_uint8 == LEXER_ASSIGN_CONST)) + { + parser_stack_pop_uint8 (context_p); + parser_emit_cbc_ext (context_p, CBC_EXT_THROW_ASSIGN_CONST_ERROR); + } + + if (index == PARSER_INVALID_LITERAL_INDEX) + { + if (JERRY_UNLIKELY (token == LEXER_ASSIGN_REFERENCE)) + { + opcode = CBC_ASSIGN_PUSH_RESULT; + } + + parser_emit_cbc (context_p, opcode); + return; + } + + if (!group_expr_assingment) + { + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + uint16_t name_index = scanner_save_literal (context_p, index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + parser_set_function_name (context_p, function_literal_index, (uint16_t) index, 0); + } + } + + if (JERRY_UNLIKELY (token == LEXER_ASSIGN_REFERENCE)) + { + parser_emit_cbc (context_p, CBC_ASSIGN_PUSH_RESULT); + return; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL && opcode == CBC_ASSIGN_SET_IDENT) + { + JERRY_ASSERT (CBC_ARGS_EQ (CBC_ASSIGN_LITERAL_SET_IDENT, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)); + + context_p->last_cbc.value = index; + context_p->last_cbc_opcode = CBC_ASSIGN_LITERAL_SET_IDENT; + return; + } + + parser_emit_cbc_literal (context_p, (uint16_t) opcode, index); + + if (opcode == CBC_ASSIGN_PROP_THIS_LITERAL && (context_p->stack_depth >= context_p->stack_limit)) + { + /* Stack limit is increased for VM_OC_ASSIGN_PROP_THIS. Needed by vm.c. */ + JERRY_ASSERT (context_p->stack_depth == context_p->stack_limit); + + context_p->stack_limit++; + + if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + } +} /* parser_process_binary_opcodes */ + +/** + * Emit opcode for logical tokens. + */ +static void +parser_process_logical_token (parser_context_t *context_p) /**< context */ +{ + parser_branch_t branch; + parser_stack_pop (context_p, &branch, sizeof (parser_branch_t)); + parser_set_branch_to_current_position (context_p, &branch); +} /* parser_process_logical_token */ + +/** + * Emit opcode for logical assignment tokens. + */ +static void +parser_process_logical_assignment_token (parser_context_t *context_p) /**< context */ +{ + parser_branch_t condition_branch; + parser_stack_pop (context_p, &condition_branch, sizeof (parser_branch_t)); + + uint8_t token = context_p->stack_top_uint8; + JERRY_ASSERT (token == LEXER_ASSIGN_REFERENCE); + parser_stack_pop_uint8 (context_p); + parser_process_binary_assignment_token (context_p, token); + + parser_branch_t prop_reference_branch; + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &prop_reference_branch); + + parser_set_branch_to_current_position (context_p, &condition_branch); + parser_emit_cbc_ext (context_p, CBC_EXT_POP_REFERENCE); + + JERRY_ASSERT (context_p->stack_limit - context_p->stack_depth >= 2); + PARSER_PLUS_EQUAL_U16 (context_p->stack_depth, 2); + + parser_set_branch_to_current_position (context_p, &prop_reference_branch); +} /* parser_process_logical_assignment_token */ + +/** + * Emit opcode for binary tokens. + */ +static void +parser_process_binary_token (parser_context_t *context_p, /**< context */ + uint8_t token) /**< token */ +{ + uint16_t opcode = LEXER_BINARY_OP_TOKEN_TO_OPCODE (token); + + if (PARSER_IS_PUSH_NUMBER (context_p->last_cbc_opcode)) + { + lexer_convert_push_number_to_push_literal (context_p); + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, opcode + CBC_BINARY_WITH_LITERAL)); + context_p->last_cbc_opcode = (uint16_t) (opcode + CBC_BINARY_WITH_LITERAL); + return; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + JERRY_ASSERT (CBC_ARGS_EQ (opcode + CBC_BINARY_WITH_TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)); + context_p->last_cbc_opcode = (uint16_t) (opcode + CBC_BINARY_WITH_TWO_LITERALS); + return; + } + + parser_emit_cbc (context_p, opcode); +} /* parser_process_binary_token */ + +/** + * Emit opcode for binary lvalue tokens. + */ +static void +parser_process_binary_lvalue_token (parser_context_t *context_p, /**< context */ + uint8_t token) /**< token */ +{ + parser_stack_push_uint8 (context_p, CBC_ASSIGN); + parser_stack_push_uint8 (context_p, LEXER_ASSIGN); + parser_stack_push_uint8 (context_p, lexer_convert_binary_lvalue_token_to_binary (token)); +} /* parser_process_binary_lvalue_token */ + +/** + * Emit opcode for binary computations. + */ +static void +parser_process_binary_opcodes (parser_context_t *context_p, /**< context */ + uint8_t min_prec_treshold) /**< minimal precedence of tokens */ +{ + while (true) + { + uint8_t token = context_p->stack_top_uint8; + + /* For left-to-right operators (all binary operators except assignment + * and logical operators), the byte code is flushed if the precedence + * of the next operator is less or equal than the current operator. For + * assignment and logical operators, we add 1 to the min precendence to + * force right-to-left evaluation order. */ + + if (!LEXER_IS_BINARY_OP_TOKEN (token) + || parser_binary_precedence_table[token - LEXER_FIRST_BINARY_OP] < min_prec_treshold) + { + return; + } + + parser_push_result (context_p); + parser_stack_pop_uint8 (context_p); + + switch (token) + { + case LEXER_ASSIGN: + { + parser_process_binary_assignment_token (context_p, token); + continue; + } + /* Binary lvalue-opcodes */ + case LEXER_ASSIGN_ADD: + case LEXER_ASSIGN_SUBTRACT: + case LEXER_ASSIGN_MULTIPLY: + case LEXER_ASSIGN_DIVIDE: + case LEXER_ASSIGN_MODULO: + case LEXER_ASSIGN_EXPONENTIATION: + case LEXER_ASSIGN_LEFT_SHIFT: + case LEXER_ASSIGN_RIGHT_SHIFT: + case LEXER_ASSIGN_UNS_RIGHT_SHIFT: + case LEXER_ASSIGN_BIT_AND: + case LEXER_ASSIGN_BIT_OR: + case LEXER_ASSIGN_BIT_XOR: + { + parser_process_binary_lvalue_token (context_p, token); + continue; + } + case LEXER_ASSIGN_NULLISH_COALESCING: + case LEXER_ASSIGN_LOGICAL_OR: + case LEXER_ASSIGN_LOGICAL_AND: + { + parser_process_logical_assignment_token (context_p); + continue; + } + case LEXER_NULLISH_COALESCING: + case LEXER_LOGICAL_OR: + case LEXER_LOGICAL_AND: + { + parser_process_logical_token (context_p); + continue; + } + case LEXER_KEYW_IN: + { + if (context_p->stack_top_uint8 == LEXER_PRIVATE_PRIMARY_EXPR) + { + parser_stack_pop_uint8 (context_p); + uint16_t lit_id = parser_stack_pop_uint16 (context_p); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN, lit_id); + continue; + } + + /* FALLTHRU */ + } + default: + { + parser_process_binary_token (context_p, token); + continue; + } + } + } +} /* parser_process_binary_opcodes */ + +/** + * End position marker of a pattern. + */ +typedef struct +{ + scanner_location_t location; /**< end position of the pattern */ + lexer_token_t token; /**< token at the end position */ +} parser_pattern_end_marker_t; + +/** + * Literal index should not be emitted while processing rhs target value + */ +#define PARSER_PATTERN_RHS_NO_LIT PARSER_INVALID_LITERAL_INDEX + +/** + * Process the target of an initializer pattern. + */ +static parser_pattern_end_marker_t +parser_pattern_get_target (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags) /**< flags */ +{ + parser_pattern_end_marker_t end_marker; + end_marker.token.type = LEXER_INVALID_PATTERN; + parser_branch_t skip_init; + + if (flags & PARSER_PATTERN_TARGET_DEFAULT) + { + JERRY_ASSERT (flags & PARSER_PATTERN_TARGET_ON_STACK); + + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init); + } + + if ((flags & (PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_TARGET_DEFAULT)) != PARSER_PATTERN_TARGET_ON_STACK) + { + scanner_location_t start_location; + + if (context_p->next_scanner_info_p->source_p != context_p->source_p + || context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED || (flags & PARSER_PATTERN_REST_ELEMENT)) + { + /* Found invalid pattern, push null value to fake the rhs target. */ + parser_emit_cbc (context_p, CBC_PUSH_NULL); + } + else + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER); + scanner_get_location (&start_location, context_p); + + scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location); + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + scanner_seek (context_p); + lexer_next_token (context_p); + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + scanner_get_location (&(end_marker.location), context_p); + end_marker.token = context_p->token; + + scanner_set_location (context_p, &start_location); + scanner_seek (context_p); + parser_flush_cbc (context_p); + } + } + + if (flags & PARSER_PATTERN_TARGET_DEFAULT) + { + parser_set_branch_to_current_position (context_p, &skip_init); + } + + return end_marker; +} /* parser_pattern_get_target */ + +/** + * Finalize an assignment/binding pattern. + */ +static void +parser_pattern_finalize (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags, /**< flags */ + parser_pattern_end_marker_t *end_marker_p) /**< pattern end position */ +{ + if ((flags & (PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_TARGET_DEFAULT)) != PARSER_PATTERN_TARGET_ON_STACK) + { + if (end_marker_p->token.type == LEXER_INVALID_PATTERN) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN); + } + + scanner_set_location (context_p, &(end_marker_p->location)); + context_p->token = end_marker_p->token; + } + else + { + JERRY_ASSERT (!(flags & PARSER_PATTERN_TARGET_DEFAULT)); + lexer_next_token (context_p); + } + + if ((flags & (PARSER_PATTERN_BINDING | PARSER_PATTERN_NESTED_PATTERN)) == PARSER_PATTERN_BINDING) + { + /* Pop the result of the expression. */ + parser_emit_cbc (context_p, CBC_POP); + } + + parser_flush_cbc (context_p); +} /* parser_pattern_finalize */ + +/** + * Emit right-hand-side target value. + */ +static void +parser_pattern_emit_rhs (parser_context_t *context_p, /**< context */ + uint16_t rhs_opcode, /**< opcode to process the rhs value */ + uint16_t literal_index) /**< literal index for object pattern */ +{ + if (literal_index != PARSER_PATTERN_RHS_NO_LIT) + { + parser_emit_cbc_ext_literal (context_p, rhs_opcode, literal_index); + } + else + { + parser_emit_cbc_ext (context_p, rhs_opcode); + } +} /* parser_pattern_emit_rhs */ + +/** + * Form an assignment from a pattern. + */ +static void +parser_pattern_form_assignment (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags, /**< flags */ + uint16_t rhs_opcode, /**< opcode to process the rhs value */ + uint16_t literal_index, /**< literal index for object pattern */ + parser_line_counter_t ident_line_counter) /**< identifier line counter */ +{ + JERRY_UNUSED (ident_line_counter); + + uint16_t name_index = PARSER_INVALID_LITERAL_INDEX; + + if ((flags & PARSER_PATTERN_BINDING) + || (context_p->last_cbc_opcode == CBC_PUSH_LITERAL && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)) + { + name_index = context_p->lit_object.index; + } + + parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START); + parser_append_binary_single_assignment_token (context_p, flags); + parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index); + + if (context_p->token.type == LEXER_ASSIGN && !(flags & PARSER_PATTERN_REST_ELEMENT)) + { + parser_branch_t skip_init; + lexer_next_token (context_p); + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init); + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (name_index != PARSER_INVALID_LITERAL_INDEX) + { + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + name_index = scanner_save_literal (context_p, name_index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + parser_set_function_name (context_p, function_literal_index, name_index, 0); + } + } + parser_set_branch_to_current_position (context_p, &skip_init); + } + + parser_process_binary_opcodes (context_p, 0); + + JERRY_ASSERT (context_p->stack_top_uint8 == LEXER_EXPRESSION_START); + parser_stack_pop_uint8 (context_p); + +} /* parser_pattern_form_assignment */ + +/** + * Parse pattern inside a pattern. + */ +static void +parser_pattern_process_nested_pattern (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags, /**< flags */ + uint16_t rhs_opcode, /**< opcode to process the rhs value */ + uint16_t literal_index) /**< literal index for object pattern */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE); + + parser_pattern_flags_t options = (parser_pattern_flags_t) ((int) PARSER_PATTERN_NESTED_PATTERN | (int) PARSER_PATTERN_TARGET_ON_STACK + | ((int) flags & ((int) PARSER_PATTERN_BINDING | (int) PARSER_PATTERN_LET | (int) PARSER_PATTERN_CONST + | (int) PARSER_PATTERN_LOCAL | (int) PARSER_PATTERN_ARGUMENTS))); + + JERRY_ASSERT (context_p->next_scanner_info_p->source_p != context_p->source_p + || context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER + || context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS); + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER) + { + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + options = (parser_pattern_flags_t) ((int) options | (int) PARSER_PATTERN_HAS_REST_ELEMENT); + } + + if (!(flags & PARSER_PATTERN_REST_ELEMENT)) + { + options = (parser_pattern_flags_t) ((int) options | (int) PARSER_PATTERN_TARGET_DEFAULT); + } + else + { + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + } + } + else + { + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + options = (parser_pattern_flags_t) ((int) options | (int) PARSER_PATTERN_HAS_REST_ELEMENT); + } + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + } + + parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index); + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + parser_parse_object_initializer (context_p, options); + } + else + { + parser_parse_array_initializer (context_p, options); + } + + parser_emit_cbc (context_p, CBC_POP); +} /* parser_pattern_process_nested_pattern */ + +/** + * Process the current {Binding, Assignment}Property + * + * @return true, if a nested pattern is processed, false otherwise + */ +static bool +parser_pattern_process_assignment (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags, /**< flags */ + uint16_t rhs_opcode, /**< opcode to process the rhs value */ + uint16_t literal_index, /**< literal index for object pattern */ + lexer_token_type_t end_type) /**< end type token */ +{ + if ((context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE) + && (context_p->next_scanner_info_p->source_p != context_p->source_p + || !(context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_NO_DESTRUCTURING))) + { + parser_pattern_process_nested_pattern (context_p, flags, rhs_opcode, literal_index); + return true; + } + + parser_line_counter_t ident_line_counter = context_p->token.line; +#if JERRY_LINE_INFO + parser_line_counter_t ident_column_counter = context_p->token.column; +#endif /* JERRY_LINE_INFO */ + + if (flags & PARSER_PATTERN_BINDING) + { + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL); + + if (flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST) && context_p->token.keyword_type == LEXER_KEYW_LET) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_LET_BINDING); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + if (flags & PARSER_PATTERN_ARGUMENTS) + { + if (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT) + { + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT; + } +#if JERRY_MODULE_SYSTEM + parser_module_append_export_name (context_p); +#endif /* JERRY_MODULE_SYSTEM */ + + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + lexer_next_token (context_p); + + if (context_p->token.type != end_type && context_p->token.type != LEXER_ASSIGN + && context_p->token.type != LEXER_COMMA) + { + parser_raise_error (context_p, PARSER_ERR_ILLEGAL_PROPERTY_IN_DECLARATION); + } + } + else + { + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_LEFT_HAND_SIDE); + + if (!PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode) && !PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN); + } + } + + parser_pattern_form_assignment (context_p, flags, rhs_opcode, literal_index, ident_line_counter); +#if JERRY_LINE_INFO + parser_line_info_append (context_p, ident_line_counter, ident_column_counter); +#endif /* JERRY_LINE_INFO */ + return false; +} /* parser_pattern_process_assignment */ + +/** + * Parse array initializer. + */ +static void +parser_parse_array_initializer (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags) /**< flags */ +{ + parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags); + + lexer_next_token (context_p); + parser_emit_cbc_ext (context_p, CBC_EXT_ITERATOR_CONTEXT_CREATE); + + while (context_p->token.type != LEXER_RIGHT_SQUARE) + { + uint16_t rhs_opcode = CBC_EXT_ITERATOR_STEP; + + if (context_p->token.type == LEXER_COMMA) + { + parser_emit_cbc_ext (context_p, rhs_opcode); + parser_emit_cbc (context_p, CBC_POP); + lexer_next_token (context_p); + continue; + } + + parser_pattern_flags_t options = flags; + + if (context_p->token.type == LEXER_THREE_DOTS) + { + lexer_next_token (context_p); + rhs_opcode = CBC_EXT_REST_INITIALIZER; + options = (parser_pattern_flags_t) ((int) options | (int) PARSER_PATTERN_REST_ELEMENT); + } + + parser_pattern_process_assignment (context_p, options, rhs_opcode, PARSER_PATTERN_RHS_NO_LIT, LEXER_RIGHT_SQUARE); + + if (context_p->token.type == LEXER_COMMA && rhs_opcode != CBC_EXT_REST_INITIALIZER) + { + lexer_next_token (context_p); + } + else if (context_p->token.type != LEXER_RIGHT_SQUARE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN); + } + } + + /* close the iterator */ + parser_emit_cbc_ext (context_p, CBC_EXT_ITERATOR_CONTEXT_END); + + parser_pattern_finalize (context_p, flags, &end_pos); +} /* parser_parse_array_initializer */ + +/** + * Parse object initializer. + */ +static void +parser_parse_object_initializer (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags) /**< flags */ +{ + parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags); + + /* 12.14.5.2: ObjectAssignmentPattern : { } */ + if (lexer_check_next_character (context_p, LIT_CHAR_RIGHT_BRACE)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_REQUIRE_OBJECT_COERCIBLE); + lexer_consume_next_character (context_p); + parser_pattern_finalize (context_p, flags, &end_pos); + return; + } + +#ifndef JERRY_NDEBUG + bool rest_found = false; +#endif /* !defined(JERRY_NDEBUG) */ + + cbc_ext_opcode_t context_opcode = CBC_EXT_OBJ_INIT_CONTEXT_CREATE; + + if (flags & PARSER_PATTERN_HAS_REST_ELEMENT) + { + context_opcode = CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE; + } + + parser_emit_cbc_ext (context_p, context_opcode); + + while (true) + { + lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_OBJECT_PATTERN); + + uint16_t prop_index = context_p->lit_object.index; + parser_line_counter_t start_line = context_p->token.line; + parser_line_counter_t start_column = context_p->token.column; + uint16_t push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL; + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + break; + } + + if (context_p->token.type == LEXER_THREE_DOTS) + { + lexer_next_token (context_p); + + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_REST_ELEMENT); + + if (parser_pattern_process_assignment (context_p, + flags, + CBC_EXT_OBJ_INIT_PUSH_REST, + PARSER_PATTERN_RHS_NO_LIT, + LEXER_RIGHT_BRACE)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_ASSIGNMENT); + } + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + +#ifndef JERRY_NDEBUG + rest_found = true; +#endif /* !defined(JERRY_NDEBUG) */ + break; + } + + if (context_p->token.type == LEXER_RIGHT_SQUARE) + { + prop_index = PARSER_PATTERN_RHS_NO_LIT; + push_prop_opcode = + ((flags & PARSER_PATTERN_HAS_REST_ELEMENT) ? CBC_EXT_INITIALIZER_PUSH_NAME : CBC_EXT_INITIALIZER_PUSH_PROP); + } + else if (flags & PARSER_PATTERN_HAS_REST_ELEMENT) + { + push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL; + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_COLON) + { + lexer_next_token (context_p); + parser_pattern_process_assignment (context_p, flags, push_prop_opcode, prop_index, LEXER_RIGHT_BRACE); + } + else + { + if (push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_NAME || push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_PROP) + { + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + if (context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_ASSIGN + && context_p->token.type != LEXER_COMMA) + { + parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED); + } + + parser_reparse_as_common_identifier (context_p, start_line, start_column); + + if (flags & PARSER_PATTERN_ARGUMENTS) + { + if (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT) + { + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT; + } + +#if JERRY_MODULE_SYSTEM + parser_module_append_export_name (context_p); +#endif /* JERRY_MODULE_SYSTEM */ + + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + + lexer_next_token (context_p); + JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE || context_p->token.type == LEXER_ASSIGN + || context_p->token.type == LEXER_COMMA); + + parser_pattern_form_assignment (context_p, flags, push_prop_opcode, prop_index, start_line); +#if JERRY_LINE_INFO + parser_line_info_append (context_p, start_line, start_column); +#endif /* JERRY_LINE_INFO */ + } + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + break; + } + else if (context_p->token.type != LEXER_COMMA) + { + parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED); + } + } + + if (flags & PARSER_PATTERN_HAS_REST_ELEMENT) + { + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, + (PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION - PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION)); + } + + parser_emit_cbc_ext (context_p, CBC_EXT_OBJ_INIT_CONTEXT_END); + + parser_pattern_finalize (context_p, flags, &end_pos); + +#ifndef JERRY_NDEBUG + /* Checked at the end because there might be syntax errors before. */ + JERRY_ASSERT (!!(flags & PARSER_PATTERN_HAS_REST_ELEMENT) == rest_found); +#endif /* !defined(JERRY_NDEBUG) */ +} /* parser_parse_object_initializer */ + +/** + * Parse an initializer. + */ +void +parser_parse_initializer (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags) /**< flags */ +{ + if (context_p->token.type == LEXER_LEFT_BRACE) + { + parser_parse_object_initializer (context_p, flags); + } + else + { + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_SQUARE); + parser_parse_array_initializer (context_p, flags); + } +} /* parser_parse_initializer */ + +/** + * Parse an initializer using the next character. + */ +void +parser_parse_initializer_by_next_char (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags) /**< flags */ +{ + JERRY_ASSERT (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE)); + + if (lexer_consume_next_character (context_p) == LIT_CHAR_LEFT_BRACE) + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER + || context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS); + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_HAS_REST_ELEMENT); + } + + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS) + { + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + } + + parser_parse_object_initializer (context_p, flags); + } + else + { + parser_parse_array_initializer (context_p, flags); + } +} /* parser_parse_initializer_by_next_char */ + +/** + * Process ternary expression. + */ +static void +parser_process_ternary_expression (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_QUESTION_MARK); + + cbc_opcode_t opcode = CBC_BRANCH_IF_FALSE_FORWARD; + parser_branch_t cond_branch; + parser_branch_t uncond_branch; + + parser_push_result (context_p); + + if (context_p->last_cbc_opcode == CBC_LOGICAL_NOT) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_BRANCH_IF_TRUE_FORWARD; + } + + parser_emit_cbc_forward_branch (context_p, (uint16_t) opcode, &cond_branch); + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &uncond_branch); + parser_set_branch_to_current_position (context_p, &cond_branch); + + /* Although byte code is constructed for two branches, + * only one of them will be executed. To reflect this + * the stack is manually adjusted. */ + JERRY_ASSERT (context_p->stack_depth > 0); + context_p->stack_depth--; + + if (context_p->token.type != LEXER_COLON) + { + parser_raise_error (context_p, PARSER_ERR_COLON_FOR_CONDITIONAL_EXPECTED); + } + + lexer_next_token (context_p); + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + parser_set_branch_to_current_position (context_p, &uncond_branch); + + /* Last opcode rewrite is not allowed because + * the result may come from the first branch. */ + parser_flush_cbc (context_p); + + parser_process_binary_opcodes (context_p, 0); +} /* parser_process_ternary_expression */ + +/** + * Process expression sequence. + */ +static void +parser_process_expression_sequence (parser_context_t *context_p) /**< context */ +{ + if (!CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode)) + { + parser_emit_cbc (context_p, CBC_POP); + } + + if (context_p->stack_top_uint8 == LEXER_LEFT_PAREN) + { + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL); + + page_p->bytes[context_p->stack.last_position - 1] = LEXER_COMMA_SEP_LIST; + context_p->stack_top_uint8 = LEXER_COMMA_SEP_LIST; + } + + lexer_next_token (context_p); +} /* parser_process_expression_sequence */ + +/** + * Process group expression. + */ +static void +parser_process_group_expression (parser_context_t *context_p, /**< context */ + size_t *grouping_level_p) /**< grouping level */ +{ + JERRY_ASSERT (*grouping_level_p >= PARSER_GROUPING_LEVEL_INCREASE); + (*grouping_level_p) -= PARSER_GROUPING_LEVEL_INCREASE; + + uint8_t token = context_p->stack_top_uint8; + + if (token == LEXER_COMMA_SEP_LIST) + { + parser_push_result (context_p); + parser_flush_cbc (context_p); + } + + parser_stack_pop_uint8 (context_p); + lexer_next_token (context_p); + + /* Lookahead for anonymous function declaration after '=' token when the assignment base is LHS expression + with a single indentifier in it. e.g.: (a) = function () {} */ + if (JERRY_UNLIKELY (context_p->token.type == LEXER_ASSIGN + && PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL + && parser_is_assignment_expr (context_p) && *grouping_level_p != PARSE_EXPR_LEFT_HAND_SIDE)) + { + parser_stack_push_uint8 (context_p, LEXER_ASSIGN_GROUP_EXPR); + } +} /* parser_process_group_expression */ + +/** + * Parse block expression. + */ +void +parser_parse_block_expression (parser_context_t *context_p, /**< context */ + int options) /**< option flags */ +{ + parser_parse_expression (context_p, options | PARSE_EXPR_NO_PUSH_RESULT); + + if (CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode)) + { + JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, context_p->last_cbc_opcode + 2)); + PARSER_PLUS_EQUAL_U16 (context_p->last_cbc_opcode, 2); + parser_flush_cbc (context_p); + } + else + { + parser_emit_cbc (context_p, CBC_POP_BLOCK); + } +} /* parser_parse_block_expression */ + +/** + * Parse expression statement. + */ +void +parser_parse_expression_statement (parser_context_t *context_p, /**< context */ + int options) /**< option flags */ +{ + parser_parse_expression (context_p, options | PARSE_EXPR_NO_PUSH_RESULT); + + if (!CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode)) + { + parser_emit_cbc (context_p, CBC_POP); + } +} /* parser_parse_expression_statement */ + +JERRY_STATIC_ASSERT ((PARSE_EXPR_LEFT_HAND_SIDE == 0x1), value_of_parse_expr_left_hand_side_must_be_1); + +/** + * Parse expression. + */ +void +parser_parse_expression (parser_context_t *context_p, /**< context */ + int options) /**< option flags */ +{ + size_t grouping_level = (options & PARSE_EXPR_LEFT_HAND_SIDE); + + parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START); + + if (options & PARSE_EXPR_HAS_LITERAL) + { + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + goto process_unary_expression; + } + + while (true) + { + if (parser_parse_unary_expression (context_p, &grouping_level)) + { + parser_process_binary_opcodes (context_p, 0); + break; + } + + while (true) + { +process_unary_expression: + parser_process_unary_expression (context_p, grouping_level); + + if (JERRY_LIKELY (grouping_level != PARSE_EXPR_LEFT_HAND_SIDE)) + { + uint8_t min_prec_treshold = 0; + + if (LEXER_IS_BINARY_OP_TOKEN (context_p->token.type)) + { + if (JERRY_UNLIKELY (context_p->token.type == LEXER_NULLISH_COALESCING)) + { + parser_check_invalid_logical_op (context_p, LEXER_LOGICAL_OR, LEXER_LOGICAL_AND); + } + + min_prec_treshold = parser_binary_precedence_table[context_p->token.type - LEXER_FIRST_BINARY_OP]; + + /* Check for BINARY_LVALUE tokens + LEXER_LOGICAL_OR + LEXER_LOGICAL_AND + LEXER_EXPONENTIATION */ + if ((min_prec_treshold == PARSER_RIGHT_TO_LEFT_ORDER_EXPONENTIATION) + || (min_prec_treshold <= PARSER_RIGHT_TO_LEFT_ORDER_MAX_PRECEDENCE + && min_prec_treshold != PARSER_RIGHT_TO_LEFT_ORDER_TERNARY_PRECEDENCE)) + { + /* Right-to-left evaluation order. */ + min_prec_treshold++; + } + } + + parser_process_binary_opcodes (context_p, min_prec_treshold); + } + if (context_p->token.type == LEXER_RIGHT_PAREN + && (context_p->stack_top_uint8 == LEXER_LEFT_PAREN || context_p->stack_top_uint8 == LEXER_COMMA_SEP_LIST)) + { + parser_process_group_expression (context_p, &grouping_level); + continue; + } + + break; + } + + if (grouping_level == PARSE_EXPR_LEFT_HAND_SIDE) + { + break; + } + + if (JERRY_UNLIKELY (context_p->token.type == LEXER_QUESTION_MARK)) + { + parser_process_ternary_expression (context_p); + + if (context_p->token.type == LEXER_RIGHT_PAREN) + { + goto process_unary_expression; + } + } + else if (LEXER_IS_BINARY_OP_TOKEN (context_p->token.type)) + { + parser_append_binary_token (context_p); + lexer_next_token (context_p); + continue; + } + + if (JERRY_UNLIKELY (context_p->token.type == LEXER_COMMA) + && (!(options & PARSE_EXPR_NO_COMMA) || grouping_level >= PARSER_GROUPING_LEVEL_INCREASE)) + { + parser_process_expression_sequence (context_p); + continue; + } + + break; + } + + if (grouping_level >= PARSER_GROUPING_LEVEL_INCREASE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + JERRY_ASSERT (context_p->stack_top_uint8 == LEXER_EXPRESSION_START); + parser_stack_pop_uint8 (context_p); + + if (!(options & PARSE_EXPR_NO_PUSH_RESULT)) + { + parser_push_result (context_p); + } +} /* parser_parse_expression */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-internal.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-internal.h new file mode 100644 index 00000000..14ee21c1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-internal.h @@ -0,0 +1,900 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_PARSER_INTERNAL_H +#define JS_PARSER_INTERNAL_H + +#include "ecma-module.h" + +#include "byte-code.h" +#include "common.h" +#include "js-lexer.h" +#include "js-parser-limits.h" +#include "js-parser.h" +#include "js-scanner.h" +#include "parser-errors.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_internals Internals + * @{ + */ + +/** + * General parser flags. + */ +typedef enum +{ + PARSER_IS_STRICT = (1u << 0), /**< strict mode code */ + PARSER_IS_FUNCTION = (1u << 1), /**< function body is parsed */ + PARSER_IS_CLOSURE = (1u << 2), /**< function body is encapsulated in {} block */ + PARSER_IS_FUNC_EXPRESSION = (1u << 3), /**< a function expression is parsed */ + PARSER_IS_PROPERTY_GETTER = (1u << 4), /**< a property getter function is parsed */ + PARSER_IS_PROPERTY_SETTER = (1u << 5), /**< a property setter function is parsed */ + PARSER_HAS_NON_STRICT_ARG = (1u << 6), /**< the function has arguments which + * are not supported in strict mode */ + PARSER_ARGUMENTS_NEEDED = (1u << 7), /**< arguments object must be created */ + PARSER_LEXICAL_ENV_NEEDED = (1u << 8), /**< lexical environment object must be created */ + PARSER_INSIDE_WITH = (1u << 9), /**< code block is inside a with statement */ + PARSER_NO_END_LABEL = (1u << 10), /**< return instruction must be inserted + * after the last byte code */ + PARSER_DEBUGGER_BREAKPOINT_APPENDED = (1u << 11), /**< pending (unsent) breakpoint + * info is available */ + PARSER_LEXICAL_BLOCK_NEEDED = (1u << 12), /**< global script: needs a lexical environment for let and const + * function: needs a lexical environment for arguments */ + PARSER_IS_ARROW_FUNCTION = (1u << 13), /**< an arrow function is parsed */ + PARSER_IS_GENERATOR_FUNCTION = (1u << 14), /**< a generator function is parsed */ + PARSER_IS_ASYNC_FUNCTION = (1u << 15), /**< an async function is parsed */ + PARSER_DISALLOW_AWAIT_YIELD = (1u << 16), /**< throw SyntaxError for await / yield keywords */ + PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT = (1u << 17), /**< function has complex (ES2015+) argument definition */ + PARSER_FUNCTION_HAS_REST_PARAM = (1u << 18), /**< function has rest parameter */ + PARSER_CLASS_CONSTRUCTOR = (1u << 19), /**< a class constructor is parsed + * Note: PARSER_ALLOW_SUPER must be present */ + /* These five status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ + PARSER_ALLOW_SUPER = (1u << 20), /**< allow super property access */ + PARSER_ALLOW_SUPER_CALL = (1u << 21), /**< allow super constructor call + * Note: PARSER_CLASS_CONSTRUCTOR must be present */ + PARSER_FUNCTION_IS_PARSING_ARGS = (1u << 22), /**< set when parsing function arguments */ + PARSER_INSIDE_CLASS_FIELD = (1u << 23), /**< a class field is being parsed */ + PARSER_ALLOW_NEW_TARGET = (1u << 24), /**< allow new.target parsing in the current context */ + PARSER_IS_METHOD = (1u << 25), /**< method is parsed */ + PARSER_IS_CLASS_STATIC_BLOCK = (1u << 26), /**< a class static block is parsed */ + PARSER_PRIVATE_FUNCTION_NAME = PARSER_IS_FUNC_EXPRESSION, /**< represents private method for + * parser_set_function_name*/ +#if JERRY_MODULE_SYSTEM + PARSER_MODULE_DEFAULT_CLASS_OR_FUNC = (1u << 27), /**< parsing a function or class default export */ + PARSER_MODULE_STORE_IDENT = (1u << 28), /**< store identifier of the current export statement */ +#endif /* JERRY_MODULE_SYSTEM */ + PARSER_HAS_LATE_LIT_INIT = (1u << 30), /**< there are identifier or string literals which construction + * is postponed after the local parser data is freed */ +#ifndef JERRY_NDEBUG + PARSER_SCANNING_SUCCESSFUL = PARSER_HAS_LATE_LIT_INIT, /**< scanning process was successful */ +#endif /* !JERRY_NDEBUG */ +} parser_general_flags_t; + +/** + * Expression parsing flags. + */ +typedef enum +{ + PARSE_EXPR = 0, /**< parse an expression without any special flags */ + PARSE_EXPR_LEFT_HAND_SIDE = (1u << 0), /**< parse a left-hand-side expression */ + PARSE_EXPR_NO_PUSH_RESULT = (1u << 1), /**< do not push the result of the expression onto the stack */ + PARSE_EXPR_NO_COMMA = (1u << 2), /**< do not parse comma operator */ + PARSE_EXPR_HAS_LITERAL = (1u << 3), /**< a primary literal is provided by a + * CBC_PUSH_LITERAL instruction */ +} parser_expression_flags_t; + +/** + * Pattern parsing flags. + */ +typedef enum +{ + PARSER_PATTERN_NO_OPTS = 0, /**< parse the expression after '=' */ + PARSER_PATTERN_BINDING = (1u << 0), /**< parse BindingPattern */ + PARSER_PATTERN_TARGET_ON_STACK = (1u << 1), /**< assignment target is the topmost element on the stack */ + PARSER_PATTERN_TARGET_DEFAULT = (1u << 2), /**< perform default value comparison for assignment target */ + PARSER_PATTERN_NESTED_PATTERN = (1u << 3), /**< parse pattern inside a pattern */ + PARSER_PATTERN_LET = (1u << 4), /**< pattern is a let declaration */ + PARSER_PATTERN_CONST = (1u << 5), /**< pattern is a const declaration */ + PARSER_PATTERN_LOCAL = (1u << 6), /**< pattern is a local (catch parameter) declaration */ + PARSER_PATTERN_REST_ELEMENT = (1u << 7), /**< parse rest array / object element */ + PARSER_PATTERN_HAS_REST_ELEMENT = (1u << 8), /**< object literal rest element will be present */ + PARSER_PATTERN_ARGUMENTS = (1u << 9), /**< parse arguments binding */ +} parser_pattern_flags_t; + +/** + * Check type for scanner_is_context_needed function. + */ +typedef enum +{ + PARSER_CHECK_BLOCK_CONTEXT, /**< check block context */ + PARSER_CHECK_GLOBAL_CONTEXT, /**< check global context */ + PARSER_CHECK_FUNCTION_CONTEXT, /**< check function context */ +} parser_check_context_type_t; + +/** + * Class field bits. + */ +typedef enum +{ + PARSER_CLASS_FIELD_END = (1u << 0), /**< last class field */ + PARSER_CLASS_FIELD_NORMAL = (1u << 1), /**< normal (non-computed) class field */ + PARSER_CLASS_FIELD_INITIALIZED = (1u << 2), /**< class field is initialized */ + PARSER_CLASS_FIELD_STATIC = (1u << 3), /**< static class field */ + PARSER_CLASS_FIELD_STATIC_BLOCK = (1u << 4), /**< static class field */ +} parser_class_field_type_t; + +/** + * Mask for strict mode code + */ +#define PARSER_STRICT_MODE_MASK 0x1 + +/** + * Shorthand for function closure definition + */ +#define PARSER_FUNCTION_CLOSURE (PARSER_IS_FUNCTION | PARSER_IS_CLOSURE) + +#if PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX +/** + * Maximum number of bytes for branch target. + */ +#define PARSER_MAX_BRANCH_LENGTH 2 +#else /* PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX */ +/** + * Maximum number of bytes for branch target. + */ +#define PARSER_MAX_BRANCH_LENGTH 3 +#endif /* PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX */ + +/** + * Offset of PARSER_ALLOW_SUPER + */ +#define PARSER_SAVED_FLAGS_OFFSET JERRY_LOG2 (PARSER_ALLOW_SUPER) + +/** + * Mask of saved flags + */ +#define PARSER_SAVED_FLAGS_MASK \ + ((1 << (JERRY_LOG2 (PARSER_ALLOW_NEW_TARGET) - JERRY_LOG2 (PARSER_ALLOW_SUPER) + 1)) - 1) + +/** + * Get class option bits from parser_general_flags_t + */ +#define PARSER_SAVE_STATUS_FLAGS(opts) ((uint16_t) (((opts) >> PARSER_SAVED_FLAGS_OFFSET) & PARSER_SAVED_FLAGS_MASK)) + +/** + * Mask for get class option bits from ecma_parse_opts_t + */ +#define PARSER_RESTORE_STATUS_FLAGS_MASK (((ECMA_PARSE_ALLOW_NEW_TARGET << 1) - 1) - (ECMA_PARSE_ALLOW_SUPER - 1)) + +/** + * Shift for get class option bits from ecma_parse_opts_t + */ +#define PARSER_RESTORE_STATUS_FLAGS_SHIFT (JERRY_LOG2 (PARSER_ALLOW_SUPER) - JERRY_LOG2 (ECMA_PARSE_ALLOW_SUPER)) + +/** + * Get class option bits from ecma_parse_opts_t + */ +#define PARSER_RESTORE_STATUS_FLAGS(opts) \ + (((opts) &PARSER_RESTORE_STATUS_FLAGS_MASK) << PARSER_RESTORE_STATUS_FLAGS_SHIFT) + +/** + * All flags that affect exotic arguments object creation. + */ +#define PARSER_ARGUMENTS_RELATED_FLAGS \ + (PARSER_ARGUMENTS_NEEDED | PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT | PARSER_IS_STRICT) + +/** + * Get the corresponding eval flag for a ecma_parse_opts_t flag + */ +#define PARSER_GET_EVAL_FLAG(type) ((type) >> JERRY_LOG2 (ECMA_PARSE_ALLOW_SUPER)) + +/** + * Check non-generator async functions + */ +#define PARSER_IS_NORMAL_ASYNC_FUNCTION(status_flags) \ + (((status_flags) & (PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION)) == PARSER_IS_ASYNC_FUNCTION) + +/* Checks whether unmapped arguments are needed. */ +#define PARSER_NEEDS_MAPPED_ARGUMENTS(status_flags) \ + (((status_flags) &PARSER_ARGUMENTS_RELATED_FLAGS) == PARSER_ARGUMENTS_NEEDED) + +/* The maximum of PARSER_CBC_STREAM_PAGE_SIZE is 127. */ +#define PARSER_CBC_STREAM_PAGE_SIZE ((uint32_t) (64 - sizeof (void *))) + +/* Defines the size of the max page. */ +#define PARSER_STACK_PAGE_SIZE ((uint32_t) (((sizeof (void *) > 4) ? 128 : 64) - sizeof (void *))) + +/* Avoid compiler warnings for += operations. */ +#define PARSER_PLUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) + (value)) +#define PARSER_MINUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) - (value)) +#define PARSER_PLUS_EQUAL_LC(base, value) (base) = (parser_line_counter_t) ((base) + (value)) + +/** + * Argument for a compact-byte code. + */ +typedef struct +{ + uint16_t literal_index; /**< literal index argument */ + uint16_t value; /**< other argument (second literal or byte). */ + uint16_t third_literal_index; /**< literal index argument */ + uint8_t literal_type; /**< last literal type */ + uint8_t literal_keyword_type; /**< last literal keyword type */ +} cbc_argument_t; + +/* Useful parser macros. */ + +#define PARSER_CBC_UNAVAILABLE CBC_EXT_OPCODE + +#define PARSER_TO_EXT_OPCODE(opcode) ((uint16_t) ((opcode) + 256)) +#define PARSER_GET_EXT_OPCODE(opcode) ((opcode) -256) +#define PARSER_IS_BASIC_OPCODE(opcode) ((opcode) < 256) +#define PARSER_IS_PUSH_LITERAL(opcode) \ + ((opcode) == CBC_PUSH_LITERAL || (opcode) == CBC_PUSH_TWO_LITERALS || (opcode) == CBC_PUSH_THREE_LITERALS) +#define PARSER_IS_PUSH_NUMBER(opcode) \ + ((opcode) >= CBC_PUSH_NUMBER_0 && (opcode) <= CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE) + +#define PARSER_IS_MUTABLE_PUSH_LITERAL(opcode) ((opcode) >= CBC_PUSH_LITERAL && (opcode) <= CBC_PUSH_THIS_LITERAL) + +#define PARSER_IS_PUSH_LITERALS_WITH_THIS(opcode) ((opcode) >= CBC_PUSH_LITERAL && (opcode) <= CBC_PUSH_THREE_LITERALS) + +#define PARSER_IS_PUSH_PROP(opcode) ((opcode) >= CBC_PUSH_PROP && (opcode) <= CBC_PUSH_PROP_THIS_LITERAL) + +#define PARSER_IS_PUSH_PROP_LITERAL(opcode) \ + ((opcode) >= CBC_PUSH_PROP_LITERAL && (opcode) <= CBC_PUSH_PROP_THIS_LITERAL) + +#define PARSER_PUSH_LITERAL_TO_PUSH_PROP_LITERAL(opcode) \ + (uint16_t) ((opcode) + (CBC_PUSH_PROP_LITERAL - CBC_PUSH_LITERAL)) + +#define PARSER_PUSH_PROP_LITERAL_TO_PUSH_LITERAL(opcode) \ + (uint16_t) ((opcode) - (CBC_PUSH_PROP_LITERAL - CBC_PUSH_LITERAL)) + +#define PARSER_PUSH_PROP_TO_PUSH_PROP_REFERENCE(opcode) \ + (uint16_t) ((opcode) + (CBC_PUSH_PROP_REFERENCE - CBC_PUSH_PROP)) + +#define PARSER_PUSH_PROP_REFERENCE_TO_PUSH_PROP(opcode) \ + (uint16_t) ((opcode) - (CBC_PUSH_PROP_REFERENCE - CBC_PUSH_PROP)) + +#define PARSER_GET_LITERAL(literal_index) \ + ((lexer_literal_t *) parser_list_get (&context_p->literal_pool, (literal_index))) + +#define PARSER_TO_BINARY_OPERATION_WITH_RESULT(opcode) \ + (PARSER_TO_EXT_OPCODE (opcode) - CBC_ASSIGN_ADD + CBC_EXT_ASSIGN_ADD_PUSH_RESULT) + +#define PARSER_TO_BINARY_OPERATION_WITH_BLOCK(opcode) \ + ((uint16_t) (PARSER_TO_EXT_OPCODE (opcode) - CBC_ASSIGN_ADD + CBC_EXT_ASSIGN_ADD_BLOCK)) + +#define PARSER_GET_FLAGS(op) (PARSER_IS_BASIC_OPCODE (op) ? cbc_flags[(op)] : cbc_ext_flags[PARSER_GET_EXT_OPCODE (op)]) + +#define PARSER_OPCODE_IS_RETURN(op) \ + ((op) == CBC_RETURN || (op) == CBC_RETURN_FUNCTION_END || (op) == CBC_RETURN_WITH_LITERAL) + +#define PARSER_ARGS_EQ(op, types) ((PARSER_GET_FLAGS (op) & CBC_ARG_TYPES) == (types)) + +/** + * All data allocated by the parser is + * stored in parser_data_pages in the memory. + */ +#if defined(_WIN32) +#pragma warning(push) +#pragma warning(disable:4200) +#endif +typedef struct parser_mem_page_t +{ + struct parser_mem_page_t *next_p; /**< next page */ + uint8_t bytes[]; /**< memory bytes, C99 flexible array member */ +} parser_mem_page_t; +#if defined(_WIN32) +#pragma warning(pop) +#endif + +/** + * Structure for managing parser memory. + */ +typedef struct +{ + parser_mem_page_t *first_p; /**< first allocated page */ + parser_mem_page_t *last_p; /**< last allocated page */ + uint32_t last_position; /**< position of the last allocated byte */ +} parser_mem_data_t; + +/** + * Parser memory list. + */ +typedef struct +{ + parser_mem_data_t data; /**< storage space */ + uint32_t page_size; /**< size of each page */ + uint32_t item_size; /**< size of each item */ + uint32_t item_count; /**< number of items on each page */ +} parser_list_t; + +/** + * Iterator for parser memory list. + */ +typedef struct +{ + parser_list_t *list_p; /**< parser list */ + parser_mem_page_t *current_p; /**< currently processed page */ + size_t current_position; /**< current position on the page */ +} parser_list_iterator_t; + +/** + * Parser memory stack. + */ +typedef struct +{ + parser_mem_data_t data; /**< storage space */ + parser_mem_page_t *free_page_p; /**< space for fast allocation */ +} parser_stack_t; + +/** + * Iterator for parser memory stack. + */ +typedef struct +{ + parser_mem_page_t *current_p; /**< currently processed page */ + size_t current_position; /**< current position on the page */ +} parser_stack_iterator_t; + +/** + * Branch type. + */ +typedef struct +{ + parser_mem_page_t *page_p; /**< branch location page */ + uint32_t offset; /**< branch location offset */ +} parser_branch_t; + +/** + * Branch chain type. + */ +typedef struct parser_branch_node_t +{ + struct parser_branch_node_t *next_p; /**< next linked list node */ + parser_branch_t branch; /**< branch */ +} parser_branch_node_t; + +/** + * Items of scope stack. + */ +typedef struct +{ + uint16_t map_from; /**< original literal index */ + uint16_t map_to; /**< encoded register or literal index and flags */ +} parser_scope_stack_t; + +/** + * This item represents a function literal in the scope stack. + * + * When map_from == PARSER_SCOPE_STACK_FUNC: + * map_to represents the literal reserved for a function literal + * Note: the name of the function is the previous value in the scope stack + * Note: map_to is not encoded in this case + */ +#define PARSER_SCOPE_STACK_FUNC 0xffff + +/** + * Mask for decoding the register index of map_to + */ +#define PARSER_SCOPE_STACK_REGISTER_MASK 0x3fff + +/** + * Function statements with the name specified + * in map_from should not be copied to global scope. + */ +#define PARSER_SCOPE_STACK_NO_FUNCTION_COPY 0x8000 + +/** + * The scope stack item represents a const binding stored in register + */ +#define PARSER_SCOPE_STACK_IS_CONST_REG 0x4000 + +/** + * The scope stack item represents a binding which has already created with ECMA_VALUE_UNINITIALIZED + */ +#define PARSER_SCOPE_STACK_IS_LOCAL_CREATED (PARSER_SCOPE_STACK_IS_CONST_REG) + +/** + * Starting literal index for registers. + */ +#define PARSER_REGISTER_START 0x8000 + +/** + * Invalid literal index + */ +#define PARSER_INVALID_LITERAL_INDEX UINT16_MAX + +/** + * Lastly emitted opcode is not a function literal + */ +#define PARSER_NOT_FUNCTION_LITERAL PARSER_INVALID_LITERAL_INDEX + +/** + * Lastly emitted opcode is not a named function literal + */ +#define PARSER_NAMED_FUNCTION (uint16_t) (PARSER_NOT_FUNCTION_LITERAL - 1) + +/** + * Lastly emitted opcode is not an anonymous class literal + */ +#define PARSER_ANONYMOUS_CLASS (uint16_t) (PARSER_NAMED_FUNCTION - 1) + +/* Forward definitions for js-scanner-internal.h. */ +struct scanner_context_t; +typedef struct scanner_context_t scanner_context_t; + +#if JERRY_LINE_INFO + +typedef struct +{ + parser_mem_page_t *last_page_p; /**< last page of line info data */ + uint32_t byte_code_position; /**< last byte code position */ + parser_line_counter_t line; /**< last line */ + parser_line_counter_t column; /**< last column */ +} parser_line_info_data_t; + +#endif /* JERRY_LINE_INFO */ + +/** + * List of private field contexts + */ +typedef struct parser_private_context_t +{ + scanner_class_private_member_t *members_p; /**< current private field context members */ + struct parser_private_context_t *prev_p; /**< previous private field context */ + uint8_t opts; /**< options */ +} parser_private_context_t; + +/** + * Those members of a context which needs + * to be saved when a sub-function is parsed. + */ +typedef struct parser_saved_context_t +{ + /* Parser members. */ + uint32_t status_flags; /**< parsing options */ + uint16_t stack_depth; /**< current stack depth */ + uint16_t stack_limit; /**< maximum stack depth */ + struct parser_saved_context_t *prev_context_p; /**< last saved context */ + parser_stack_iterator_t last_statement; /**< last statement position */ + + /* Literal types */ + uint16_t argument_count; /**< number of function arguments */ + uint16_t argument_length; /**< length property of arguments */ + uint16_t register_count; /**< number of registers */ + uint16_t literal_count; /**< number of literals */ + + /* Memory storage members. */ + parser_mem_data_t byte_code; /**< byte code buffer */ + uint32_t byte_code_size; /**< byte code size for branches */ + parser_mem_data_t literal_pool_data; /**< literal list */ + parser_scope_stack_t *scope_stack_p; /**< scope stack */ + uint16_t scope_stack_size; /**< size of scope stack */ + uint16_t scope_stack_top; /**< preserved top of scope stack */ + uint16_t scope_stack_reg_top; /**< preserved top register of scope stack */ + uint16_t scope_stack_global_end; /**< end of global declarations of a function */ + ecma_value_t tagged_template_literal_cp; /**< compessed pointer to the tagged template literal collection */ +#ifndef JERRY_NDEBUG + uint16_t context_stack_depth; /**< current context stack depth */ +#endif /* !JERRY_NDEBUG */ + +#if JERRY_LINE_INFO + parser_line_info_data_t *line_info_p; /**< line info data */ +#endif /* JERRY_LINE_INFO */ + +#if JERRY_FUNCTION_TO_STRING + const uint8_t *function_start_p; /**< start position of the current function */ +#endif /* JERRY_FUNCTION_TO_STRING */ +} parser_saved_context_t; + +/** + * Shared parser context. + */ +typedef struct +{ + PARSER_TRY_CONTEXT (try_buffer); /**< try_buffer */ + parser_error_msg_t error; /**< error code */ + /** Union for rarely used members. */ + union + { + void *allocated_buffer_p; /**< dinamically allocated buffer + * which needs to be freed on error */ + scanner_context_t *scanner_context_p; /**< scanner context for the pre-scanner */ + } u; + uint32_t allocated_buffer_size; /**< size of the dinamically allocated buffer */ + + /* Parser members. */ + uint32_t status_flags; /**< status flags */ + uint32_t global_status_flags; /**< global status flags */ + uint16_t stack_depth; /**< current stack depth */ + uint16_t stack_limit; /**< maximum stack depth */ + const jerry_parse_options_t *options_p; /**< parse options */ + parser_saved_context_t *last_context_p; /**< last saved context */ + parser_stack_iterator_t last_statement; /**< last statement position */ + cbc_script_t *script_p; /**< current script */ + const uint8_t *source_start_p; /**< source start */ + lit_utf8_size_t source_size; /**< source size */ + const uint8_t *arguments_start_p; /**< function argument list start */ + lit_utf8_size_t arguments_size; /**< function argument list size */ + ecma_value_t script_value; /**< current script as value */ + ecma_value_t argument_list; /**< current argument list as value */ + ecma_value_t user_value; /**< current user value */ + +#if JERRY_MODULE_SYSTEM + ecma_module_names_t *module_names_p; /**< import / export names that is being processed */ + lexer_literal_t *module_identifier_lit_p; /**< the literal for the identifier of the current element */ +#endif /* JERRY_MODULE_SYSTEM */ + + /* Lexer members. */ + lexer_token_t token; /**< current token */ + lexer_lit_object_t lit_object; /**< current literal object */ + const uint8_t *source_p; /**< next source byte */ + const uint8_t *source_end_p; /**< last source byte */ + parser_line_counter_t line; /**< current line */ + parser_line_counter_t column; /**< current column */ + + /* Scanner members. */ + scanner_info_t *next_scanner_info_p; /**< next scanner info block */ + scanner_info_t *active_scanner_info_p; /**< currently active scanner info block */ + scanner_info_t *skipped_scanner_info_p; /**< next scanner info block */ + scanner_info_t *skipped_scanner_info_end_p; /**< currently active scanner info block */ + + /* Compact byte code members. */ + cbc_argument_t last_cbc; /**< argument of the last cbc */ + uint16_t last_cbc_opcode; /**< opcode of the last cbc */ + + /* Literal types */ + uint16_t argument_count; /**< number of function arguments */ + uint16_t argument_length; /**< length property of arguments */ + uint16_t register_count; /**< number of registers */ + uint16_t literal_count; /**< number of literals */ + + /* Memory storage members. */ + parser_mem_data_t byte_code; /**< byte code buffer */ + uint32_t byte_code_size; /**< current byte code size for branches */ + parser_list_t literal_pool; /**< literal list */ + parser_mem_data_t stack; /**< storage space */ + parser_scope_stack_t *scope_stack_p; /**< scope stack */ + parser_mem_page_t *free_page_p; /**< space for fast allocation */ + uint16_t scope_stack_size; /**< size of scope stack */ + uint16_t scope_stack_top; /**< current top of scope stack */ + uint16_t scope_stack_reg_top; /**< current top register of scope stack */ + uint16_t scope_stack_global_end; /**< end of global declarations of a function */ + ecma_value_t tagged_template_literal_cp; /**< compessed pointer to the tagged template literal collection */ + parser_private_context_t *private_context_p; /**< private context */ + uint8_t stack_top_uint8; /**< top byte stored on the stack */ + +#ifndef JERRY_NDEBUG + /* Variables for debugging / logging. */ + uint16_t context_stack_depth; /**< current context stack depth */ +#endif /* !JERRY_NDEBUG */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + int is_show_opcodes; /**< show opcodes */ + uint32_t total_byte_code_size; /**< total byte code size */ +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +#if JERRY_LINE_INFO + parser_line_info_data_t *line_info_p; /**< line info data */ +#endif /* JERRY_LINE_INFO */ + +#if JERRY_FUNCTION_TO_STRING + const uint8_t *function_start_p; /**< start position of the function which will be parsed */ + const uint8_t *function_end_p; /**< end position of the current function */ +#endif /* JERRY_FUNCTION_TO_STRING */ +} parser_context_t; + +/** + * @} + * @} + * @} + * + * \addtogroup mem Memory allocation + * @{ + * + * \addtogroup mem_parser Parser memory manager + * @{ + */ + +/* Memory management. + * Note: throws an error if unsuccessful. */ +void *parser_malloc (parser_context_t *context_p, size_t size); +void parser_free (void *ptr, size_t size); +void *parser_malloc_local (parser_context_t *context_p, size_t size); +void parser_free_local (void *ptr, size_t size); +void parser_free_allocated_buffer (parser_context_t *context_p); + +/* Parser byte stream. */ + +void parser_cbc_stream_init (parser_mem_data_t *data_p); +void parser_cbc_stream_free (parser_mem_data_t *data_p); +void parser_cbc_stream_alloc_page (parser_context_t *context_p, parser_mem_data_t *data_p); + +/* Parser list. Ensures pointer alignment. */ + +void parser_list_init (parser_list_t *list_p, uint32_t item_size, uint32_t item_count); +void parser_list_free (parser_list_t *list_p); +void parser_list_reset (parser_list_t *list_p); +void *parser_list_append (parser_context_t *context_p, parser_list_t *list_p); +void *parser_list_get (parser_list_t *list_p, size_t index); +void parser_list_iterator_init (parser_list_t *list_p, parser_list_iterator_t *iterator_p); +void *parser_list_iterator_next (parser_list_iterator_t *iterator_p); + +/* Parser stack. Optimized for pushing bytes. + * Pop functions never throws error. */ + +void parser_stack_init (parser_context_t *context_p); +void parser_stack_free (parser_context_t *context_p); +void parser_stack_push_uint8 (parser_context_t *context_p, uint8_t uint8_value); +void parser_stack_pop_uint8 (parser_context_t *context_p); +void parser_stack_change_last_uint8 (parser_context_t *context_p, uint8_t new_value); +uint8_t *parser_stack_get_prev_uint8 (parser_context_t *context_p); +void parser_stack_push_uint16 (parser_context_t *context_p, uint16_t uint16_value); +uint16_t parser_stack_pop_uint16 (parser_context_t *context_p); +void parser_stack_push (parser_context_t *context_p, const void *data_p, uint32_t length); +void parser_stack_pop (parser_context_t *context_p, void *data_p, uint32_t length); +void parser_stack_iterator_init (parser_context_t *context_p, parser_stack_iterator_t *iterator); +uint8_t parser_stack_iterator_read_uint8 (parser_stack_iterator_t *iterator); +void parser_stack_iterator_skip (parser_stack_iterator_t *iterator, size_t length); +void parser_stack_iterator_read (parser_stack_iterator_t *iterator, void *data_p, size_t length); +void parser_stack_iterator_write (parser_stack_iterator_t *iterator, const void *data_p, size_t length); + +/** + * @} + * @} + * + * \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_utils Utility + * @{ + */ + +/* Compact byte code emitting functions. */ + +void parser_flush_cbc (parser_context_t *context_p); +void parser_emit_cbc (parser_context_t *context_p, uint16_t opcode); +void parser_emit_cbc_literal (parser_context_t *context_p, uint16_t opcode, uint16_t literal_index); +void +parser_emit_cbc_literal_value (parser_context_t *context_p, uint16_t opcode, uint16_t literal_index, uint16_t value); +void parser_emit_cbc_literal_from_token (parser_context_t *context_p, uint16_t opcode); +void parser_emit_cbc_call (parser_context_t *context_p, uint16_t opcode, size_t call_arguments); +void parser_emit_cbc_push_number (parser_context_t *context_p, bool is_negative_number); +void parser_emit_cbc_forward_branch (parser_context_t *context_p, uint16_t opcode, parser_branch_t *branch_p); +parser_branch_node_t * +parser_emit_cbc_forward_branch_item (parser_context_t *context_p, uint16_t opcode, parser_branch_node_t *next_p); +void parser_emit_cbc_backward_branch (parser_context_t *context_p, uint16_t opcode, uint32_t offset); +ecma_string_t *parser_new_ecma_string_from_literal (lexer_literal_t *literal_p); +void parser_set_branch_to_current_position (parser_context_t *context_p, parser_branch_t *branch_p); +void parser_set_breaks_to_current_position (parser_context_t *context_p, parser_branch_node_t *current_p); +void parser_set_continues_to_current_position (parser_context_t *context_p, parser_branch_node_t *current_p); +void parser_reverse_class_fields (parser_context_t *context_p, size_t fields_size); + +/* Convenience macros. */ +#define parser_emit_cbc_ext(context_p, opcode) parser_emit_cbc ((context_p), PARSER_TO_EXT_OPCODE (opcode)) +#define parser_emit_cbc_ext_literal(context_p, opcode, literal_index) \ + parser_emit_cbc_literal ((context_p), PARSER_TO_EXT_OPCODE (opcode), (literal_index)) +#define parser_emit_cbc_ext_literal_from_token(context_p, opcode) \ + parser_emit_cbc_literal_from_token ((context_p), PARSER_TO_EXT_OPCODE (opcode)) +#define parser_emit_cbc_ext_call(context_p, opcode, call_arguments) \ + parser_emit_cbc_call ((context_p), PARSER_TO_EXT_OPCODE (opcode), (call_arguments)) +#define parser_emit_cbc_ext_call(context_p, opcode, call_arguments) \ + parser_emit_cbc_call ((context_p), PARSER_TO_EXT_OPCODE (opcode), (call_arguments)) +#define parser_emit_cbc_ext_forward_branch(context_p, opcode, branch_p) \ + parser_emit_cbc_forward_branch ((context_p), PARSER_TO_EXT_OPCODE (opcode), (branch_p)) +#define parser_emit_cbc_ext_backward_branch(context_p, opcode, offset) \ + parser_emit_cbc_backward_branch ((context_p), PARSER_TO_EXT_OPCODE (opcode), (offset)) + +/** + * @} + * + * \addtogroup jsparser_lexer Lexer + * @{ + */ + +/* Lexer functions */ + +void lexer_next_token (parser_context_t *context_p); +bool lexer_check_next_character (parser_context_t *context_p, lit_utf8_byte_t character); +bool lexer_check_next_characters (parser_context_t *context_p, lit_utf8_byte_t character1, lit_utf8_byte_t character2); +uint8_t lexer_consume_next_character (parser_context_t *context_p); +bool lexer_check_post_primary_exp (parser_context_t *context_p); +void lexer_skip_empty_statements (parser_context_t *context_p); +bool lexer_check_arrow (parser_context_t *context_p); +bool lexer_check_arrow_param (parser_context_t *context_p); +bool lexer_check_yield_no_arg (parser_context_t *context_p); +bool lexer_consume_generator (parser_context_t *context_p); +bool lexer_consume_assign (parser_context_t *context_p); +void lexer_update_await_yield (parser_context_t *context_p, uint32_t status_flags); +bool lexer_scan_private_identifier (parser_context_t *context_p); +void lexer_parse_string (parser_context_t *context_p, lexer_string_options_t opts); +void lexer_expect_identifier (parser_context_t *context_p, uint8_t literal_type); +bool lexer_scan_identifier (parser_context_t *context_p, lexer_parse_options_t opts); +void lexer_check_property_modifier (parser_context_t *context_p); +void lexer_convert_ident_to_cesu8 (uint8_t *destination_p, const uint8_t *source_p, prop_length_t length); + +const uint8_t *lexer_convert_literal_to_chars (parser_context_t *context_p, + const lexer_lit_location_t *literal_p, + uint8_t *local_byte_array_p, + lexer_string_options_t opts); +void lexer_expect_object_literal_id (parser_context_t *context_p, uint32_t ident_opts); +lexer_literal_t *lexer_construct_unused_literal (parser_context_t *context_p); +void lexer_construct_literal_object (parser_context_t *context_p, + const lexer_lit_location_t *lit_location_p, + uint8_t literal_type); +bool lexer_construct_number_object (parser_context_t *context_p, bool is_expr, bool is_negative_number); +void lexer_convert_push_number_to_push_literal (parser_context_t *context_p); +uint16_t lexer_construct_function_object (parser_context_t *context_p, uint32_t extra_status_flags); +uint16_t lexer_construct_class_static_block_function (parser_context_t *context_p); +void lexer_construct_regexp_object (parser_context_t *context_p, bool parse_only); +bool lexer_compare_identifier_to_string (const lexer_lit_location_t *left_p, const uint8_t *right_p, size_t size); +bool lexer_compare_identifiers (parser_context_t *context_p, + const lexer_lit_location_t *left_p, + const lexer_lit_location_t *right_p); +bool lexer_current_is_literal (parser_context_t *context_p, const lexer_lit_location_t *right_ident_p); +bool lexer_string_is_use_strict (parser_context_t *context_p); +bool lexer_string_is_directive (parser_context_t *context_p); +bool lexer_token_is_identifier (parser_context_t *context_p, const char *identifier_p, size_t identifier_length); +bool lexer_token_is_let (parser_context_t *context_p); +bool lexer_token_is_async (parser_context_t *context_p); +bool lexer_compare_literal_to_string (parser_context_t *context_p, const char *string_p, size_t string_length); +void lexer_init_line_info (parser_context_t *context_p); +uint8_t lexer_convert_binary_lvalue_token_to_binary (uint8_t token); + +/** + * @} + * + * \addtogroup jsparser_expr Expression parser + * @{ + */ + +/* Parser functions. */ + +void parser_parse_block_expression (parser_context_t *context_p, int options); +void parser_parse_expression_statement (parser_context_t *context_p, int options); +void parser_parse_expression (parser_context_t *context_p, int options); +void parser_resolve_private_identifier (parser_context_t *context_p); +void parser_save_private_context (parser_context_t *context_p, + parser_private_context_t *private_ctx_p, + scanner_class_info_t *class_info_p); +void parser_restore_private_context (parser_context_t *context_p, parser_private_context_t *private_ctx_p); +void parser_parse_class (parser_context_t *context_p, bool is_statement); +void parser_parse_initializer (parser_context_t *context_p, parser_pattern_flags_t flags); +void parser_parse_initializer_by_next_char (parser_context_t *context_p, parser_pattern_flags_t flags); +/** + * @} + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +void scanner_release_next (parser_context_t *context_p, size_t size); +void scanner_set_active (parser_context_t *context_p); +void scanner_revert_active (parser_context_t *context_p); +void scanner_release_active (parser_context_t *context_p, size_t size); +void scanner_release_switch_cases (scanner_case_info_t *case_p); +void scanner_release_private_fields (scanner_class_private_member_t *member_p); +void scanner_seek (parser_context_t *context_p); +void scanner_reverse_info_list (parser_context_t *context_p); +void scanner_cleanup (parser_context_t *context_p); + +bool scanner_is_context_needed (parser_context_t *context_p, parser_check_context_type_t check_type); +bool scanner_try_scan_new_target (parser_context_t *context_p); +void scanner_check_variables (parser_context_t *context_p); +void scanner_create_variables (parser_context_t *context_p, uint32_t option_flags); + +void scanner_get_location (scanner_location_t *location_p, parser_context_t *context_p); +void scanner_set_location (parser_context_t *context_p, scanner_location_t *location_p); +uint16_t scanner_decode_map_to (parser_scope_stack_t *stack_item_p); +uint16_t scanner_save_literal (parser_context_t *context_p, uint16_t ident_index); +bool scanner_literal_is_const_reg (parser_context_t *context_p, uint16_t literal_index); +bool scanner_literal_is_created (parser_context_t *context_p, uint16_t literal_index); +bool scanner_literal_exists (parser_context_t *context_p, uint16_t literal_index); + +void scanner_scan_all (parser_context_t *context_p); + +/** + * @} + * + * \addtogroup jsparser_stmt Statement parser + * @{ + */ + +void parser_parse_statements (parser_context_t *context_p); +void parser_free_jumps (parser_stack_iterator_t iterator); + +#if JERRY_MODULE_SYSTEM +/** + * @} + * + * \addtogroup jsparser_stmt Module statement parser + * @{ + */ + +extern const lexer_lit_location_t lexer_default_literal; +void parser_module_check_request_place (parser_context_t *context_p); +void parser_module_context_init (parser_context_t *context_p); +void parser_module_append_names (parser_context_t *context_p, ecma_module_names_t **module_names_p); +void parser_module_handle_module_specifier (parser_context_t *context_p, ecma_module_node_t **node_list_p); +void parser_module_handle_requests (parser_context_t *context_p); +void parser_module_parse_export_clause (parser_context_t *context_p); +void parser_module_parse_import_clause (parser_context_t *context_p); +void parser_module_set_default (parser_context_t *context_p); +bool parser_module_check_duplicate_import (parser_context_t *context_p, ecma_string_t *local_name_p); +bool parser_module_check_duplicate_export (parser_context_t *context_p, ecma_string_t *export_name_p); +void parser_module_append_export_name (parser_context_t *context_p); +void +parser_module_add_names_to_node (parser_context_t *context_p, ecma_string_t *imex_name_p, ecma_string_t *local_name_p); + +#endif /* JERRY_MODULE_SYSTEM */ + +/* + * @} + * + * \addtogroup jsparser_line_info_create Create line info data + * @{ + */ + +#if JERRY_LINE_INFO +void parser_line_info_free (parser_line_info_data_t *line_info_p); +void parser_line_info_append (parser_context_t *context_p, parser_line_counter_t line, parser_line_counter_t column); +uint8_t *parser_line_info_generate (parser_context_t *context_p); +#endif /* JERRY_LINE_INFO */ + +/** + * @} + * + * \addtogroup jsparser_parser Parser + * @{ + */ + +ecma_compiled_code_t *parser_parse_function (parser_context_t *context_p, uint32_t status_flags); +ecma_compiled_code_t *parser_parse_class_static_block (parser_context_t *context_p); +ecma_compiled_code_t *parser_parse_arrow_function (parser_context_t *context_p, uint32_t status_flags); +ecma_compiled_code_t *parser_parse_class_fields (parser_context_t *context_p); +void parser_set_function_name (parser_context_t *context_p, + uint16_t function_literal_index, + uint16_t name_index, + uint32_t status_flags); +void parser_compiled_code_set_function_name (parser_context_t *context_p, + ecma_compiled_code_t *bytecode_p, + uint16_t name_index, + uint32_t status_flags); +uint16_t parser_check_anonymous_function_declaration (parser_context_t *context_p); + +/* Error management. */ + +void parser_raise_error (parser_context_t *context_p, parser_error_msg_t error); + +#if JERRY_PARSER_DUMP_BYTE_CODE +void util_print_cbc (ecma_compiled_code_t *compiled_code_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_PARSER_INTERNAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-limits.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-limits.h new file mode 100644 index 00000000..0eb9b538 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-limits.h @@ -0,0 +1,134 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_PARSER_LIMITS_H +#define JS_PARSER_LIMITS_H + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_internals Internals + * @{ + */ + +/** + * Maximum identifier length accepted by the parser. + * Limit: LEXER_MAX_STRING_LENGTH. + */ +#ifndef PARSER_MAXIMUM_IDENT_LENGTH +#define PARSER_MAXIMUM_IDENT_LENGTH 255 +#endif /* !PARSER_MAXIMUM_IDENT_LENGTH */ + +/** + * Maximum string limit. + * Limit: 2147483647 / 65535. + */ +#if JERRY_CPOINTER_32_BIT +#define PARSER_MAXIMUM_STRING_LIMIT 2147483647 +#else /* !JERRY_CPOINTER_32_BIT */ +#define PARSER_MAXIMUM_STRING_LIMIT 65535 +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Maximum string length. + * Limit: PARSER_MAXIMUM_STRING_LIMIT. + */ +#ifndef PARSER_MAXIMUM_STRING_LENGTH +#define PARSER_MAXIMUM_STRING_LENGTH PARSER_MAXIMUM_STRING_LIMIT +#endif /* !PARSER_MAXIMUM_STRING_LENGTH */ + +/** + * Maximum number of registers. + * Limit: min: 256, max: min(PARSER_MAXIMUM_NUMBER_OF_LITERALS / 2, 16383) + */ +#ifndef PARSER_MAXIMUM_NUMBER_OF_REGISTERS +#define PARSER_MAXIMUM_NUMBER_OF_REGISTERS 256 +#endif /* !PARSER_MAXIMUM_NUMBER_OF_REGISTERS */ + +/** + * Maximum number of literals. + * Limit: 32767 - PARSER_MAXIMUM_NUMBER_OF_REGISTERS. Recommended: 32767 - PARSER_MAXIMUM_NUMBER_OF_REGISTERS. + */ +#ifndef PARSER_MAXIMUM_NUMBER_OF_LITERALS +#define PARSER_MAXIMUM_NUMBER_OF_LITERALS (32767 - PARSER_MAXIMUM_NUMBER_OF_REGISTERS) +#endif /* !PARSER_MAXIMUM_NUMBER_OF_LITERALS */ + +/** + * Maximum depth of scope stack. + * Limit: 32767. Recommended: 32767 + */ +#ifndef PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK +#define PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK 32767 +#endif /* !PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK */ + +/** + * Maximum code size. + * Limit: 16777215. Recommended: 65535, 16777215. + */ +#ifndef PARSER_MAXIMUM_CODE_SIZE +#define PARSER_MAXIMUM_CODE_SIZE (65535 << (JMEM_ALIGNMENT_LOG)) +#endif /* !PARSER_MAXIMUM_CODE_SIZE */ + +/** + * Maximum number of values pushed onto the stack by a function. + * Limit: 65500. Recommended: 1024. + */ +#ifndef PARSER_MAXIMUM_STACK_LIMIT +#define PARSER_MAXIMUM_STACK_LIMIT 1024 + +#endif /* !PARSER_MAXIMUM_STACK_LIMIT */ + +/* Checks. */ + +#if (PARSER_MAXIMUM_STRING_LENGTH < 1) || (PARSER_MAXIMUM_STRING_LENGTH > PARSER_MAXIMUM_STRING_LIMIT) +#error "Maximum string length is not within range." +#endif /* (PARSER_MAXIMUM_STRING_LENGTH < 1) || (PARSER_MAXIMUM_STRING_LENGTH > PARSER_MAXIMUM_STRING_LIMIT) */ + +#if (PARSER_MAXIMUM_IDENT_LENGTH < 1) || (PARSER_MAXIMUM_IDENT_LENGTH > PARSER_MAXIMUM_STRING_LENGTH) +#error "Maximum identifier length is not within range." +#endif /* (PARSER_MAXIMUM_IDENT_LENGTH < 1) || (PARSER_MAXIMUM_IDENT_LENGTH > PARSER_MAXIMUM_STRING_LENGTH) */ + +#if ((PARSER_MAXIMUM_NUMBER_OF_LITERALS < 1) \ + || (PARSER_MAXIMUM_NUMBER_OF_LITERALS + PARSER_MAXIMUM_NUMBER_OF_REGISTERS > 32767)) +#error "Maximum number of literals is not within range." +#endif /* ((PARSER_MAXIMUM_NUMBER_OF_LITERALS < 1) \ + || (PARSER_MAXIMUM_NUMBER_OF_LITERALS > 32767)) */ + +#if (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK < 1) || (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK > 32767) +#error "Maximum depth of scope stack is not within range." +#endif /* (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK < 1) || (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK > 32767) */ + +#if ((PARSER_MAXIMUM_NUMBER_OF_REGISTERS * 2) > PARSER_MAXIMUM_NUMBER_OF_LITERALS) +#error "Maximum number of registers is not within range." +#endif /* ((PARSER_MAXIMUM_NUMBER_OF_REGISTERS * 2) > PARSER_MAXIMUM_NUMBER_OF_LITERALS) */ + +#if (PARSER_MAXIMUM_CODE_SIZE < 4096) || (PARSER_MAXIMUM_CODE_SIZE > 16777215) +#error "Maximum code size is not within range." +#endif /* (PARSER_MAXIMUM_CODE_SIZE < 4096) || (PARSER_MAXIMUM_CODE_SIZE > 16777215) */ + +#if (PARSER_MAXIMUM_STACK_LIMIT < 16) || (PARSER_MAXIMUM_STACK_LIMIT > 65500) +#error "Maximum function stack usage is not within range." +#endif /* (PARSER_MAXIMUM_STACK_LIMIT < 16) || (PARSER_MAXIMUM_STACK_LIMIT > 65500) */ + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_PARSER_LIMITS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-line-info-create.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-line-info-create.cpp new file mode 100644 index 00000000..475d6b4f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-line-info-create.cpp @@ -0,0 +1,592 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-line-info.h" + +#include "js-parser-internal.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_line_info_create Create line info data + * @{ + */ + +#if JERRY_PARSER + +#if JERRY_LINE_INFO + +/* + * The line-info data structure uses two number encodings: + * + * Vlq (variable length quantity): + * Each byte has 7 bit data and the highest bit is set for continuation. + * The format is big endian. + * + * Small: + * One byte can encode signed values between 127 and -126. + * Two byte can encode signed values between 319 and -318. + * Large values are encoded with vlq with a prefix byte. + * + * The line-info data structure is a sequence of chunks: + * + * +------+--------------+------------+----------------+ + * | Line | StreamLength | StreamData | [ByteCodeSize] | + * +------+--------------+------------+----------------+ + * + * Line [Vlq encoding]: + * Specifies the start line of this chunk, relative to its previous value. + * The starting column is always ECMA_LINE_INFO_COLUMN_DEFAULT + * + * StreamLength [uint8_t]: + * Length of the StreamData in bytes minus ECMA_LINE_INFO_STREAM_SIZE_MIN. + * The 0 value represents the last chunk, which size is not specified + * (Can be less than ECMA_LINE_INFO_STREAM_SIZE_MIN). + * + * StreamData [sequence of bytes]: + * Sequence of the following items: + * + * +-----------+--------+--------+ + * | EndOffset | [Line] | Column | + * +-----------+--------+--------+ + * + * EndOffset [Small encoding]: + * Specifies the EndOffset in the byte code, relative to the previous EndOffset. + * The range of byte codes corresponding to the line/column position of this item + * is between the EndOffset of the previous item (inclusive) and the EndOffset + * of this item (exclusive). The last end offset of a stream is always 0, which + * represents an unterminated range. + * + * Line [Small encoding] [Optional]: + * If bit 1 of end offset is set, this specifies the line position of this item, + * relative to the previous line position, and the column position is set to + * ECMA_LINE_INFO_COLUMN_DEFAULT. + * + * Column [Small encoding]: + * Specifies the current column position relative to the previous column position. + * + * ByteCodeSize [Vlq encoding] [Optional]: + * If StreamLength is not 0, this specifies the byte code size of the whole range. + * This value can be used to skip the byte codes which line info is stored + * in this chunk. This information is not available for the last chunk. + */ + +/** + * Maximum number of bytes requires to encode a number. + */ +#define PARSER_LINE_INFO_BUFFER_MAX_SIZE 6 + +/** + * Stream generation ends after this size is reached, + * since there might be not enough place for the next item. + */ +#define PARSER_LINE_INFO_STREAM_SIZE_LIMIT \ + (ECMA_LINE_INFO_STREAM_SIZE_MIN + UINT8_MAX - ((2 * PARSER_LINE_INFO_BUFFER_MAX_SIZE) + 1)) + +/** + * Page size of line info pages excluding the first one. + */ +#define PARSER_LINE_INFO_PAGE_SIZE (sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE) + +/** + * Page size of the first line info page. + */ +#define PARSER_LINE_INFO_FIRST_PAGE_SIZE (sizeof (parser_line_info_data_t) + PARSER_LINE_INFO_PAGE_SIZE) + +/** + * Get memory data of the first page. + */ +#define PARSER_LINE_INFO_GET_FIRST_PAGE(line_info_p) (((parser_mem_page_t *) ((line_info_p) + 1))) + +/** + * Free line info temporary data collected during parsing. + */ +void +parser_line_info_free (parser_line_info_data_t *line_info_p) +{ + if (line_info_p == NULL) + { + return; + } + + parser_mem_page_t *current_page_p = PARSER_LINE_INFO_GET_FIRST_PAGE (line_info_p)->next_p; + parser_free (line_info_p, PARSER_LINE_INFO_FIRST_PAGE_SIZE); + + while (current_page_p != NULL) + { + parser_mem_page_t *next_p = current_page_p->next_p; + + parser_free (current_page_p, PARSER_LINE_INFO_PAGE_SIZE); + current_page_p = next_p; + } +} /* parser_line_info_free */ + +/** + * Encodes an uint32_t number into a buffer. Numbers expected to be larger values. + * + * @return the number of bytes written to the buffer + */ +static uint32_t +parser_line_info_encode_vlq (uint8_t *buffer_p, /**< target buffer */ + uint32_t value) /**< encoded value */ +{ + if (value <= ECMA_LINE_INFO_VLQ_MASK) + { + *buffer_p = (uint8_t) value; + return 1; + } + + uint32_t length = 0; + uint32_t current_value = value; + + do + { + current_value >>= ECMA_LINE_INFO_VLQ_SHIFT; + length++; + } while (current_value > 0); + + buffer_p += length; + + do + { + *(--buffer_p) = (uint8_t) (value | ECMA_LINE_INFO_VLQ_CONTINUE); + value >>= ECMA_LINE_INFO_VLQ_SHIFT; + } while (value > 0); + + buffer_p[length - 1] &= ECMA_LINE_INFO_VLQ_MASK; + return length; +} /* parser_line_info_encode_vlq */ + +/** + * Encodes an uint32_t number into a buffer. Numbers expected to be smaller values. + * + * @return the number of bytes written to the buffer + */ +static uint32_t +parser_line_info_encode_small (uint8_t *buffer_p, /**< target buffer */ + uint32_t value) /**< encoded value */ +{ + if (JERRY_LIKELY (value < ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN)) + { + buffer_p[0] = (uint8_t) value; + return 1; + } + + if (JERRY_LIKELY (value < ECMA_LINE_INFO_ENCODE_VLQ_MIN)) + { + buffer_p[0] = ECMA_LINE_INFO_ENCODE_TWO_BYTE; + buffer_p[1] = (uint8_t) (value - ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN); + return 2; + } + + *buffer_p++ = ECMA_LINE_INFO_ENCODE_VLQ; + return parser_line_info_encode_vlq (buffer_p, value - ECMA_LINE_INFO_ENCODE_VLQ_MIN) + 1; +} /* parser_line_info_encode_small */ + +/** + * Encodes the difference between two values. + * + * @return encoded difference + */ +static inline uint32_t +parser_line_info_difference_get (uint32_t current_value, /**< current value */ + uint32_t prev_value) /**< previous value */ +{ + uint32_t result = current_value - prev_value - 1; + + if (result <= (UINT32_MAX >> 1)) + { + return (result << 1) | ECMA_LINE_INFO_INCREASE; + } + + return ((UINT32_MAX - result) << 1) | ECMA_LINE_INFO_DECREASE; +} /* parser_line_info_difference_get */ + +/** + * Appends a value at the end of the line info stream. + */ +static void +parser_line_info_append_number (parser_context_t *context_p, /**< context */ + uint32_t value) /**< value to be encoded */ +{ + parser_line_info_data_t *line_info_p = context_p->line_info_p; + uint8_t buffer[PARSER_LINE_INFO_BUFFER_MAX_SIZE]; + + JERRY_ASSERT (line_info_p != NULL); + + uint32_t length = parser_line_info_encode_vlq (buffer, value); + uint8_t offset = line_info_p->last_page_p->bytes[0]; + + if (offset + length <= PARSER_STACK_PAGE_SIZE) + { + memcpy (line_info_p->last_page_p->bytes + offset, buffer, length); + + line_info_p->last_page_p->bytes[0] = (uint8_t) (length + offset); + return; + } + + parser_mem_page_t *new_page_p; + new_page_p = (parser_mem_page_t *) parser_malloc (context_p, PARSER_LINE_INFO_PAGE_SIZE); + + new_page_p->next_p = NULL; + + line_info_p->last_page_p->next_p = new_page_p; + line_info_p->last_page_p = new_page_p; + + new_page_p->bytes[0] = (uint8_t) (length + 1); + memcpy (new_page_p->bytes + 1, buffer, length); +} /* parser_line_info_append_number */ + +/** + * Updates the current line information data. + */ +void +parser_line_info_append (parser_context_t *context_p, /**< context */ + parser_line_counter_t line, /**< line */ + parser_line_counter_t column) /**< column */ +{ + parser_line_info_data_t *line_info_p = context_p->line_info_p; + uint32_t value; + + if (line_info_p != NULL) + { + if (line_info_p->byte_code_position == context_p->byte_code_size + || (line_info_p->line == line && line_info_p->column == column)) + { + return; + } + + /* Sets ECMA_LINE_INFO_HAS_LINE bit. */ + value = (uint32_t) (line != line_info_p->line); + } + else + { + line_info_p = (parser_line_info_data_t *) parser_malloc (context_p, PARSER_LINE_INFO_FIRST_PAGE_SIZE); + context_p->line_info_p = line_info_p; + + parser_mem_page_t *page_p = PARSER_LINE_INFO_GET_FIRST_PAGE (line_info_p); + page_p->next_p = NULL; + page_p->bytes[0] = 1; + + line_info_p->last_page_p = page_p; + line_info_p->byte_code_position = 0; + line_info_p->line = 1; + line_info_p->column = 1; + + /* Sets ECMA_LINE_INFO_HAS_LINE bit. */ + value = (uint32_t) (line != 1); + } + + value |= ((context_p->byte_code_size - line_info_p->byte_code_position) << 1); + + parser_line_info_append_number (context_p, value); + line_info_p->byte_code_position = context_p->byte_code_size; + + if (value & ECMA_LINE_INFO_HAS_LINE) + { + value = parser_line_info_difference_get (line, line_info_p->line); + parser_line_info_append_number (context_p, value); + line_info_p->line = line; + } + + value = parser_line_info_difference_get (column, line_info_p->column); + parser_line_info_append_number (context_p, value); + line_info_p->column = column; +} /* parser_line_info_append */ + +/** + * Line info iterator structure + */ +typedef struct +{ + parser_mem_page_t *current_page_p; /**< current page */ + uint32_t offset; /**< current offset */ +} parser_line_info_iterator_t; + +/** + * Decodes the next value from the iterator stream + */ +static uint32_t +parser_line_info_iterator_get (parser_line_info_iterator_t *iterator_p) /**< iterator */ +{ + uint8_t *source_p = iterator_p->current_page_p->bytes + iterator_p->offset; + uint32_t result = ecma_line_info_decode_vlq (&source_p); + + iterator_p->offset = (uint32_t) (source_p - iterator_p->current_page_p->bytes); + + JERRY_ASSERT (iterator_p->offset <= iterator_p->current_page_p->bytes[0]); + + if (iterator_p->offset < iterator_p->current_page_p->bytes[0]) + { + return result; + } + + iterator_p->current_page_p = iterator_p->current_page_p->next_p; + iterator_p->offset = 1; + return result; +} /* parser_line_info_iterator_get */ + +/** + * Generate line info data + * + * @return generated line info data + */ +uint8_t * +parser_line_info_generate (parser_context_t *context_p) /**< context */ +{ + parser_line_info_iterator_t iterator; + uint8_t *line_info_p = NULL; + uint8_t *dst_p = NULL; + uint32_t total_length = 0; + uint32_t total_length_size = 0; + + while (true) + { + /* The following code runs twice: first the size of the data, + * is computed and the data is generated during the second run. + * Note: line_info_p is NULL during the first run. */ + parser_mem_page_t *iterator_byte_code_page_p = context_p->byte_code.first_p; + uint32_t iterator_byte_code_page_offset = 0; + uint32_t iterator_byte_code_base = 0; + uint32_t iterator_last_byte_code_offset = UINT32_MAX; + uint32_t iterator_prev_line = 0; + uint32_t iterator_prev_column = 0; + uint32_t iterator_line = 1; + uint32_t iterator_column = 1; + uint8_t block_buffer[PARSER_LINE_INFO_BUFFER_MAX_SIZE]; + uint8_t line_column_buffer[PARSER_LINE_INFO_BUFFER_MAX_SIZE * 2]; + uint8_t *block_size_p = NULL; + uint32_t block_byte_code_offset = 0; + uint32_t block_prev_line = 1; + uint32_t stream_byte_code_offset = 0; + uint32_t stream_current_line = 1; + uint32_t stream_current_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + uint32_t stream_prev_line = 1; + uint32_t stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + uint32_t stream_size = 0; + uint32_t stream_value_count = 0; + uint32_t value; + + iterator.current_page_p = PARSER_LINE_INFO_GET_FIRST_PAGE (context_p->line_info_p); + iterator.offset = 1; + + do + { + /* Decode line information generated during parsing. */ + value = parser_line_info_iterator_get (&iterator); + iterator_byte_code_page_offset += (value >> 1); + + if (value & 0x1) + { + value = parser_line_info_iterator_get (&iterator); + JERRY_ASSERT (value != ((0 << 1) | ECMA_LINE_INFO_DECREASE)); + iterator_line = ecma_line_info_difference_update (iterator_line, value); + } + + value = parser_line_info_iterator_get (&iterator); + iterator_column = ecma_line_info_difference_update (iterator_column, value); + + while (iterator_byte_code_page_offset >= PARSER_CBC_STREAM_PAGE_SIZE) + { + uint8_t relative_offset = iterator_byte_code_page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1]; + iterator_byte_code_base += relative_offset & CBC_LOWER_SEVEN_BIT_MASK; + iterator_byte_code_page_offset -= PARSER_CBC_STREAM_PAGE_SIZE; + iterator_byte_code_page_p = iterator_byte_code_page_p->next_p; + } + + uint32_t iterator_byte_code_offset = iterator_byte_code_base; + + if (iterator_byte_code_page_offset > 0) + { + uint8_t relative_offset = iterator_byte_code_page_p->bytes[iterator_byte_code_page_offset - 1]; + iterator_byte_code_offset += relative_offset & CBC_LOWER_SEVEN_BIT_MASK; + } + + /* Skip those line/column pairs which byte code was discarded during post processing + * or does not change line/column (this is possible when multiple skips occures). */ + if (iterator_byte_code_offset == iterator_last_byte_code_offset + || (iterator_line == iterator_prev_line && iterator_column == iterator_prev_column)) + { + continue; + } + + iterator_prev_line = iterator_line; + iterator_prev_column = iterator_column; + iterator_last_byte_code_offset = iterator_byte_code_offset; + + if (block_size_p != NULL) + { + /* Sets ECMA_LINE_INFO_HAS_LINE bit. */ + value = (((iterator_byte_code_offset - stream_byte_code_offset) << 1) + | (uint32_t) (stream_prev_line != stream_current_line)); + + uint32_t line_column_size = 0; + uint32_t offset_size = parser_line_info_encode_small (block_buffer, value); + stream_byte_code_offset = iterator_byte_code_offset; + + if (value & ECMA_LINE_INFO_HAS_LINE) + { + value = parser_line_info_difference_get (stream_current_line, stream_prev_line); + line_column_size = parser_line_info_encode_small (line_column_buffer, value); + stream_prev_line = stream_current_line; + stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + } + + value = parser_line_info_difference_get (stream_current_column, stream_prev_column); + line_column_size += parser_line_info_encode_small (line_column_buffer + line_column_size, value); + + stream_prev_column = stream_current_column; + stream_current_line = iterator_line; + stream_current_column = iterator_column; + + stream_value_count++; + + if (stream_value_count < ECMA_LINE_INFO_STREAM_VALUE_COUNT_MAX + && (stream_size + offset_size + line_column_size <= PARSER_LINE_INFO_STREAM_SIZE_LIMIT)) + { + stream_size += offset_size + line_column_size; + + if (line_info_p != NULL) + { + memcpy (dst_p, block_buffer, offset_size); + dst_p += offset_size; + memcpy (dst_p, line_column_buffer, line_column_size); + dst_p += line_column_size; + } + continue; + } + + /* Finalize the current chunk. The size of EndOffset is always 1. */ + stream_size += 1 + line_column_size; + + JERRY_ASSERT (stream_size > ECMA_LINE_INFO_STREAM_SIZE_MIN + && (stream_size - ECMA_LINE_INFO_STREAM_SIZE_MIN) <= UINT8_MAX); + + if (line_info_p != NULL) + { + *block_size_p = (uint8_t) (stream_size - ECMA_LINE_INFO_STREAM_SIZE_MIN); + /* Set EndOffset to 0 and copy the has_line bit. */ + *dst_p++ = (uint8_t) (block_buffer[0] & ECMA_LINE_INFO_HAS_LINE); + memcpy (dst_p, line_column_buffer, line_column_size); + dst_p += line_column_size; + } + else + { + total_length += stream_size; + dst_p = block_buffer; + } + + uint32_t byte_code_diff = iterator_last_byte_code_offset - block_byte_code_offset; + dst_p += parser_line_info_encode_vlq (dst_p, byte_code_diff); + block_byte_code_offset = iterator_last_byte_code_offset; + + if (line_info_p == NULL) + { + total_length += (uint32_t) (dst_p - block_buffer); + } + } + + /* Start a new chunk. */ + if (line_info_p == NULL) + { + dst_p = block_buffer; + } + + value = parser_line_info_difference_get (iterator_line, block_prev_line); + + dst_p += parser_line_info_encode_vlq (dst_p, value); + block_size_p = dst_p; + dst_p++; + + if (line_info_p == NULL) + { + total_length += (uint32_t) (dst_p - block_buffer); + } + + block_prev_line = iterator_line; + stream_current_line = iterator_line; + stream_current_column = iterator_column; + stream_prev_line = iterator_line; + stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + stream_size = 0; + stream_value_count = 0; + } while (iterator.current_page_p != NULL); + + value = (stream_prev_line != stream_current_line); + + /* Finalize the last stream */ + if (line_info_p == NULL) + { + dst_p = line_column_buffer; + total_length += stream_size + 1; + } + else + { + *block_size_p = 0; + /* Small encoded value of has_line bit. */ + *dst_p++ = (uint8_t) value; + } + + if (value) + { + value = parser_line_info_difference_get (stream_current_line, stream_prev_line); + dst_p += parser_line_info_encode_small (dst_p, value); + stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + } + + value = parser_line_info_difference_get (stream_current_column, stream_prev_column); + dst_p += parser_line_info_encode_small (dst_p, value); + + if (line_info_p == NULL) + { + total_length += (uint32_t) (dst_p - line_column_buffer); + } + + if (line_info_p != NULL) + { + break; + } + + total_length_size = parser_line_info_encode_vlq (block_buffer, total_length); + + /* TODO: Support allocation fail. */ + line_info_p = (uint8_t *) jmem_heap_alloc_block (total_length + total_length_size); + dst_p = line_info_p + parser_line_info_encode_vlq (line_info_p, total_length); + } + + JERRY_ASSERT (line_info_p + total_length_size + total_length == dst_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + ecma_line_info_dump (line_info_p); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + return line_info_p; +} /* parser_line_info_generate */ + +#endif /* JERRY_LINE_INFO */ + +#endif /* JERRY_PARSER */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-mem.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-mem.cpp new file mode 100644 index 00000000..4c8d2b62 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-mem.cpp @@ -0,0 +1,729 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" + +#if JERRY_PARSER + +/** \addtogroup mem Memory allocation + * @{ + * + * \addtogroup mem_parser Parser memory manager + * @{ + */ + +/**********************************************************************/ +/* Memory allocation */ +/**********************************************************************/ + +/** + * Allocate memory. + * + * @return allocated memory. + */ +void * +parser_malloc (parser_context_t *context_p, /**< context */ + size_t size) /**< size of the memory block */ +{ + void *result; + + JERRY_ASSERT (size > 0); + result = jmem_heap_alloc_block_null_on_error (size); + + if (result == NULL) + { + parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY); + } + return result; +} /* parser_malloc */ + +/** + * Free memory allocated by parser_malloc. + */ +void +parser_free (void *ptr, /**< pointer to free */ + size_t size) /**< size of the memory block */ +{ + jmem_heap_free_block (ptr, size); +} /* parser_free */ + +/** + * Allocate local memory for short term use. + * + * @return allocated memory. + */ +void * +parser_malloc_local (parser_context_t *context_p, /**< context */ + size_t size) /**< size of the memory */ +{ + void *result; + + JERRY_ASSERT (size > 0); + result = jmem_heap_alloc_block (size); + if (result == 0) + { + parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY); + } + return result; +} /* parser_malloc_local */ + +/** + * Free memory allocated by parser_malloc_local. + */ +void +parser_free_local (void *ptr, /**< pointer to free */ + size_t size) /**< size of the memory */ +{ + jmem_heap_free_block (ptr, size); +} /* parser_free_local */ + +/** + * Free the dynamically allocated buffer stored in the context + */ +void +parser_free_allocated_buffer (parser_context_t *context_p) /**< context */ +{ + if (context_p->u.allocated_buffer_p != NULL) + { + parser_free_local (context_p->u.allocated_buffer_p, context_p->allocated_buffer_size); + context_p->u.allocated_buffer_p = NULL; + } +} /* parser_free_allocated_buffer */ + +/**********************************************************************/ +/* Parser data management functions */ +/**********************************************************************/ + +/** + * Initialize parse data. + */ +static void +parser_data_init (parser_mem_data_t *data_p, /**< memory manager */ + uint32_t page_size) /**< size of each page */ +{ + data_p->first_p = NULL; + data_p->last_p = NULL; + data_p->last_position = page_size; +} /* parser_data_init */ + +/** + * Free parse data. + */ +static void +parser_data_free (parser_mem_data_t *data_p, /**< memory manager */ + uint32_t page_size) /**< size of each page */ +{ + parser_mem_page_t *page_p = data_p->first_p; + + while (page_p != NULL) + { + parser_mem_page_t *next_p = page_p->next_p; + + parser_free (page_p, page_size); + page_p = next_p; + } +} /* parser_data_free */ + +/**********************************************************************/ +/* Parser byte stream management functions */ +/**********************************************************************/ + +/** + * Initialize byte stream. + */ +void +parser_cbc_stream_init (parser_mem_data_t *data_p) /**< memory manager */ +{ + parser_data_init (data_p, PARSER_CBC_STREAM_PAGE_SIZE); +} /* parser_cbc_stream_init */ + +/** + * Free byte stream. + */ +void +parser_cbc_stream_free (parser_mem_data_t *data_p) /**< memory manager */ +{ + parser_data_free (data_p, sizeof (parser_mem_page_t *) + PARSER_CBC_STREAM_PAGE_SIZE); +} /* parser_cbc_stream_free */ + +/** + * Appends a byte at the end of the byte stream. + */ +void +parser_cbc_stream_alloc_page (parser_context_t *context_p, /**< context */ + parser_mem_data_t *data_p) /**< memory manager */ +{ + size_t size = sizeof (parser_mem_page_t *) + PARSER_CBC_STREAM_PAGE_SIZE; + parser_mem_page_t *page_p = (parser_mem_page_t *) parser_malloc (context_p, size); + + page_p->next_p = NULL; + data_p->last_position = 0; + + if (data_p->last_p != NULL) + { + data_p->last_p->next_p = page_p; + } + else + { + data_p->first_p = page_p; + } + data_p->last_p = page_p; +} /* parser_cbc_stream_alloc_page */ + +/**********************************************************************/ +/* Parser list management functions */ +/**********************************************************************/ + +/** + * Initialize parser list. + */ +void +parser_list_init (parser_list_t *list_p, /**< parser list */ + uint32_t item_size, /**< size for each page */ + uint32_t item_count) /**< number of items on each page */ +{ + /* Align to pointer size. */ + item_size = (uint32_t) (((item_size) + sizeof (void *) - 1) & ~(sizeof (void *) - 1)); + parser_data_init (&list_p->data, item_size * item_count); + list_p->page_size = item_size * item_count; + list_p->item_size = item_size; + list_p->item_count = item_count; +} /* parser_list_init */ + +/** + * Free parser list. + */ +void +parser_list_free (parser_list_t *list_p) /**< parser list */ +{ + parser_data_free (&list_p->data, (uint32_t) (sizeof (parser_mem_page_t *) + list_p->page_size)); +} /* parser_list_free */ + +/** + * Reset parser list. + */ +void +parser_list_reset (parser_list_t *list_p) /**< parser list */ +{ + parser_data_init (&list_p->data, list_p->page_size); +} /* parser_list_reset */ + +/** + * Allocate space for the next item. + * + * @return pointer to the appended item. + */ +void * +parser_list_append (parser_context_t *context_p, /**< context */ + parser_list_t *list_p) /**< parser list */ +{ + parser_mem_page_t *page_p = list_p->data.last_p; + void *result; + + if (list_p->data.last_position + list_p->item_size > list_p->page_size) + { + size_t size = sizeof (parser_mem_page_t *) + list_p->page_size; + + page_p = (parser_mem_page_t *) parser_malloc (context_p, size); + + page_p->next_p = NULL; + list_p->data.last_position = 0; + + if (list_p->data.last_p != NULL) + { + list_p->data.last_p->next_p = page_p; + } + else + { + list_p->data.first_p = page_p; + } + list_p->data.last_p = page_p; + } + + result = page_p->bytes + list_p->data.last_position; + list_p->data.last_position += list_p->item_size; + return result; +} /* parser_list_append */ + +/** + * Return the nth item of the list. + * + * @return pointer to the item. + */ +void * +parser_list_get (parser_list_t *list_p, /**< parser list */ + size_t index) /**< item index */ +{ + size_t item_count = list_p->item_count; + parser_mem_page_t *page_p = list_p->data.first_p; + + while (index >= item_count) + { + JERRY_ASSERT (page_p != NULL); + page_p = page_p->next_p; + index -= item_count; + } + + JERRY_ASSERT (page_p != NULL); + JERRY_ASSERT (page_p != list_p->data.last_p || (index * list_p->item_size < list_p->data.last_position)); + return page_p->bytes + (index * list_p->item_size); +} /* parser_list_get */ + +/** + * Initialize a parser list iterator. + */ +void +parser_list_iterator_init (parser_list_t *list_p, /**< parser list */ + parser_list_iterator_t *iterator_p) /**< iterator */ +{ + iterator_p->list_p = list_p; + iterator_p->current_p = list_p->data.first_p; + iterator_p->current_position = 0; +} /* parser_list_iterator_init */ + +/** + * Next iterator step. + * + * @return the address of the current item, or NULL at the end. + */ +void * +parser_list_iterator_next (parser_list_iterator_t *iterator_p) /**< iterator */ +{ + void *result; + + if (iterator_p->current_p == NULL) + { + return NULL; + } + + result = iterator_p->current_p->bytes + iterator_p->current_position; + iterator_p->current_position += iterator_p->list_p->item_size; + + if (iterator_p->current_p->next_p == NULL) + { + if (iterator_p->current_position >= iterator_p->list_p->data.last_position) + { + iterator_p->current_p = NULL; + iterator_p->current_position = 0; + } + } + else if (iterator_p->current_position >= iterator_p->list_p->page_size) + { + iterator_p->current_p = iterator_p->current_p->next_p; + iterator_p->current_position = 0; + } + return result; +} /* parser_list_iterator_next */ + +/**********************************************************************/ +/* Parser stack management functions */ +/**********************************************************************/ + +/* Stack is a reversed storage. */ + +/** + * Initialize parser stack. + */ +void +parser_stack_init (parser_context_t *context_p) /**< context */ +{ + parser_data_init (&context_p->stack, PARSER_STACK_PAGE_SIZE); + context_p->free_page_p = NULL; +} /* parser_stack_init */ + +/** + * Free parser stack. + */ +void +parser_stack_free (parser_context_t *context_p) /**< context */ +{ + parser_data_free (&context_p->stack, sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); + + if (context_p->free_page_p != NULL) + { + parser_free (context_p->free_page_p, sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); + } +} /* parser_stack_free */ + +/** + * Pushes an uint8_t value onto the stack. + */ +void +parser_stack_push_uint8 (parser_context_t *context_p, /**< context */ + uint8_t uint8_value) /**< value pushed onto the stack */ +{ + parser_mem_page_t *page_p = context_p->stack.first_p; + + /* This assert might trigger false positive valgrind errors, when + * parser_stack_push() pushes not fully initialized structures. + * More precisely when the last byte of the structure is uninitialized. */ + JERRY_ASSERT (page_p == NULL || context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); + + if (context_p->stack.last_position >= PARSER_STACK_PAGE_SIZE) + { + if (context_p->free_page_p != NULL) + { + page_p = context_p->free_page_p; + context_p->free_page_p = NULL; + } + else + { + size_t size = sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE; + page_p = (parser_mem_page_t *) parser_malloc (context_p, size); + } + + page_p->next_p = context_p->stack.first_p; + context_p->stack.last_position = 0; + context_p->stack.first_p = page_p; + } + + page_p->bytes[context_p->stack.last_position++] = uint8_value; + context_p->stack_top_uint8 = uint8_value; +} /* parser_stack_push_uint8 */ + +/** + * Pops the last uint8_t value from the stack. + */ +void +parser_stack_pop_uint8 (parser_context_t *context_p) /**< context */ +{ + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); + + context_p->stack.last_position--; + + if (context_p->stack.last_position == 0) + { + context_p->stack.first_p = page_p->next_p; + context_p->stack.last_position = PARSER_STACK_PAGE_SIZE; + + if (context_p->free_page_p == NULL) + { + context_p->free_page_p = page_p; + } + else + { + parser_free (page_p, sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); + } + + page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL); + } + + context_p->stack_top_uint8 = page_p->bytes[context_p->stack.last_position - 1]; +} /* parser_stack_pop_uint8 */ + +/** + * Change last byte of the stack. + */ +void +parser_stack_change_last_uint8 (parser_context_t *context_p, /**< context */ + uint8_t new_value) /**< new value */ +{ + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); + + page_p->bytes[context_p->stack.last_position - 1] = new_value; + context_p->stack_top_uint8 = new_value; +} /* parser_stack_change_last_uint8 */ + +/** + * Get the uint8 value before the top of the stack. + * + * Pointer to the uint8 value + */ +uint8_t * +parser_stack_get_prev_uint8 (parser_context_t *context_p) /**< context */ +{ + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL && (context_p->stack.last_position >= 2 || page_p->next_p != NULL)); + + if (context_p->stack.last_position >= 2) + { + return page_p->bytes + (context_p->stack.last_position - 2); + } + + return page_p->next_p->bytes + (PARSER_STACK_PAGE_SIZE - 1); +} /* parser_stack_get_prev_uint8 */ + +/** + * Pushes an uint16_t value onto the stack. + */ +void +parser_stack_push_uint16 (parser_context_t *context_p, /**< context */ + uint16_t uint16_value) /**< value pushed onto the stack */ +{ + if (context_p->stack.last_position + 2 <= PARSER_STACK_PAGE_SIZE) + { + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); + + page_p->bytes[context_p->stack.last_position++] = (uint8_t) (uint16_value >> 8); + page_p->bytes[context_p->stack.last_position++] = (uint8_t) uint16_value; + context_p->stack_top_uint8 = (uint8_t) uint16_value; + } + else + { + parser_stack_push_uint8 (context_p, (uint8_t) (uint16_value >> 8)); + parser_stack_push_uint8 (context_p, (uint8_t) uint16_value); + } +} /* parser_stack_push_uint16 */ + +/** + * Pops the last uint16_t value from the stack. + * + * @return the value popped from the stack. + */ +uint16_t +parser_stack_pop_uint16 (parser_context_t *context_p) /**< context */ +{ + uint32_t value = context_p->stack_top_uint8; + + if (context_p->stack.last_position >= 3) + { + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); + + value |= ((uint32_t) page_p->bytes[context_p->stack.last_position - 2]) << 8; + context_p->stack_top_uint8 = page_p->bytes[context_p->stack.last_position - 3]; + context_p->stack.last_position -= 2; + } + else + { + parser_stack_pop_uint8 (context_p); + value |= ((uint32_t) context_p->stack_top_uint8) << 8; + parser_stack_pop_uint8 (context_p); + } + return (uint16_t) value; +} /* parser_stack_pop_uint16 */ + +/** + * Pushes a data onto the stack. + */ +void +parser_stack_push (parser_context_t *context_p, /**< context */ + const void *data_p, /**< data pushed onto the stack */ + uint32_t length) /**< length of the data */ +{ + uint32_t fragment_length = PARSER_STACK_PAGE_SIZE - context_p->stack.last_position; + const uint8_t *bytes_p = (const uint8_t *) data_p; + parser_mem_page_t *page_p; + + JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); + + context_p->stack_top_uint8 = bytes_p[length - 1]; + + if (fragment_length > 0) + { + /* Fill the remaining bytes. */ + if (fragment_length > length) + { + fragment_length = length; + } + + memcpy (context_p->stack.first_p->bytes + context_p->stack.last_position, bytes_p, fragment_length); + + if (fragment_length == length) + { + context_p->stack.last_position += length; + return; + } + + bytes_p += fragment_length; + length -= fragment_length; + } + + if (context_p->free_page_p != NULL) + { + page_p = context_p->free_page_p; + context_p->free_page_p = NULL; + } + else + { + size_t size = sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE; + + page_p = (parser_mem_page_t *) parser_malloc (context_p, size); + } + + page_p->next_p = context_p->stack.first_p; + + context_p->stack.first_p = page_p; + + memcpy (page_p->bytes, bytes_p, length); + context_p->stack.last_position = length; +} /* parser_stack_push */ + +/** + * Pop bytes from the top of the stack. + */ +void +parser_stack_pop (parser_context_t *context_p, /**< context */ + void *data_p, /**< destination buffer, can be NULL */ + uint32_t length) /**< length of the data */ +{ + uint8_t *bytes_p = (uint8_t *) data_p; + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); + + if (context_p->stack.last_position > length) + { + context_p->stack.last_position -= length; + context_p->stack_top_uint8 = page_p->bytes[context_p->stack.last_position - 1]; + + if (bytes_p != NULL) + { + memcpy (bytes_p, context_p->stack.first_p->bytes + context_p->stack.last_position, length); + } + return; + } + + JERRY_ASSERT (page_p->next_p != NULL); + + length -= context_p->stack.last_position; + + if (bytes_p != NULL) + { + memcpy (bytes_p + length, page_p->bytes, context_p->stack.last_position); + } + + context_p->stack.first_p = page_p->next_p; + context_p->stack.last_position = PARSER_STACK_PAGE_SIZE - length; + context_p->stack_top_uint8 = page_p->next_p->bytes[context_p->stack.last_position - 1]; + + if (bytes_p != NULL && length > 0) + { + memcpy (bytes_p, page_p->next_p->bytes + context_p->stack.last_position, length); + } + + JERRY_ASSERT (context_p->stack.last_position > 0); + + if (context_p->free_page_p == NULL) + { + context_p->free_page_p = page_p; + } + else + { + parser_free (page_p, sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); + } +} /* parser_stack_pop */ + +/** + * Initialize stack iterator. + */ +void +parser_stack_iterator_init (parser_context_t *context_p, /**< context */ + parser_stack_iterator_t *iterator) /**< iterator */ +{ + iterator->current_p = context_p->stack.first_p; + iterator->current_position = context_p->stack.last_position; +} /* parser_stack_iterator_init */ + +/** + * Read the next byte from the stack. + * + * @return byte + */ +uint8_t +parser_stack_iterator_read_uint8 (parser_stack_iterator_t *iterator) /**< iterator */ +{ + JERRY_ASSERT (iterator->current_position > 0 && iterator->current_position <= PARSER_STACK_PAGE_SIZE); + return iterator->current_p->bytes[iterator->current_position - 1]; +} /* parser_stack_iterator_read_uint8 */ + +/** + * Skip the next n bytes of the stack. + */ +void +parser_stack_iterator_skip (parser_stack_iterator_t *iterator, /**< iterator */ + size_t length) /**< number of skipped bytes */ +{ + JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); + + if (length < iterator->current_position) + { + iterator->current_position -= length; + } + else + { + iterator->current_position = PARSER_STACK_PAGE_SIZE - (length - iterator->current_position); + iterator->current_p = iterator->current_p->next_p; + } +} /* parser_stack_iterator_skip */ + +/** + * Read bytes from the stack. + */ +void +parser_stack_iterator_read (parser_stack_iterator_t *iterator, /**< iterator */ + void *data_p, /**< destination buffer */ + size_t length) /**< length of the data */ +{ + uint8_t *bytes_p = (uint8_t *) data_p; + + JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); + + if (length <= iterator->current_position) + { + memcpy (bytes_p, iterator->current_p->bytes + iterator->current_position - length, length); + } + else + { + JERRY_ASSERT (iterator->current_p->next_p != NULL); + + length -= iterator->current_position; + memcpy (bytes_p + length, iterator->current_p->bytes, iterator->current_position); + memcpy (bytes_p, iterator->current_p->next_p->bytes + PARSER_STACK_PAGE_SIZE - length, length); + } +} /* parser_stack_iterator_read */ + +/** + * Write bytes onto the stack. + */ +void +parser_stack_iterator_write (parser_stack_iterator_t *iterator, /**< iterator */ + const void *data_p, /**< destination buffer */ + size_t length) /**< length of the data */ +{ + const uint8_t *bytes_p = (const uint8_t *) data_p; + + JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); + + if (length <= iterator->current_position) + { + memcpy (iterator->current_p->bytes + iterator->current_position - length, bytes_p, length); + } + else + { + JERRY_ASSERT (iterator->current_p->next_p != NULL); + + length -= iterator->current_position; + memcpy (iterator->current_p->bytes, bytes_p + length, iterator->current_position); + memcpy (iterator->current_p->next_p->bytes + PARSER_STACK_PAGE_SIZE - length, bytes_p, length); + } +} /* parser_stack_iterator_write */ + +/** + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-module.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-module.cpp new file mode 100644 index 00000000..465f8122 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-module.cpp @@ -0,0 +1,529 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" + +#if JERRY_MODULE_SYSTEM +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-module.h" + +#include "jcontext.h" + +/** + * Description of "*default*" literal string. + */ +const lexer_lit_location_t lexer_default_literal = { (const uint8_t *) "*default*", + 9, + LEXER_IDENT_LITERAL, + LEXER_LIT_LOCATION_IS_ASCII }; + +/** + * Check for duplicated imported binding names. + * + * @return true - if the given name is a duplicate + * false - otherwise + */ +bool +parser_module_check_duplicate_import (parser_context_t *context_p, /**< parser context */ + ecma_string_t *local_name_p) /**< newly imported name */ +{ + ecma_module_names_t *module_names_p = context_p->module_names_p; + + while (module_names_p != NULL) + { + if (ecma_compare_ecma_strings (module_names_p->local_name_p, local_name_p)) + { + return true; + } + + module_names_p = module_names_p->next_p; + } + + ecma_module_node_t *module_node_p = JERRY_CONTEXT (module_current_p)->imports_p; + + while (module_node_p != NULL) + { + module_names_p = module_node_p->module_names_p; + + while (module_names_p != NULL) + { + if (ecma_compare_ecma_strings (module_names_p->local_name_p, local_name_p)) + { + return true; + } + + module_names_p = module_names_p->next_p; + } + + module_node_p = module_node_p->next_p; + } + + return false; +} /* parser_module_check_duplicate_import */ + +/** + * Append an identifier to the exported bindings. + */ +void +parser_module_append_export_name (parser_context_t *context_p) /**< parser context */ +{ + if (!(context_p->status_flags & PARSER_MODULE_STORE_IDENT)) + { + return; + } + + context_p->module_identifier_lit_p = context_p->lit_object.literal_p; + ecma_string_t *name_p = parser_new_ecma_string_from_literal (context_p->lit_object.literal_p); + + if (parser_module_check_duplicate_export (context_p, name_p)) + { + ecma_deref_ecma_string (name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER); + } + + parser_module_add_names_to_node (context_p, name_p, name_p); + ecma_deref_ecma_string (name_p); +} /* parser_module_append_export_name */ + +/** + * Check for duplicated exported bindings. + * @return - true - if the exported name is a duplicate + * false - otherwise + */ +bool +parser_module_check_duplicate_export (parser_context_t *context_p, /**< parser context */ + ecma_string_t *export_name_p) /**< exported identifier */ +{ + /* We have to check in the currently constructed node, as well as all of the already added nodes. */ + ecma_module_names_t *current_names_p = context_p->module_names_p; + + while (current_names_p != NULL) + { + if (ecma_compare_ecma_strings (current_names_p->imex_name_p, export_name_p)) + { + return true; + } + current_names_p = current_names_p->next_p; + } + + ecma_module_names_t *name_p = JERRY_CONTEXT (module_current_p)->local_exports_p; + + while (name_p != NULL) + { + if (ecma_compare_ecma_strings (name_p->imex_name_p, export_name_p)) + { + return true; + } + + name_p = name_p->next_p; + } + + ecma_module_node_t *export_node_p = JERRY_CONTEXT (module_current_p)->indirect_exports_p; + + while (export_node_p != NULL) + { + name_p = export_node_p->module_names_p; + + while (name_p != NULL) + { + if (ecma_compare_ecma_strings (name_p->imex_name_p, export_name_p)) + { + return true; + } + + name_p = name_p->next_p; + } + + export_node_p = export_node_p->next_p; + } + + /* Star exports don't have any names associated with them, so no need to check those. */ + return false; +} /* parser_module_check_duplicate_export */ + +/** + * Add module names to current module node. + */ +void +parser_module_add_names_to_node (parser_context_t *context_p, /**< parser context */ + ecma_string_t *imex_name_p, /**< import/export name */ + ecma_string_t *local_name_p) /**< local name */ +{ + ecma_module_names_t *new_name_p = (ecma_module_names_t *) parser_malloc (context_p, sizeof (ecma_module_names_t)); + + new_name_p->next_p = context_p->module_names_p; + context_p->module_names_p = new_name_p; + + JERRY_ASSERT (imex_name_p != NULL); + ecma_ref_ecma_string (imex_name_p); + new_name_p->imex_name_p = imex_name_p; + + JERRY_ASSERT (local_name_p != NULL); + ecma_ref_ecma_string (local_name_p); + new_name_p->local_name_p = local_name_p; +} /* parser_module_add_names_to_node */ + +/** + * Parse an ExportClause. + */ +void +parser_module_parse_export_clause (parser_context_t *context_p) /**< parser context */ +{ + bool has_module_specifier = false; + + if (context_p->source_p == context_p->next_scanner_info_p->source_p) + { + has_module_specifier = true; + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_EXPORT_MODULE_SPECIFIER); + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE); + lexer_next_token (context_p); + + while (true) + { + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + lexer_next_token (context_p); + break; + } + + /* 15.2.3.1 The referenced binding cannot be a reserved word. */ + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL + || context_p->token.keyword_type >= LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + ecma_string_t *export_name_p = NULL; + ecma_string_t *local_name_p = NULL; + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + + if (!has_module_specifier && !scanner_literal_exists (context_p, context_p->lit_object.index)) + { + parser_raise_error (context_p, PARSER_ERR_EXPORT_NOT_DEFINED); + } + + uint16_t local_name_index = context_p->lit_object.index; + uint16_t export_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS; + + lexer_next_token (context_p); + if (lexer_token_is_identifier (context_p, "as", 2)) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + + export_name_index = context_p->lit_object.index; + + lexer_next_token (context_p); + } + + local_name_p = parser_new_ecma_string_from_literal (PARSER_GET_LITERAL (local_name_index)); + + if (export_name_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + export_name_p = parser_new_ecma_string_from_literal (PARSER_GET_LITERAL (export_name_index)); + } + else + { + export_name_p = local_name_p; + ecma_ref_ecma_string (local_name_p); + } + + if (parser_module_check_duplicate_export (context_p, export_name_p)) + { + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (export_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER); + } + + parser_module_add_names_to_node (context_p, export_name_p, local_name_p); + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (export_name_p); + + if (context_p->token.type != LEXER_COMMA && context_p->token.type != LEXER_RIGHT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED); + } + else if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + } + + if (lexer_token_is_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + } +} /* parser_module_parse_export_clause */ + +/** + * Parse an ImportClause + */ +void +parser_module_parse_import_clause (parser_context_t *context_p) /**< parser context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE); + lexer_next_token (context_p); + + while (true) + { + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + lexer_next_token (context_p); + break; + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + ecma_string_t *import_name_p = NULL; + ecma_string_t *local_name_p = NULL; + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + + uint16_t import_name_index = context_p->lit_object.index; + uint16_t local_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS; + + lexer_next_token (context_p); + if (lexer_token_is_identifier (context_p, "as", 2)) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + + local_name_index = context_p->lit_object.index; + + lexer_next_token (context_p); + } + + import_name_p = parser_new_ecma_string_from_literal (PARSER_GET_LITERAL (import_name_index)); + + if (local_name_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + local_name_p = parser_new_ecma_string_from_literal (PARSER_GET_LITERAL (local_name_index)); + } + else + { + local_name_p = import_name_p; + ecma_ref_ecma_string (local_name_p); + } + + if (parser_module_check_duplicate_import (context_p, local_name_p)) + { + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (import_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_IMPORT_BINDING); + } + + parser_module_add_names_to_node (context_p, import_name_p, local_name_p); + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (import_name_p); + + if (context_p->token.type != LEXER_COMMA && (context_p->token.type != LEXER_RIGHT_BRACE)) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED); + } + else if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + } + + if (lexer_token_is_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + } +} /* parser_module_parse_import_clause */ + +/** + * Raises parser error if the import or export statement is not in the global scope. + */ +void +parser_module_check_request_place (parser_context_t *context_p) /**< parser context */ +{ + if (context_p->last_context_p != NULL || context_p->stack_top_uint8 != 0 + || (context_p->status_flags & PARSER_IS_FUNCTION) || (context_p->global_status_flags & ECMA_PARSE_EVAL) + || (context_p->global_status_flags & ECMA_PARSE_MODULE) == 0) + { + parser_raise_error (context_p, PARSER_ERR_MODULE_UNEXPECTED); + } +} /* parser_module_check_request_place */ + +/** + * Append names to the names list. + */ +void +parser_module_append_names (parser_context_t *context_p, /**< parser context */ + ecma_module_names_t **module_names_p) /**< target names */ +{ + ecma_module_names_t *last_name_p = context_p->module_names_p; + + if (last_name_p == NULL) + { + return; + } + + if (*module_names_p != NULL) + { + while (last_name_p->next_p != NULL) + { + last_name_p = last_name_p->next_p; + } + + last_name_p->next_p = *module_names_p; + } + + *module_names_p = context_p->module_names_p; + context_p->module_names_p = NULL; +} /* parser_module_append_names */ + +/** + * Handle module specifier at the end of the import / export statement. + */ +void +parser_module_handle_module_specifier (parser_context_t *context_p, /**< parser context */ + ecma_module_node_t **node_list_p) /**< target node list */ +{ + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_STRING_LITERAL + || context_p->token.lit_location.length == 0) + { + parser_raise_error (context_p, PARSER_ERR_STRING_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + + lexer_literal_t *path_p = context_p->lit_object.literal_p; + + lexer_next_token (context_p); + + /* The lexer_next_token may throw an error, so the path is constructed after its call. */ + ecma_string_t *path_string_p = parser_new_ecma_string_from_literal (path_p); + + ecma_module_node_t *node_p = JERRY_CONTEXT (module_current_p)->imports_p; + ecma_module_node_t *last_node_p = NULL; + + /* Check if we have an import node with the same module request. */ + + while (node_p != NULL) + { + if (ecma_compare_ecma_strings (ecma_get_string_from_value (node_p->u.path_or_module), path_string_p)) + { + ecma_deref_ecma_string (path_string_p); + break; + } + + last_node_p = node_p; + node_p = node_p->next_p; + } + + if (node_p == NULL) + { + node_p = (ecma_module_node_t *) jmem_heap_alloc_block_null_on_error (sizeof (ecma_module_node_t)); + + if (node_p == NULL) + { + ecma_deref_ecma_string (path_string_p); + parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY); + } + + if (last_node_p == NULL) + { + JERRY_CONTEXT (module_current_p)->imports_p = node_p; + } + else + { + last_node_p->next_p = node_p; + } + + node_p->next_p = NULL; + node_p->module_names_p = NULL; + node_p->u.path_or_module = ecma_make_string_value (path_string_p); + } + + /* Append to imports. */ + if (node_list_p == NULL) + { + parser_module_append_names (context_p, &node_p->module_names_p); + return; + } + + ecma_value_t *module_object_p = &node_p->u.path_or_module; + + node_p = *node_list_p; + last_node_p = NULL; + + while (node_p != NULL) + { + if (node_p->u.module_object_p == module_object_p) + { + parser_module_append_names (context_p, &node_p->module_names_p); + return; + } + + last_node_p = node_p; + node_p = node_p->next_p; + } + + node_p = (ecma_module_node_t *) parser_malloc (context_p, sizeof (ecma_module_node_t)); + + if (last_node_p == NULL) + { + *node_list_p = node_p; + } + else + { + last_node_p->next_p = node_p; + } + + node_p->next_p = NULL; + node_p->module_names_p = context_p->module_names_p; + node_p->u.module_object_p = module_object_p; + + context_p->module_names_p = NULL; +} /* parser_module_handle_module_specifier */ + +#endif /* JERRY_MODULE_SYSTEM */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-statm.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-statm.cpp new file mode 100644 index 00000000..51b51c11 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-statm.cpp @@ -0,0 +1,3315 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" + +#if JERRY_PARSER +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "lit-char-helpers.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_stmt Statement parser + * @{ + */ + +/** + * Parser statement types. + * + * When a new statement is added, the following + * arrays must be updated as well: + * - statement_lengths[] + * - parser_statement_flags[] + */ +typedef enum +{ + PARSER_STATEMENT_START, + PARSER_STATEMENT_BLOCK, + PARSER_STATEMENT_BLOCK_SCOPE, + PARSER_STATEMENT_PRIVATE_SCOPE, + PARSER_STATEMENT_BLOCK_CONTEXT, + PARSER_STATEMENT_PRIVATE_CONTEXT, + PARSER_STATEMENT_LABEL, + PARSER_STATEMENT_IF, + PARSER_STATEMENT_ELSE, + PARSER_STATEMENT_SWITCH, + PARSER_STATEMENT_SWITCH_NO_DEFAULT, + PARSER_STATEMENT_DO_WHILE, + PARSER_STATEMENT_WHILE, + PARSER_STATEMENT_FOR, + PARSER_STATEMENT_FOR_IN, + PARSER_STATEMENT_FOR_OF, + PARSER_STATEMENT_FOR_AWAIT_OF, + PARSER_STATEMENT_WITH, + PARSER_STATEMENT_TRY, +} parser_statement_type_t; + +/** + * Parser statement type flags. + */ +typedef enum +{ + PARSER_STATM_NO_OPTS = 0, /**< no options */ + PARSER_STATM_SINGLE_STATM = (1 << 0), /**< statment can form single statement context */ + PARSER_STATM_HAS_BLOCK = (1 << 1), /**< statement always has a code block */ + PARSER_STATM_BREAK_TARGET = (1 << 2), /**< break target statement */ + PARSER_STATM_CONTINUE_TARGET = (1 << 3), /**< continue target statement */ + PARSER_STATM_CONTEXT_BREAK = (1 << 4), /**< uses another instruction form when crosses their borders */ +} parser_statement_flags_t; + +/** + * Parser statement attributes. + * Note: the order of the attributes must be keep in sync with parser_statement_type_t + */ +static const uint8_t parser_statement_flags[] = { + /* PARSER_STATEMENT_START */ + PARSER_STATM_HAS_BLOCK, + /* PARSER_STATEMENT_BLOCK, */ + PARSER_STATM_HAS_BLOCK, + /* PARSER_STATEMENT_BLOCK_SCOPE, */ + PARSER_STATM_HAS_BLOCK, + /* PARSER_STATEMENT_PRIVATE_SCOPE, */ + PARSER_STATM_NO_OPTS, + /* PARSER_STATEMENT_BLOCK_CONTEXT, */ + PARSER_STATM_HAS_BLOCK | PARSER_STATM_CONTEXT_BREAK, + /* PARSER_STATEMENT_PRIVATE_CONTEXT, */ + PARSER_STATM_CONTEXT_BREAK, + /* PARSER_STATEMENT_LABEL */ + PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_IF */ + PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_ELSE */ + PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_SWITCH */ + PARSER_STATM_HAS_BLOCK | PARSER_STATM_BREAK_TARGET, + /* PARSER_STATEMENT_SWITCH_NO_DEFAULT */ + PARSER_STATM_HAS_BLOCK | PARSER_STATM_BREAK_TARGET, + /* PARSER_STATEMENT_DO_WHILE */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_WHILE */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_FOR */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_FOR_IN */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM | PARSER_STATM_CONTEXT_BREAK, + /* PARSER_STATEMENT_FOR_OF */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM | PARSER_STATM_CONTEXT_BREAK, + /* PARSER_STATEMENT_FOR_AWAIT_OF */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM | PARSER_STATM_CONTEXT_BREAK, + /* PARSER_STATEMENT_WITH */ + PARSER_STATM_CONTEXT_BREAK | PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_TRY */ + PARSER_STATM_HAS_BLOCK | PARSER_STATM_CONTEXT_BREAK +}; + +/** + * Block statement. + */ +typedef struct +{ + uint16_t scope_stack_top; /**< preserved top of scope stack */ + uint16_t scope_stack_reg_top; /**< preserved top register of scope stack */ +} parser_block_statement_t; + +/** + * Context of block statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ +} parser_block_context_t; + +/** + * Loop statement. + */ +typedef struct +{ + parser_branch_node_t *branch_list_p; /**< list of breaks and continues targeting this statement */ +} parser_loop_statement_t; + +/** + * Label statement. + */ +typedef struct +{ + lexer_lit_location_t label_ident; /**< name of the label */ + parser_branch_node_t *break_list_p; /**< list of breaks targeting this label */ +} parser_label_statement_t; + +/** + * If/else statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ +} parser_if_else_statement_t; + +/** + * Switch statement. + */ +typedef struct +{ + parser_branch_t default_branch; /**< branch to the default case */ + parser_branch_node_t *branch_list_p; /**< branches of case statements */ +} parser_switch_statement_t; + +/** + * Do-while statement. + */ +typedef struct +{ + uint32_t start_offset; /**< start byte code offset */ +} parser_do_while_statement_t; + +/** + * While statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ + scanner_location_t condition_location; /**< condition part */ + uint32_t start_offset; /**< start byte code offset */ +} parser_while_statement_t; + +/** + * For statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ + scanner_location_t condition_location; /**< condition part */ + scanner_location_t expression_location; /**< expression part */ + uint32_t start_offset; /**< start byte code offset */ +} parser_for_statement_t; + +/** + * For-in statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ + uint32_t start_offset; /**< start byte code offset */ +} parser_for_in_of_statement_t; + +/** + * With statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ +} parser_with_statement_t; + +/** + * Lexer token types. + */ +typedef enum +{ + parser_try_block, /**< try block */ + parser_catch_block, /**< catch block */ + parser_finally_block, /**< finally block */ +} parser_try_block_type_t; + +/** + * Try statement. + */ +typedef struct +{ + parser_try_block_type_t type; /**< current block type */ + uint16_t scope_stack_top; /**< current top of scope stack */ + uint16_t scope_stack_reg_top; /**< current top register of scope stack */ + parser_branch_t branch; /**< branch to the end of the current block */ +} parser_try_statement_t; + +/** + * Returns the data consumed by a statement. It can be used + * to skip undesired frames on the stack during frame search. + * + * @return size consumed by a statement. + */ +static inline size_t +parser_statement_length (uint8_t type) /**< type of statement */ +{ + static const uint8_t statement_lengths[] = { + /* PARSER_STATEMENT_BLOCK */ + 1, + /* PARSER_STATEMENT_BLOCK_SCOPE */ + (uint8_t) (sizeof (parser_block_statement_t) + 1), + /* PARSER_STATEMENT_PRIVATE_SCOPE */ + (uint8_t) (sizeof (parser_block_statement_t) + 1), + /* PARSER_STATEMENT_BLOCK_CONTEXT */ + (uint8_t) (sizeof (parser_block_statement_t) + sizeof (parser_block_context_t) + 1), + /* PARSER_STATEMENT_PRIVATE_CONTEXT */ + (uint8_t) (sizeof (parser_block_statement_t) + sizeof (parser_block_context_t) + 1), + /* PARSER_STATEMENT_LABEL */ + (uint8_t) (sizeof (parser_label_statement_t) + 1), + /* PARSER_STATEMENT_IF */ + (uint8_t) (sizeof (parser_if_else_statement_t) + 1), + /* PARSER_STATEMENT_ELSE */ + (uint8_t) (sizeof (parser_if_else_statement_t) + 1), + /* PARSER_STATEMENT_SWITCH */ + (uint8_t) (sizeof (parser_switch_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_SWITCH_NO_DEFAULT */ + (uint8_t) (sizeof (parser_switch_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_DO_WHILE */ + (uint8_t) (sizeof (parser_do_while_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_WHILE */ + (uint8_t) (sizeof (parser_while_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_FOR */ + (uint8_t) (sizeof (parser_for_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_FOR_IN */ + (uint8_t) (sizeof (parser_for_in_of_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_FOR_OF */ + (uint8_t) (sizeof (parser_for_in_of_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_FOR_AWAIT_OF */ + (uint8_t) (sizeof (parser_for_in_of_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_WITH */ + (uint8_t) (sizeof (parser_with_statement_t) + 1 + 1), + /* PARSER_STATEMENT_TRY */ + (uint8_t) (sizeof (parser_try_statement_t) + 1), + }; + + JERRY_ASSERT (type >= PARSER_STATEMENT_BLOCK && type <= PARSER_STATEMENT_TRY); + + return statement_lengths[type - PARSER_STATEMENT_BLOCK]; +} /* parser_statement_length */ +/** + * Parse expression enclosed in parens. + */ +static inline void +parser_parse_enclosed_expr (parser_context_t *context_p) /**< context */ +{ + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED); + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + lexer_next_token (context_p); +} /* parser_parse_enclosed_expr */ + +/** + * Create a block context. + * + * @return true - when a context is created, false - otherwise + */ +static bool +parser_push_block_context (parser_context_t *context_p, /**< context */ + bool is_private) /**< is private (bound to a statement) context */ +{ + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK); + + parser_block_statement_t block_statement; + block_statement.scope_stack_top = context_p->scope_stack_top; + block_statement.scope_stack_reg_top = context_p->scope_stack_reg_top; + + bool is_context_needed = false; + + if (scanner_is_context_needed (context_p, PARSER_CHECK_BLOCK_CONTEXT)) + { + parser_block_context_t block_context; + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + parser_emit_cbc_forward_branch (context_p, CBC_BLOCK_CREATE_CONTEXT, &block_context.branch); + parser_stack_push (context_p, &block_context, sizeof (parser_block_context_t)); + is_context_needed = true; + } + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + parser_stack_push (context_p, &block_statement, sizeof (parser_block_statement_t)); + + uint8_t statement_type; + + if (is_private) + { + statement_type = (is_context_needed ? PARSER_STATEMENT_PRIVATE_CONTEXT : PARSER_STATEMENT_PRIVATE_SCOPE); + } + else + { + statement_type = (is_context_needed ? PARSER_STATEMENT_BLOCK_CONTEXT : PARSER_STATEMENT_BLOCK_SCOPE); + } + + parser_stack_push_uint8 (context_p, statement_type); + + return is_context_needed; +} /* parser_push_block_context */ + +/** + * Pop block context. + */ +static void +parser_pop_block_context (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK_CONTEXT + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_CONTEXT); + + uint8_t type = context_p->stack_top_uint8; + + parser_block_statement_t block_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &block_statement, sizeof (parser_block_statement_t)); + + context_p->scope_stack_top = block_statement.scope_stack_top; + context_p->scope_stack_reg_top = block_statement.scope_stack_reg_top; + + if (type == PARSER_STATEMENT_BLOCK_CONTEXT || type == PARSER_STATEMENT_PRIVATE_CONTEXT) + { + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + parser_block_context_t block_context; + parser_stack_pop (context_p, &block_context, sizeof (parser_block_context_t)); + + parser_emit_cbc (context_p, CBC_CONTEXT_END); + parser_set_branch_to_current_position (context_p, &block_context.branch); + } + + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_pop_block_context */ + +/** + * Validate lexical context for a declaration. + */ +static void +parser_validate_lexical_context (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_LET || context_p->token.type == LEXER_KEYW_CONST + || context_p->token.type == LEXER_KEYW_CLASS); + + if (parser_statement_flags[context_p->stack_top_uint8] & PARSER_STATM_SINGLE_STATM) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_SINGLE_STATEMENT); + } +} /* parser_validate_lexical_context */ + +/** + * Parse var statement. + */ +static void +parser_parse_var_statement (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_VAR || context_p->token.type == LEXER_KEYW_LET + || context_p->token.type == LEXER_KEYW_CONST); + + uint8_t declaration_type = context_p->token.type; + + if (declaration_type != LEXER_KEYW_VAR) + { + parser_validate_lexical_context (context_p); + } + + while (true) + { + if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE)) + { + parser_pattern_flags_t flags = PARSER_PATTERN_BINDING; + + if (declaration_type == LEXER_KEYW_LET) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_LET); + } + else if (declaration_type == LEXER_KEYW_CONST) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_CONST); + } + + parser_parse_initializer_by_next_char (context_p, flags); + } + else + { + lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL); + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); +#if JERRY_LINE_INFO + parser_line_counter_t ident_column_counter = context_p->token.column; +#endif /* JERRY_LINE_INFO */ + +#if JERRY_MODULE_SYSTEM + parser_module_append_export_name (context_p); +#endif /* JERRY_MODULE_SYSTEM */ + + if (declaration_type != LEXER_KEYW_VAR && context_p->token.keyword_type == LEXER_KEYW_LET) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_LET_BINDING); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_ASSIGN) + { +#if JERRY_LINE_INFO + parser_line_info_append (context_p, ident_line_counter, ident_column_counter); +#endif /* JERRY_LINE_INFO */ + + uint16_t index = context_p->lit_object.index; + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + cbc_opcode_t opcode = CBC_ASSIGN_SET_IDENT; + + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + uint16_t name_index = scanner_save_literal (context_p, index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + parser_set_function_name (context_p, function_literal_index, index, 0); + } + + if (declaration_type != LEXER_KEYW_VAR && (index < PARSER_REGISTER_START)) + { + opcode = CBC_INIT_LET; + + if (scanner_literal_is_created (context_p, index)) + { + opcode = CBC_ASSIGN_LET_CONST; + } + else if (declaration_type == LEXER_KEYW_CONST) + { + opcode = CBC_INIT_CONST; + } + } + + parser_emit_cbc_literal (context_p, (uint16_t) opcode, index); + } + else if (declaration_type == LEXER_KEYW_LET) + { + parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED); + + uint16_t index = context_p->lit_object.index; + cbc_opcode_t opcode = CBC_MOV_IDENT; + + if (index < PARSER_REGISTER_START) + { + opcode = (scanner_literal_is_created (context_p, index) ? CBC_ASSIGN_LET_CONST : CBC_INIT_LET); + } + + parser_emit_cbc_literal (context_p, (uint16_t) opcode, index); + } + else if (declaration_type == LEXER_KEYW_CONST) + { + parser_raise_error (context_p, PARSER_ERR_MISSING_ASSIGN_AFTER_CONST); + } + } + + if (context_p->token.type != LEXER_COMMA) + { + break; + } + } + +#if JERRY_MODULE_SYSTEM + context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_STORE_IDENT); +#endif /* JERRY_MODULE_SYSTEM */ +} /* parser_parse_var_statement */ + +/** + * Parse function statement. + */ +static void +parser_parse_function_statement (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FUNCTION); + + bool is_single_statement = (parser_statement_flags[context_p->stack_top_uint8] & PARSER_STATM_SINGLE_STATM) != 0; + + if (JERRY_UNLIKELY (is_single_statement)) + { + if (context_p->status_flags & PARSER_IS_STRICT) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_SINGLE_STATEMENT); + } + + if (context_p->stack_top_uint8 == PARSER_STATEMENT_IF || context_p->stack_top_uint8 == PARSER_STATEMENT_ELSE) + { + /* There must be a parser error later if this check fails. */ + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + parser_push_block_context (context_p, true); + } + } + else if (context_p->stack_top_uint8 == PARSER_STATEMENT_LABEL) + { + parser_stack_iterator_t iterator; + parser_stack_iterator_init (context_p, &iterator); + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t) + 1); + + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + + if (type == PARSER_STATEMENT_LABEL) + { + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t) + 1); + continue; + } + + if (parser_statement_flags[type] & PARSER_STATM_HAS_BLOCK) + { + break; + } + + parser_raise_error (context_p, PARSER_ERR_LABELLED_FUNC_NOT_IN_BLOCK); + } + } + else + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_SINGLE_STATEMENT); + } + } +#if JERRY_FUNCTION_TO_STRING + if (!(context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC)) + { + context_p->function_start_p = context_p->token.lit_location.char_p; + } +#endif /* JERRY_FUNCTION_TO_STRING */ + + bool is_generator_function = false; + + if (lexer_consume_generator (context_p)) + { + if (is_single_statement) + { + parser_raise_error (context_p, PARSER_ERR_GENERATOR_IN_SINGLE_STATEMENT_POS); + } + is_generator_function = true; + } + + lexer_expect_identifier (context_p, LEXER_NEW_IDENT_LITERAL); + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED) + { + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + uint16_t function_name_index = context_p->lit_object.index; + +#if JERRY_MODULE_SYSTEM + parser_module_append_export_name (context_p); + context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_STORE_IDENT); +#endif /* JERRY_MODULE_SYSTEM */ + + uint32_t status_flags = PARSER_FUNCTION_CLOSURE; + + if (context_p->token.keyword_type >= LEXER_FIRST_NON_STRICT_ARGUMENTS) + { + status_flags |= PARSER_HAS_NON_STRICT_ARG; + } + + if (is_generator_function) + { + status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + } + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC) + { + status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + } + + JERRY_ASSERT (context_p->scope_stack_top >= 2); + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top - 2; + + uint16_t literal_index = context_p->lit_object.index; + + while (literal_index != scope_stack_p->map_from) + { + scope_stack_p--; + + JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p); + } + + JERRY_ASSERT (scope_stack_p[1].map_from == PARSER_SCOPE_STACK_FUNC); + + if (!(context_p->status_flags & PARSER_IS_STRICT) + && (scope_stack_p >= context_p->scope_stack_p + context_p->scope_stack_global_end)) + { + bool copy_value = true; + + parser_scope_stack_t *stack_p = context_p->scope_stack_p; + + while (stack_p < scope_stack_p) + { + if (literal_index == stack_p->map_from && (stack_p->map_to & PARSER_SCOPE_STACK_NO_FUNCTION_COPY)) + { + copy_value = false; + break; + } + stack_p++; + } + + if (copy_value) + { + stack_p = context_p->scope_stack_p; + + while (stack_p < scope_stack_p) + { + if (literal_index == stack_p->map_from) + { + JERRY_ASSERT (!(stack_p->map_to & PARSER_SCOPE_STACK_NO_FUNCTION_COPY)); + + uint16_t map_to = scanner_decode_map_to (stack_p); + uint16_t opcode = ((map_to >= PARSER_REGISTER_START) ? CBC_ASSIGN_LITERAL_SET_IDENT : CBC_COPY_TO_GLOBAL); + + parser_emit_cbc_literal_value (context_p, opcode, scanner_decode_map_to (scope_stack_p), map_to); + break; + } + stack_p++; + } + + parser_flush_cbc (context_p); + } + + if (JERRY_UNLIKELY (context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_CONTEXT)) + { + parser_pop_block_context (context_p); + } + } + + lexer_literal_t *literal_p = PARSER_GET_LITERAL ((size_t) scope_stack_p[1].map_to); + + JERRY_ASSERT ((literal_p->type == LEXER_UNUSED_LITERAL || literal_p->type == LEXER_FUNCTION_LITERAL) + && literal_p->status_flags == 0); + + ecma_compiled_code_t *compiled_code_p = parser_parse_function (context_p, status_flags); + + if (literal_p->type == LEXER_FUNCTION_LITERAL) + { + ecma_bytecode_deref (literal_p->u.bytecode_p); + } + + literal_p->u.bytecode_p = compiled_code_p; + literal_p->type = LEXER_FUNCTION_LITERAL; + + parser_compiled_code_set_function_name (context_p, compiled_code_p, function_name_index, 0); + lexer_next_token (context_p); +} /* parser_parse_function_statement */ + +/** + * Parse if statement (starting part). + */ +static void +parser_parse_if_statement_start (parser_context_t *context_p) /**< context */ +{ + parser_if_else_statement_t if_statement; + + parser_parse_enclosed_expr (context_p); + + parser_emit_cbc_forward_branch (context_p, CBC_BRANCH_IF_FALSE_FORWARD, &if_statement.branch); + + parser_stack_push (context_p, &if_statement, sizeof (parser_if_else_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_IF); + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_parse_if_statement_start */ + +/** + * Parse if statement (ending part). + * + * @return true - if parsing an 'else' statement + * false - otherwise + */ +static bool +parser_parse_if_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_if_else_statement_t if_statement; + parser_if_else_statement_t else_statement; + parser_stack_iterator_t iterator; + + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_IF); + + if (context_p->token.type != LEXER_KEYW_ELSE) + { + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &if_statement, sizeof (parser_if_else_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_set_branch_to_current_position (context_p, &if_statement.branch); + + return false; + } + + parser_stack_change_last_uint8 (context_p, PARSER_STATEMENT_ELSE); + parser_stack_iterator_init (context_p, &iterator); + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &if_statement, sizeof (parser_if_else_statement_t)); + + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &else_statement.branch); + + parser_set_branch_to_current_position (context_p, &if_statement.branch); + + parser_stack_iterator_write (&iterator, &else_statement, sizeof (parser_if_else_statement_t)); + + lexer_next_token (context_p); + return true; +} /* parser_parse_if_statement_end */ + +/** + * Parse with statement (starting part). + */ +static void +parser_parse_with_statement_start (parser_context_t *context_p) /**< context */ +{ + parser_with_statement_t with_statement; + + if (context_p->status_flags & PARSER_IS_STRICT) + { + parser_raise_error (context_p, PARSER_ERR_WITH_NOT_ALLOWED); + } + + parser_parse_enclosed_expr (context_p); + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + uint8_t inside_with = (context_p->status_flags & PARSER_INSIDE_WITH) != 0; + + context_p->status_flags |= PARSER_INSIDE_WITH; + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_WITH_CREATE_CONTEXT, &with_statement.branch); + + parser_stack_push (context_p, &with_statement, sizeof (parser_with_statement_t)); + parser_stack_push_uint8 (context_p, inside_with); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_WITH); + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_parse_with_statement_start */ + +/** + * Parse with statement (ending part). + */ +static void +parser_parse_with_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_with_statement_t with_statement; + + JERRY_ASSERT (context_p->status_flags & PARSER_INSIDE_WITH); + + parser_stack_pop_uint8 (context_p); + + if (!context_p->stack_top_uint8) + { + context_p->status_flags &= (uint32_t) ~PARSER_INSIDE_WITH; + } + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &with_statement, sizeof (parser_with_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_flush_cbc (context_p); + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + parser_emit_cbc (context_p, CBC_CONTEXT_END); + parser_set_branch_to_current_position (context_p, &with_statement.branch); +} /* parser_parse_with_statement_end */ + +/** + * Parse do-while statement (ending part). + */ +static void +parser_parse_do_while_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_loop_statement_t loop; + + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_DO_WHILE); + + if (context_p->token.type != LEXER_KEYW_WHILE) + { + parser_raise_error (context_p, PARSER_ERR_WHILE_EXPECTED); + } + + parser_stack_iterator_t iterator; + parser_stack_iterator_init (context_p, &iterator); + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + + parser_set_continues_to_current_position (context_p, loop.branch_list_p); + + JERRY_ASSERT (context_p->next_scanner_info_p->source_p != context_p->source_p); + + parser_parse_enclosed_expr (context_p); + + if (context_p->last_cbc_opcode != CBC_PUSH_FALSE) + { + cbc_opcode_t opcode = CBC_BRANCH_IF_TRUE_BACKWARD; + if (context_p->last_cbc_opcode == CBC_LOGICAL_NOT) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_BRANCH_IF_FALSE_BACKWARD; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TRUE) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_JUMP_BACKWARD; + } + + parser_do_while_statement_t do_while_statement; + parser_stack_iterator_skip (&iterator, sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &do_while_statement, sizeof (parser_do_while_statement_t)); + + parser_emit_cbc_backward_branch (context_p, (uint16_t) opcode, do_while_statement.start_offset); + } + else + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + + parser_stack_pop (context_p, NULL, 1 + sizeof (parser_loop_statement_t) + sizeof (parser_do_while_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_set_breaks_to_current_position (context_p, loop.branch_list_p); +} /* parser_parse_do_while_statement_end */ + +/** + * Parse while statement (starting part). + */ +static void +parser_parse_while_statement_start (parser_context_t *context_p) /**< context */ +{ + parser_while_statement_t while_statement; + parser_loop_statement_t loop; + + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_WHILE); + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->source_p != context_p->source_p + || context_p->next_scanner_info_p->type == SCANNER_TYPE_WHILE); + + if (context_p->next_scanner_info_p->source_p != context_p->source_p) + { + /* The prescanner couldn't find the end of the while condition. */ + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR); + + JERRY_ASSERT (context_p->token.type != LEXER_RIGHT_PAREN); + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &while_statement.branch); + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + while_statement.start_offset = context_p->byte_code_size; + scanner_get_location (&while_statement.condition_location, context_p); + + scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location); + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + scanner_seek (context_p); + lexer_next_token (context_p); + + loop.branch_list_p = NULL; + + parser_stack_push (context_p, &while_statement, sizeof (parser_while_statement_t)); + parser_stack_push (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_WHILE); + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_parse_while_statement_start */ + +/** + * Parse while statement (ending part). + */ +static void JERRY_ATTR_NOINLINE +parser_parse_while_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_while_statement_t while_statement; + parser_loop_statement_t loop; + lexer_token_t current_token; + scanner_location_t location; + cbc_opcode_t opcode; + + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_WHILE); + + parser_stack_iterator_t iterator; + parser_stack_iterator_init (context_p, &iterator); + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &while_statement, sizeof (parser_while_statement_t)); + + scanner_get_location (&location, context_p); + current_token = context_p->token; + + parser_set_branch_to_current_position (context_p, &while_statement.branch); + parser_set_continues_to_current_position (context_p, loop.branch_list_p); + + scanner_set_location (context_p, &while_statement.condition_location); + scanner_seek (context_p); + lexer_next_token (context_p); + + parser_parse_expression (context_p, PARSE_EXPR); + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + opcode = CBC_BRANCH_IF_TRUE_BACKWARD; + if (context_p->last_cbc_opcode == CBC_LOGICAL_NOT) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_BRANCH_IF_FALSE_BACKWARD; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TRUE) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_JUMP_BACKWARD; + } + + parser_stack_pop (context_p, NULL, 1 + sizeof (parser_loop_statement_t) + sizeof (parser_while_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_emit_cbc_backward_branch (context_p, (uint16_t) opcode, while_statement.start_offset); + parser_set_breaks_to_current_position (context_p, loop.branch_list_p); + + /* Calling scanner_seek is unnecessary because all + * info blocks inside the while statement should be processed. */ + scanner_set_location (context_p, &location); + context_p->token = current_token; +} /* parser_parse_while_statement_end */ + +/** + * Check whether the opcode is a valid LeftHandSide expression + * and convert it back to an assignment. + * + * @return the compatible assignment opcode + */ +static uint16_t +parser_check_left_hand_side_expression (parser_context_t *context_p, /**< context */ + uint16_t opcode) /**< opcode to check */ +{ + if (opcode == CBC_PUSH_LITERAL && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + return CBC_ASSIGN_SET_IDENT; + } + else if (opcode == CBC_PUSH_PROP) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + return CBC_ASSIGN; + } + else if (opcode == CBC_PUSH_PROP_LITERAL) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + return CBC_ASSIGN_PROP_LITERAL; + } + else if (opcode == CBC_PUSH_PROP_LITERAL_LITERAL) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + return CBC_ASSIGN; + } + else if (opcode == CBC_PUSH_PROP_THIS_LITERAL) + { + context_p->last_cbc_opcode = CBC_PUSH_THIS_LITERAL; + return CBC_ASSIGN; + } + else + { + /* Invalid LeftHandSide expression. */ + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_FOR_LOOP); + return CBC_ASSIGN; + } + + return opcode; +} /* parser_check_left_hand_side_expression */ + +/** + * Parse for statement (starting part). + */ +static void +parser_parse_for_statement_start (parser_context_t *context_p) /**< context */ +{ + parser_loop_statement_t loop; + + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FOR); + lexer_next_token (context_p); + bool is_for_await = false; + + if (context_p->token.type == LEXER_KEYW_AWAIT) + { + if (JERRY_UNLIKELY (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + lexer_next_token (context_p); + is_for_await = true; + } + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + if (context_p->token.type == LEXER_LITERAL && context_p->token.keyword_type == LEXER_KEYW_AWAIT + && !(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + parser_raise_error (context_p, PARSER_ERR_FOR_AWAIT_NO_ASYNC); + } + + parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + parser_for_in_of_statement_t for_in_of_statement; + scanner_location_t start_location, end_location; + + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FOR_IN + || context_p->next_scanner_info_p->type == SCANNER_TYPE_FOR_OF); + + bool is_for_in = (context_p->next_scanner_info_p->type == SCANNER_TYPE_FOR_IN); + end_location = ((scanner_location_info_t *) context_p->next_scanner_info_p)->location; + + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + + scanner_get_location (&start_location, context_p); + lexer_next_token (context_p); + + uint8_t token_type = LEXER_EOS; + bool has_context = false; + + if (context_p->token.type == LEXER_KEYW_VAR || context_p->token.type == LEXER_KEYW_LET + || context_p->token.type == LEXER_KEYW_CONST) + { + token_type = context_p->token.type; + has_context = context_p->next_scanner_info_p->source_p == context_p->source_p; + JERRY_ASSERT (!has_context || context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK); + scanner_get_location (&start_location, context_p); + + /* TODO: remove this after the pre-scanner supports strict mode detection. */ + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION) + { + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + } + else if (context_p->token.type == LEXER_LITERAL && lexer_token_is_let (context_p)) + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION) + { + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + else + { + token_type = LEXER_KEYW_LET; + has_context = (context_p->next_scanner_info_p->source_p == context_p->source_p); + scanner_get_location (&start_location, context_p); + } + } + + if (has_context) + { + has_context = parser_push_block_context (context_p, true); + } + + scanner_set_location (context_p, &end_location); + + /* The length of both 'in' and 'of' is two. */ + const uint8_t *source_end_p = context_p->source_p - 2; + + scanner_seek (context_p); + + if (is_for_in && is_for_await) + { + context_p->token.line = context_p->line; + context_p->token.column = context_p->column - 2; + parser_raise_error (context_p, PARSER_ERR_FOR_AWAIT_NO_OF); + } + + lexer_next_token (context_p); + int options = is_for_in ? PARSE_EXPR : PARSE_EXPR_NO_COMMA; + parser_parse_expression (context_p, options); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, + is_for_in ? PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION : PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + cbc_ext_opcode_t init_opcode = CBC_EXT_FOR_IN_INIT; + + if (!is_for_in) + { + init_opcode = is_for_await ? CBC_EXT_FOR_AWAIT_OF_INIT : CBC_EXT_FOR_OF_INIT; + } + + parser_emit_cbc_ext_forward_branch (context_p, init_opcode, &for_in_of_statement.branch); + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + for_in_of_statement.start_offset = context_p->byte_code_size; + + if (has_context) + { + parser_emit_cbc_ext (context_p, CBC_EXT_CLONE_CONTEXT); + } + + /* The expression parser must not read the 'in' or 'of' tokens. */ + scanner_get_location (&end_location, context_p); + scanner_set_location (context_p, &start_location); + + const uint8_t *original_source_end_p = context_p->source_end_p; + context_p->source_end_p = source_end_p; + scanner_seek (context_p); + + if (token_type == LEXER_EOS) + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE) + { + token_type = context_p->token.type; + } + } + + switch (token_type) + { + case LEXER_KEYW_LET: + case LEXER_KEYW_CONST: + case LEXER_KEYW_VAR: + { + if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE)) + { + parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT : CBC_EXT_FOR_OF_GET_NEXT); + + parser_pattern_flags_t flags = (parser_pattern_flags_t ) ((unsigned int) PARSER_PATTERN_BINDING | (unsigned int) PARSER_PATTERN_TARGET_ON_STACK); + + if (context_p->next_scanner_info_p->source_p == (context_p->source_p + 1)) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER) + { + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + } + else + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS); + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_HAS_REST_ELEMENT); + } + + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + } + + if (token_type == LEXER_KEYW_LET) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_LET); + } + else if (token_type == LEXER_KEYW_CONST) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_CONST); + } + + parser_parse_initializer_by_next_char (context_p, flags); + break; + } + + lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL); + + if (context_p->token.keyword_type == LEXER_KEYW_LET && token_type != LEXER_KEYW_VAR) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_LET_BINDING); + } + + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + uint16_t literal_index = context_p->lit_object.index; + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_ASSIGN) + { + if ((context_p->status_flags & PARSER_IS_STRICT) || !is_for_in) + { + parser_raise_error (context_p, PARSER_ERR_FOR_IN_OF_DECLARATION); + } + parser_branch_t branch; + + /* Initialiser is never executed. */ + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &branch); + lexer_next_token (context_p); + parser_parse_expression_statement (context_p, PARSE_EXPR_NO_COMMA); + parser_set_branch_to_current_position (context_p, &branch); + } + + parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT : CBC_EXT_FOR_OF_GET_NEXT); +#ifndef JERRY_NDEBUG + if (literal_index < PARSER_REGISTER_START && has_context + && !scanner_literal_is_created (context_p, literal_index)) + { + context_p->global_status_flags |= ECMA_PARSE_INTERNAL_FOR_IN_OFF_CONTEXT_ERROR; + } +#endif /* !JERRY_NDEBUG */ + + uint16_t opcode = (has_context ? CBC_ASSIGN_LET_CONST : CBC_ASSIGN_SET_IDENT); + parser_emit_cbc_literal (context_p, opcode, literal_index); + break; + } + case LEXER_LEFT_BRACE: + case LEXER_LEFT_SQUARE: + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS + && (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_DESTRUCTURING_FOR)) + { + parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT : CBC_EXT_FOR_OF_GET_NEXT); + + uint32_t flags = PARSER_PATTERN_TARGET_ON_STACK; + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags |= PARSER_PATTERN_HAS_REST_ELEMENT; + } + + scanner_release_next (context_p, sizeof (scanner_info_t)); + parser_parse_initializer (context_p, (parser_pattern_flags_t) flags); + /* Pop the value returned by GET_NEXT. */ + parser_emit_cbc (context_p, CBC_POP); + break; + } + /* FALLTHRU */ + } + default: + { + uint16_t opcode; + + parser_parse_expression (context_p, PARSE_EXPR_LEFT_HAND_SIDE); + + opcode = context_p->last_cbc_opcode; + + /* The CBC_EXT_FOR_IN_CREATE_CONTEXT flushed the opcode combiner. */ + JERRY_ASSERT (opcode != CBC_PUSH_TWO_LITERALS && opcode != CBC_PUSH_THREE_LITERALS); + + opcode = parser_check_left_hand_side_expression (context_p, opcode); + + parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT : CBC_EXT_FOR_OF_GET_NEXT); + parser_flush_cbc (context_p); + + context_p->last_cbc_opcode = opcode; + break; + } + } + + if (context_p->token.type != LEXER_EOS) + { + parser_raise_error (context_p, is_for_in ? PARSER_ERR_IN_EXPECTED : PARSER_ERR_OF_EXPECTED); + } + + parser_flush_cbc (context_p); + scanner_set_location (context_p, &end_location); + context_p->source_end_p = original_source_end_p; + lexer_next_token (context_p); + + loop.branch_list_p = NULL; + + parser_stack_push (context_p, &for_in_of_statement, sizeof (parser_for_in_of_statement_t)); + parser_stack_push (context_p, &loop, sizeof (parser_loop_statement_t)); + + uint8_t for_type = PARSER_STATEMENT_FOR_IN; + + if (!is_for_in) + { + for_type = is_for_await ? PARSER_STATEMENT_FOR_AWAIT_OF : PARSER_STATEMENT_FOR_OF; + } + + parser_stack_push_uint8 (context_p, for_type); + parser_stack_iterator_init (context_p, &context_p->last_statement); + return; + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_SEMICOLON) + { + const uint8_t *source_p = context_p->source_p; + + switch (context_p->token.type) + { + case LEXER_LITERAL: + { + if (!lexer_token_is_let (context_p)) + { + parser_parse_expression_statement (context_p, PARSE_EXPR); + break; + } + + /* FALLTHRU */ + } + case LEXER_KEYW_LET: + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type != SCANNER_TYPE_BLOCK) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION) + { + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + + parser_parse_expression_statement (context_p, PARSE_EXPR); + break; + } + + context_p->token.type = LEXER_KEYW_LET; + + /* FALLTHRU */ + } + case LEXER_KEYW_CONST: + { + if (context_p->next_scanner_info_p->source_p == source_p) + { + parser_push_block_context (context_p, true); + } + /* FALLTHRU */ + } + case LEXER_KEYW_VAR: + { + parser_parse_var_statement (context_p); + break; + } + default: + { + parser_parse_expression_statement (context_p, PARSE_EXPR); + break; + } + } + + if (context_p->token.type != LEXER_SEMICOLON) + { + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + } + + if (is_for_await) + { + parser_raise_error (context_p, PARSER_ERR_FOR_AWAIT_NO_OF); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->source_p != context_p->source_p + || context_p->next_scanner_info_p->type == SCANNER_TYPE_FOR); + + if (context_p->next_scanner_info_p->source_p != context_p->source_p + || ((scanner_for_info_t *) context_p->next_scanner_info_p)->end_location.source_p == NULL) + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + /* Even though the scanning is failed, there might be valid statements + * inside the for statement which depend on scanner info blocks. */ + scanner_release_next (context_p, sizeof (scanner_for_info_t)); + } + + /* The prescanner couldn't find the second semicolon or the closing paranthesis. */ + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_SEMICOLON) + { + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + + lexer_next_token (context_p); + parser_parse_expression_statement (context_p, PARSE_EXPR); + + JERRY_ASSERT (context_p->token.type != LEXER_RIGHT_PAREN); + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + parser_for_statement_t for_statement; + scanner_for_info_t *for_info_p = (scanner_for_info_t *) context_p->next_scanner_info_p; + + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &for_statement.branch); + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + for_statement.start_offset = context_p->byte_code_size; + scanner_get_location (&for_statement.condition_location, context_p); + for_statement.expression_location = for_info_p->expression_location; + + scanner_set_location (context_p, &for_info_p->end_location); + scanner_release_next (context_p, sizeof (scanner_for_info_t)); + scanner_seek (context_p); + lexer_next_token (context_p); + + loop.branch_list_p = NULL; + + parser_stack_push (context_p, &for_statement, sizeof (parser_for_statement_t)); + parser_stack_push (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_FOR); + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_parse_for_statement_start */ + +/** + * Parse for statement (ending part). + */ +static void JERRY_ATTR_NOINLINE +parser_parse_for_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_for_statement_t for_statement; + parser_loop_statement_t loop; + lexer_token_t current_token; + scanner_location_t location; + cbc_opcode_t opcode; + + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_FOR); + + parser_stack_iterator_t iterator; + parser_stack_iterator_init (context_p, &iterator); + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &for_statement, sizeof (parser_for_statement_t)); + + bool has_block_context = false; + uint8_t next_statement_type; + + parser_stack_iterator_skip (&iterator, sizeof (parser_for_statement_t)); + parser_stack_iterator_read (&iterator, &next_statement_type, 1); + + if (next_statement_type == PARSER_STATEMENT_PRIVATE_CONTEXT) + { + has_block_context = true; + } + + scanner_get_location (&location, context_p); + current_token = context_p->token; + + scanner_set_location (context_p, &for_statement.expression_location); + scanner_seek (context_p); + lexer_next_token (context_p); + + parser_set_continues_to_current_position (context_p, loop.branch_list_p); + + if (has_block_context) + { + parser_emit_cbc_ext (context_p, CBC_EXT_CLONE_FULL_CONTEXT); + } + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_parse_expression_statement (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + } + + parser_set_branch_to_current_position (context_p, &for_statement.branch); + + scanner_set_location (context_p, &for_statement.condition_location); + scanner_seek (context_p); + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_SEMICOLON) + { + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_SEMICOLON) + { + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + + opcode = CBC_BRANCH_IF_TRUE_BACKWARD; + if (context_p->last_cbc_opcode == CBC_LOGICAL_NOT) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_BRANCH_IF_FALSE_BACKWARD; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TRUE) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_JUMP_BACKWARD; + } + } + else + { + opcode = CBC_JUMP_BACKWARD; + } + + parser_stack_pop (context_p, NULL, 1 + sizeof (parser_loop_statement_t) + sizeof (parser_for_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_emit_cbc_backward_branch (context_p, (uint16_t) opcode, for_statement.start_offset); + parser_set_breaks_to_current_position (context_p, loop.branch_list_p); + + if (context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_CONTEXT) + { + parser_pop_block_context (context_p); + } + + /* Calling scanner_seek is unnecessary because all + * info blocks inside the for statement should be processed. */ + scanner_set_location (context_p, &location); + context_p->token = current_token; +} /* parser_parse_for_statement_end */ + +/** + * Parse switch statement (starting part). + */ +static void JERRY_ATTR_NOINLINE +parser_parse_switch_statement_start (parser_context_t *context_p) /**< context */ +{ + parser_switch_statement_t switch_statement; + parser_loop_statement_t loop; + parser_stack_iterator_t iterator; + scanner_location_t start_location; + bool switch_case_was_found; + bool default_case_was_found; + parser_branch_node_t *case_branches_p = NULL; + + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_SWITCH); + + parser_parse_enclosed_expr (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p - 1) + { + parser_push_block_context (context_p, true); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_SWITCH); + + scanner_case_info_t *case_info_p = ((scanner_switch_info_t *) context_p->next_scanner_info_p)->case_p; + scanner_set_active (context_p); + + if (case_info_p == NULL) + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + scanner_release_active (context_p, sizeof (scanner_switch_info_t)); + + parser_emit_cbc (context_p, CBC_POP); + parser_flush_cbc (context_p); + + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_BLOCK); + parser_stack_iterator_init (context_p, &context_p->last_statement); + return; + } + + parser_raise_error (context_p, PARSER_ERR_INVALID_SWITCH); + } + + scanner_get_location (&start_location, context_p); + + /* The reason of using an iterator is error management. If an error + * occures, parser_free_jumps() free all data. However, the branches + * created by parser_emit_cbc_forward_branch_item() would not be freed. + * To free these branches, the current switch data is always stored + * on the stack. If any change happens, this data is updated. Updates + * are done using the iterator. */ + + switch_statement.branch_list_p = NULL; + loop.branch_list_p = NULL; + + parser_stack_push (context_p, &switch_statement, sizeof (parser_switch_statement_t)); + parser_stack_iterator_init (context_p, &iterator); + parser_stack_push (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_SWITCH); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + switch_case_was_found = false; + default_case_was_found = false; + + do + { + scanner_set_location (context_p, &case_info_p->location); + scanner_seek (context_p); + case_info_p = case_info_p->next_p; + + /* The last letter of case and default is 'e' and 't' respectively. */ + JERRY_ASSERT (context_p->source_p[-1] == LIT_CHAR_LOWERCASE_E || context_p->source_p[-1] == LIT_CHAR_LOWERCASE_T); + + bool is_default = context_p->source_p[-1] == LIT_CHAR_LOWERCASE_T; + lexer_next_token (context_p); + + if (is_default) + { + if (default_case_was_found) + { + parser_raise_error (context_p, PARSER_ERR_MULTIPLE_DEFAULTS_NOT_ALLOWED); + } + + if (context_p->token.type != LEXER_COLON) + { + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + default_case_was_found = true; + continue; + } + + switch_case_was_found = true; + +#if JERRY_LINE_INFO + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); +#endif /* JERRY_LINE_INFO */ + + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_COLON) + { + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + uint16_t opcode = CBC_BRANCH_IF_STRICT_EQUAL; + + if (case_info_p == NULL + || (case_info_p->next_p == NULL && case_info_p->location.source_p[-1] == LIT_CHAR_LOWERCASE_T)) + { + /* There are no more 'case' statements in the switch. */ + parser_emit_cbc (context_p, CBC_STRICT_EQUAL); + opcode = CBC_BRANCH_IF_TRUE_FORWARD; + } + + parser_branch_node_t *new_case_p = parser_emit_cbc_forward_branch_item (context_p, opcode, NULL); + + if (case_branches_p == NULL) + { + switch_statement.branch_list_p = new_case_p; + parser_stack_iterator_write (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + } + else + { + case_branches_p->next_p = new_case_p; + } + + case_branches_p = new_case_p; + } while (case_info_p != NULL); + + JERRY_ASSERT (switch_case_was_found || default_case_was_found); + + if (!switch_case_was_found) + { + /* There was no case statement, so the expression result + * of the switch must be popped from the stack */ + parser_emit_cbc (context_p, CBC_POP); + } + + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &switch_statement.default_branch); + parser_stack_iterator_write (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + + if (!default_case_was_found) + { + parser_stack_change_last_uint8 (context_p, PARSER_STATEMENT_SWITCH_NO_DEFAULT); + } + + scanner_release_switch_cases (((scanner_switch_info_t *) context_p->active_scanner_info_p)->case_p); + scanner_release_active (context_p, sizeof (scanner_switch_info_t)); + + scanner_set_location (context_p, &start_location); + scanner_seek (context_p); + lexer_next_token (context_p); +} /* parser_parse_switch_statement_start */ + +/** + * Parse try statement (ending part). + */ +static void +parser_parse_try_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_try_statement_t try_statement; + parser_stack_iterator_t iterator; + + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_TRY); + + parser_stack_iterator_init (context_p, &iterator); + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &try_statement, sizeof (parser_try_statement_t)); + + context_p->scope_stack_top = try_statement.scope_stack_top; + context_p->scope_stack_reg_top = try_statement.scope_stack_reg_top; + + lexer_next_token (context_p); + + if (try_statement.type == parser_finally_block) + { + parser_flush_cbc (context_p); + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + parser_emit_cbc (context_p, CBC_CONTEXT_END); + parser_set_branch_to_current_position (context_p, &try_statement.branch); + } + else + { + parser_set_branch_to_current_position (context_p, &try_statement.branch); + + if (try_statement.type == parser_catch_block) + { + if (context_p->token.type != LEXER_KEYW_FINALLY) + { + parser_flush_cbc (context_p); + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + parser_emit_cbc (context_p, CBC_CONTEXT_END); + parser_flush_cbc (context_p); + + try_statement.type = parser_finally_block; + } + } + else + { + JERRY_ASSERT (try_statement.type == parser_try_block); + + if (context_p->token.type != LEXER_KEYW_CATCH && context_p->token.type != LEXER_KEYW_FINALLY) + { + parser_raise_error (context_p, PARSER_ERR_CATCH_FINALLY_EXPECTED); + } + } + } + + if (try_statement.type == parser_finally_block) + { + parser_stack_pop (context_p, NULL, (uint32_t) (sizeof (parser_try_statement_t) + 1)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + return; + } + + if (context_p->token.type == LEXER_KEYW_CATCH) + { + lexer_next_token (context_p); + + try_statement.type = parser_catch_block; + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_CATCH, &try_statement.branch); + + try_statement.scope_stack_top = context_p->scope_stack_top; + try_statement.scope_stack_reg_top = context_p->scope_stack_reg_top; + +#ifndef JERRY_NDEBUG + bool block_found = false; +#endif /* !JERRY_NDEBUG */ + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK); +#ifndef JERRY_NDEBUG + block_found = true; +#endif /* !JERRY_NDEBUG */ + + if (scanner_is_context_needed (context_p, PARSER_CHECK_BLOCK_CONTEXT)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV); + } + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + } + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE)) + { + parser_pattern_flags_t flags = (parser_pattern_flags_t) ((unsigned int) PARSER_PATTERN_BINDING | (unsigned int) PARSER_PATTERN_TARGET_ON_STACK | (unsigned int) PARSER_PATTERN_LET); + + parser_parse_initializer_by_next_char (context_p, flags); + } + else + { + lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL); + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + uint16_t literal_index = context_p->lit_object.index; + parser_emit_cbc_literal (context_p, + (literal_index >= PARSER_REGISTER_START) ? CBC_ASSIGN_SET_IDENT : CBC_ASSIGN_LET_CONST, + literal_index); + + lexer_next_token (context_p); + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (block_found); +#endif /* !JERRY_NDEBUG */ + } + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + } + else if (context_p->token.type == LEXER_LEFT_BRACE) + { + parser_emit_cbc (context_p, CBC_POP); + } + else + { + parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED); + } + + parser_flush_cbc (context_p); + } + else + { + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FINALLY); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + try_statement.type = parser_finally_block; + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_FINALLY, &try_statement.branch); + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK); + + if (scanner_is_context_needed (context_p, PARSER_CHECK_BLOCK_CONTEXT)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV); + } + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + } + } + + lexer_next_token (context_p); + parser_stack_iterator_write (&iterator, &try_statement, sizeof (parser_try_statement_t)); +} /* parser_parse_try_statement_end */ + +/** + * Parse default statement. + */ +static void +parser_parse_default_statement (parser_context_t *context_p) /**< context */ +{ + parser_stack_iterator_t iterator; + parser_switch_statement_t switch_statement; + + if (context_p->stack_top_uint8 != PARSER_STATEMENT_SWITCH + && context_p->stack_top_uint8 != PARSER_STATEMENT_SWITCH_NO_DEFAULT) + { + parser_raise_error (context_p, PARSER_ERR_DEFAULT_NOT_IN_SWITCH); + } + + lexer_next_token (context_p); + /* Already checked in parser_parse_switch_statement_start. */ + JERRY_ASSERT (context_p->token.type == LEXER_COLON); + lexer_next_token (context_p); + + parser_stack_iterator_init (context_p, &iterator); + parser_stack_iterator_skip (&iterator, 1 + sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + + parser_set_branch_to_current_position (context_p, &switch_statement.default_branch); +} /* parser_parse_default_statement */ + +/** + * Parse case statement. + */ +static void +parser_parse_case_statement (parser_context_t *context_p) /**< context */ +{ + parser_stack_iterator_t iterator; + parser_switch_statement_t switch_statement; + parser_branch_node_t *branch_p; + + if (context_p->stack_top_uint8 != PARSER_STATEMENT_SWITCH + && context_p->stack_top_uint8 != PARSER_STATEMENT_SWITCH_NO_DEFAULT) + { + parser_raise_error (context_p, PARSER_ERR_CASE_NOT_IN_SWITCH); + } + + if (context_p->next_scanner_info_p->source_p != context_p->source_p) + { + lexer_next_token (context_p); + + parser_parse_expression (context_p, PARSE_EXPR); + + JERRY_ASSERT (context_p->token.type != LEXER_COLON); + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_CASE); + + scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location); + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + scanner_seek (context_p); + lexer_next_token (context_p); + + parser_stack_iterator_init (context_p, &iterator); + parser_stack_iterator_skip (&iterator, 1 + sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + + /* Free memory after the case statement is found. */ + + branch_p = switch_statement.branch_list_p; + JERRY_ASSERT (branch_p != NULL); + switch_statement.branch_list_p = branch_p->next_p; + parser_stack_iterator_write (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + + parser_set_branch_to_current_position (context_p, &branch_p->branch); + parser_free (branch_p, sizeof (parser_branch_node_t)); +} /* parser_parse_case_statement */ + +/** + * Parse break statement. + */ +static void +parser_parse_break_statement (parser_context_t *context_p) /**< context */ +{ + parser_stack_iterator_t iterator; + cbc_opcode_t opcode = CBC_JUMP_FORWARD; + + lexer_next_token (context_p); + parser_stack_iterator_init (context_p, &iterator); + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + /* The label with the same name is searched on the stack. */ + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + if (type == PARSER_STATEMENT_START) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_BREAK_LABEL); + } + + if (parser_statement_flags[type] & PARSER_STATM_CONTEXT_BREAK) + { + opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT; + } + + if (type == PARSER_STATEMENT_LABEL) + { + parser_label_statement_t label_statement; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &label_statement, sizeof (parser_label_statement_t)); + + if (lexer_current_is_literal (context_p, &label_statement.label_ident)) + { + label_statement.break_list_p = + parser_emit_cbc_forward_branch_item (context_p, (uint16_t) opcode, label_statement.break_list_p); + parser_stack_iterator_write (&iterator, &label_statement, sizeof (parser_label_statement_t)); + lexer_next_token (context_p); + return; + } + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t)); + } + else + { + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + } + } + } + + /* The first switch or loop statement is searched. */ + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + if (type == PARSER_STATEMENT_START) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_BREAK); + } + + if (parser_statement_flags[type] & PARSER_STATM_CONTEXT_BREAK) + { + opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT; + } + + if (parser_statement_flags[type] & PARSER_STATM_BREAK_TARGET) + { + parser_loop_statement_t loop; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + loop.branch_list_p = parser_emit_cbc_forward_branch_item (context_p, (uint16_t) opcode, loop.branch_list_p); + parser_stack_iterator_write (&iterator, &loop, sizeof (parser_loop_statement_t)); + return; + } + + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + } +} /* parser_parse_break_statement */ + +/** + * Parse continue statement. + */ +static void +parser_parse_continue_statement (parser_context_t *context_p) /**< context */ +{ + parser_stack_iterator_t iterator; + cbc_opcode_t opcode = CBC_JUMP_FORWARD; + + lexer_next_token (context_p); + parser_stack_iterator_init (context_p, &iterator); + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + parser_stack_iterator_t loop_iterator; + + loop_iterator.current_p = NULL; + + /* The label with the same name is searched on the stack. */ + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + + if (type == PARSER_STATEMENT_START) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CONTINUE_LABEL); + } + + /* Only those labels are checked, whose are label of a loop. */ + if (loop_iterator.current_p != NULL && type == PARSER_STATEMENT_LABEL) + { + parser_label_statement_t label_statement; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &label_statement, sizeof (parser_label_statement_t)); + + if (lexer_current_is_literal (context_p, &label_statement.label_ident)) + { + parser_loop_statement_t loop; + + parser_stack_iterator_skip (&loop_iterator, 1); + parser_stack_iterator_read (&loop_iterator, &loop, sizeof (parser_loop_statement_t)); + loop.branch_list_p = parser_emit_cbc_forward_branch_item (context_p, (uint16_t) opcode, loop.branch_list_p); + loop.branch_list_p->branch.offset |= CBC_HIGHEST_BIT_MASK; + parser_stack_iterator_write (&loop_iterator, &loop, sizeof (parser_loop_statement_t)); + lexer_next_token (context_p); + return; + } + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t)); + continue; + } + + if (parser_statement_flags[type] & PARSER_STATM_CONTEXT_BREAK) + { + opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT; + } + + const bool is_private_scope = + (type == PARSER_STATEMENT_PRIVATE_SCOPE || type == PARSER_STATEMENT_PRIVATE_CONTEXT); + + if (parser_statement_flags[type] & PARSER_STATM_CONTINUE_TARGET) + { + loop_iterator = iterator; + } + else if (!is_private_scope) + { + loop_iterator.current_p = NULL; + } + + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + } + } + + /* The first loop statement is searched. */ + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + if (type == PARSER_STATEMENT_START) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CONTINUE); + } + + if (parser_statement_flags[type] & PARSER_STATM_CONTINUE_TARGET) + { + parser_loop_statement_t loop; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + loop.branch_list_p = parser_emit_cbc_forward_branch_item (context_p, (uint16_t) opcode, loop.branch_list_p); + loop.branch_list_p->branch.offset |= CBC_HIGHEST_BIT_MASK; + parser_stack_iterator_write (&iterator, &loop, sizeof (parser_loop_statement_t)); + return; + } + + if (parser_statement_flags[type] & PARSER_STATM_CONTEXT_BREAK) + { + opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT; + } + + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + } +} /* parser_parse_continue_statement */ + +#if JERRY_MODULE_SYSTEM +/** + * Parse import statement. + * Note: See 15.2.2 + */ +static void +parser_parse_import_statement (parser_context_t *context_p) /**< parser context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_IMPORT); + JERRY_ASSERT (context_p->module_names_p == NULL); + + if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_PAREN, LIT_CHAR_DOT)) + { + if (context_p->status_flags & PARSER_IS_FUNCTION) + { + parser_parse_expression_statement (context_p, PARSE_EXPR); + return; + } + + parser_parse_block_expression (context_p, PARSE_EXPR); + return; + } + + parser_module_check_request_place (context_p); + lexer_next_token (context_p); + + /* Check for a ModuleSpecifier*/ + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_STRING_LITERAL) + { + if (!(context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_MULTIPLY + || (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL))) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED); + } + + if (context_p->token.type == LEXER_LITERAL) + { + /* Handle ImportedDefaultBinding */ + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL); + + ecma_string_t *local_name_p = parser_new_ecma_string_from_literal (context_p->lit_object.literal_p); + + if (parser_module_check_duplicate_import (context_p, local_name_p)) + { + ecma_deref_ecma_string (local_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_IMPORT_BINDING); + } + + ecma_string_t *import_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_DEFAULT); + parser_module_add_names_to_node (context_p, import_name_p, local_name_p); + + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (import_name_p); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + if (context_p->token.type != LEXER_MULTIPLY && context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_EXPECTED); + } + } + else if (!lexer_token_is_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_FROM_COMMA_EXPECTED); + } + } + + if (context_p->token.type == LEXER_MULTIPLY) + { + /* NameSpaceImport */ + lexer_next_token (context_p); + if (!lexer_token_is_identifier (context_p, "as", 2)) + { + parser_raise_error (context_p, PARSER_ERR_AS_EXPECTED); + } + + lexer_next_token (context_p); + if (context_p->token.type != LEXER_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL); + + ecma_string_t *local_name_p = parser_new_ecma_string_from_literal (context_p->lit_object.literal_p); + + if (parser_module_check_duplicate_import (context_p, local_name_p)) + { + ecma_deref_ecma_string (local_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_IMPORT_BINDING); + } + + ecma_string_t *import_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR); + + parser_module_add_names_to_node (context_p, import_name_p, local_name_p); + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (import_name_p); + + lexer_next_token (context_p); + } + else if (context_p->token.type == LEXER_LEFT_BRACE) + { + /* Handle NamedImports */ + parser_module_parse_import_clause (context_p); + } + + if (!lexer_token_is_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED); + } + lexer_next_token (context_p); + } + + parser_module_handle_module_specifier (context_p, NULL); +} /* parser_parse_import_statement */ + +/** + * Parse export statement. + * + * @return true - if function of class statement was found + * false - otherwise + */ +static bool +parser_parse_export_statement (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_EXPORT); + JERRY_ASSERT (context_p->module_names_p == NULL); + + parser_module_check_request_place (context_p); + + bool consume_last_statement = false; + + lexer_next_token (context_p); + switch (context_p->token.type) + { + case LEXER_KEYW_DEFAULT: + { + scanner_location_t location; + scanner_get_location (&location, context_p); + + context_p->status_flags |= PARSER_MODULE_STORE_IDENT; + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LITERAL && lexer_token_is_async (context_p) + && context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION) + { +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = context_p->token.lit_location.char_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + lexer_next_token (context_p); + } + + if (context_p->token.type == LEXER_KEYW_CLASS) + { + context_p->status_flags |= PARSER_MODULE_DEFAULT_CLASS_OR_FUNC; + parser_parse_class (context_p, true); + consume_last_statement = true; + } + else if (context_p->token.type == LEXER_KEYW_FUNCTION) + { + context_p->status_flags |= PARSER_MODULE_DEFAULT_CLASS_OR_FUNC; + parser_parse_function_statement (context_p); + consume_last_statement = true; + } + else + { + /* Assignment expression */ + scanner_set_location (context_p, &location); + + /* 15.2.3.5 Use the synthetic name '*default*' as the identifier. */ + lexer_construct_literal_object (context_p, &lexer_default_literal, lexer_default_literal.type); + + context_p->token.lit_location.type = LEXER_IDENT_LITERAL; + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + + /* Do not overwrite this identifier. */ + context_p->status_flags &= (uint32_t) ~PARSER_MODULE_STORE_IDENT; + context_p->module_identifier_lit_p = context_p->lit_object.literal_p; + + /* Fake an assignment to the default identifier */ + context_p->token.type = LEXER_ASSIGN; + + parser_parse_expression_statement (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_HAS_LITERAL); + } + + ecma_string_t *name_p = parser_new_ecma_string_from_literal (context_p->module_identifier_lit_p); + + ecma_string_t *export_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_DEFAULT); + + if (parser_module_check_duplicate_export (context_p, export_name_p)) + { + ecma_deref_ecma_string (name_p); + ecma_deref_ecma_string (export_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER); + } + + parser_module_add_names_to_node (context_p, export_name_p, name_p); + ecma_deref_ecma_string (name_p); + ecma_deref_ecma_string (export_name_p); + break; + } + case LEXER_MULTIPLY: + { + lexer_next_token (context_p); + + ecma_module_node_t **target_node_list_p = &(JERRY_CONTEXT (module_current_p)->star_exports_p); + + if (lexer_token_is_identifier (context_p, "as", 2)) + { + target_node_list_p = &(JERRY_CONTEXT (module_current_p)->indirect_exports_p); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + + lexer_literal_t *literal_p = PARSER_GET_LITERAL (context_p->lit_object.index); + ecma_string_t *export_name_p = parser_new_ecma_string_from_literal (literal_p); + + if (parser_module_check_duplicate_export (context_p, export_name_p)) + { + ecma_deref_ecma_string (export_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER); + } + + ecma_string_t *local_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR); + parser_module_add_names_to_node (context_p, export_name_p, local_name_p); + ecma_deref_ecma_string (export_name_p); + + lexer_next_token (context_p); + } + + if (!lexer_token_is_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED); + } + + lexer_next_token (context_p); + parser_module_handle_module_specifier (context_p, target_node_list_p); + return false; + } + case LEXER_KEYW_VAR: + case LEXER_KEYW_LET: + case LEXER_KEYW_CONST: + { + context_p->status_flags |= PARSER_MODULE_STORE_IDENT; + parser_parse_var_statement (context_p); + break; + } + case LEXER_KEYW_CLASS: + { + context_p->status_flags |= PARSER_MODULE_STORE_IDENT; + parser_parse_class (context_p, true); + consume_last_statement = true; + break; + } + case LEXER_KEYW_FUNCTION: + { + context_p->status_flags |= PARSER_MODULE_STORE_IDENT; + parser_parse_function_statement (context_p); + consume_last_statement = true; + break; + } + case LEXER_LEFT_BRACE: + { + parser_module_parse_export_clause (context_p); + + if (lexer_token_is_identifier (context_p, "from", 4)) + { + lexer_next_token (context_p); + parser_module_handle_module_specifier (context_p, &(JERRY_CONTEXT (module_current_p)->indirect_exports_p)); + return false; + } + break; + } + default: + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED); + break; + } + } + + context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC | PARSER_MODULE_STORE_IDENT); + parser_module_append_names (context_p, &(JERRY_CONTEXT (module_current_p)->local_exports_p)); + + return consume_last_statement; +} /* parser_parse_export_statement */ +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * Parse label statement. + */ +static void +parser_parse_label (parser_context_t *context_p) /**< context */ +{ + parser_stack_iterator_t iterator; + parser_label_statement_t label_statement; + + parser_stack_iterator_init (context_p, &iterator); + + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + if (type == PARSER_STATEMENT_START) + { + break; + } + + if (type == PARSER_STATEMENT_LABEL) + { + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &label_statement, sizeof (parser_label_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t)); + + if (lexer_current_is_literal (context_p, &label_statement.label_ident)) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_LABEL); + } + } + else + { + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + } + } + + label_statement.label_ident = context_p->token.lit_location; + label_statement.break_list_p = NULL; + parser_stack_push (context_p, &label_statement, sizeof (parser_label_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_LABEL); + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_parse_label */ + +/** + * Strict mode types for statement parsing. + */ +typedef enum +{ + PARSER_USE_STRICT_NOT_FOUND = 0, /**< 'use strict' directive is not found */ + PARSER_USE_STRICT_FOUND = 1, /**< 'use strict' directive is found but strict mode has already been enabled */ + PARSER_USE_STRICT_SET = 2, /**< strict mode is enabled after 'use strict' directive is found */ +} parser_strict_mode_type_t; + +/** + * Parse statements. + */ +void +parser_parse_statements (parser_context_t *context_p) /**< context */ +{ + /* Statement parsing cannot be nested. */ + JERRY_ASSERT (context_p->last_statement.current_p == NULL); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_START); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + while (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + lexer_lit_location_t lit_location; + parser_strict_mode_type_t strict_mode = PARSER_USE_STRICT_NOT_FOUND; + + JERRY_ASSERT (context_p->stack_depth <= 1); +#ifndef JERRY_NDEBUG + JERRY_ASSERT (context_p->context_stack_depth == context_p->stack_depth); +#endif /* !JERRY_NDEBUG */ + + if (lexer_string_is_use_strict (context_p)) + { + strict_mode = PARSER_USE_STRICT_FOUND; + + if (!(context_p->status_flags & PARSER_IS_STRICT)) + { + /* The next token should be parsed in strict mode. */ + context_p->status_flags |= PARSER_IS_STRICT; + strict_mode = PARSER_USE_STRICT_SET; + } + } + + lit_location = context_p->token.lit_location; + lexer_next_token (context_p); + + if (!lexer_string_is_directive (context_p)) + { + /* The string is part of an expression statement. */ + if (strict_mode == PARSER_USE_STRICT_SET) + { + context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT; + } + +#if JERRY_LINE_INFO + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); +#endif /* JERRY_LINE_INFO */ + + lexer_construct_literal_object (context_p, &lit_location, LEXER_STRING_LITERAL); + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + /* The extra_value is used for saving the token. */ + context_p->token.extra_value = context_p->token.type; + context_p->token.type = LEXER_EXPRESSION_START; + break; + } + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (strict_mode == PARSER_USE_STRICT_SET && context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG (" Note: switch to strict mode\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + if (strict_mode != PARSER_USE_STRICT_NOT_FOUND && (context_p->status_flags & PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT)) + { + parser_raise_error (context_p, PARSER_ERR_USE_STRICT_NOT_ALLOWED); + } + + if (context_p->token.type == LEXER_SEMICOLON) + { + lexer_next_token (context_p); + } + + /* The last directive prologue can be the result of the script. */ + if (!(context_p->status_flags & PARSER_IS_FUNCTION) + && (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_STRING_LITERAL)) + { + lexer_construct_literal_object (context_p, &lit_location, LEXER_STRING_LITERAL); + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + parser_emit_cbc (context_p, CBC_POP_BLOCK); + parser_flush_cbc (context_p); + break; + } + } + + if (context_p->status_flags & PARSER_IS_STRICT && context_p->status_flags & PARSER_HAS_NON_STRICT_ARG) + { + parser_raise_error (context_p, PARSER_ERR_NON_STRICT_ARG_DEFINITION); + } + + while (context_p->token.type != LEXER_EOS || context_p->stack_top_uint8 != PARSER_STATEMENT_START) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (context_p->stack_depth == context_p->context_stack_depth); +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (context_p->stack_top_uint8 != PARSER_STATEMENT_PRIVATE_SCOPE + && context_p->stack_top_uint8 != PARSER_STATEMENT_PRIVATE_CONTEXT); + +#if JERRY_LINE_INFO + if (context_p->token.type != LEXER_SEMICOLON && context_p->token.type != LEXER_LEFT_BRACE + && context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_KEYW_VAR + && context_p->token.type != LEXER_KEYW_LET && context_p->token.type != LEXER_KEYW_CONST + && context_p->token.type != LEXER_KEYW_FUNCTION && context_p->token.type != LEXER_KEYW_CASE + && context_p->token.type != LEXER_KEYW_DEFAULT) + { + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); + } +#endif /* JERRY_LINE_INFO */ + + switch (context_p->token.type) + { + case LEXER_SEMICOLON: + { + break; + } + + case LEXER_RIGHT_BRACE: + { + if (parser_statement_flags[context_p->stack_top_uint8] & PARSER_STATM_SINGLE_STATM) + { + parser_raise_error (context_p, PARSER_ERR_STATEMENT_EXPECTED); + } + break; + } + + case LEXER_LEFT_BRACE: + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + parser_push_block_context (context_p, false); + } + else + { + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_BLOCK); + } + + parser_stack_iterator_init (context_p, &context_p->last_statement); + lexer_next_token (context_p); + continue; + } + + case LEXER_KEYW_VAR: + case LEXER_KEYW_LET: + case LEXER_KEYW_CONST: + { + parser_parse_var_statement (context_p); + break; + } + case LEXER_KEYW_CLASS: + { + parser_validate_lexical_context (context_p); + parser_parse_class (context_p, true); + goto consume_last_statement; + } +#if JERRY_MODULE_SYSTEM + case LEXER_KEYW_IMPORT: + { + parser_parse_import_statement (context_p); + break; + } + + case LEXER_KEYW_EXPORT: + { + if (parser_parse_export_statement (context_p)) + { + goto consume_last_statement; + } + break; + } +#endif /* JERRY_MODULE_SYSTEM */ + + case LEXER_KEYW_FUNCTION: + { + parser_parse_function_statement (context_p); + goto consume_last_statement; + } + + case LEXER_KEYW_IF: + { + parser_parse_if_statement_start (context_p); + continue; + } + + case LEXER_KEYW_SWITCH: + { + parser_parse_switch_statement_start (context_p); + continue; + } + + case LEXER_KEYW_DO: + { + parser_do_while_statement_t do_while_statement; + parser_loop_statement_t loop; + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + do_while_statement.start_offset = context_p->byte_code_size; + loop.branch_list_p = NULL; + + parser_stack_push (context_p, &do_while_statement, sizeof (parser_do_while_statement_t)); + parser_stack_push (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_DO_WHILE); + parser_stack_iterator_init (context_p, &context_p->last_statement); + lexer_next_token (context_p); + continue; + } + + case LEXER_KEYW_WHILE: + { + parser_parse_while_statement_start (context_p); + continue; + } + + case LEXER_KEYW_FOR: + { + parser_parse_for_statement_start (context_p); + continue; + } + + case LEXER_KEYW_WITH: + { + parser_parse_with_statement_start (context_p); + continue; + } + + case LEXER_KEYW_TRY: + { + parser_try_statement_t try_statement; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + try_statement.type = parser_try_block; + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_TRY_CREATE_CONTEXT, &try_statement.branch); + + try_statement.scope_stack_top = context_p->scope_stack_top; + try_statement.scope_stack_reg_top = context_p->scope_stack_reg_top; + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK); + + if (scanner_is_context_needed (context_p, PARSER_CHECK_BLOCK_CONTEXT)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV); + } + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + } + + parser_stack_push (context_p, &try_statement, sizeof (parser_try_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_TRY); + parser_stack_iterator_init (context_p, &context_p->last_statement); + lexer_next_token (context_p); + continue; + } + + case LEXER_KEYW_DEFAULT: + { + parser_parse_default_statement (context_p); + continue; + } + + case LEXER_KEYW_CASE: + { + parser_parse_case_statement (context_p); + continue; + } + + case LEXER_KEYW_BREAK: + { + parser_parse_break_statement (context_p); + break; + } + + case LEXER_KEYW_CONTINUE: + { + parser_parse_continue_statement (context_p); + break; + } + + case LEXER_KEYW_THROW: + { + lexer_next_token (context_p); + if (context_p->token.flags & LEXER_WAS_NEWLINE) + { + parser_raise_error (context_p, PARSER_ERR_EXPRESSION_EXPECTED); + } + parser_parse_expression (context_p, PARSE_EXPR); + parser_emit_cbc (context_p, CBC_THROW); + break; + } + + case LEXER_KEYW_RETURN: + { + if (!(context_p->status_flags & PARSER_IS_FUNCTION)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_RETURN); + } + if (context_p->status_flags & PARSER_IS_CLASS_STATIC_BLOCK) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_RETURN); + } + + lexer_next_token (context_p); + + if ((context_p->token.flags & LEXER_WAS_NEWLINE) || context_p->token.type == LEXER_SEMICOLON + || context_p->token.type == LEXER_EOS || context_p->token.type == LEXER_RIGHT_BRACE) + { + if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) + { + parser_emit_cbc_ext (context_p, CBC_EXT_RETURN_UNDEFINED); + break; + } + + parser_emit_cbc (context_p, CBC_RETURN_FUNCTION_END); + break; + } + + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = CBC_RETURN_WITH_LITERAL; + break; + } + + parser_emit_cbc (context_p, CBC_RETURN); + break; + } + + case LEXER_KEYW_DEBUGGER: + { + lexer_next_token (context_p); + break; + } + + case LEXER_LITERAL: + { + if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + if (JERRY_UNLIKELY (lexer_check_next_character (context_p, LIT_CHAR_COLON))) + { + parser_parse_label (context_p); + lexer_consume_next_character (context_p); + lexer_next_token (context_p); + continue; + } + + if (JERRY_UNLIKELY (lexer_token_is_let (context_p))) + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION) + { + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + + if (context_p->status_flags & PARSER_IS_FUNCTION) + { + parser_parse_expression_statement (context_p, PARSE_EXPR); + break; + } + + parser_parse_block_expression (context_p, PARSE_EXPR); + break; + } + + context_p->token.type = LEXER_KEYW_LET; + parser_parse_var_statement (context_p); + break; + } + + if (JERRY_UNLIKELY (lexer_token_is_async (context_p)) + && context_p->next_scanner_info_p->source_p == context_p->source_p) + { + bool is_statement = true; + + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION) + { + is_statement = (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_STATEMENT) != 0; + + JERRY_ASSERT (!is_statement || (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC)); + } + else + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_ASYNC_FUNCTION); + + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + + if (is_statement) + { + if (parser_statement_flags[context_p->stack_top_uint8] & PARSER_STATM_SINGLE_STATM) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_SINGLE_STATEMENT); + } + +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = context_p->token.lit_location.char_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + lexer_next_token (context_p); + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FUNCTION); + continue; + } + } + } + /* FALLTHRU */ + } + + default: + { + int options = PARSE_EXPR; + + if (context_p->token.type == LEXER_EXPRESSION_START) + { + /* Restore the token type form the extra_value. */ + context_p->token.type = context_p->token.extra_value; + options |= PARSE_EXPR_HAS_LITERAL; + } + + if (context_p->status_flags & PARSER_IS_FUNCTION) + { + parser_parse_expression_statement (context_p, options); + } + else + { + parser_parse_block_expression (context_p, options); + } + + break; + } + } + + parser_flush_cbc (context_p); + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + if (context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK) + { + parser_stack_pop_uint8 (context_p); + parser_stack_iterator_init (context_p, &context_p->last_statement); + lexer_next_token (context_p); + } + else if (context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK_CONTEXT) + { + parser_pop_block_context (context_p); + lexer_next_token (context_p); + } + else if (context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH + || context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH_NO_DEFAULT) + { + int has_default = (context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH); + parser_loop_statement_t loop; + parser_switch_statement_t switch_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_pop (context_p, &switch_statement, sizeof (parser_switch_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + JERRY_ASSERT (switch_statement.branch_list_p == NULL); + + if (!has_default) + { + parser_set_branch_to_current_position (context_p, &switch_statement.default_branch); + } + + parser_set_breaks_to_current_position (context_p, loop.branch_list_p); + lexer_next_token (context_p); + + if (context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_CONTEXT) + { + parser_pop_block_context (context_p); + } + } + else if (context_p->stack_top_uint8 == PARSER_STATEMENT_TRY) + { + parser_parse_try_statement_end (context_p); + } + else if (context_p->stack_top_uint8 == PARSER_STATEMENT_START) + { + if (context_p->status_flags & PARSER_IS_CLOSURE) + { +#if JERRY_LINE_INFO + if (context_p->line_info_p == NULL) + { + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); + } +#endif /* JERRY_LINE_INFO */ + +#if JERRY_FUNCTION_TO_STRING + context_p->function_end_p = context_p->source_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + + parser_stack_pop_uint8 (context_p); + context_p->last_statement.current_p = NULL; + /* There is no lexer_next_token here, since the + * next token belongs to the parent context. */ + return; + } + parser_raise_error (context_p, PARSER_ERR_INVALID_RIGHT_SQUARE); + } + } + else if (context_p->token.type == LEXER_SEMICOLON) + { + lexer_next_token (context_p); + } + else if (context_p->token.type != LEXER_EOS && !(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + +consume_last_statement: + while (true) + { + switch (context_p->stack_top_uint8) + { + case PARSER_STATEMENT_LABEL: + { + parser_label_statement_t label; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &label, sizeof (parser_label_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_set_breaks_to_current_position (context_p, label.break_list_p); + continue; + } + + case PARSER_STATEMENT_IF: + { + if (parser_parse_if_statement_end (context_p)) + { + break; + } + continue; + } + + case PARSER_STATEMENT_ELSE: + { + parser_if_else_statement_t else_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &else_statement, sizeof (parser_if_else_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_set_branch_to_current_position (context_p, &else_statement.branch); + continue; + } + + case PARSER_STATEMENT_DO_WHILE: + { + parser_parse_do_while_statement_end (context_p); + if (context_p->token.type == LEXER_SEMICOLON) + { + lexer_next_token (context_p); + } + continue; + } + + case PARSER_STATEMENT_WHILE: + { + parser_parse_while_statement_end (context_p); + continue; + } + + case PARSER_STATEMENT_FOR: + { + parser_parse_for_statement_end (context_p); + continue; + } + + case PARSER_STATEMENT_FOR_IN: + case PARSER_STATEMENT_FOR_OF: + case PARSER_STATEMENT_FOR_AWAIT_OF: + { + parser_for_in_of_statement_t for_in_of_statement; + parser_loop_statement_t loop; + + uint8_t for_type = context_p->stack_top_uint8; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_pop (context_p, &for_in_of_statement, sizeof (parser_for_in_of_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_set_continues_to_current_position (context_p, loop.branch_list_p); + + parser_flush_cbc (context_p); + + uint16_t stack_allocation = PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION; + if (for_type != PARSER_STATEMENT_FOR_IN) + { + stack_allocation = (for_type == PARSER_STATEMENT_FOR_OF ? PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION + : PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION); + } + + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, stack_allocation); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, stack_allocation); +#endif /* !JERRY_NDEBUG */ + + cbc_ext_opcode_t opcode = CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT; + + if (for_type != PARSER_STATEMENT_FOR_IN) + { + opcode = (for_type == PARSER_STATEMENT_FOR_OF ? CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT + : CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT); + } + + parser_emit_cbc_ext_backward_branch (context_p, opcode, for_in_of_statement.start_offset); + + parser_set_breaks_to_current_position (context_p, loop.branch_list_p); + parser_set_branch_to_current_position (context_p, &for_in_of_statement.branch); + + if (context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_CONTEXT) + { + parser_pop_block_context (context_p); + } + + continue; + } + + case PARSER_STATEMENT_WITH: + { + parser_parse_with_statement_end (context_p); + continue; + } + + default: + { + break; + } + } + break; + } + } + + parser_stack_pop_uint8 (context_p); + context_p->last_statement.current_p = NULL; + + if (context_p->status_flags & PARSER_IS_CLOSURE) + { + parser_raise_error (context_p, PARSER_ERR_STATEMENT_EXPECTED); + } + +#if JERRY_LINE_INFO + if (context_p->line_info_p == NULL) + { + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); + } +#endif /* JERRY_LINE_INFO */ +} /* parser_parse_statements */ + +/** + * Free jumps stored on the stack if a parse error is occurred. + */ +void JERRY_ATTR_NOINLINE +parser_free_jumps (parser_stack_iterator_t iterator) /**< iterator position */ +{ + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + parser_branch_node_t *branch_list_p = NULL; + + switch (type) + { + case PARSER_STATEMENT_START: + { + return; + } + + case PARSER_STATEMENT_LABEL: + { + parser_label_statement_t label; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &label, sizeof (parser_label_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t)); + branch_list_p = label.break_list_p; + break; + } + + case PARSER_STATEMENT_SWITCH: + case PARSER_STATEMENT_SWITCH_NO_DEFAULT: + { + parser_switch_statement_t switch_statement; + parser_loop_statement_t loop; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_switch_statement_t)); + + branch_list_p = switch_statement.branch_list_p; + while (branch_list_p != NULL) + { + parser_branch_node_t *next_p = branch_list_p->next_p; + parser_free (branch_list_p, sizeof (parser_branch_node_t)); + branch_list_p = next_p; + } + branch_list_p = loop.branch_list_p; + break; + } + + case PARSER_STATEMENT_DO_WHILE: + case PARSER_STATEMENT_WHILE: + case PARSER_STATEMENT_FOR: + case PARSER_STATEMENT_FOR_IN: + case PARSER_STATEMENT_FOR_OF: + { + parser_loop_statement_t loop; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + parser_stack_iterator_skip (&iterator, parser_statement_length (type) - 1); + branch_list_p = loop.branch_list_p; + break; + } + + default: + { + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + continue; + } + } + + while (branch_list_p != NULL) + { + parser_branch_node_t *next_p = branch_list_p->next_p; + parser_free (branch_list_p, sizeof (parser_branch_node_t)); + branch_list_p = next_p; + } + } +} /* parser_free_jumps */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.cpp new file mode 100644 index 00000000..f2ce91ec --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.cpp @@ -0,0 +1,161 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-tagged-template-literal.h" + +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "js-lexer.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_tagged_template_literal Tagged template literal + * @{ + */ + +/** + * Append the cooked and raw string to the corresponding array + */ +void +parser_tagged_template_literal_append_strings (parser_context_t *context_p, /**< parser context */ + ecma_object_t *template_obj_p, /**< template object */ + ecma_object_t *raw_strings_p, /**< raw strings object */ + uint32_t prop_idx) /**< property index to set the values */ +{ + lexer_lit_location_t *lit_loc_p = &context_p->token.lit_location; + + if (lit_loc_p->length == 0 && !(lit_loc_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + ecma_builtin_helper_def_prop_by_index (template_obj_p, + prop_idx, + ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY), + ECMA_PROPERTY_FLAG_ENUMERABLE); + + ecma_builtin_helper_def_prop_by_index (raw_strings_p, + prop_idx, + ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY), + ECMA_PROPERTY_FLAG_ENUMERABLE); + return; + } + + uint8_t local_byte_array[LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE]; + const uint8_t *source_p = + lexer_convert_literal_to_chars (context_p, &context_p->token.lit_location, local_byte_array, LEXER_STRING_NO_OPTS); + + ecma_string_t *raw_str_p; + ecma_string_t *cooked_str_p = + ((lit_loc_p->status_flags & LEXER_FLAG_ASCII) ? ecma_new_ecma_string_from_ascii (source_p, lit_loc_p->length) + : ecma_new_ecma_string_from_utf8 (source_p, lit_loc_p->length)); + + parser_free_allocated_buffer (context_p); + + if (lit_loc_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE) + { + context_p->source_p = context_p->token.lit_location.char_p - 1; + lexer_parse_string (context_p, LEXER_STRING_RAW); + source_p = + lexer_convert_literal_to_chars (context_p, &context_p->token.lit_location, local_byte_array, LEXER_STRING_RAW); + + raw_str_p = + ((lit_loc_p->status_flags & LEXER_FLAG_ASCII) ? ecma_new_ecma_string_from_ascii (source_p, lit_loc_p->length) + : ecma_new_ecma_string_from_utf8 (source_p, lit_loc_p->length)); + + parser_free_allocated_buffer (context_p); + } + else + { + ecma_ref_ecma_string (cooked_str_p); + raw_str_p = cooked_str_p; + } + + ecma_builtin_helper_def_prop_by_index (template_obj_p, + prop_idx, + ecma_make_string_value (cooked_str_p), + ECMA_PROPERTY_FLAG_ENUMERABLE); + + ecma_builtin_helper_def_prop_by_index (raw_strings_p, + prop_idx, + ecma_make_string_value (raw_str_p), + ECMA_PROPERTY_FLAG_ENUMERABLE); + + ecma_deref_ecma_string (cooked_str_p); + ecma_deref_ecma_string (raw_str_p); +} /* parser_tagged_template_literal_append_strings */ + +/** + * Create new tagged template literal object + * + * @return pointer to the allocated object + */ +ecma_object_t * +parser_new_tagged_template_literal (ecma_object_t **raw_strings_p) /**< [out] raw strings object */ +{ + ecma_object_t *template_obj_p = ecma_op_new_array_object (0); + *raw_strings_p = ecma_op_new_array_object (0); + + ecma_extended_object_t *template_ext_obj_p = (ecma_extended_object_t *) template_obj_p; + ecma_extended_object_t *raw_ext_obj_p = (ecma_extended_object_t *) *raw_strings_p; + + const uint8_t flags = ECMA_PROPERTY_VIRTUAL | ECMA_PROPERTY_FLAG_WRITABLE | ECMA_FAST_ARRAY_FLAG; + JERRY_ASSERT (template_ext_obj_p->u.array.length_prop_and_hole_count == flags); + JERRY_ASSERT (raw_ext_obj_p->u.array.length_prop_and_hole_count == flags); + + template_ext_obj_p->u.array.length_prop_and_hole_count = flags | ECMA_ARRAY_TEMPLATE_LITERAL; + raw_ext_obj_p->u.array.length_prop_and_hole_count = flags | ECMA_ARRAY_TEMPLATE_LITERAL; + + ecma_builtin_helper_def_prop (template_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_RAW), + ecma_make_object_value (*raw_strings_p), + ECMA_PROPERTY_FIXED); + + return template_obj_p; +} /* parser_new_tagged_template_literal */ + +/** + * Set integrity level of the given template array object to "frozen" + */ +static void +parser_tagged_template_literal_freeze_array (ecma_object_t *obj_p /**< template object */) +{ + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); + ecma_op_ordinary_object_prevent_extensions (obj_p); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + ext_obj_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_PROPERTY_FLAG_WRITABLE; +} /* parser_tagged_template_literal_freeze_array */ + +/** + * Finalize the tagged template object + */ +void +parser_tagged_template_literal_finalize (ecma_object_t *template_obj_p, /**< template object */ + ecma_object_t *raw_strings_p) /**< raw strings object */ +{ + parser_tagged_template_literal_freeze_array (template_obj_p); + parser_tagged_template_literal_freeze_array (raw_strings_p); +} /* parser_tagged_template_literal_finalize */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.h new file mode 100644 index 00000000..919cc1b5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.h @@ -0,0 +1,49 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_TAGGED_TEMPLATE_LITERAL_H +#define ECMA_TAGGED_TEMPLATE_LITERAL_H + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_tagged_template_literal Tagged template literal + * @{ + */ + +#include "ecma-globals.h" + +#include "common.h" +#include "js-parser-internal.h" + +ecma_object_t *parser_new_tagged_template_literal (ecma_object_t **raw_strings_p); + +void parser_tagged_template_literal_append_strings (parser_context_t *context_p, + ecma_object_t *template_obj_p, + ecma_object_t *raw_strings_p, + uint32_t prop_index); + +void parser_tagged_template_literal_finalize (ecma_object_t *template_obj_p, ecma_object_t *raw_strings_p); + +/** + * @} + * @} + * @} + */ + +#endif /* ECMA_TAGGED_TEMPLATE_LITERAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-util.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-util.cpp new file mode 100644 index 00000000..c3ba131d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-util.cpp @@ -0,0 +1,874 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-helpers.h" + +#include "js-parser-internal.h" + +#if JERRY_PARSER + +#if JERRY_LINE_INFO +#include "jcontext.h" +#endif /* JERRY_LINE_INFO */ + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_utils Utility + * @{ + */ + +/**********************************************************************/ +/* Emitting byte codes */ +/**********************************************************************/ + +/** + * Append two bytes to the cbc stream. + */ +static void +parser_emit_two_bytes (parser_context_t *context_p, /**< context */ + uint8_t first_byte, /**< first byte */ + uint8_t second_byte) /**< second byte */ +{ + uint32_t last_position = context_p->byte_code.last_position; + + if (last_position + 2 <= PARSER_CBC_STREAM_PAGE_SIZE) + { + parser_mem_page_t *page_p = context_p->byte_code.last_p; + + page_p->bytes[last_position] = first_byte; + page_p->bytes[last_position + 1] = second_byte; + context_p->byte_code.last_position = last_position + 2; + } + else if (last_position >= PARSER_CBC_STREAM_PAGE_SIZE) + { + parser_mem_page_t *page_p; + + parser_cbc_stream_alloc_page (context_p, &context_p->byte_code); + page_p = context_p->byte_code.last_p; + page_p->bytes[0] = first_byte; + page_p->bytes[1] = second_byte; + context_p->byte_code.last_position = 2; + } + else + { + context_p->byte_code.last_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] = first_byte; + parser_cbc_stream_alloc_page (context_p, &context_p->byte_code); + context_p->byte_code.last_p->bytes[0] = second_byte; + context_p->byte_code.last_position = 1; + } +} /* parser_emit_two_bytes */ + +/** + * Append byte to the end of the current byte code stream. + * + * @param context_p parser context + * @param byte byte + */ +#define PARSER_APPEND_TO_BYTE_CODE(context_p, byte) \ + if ((context_p)->byte_code.last_position >= PARSER_CBC_STREAM_PAGE_SIZE) \ + { \ + parser_cbc_stream_alloc_page ((context_p), &(context_p)->byte_code); \ + } \ + (context_p)->byte_code.last_p->bytes[(context_p)->byte_code.last_position++] = (uint8_t) (byte) + +#if JERRY_PARSER_DUMP_BYTE_CODE + +/** + * Print literal corresponding to the current index + */ +static void +parser_print_literal (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< index of literal */ +{ + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p; + parser_scope_stack_t *scope_stack_end_p = scope_stack_p + context_p->scope_stack_top; + bool in_scope_literal = false; + + while (scope_stack_p < scope_stack_end_p) + { + scope_stack_end_p--; + + if (scope_stack_end_p->map_from == PARSER_SCOPE_STACK_FUNC) + { + if (literal_index == scope_stack_end_p->map_to) + { + in_scope_literal = true; + break; + } + } + else if (literal_index == scanner_decode_map_to (scope_stack_end_p)) + { + in_scope_literal = true; + break; + } + } + + if (literal_index < PARSER_REGISTER_START) + { + JERRY_DEBUG_MSG (in_scope_literal ? " IDX:%d->" : " idx:%d->", literal_index); + lexer_literal_t *literal_p = PARSER_GET_LITERAL (literal_index); + util_print_literal (literal_p); + return; + } + + if (!in_scope_literal) + { + JERRY_DEBUG_MSG (" reg:%d", (int) (literal_index - PARSER_REGISTER_START)); + return; + } + + JERRY_DEBUG_MSG (" REG:%d->", (int) (literal_index - PARSER_REGISTER_START)); + + lexer_literal_t *literal_p = PARSER_GET_LITERAL (scope_stack_end_p->map_from); + util_print_literal (literal_p); +} /* parser_print_literal */ + +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * Append the current byte code to the stream + */ +void +parser_flush_cbc (parser_context_t *context_p) /**< context */ +{ + uint8_t flags; + uint16_t last_opcode = context_p->last_cbc_opcode; + + if (last_opcode == PARSER_CBC_UNAVAILABLE) + { + return; + } + + context_p->status_flags |= PARSER_NO_END_LABEL; + + if (PARSER_IS_BASIC_OPCODE (last_opcode)) + { + cbc_opcode_t opcode = (cbc_opcode_t) last_opcode; + + JERRY_ASSERT (opcode < CBC_END); + flags = cbc_flags[opcode]; + + PARSER_APPEND_TO_BYTE_CODE (context_p, opcode); + context_p->byte_code_size++; + } + else + { + cbc_ext_opcode_t opcode = (cbc_ext_opcode_t) PARSER_GET_EXT_OPCODE (last_opcode); + + JERRY_ASSERT (opcode < CBC_EXT_END); + flags = cbc_ext_flags[opcode]; + parser_emit_two_bytes (context_p, CBC_EXT_OPCODE, (uint8_t) opcode); + context_p->byte_code_size += 2; + } + + JERRY_ASSERT ((flags >> CBC_STACK_ADJUST_SHIFT) >= CBC_STACK_ADJUST_BASE + || (CBC_STACK_ADJUST_BASE - (flags >> CBC_STACK_ADJUST_SHIFT)) <= context_p->stack_depth); + PARSER_PLUS_EQUAL_U16 (context_p->stack_depth, CBC_STACK_ADJUST_VALUE (flags)); + + if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)) + { + uint16_t literal_index = context_p->last_cbc.literal_index; + + parser_emit_two_bytes (context_p, (uint8_t) (literal_index & 0xff), (uint8_t) (literal_index >> 8)); + context_p->byte_code_size += 2; + } + + if (flags & CBC_HAS_LITERAL_ARG2) + { + uint16_t literal_index = context_p->last_cbc.value; + + parser_emit_two_bytes (context_p, (uint8_t) (literal_index & 0xff), (uint8_t) (literal_index >> 8)); + context_p->byte_code_size += 2; + + if (!(flags & CBC_HAS_LITERAL_ARG)) + { + literal_index = context_p->last_cbc.third_literal_index; + + parser_emit_two_bytes (context_p, (uint8_t) (literal_index & 0xff), (uint8_t) (literal_index >> 8)); + context_p->byte_code_size += 2; + } + } + + if (flags & CBC_HAS_BYTE_ARG) + { + uint8_t byte_argument = (uint8_t) context_p->last_cbc.value; + + JERRY_ASSERT (context_p->last_cbc.value <= CBC_MAXIMUM_BYTE_VALUE); + + if (flags & CBC_POP_STACK_BYTE_ARG) + { + JERRY_ASSERT (context_p->stack_depth >= byte_argument); + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, byte_argument); + } + + PARSER_APPEND_TO_BYTE_CODE (context_p, byte_argument); + context_p->byte_code_size++; + } + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG (" [%3d] %s", + (int) context_p->stack_depth, + PARSER_IS_BASIC_OPCODE (last_opcode) ? cbc_names[last_opcode] + : cbc_ext_names[PARSER_GET_EXT_OPCODE (last_opcode)]); + + if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)) + { + parser_print_literal (context_p, context_p->last_cbc.literal_index); + } + + if (flags & CBC_HAS_LITERAL_ARG2) + { + parser_print_literal (context_p, context_p->last_cbc.value); + + if (!(flags & CBC_HAS_LITERAL_ARG)) + { + parser_print_literal (context_p, context_p->last_cbc.third_literal_index); + } + } + + if (flags & CBC_HAS_BYTE_ARG) + { + if (last_opcode == CBC_PUSH_NUMBER_POS_BYTE || last_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) + { + JERRY_DEBUG_MSG (" number:%d", (int) context_p->last_cbc.value + 1); + } + else if (last_opcode == CBC_PUSH_NUMBER_NEG_BYTE || last_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE) + { + JERRY_DEBUG_MSG (" number:%d", -((int) context_p->last_cbc.value + 1)); + } + else + { + JERRY_DEBUG_MSG (" byte_arg:%d", (int) context_p->last_cbc.value); + } + } + + JERRY_DEBUG_MSG ("\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + if (context_p->stack_depth > context_p->stack_limit) + { + context_p->stack_limit = context_p->stack_depth; + if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + } + + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; +} /* parser_flush_cbc */ + +/** + * Append a byte code + */ +void +parser_emit_cbc (parser_context_t *context_p, /**< context */ + uint16_t opcode) /**< opcode */ +{ + JERRY_ASSERT (PARSER_ARGS_EQ (opcode, 0)); + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->last_cbc_opcode = opcode; +} /* parser_emit_cbc */ + +/** + * Append a byte code with a literal argument + */ +void +parser_emit_cbc_literal (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + uint16_t literal_index) /**< literal index */ +{ + JERRY_ASSERT (PARSER_ARGS_EQ (opcode, CBC_HAS_LITERAL_ARG)); + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.literal_index = literal_index; + context_p->last_cbc.literal_type = LEXER_UNUSED_LITERAL; + context_p->last_cbc.literal_keyword_type = LEXER_EOS; +} /* parser_emit_cbc_literal */ + +/** + * Append a byte code with a literal and value argument + */ +void +parser_emit_cbc_literal_value (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + uint16_t literal_index, /**< literal index */ + uint16_t value) /**< value */ +{ + JERRY_ASSERT (PARSER_ARGS_EQ (opcode, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)); + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.literal_index = literal_index; + context_p->last_cbc.literal_type = LEXER_UNUSED_LITERAL; + context_p->last_cbc.literal_keyword_type = LEXER_EOS; + context_p->last_cbc.value = value; +} /* parser_emit_cbc_literal_value */ + +/** + * Append a byte code with the current literal argument + */ +void +parser_emit_cbc_literal_from_token (parser_context_t *context_p, /**< context */ + uint16_t opcode) /**< opcode */ +{ + JERRY_ASSERT (PARSER_ARGS_EQ (opcode, CBC_HAS_LITERAL_ARG)); + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.literal_index = context_p->lit_object.index; + context_p->last_cbc.literal_type = context_p->token.lit_location.type; + context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type; +} /* parser_emit_cbc_literal_from_token */ + +/** + * Append a byte code with a call argument + */ +void +parser_emit_cbc_call (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + size_t call_arguments) /**< number of arguments */ +{ + JERRY_ASSERT (PARSER_ARGS_EQ (opcode, CBC_HAS_BYTE_ARG)); + JERRY_ASSERT (call_arguments <= CBC_MAXIMUM_BYTE_VALUE); + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.value = (uint16_t) call_arguments; +} /* parser_emit_cbc_call */ + +/** + * Append a push number 1/2 byte code + */ +void +parser_emit_cbc_push_number (parser_context_t *context_p, /**< context */ + bool is_negative_number) /**< sign is negative */ +{ + uint16_t value = context_p->lit_object.index; + uint16_t lit_value = PARSER_INVALID_LITERAL_INDEX; + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + lit_value = context_p->last_cbc.literal_index; + } + else + { + if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + lit_value = context_p->last_cbc.value; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + lit_value = context_p->last_cbc.third_literal_index; + } + + parser_flush_cbc (context_p); + } + } + + if (value == 0) + { + if (lit_value == PARSER_INVALID_LITERAL_INDEX) + { + context_p->last_cbc_opcode = CBC_PUSH_NUMBER_0; + return; + } + + context_p->last_cbc_opcode = CBC_PUSH_LITERAL_PUSH_NUMBER_0; + context_p->last_cbc.literal_index = lit_value; + return; + } + + uint16_t opcode; + + if (lit_value == PARSER_INVALID_LITERAL_INDEX) + { + opcode = (is_negative_number ? CBC_PUSH_NUMBER_NEG_BYTE : CBC_PUSH_NUMBER_POS_BYTE); + + JERRY_ASSERT (CBC_STACK_ADJUST_VALUE (PARSER_GET_FLAGS (opcode)) == 1); + } + else + { + opcode = (is_negative_number ? CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE : CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE); + JERRY_ASSERT (CBC_STACK_ADJUST_VALUE (PARSER_GET_FLAGS (opcode)) == 2); + + context_p->last_cbc.literal_index = lit_value; + } + + JERRY_ASSERT (value > 0 && value <= CBC_PUSH_NUMBER_BYTE_RANGE_END); + + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.value = (uint16_t) (value - 1); +} /* parser_emit_cbc_push_number */ + +/** + * Append a byte code with a branch argument + */ +void +parser_emit_cbc_forward_branch (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + parser_branch_t *branch_p) /**< branch result */ +{ + uint8_t flags; + uint32_t extra_byte_code_increase; + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->status_flags |= PARSER_NO_END_LABEL; + + if (PARSER_IS_BASIC_OPCODE (opcode)) + { + JERRY_ASSERT (opcode < CBC_END); + flags = cbc_flags[opcode]; + extra_byte_code_increase = 0; + } + else + { + PARSER_APPEND_TO_BYTE_CODE (context_p, CBC_EXT_OPCODE); + opcode = (uint16_t) PARSER_GET_EXT_OPCODE (opcode); + + JERRY_ASSERT (opcode < CBC_EXT_END); + flags = cbc_ext_flags[opcode]; + extra_byte_code_increase = 1; + } + + JERRY_ASSERT (flags & CBC_HAS_BRANCH_ARG); + JERRY_ASSERT (CBC_BRANCH_IS_FORWARD (flags)); + JERRY_ASSERT (CBC_BRANCH_OFFSET_LENGTH (opcode) == 1); + + /* Branch opcodes never push anything onto the stack. */ + JERRY_ASSERT ((flags >> CBC_STACK_ADJUST_SHIFT) >= CBC_STACK_ADJUST_BASE + || (CBC_STACK_ADJUST_BASE - (flags >> CBC_STACK_ADJUST_SHIFT)) <= context_p->stack_depth); + PARSER_PLUS_EQUAL_U16 (context_p->stack_depth, CBC_STACK_ADJUST_VALUE (flags)); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG (" [%3d] %s\n", + (int) context_p->stack_depth, + extra_byte_code_increase == 0 ? cbc_names[opcode] : cbc_ext_names[opcode]); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + PARSER_PLUS_EQUAL_U16 (opcode, PARSER_MAX_BRANCH_LENGTH - 1); + + parser_emit_two_bytes (context_p, (uint8_t) opcode, 0); + branch_p->page_p = context_p->byte_code.last_p; + branch_p->offset = (context_p->byte_code.last_position - 1) | (context_p->byte_code_size << 8); + + context_p->byte_code_size += extra_byte_code_increase; + +#if PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX + PARSER_APPEND_TO_BYTE_CODE (context_p, 0); +#else /* PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX */ + parser_emit_two_bytes (context_p, 0, 0); +#endif /* PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX */ + + context_p->byte_code_size += PARSER_MAX_BRANCH_LENGTH + 1; + + if (context_p->stack_depth > context_p->stack_limit) + { + context_p->stack_limit = context_p->stack_depth; + if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + } +} /* parser_emit_cbc_forward_branch */ + +/** + * Append a branch byte code and create an item. + * + * @return newly created parser branch node + */ +parser_branch_node_t * +parser_emit_cbc_forward_branch_item (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + parser_branch_node_t *next_p) /**< next branch */ +{ + parser_branch_t branch; + parser_branch_node_t *new_item; + + /* Since byte code insertion may throw an out-of-memory error, + * the branch is constructed locally, and copied later. */ + parser_emit_cbc_forward_branch (context_p, opcode, &branch); + + new_item = (parser_branch_node_t *) parser_malloc (context_p, sizeof (parser_branch_node_t)); + new_item->branch = branch; + new_item->next_p = next_p; + return new_item; +} /* parser_emit_cbc_forward_branch_item */ + +/** + * Append a byte code with a branch argument + */ +void +parser_emit_cbc_backward_branch (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + uint32_t offset) /**< destination offset */ +{ + uint8_t flags; +#if JERRY_PARSER_DUMP_BYTE_CODE + const char *name; +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->status_flags |= PARSER_NO_END_LABEL; + offset = context_p->byte_code_size - offset; + + if (PARSER_IS_BASIC_OPCODE (opcode)) + { + JERRY_ASSERT (opcode < CBC_END); + flags = cbc_flags[opcode]; + +#if JERRY_PARSER_DUMP_BYTE_CODE + name = cbc_names[opcode]; +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + } + else + { + PARSER_APPEND_TO_BYTE_CODE (context_p, CBC_EXT_OPCODE); + opcode = (uint16_t) PARSER_GET_EXT_OPCODE (opcode); + + JERRY_ASSERT (opcode < CBC_EXT_END); + flags = cbc_ext_flags[opcode]; + context_p->byte_code_size++; + +#if JERRY_PARSER_DUMP_BYTE_CODE + name = cbc_ext_names[opcode]; +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + } + + JERRY_ASSERT (flags & CBC_HAS_BRANCH_ARG); + JERRY_ASSERT (CBC_BRANCH_IS_BACKWARD (flags)); + JERRY_ASSERT (CBC_BRANCH_OFFSET_LENGTH (opcode) == 1); + JERRY_ASSERT (offset <= context_p->byte_code_size); + + /* Branch opcodes never push anything onto the stack. */ + JERRY_ASSERT ((flags >> CBC_STACK_ADJUST_SHIFT) >= CBC_STACK_ADJUST_BASE + || (CBC_STACK_ADJUST_BASE - (flags >> CBC_STACK_ADJUST_SHIFT)) <= context_p->stack_depth); + PARSER_PLUS_EQUAL_U16 (context_p->stack_depth, CBC_STACK_ADJUST_VALUE (flags)); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG (" [%3d] %s\n", (int) context_p->stack_depth, name); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + context_p->byte_code_size += 2; +#if PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX + if (offset > UINT16_MAX) + { + opcode++; + context_p->byte_code_size++; + } +#endif /* PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX */ + + if (offset > UINT8_MAX) + { + opcode++; + context_p->byte_code_size++; + } + + PARSER_APPEND_TO_BYTE_CODE (context_p, (uint8_t) opcode); + +#if PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX + if (offset > UINT16_MAX) + { + PARSER_APPEND_TO_BYTE_CODE (context_p, offset >> 16); + } +#endif /* PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX */ + + if (offset > UINT8_MAX) + { + PARSER_APPEND_TO_BYTE_CODE (context_p, (offset >> 8) & 0xff); + } + + PARSER_APPEND_TO_BYTE_CODE (context_p, offset & 0xff); +} /* parser_emit_cbc_backward_branch */ + +#undef PARSER_CHECK_LAST_POSITION +#undef PARSER_APPEND_TO_BYTE_CODE + +/** + * Helper function for parser. + * + * @return a new string based on encode. + */ +ecma_string_t * +parser_new_ecma_string_from_literal (lexer_literal_t *literal_p) /**< literal */ +{ + JERRY_ASSERT (literal_p != NULL); + + ecma_string_t *new_string = NULL; + + if (literal_p->status_flags & LEXER_FLAG_ASCII) + { + new_string = ecma_new_ecma_string_from_ascii (literal_p->u.char_p, literal_p->prop.length); + } + else + { + new_string = ecma_new_ecma_string_from_utf8 (literal_p->u.char_p, literal_p->prop.length); + } + + return new_string; +} /* parser_new_ecma_string_from_literal */ + +/** + * Set a branch to the current byte code position + */ +void +parser_set_branch_to_current_position (parser_context_t *context_p, /**< context */ + parser_branch_t *branch_p) /**< branch result */ +{ + uint32_t delta; + size_t offset; + parser_mem_page_t *page_p = branch_p->page_p; + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->status_flags &= (uint32_t) ~PARSER_NO_END_LABEL; + + JERRY_ASSERT (context_p->byte_code_size > (branch_p->offset >> 8)); + + delta = context_p->byte_code_size - (branch_p->offset >> 8); + offset = (branch_p->offset & CBC_LOWER_SEVEN_BIT_MASK); + + JERRY_ASSERT (delta <= PARSER_MAXIMUM_CODE_SIZE); + +#if PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX + page_p->bytes[offset++] = (uint8_t) (delta >> 8); + if (offset >= PARSER_CBC_STREAM_PAGE_SIZE) + { + page_p = page_p->next_p; + offset = 0; + } +#else /* PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX */ + page_p->bytes[offset++] = (uint8_t) (delta >> 16); + if (offset >= PARSER_CBC_STREAM_PAGE_SIZE) + { + page_p = page_p->next_p; + offset = 0; + } + page_p->bytes[offset++] = (uint8_t) ((delta >> 8) & 0xff); + if (offset >= PARSER_CBC_STREAM_PAGE_SIZE) + { + page_p = page_p->next_p; + offset = 0; + } +#endif /* PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX */ + page_p->bytes[offset] = delta & 0xff; +} /* parser_set_branch_to_current_position */ + +/** + * Set breaks to the current byte code position + */ +void +parser_set_breaks_to_current_position (parser_context_t *context_p, /**< context */ + parser_branch_node_t *current_p) /**< branch list */ +{ + while (current_p != NULL) + { + parser_branch_node_t *next_p = current_p->next_p; + + if (!(current_p->branch.offset & CBC_HIGHEST_BIT_MASK)) + { + parser_set_branch_to_current_position (context_p, ¤t_p->branch); + } + parser_free (current_p, sizeof (parser_branch_node_t)); + current_p = next_p; + } +} /* parser_set_breaks_to_current_position */ + +/** + * Set continues to the current byte code position + */ +void +parser_set_continues_to_current_position (parser_context_t *context_p, /**< context */ + parser_branch_node_t *current_p) /**< branch list */ +{ + while (current_p != NULL) + { + if (current_p->branch.offset & CBC_HIGHEST_BIT_MASK) + { + parser_set_branch_to_current_position (context_p, ¤t_p->branch); + } + current_p = current_p->next_p; + } +} /* parser_set_continues_to_current_position */ + +/** + * Return the size of internal record corresponding to a class field + * + * @return internal record size + */ +static size_t +parser_get_class_field_info_size (uint8_t class_field_type) /**< class field type */ +{ + if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED) + { + return sizeof (scanner_range_t) + 1; + } + + if (class_field_type & PARSER_CLASS_FIELD_NORMAL) + { + return sizeof (scanner_location_t) + 1; + } + + return 1; +} /* parser_get_class_field_info_size */ + +/** + * Reverse the field list of a class + */ +void +parser_reverse_class_fields (parser_context_t *context_p, /**< context */ + size_t fields_size) /**< size of consumed memory */ +{ + uint8_t *data_p = (uint8_t *) parser_malloc (context_p, fields_size); + uint8_t *data_end_p = data_p + fields_size; + uint8_t *current_p = data_p; + bool has_fields = false; + parser_stack_iterator_t iterator; + + JERRY_ASSERT (!(context_p->stack_top_uint8 & PARSER_CLASS_FIELD_END)); + + parser_stack_iterator_init (context_p, &iterator); + + do + { + uint8_t class_field_type = parser_stack_iterator_read_uint8 (&iterator); + size_t info_size = parser_get_class_field_info_size (class_field_type); + + parser_stack_iterator_read (&iterator, current_p, info_size); + parser_stack_iterator_skip (&iterator, info_size); + current_p += info_size; + + if (!(class_field_type & PARSER_CLASS_FIELD_STATIC)) + { + has_fields = true; + context_p->stack_top_uint8 = class_field_type; + } + } while (current_p < data_end_p); + + parser_stack_iterator_init (context_p, &iterator); + current_p = data_end_p; + + bool has_static_fields = false; + + if (has_fields) + { + do + { + uint8_t class_field_type = current_p[-1]; + + size_t info_size = parser_get_class_field_info_size (class_field_type); + + if (!(class_field_type & PARSER_CLASS_FIELD_STATIC)) + { + current_p -= info_size; + parser_stack_iterator_write (&iterator, current_p, info_size); + parser_stack_iterator_skip (&iterator, info_size); + continue; + } + + if (!has_static_fields) + { + has_static_fields = true; + current_p[-1] |= PARSER_CLASS_FIELD_END; + } + current_p -= info_size; + } while (current_p > data_p); + } + else + { + /* All class fields are static. */ + has_static_fields = true; + JERRY_ASSERT (data_end_p[-1] & PARSER_CLASS_FIELD_STATIC); + context_p->stack_top_uint8 = data_end_p[-1]; + } + + if (has_static_fields) + { + current_p = data_end_p; + + do + { + uint8_t class_field_type = current_p[-1]; + + size_t info_size = parser_get_class_field_info_size (class_field_type); + current_p -= info_size; + + if (class_field_type & PARSER_CLASS_FIELD_STATIC) + { + parser_stack_iterator_write (&iterator, current_p, info_size); + parser_stack_iterator_skip (&iterator, info_size); + } + } while (current_p > data_p); + } + + parser_free (data_p, fields_size); +} /* parser_reverse_class_fields */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.cpp new file mode 100644 index 00000000..f7559bb3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.cpp @@ -0,0 +1,3218 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-exceptions.h" +#include "ecma-extended-info.h" +#include "ecma-helpers.h" +#include "ecma-literal-storage.h" +#include "ecma-module.h" + +#include "jcontext.h" +#include "js-parser-internal.h" +#include "lit-char-helpers.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_parser Parser + * @{ + */ + +#if JERRY_PARSER + +JERRY_STATIC_ASSERT (((int) ECMA_PARSE_STRICT_MODE == (int) PARSER_IS_STRICT), + ecma_parse_strict_mode_must_be_equal_to_parser_is_strict); + +JERRY_STATIC_ASSERT (PARSER_SAVE_STATUS_FLAGS (PARSER_ALLOW_SUPER) == 0x1, incorrect_saving_of_ecma_parse_allow_super); +JERRY_STATIC_ASSERT ((PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_ALLOW_SUPER) == PARSER_ALLOW_SUPER), + incorrect_restoring_of_ecma_parse_allow_super); + +JERRY_STATIC_ASSERT ((PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_FUNCTION_CONTEXT) == 0), + ecma_parse_function_context_must_not_be_transformed); + +/** + * Compute real literal indicies. + * + * @return length of the prefix opcodes + */ +static void +parser_compute_indicies (parser_context_t *context_p, /**< context */ + uint16_t *ident_end, /**< end of the identifier group */ + uint16_t *const_literal_end) /**< end of the const literal group */ +{ + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + + uint16_t ident_count = 0; + uint16_t const_literal_count = 0; + + uint16_t ident_index; + uint16_t const_literal_index; + uint16_t literal_index; + + /* First phase: count the number of items in each group. */ + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator))) + { + switch (literal_p->type) + { + case LEXER_IDENT_LITERAL: + { + if (literal_p->status_flags & LEXER_FLAG_USED) + { + ident_count++; + break; + } + else if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR)) + { + jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length); + /* This literal should not be freed even if an error is encountered later. */ + literal_p->status_flags |= LEXER_FLAG_SOURCE_PTR; + } + continue; + } + case LEXER_STRING_LITERAL: + { + const_literal_count++; + break; + } + case LEXER_NUMBER_LITERAL: + { + const_literal_count++; + continue; + } + case LEXER_FUNCTION_LITERAL: + case LEXER_REGEXP_LITERAL: + { + continue; + } + default: + { + JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL); + continue; + } + } + + const uint8_t *char_p = literal_p->u.char_p; + uint32_t status_flags = context_p->status_flags; + + if ((literal_p->status_flags & LEXER_FLAG_SOURCE_PTR) && literal_p->prop.length < 0xfff) + { + size_t bytes_to_end = (size_t) (context_p->source_end_p - char_p); + + if (bytes_to_end < 0xfffff) + { + literal_p->u.source_data = ((uint32_t) bytes_to_end) | (((uint32_t) literal_p->prop.length) << 20); + literal_p->status_flags |= LEXER_FLAG_LATE_INIT; + status_flags |= PARSER_HAS_LATE_LIT_INIT; + context_p->status_flags = status_flags; + char_p = NULL; + } + } + + if (char_p != NULL) + { + literal_p->u.value = ecma_find_or_create_literal_string (char_p, + literal_p->prop.length, + (literal_p->status_flags & LEXER_FLAG_ASCII) != 0); + + if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR)) + { + jmem_heap_free_block ((void *) char_p, literal_p->prop.length); + /* This literal should not be freed even if an error is encountered later. */ + literal_p->status_flags |= LEXER_FLAG_SOURCE_PTR; + } + } + } + + ident_index = context_p->register_count; + const_literal_index = (uint16_t) (ident_index + ident_count); + literal_index = (uint16_t) (const_literal_index + const_literal_count); + + /* Second phase: Assign an index to each literal. */ + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator))) + { + switch (literal_p->type) + { + case LEXER_IDENT_LITERAL: + { + if (literal_p->status_flags & LEXER_FLAG_USED) + { + literal_p->prop.index = ident_index; + ident_index++; + } + break; + } + case LEXER_STRING_LITERAL: + case LEXER_NUMBER_LITERAL: + { + JERRY_ASSERT ((literal_p->status_flags & ~(LEXER_FLAG_SOURCE_PTR | LEXER_FLAG_LATE_INIT)) == 0); + literal_p->prop.index = const_literal_index; + const_literal_index++; + break; + } + case LEXER_FUNCTION_LITERAL: + case LEXER_REGEXP_LITERAL: + { + JERRY_ASSERT (literal_p->status_flags == 0); + + literal_p->prop.index = literal_index; + literal_index++; + break; + } + default: + { + JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL + && literal_p->status_flags == LEXER_FLAG_FUNCTION_ARGUMENT); + break; + } + } + } + + JERRY_ASSERT (ident_index == context_p->register_count + ident_count); + JERRY_ASSERT (const_literal_index == ident_index + const_literal_count); + JERRY_ASSERT (literal_index <= context_p->register_count + context_p->literal_count); + + context_p->literal_count = literal_index; + + *ident_end = ident_index; + *const_literal_end = const_literal_index; +} /* parser_compute_indicies */ + +/** + * Initialize literal pool. + */ +static void +parser_init_literal_pool (parser_context_t *context_p, /**< context */ + ecma_value_t *literal_pool_p) /**< start of literal pool */ +{ + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator))) + { + switch (literal_p->type) + { + case LEXER_IDENT_LITERAL: + { + if (!(literal_p->status_flags & LEXER_FLAG_USED)) + { + break; + } + /* FALLTHRU */ + } + case LEXER_STRING_LITERAL: + { + ecma_value_t lit_value = literal_p->u.value; + + JERRY_ASSERT (literal_p->prop.index >= context_p->register_count); + literal_pool_p[literal_p->prop.index] = lit_value; + break; + } + case LEXER_NUMBER_LITERAL: + { + JERRY_ASSERT (literal_p->prop.index >= context_p->register_count); + + literal_pool_p[literal_p->prop.index] = literal_p->u.value; + break; + } + case LEXER_FUNCTION_LITERAL: + case LEXER_REGEXP_LITERAL: + { + JERRY_ASSERT (literal_p->prop.index >= context_p->register_count); + + ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[literal_p->prop.index], literal_p->u.bytecode_p); + break; + } + default: + { + JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL); + break; + } + } + } +} /* parser_init_literal_pool */ + +/* + * During byte code post processing certain bytes are not + * copied into the final byte code buffer. For example, if + * one byte is enough for encoding a literal index, the + * second byte is not copied. However, when a byte is skipped, + * the offsets of those branches which crosses (jumps over) + * that byte code should also be decreased by one. Instead + * of finding these jumps every time when a byte is skipped, + * all branch offset updates are computed in one step. + * + * Branch offset mapping example: + * + * Let's assume that each parser_mem_page of the byte_code + * buffer is 8 bytes long and only 4 bytes are kept for a + * given page: + * + * +---+---+---+---+---+---+---+---+ + * | X | 1 | 2 | 3 | X | 4 | X | X | + * +---+---+---+---+---+---+---+---+ + * + * X marks those bytes which are removed. The resulting + * offset mapping is the following: + * + * +---+---+---+---+---+---+---+---+ + * | 0 | 1 | 2 | 3 | 3 | 4 | 4 | 4 | + * +---+---+---+---+---+---+---+---+ + * + * Each X is simply replaced by the index of the previous + * index starting from zero. This shows the number of + * copied bytes before a given byte including the byte + * itself. The last byte always shows the number of bytes + * copied from this page. + * + * This mapping allows recomputing all branch targets, + * since mapping[to] - mapping[from] is the new argument + * for forward branches. As for backward branches, the + * equation is reversed to mapping[from] - mapping[to]. + * + * The mapping is relative to one page, so distance + * computation affecting multiple pages requires a loop. + * We should also note that only argument bytes can + * be skipped, so removed bytes cannot be targeted by + * branches. Valid branches always target instruction + * starts only. + */ + +/** + * Recompute the argument of a forward branch. + * + * @return the new distance + */ +static size_t +parser_update_forward_branch (parser_mem_page_t *page_p, /**< current page */ + size_t full_distance, /**< full distance */ + uint8_t bytes_copied_before_jump) /**< bytes copied before jump */ +{ + size_t new_distance = 0; + + while (full_distance > PARSER_CBC_STREAM_PAGE_SIZE) + { + new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK; + full_distance -= PARSER_CBC_STREAM_PAGE_SIZE; + page_p = page_p->next_p; + } + + new_distance += page_p->bytes[full_distance - 1] & CBC_LOWER_SEVEN_BIT_MASK; + return new_distance - bytes_copied_before_jump; +} /* parser_update_forward_branch */ + +/** + * Recompute the argument of a backward branch. + * + * @return the new distance + */ +static size_t +parser_update_backward_branch (parser_mem_page_t *page_p, /**< current page */ + size_t full_distance, /**< full distance */ + uint8_t bytes_copied_before_jump) /**< bytes copied before jump */ +{ + size_t new_distance = bytes_copied_before_jump; + + while (full_distance >= PARSER_CBC_STREAM_PAGE_SIZE) + { + JERRY_ASSERT (page_p != NULL); + new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK; + full_distance -= PARSER_CBC_STREAM_PAGE_SIZE; + page_p = page_p->next_p; + } + + if (full_distance > 0) + { + size_t offset = PARSER_CBC_STREAM_PAGE_SIZE - full_distance; + + JERRY_ASSERT (page_p != NULL); + + new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK; + new_distance -= page_p->bytes[offset - 1] & CBC_LOWER_SEVEN_BIT_MASK; + } + + return new_distance; +} /* parser_update_backward_branch */ + +/** + * Update targets of all branches in one step. + */ +static void +parse_update_branches (parser_context_t *context_p, /**< context */ + uint8_t *byte_code_p) /**< byte code */ +{ + parser_mem_page_t *page_p = context_p->byte_code.first_p; + parser_mem_page_t *prev_page_p = NULL; + parser_mem_page_t *last_page_p = context_p->byte_code.last_p; + size_t last_position = context_p->byte_code.last_position; + size_t offset = 0; + size_t bytes_copied = 0; + + if (last_position >= PARSER_CBC_STREAM_PAGE_SIZE) + { + last_page_p = NULL; + last_position = 0; + } + + while (page_p != last_page_p || offset < last_position) + { + /* Branch instructions are marked to improve search speed. */ + if (page_p->bytes[offset] & CBC_HIGHEST_BIT_MASK) + { + uint8_t *bytes_p = byte_code_p + bytes_copied; + uint8_t flags; + uint8_t bytes_copied_before_jump = 0; + size_t branch_argument_length; + size_t target_distance; + size_t length; + + if (offset > 0) + { + bytes_copied_before_jump = page_p->bytes[offset - 1] & CBC_LOWER_SEVEN_BIT_MASK; + } + bytes_p += bytes_copied_before_jump; + + if (*bytes_p == CBC_EXT_OPCODE) + { + bytes_p++; + flags = cbc_ext_flags[*bytes_p]; + } + else + { + flags = cbc_flags[*bytes_p]; + } + + JERRY_ASSERT (flags & CBC_HAS_BRANCH_ARG); + branch_argument_length = CBC_BRANCH_OFFSET_LENGTH (*bytes_p); + bytes_p++; + + /* Decoding target. */ + length = branch_argument_length; + target_distance = 0; + do + { + target_distance = (target_distance << 8) | *bytes_p; + bytes_p++; + } while (--length > 0); + + if (CBC_BRANCH_IS_FORWARD (flags)) + { + /* Branch target was not set. */ + JERRY_ASSERT (target_distance > 0); + + target_distance = parser_update_forward_branch (page_p, offset + target_distance, bytes_copied_before_jump); + } + else + { + if (target_distance < offset) + { + uint8_t bytes_copied_before_target = page_p->bytes[offset - target_distance - 1]; + bytes_copied_before_target = bytes_copied_before_target & CBC_LOWER_SEVEN_BIT_MASK; + + target_distance = (size_t) (bytes_copied_before_jump - bytes_copied_before_target); + } + else if (target_distance == offset) + { + target_distance = bytes_copied_before_jump; + } + else + { + target_distance = + parser_update_backward_branch (prev_page_p, target_distance - offset, bytes_copied_before_jump); + } + } + + /* Encoding target again. */ + do + { + bytes_p--; + *bytes_p = (uint8_t) (target_distance & 0xff); + target_distance >>= 8; + } while (--branch_argument_length > 0); + } + + offset++; + if (offset >= PARSER_CBC_STREAM_PAGE_SIZE) + { + parser_mem_page_t *next_p = page_p->next_p; + + /* We reverse the pages before the current page. */ + page_p->next_p = prev_page_p; + prev_page_p = page_p; + + bytes_copied += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK; + page_p = next_p; + offset = 0; + } + } + + /* After this point the pages of the byte code stream are + * not used anymore. However, they needs to be freed during + * cleanup, so the first and last pointers of the stream + * descriptor are reversed as well. */ + if (last_page_p != NULL) + { + JERRY_ASSERT (last_page_p == context_p->byte_code.last_p); + last_page_p->next_p = prev_page_p; + } + else + { + last_page_p = context_p->byte_code.last_p; + } + + context_p->byte_code.last_p = context_p->byte_code.first_p; + context_p->byte_code.first_p = last_page_p; +} /* parse_update_branches */ + +/** + * Forward iterator: move to the next byte code + * + * @param page_p page + * @param offset offset + */ +#define PARSER_NEXT_BYTE(page_p, offset) \ + do \ + { \ + if (++(offset) >= PARSER_CBC_STREAM_PAGE_SIZE) \ + { \ + offset = 0; \ + page_p = page_p->next_p; \ + } \ + } while (0) + +/** + * Forward iterator: move to the next byte code. Also updates the offset of the previous byte code. + * + * @param page_p page + * @param offset offset + * @param real_offset real offset + */ +#define PARSER_NEXT_BYTE_UPDATE(page_p, offset, real_offset) \ + do \ + { \ + page_p->bytes[offset] = real_offset; \ + if (++(offset) >= PARSER_CBC_STREAM_PAGE_SIZE) \ + { \ + offset = 0; \ + real_offset = 0; \ + page_p = page_p->next_p; \ + } \ + } while (0) + +/** + * Post processing main function. + * + * @return compiled code + */ +static ecma_compiled_code_t * +parser_post_processing (parser_context_t *context_p) /**< context */ +{ + uint16_t literal_one_byte_limit; + uint16_t ident_end; + uint16_t const_literal_end; + parser_mem_page_t *page_p; + parser_mem_page_t *last_page_p; + size_t last_position; + size_t offset; + size_t length; + size_t literal_length; + size_t total_size; + uint8_t real_offset; + uint8_t *byte_code_p; + bool needs_uint16_arguments; + cbc_opcode_t last_opcode = CBC_EXT_OPCODE; + ecma_compiled_code_t *compiled_code_p; + ecma_value_t *literal_pool_p; + uint8_t *dst_p; + + if ((context_p->status_flags & (PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED)) + == (PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED)) + { + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + context_p->status_flags &= (uint32_t) ~PARSER_LEXICAL_BLOCK_NEEDED; + + parser_emit_cbc (context_p, CBC_CONTEXT_END); + + parser_branch_t branch; + parser_stack_pop (context_p, &branch, sizeof (parser_branch_t)); + parser_set_branch_to_current_position (context_p, &branch); + + JERRY_ASSERT (!(context_p->status_flags & PARSER_NO_END_LABEL)); + } + + if (PARSER_IS_NORMAL_ASYNC_FUNCTION (context_p->status_flags)) + { + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + if (context_p->stack_limit < PARSER_FINALLY_CONTEXT_STACK_ALLOCATION) + { + context_p->stack_limit = PARSER_FINALLY_CONTEXT_STACK_ALLOCATION; + } + + parser_branch_t branch; + + parser_stack_pop (context_p, &branch, sizeof (parser_branch_t)); + parser_set_branch_to_current_position (context_p, &branch); + + JERRY_ASSERT (!(context_p->status_flags & PARSER_NO_END_LABEL)); + } + +#if JERRY_LINE_INFO + JERRY_ASSERT (context_p->line_info_p != NULL); +#endif /* JERRY_LINE_INFO */ + + JERRY_ASSERT (context_p->stack_depth == 0); +#ifndef JERRY_NDEBUG + JERRY_ASSERT (context_p->context_stack_depth == 0); +#endif /* !JERRY_NDEBUG */ + + if ((size_t) context_p->stack_limit + (size_t) context_p->register_count > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + + if (JERRY_UNLIKELY (context_p->script_p->refs_and_type >= CBC_SCRIPT_REF_MAX)) + { + /* This is probably never happens in practice. */ + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } + + context_p->script_p->refs_and_type += CBC_SCRIPT_REF_ONE; + + JERRY_ASSERT (context_p->literal_count <= PARSER_MAXIMUM_NUMBER_OF_LITERALS); + + parser_compute_indicies (context_p, &ident_end, &const_literal_end); + + if (context_p->literal_count <= CBC_MAXIMUM_SMALL_VALUE) + { + literal_one_byte_limit = CBC_MAXIMUM_BYTE_VALUE - 1; + } + else + { + literal_one_byte_limit = CBC_LOWER_SEVEN_BIT_MASK; + } + + last_page_p = context_p->byte_code.last_p; + last_position = context_p->byte_code.last_position; + + if (last_position >= PARSER_CBC_STREAM_PAGE_SIZE) + { + last_page_p = NULL; + last_position = 0; + } + + page_p = context_p->byte_code.first_p; + offset = 0; + length = 0; + + while (page_p != last_page_p || offset < last_position) + { + uint8_t *opcode_p; + uint8_t flags; + size_t branch_offset_length; + + opcode_p = page_p->bytes + offset; + last_opcode = (cbc_opcode_t) (*opcode_p); + PARSER_NEXT_BYTE (page_p, offset); + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (last_opcode); + flags = cbc_flags[last_opcode]; + length++; + + switch (last_opcode) + { + case CBC_EXT_OPCODE: + { + cbc_ext_opcode_t ext_opcode; + + ext_opcode = (cbc_ext_opcode_t) page_p->bytes[offset]; + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (ext_opcode); + flags = cbc_ext_flags[ext_opcode]; + PARSER_NEXT_BYTE (page_p, offset); + length++; + break; + } + case CBC_POST_DECR: + { + *opcode_p = CBC_PRE_DECR; + break; + } + case CBC_POST_INCR: + { + *opcode_p = CBC_PRE_INCR; + break; + } + case CBC_POST_DECR_IDENT: + { + *opcode_p = CBC_PRE_DECR_IDENT; + break; + } + case CBC_POST_INCR_IDENT: + { + *opcode_p = CBC_PRE_INCR_IDENT; + break; + } + default: + { + break; + } + } + + while (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)) + { + uint8_t *first_byte = page_p->bytes + offset; + uint32_t literal_index = *first_byte; + + PARSER_NEXT_BYTE (page_p, offset); + length++; + + literal_index |= ((uint32_t) page_p->bytes[offset]) << 8; + + if (literal_index >= PARSER_REGISTER_START) + { + literal_index -= PARSER_REGISTER_START; + } + else + { + literal_index = (PARSER_GET_LITERAL (literal_index))->prop.index; + } + + if (literal_index <= literal_one_byte_limit) + { + *first_byte = (uint8_t) literal_index; + } + else + { + if (context_p->literal_count <= CBC_MAXIMUM_SMALL_VALUE) + { + JERRY_ASSERT (literal_index <= CBC_MAXIMUM_SMALL_VALUE); + *first_byte = CBC_MAXIMUM_BYTE_VALUE; + page_p->bytes[offset] = (uint8_t) (literal_index - CBC_MAXIMUM_BYTE_VALUE); + length++; + } + else + { + JERRY_ASSERT (literal_index <= CBC_MAXIMUM_FULL_VALUE); + *first_byte = (uint8_t) ((literal_index >> 8) | CBC_HIGHEST_BIT_MASK); + page_p->bytes[offset] = (uint8_t) (literal_index & 0xff); + length++; + } + } + PARSER_NEXT_BYTE (page_p, offset); + + if (flags & CBC_HAS_LITERAL_ARG2) + { + if (flags & CBC_HAS_LITERAL_ARG) + { + flags = CBC_HAS_LITERAL_ARG; + } + else + { + flags = CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2; + } + } + else + { + break; + } + } + + if (flags & CBC_HAS_BYTE_ARG) + { + /* This argument will be copied without modification. */ + PARSER_NEXT_BYTE (page_p, offset); + length++; + } + + if (flags & CBC_HAS_BRANCH_ARG) + { + bool prefix_zero = true; + + /* The leading zeroes are dropped from the stream. + * Although dropping these zeroes for backward + * branches are unnecessary, we use the same + * code path for simplicity. */ + JERRY_ASSERT (branch_offset_length > 0 && branch_offset_length <= 3); + + while (--branch_offset_length > 0) + { + uint8_t byte = page_p->bytes[offset]; + if (byte > 0 || !prefix_zero) + { + prefix_zero = false; + length++; + } + else + { + JERRY_ASSERT (CBC_BRANCH_IS_FORWARD (flags)); + } + PARSER_NEXT_BYTE (page_p, offset); + } + + if (last_opcode == (cbc_opcode_t) (CBC_JUMP_FORWARD + PARSER_MAX_BRANCH_LENGTH - 1) && prefix_zero + && page_p->bytes[offset] == PARSER_MAX_BRANCH_LENGTH + 1) + { + /* Uncoditional jumps which jump right after the instruction + * are effectively NOPs. These jumps are removed from the + * stream. The 1 byte long CBC_JUMP_FORWARD form marks these + * instructions, since this form is constructed during post + * processing and cannot be emitted directly. */ + *opcode_p = CBC_JUMP_FORWARD; + length--; + } + else + { + /* Other last bytes are always copied. */ + length++; + } + + PARSER_NEXT_BYTE (page_p, offset); + } + } + + if (!(context_p->status_flags & PARSER_NO_END_LABEL) || !(PARSER_OPCODE_IS_RETURN (last_opcode))) + { + context_p->status_flags &= (uint32_t) ~PARSER_NO_END_LABEL; + + if (PARSER_IS_NORMAL_ASYNC_FUNCTION (context_p->status_flags)) + { + length++; + } + + length++; + } + + needs_uint16_arguments = false; + total_size = sizeof (cbc_uint8_arguments_t); + + if (context_p->stack_limit > CBC_MAXIMUM_BYTE_VALUE || context_p->register_count > CBC_MAXIMUM_BYTE_VALUE + || context_p->literal_count > CBC_MAXIMUM_BYTE_VALUE) + { + needs_uint16_arguments = true; + total_size = sizeof (cbc_uint16_arguments_t); + } + + literal_length = (size_t) (context_p->literal_count - context_p->register_count) * sizeof (ecma_value_t); + + total_size += literal_length + length; + + if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags)) + { + total_size += context_p->argument_count * sizeof (ecma_value_t); + } + + /* function.name */ + if (!(context_p->status_flags & PARSER_CLASS_CONSTRUCTOR)) + { + total_size += sizeof (ecma_value_t); + } + + if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) + { + total_size += sizeof (ecma_value_t); + } + +#if JERRY_LINE_INFO + total_size += sizeof (ecma_value_t); +#endif /* JERRY_LINE_INFO */ + uint8_t extended_info = 0; + + if (context_p->argument_length != UINT16_MAX) + { + extended_info |= CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH; + total_size += ecma_extended_info_get_encoded_length (context_p->argument_length); + } +#if JERRY_FUNCTION_TO_STRING + if (context_p->last_context_p != NULL) + { + extended_info |= CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE; + + const uint8_t *start_p = context_p->source_start_p; + const uint8_t *function_start_p = context_p->last_context_p->function_start_p; + + if (function_start_p < start_p || function_start_p >= start_p + context_p->source_size) + { + JERRY_ASSERT (context_p->arguments_start_p != NULL && function_start_p >= context_p->arguments_start_p + && function_start_p < context_p->arguments_start_p + context_p->arguments_size); + + start_p = context_p->arguments_start_p; + extended_info |= CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS; + } + + total_size += ecma_extended_info_get_encoded_length ((uint32_t) (function_start_p - start_p)); + total_size += ecma_extended_info_get_encoded_length ((uint32_t) (context_p->function_end_p - function_start_p)); + } +#endif /* JERRY_FUNCTION_TO_STRING */ + if (extended_info != 0) + { + total_size += sizeof (uint8_t); + } + + total_size = JERRY_ALIGNUP (total_size, JMEM_ALIGNMENT); + compiled_code_p = (ecma_compiled_code_t *) parser_malloc (context_p, total_size); + +#if JERRY_SNAPSHOT_SAVE || JERRY_PARSER_DUMP_BYTE_CODE + // Avoid getting junk bytes + memset (compiled_code_p, 0, total_size); +#endif /* JERRY_SNAPSHOT_SAVE || JERRY_PARSER_DUMP_BYTE_CODE */ + + byte_code_p = (uint8_t *) compiled_code_p; + compiled_code_p->size = (uint16_t) (total_size >> JMEM_ALIGNMENT_LOG); + compiled_code_p->refs = 1; + compiled_code_p->status_flags = 0; + + if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + JERRY_ASSERT (context_p->argument_count > 0); + context_p->argument_count--; + } + + if (needs_uint16_arguments) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p; + + args_p->stack_limit = context_p->stack_limit; + args_p->script_value = context_p->script_value; + args_p->argument_end = context_p->argument_count; + args_p->register_end = context_p->register_count; + args_p->ident_end = ident_end; + args_p->const_literal_end = const_literal_end; + args_p->literal_end = context_p->literal_count; + + compiled_code_p->status_flags |= CBC_CODE_FLAGS_UINT16_ARGUMENTS; + byte_code_p += sizeof (cbc_uint16_arguments_t); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p; + + args_p->stack_limit = (uint8_t) context_p->stack_limit; + args_p->argument_end = (uint8_t) context_p->argument_count; + args_p->script_value = context_p->script_value; + args_p->register_end = (uint8_t) context_p->register_count; + args_p->ident_end = (uint8_t) ident_end; + args_p->const_literal_end = (uint8_t) const_literal_end; + args_p->literal_end = (uint8_t) context_p->literal_count; + + byte_code_p += sizeof (cbc_uint8_arguments_t); + } + + uint16_t encoding_limit; + uint16_t encoding_delta; + + if (context_p->literal_count > CBC_MAXIMUM_SMALL_VALUE) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_FULL_LITERAL_ENCODING; + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + else + { + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + + if (context_p->status_flags & PARSER_IS_STRICT) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_STRICT_MODE; + } + + if ((context_p->status_flags & PARSER_ARGUMENTS_NEEDED) && PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags)) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED; + } + + if (!(context_p->status_flags & PARSER_LEXICAL_ENV_NEEDED)) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED; + } + + uint16_t function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_NORMAL); + + if (context_p->status_flags & (PARSER_IS_PROPERTY_GETTER | PARSER_IS_PROPERTY_SETTER)) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ACCESSOR); + } + else if (!(context_p->status_flags & PARSER_IS_FUNCTION)) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_SCRIPT); + } + else if (context_p->status_flags & PARSER_IS_ARROW_FUNCTION) + { + if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ASYNC_ARROW); + } + else + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ARROW); + } + } + else if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) + { + if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ASYNC_GENERATOR); + } + else + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_GENERATOR); + } + } + else if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ASYNC); + } + else if (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_CONSTRUCTOR); + } + else if (context_p->status_flags & PARSER_IS_METHOD) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_METHOD); + } + + if (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED) + { + JERRY_ASSERT (!(context_p->status_flags & PARSER_IS_FUNCTION)); + compiled_code_p->status_flags |= CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED; + } + + compiled_code_p->status_flags |= function_type; + +#if JERRY_LINE_INFO + compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_LINE_INFO; +#endif /* JERRY_LINE_INFO */ + + literal_pool_p = ((ecma_value_t *) byte_code_p) - context_p->register_count; + byte_code_p += literal_length; + dst_p = byte_code_p; + + parser_init_literal_pool (context_p, literal_pool_p); + + page_p = context_p->byte_code.first_p; + offset = 0; + real_offset = 0; + uint8_t last_register_index = + (uint8_t) JERRY_MIN (context_p->register_count, (PARSER_MAXIMUM_NUMBER_OF_REGISTERS - 1)); + + while (page_p != last_page_p || offset < last_position) + { + uint8_t flags; + uint8_t *opcode_p; + uint8_t *branch_mark_p; + cbc_opcode_t opcode; + size_t branch_offset_length; + + opcode_p = dst_p; + branch_mark_p = page_p->bytes + offset; + opcode = (cbc_opcode_t) (*branch_mark_p); + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (opcode); + + if (opcode == CBC_JUMP_FORWARD) + { + /* These opcodes are deleted from the stream. */ + size_t counter = PARSER_MAX_BRANCH_LENGTH + 1; + + do + { + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + } while (--counter > 0); + + continue; + } + + /* Storing the opcode */ + *dst_p++ = (uint8_t) opcode; + real_offset++; + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + flags = cbc_flags[opcode]; + + if (opcode == CBC_EXT_OPCODE) + { + cbc_ext_opcode_t ext_opcode; + + ext_opcode = (cbc_ext_opcode_t) page_p->bytes[offset]; + flags = cbc_ext_flags[ext_opcode]; + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (ext_opcode); + + /* Storing the extended opcode */ + *dst_p++ = (uint8_t) ext_opcode; + opcode_p++; + real_offset++; + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + } + + /* Only literal and call arguments can be combined. */ + JERRY_ASSERT (!(flags & CBC_HAS_BRANCH_ARG) || !(flags & (CBC_HAS_BYTE_ARG | CBC_HAS_LITERAL_ARG))); + + while (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)) + { + uint16_t first_byte = page_p->bytes[offset]; + + uint8_t *opcode_pos_p = dst_p - 1; + *dst_p++ = (uint8_t) first_byte; + real_offset++; + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + + if (first_byte > literal_one_byte_limit) + { + *dst_p++ = page_p->bytes[offset]; + + if (first_byte >= encoding_limit) + { + first_byte = (uint16_t) (((first_byte << 8) | dst_p[-1]) - encoding_delta); + } + real_offset++; + } + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + + if (flags & CBC_HAS_LITERAL_ARG2) + { + if (flags & CBC_HAS_LITERAL_ARG) + { + flags = CBC_HAS_LITERAL_ARG; + } + else + { + flags = CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2; + } + } + else + { + if (opcode == CBC_ASSIGN_SET_IDENT && JERRY_LIKELY (first_byte < last_register_index)) + { + *opcode_pos_p = CBC_MOV_IDENT; + } + + break; + } + } + + if (flags & CBC_HAS_BYTE_ARG) + { + /* This argument will be copied without modification. */ + *dst_p++ = page_p->bytes[offset]; + real_offset++; + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + continue; + } + + if (flags & CBC_HAS_BRANCH_ARG) + { + *branch_mark_p |= CBC_HIGHEST_BIT_MASK; + bool prefix_zero = true; + + /* The leading zeroes are dropped from the stream. */ + JERRY_ASSERT (branch_offset_length > 0 && branch_offset_length <= 3); + + while (--branch_offset_length > 0) + { + uint8_t byte = page_p->bytes[offset]; + if (byte > 0 || !prefix_zero) + { + prefix_zero = false; + *dst_p++ = page_p->bytes[offset]; + real_offset++; + } + else + { + /* When a leading zero is dropped, the branch + * offset length must be decreased as well. */ + (*opcode_p)--; + } + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + } + + *dst_p++ = page_p->bytes[offset]; + real_offset++; + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + continue; + } + } + + if (!(context_p->status_flags & PARSER_NO_END_LABEL)) + { + *dst_p++ = CBC_RETURN_FUNCTION_END; + + if (PARSER_IS_NORMAL_ASYNC_FUNCTION (context_p->status_flags)) + { + dst_p[-1] = CBC_EXT_OPCODE; + dst_p[0] = CBC_EXT_ASYNC_EXIT; + dst_p++; + } + } + JERRY_ASSERT (dst_p == byte_code_p + length); + +#if JERRY_LINE_INFO + uint8_t *line_info_p = parser_line_info_generate (context_p); +#endif /* JERRY_LINE_INFO */ + + parse_update_branches (context_p, byte_code_p); + + parser_cbc_stream_free (&context_p->byte_code); + + if (context_p->status_flags & PARSER_HAS_LATE_LIT_INIT) + { + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + uint16_t register_count = context_p->register_count; + + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator))) + { + if ((literal_p->status_flags & LEXER_FLAG_LATE_INIT) && literal_p->prop.index >= register_count) + { + uint32_t source_data = literal_p->u.source_data; + const uint8_t *char_p = context_p->source_end_p - (source_data & 0xfffff); + ecma_value_t lit_value = ecma_find_or_create_literal_string (char_p, + source_data >> 20, + (literal_p->status_flags & LEXER_FLAG_ASCII) != 0); + literal_pool_p[literal_p->prop.index] = lit_value; + } + } + } + + ecma_value_t *base_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size); + + if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags)) + { + parser_list_iterator_t literal_iterator; + uint16_t argument_count = 0; + uint16_t register_count = context_p->register_count; + base_p -= context_p->argument_count; + + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + while (argument_count < context_p->argument_count) + { + lexer_literal_t *literal_p; + literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator); + + JERRY_ASSERT (literal_p != NULL); + + if (!(literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT)) + { + continue; + } + + /* All arguments must be moved to initialized registers. */ + if (literal_p->type == LEXER_UNUSED_LITERAL) + { + base_p[argument_count] = ECMA_VALUE_EMPTY; + argument_count++; + continue; + } + + JERRY_ASSERT (literal_p->type == LEXER_IDENT_LITERAL); + + JERRY_ASSERT (literal_p->prop.index >= register_count); + + base_p[argument_count] = literal_pool_p[literal_p->prop.index]; + argument_count++; + } + } + + if (!(context_p->status_flags & PARSER_CLASS_CONSTRUCTOR)) + { + *(--base_p) = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_TAGGED_LITERALS; + *(--base_p) = (ecma_value_t) context_p->tagged_template_literal_cp; + } + +#if JERRY_LINE_INFO + ECMA_SET_INTERNAL_VALUE_POINTER (base_p[-1], line_info_p); +#endif /* JERRY_LINE_INFO */ + + if (extended_info != 0) + { +#if JERRY_LINE_INFO + base_p--; +#endif /* JERRY_LINE_INFO */ + + uint8_t *extended_info_p = ((uint8_t *) base_p) - 1; + + compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_EXTENDED_INFO; + *extended_info_p = extended_info; + + if (context_p->argument_length != UINT16_MAX) + { + ecma_extended_info_encode_vlq (&extended_info_p, context_p->argument_length); + } + +#if JERRY_FUNCTION_TO_STRING + if (context_p->last_context_p != NULL) + { + const uint8_t *start_p = context_p->source_start_p; + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS) + { + start_p = context_p->arguments_start_p; + } + + const uint8_t *function_start_p = context_p->last_context_p->function_start_p; + + ecma_extended_info_encode_vlq (&extended_info_p, (uint32_t) (function_start_p - start_p)); + ecma_extended_info_encode_vlq (&extended_info_p, (uint32_t) (context_p->function_end_p - function_start_p)); + } +#endif /* JERRY_FUNCTION_TO_STRING */ + } + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + util_print_cbc (compiled_code_p); + JERRY_DEBUG_MSG ("\nByte code size: %d bytes\n", (int) length); + context_p->total_byte_code_size += (uint32_t) length; + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + return compiled_code_p; +} /* parser_post_processing */ + +#undef PARSER_NEXT_BYTE +#undef PARSER_NEXT_BYTE_UPDATE + +/** + * Resolve private identifier in direct eval context + */ +static bool +parser_resolve_private_identifier_eval (parser_context_t *context_p) /**< context */ +{ + ecma_string_t *search_key_p; + uint8_t *destination_p = (uint8_t *) parser_malloc (context_p, context_p->token.lit_location.length); + + lexer_convert_ident_to_cesu8 (destination_p, + context_p->token.lit_location.char_p, + context_p->token.lit_location.length); + + search_key_p = ecma_new_ecma_string_from_utf8 (destination_p, context_p->token.lit_location.length); + + parser_free (destination_p, context_p->token.lit_location.length); + + ecma_object_t *lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p; + + while (true) + { + JERRY_ASSERT (lex_env_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) != 0 + && !ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + ecma_object_t *class_object_p = ((ecma_lexical_environment_class_t *) lex_env_p)->object_p; + + ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS); + ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p); + + if (prop_p != NULL) + { + ecma_value_t *collection_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + ecma_value_t *current_p = collection_p + 1; + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + + while (current_p < end_p) + { + current_p++; /* skip kind */ + ecma_string_t *private_key_p = ecma_get_prop_name_from_value (*current_p++); + current_p++; /* skip value */ + + JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p)); + + ecma_string_t *private_key_desc_p = + ecma_get_string_from_value (((ecma_extended_string_t *) private_key_p)->u.symbol_descriptor); + + if (ecma_compare_ecma_strings (private_key_desc_p, search_key_p)) + { + ecma_deref_ecma_string (search_key_p); + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + return true; + } + } + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + ecma_deref_ecma_string (search_key_p); + return false; +} /* parser_resolve_private_identifier_eval */ + +/** + * Resolve private identifier + */ +void +parser_resolve_private_identifier (parser_context_t *context_p) /**< context */ +{ + if ((context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL) && parser_resolve_private_identifier_eval (context_p)) + { + return; + } + + parser_private_context_t *context_iter_p = context_p->private_context_p; + + while (context_iter_p) + { + if (context_iter_p == NULL || !(context_iter_p->opts & SCANNER_PRIVATE_FIELD_ACTIVE)) + { + parser_raise_error (context_p, PARSER_ERR_UNDECLARED_PRIVATE_FIELD); + } + + if (!(context_iter_p->opts & SCANNER_SUCCESSFUL_CLASS_SCAN)) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + return; + } + + parser_private_context_t *private_context_p = context_iter_p; + + if (private_context_p == NULL) + { + parser_raise_error (context_p, PARSER_ERR_UNDECLARED_PRIVATE_FIELD); + } + + scanner_class_private_member_t *ident_iter = private_context_p->members_p; + + while (ident_iter) + { + if (lexer_compare_identifiers (context_p, &context_p->token.lit_location, &ident_iter->loc)) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + return; + } + + ident_iter = ident_iter->prev_p; + } + + context_iter_p = context_iter_p->prev_p; + } + + parser_raise_error (context_p, PARSER_ERR_UNDECLARED_PRIVATE_FIELD); +} /* parser_resolve_private_identifier */ + +/** + * Save private field context + */ +void +parser_save_private_context (parser_context_t *context_p, /**< context */ + parser_private_context_t *private_ctx_p, /**< private context */ + scanner_class_info_t *class_info_p) /**< class scanner info */ +{ + private_ctx_p->prev_p = context_p->private_context_p; + context_p->private_context_p = private_ctx_p; + + context_p->private_context_p->members_p = class_info_p->members; + context_p->private_context_p->opts = class_info_p->info.u8_arg; + class_info_p->members = NULL; +} /* parser_save_private_context */ + +/** + * Release contexts private fields + */ +static void +parser_free_private_fields (parser_context_t *context_p) /**< context */ +{ + parser_private_context_t *iter = context_p->private_context_p; + + while (iter != NULL) + { + parser_private_context_t *prev_p = iter->prev_p; + scanner_release_private_fields (iter->members_p); + iter = prev_p; + } +} /* parser_free_private_fields */ + +/** + * Restore contexts private fields + */ +void +parser_restore_private_context (parser_context_t *context_p, /**< context */ + parser_private_context_t *private_ctx_p) /**< private context */ +{ + scanner_release_private_fields (context_p->private_context_p->members_p); + context_p->private_context_p = private_ctx_p->prev_p; +} /* parser_restore_private_context */ + +/** + * Free identifiers and literals. + */ +static void +parser_free_literals (parser_list_t *literal_pool_p) /**< literals */ +{ + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + + parser_list_iterator_init (literal_pool_p, &literal_iterator); + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + util_free_literal (literal_p); + } + + parser_list_free (literal_pool_p); +} /* parser_free_literals */ + +/** + * Parse function arguments + */ +static void +parser_parse_function_arguments (parser_context_t *context_p, /**< context */ + lexer_token_type_t end_type) /**< expected end type */ +{ + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + + JERRY_ASSERT (context_p->status_flags & PARSER_IS_FUNCTION); + JERRY_ASSERT (!(context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)); + + bool has_duplicated_arg_names = false; + + if (PARSER_IS_NORMAL_ASYNC_FUNCTION (context_p->status_flags)) + { + parser_branch_t branch; + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_TRY_CREATE_CONTEXT, &branch); + parser_stack_push (context_p, &branch, sizeof (parser_branch_t)); + +#ifndef JERRY_NDEBUG + context_p->context_stack_depth = PARSER_TRY_CONTEXT_STACK_ALLOCATION; +#endif /* !JERRY_NDEBUG */ + } + + if (context_p->token.type == end_type) + { + context_p->status_flags &= (uint32_t) ~PARSER_DISALLOW_AWAIT_YIELD; + + if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) + { + scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_ARGS); + parser_emit_cbc_ext (context_p, CBC_EXT_CREATE_GENERATOR); + parser_emit_cbc (context_p, CBC_POP); + scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY); + return; + } + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + return; + } + + bool has_complex_argument = (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_HAS_COMPLEX_ARGUMENT) != 0; + bool is_strict = (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_IS_STRICT) != 0; + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_ARGS); + scanner_set_active (context_p); + + context_p->status_flags |= PARSER_FUNCTION_IS_PARSING_ARGS; + + while (true) + { + if (context_p->token.type == LEXER_THREE_DOTS) + { + if (context_p->status_flags & PARSER_IS_PROPERTY_SETTER) + { + parser_raise_error (context_p, PARSER_ERR_SETTER_REST_PARAMETER); + } + lexer_next_token (context_p); + + if (has_duplicated_arg_names) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES); + } + + context_p->status_flags |= PARSER_FUNCTION_HAS_REST_PARAM | PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT; + } + + if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE) + { + if (has_duplicated_arg_names) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES); + } + + context_p->status_flags |= PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT; + + if (!(context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)) + { + parser_emit_cbc_literal (context_p, + CBC_PUSH_LITERAL, + (uint16_t) (PARSER_REGISTER_START + context_p->argument_count)); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_REST_OBJECT); + } + + uint32_t flags = + (PARSER_PATTERN_BINDING | PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_LOCAL | PARSER_PATTERN_ARGUMENTS); + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER) + { + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags |= PARSER_PATTERN_HAS_REST_ELEMENT; + } + + if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + parser_raise_error (context_p, PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER); + } + + if (context_p->argument_length == UINT16_MAX) + { + context_p->argument_length = context_p->argument_count; + } + + flags |= PARSER_PATTERN_TARGET_DEFAULT; + } + else if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS) + { + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags |= PARSER_PATTERN_HAS_REST_ELEMENT; + } + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + else + { + parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN); + } + } + + parser_parse_initializer (context_p, (parser_pattern_flags_t) flags); + + context_p->argument_count++; + if (context_p->argument_count >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED); + } + + if (context_p->token.type != LEXER_COMMA) + { + if (context_p->token.type != end_type) + { + parser_error_msg_t error = + ((end_type == LEXER_RIGHT_PAREN) ? PARSER_ERR_RIGHT_PAREN_EXPECTED : PARSER_ERR_IDENTIFIER_EXPECTED); + + parser_raise_error (context_p, error); + } + break; + } + + lexer_next_token (context_p); + + if (context_p->token.type == end_type) + { + break; + } + continue; + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL); + + if (context_p->token.keyword_type >= LEXER_FIRST_NON_STRICT_ARGUMENTS) + { + context_p->status_flags |= PARSER_HAS_NON_STRICT_ARG; + } + + if (JERRY_UNLIKELY (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT)) + { + if ((context_p->status_flags & PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT) + || (context_p->status_flags & PARSER_IS_ARROW_FUNCTION)) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES); + } + has_duplicated_arg_names = true; + + context_p->status_flags |= PARSER_HAS_NON_STRICT_ARG; + } + else + { + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT; + } + + lexer_next_token (context_p); + + uint16_t literal_index = context_p->lit_object.index; + + if (context_p->token.type == LEXER_ASSIGN) + { + JERRY_ASSERT (has_complex_argument); + + if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + parser_raise_error (context_p, PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER); + } + + if (context_p->argument_length == UINT16_MAX) + { + context_p->argument_length = context_p->argument_count; + } + + parser_branch_t skip_init; + + if (has_duplicated_arg_names) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES); + } + + context_p->status_flags |= PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT; + + /* LEXER_ASSIGN does not overwrite lit_object. */ + parser_emit_cbc_literal (context_p, + CBC_PUSH_LITERAL, + (uint16_t) (PARSER_REGISTER_START + context_p->argument_count)); + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init); + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + parser_set_branch_to_current_position (context_p, &skip_init); + + uint16_t opcode = CBC_ASSIGN_LET_CONST; + + if (literal_index >= PARSER_REGISTER_START) + { + opcode = CBC_MOV_IDENT; + } + else if (!scanner_literal_is_created (context_p, literal_index)) + { + opcode = CBC_INIT_ARG_OR_CATCH; + } + + parser_emit_cbc_literal (context_p, opcode, literal_index); + } + else if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_REST_OBJECT); + + uint16_t opcode = CBC_MOV_IDENT; + + if (literal_index < PARSER_REGISTER_START) + { + opcode = CBC_INIT_ARG_OR_CATCH; + + if (scanner_literal_is_created (context_p, literal_index)) + { + opcode = CBC_ASSIGN_LET_CONST; + } + } + + parser_emit_cbc_literal (context_p, opcode, literal_index); + } + else if (has_complex_argument && literal_index < PARSER_REGISTER_START) + { + uint16_t opcode = CBC_INIT_ARG_OR_FUNC; + + if (scanner_literal_is_created (context_p, literal_index)) + { + opcode = CBC_ASSIGN_LET_CONST_LITERAL; + } + + parser_emit_cbc_literal_value (context_p, + opcode, + (uint16_t) (PARSER_REGISTER_START + context_p->argument_count), + literal_index); + } + + context_p->argument_count++; + if (context_p->argument_count >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED); + } + + if (context_p->token.type != LEXER_COMMA) + { + if (context_p->token.type != end_type) + { + parser_error_msg_t error = + ((end_type == LEXER_RIGHT_PAREN) ? PARSER_ERR_RIGHT_PAREN_EXPECTED : PARSER_ERR_IDENTIFIER_EXPECTED); + + parser_raise_error (context_p, error); + } + break; + } + + if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + parser_raise_error (context_p, PARSER_ERR_FORMAL_PARAM_AFTER_REST_PARAMETER); + } + + lexer_next_token (context_p); + + if (context_p->token.type == end_type) + { + break; + } + } + + scanner_revert_active (context_p); + + JERRY_ASSERT (has_complex_argument || !(context_p->status_flags & PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT)); + + if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) + { + parser_emit_cbc_ext (context_p, CBC_EXT_CREATE_GENERATOR); + parser_emit_cbc (context_p, CBC_POP); + } + + if (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED) + { + if ((context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_LEXICAL_ENV_NEEDED) + || scanner_is_context_needed (context_p, PARSER_CHECK_FUNCTION_CONTEXT)) + { + context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED; + + parser_branch_t branch; + parser_emit_cbc_forward_branch (context_p, CBC_BLOCK_CREATE_CONTEXT, &branch); + parser_stack_push (context_p, &branch, sizeof (parser_branch_t)); + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + } + else + { + context_p->status_flags &= (uint32_t) ~PARSER_LEXICAL_BLOCK_NEEDED; + } + } + + context_p->status_flags &= (uint32_t) ~(PARSER_DISALLOW_AWAIT_YIELD | PARSER_FUNCTION_IS_PARSING_ARGS); + scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY); + + if (is_strict) + { + context_p->status_flags |= PARSER_IS_STRICT; + } +} /* parser_parse_function_arguments */ + +#ifndef JERRY_NDEBUG +JERRY_STATIC_ASSERT ((PARSER_SCANNING_SUCCESSFUL == PARSER_HAS_LATE_LIT_INIT), + parser_scanning_successful_should_share_the_bit_position_with_parser_has_late_lit_init); +#endif /* !JERRY_NDEBUG */ + +/** + * Parser script size + */ +static size_t +parser_script_size (parser_context_t *context_p) /**< context */ +{ + size_t script_size = sizeof (cbc_script_t); + + if (context_p->user_value != ECMA_VALUE_EMPTY) + { + script_size += sizeof (ecma_value_t); + } + +#if JERRY_FUNCTION_TO_STRING + if (context_p->argument_list != ECMA_VALUE_EMPTY) + { + script_size += sizeof (ecma_value_t); + } +#endif /* JERRY_FUNCTION_TO_STRING */ + +#if JERRY_MODULE_SYSTEM + if (context_p->global_status_flags & ECMA_PARSE_INTERNAL_HAS_IMPORT_META) + { + script_size += sizeof (ecma_value_t); + } +#endif /* JERRY_MODULE_SYSTEM */ + return script_size; +} /* parser_script_size */ + +#if JERRY_SOURCE_NAME +/** + * Parser resource name + */ +static ecma_value_t +parser_source_name (parser_context_t *context_p) /**< context */ +{ + if (context_p->options_p != NULL && (context_p->options_p->options & JERRY_PARSE_HAS_SOURCE_NAME)) + { + JERRY_ASSERT (ecma_is_value_string (context_p->options_p->source_name)); + + ecma_ref_ecma_string (ecma_get_string_from_value (context_p->options_p->source_name)); + return context_p->options_p->source_name; + } + + if (context_p->global_status_flags & ECMA_PARSE_EVAL) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_EVAL); + } + + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_ANON); +} /* parser_source_name */ +#endif /* JERRY_SOURCE_NAME */ + +/** + * Parse and compile EcmaScript source code + * + * Note: source must be a valid UTF-8 string + * + * @return compiled code + */ +static ecma_compiled_code_t * +parser_parse_source (void *source_p, /**< source code */ + uint32_t parse_opts, /**< ecma_parse_opts_t option bits */ + const jerry_parse_options_t *options_p) /**< additional configuration options */ +{ + parser_context_t context; + ecma_compiled_code_t *compiled_code_p; + + context.error = PARSER_ERR_NO_ERROR; + context.status_flags = parse_opts & PARSER_STRICT_MODE_MASK; + context.global_status_flags = parse_opts; + + context.status_flags |= PARSER_RESTORE_STATUS_FLAGS (parse_opts); + context.tagged_template_literal_cp = JMEM_CP_NULL; + + context.stack_depth = 0; + context.stack_limit = 0; + context.options_p = options_p; + context.script_p = NULL; + context.arguments_start_p = NULL; + context.arguments_size = 0; +#if JERRY_MODULE_SYSTEM + if (context.global_status_flags & ECMA_PARSE_MODULE) + { + context.status_flags |= PARSER_IS_STRICT; + } + + context.module_names_p = NULL; +#endif /* JERRY_MODULE_SYSTEM */ + + context.argument_list = ECMA_VALUE_EMPTY; + + if (context.options_p != NULL && (context.options_p->options & JERRY_PARSE_HAS_ARGUMENT_LIST)) + { + context.argument_list = context.options_p->argument_list; + } + else if (context.global_status_flags & ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE) + { + JERRY_ASSERT (context.global_status_flags & ECMA_PARSE_HAS_SOURCE_VALUE); + context.argument_list = ((ecma_value_t *) source_p)[1]; + } + + if (context.argument_list != ECMA_VALUE_EMPTY) + { + JERRY_ASSERT (ecma_is_value_string (context.argument_list)); + + context.status_flags |= PARSER_IS_FUNCTION; + + if (parse_opts & ECMA_PARSE_GENERATOR_FUNCTION) + { + context.status_flags |= PARSER_IS_GENERATOR_FUNCTION; + } + if (parse_opts & ECMA_PARSE_ASYNC_FUNCTION) + { + context.status_flags |= PARSER_IS_ASYNC_FUNCTION; + } + + ecma_string_t *string_p = ecma_get_string_from_value (context.argument_list); + uint8_t flags = ECMA_STRING_FLAG_EMPTY; + + context.arguments_start_p = ecma_string_get_chars (string_p, &context.arguments_size, NULL, NULL, &flags); + + if (flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + context.global_status_flags |= ECMA_PARSE_INTERNAL_FREE_ARG_LIST; + } + } + + if (!(context.global_status_flags & ECMA_PARSE_HAS_SOURCE_VALUE)) + { + context.source_start_p = ((parser_source_char_t *) source_p)->source_p; + context.source_size = (lit_utf8_size_t) ((parser_source_char_t *) source_p)->source_size; + } + else + { + ecma_value_t source = ((ecma_value_t *) source_p)[0]; + + JERRY_ASSERT (ecma_is_value_string (source)); + + ecma_string_t *string_p = ecma_get_string_from_value (source); + uint8_t flags = ECMA_STRING_FLAG_EMPTY; + + context.source_start_p = ecma_string_get_chars (string_p, &context.source_size, NULL, NULL, &flags); + + if (flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + context.global_status_flags |= ECMA_PARSE_INTERNAL_FREE_SOURCE; + } + } + + context.user_value = ECMA_VALUE_EMPTY; + + if ((context.global_status_flags & ECMA_PARSE_EVAL) && JERRY_CONTEXT (vm_top_context_p) != NULL) + { + const ecma_compiled_code_t *bytecode_header_p = JERRY_CONTEXT (vm_top_context_p)->shared_p->bytecode_header_p; + +#if JERRY_SNAPSHOT_EXEC + if (JERRY_LIKELY (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))) + { +#endif /* JERRY_SNAPSHOT_EXEC */ + ecma_value_t parent_script_value = ((cbc_uint8_arguments_t *) bytecode_header_p)->script_value; + ; + cbc_script_t *parent_script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, parent_script_value); + + if (parent_script_p->refs_and_type & CBC_SCRIPT_HAS_USER_VALUE) + { + context.user_value = CBC_SCRIPT_GET_USER_VALUE (parent_script_p); + } +#if JERRY_SNAPSHOT_EXEC + } +#endif /* JERRY_SNAPSHOT_EXEC */ + } + else if (context.options_p != NULL && (context.options_p->options & JERRY_PARSE_HAS_USER_VALUE)) + { + context.user_value = context.options_p->user_value; + } + + context.last_context_p = NULL; + context.last_statement.current_p = NULL; + context.token.flags = 0; + lexer_init_line_info (&context); + + scanner_info_t scanner_info_end; + scanner_info_end.next_p = NULL; + scanner_info_end.source_p = NULL; + scanner_info_end.type = SCANNER_TYPE_END; + context.next_scanner_info_p = &scanner_info_end; + context.active_scanner_info_p = NULL; + context.skipped_scanner_info_p = NULL; + context.skipped_scanner_info_end_p = NULL; + + context.last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + + context.argument_count = 0; + context.argument_length = UINT16_MAX; + context.register_count = 0; + context.literal_count = 0; + + parser_cbc_stream_init (&context.byte_code); + context.byte_code_size = 0; + parser_list_init (&context.literal_pool, + sizeof (lexer_literal_t), + (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_literal_t))); + context.scope_stack_p = NULL; + context.scope_stack_size = 0; + context.scope_stack_top = 0; + context.scope_stack_reg_top = 0; + context.scope_stack_global_end = 0; + context.tagged_template_literal_cp = JMEM_CP_NULL; + context.private_context_p = NULL; + +#ifndef JERRY_NDEBUG + context.context_stack_depth = 0; +#endif /* !JERRY_NDEBUG */ + +#if JERRY_LINE_INFO + context.line_info_p = NULL; +#endif /* JERRY_LINE_INFO */ + +#if JERRY_FUNCTION_TO_STRING + context.function_start_p = NULL; + context.function_end_p = NULL; +#endif /* JERRY_FUNCTION_TO_STRING */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + context.is_show_opcodes = (JERRY_CONTEXT (jerry_init_flags) & JERRY_INIT_SHOW_OPCODES); + context.total_byte_code_size = 0; + + if (context.is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- %s parsing start ---\n\n", (context.arguments_start_p == NULL) ? "Script" : "Function"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + scanner_scan_all (&context); + + if (JERRY_UNLIKELY (context.error != PARSER_ERR_NO_ERROR)) + { + JERRY_ASSERT (context.error == PARSER_ERR_OUT_OF_MEMORY); + + /* It is unlikely that memory can be allocated in an out-of-memory + * situation. However, a simple value can still be thrown. */ + jcontext_raise_exception (ECMA_VALUE_NULL); + return NULL; + } + + if (context.arguments_start_p == NULL) + { + context.source_p = context.source_start_p; + context.source_end_p = context.source_start_p + context.source_size; + } + else + { + context.source_p = context.arguments_start_p; + context.source_end_p = context.arguments_start_p + context.arguments_size; + } + + context.u.allocated_buffer_p = NULL; + context.token.flags = 0; + lexer_init_line_info (&context); + + parser_stack_init (&context); + + JERRY_ASSERT (context.next_scanner_info_p->source_p == context.source_p); + JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + + if (context.next_scanner_info_p->u8_arg & SCANNER_FUNCTION_IS_STRICT) + { + context.status_flags |= PARSER_IS_STRICT; + } + + PARSER_TRY (context.try_buffer) + { + context.script_p = (cbc_script_t *) parser_malloc (&context, parser_script_size (&context)); + + CBC_SCRIPT_SET_TYPE (context.script_p, context.user_value, CBC_SCRIPT_REF_ONE); + + if (context.global_status_flags & (ECMA_PARSE_EVAL | ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE)) + { + context.script_p->refs_and_type |= CBC_SCRIPT_IS_EVAL_CODE; + } + +#if JERRY_BUILTIN_REALMS + context.script_p->realm_p = (ecma_object_t *) JERRY_CONTEXT (global_object_p); +#endif /* JERRY_BUILTIN_REALMS */ + +#if JERRY_SOURCE_NAME + context.script_p->source_name = parser_source_name (&context); +#endif /* JERRY_SOURCE_NAME */ + + ECMA_SET_INTERNAL_VALUE_POINTER (context.script_value, context.script_p); + + /* Pushing a dummy value ensures the stack is never empty. + * This simplifies the stack management routines. */ + parser_stack_push_uint8 (&context, CBC_MAXIMUM_BYTE_VALUE); + /* The next token must always be present to make decisions + * in the parser. Therefore when a token is consumed, the + * lexer_next_token() must be immediately called. */ + lexer_next_token (&context); + + if (context.arguments_start_p != NULL) + { + parser_parse_function_arguments (&context, LEXER_EOS); + + JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS); + scanner_release_next (&context, sizeof (scanner_info_t)); + + context.source_p = context.source_start_p; + context.source_end_p = context.source_start_p + context.source_size; + lexer_init_line_info (&context); + + lexer_next_token (&context); + } +#if JERRY_MODULE_SYSTEM + else if (parse_opts & ECMA_PARSE_MODULE) + { + parser_branch_t branch; + parser_emit_cbc_forward_branch (&context, CBC_JUMP_FORWARD, &branch); + + scanner_create_variables (&context, SCANNER_CREATE_VARS_IS_MODULE); + parser_emit_cbc (&context, CBC_RETURN_FUNCTION_END); + + parser_set_branch_to_current_position (&context, &branch); + } +#endif /* JERRY_MODULE_SYSTEM */ + else + { + JERRY_ASSERT (context.next_scanner_info_p->source_p == context.source_start_p + && context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + + if (scanner_is_context_needed (&context, PARSER_CHECK_GLOBAL_CONTEXT)) + { + context.status_flags |= PARSER_LEXICAL_BLOCK_NEEDED; + } + + if (!(parse_opts & ECMA_PARSE_EVAL)) + { + scanner_check_variables (&context); + } + + scanner_create_variables (&context, SCANNER_CREATE_VARS_IS_SCRIPT); + } + + parser_parse_statements (&context); + + JERRY_ASSERT (context.last_statement.current_p == NULL); + + JERRY_ASSERT (context.last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + JERRY_ASSERT (context.u.allocated_buffer_p == NULL); + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (context.status_flags & PARSER_SCANNING_SUCCESSFUL); + JERRY_ASSERT (!(context.global_status_flags & ECMA_PARSE_INTERNAL_FOR_IN_OFF_CONTEXT_ERROR)); + context.status_flags &= (uint32_t) ~PARSER_SCANNING_SUCCESSFUL; +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (!(context.status_flags & PARSER_HAS_LATE_LIT_INIT)); + + compiled_code_p = parser_post_processing (&context); + parser_list_free (&context.literal_pool); + + /* When parsing is successful, only the dummy value can be remained on the stack. */ + JERRY_ASSERT (context.stack_top_uint8 == CBC_MAXIMUM_BYTE_VALUE && context.stack.last_position == 1 + && context.stack.first_p != NULL && context.stack.first_p->next_p == NULL + && context.stack.last_p == NULL); + + JERRY_ASSERT (context.arguments_start_p != NULL || !(context.status_flags & PARSER_ARGUMENTS_NEEDED)); + + context.script_p->refs_and_type -= CBC_SCRIPT_REF_ONE; + + if (context.user_value != ECMA_VALUE_EMPTY) + { + CBC_SCRIPT_GET_USER_VALUE (context.script_p) = ecma_copy_value_if_not_object (context.user_value); + } + +#if JERRY_MODULE_SYSTEM + if (context.global_status_flags & ECMA_PARSE_INTERNAL_HAS_IMPORT_META) + { + int idx = (context.user_value != ECMA_VALUE_EMPTY) ? 1 : 0; + ecma_value_t module = ecma_make_object_value ((ecma_object_t *) JERRY_CONTEXT (module_current_p)); + + CBC_SCRIPT_GET_OPTIONAL_VALUES (context.script_p)[idx] = module; + context.script_p->refs_and_type |= CBC_SCRIPT_HAS_IMPORT_META; + } +#endif /* JERRY_MODULE_SYSTEM */ + +#if JERRY_FUNCTION_TO_STRING + if (!(context.global_status_flags & ECMA_PARSE_HAS_SOURCE_VALUE)) + { + ecma_string_t *string_p; + + if (context.global_status_flags & ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER) + { + string_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (context.source_start_p, context.source_size); + } + else + { + string_p = ecma_new_ecma_string_from_utf8 (context.source_start_p, context.source_size); + } + + context.script_p->source_code = ecma_make_string_value (string_p); + } + else + { + ecma_value_t source = ((ecma_value_t *) source_p)[0]; + + ecma_ref_ecma_string (ecma_get_string_from_value (source)); + context.script_p->source_code = source; + } + + if (context.argument_list != ECMA_VALUE_EMPTY) + { + int idx = (context.user_value != ECMA_VALUE_EMPTY) ? 1 : 0; + + CBC_SCRIPT_GET_OPTIONAL_VALUES (context.script_p)[idx] = context.argument_list; + + ecma_ref_ecma_string (ecma_get_string_from_value (context.argument_list)); + context.script_p->refs_and_type |= CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS; + } +#endif /* JERRY_FUNCTION_TO_STRING */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context.is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n%s parsing successfully completed. Total byte code size: %d bytes\n", + (context.arguments_start_p == NULL) ? "Script" : "Function", + (int) context.total_byte_code_size); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + } + PARSER_CATCH + { + if (context.last_statement.current_p != NULL) + { + parser_free_jumps (context.last_statement); + } + + parser_free_allocated_buffer (&context); + + scanner_cleanup (&context); + +#if JERRY_MODULE_SYSTEM + if (context.module_names_p != NULL) + { + ecma_module_release_module_names (context.module_names_p); + } +#endif /* JERRY_MODULE_SYSTEM */ + + compiled_code_p = NULL; + parser_free_literals (&context.literal_pool); + parser_cbc_stream_free (&context.byte_code); + +#if JERRY_SOURCE_NAME + ecma_deref_ecma_string (ecma_get_string_from_value (context.script_p->source_name)); +#endif /* JERRY_SOURCE_NAME */ + + if (context.script_p != NULL) + { + JERRY_ASSERT (context.script_p->refs_and_type >= CBC_SCRIPT_REF_ONE); + jmem_heap_free_block (context.script_p, parser_script_size (&context)); + } + } + PARSER_TRY_END + + if (context.scope_stack_p != NULL) + { + parser_free (context.scope_stack_p, context.scope_stack_size * sizeof (parser_scope_stack_t)); + } + +#if JERRY_LINE_INFO + parser_line_info_free (context.line_info_p); +#endif /* JERRY_LINE_INFO */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context.is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- %s parsing end ---\n\n", (context.arguments_start_p == NULL) ? "Script" : "Function"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_stack_free (&context); + + if (context.global_status_flags & ECMA_PARSE_INTERNAL_FREE_SOURCE) + { + jmem_heap_free_block ((void *) context.source_start_p, context.source_size); + } + + if (context.global_status_flags & ECMA_PARSE_INTERNAL_FREE_ARG_LIST) + { + jmem_heap_free_block ((void *) context.arguments_start_p, context.arguments_size); + } + + if (compiled_code_p != NULL) + { + return compiled_code_p; + } + + if (context.error == PARSER_ERR_OUT_OF_MEMORY) + { + /* It is unlikely that memory can be allocated in an out-of-memory + * situation. However, a simple value can still be thrown. */ + jcontext_raise_exception (ECMA_VALUE_NULL); + return NULL; + } +#if (JERRY_STACK_LIMIT != 0) + if (context.error == PARSER_ERR_STACK_OVERFLOW) + { + ecma_raise_standard_error (JERRY_ERROR_RANGE, ECMA_ERR_MAXIMUM_CALL_STACK_SIZE_EXCEEDED); + return NULL; + } +#endif /* JERRY_STACK_LIMIT != 0 */ + +#if JERRY_ERROR_MESSAGES + ecma_string_t *err_str_p; + + if (context.error == PARSER_ERR_INVALID_REGEXP) + { + ecma_value_t error = jcontext_take_exception (); + ecma_property_t *prop_p = + ecma_find_named_property (ecma_get_object_from_value (error), ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE)); + ecma_free_value (error); + JERRY_ASSERT (prop_p); + err_str_p = ecma_get_string_from_value (ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + ecma_ref_ecma_string (err_str_p); + } + else + { + err_str_p = ecma_new_ecma_external_string_from_cesu8 (parser_get_error_utf8 (context.error), + parser_get_error_size (context.error), + NULL); + } + ecma_value_t err_str_val = ecma_make_string_value (err_str_p); + ecma_value_t line_str_val = ecma_make_uint32_value (context.token.line); + ecma_value_t col_str_val = ecma_make_uint32_value (context.token.column); + ecma_value_t source_name = parser_source_name (&context); + + ecma_raise_standard_error_with_format (JERRY_ERROR_SYNTAX, + "% [%:%:%]", + err_str_val, + source_name, + line_str_val, + col_str_val); + + ecma_free_value (source_name); + ecma_free_value (col_str_val); + ecma_free_value (line_str_val); + ecma_deref_ecma_string (err_str_p); +#else /* !JERRY_ERROR_MESSAGES */ + if (context.error == PARSER_ERR_INVALID_REGEXP) + { + jcontext_release_exception (); + } + + ecma_raise_syntax_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + + return NULL; +} /* parser_parse_source */ + +/** + * Save parser context before function parsing. + */ +static void +parser_save_context (parser_context_t *context_p, /**< context */ + parser_saved_context_t *saved_context_p) /**< target for saving the context */ +{ + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + if (context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS) + { + context_p->status_flags |= PARSER_LEXICAL_BLOCK_NEEDED; + } + + /* Save private part of the context. */ + + saved_context_p->status_flags = context_p->status_flags; + saved_context_p->stack_depth = context_p->stack_depth; + saved_context_p->stack_limit = context_p->stack_limit; + saved_context_p->prev_context_p = context_p->last_context_p; + saved_context_p->last_statement = context_p->last_statement; + + saved_context_p->argument_count = context_p->argument_count; + saved_context_p->argument_length = context_p->argument_length; + saved_context_p->register_count = context_p->register_count; + saved_context_p->literal_count = context_p->literal_count; + + saved_context_p->byte_code = context_p->byte_code; + saved_context_p->byte_code_size = context_p->byte_code_size; + saved_context_p->literal_pool_data = context_p->literal_pool.data; + saved_context_p->scope_stack_p = context_p->scope_stack_p; + saved_context_p->scope_stack_size = context_p->scope_stack_size; + saved_context_p->scope_stack_top = context_p->scope_stack_top; + saved_context_p->scope_stack_reg_top = context_p->scope_stack_reg_top; + saved_context_p->scope_stack_global_end = context_p->scope_stack_global_end; + saved_context_p->tagged_template_literal_cp = context_p->tagged_template_literal_cp; + +#ifndef JERRY_NDEBUG + saved_context_p->context_stack_depth = context_p->context_stack_depth; +#endif /* !JERRY_NDEBUG */ + +#if JERRY_LINE_INFO + saved_context_p->line_info_p = context_p->line_info_p; +#endif /* JERRY_LINE_INFO */ + +#if JERRY_FUNCTION_TO_STRING + saved_context_p->function_start_p = context_p->function_start_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + + /* Reset private part of the context. */ + + context_p->status_flags &= PARSER_IS_STRICT; + context_p->stack_depth = 0; + context_p->stack_limit = 0; + context_p->last_context_p = saved_context_p; + context_p->last_statement.current_p = NULL; + + context_p->argument_count = 0; + context_p->argument_length = UINT16_MAX; + context_p->register_count = 0; + context_p->literal_count = 0; + + parser_cbc_stream_init (&context_p->byte_code); + context_p->byte_code_size = 0; + parser_list_reset (&context_p->literal_pool); + context_p->scope_stack_p = NULL; + context_p->scope_stack_size = 0; + context_p->scope_stack_top = 0; + context_p->scope_stack_reg_top = 0; + context_p->scope_stack_global_end = 0; + context_p->tagged_template_literal_cp = JMEM_CP_NULL; + +#ifndef JERRY_NDEBUG + context_p->context_stack_depth = 0; +#endif /* !JERRY_NDEBUG */ + +#if JERRY_LINE_INFO + context_p->line_info_p = NULL; +#endif /* JERRY_LINE_INFO */ +} /* parser_save_context */ + +/** + * Restore parser context after function parsing. + */ +static void +parser_restore_context (parser_context_t *context_p, /**< context */ + parser_saved_context_t *saved_context_p) /**< target for saving the context */ +{ + parser_list_free (&context_p->literal_pool); + + if (context_p->scope_stack_p != NULL) + { + parser_free (context_p->scope_stack_p, context_p->scope_stack_size * sizeof (parser_scope_stack_t)); + } + +#if JERRY_LINE_INFO + parser_line_info_free (context_p->line_info_p); +#endif /* JERRY_LINE_INFO */ + + /* Restore private part of the context. */ + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + context_p->status_flags = saved_context_p->status_flags; + context_p->stack_depth = saved_context_p->stack_depth; + context_p->stack_limit = saved_context_p->stack_limit; + context_p->last_context_p = saved_context_p->prev_context_p; + context_p->last_statement = saved_context_p->last_statement; + + context_p->argument_count = saved_context_p->argument_count; + context_p->argument_length = saved_context_p->argument_length; + context_p->register_count = saved_context_p->register_count; + context_p->literal_count = saved_context_p->literal_count; + + context_p->byte_code = saved_context_p->byte_code; + context_p->byte_code_size = saved_context_p->byte_code_size; + context_p->literal_pool.data = saved_context_p->literal_pool_data; + context_p->scope_stack_p = saved_context_p->scope_stack_p; + context_p->scope_stack_size = saved_context_p->scope_stack_size; + context_p->scope_stack_top = saved_context_p->scope_stack_top; + context_p->scope_stack_reg_top = saved_context_p->scope_stack_reg_top; + context_p->scope_stack_global_end = saved_context_p->scope_stack_global_end; + context_p->tagged_template_literal_cp = saved_context_p->tagged_template_literal_cp; + +#ifndef JERRY_NDEBUG + context_p->context_stack_depth = saved_context_p->context_stack_depth; +#endif /* !JERRY_NDEBUG */ + +#if JERRY_LINE_INFO + context_p->line_info_p = saved_context_p->line_info_p; +#endif /* JERRY_LINE_INFO */ +} /* parser_restore_context */ + +/** + * Parse function code + * + * @return compiled code + */ +ecma_compiled_code_t * +parser_parse_function (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< extra status flags */ +{ + parser_saved_context_t saved_context; + ecma_compiled_code_t *compiled_code_p; + + JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION); + parser_save_context (context_p, &saved_context); + context_p->status_flags |= status_flags; + context_p->status_flags |= PARSER_ALLOW_NEW_TARGET; + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- %s parsing start ---\n\n", + (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR) ? "Class constructor" : "Function"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIST_EXPECTED); + } + + lexer_next_token (context_p); + + parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN); + lexer_next_token (context_p); + + if ((context_p->status_flags & PARSER_IS_PROPERTY_GETTER) && context_p->argument_count != 0) + { + parser_raise_error (context_p, PARSER_ERR_NO_ARGUMENTS_EXPECTED); + } + + if ((context_p->status_flags & PARSER_IS_PROPERTY_SETTER) && context_p->argument_count != 1) + { + parser_raise_error (context_p, PARSER_ERR_ONE_ARGUMENT_EXPECTED); + } + + if ((context_p->status_flags & (PARSER_CLASS_CONSTRUCTOR | PARSER_ALLOW_SUPER_CALL)) == PARSER_CLASS_CONSTRUCTOR) + { + parser_emit_cbc_ext (context_p, CBC_EXT_RUN_FIELD_INIT); + parser_flush_cbc (context_p); + } + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes && (context_p->status_flags & PARSER_HAS_NON_STRICT_ARG)) + { + JERRY_DEBUG_MSG (" Note: legacy (non-strict) argument definition\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + + lexer_next_token (context_p); + parser_parse_statements (context_p); + compiled_code_p = parser_post_processing (context_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- %s parsing end ---\n\n", + (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR) ? "Class constructor" : "Function"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_restore_context (context_p, &saved_context); + + return compiled_code_p; +} /* parser_parse_function */ + +/** + * Parse static class block code + * + * @return compiled code + */ +ecma_compiled_code_t * +parser_parse_class_static_block (parser_context_t *context_p) /**< context */ +{ + parser_saved_context_t saved_context; + ecma_compiled_code_t *compiled_code_p; + + parser_save_context (context_p, &saved_context); + context_p->status_flags |= (PARSER_IS_CLASS_STATIC_BLOCK | PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER + | PARSER_INSIDE_CLASS_FIELD | PARSER_ALLOW_NEW_TARGET | PARSER_DISALLOW_AWAIT_YIELD); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Static class block parsing start ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + lexer_next_token (context_p); + + parser_parse_statements (context_p); + compiled_code_p = parser_post_processing (context_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Static class block parsing end ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_restore_context (context_p, &saved_context); + + return compiled_code_p; +} /* parser_parse_class_static_block */ + +/** + * Parse arrow function code + * + * @return compiled code + */ +ecma_compiled_code_t * +parser_parse_arrow_function (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< extra status flags */ +{ + parser_saved_context_t saved_context; + ecma_compiled_code_t *compiled_code_p; + + JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION); + JERRY_ASSERT (status_flags & PARSER_IS_ARROW_FUNCTION); + parser_save_context (context_p, &saved_context); + context_p->status_flags |= status_flags; + context_p->status_flags |= + saved_context.status_flags & (PARSER_ALLOW_NEW_TARGET | PARSER_ALLOW_SUPER | PARSER_ALLOW_SUPER_CALL); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Arrow function parsing start ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + /* The `await` keyword is disallowed in the IdentifierReference position */ + if (status_flags & PARSER_IS_CLASS_STATIC_BLOCK) + { + context_p->status_flags |= PARSER_DISALLOW_AWAIT_YIELD; + } + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + lexer_next_token (context_p); + parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN); + lexer_next_token (context_p); + } + else + { + parser_parse_function_arguments (context_p, LEXER_ARROW); + } + + /* The `await` keyword is interpreted as an identifier within the body of arrow functions */ + if (status_flags & PARSER_IS_CLASS_STATIC_BLOCK) + { + context_p->status_flags &= (uint32_t) ~(PARSER_DISALLOW_AWAIT_YIELD | PARSER_IS_CLASS_STATIC_BLOCK); + } + + JERRY_ASSERT (context_p->token.type == LEXER_ARROW); + + lexer_next_token (context_p); + bool next_token_needed = false; + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + lexer_next_token (context_p); + + context_p->status_flags |= PARSER_IS_CLOSURE; + parser_parse_statements (context_p); + + /* Unlike normal function, arrow functions consume their close brace. */ + JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE); + next_token_needed = true; + } + else + { + if (context_p->status_flags & PARSER_IS_STRICT && context_p->status_flags & PARSER_HAS_NON_STRICT_ARG) + { + parser_raise_error (context_p, PARSER_ERR_NON_STRICT_ARG_DEFINITION); + } + +#if JERRY_LINE_INFO + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); +#endif /* JERRY_LINE_INFO */ + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = CBC_RETURN_WITH_LITERAL; + } + else + { + parser_emit_cbc (context_p, CBC_RETURN); + } + parser_flush_cbc (context_p); + + lexer_update_await_yield (context_p, saved_context.status_flags); + } + + compiled_code_p = parser_post_processing (context_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Arrow function parsing end ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_restore_context (context_p, &saved_context); + + if (next_token_needed) + { + lexer_next_token (context_p); + } + + return compiled_code_p; +} /* parser_parse_arrow_function */ + +/** + * Parse class fields + * + * @return compiled code + */ +ecma_compiled_code_t * +parser_parse_class_fields (parser_context_t *context_p) /**< context */ +{ + parser_saved_context_t saved_context; + ecma_compiled_code_t *compiled_code_p; + + uint32_t extra_status_flags = context_p->status_flags & PARSER_INSIDE_WITH; + + parser_save_context (context_p, &saved_context); + context_p->status_flags |= (PARSER_IS_FUNCTION | PARSER_ALLOW_SUPER | PARSER_INSIDE_CLASS_FIELD + | PARSER_ALLOW_NEW_TARGET | extra_status_flags); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Class fields parsing start ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + const uint8_t *source_end_p = context_p->source_end_p; + bool first_computed_class_field = true; + scanner_location_t end_location; + scanner_get_location (&end_location, context_p); + + do + { + uint8_t class_field_type = context_p->stack_top_uint8; + parser_stack_pop_uint8 (context_p); + + scanner_range_t range = { 0 }; + + if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED) + { + parser_stack_pop (context_p, &range, sizeof (scanner_range_t)); + } + else if (class_field_type & PARSER_CLASS_FIELD_NORMAL) + { + parser_stack_pop (context_p, &range.start_location, sizeof (scanner_location_t)); + } + + uint16_t literal_index = 0; + bool is_private = false; + + if (class_field_type & PARSER_CLASS_FIELD_NORMAL) + { + scanner_set_location (context_p, &range.start_location); + + if (class_field_type & PARSER_CLASS_FIELD_STATIC_BLOCK) + { + scanner_seek (context_p); + JERRY_ASSERT (context_p->source_p[1] == LIT_CHAR_LEFT_BRACE); + context_p->source_p += 2; + context_p->source_end_p = source_end_p; + + uint16_t func_index = lexer_construct_class_static_block_function (context_p); + + parser_emit_cbc_ext_literal (context_p, CBC_EXT_CLASS_CALL_STATIC_BLOCK, func_index); + continue; + } + + uint32_t ident_opts = LEXER_OBJ_IDENT_ONLY_IDENTIFIERS; + is_private = context_p->source_p[-1] == LIT_CHAR_HASHMARK; + + if (is_private) + { + ident_opts |= LEXER_OBJ_IDENT_CLASS_PRIVATE; + } + + context_p->source_end_p = source_end_p; + scanner_seek (context_p); + + lexer_expect_object_literal_id (context_p, ident_opts); + + literal_index = context_p->lit_object.index; + + if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED) + { + lexer_next_token (context_p); + JERRY_ASSERT (context_p->token.type == LEXER_ASSIGN); + } + } + else if (first_computed_class_field) + { + parser_emit_cbc (context_p, CBC_PUSH_NUMBER_0); + first_computed_class_field = false; + } + + if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED) + { + if (!(class_field_type & PARSER_CLASS_FIELD_NORMAL)) + { + scanner_set_location (context_p, &range.start_location); + scanner_seek (context_p); + } + + context_p->source_end_p = range.source_end_p; + lexer_next_token (context_p); + +#if JERRY_LINE_INFO + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); +#endif /* JERRY_LINE_INFO */ + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->token.type != LEXER_EOS) + { + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + } + else + { + parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED); + } + + if (class_field_type & PARSER_CLASS_FIELD_NORMAL) + { + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, literal_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + uint32_t function_name_status_flags = is_private ? PARSER_PRIVATE_FUNCTION_NAME : 0; + parser_set_function_name (context_p, function_literal_index, literal_index, function_name_status_flags); + } + + if (is_private) + { + parser_emit_cbc_ext_literal (context_p, CBC_EXT_PRIVATE_FIELD_ADD, literal_index); + } + else + { + parser_emit_cbc_ext_literal (context_p, CBC_EXT_DEFINE_FIELD, literal_index); + } + + /* Prepare stack slot for assignment property reference base. Needed by vm.c */ + if (context_p->stack_limit == context_p->stack_depth) + { + context_p->stack_limit++; + JERRY_ASSERT (context_p->stack_limit <= PARSER_MAXIMUM_STACK_LIMIT); + } + } + else + { + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + uint16_t opcode = CBC_EXT_SET_NEXT_COMPUTED_FIELD; + + if (function_literal_index < PARSER_NAMED_FUNCTION || function_literal_index == PARSER_ANONYMOUS_CLASS) + { + opcode = CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC; + } + + parser_flush_cbc (context_p); + + /* The next opcode pushes two more temporary values onto the stack */ + if (context_p->stack_depth + 1 > context_p->stack_limit) + { + context_p->stack_limit = (uint16_t) (context_p->stack_depth + 1); + if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + } + + parser_emit_cbc_ext (context_p, opcode); + } + } while (!(context_p->stack_top_uint8 & PARSER_CLASS_FIELD_END)); + + if (!first_computed_class_field) + { + parser_emit_cbc (context_p, CBC_POP); + } + + parser_flush_cbc (context_p); + context_p->source_end_p = source_end_p; + scanner_set_location (context_p, &end_location); + +#if JERRY_LINE_INFO + if (context_p->line_info_p == NULL) + { + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); + } +#endif /* JERRY_LINE_INFO */ + + compiled_code_p = parser_post_processing (context_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Class fields parsing end ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_restore_context (context_p, &saved_context); + + return compiled_code_p; +} /* parser_parse_class_fields */ + +/** + * Check whether the last emitted cbc opcode was an anonymous function declaration + * + * @return PARSER_NOT_FUNCTION_LITERAL - if the last opcode is not a function literal + * PARSER_NAMED_FUNCTION - if the last opcode is not a named function declataion + * PARSER_ANONYMOUS_CLASS - if the last opcode is an anonymous class declaration + * literal index of the anonymous function literal - otherwise + */ +uint16_t +parser_check_anonymous_function_declaration (parser_context_t *context_p) /**< context */ +{ + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS)) + { + return PARSER_ANONYMOUS_CLASS; + } + + if (context_p->last_cbc.literal_type != LEXER_FUNCTION_LITERAL) + { + return PARSER_NOT_FUNCTION_LITERAL; + } + + uint16_t literal_index = PARSER_NOT_FUNCTION_LITERAL; + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + literal_index = context_p->last_cbc.literal_index; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + literal_index = context_p->last_cbc.value; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS) + { + literal_index = context_p->last_cbc.third_literal_index; + } + else + { + return PARSER_NOT_FUNCTION_LITERAL; + } + + const ecma_compiled_code_t *bytecode_p; + bytecode_p = (const ecma_compiled_code_t *) (PARSER_GET_LITERAL (literal_index)->u.bytecode_p); + bool is_anon = + ecma_is_value_magic_string (*ecma_compiled_code_resolve_function_name (bytecode_p), LIT_MAGIC_STRING__EMPTY); + + return (is_anon ? literal_index : PARSER_NAMED_FUNCTION); +} /* parser_check_anonymous_function_declaration */ + +/** + * Set the function name of the function literal corresponds to the given function literal index + * to the given character buffer of literal corresponds to the given name index. + */ +void +parser_set_function_name (parser_context_t *context_p, /**< context */ + uint16_t function_literal_index, /**< function literal index */ + uint16_t name_index, /**< function name literal index */ + uint32_t status_flags) /**< status flags */ +{ + ecma_compiled_code_t *bytecode_p; + bytecode_p = (ecma_compiled_code_t *) (PARSER_GET_LITERAL (function_literal_index)->u.bytecode_p); + + parser_compiled_code_set_function_name (context_p, bytecode_p, name_index, status_flags); +} /* parser_set_function_name */ + +/** + * Prepend the given prefix into the current function name literal + * + * @return pointer to the newly allocated buffer + */ +static uint8_t * +parser_add_function_name_prefix (parser_context_t *context_p, /**< context */ + const char *prefix_p, /**< prefix */ + uint32_t prefix_size, /**< prefix's length */ + uint32_t *name_length_p, /**< [out] function name's size */ + lexer_literal_t *name_lit_p) /**< function name literal */ +{ + *name_length_p += prefix_size; + uint8_t *name_buffer_p = (uint8_t *) parser_malloc (context_p, *name_length_p * sizeof (uint8_t)); + memcpy (name_buffer_p, prefix_p, prefix_size); + memcpy (name_buffer_p + prefix_size, name_lit_p->u.char_p, name_lit_p->prop.length); + + return name_buffer_p; +} /* parser_add_function_name_prefix */ + +/** + * Set the function name of the given compiled code + * to the given character buffer of literal corresponds to the given name index. + */ +void +parser_compiled_code_set_function_name (parser_context_t *context_p, /**< context */ + ecma_compiled_code_t *bytecode_p, /**< function literal index */ + uint16_t name_index, /**< function name literal index */ + uint32_t status_flags) /**< status flags */ +{ + ecma_value_t *func_name_start_p; + func_name_start_p = ecma_compiled_code_resolve_function_name ((const ecma_compiled_code_t *) bytecode_p); + + if (JERRY_UNLIKELY (!ecma_is_value_magic_string (*func_name_start_p, LIT_MAGIC_STRING__EMPTY))) + { + return; + } + + parser_scope_stack_t *scope_stack_start_p = context_p->scope_stack_p; + parser_scope_stack_t *scope_stack_p = scope_stack_start_p + context_p->scope_stack_top; + + while (scope_stack_p > scope_stack_start_p) + { + scope_stack_p--; + + if (scope_stack_p->map_from != PARSER_SCOPE_STACK_FUNC && scanner_decode_map_to (scope_stack_p) == name_index) + { + name_index = scope_stack_p->map_from; + break; + } + } + + lexer_literal_t *name_lit_p = (lexer_literal_t *) PARSER_GET_LITERAL (name_index); + + if (name_lit_p->type != LEXER_IDENT_LITERAL && name_lit_p->type != LEXER_STRING_LITERAL) + { + return; + } + + uint8_t *name_buffer_p = (uint8_t *) name_lit_p->u.char_p; + uint32_t name_length = name_lit_p->prop.length; + + if (status_flags & PARSER_PRIVATE_FUNCTION_NAME) + { + name_buffer_p = parser_add_function_name_prefix (context_p, "#", 1, &name_length, name_lit_p); + } + else if (status_flags & (PARSER_IS_PROPERTY_GETTER | PARSER_IS_PROPERTY_SETTER)) + { + name_buffer_p = parser_add_function_name_prefix (context_p, + (status_flags & PARSER_IS_PROPERTY_GETTER) ? "get " : "set ", + 4, + &name_length, + name_lit_p); + } + + *func_name_start_p = + ecma_find_or_create_literal_string (name_buffer_p, name_length, (status_flags & LEXER_FLAG_ASCII) != 0); + + if (name_buffer_p != name_lit_p->u.char_p) + { + parser_free (name_buffer_p, name_length); + } +} /* parser_compiled_code_set_function_name */ + +/** + * Raise a parse error. + */ +void +parser_raise_error (parser_context_t *context_p, /**< context */ + parser_error_msg_t error) /**< error code */ +{ + /* Must be compatible with the scanner because + * the lexer might throws errors during prescanning. */ + parser_saved_context_t *saved_context_p = context_p->last_context_p; + + while (saved_context_p != NULL) + { + parser_cbc_stream_free (&saved_context_p->byte_code); + + /* First the current literal pool is freed, and then it is replaced + * by the literal pool coming from the saved context. Since literals + * are not used anymore, this is a valid replacement. The last pool + * is freed by parser_parse_source. */ + + parser_free_literals (&context_p->literal_pool); + context_p->literal_pool.data = saved_context_p->literal_pool_data; + + if (context_p->scope_stack_p != NULL) + { + parser_free (context_p->scope_stack_p, context_p->scope_stack_size * sizeof (parser_scope_stack_t)); + } + context_p->scope_stack_p = saved_context_p->scope_stack_p; + context_p->scope_stack_size = saved_context_p->scope_stack_size; + + if (saved_context_p->last_statement.current_p != NULL) + { + parser_free_jumps (saved_context_p->last_statement); + } + + if (saved_context_p->tagged_template_literal_cp != JMEM_CP_NULL) + { + ecma_collection_t *collection = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, saved_context_p->tagged_template_literal_cp); + ecma_collection_free_template_literal (collection); + } + +#if JERRY_LINE_INFO + parser_line_info_free (saved_context_p->line_info_p); +#endif /* JERRY_LINE_INFO */ + + saved_context_p = saved_context_p->prev_context_p; + } + + parser_free_private_fields (context_p); + + if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) + { + ecma_collection_t *collection = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, context_p->tagged_template_literal_cp); + ecma_collection_free_template_literal (collection); + } + + context_p->error = error; + PARSER_THROW (context_p->try_buffer); + /* Should never been reached. */ + JERRY_ASSERT (0); +} /* parser_raise_error */ + +#endif /* JERRY_PARSER */ + +/** + * Parse EcmaScript source code + * + * Note: + * if arg_list_p is not NULL, a function body is parsed + * returned value must be freed with ecma_free_value + * + * @return pointer to compiled byte code - if success + * NULL - otherwise + */ +ecma_compiled_code_t * +parser_parse_script (void *source_p, /**< source code */ + uint32_t parse_opts, /**< ecma_parse_opts_t option bits */ + const jerry_parse_options_t *options_p) /**< additional configuration options */ +{ +#if JERRY_PARSER + ecma_compiled_code_t *bytecode_p = parser_parse_source (source_p, parse_opts, options_p); + + if (JERRY_UNLIKELY (bytecode_p == NULL)) + { + /* Exception has already thrown. */ + return NULL; + } + + return bytecode_p; +#else /* !JERRY_PARSER */ + JERRY_UNUSED (arg_list_p); + JERRY_UNUSED (arg_list_size); + JERRY_UNUSED (source_p); + JERRY_UNUSED (source_size); + JERRY_UNUSED (parse_opts); + JERRY_UNUSED (source_name); + + ecma_raise_syntax_error (ECMA_ERR_PARSER_NOT_SUPPORTED); + return NULL; +#endif /* JERRY_PARSER */ +} /* parser_parse_script */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.h new file mode 100644 index 00000000..59238d54 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.h @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_PARSER_H +#define JS_PARSER_H + +#include "ecma-globals.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_parser Parser + * @{ + */ + +/* Note: source must be a valid UTF-8 string */ +ecma_compiled_code_t *parser_parse_script (void *source_p, uint32_t parse_opts, const jerry_parse_options_t *options_p); + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_PARSER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-internal.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-internal.h new file mode 100644 index 00000000..128f401f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-internal.h @@ -0,0 +1,399 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_SCANNER_INTERNAL_H +#define JS_SCANNER_INTERNAL_H + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +/** + * Scan mode types. + */ +typedef enum +{ + SCAN_MODE_PRIMARY_EXPRESSION, /**< scanning primary expression */ + SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW, /**< scanning primary expression after new */ + SCAN_MODE_POST_PRIMARY_EXPRESSION, /**< scanning post primary expression */ + SCAN_MODE_PRIMARY_EXPRESSION_END, /**< scanning primary expression end */ + SCAN_MODE_STATEMENT, /**< scanning statement */ + SCAN_MODE_STATEMENT_OR_TERMINATOR, /**< scanning statement or statement end */ + SCAN_MODE_STATEMENT_END, /**< scanning statement end */ + SCAN_MODE_VAR_STATEMENT, /**< scanning var statement */ + SCAN_MODE_PROPERTY_NAME, /**< scanning property name */ + SCAN_MODE_FUNCTION_ARGUMENTS, /**< scanning function arguments */ + SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS, /**< continue scanning function arguments */ + SCAN_MODE_BINDING, /**< array or object binding */ + SCAN_MODE_CLASS_DECLARATION, /**< scanning class declaration */ + SCAN_MODE_CLASS_BODY, /**< scanning class body */ + SCAN_MODE_CLASS_BODY_NO_SCAN, /**< scanning class body without calling lexer_scan_identifier */ +} scan_modes_t; + +/** + * Scan stack mode types. + */ +typedef enum +{ + SCAN_STACK_SCRIPT, /**< script */ + SCAN_STACK_SCRIPT_FUNCTION, /**< script is a function body */ + SCAN_STACK_BLOCK_STATEMENT, /**< block statement group */ + SCAN_STACK_FUNCTION_STATEMENT, /**< function statement */ + SCAN_STACK_FUNCTION_EXPRESSION, /**< function expression */ + SCAN_STACK_FUNCTION_PROPERTY, /**< function expression in an object literal */ + SCAN_STACK_FUNCTION_ARROW, /**< arrow function expression */ + SCAN_STACK_SWITCH_BLOCK, /**< block part of "switch" statement */ + SCAN_STACK_IF_STATEMENT, /**< statement part of "if" statements */ + SCAN_STACK_WITH_STATEMENT, /**< statement part of "with" statements */ + SCAN_STACK_WITH_EXPRESSION, /**< expression part of "with" statements */ + SCAN_STACK_DO_STATEMENT, /**< statement part of "do" statements */ + SCAN_STACK_DO_EXPRESSION, /**< expression part of "do" statements */ + SCAN_STACK_WHILE_EXPRESSION, /**< expression part of "while" iterator */ + SCAN_STACK_PAREN_EXPRESSION, /**< expression in brackets */ + SCAN_STACK_STATEMENT_WITH_EXPR, /**< statement which starts with expression enclosed in brackets */ + SCAN_STACK_BINDING_INIT, /**< post processing after a single initializer */ + SCAN_STACK_BINDING_LIST_INIT, /**< post processing after an initializer list */ + SCAN_STACK_LET, /**< let statement */ + SCAN_STACK_CONST, /**< const statement */ + /* The SCANNER_IS_FOR_START macro needs to be updated when the following constants are reordered. */ + SCAN_STACK_VAR, /**< var statement */ + SCAN_STACK_FOR_VAR_START, /**< start of "for" iterator with var statement */ + SCAN_STACK_FOR_LET_START, /**< start of "for" iterator with let statement */ + SCAN_STACK_FOR_CONST_START, /**< start of "for" iterator with const statement */ + SCAN_STACK_FOR_START, /**< start of "for" iterator */ + SCAN_STACK_FOR_CONDITION, /**< condition part of "for" iterator */ + SCAN_STACK_FOR_EXPRESSION, /**< expression part of "for" iterator */ + SCAN_STACK_SWITCH_EXPRESSION, /**< expression part of "switch" statement */ + SCAN_STACK_CASE_STATEMENT, /**< case statement inside a switch statement */ + SCAN_STACK_COLON_EXPRESSION, /**< expression between a question mark and colon */ + SCAN_STACK_TRY_STATEMENT, /**< try statement */ + SCAN_STACK_CATCH_STATEMENT, /**< catch statement */ + SCAN_STACK_ARRAY_LITERAL, /**< array literal or destructuring assignment or binding */ + SCAN_STACK_OBJECT_LITERAL, /**< object literal group */ + SCAN_STACK_PROPERTY_ACCESSOR, /**< property accessor in square brackets */ + /* These four must be in this order. */ + SCAN_STACK_COMPUTED_PROPERTY, /**< computed property name */ + SCAN_STACK_COMPUTED_GENERATOR, /**< computed generator function */ + SCAN_STACK_COMPUTED_ASYNC, /**< computed async function */ + SCAN_STACK_COMPUTED_ASYNC_GENERATOR, /**< computed async function */ + SCAN_STACK_TEMPLATE_STRING, /**< template string */ + SCAN_STACK_TAGGED_TEMPLATE_LITERAL, /**< tagged template literal */ + SCAN_STACK_PRIVATE_BLOCK_EARLY, /**< private block for single statements (force early declarations) */ + SCAN_STACK_PRIVATE_BLOCK, /**< private block for single statements */ + SCAN_STACK_ARROW_ARGUMENTS, /**< might be arguments of an arrow function */ + SCAN_STACK_ARROW_EXPRESSION, /**< expression body of an arrow function */ + SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR, /**< explicit class constructor */ + SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR, /**< implicit class constructor */ + SCAN_STACK_CLASS_STATEMENT, /**< class statement */ + SCAN_STACK_CLASS_EXPRESSION, /**< class expression */ + SCAN_STACK_CLASS_EXTENDS, /**< class extends expression */ + SCAN_STACK_CLASS_FIELD_INITIALIZER, /**< class field initializer */ + SCAN_STACK_FUNCTION_PARAMETERS, /**< function parameter initializer */ + SCAN_STACK_FOR_START_PATTERN, /**< possible assignment pattern for "for" iterator */ + SCAN_STACK_USE_ASYNC, /**< an "async" identifier is used */ + SCAN_STACK_CLASS_STATIC_BLOCK, /**< class static block */ +#if JERRY_MODULE_SYSTEM + SCAN_STACK_EXPORT_DEFAULT, /**< scan primary expression after export default */ +#endif /* JERRY_MODULE_SYSTEM */ +} scan_stack_modes_t; + +/** + * Scanner context flag types. + */ +typedef enum +{ + SCANNER_CONTEXT_NO_FLAGS = 0, /**< no flags are set */ + SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION = (1 << 0), /**< throw async function error */ +} scanner_context_flags_t; + +/** + * Checks whether the stack top is a for statement start. + */ +#define SCANNER_IS_FOR_START(stack_top) ((stack_top) >= SCAN_STACK_FOR_VAR_START && (stack_top) <= SCAN_STACK_FOR_START) + +/** + * Generic descriptor which stores only the start position. + */ +typedef struct +{ + const uint8_t *source_p; /**< start source byte */ +} scanner_source_start_t; + +/** + * Descriptor for storing a binding literal on stack. + */ +typedef struct +{ + lexer_lit_location_t *literal_p; /**< binding literal */ +} scanner_binding_literal_t; + +/** + * Flags for type member of lexer_lit_location_t structure in the literal pool. + */ +typedef enum +{ + SCANNER_LITERAL_IS_ARG = (1 << 0), /**< literal is argument */ + SCANNER_LITERAL_IS_VAR = (1 << 1), /**< literal is var */ + /** literal is a destructured argument binding of a possible arrow function */ + SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG = SCANNER_LITERAL_IS_VAR, + SCANNER_LITERAL_IS_FUNC = (1 << 2), /**< literal is function */ + SCANNER_LITERAL_NO_REG = (1 << 3), /**< literal cannot be stored in a register */ + SCANNER_LITERAL_IS_LET = (1 << 4), /**< literal is let */ + /** literal is a function declared in this block (prevents declaring let/const with the same name) */ + SCANNER_LITERAL_IS_FUNC_DECLARATION = SCANNER_LITERAL_IS_LET, + SCANNER_LITERAL_IS_CONST = (1 << 5), /**< literal is const */ + /** literal is a destructured argument binding */ + SCANNER_LITERAL_IS_DESTRUCTURED_ARG = SCANNER_LITERAL_IS_CONST, + SCANNER_LITERAL_IS_USED = (1 << 6), /**< literal is used */ + SCANNER_LITERAL_EARLY_CREATE = (1 << 7), /**< binding should be created early with ECMA_VALUE_UNINITIALIZED */ +} scanner_literal_type_flags_t; + +/* + * Known combinations: + * + * SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION : + * function declared in this block + * SCANNER_LITERAL_IS_LOCAL : + * module import on global scope, catch block variable otherwise + * SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC : + * a function argument which is reassigned to a function later + * SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG : + * destructured binding argument + * SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_FUNC : + * destructured binding argument which is reassigned to a function later + */ + +/** + * Literal is a local declration (let, const, catch variable, etc.) + */ +#define SCANNER_LITERAL_IS_LOCAL (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST) + +/** + * Literal is a local function declaration + */ +#define SCANNER_LITERAL_IS_LOCAL_FUNC (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION) + +/** + * For statement descriptor. + */ +typedef struct +{ + /** shared fields of for statements */ + union + { + const uint8_t *source_p; /**< start source byte */ + scanner_for_info_t *for_info_p; /**< for info */ + } u; +} scanner_for_statement_t; + +/** + * Switch statement descriptor. + */ +typedef struct +{ + scanner_case_info_t **last_case_p; /**< last case info */ +} scanner_switch_statement_t; + +/** + * Types of scanner destructuring bindings. + */ +typedef enum +{ + /* Update SCANNER_NEEDS_BINDING_LIST after changing these values. */ + SCANNER_BINDING_NONE, /**< not a destructuring binding expression */ + SCANNER_BINDING_VAR, /**< destructuring var binding */ + SCANNER_BINDING_LET, /**< destructuring let binding */ + SCANNER_BINDING_CATCH, /**< destructuring catch binding */ + SCANNER_BINDING_CONST, /**< destructuring const binding */ + SCANNER_BINDING_ARG, /**< destructuring arg binding */ + SCANNER_BINDING_ARROW_ARG, /**< possible destructuring arg binding of an arrow function */ +} scanner_binding_type_t; + +/** + * Check whether a binding list is needed for the binding pattern. + */ +#define SCANNER_NEEDS_BINDING_LIST(type) ((type) >= SCANNER_BINDING_LET) + +/** + * Scanner binding items for destructuring binding patterns. + */ +typedef struct scanner_binding_item_t +{ + struct scanner_binding_item_t *next_p; /**< next binding in the list */ + lexer_lit_location_t *literal_p; /**< binding literal */ +} scanner_binding_item_t; + +/** + * Scanner binding lists for destructuring binding patterns. + */ +typedef struct scanner_binding_list_t +{ + struct scanner_binding_list_t *prev_p; /**< prev list */ + scanner_binding_item_t *items_p; /**< list of bindings */ + bool is_nested; /**< is nested binding declaration */ +} scanner_binding_list_t; + +/** + * Flags for scanner_literal_pool_t structure. + */ +typedef enum +{ + SCANNER_LITERAL_POOL_FUNCTION = (1 << 0), /**< literal pool represents a function */ + SCANNER_LITERAL_POOL_CLASS_NAME = (1 << 1), /**< literal pool which contains a class name */ + SCANNER_LITERAL_POOL_CLASS_FIELD = (1 << 2), /**< literal pool is created for a class field initializer */ + SCANNER_LITERAL_POOL_IS_STRICT = (1 << 3), /**< literal pool represents a strict mode code block */ + SCANNER_LITERAL_POOL_CAN_EVAL = (1 << 4), /**< prepare for executing eval in this block */ + SCANNER_LITERAL_POOL_NO_ARGUMENTS = (1 << 5), /**< arguments object must not be constructed, + * or arguments cannot be stored in registers if + * SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS is set */ + SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS = (1 << 6), /**< arguments is referenced in function args */ + SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT = (1 << 7), /**< function has complex (ES2015+) argument definition */ + SCANNER_LITERAL_POOL_IN_WITH = (1 << 8), /**< literal pool is in a with statement */ + SCANNER_LITERAL_POOL_ARROW = (1 << 9), /**< arrow function */ + SCANNER_LITERAL_POOL_GENERATOR = (1 << 10), /**< generator function */ + SCANNER_LITERAL_POOL_ASYNC = (1 << 11), /**< async function */ + SCANNER_LITERAL_POOL_FUNCTION_STATEMENT = (1 << 12), /**< function statement */ + SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE = (1 << 13), /**< function body contains super reference */ +#if JERRY_MODULE_SYSTEM + SCANNER_LITERAL_POOL_IN_EXPORT = (1 << 14), /**< the declared variables are exported by the module system */ +#endif /* JERRY_MODULE_SYSTEM */ +} scanner_literal_pool_flags_t; + +/** + * Define a function where no arguments are allowed. + */ +#define SCANNER_LITERAL_POOL_ARROW_FLAGS \ + (SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_NO_ARGUMENTS | SCANNER_LITERAL_POOL_ARROW) + +/** + * This flag represents that the bracketed expression might be an async arrow function. + * The SCANNER_LITERAL_POOL_ARROW flag is reused for this purpose. + */ +#define SCANNER_LITERAL_POOL_MAY_ASYNC_ARROW SCANNER_LITERAL_POOL_ARROW + +/** + * Getting the generator and async properties of literal pool status flags. + */ +#define SCANNER_FROM_LITERAL_POOL_TO_COMPUTED(status_flags) \ + ((uint8_t) ((((status_flags) >> 10) & 0x3) + SCAN_STACK_COMPUTED_PROPERTY)) + +/** + * Setting the generator and async properties of literal pool status flags. + */ +#define SCANNER_FROM_COMPUTED_TO_LITERAL_POOL(mode) (((mode) -SCAN_STACK_COMPUTED_PROPERTY) << 10) + +/** + * Literal pool which may contains function argument identifiers + */ +#define SCANNER_LITERAL_POOL_MAY_HAVE_ARGUMENTS(status_flags) \ + (!((status_flags) & (SCANNER_LITERAL_POOL_CLASS_NAME | SCANNER_LITERAL_POOL_CLASS_FIELD))) + +/** + * Local literal pool. + */ +typedef struct scanner_literal_pool_t +{ + struct scanner_literal_pool_t *prev_p; /**< previous literal pool */ + const uint8_t *source_p; /**< source position where the final data needs to be inserted */ + parser_list_t literal_pool; /**< list of literal */ + uint16_t status_flags; /**< combination of scanner_literal_pool_flags_t flags */ + uint16_t no_declarations; /**< size of scope stack required during parsing */ +} scanner_literal_pool_t; + +/** + * Scanner context. + */ +struct scanner_context_t +{ + uint32_t context_status_flags; /**< original status flags of the context */ + uint8_t mode; /**< scanner mode */ + uint8_t binding_type; /**< current destructuring binding type */ + uint16_t status_flags; /**< scanner status flags */ + scanner_binding_list_t *active_binding_list_p; /**< currently active binding list */ + scanner_literal_pool_t *active_literal_pool_p; /**< currently active literal pool */ + scanner_switch_statement_t active_switch_statement; /**< currently active switch statement */ + scanner_info_t *end_arguments_p; /**< position of end arguments */ + const uint8_t *async_source_p; /**< source position for async functions */ +}; + +/* Scanner utils. */ + +void scanner_raise_error (parser_context_t *context_p); +void scanner_raise_redeclaration_error (parser_context_t *context_p); + +void *scanner_malloc (parser_context_t *context_p, size_t size); +void scanner_free (void *ptr, size_t size); + +size_t scanner_get_stream_size (scanner_info_t *info_p, size_t size); +scanner_info_t *scanner_insert_info (parser_context_t *context_p, const uint8_t *source_p, size_t size); +scanner_info_t *scanner_insert_info_before (parser_context_t *context_p, + const uint8_t *source_p, + scanner_info_t *start_info_p, + size_t size); +scanner_literal_pool_t * +scanner_push_literal_pool (parser_context_t *context_p, scanner_context_t *scanner_context_p, uint16_t status_flags); +void scanner_pop_literal_pool (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_filter_arguments (parser_context_t *context_p, scanner_context_t *scanner_context_p); +lexer_lit_location_t *scanner_add_custom_literal (parser_context_t *context_p, + scanner_literal_pool_t *literal_pool_p, + const lexer_lit_location_t *literal_location_p); +lexer_lit_location_t *scanner_add_literal (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_add_reference (parser_context_t *context_p, scanner_context_t *scanner_context_p); +lexer_lit_location_t *scanner_append_argument (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_add_private_identifier (parser_context_t *context_p, scanner_private_field_flags_t opts); +void scanner_detect_invalid_var (parser_context_t *context_p, + scanner_context_t *scanner_context_p, + lexer_lit_location_t *var_literal_p); +void scanner_detect_invalid_let (parser_context_t *context_p, lexer_lit_location_t *let_literal_p); +void scanner_detect_eval_call (parser_context_t *context_p, scanner_context_t *scanner_context_p); + +lexer_lit_location_t * +scanner_push_class_declaration (parser_context_t *context_p, scanner_context_t *scanner_context_p, uint8_t stack_mode); +void scanner_push_class_field_initializer (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_push_destructuring_pattern (parser_context_t *context_p, + scanner_context_t *scanner_context_p, + uint8_t binding_type, + bool is_nested); +void scanner_pop_binding_list (scanner_context_t *scanner_context_p); +void scanner_append_hole (parser_context_t *context_p, scanner_context_t *scanner_context_p); + +/* Scanner operations. */ + +void scanner_add_async_literal (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_check_arrow (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void +scanner_scan_simple_arrow (parser_context_t *context_p, scanner_context_t *scanner_context_p, const uint8_t *source_p); +void scanner_check_arrow_arg (parser_context_t *context_p, scanner_context_t *scanner_context_p); +bool scanner_check_async_function (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_check_function_after_if (parser_context_t *context_p, scanner_context_t *scanner_context_p); +#if JERRY_MODULE_SYSTEM +void scanner_check_import_meta (parser_context_t *context_p); +#endif /* JERRY_MODULE_SYSTEM */ +void scanner_scan_bracket (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_check_directives (parser_context_t *context_p, scanner_context_t *scanner_context_p); + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_SCANNER_INTERNAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-ops.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-ops.cpp new file mode 100644 index 00000000..98dadc0f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-ops.cpp @@ -0,0 +1,602 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" +#include "js-scanner-internal.h" +#include "lit-char-helpers.h" + +#if JERRY_PARSER + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +/** + * Add the "async" literal to the literal pool. + */ +void +scanner_add_async_literal (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + lexer_lit_location_t async_literal; + + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC); + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &async_literal, sizeof (lexer_lit_location_t)); + + lexer_lit_location_t *lit_location_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &async_literal); + + lit_location_p->type |= SCANNER_LITERAL_IS_USED; + + if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + lit_location_p->type |= SCANNER_LITERAL_NO_REG; + } +} /* scanner_add_async_literal */ + +/** + * Init scanning the body of an arrow function. + */ +static void +scanner_check_arrow_body (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + lexer_next_token (context_p); + + scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ARROW; + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_EXPRESSION); + return; + } + + lexer_next_token (context_p); + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_ARROW); + scanner_check_directives (context_p, scanner_context_p); +} /* scanner_check_arrow_body */ + +/** + * Process arrow function with argument list. + */ +void +scanner_check_arrow (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + parser_stack_pop_uint8 (context_p); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_ARROW || (context_p->token.flags & LEXER_WAS_NEWLINE)) + { + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + scanner_add_async_literal (context_p, scanner_context_p); + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + scanner_pop_literal_pool (context_p, scanner_context_p); + return; + } + + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + parser_stack_pop (context_p, NULL, sizeof (lexer_lit_location_t) + 1); + } + + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + uint16_t status_flags = literal_pool_p->status_flags; + + bool is_async_arrow = (status_flags & SCANNER_LITERAL_POOL_MAY_ASYNC_ARROW) != 0; + + status_flags |= SCANNER_LITERAL_POOL_ARROW_FLAGS; + status_flags &= + (uint16_t) ~(SCANNER_LITERAL_POOL_IN_WITH | SCANNER_LITERAL_POOL_GENERATOR | SCANNER_LITERAL_POOL_ASYNC); + + context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION); + + if (is_async_arrow) + { + status_flags |= SCANNER_LITERAL_POOL_ASYNC; + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION; + } + + literal_pool_p->status_flags = status_flags; + + scanner_filter_arguments (context_p, scanner_context_p); + scanner_check_arrow_body (context_p, scanner_context_p); +} /* scanner_check_arrow */ + +/** + * Process arrow function with a single argument. + */ +void +scanner_scan_simple_arrow (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + const uint8_t *source_p) /**< identifier end position */ +{ + uint16_t status_flags = SCANNER_LITERAL_POOL_ARROW_FLAGS; + + context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION); + + if (scanner_context_p->async_source_p != NULL) + { + JERRY_ASSERT (scanner_context_p->async_source_p == source_p); + + status_flags |= SCANNER_LITERAL_POOL_ASYNC; + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION; + } + + scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, status_flags); + literal_pool_p->source_p = source_p; + + lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p); + location_p->type |= SCANNER_LITERAL_IS_ARG; + + /* Skip the => token, which size is two. */ + context_p->source_p += 2; + PARSER_PLUS_EQUAL_LC (context_p->column, 2); + context_p->token.flags = (uint8_t) (context_p->token.flags & ~LEXER_NO_SKIP_SPACES); + + scanner_check_arrow_body (context_p, scanner_context_p); +} /* scanner_scan_simple_arrow */ + +/** + * Process the next argument of a might-be arrow function. + */ +void +scanner_check_arrow_arg (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS); + + const uint8_t *source_p = context_p->source_p; + bool process_arrow = false; + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (context_p->token.type == LEXER_THREE_DOTS) + { + lexer_next_token (context_p); + } + + switch (context_p->token.type) + { + case LEXER_RIGHT_PAREN: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return; + } + case LEXER_LITERAL: + { + if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + + if (lexer_check_arrow (context_p)) + { + process_arrow = true; + break; + } + + lexer_lit_location_t *argument_literal_p = scanner_append_argument (context_p, scanner_context_p); + + scanner_detect_eval_call (context_p, scanner_context_p); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_COMMA || context_p->token.type == LEXER_RIGHT_PAREN) + { + return; + } + + if (context_p->token.type != LEXER_ASSIGN) + { + break; + } + + if (argument_literal_p->type & SCANNER_LITERAL_IS_USED) + { + JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE); + return; + } + + scanner_binding_literal_t binding_literal; + binding_literal.literal_p = argument_literal_p; + + parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT); + return; + } + case LEXER_LEFT_SQUARE: + case LEXER_LEFT_BRACE: + { + scanner_append_hole (context_p, scanner_context_p); + scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_ARROW_ARG, false); + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + parser_stack_push_uint8 (context_p, 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; + return; + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + scanner_context_p->mode = SCAN_MODE_BINDING; + lexer_next_token (context_p); + return; + } + } + + scanner_pop_literal_pool (context_p, scanner_context_p); + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + scanner_add_async_literal (context_p, scanner_context_p); + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION); + + if (process_arrow) + { + scanner_scan_simple_arrow (context_p, scanner_context_p, source_p); + } +} /* scanner_check_arrow_arg */ + +/** + * Detect async functions. + * + * @return true, if async is followed by a function keyword, false otherwise + */ +bool +scanner_check_async_function (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + JERRY_ASSERT (lexer_token_is_async (context_p)); + JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION + || scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW); + JERRY_ASSERT (scanner_context_p->async_source_p != NULL); + + lexer_lit_location_t async_literal = context_p->token.lit_location; + + lexer_next_token (context_p); + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + if (context_p->token.type == LEXER_KEYW_FUNCTION) + { + return true; + } + + if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + if (!lexer_check_arrow (context_p)) + { + scanner_raise_error (context_p); + } + + scanner_scan_simple_arrow (context_p, scanner_context_p, scanner_context_p->async_source_p); + scanner_context_p->async_source_p = NULL; + return false; + } + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + parser_stack_push (context_p, &async_literal, sizeof (lexer_lit_location_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_USE_ASYNC); + return false; + } + } + + lexer_lit_location_t *lit_location_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &async_literal); + lit_location_p->type |= SCANNER_LITERAL_IS_USED; + + if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + lit_location_p->type |= SCANNER_LITERAL_NO_REG; + } + + scanner_context_p->async_source_p = NULL; + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return false; +} /* scanner_check_async_function */ + +/** + * Check whether the statement of an if/else construct is a function statement. + */ +void +scanner_check_function_after_if (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + lexer_next_token (context_p); + scanner_context_p->mode = SCAN_MODE_STATEMENT; + + if (JERRY_UNLIKELY (context_p->token.type == LEXER_KEYW_FUNCTION)) + { + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + + literal_pool_p->source_p = context_p->source_p; + parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK); + } +} /* scanner_check_function_after_if */ + +#if JERRY_MODULE_SYSTEM + +/** + * Check whether the next token is meta. + */ +void +scanner_check_import_meta (parser_context_t *context_p) /**< context */ +{ + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL + || context_p->token.keyword_type != LEXER_KEYW_META + || (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + context_p->global_status_flags |= ECMA_PARSE_INTERNAL_HAS_IMPORT_META; +} /* scanner_check_import_meta */ + +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * Arrow types for scanner_scan_bracket() function. + */ +typedef enum +{ + SCANNER_SCAN_BRACKET_NO_ARROW, /**< not an arrow function */ + SCANNER_SCAN_BRACKET_SIMPLE_ARROW, /**< simple arrow function */ + SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG, /**< arrow function with one argument */ +} scanner_scan_bracket_arrow_type_t; + +/** + * Scan bracketed expressions. + */ +void +scanner_scan_bracket (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + size_t depth = 0; + const uint8_t *arrow_source_p; + const uint8_t *async_source_p = NULL; + scanner_scan_bracket_arrow_type_t arrow_type = SCANNER_SCAN_BRACKET_NO_ARROW; + + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_PAREN); + + do + { + arrow_source_p = context_p->source_p; + depth++; + lexer_next_token (context_p); + } while (context_p->token.type == LEXER_LEFT_PAREN); + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + switch (context_p->token.type) + { + case LEXER_LITERAL: + { + if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + arrow_source_p = NULL; + break; + } + + const uint8_t *source_p = context_p->source_p; + + if (lexer_check_arrow (context_p)) + { + arrow_source_p = source_p; + arrow_type = SCANNER_SCAN_BRACKET_SIMPLE_ARROW; + break; + } + + size_t total_depth = depth; + + while (depth > 0 && lexer_check_next_character (context_p, LIT_CHAR_RIGHT_PAREN)) + { + lexer_consume_next_character (context_p); + depth--; + } + + if (context_p->token.keyword_type == LEXER_KEYW_EVAL + && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + /* A function call cannot be an eval function. */ + arrow_source_p = NULL; + const uint16_t flags = (uint16_t) (SCANNER_LITERAL_POOL_CAN_EVAL | SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE); + + scanner_context_p->active_literal_pool_p->status_flags |= flags; + break; + } + + if (total_depth == depth) + { + if (lexer_check_arrow_param (context_p)) + { + JERRY_ASSERT (depth > 0); + depth--; + break; + } + + if (JERRY_UNLIKELY (lexer_token_is_async (context_p))) + { + async_source_p = source_p; + } + } + + if (depth == total_depth - 1 && lexer_check_arrow (context_p)) + { + arrow_type = SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG; + break; + } + + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + scanner_add_async_literal (context_p, scanner_context_p); + } + + arrow_source_p = NULL; + break; + } + case LEXER_THREE_DOTS: + case LEXER_LEFT_SQUARE: + case LEXER_LEFT_BRACE: + case LEXER_RIGHT_PAREN: + { + JERRY_ASSERT (depth > 0); + depth--; + break; + } + default: + { + arrow_source_p = NULL; + break; + } + } + + if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL) && (arrow_source_p == NULL || depth > 0)) + { + scanner_context_p->async_source_p = NULL; + } + + while (depth > 0) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION); + depth--; + } + + if (arrow_source_p != NULL) + { + JERRY_ASSERT (async_source_p == NULL); + + if (arrow_type == SCANNER_SCAN_BRACKET_SIMPLE_ARROW) + { + scanner_scan_simple_arrow (context_p, scanner_context_p, arrow_source_p); + return; + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_ARGUMENTS); + + uint16_t status_flags = 0; + + if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL)) + { + status_flags |= SCANNER_LITERAL_POOL_MAY_ASYNC_ARROW; + arrow_source_p = scanner_context_p->async_source_p; + scanner_context_p->async_source_p = NULL; + } + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, status_flags); + literal_pool_p->source_p = arrow_source_p; + + if (arrow_type == SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG) + { + scanner_append_argument (context_p, scanner_context_p); + scanner_detect_eval_call (context_p, scanner_context_p); + + context_p->token.type = LEXER_RIGHT_PAREN; + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + } + else if (context_p->token.type == LEXER_RIGHT_PAREN) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + } + else + { + scanner_check_arrow_arg (context_p, scanner_context_p); + } + } + else if (JERRY_UNLIKELY (async_source_p != NULL)) + { + scanner_context_p->async_source_p = async_source_p; + scanner_check_async_function (context_p, scanner_context_p); + } +} /* scanner_scan_bracket */ + +/** + * Check directives before a source block. + */ +void +scanner_check_directives (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + + while (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + bool is_use_strict = false; + + if (lexer_string_is_use_strict (context_p) && !(context_p->status_flags & PARSER_IS_STRICT)) + { + is_use_strict = true; + context_p->status_flags |= PARSER_IS_STRICT; + } + + lexer_next_token (context_p); + + if (!lexer_string_is_directive (context_p)) + { + if (is_use_strict) + { + context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT; + } + + /* The string is part of an expression statement. */ + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + break; + } + + if (is_use_strict) + { + scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_IS_STRICT; + } + + if (context_p->token.type == LEXER_SEMICOLON) + { + lexer_next_token (context_p); + } + } +} /* scanner_check_directives */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-util.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-util.cpp new file mode 100644 index 00000000..a9c9655a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-util.cpp @@ -0,0 +1,2950 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-helpers.h" +#include "ecma-lex-env.h" + +#include "jcontext.h" +#include "js-parser-internal.h" +#include "js-scanner-internal.h" +#include "lit-char-helpers.h" + +#if JERRY_PARSER + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +JERRY_STATIC_ASSERT (PARSER_MAXIMUM_NUMBER_OF_LITERALS + PARSER_MAXIMUM_NUMBER_OF_REGISTERS < PARSER_REGISTER_START, + maximum_number_of_literals_plus_registers_must_be_less_than_register_start); + +JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) == 0, + is_arrow_arg_binding_flag_must_not_use_local_flags); + +JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_LET & SCANNER_LITERAL_IS_LOCAL) != 0, is_let_flag_must_use_local_flags); + +JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_CONST & SCANNER_LITERAL_IS_LOCAL) != 0, is_const_flag_must_use_local_flags); + +JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_FUNC_DECLARATION & SCANNER_LITERAL_IS_LOCAL) != 0, + is_func_declaration_flag_must_use_local_flags); + +JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) != 0, + is_arg_binding_flag_must_use_local_flags); + +JERRY_STATIC_ASSERT (((int)SCANNER_LITERAL_IS_FUNC_DECLARATION != (int)SCANNER_LITERAL_IS_DESTRUCTURED_ARG), + is_func_declaration_must_be_different_from_is_arg_binding); + +JERRY_STATIC_ASSERT (((int)PARSER_SCOPE_STACK_IS_CONST_REG == (int)PARSER_SCOPE_STACK_IS_LOCAL_CREATED), + scope_stack_is_const_reg_and_scope_stack_is_local_created_must_be_the_same); + +/** + * Raise a scanner error. + */ +void +scanner_raise_error (parser_context_t *context_p /**< context */) +{ + PARSER_THROW (context_p->try_buffer); + /* Should never been reached. */ + JERRY_ASSERT (0); +} /* scanner_raise_error */ + +/** + * Raise a variable redeclaration error. + */ +void +scanner_raise_redeclaration_error (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *info_p = scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_ERR_REDECLARED; + + scanner_raise_error (context_p); +} /* scanner_raise_redeclaration_error */ + +/** + * Allocate memory for scanner. + * + * @return allocated memory + */ +void * +scanner_malloc (parser_context_t *context_p, /**< context */ + size_t size) /**< size of the memory block */ +{ + void *result; + + JERRY_ASSERT (size > 0); + result = jmem_heap_alloc_block_null_on_error (size); + + if (result == NULL) + { + scanner_cleanup (context_p); + + /* This is the only error which specify its reason. */ + context_p->error = PARSER_ERR_OUT_OF_MEMORY; + PARSER_THROW (context_p->try_buffer); + } + return result; +} /* scanner_malloc */ + +/** + * Free memory allocated by scanner_malloc. + */ +void +scanner_free (void *ptr, /**< pointer to free */ + size_t size) /**< size of the memory block */ +{ + jmem_heap_free_block (ptr, size); +} /* scanner_free */ + +/** + * Count the size of a stream after an info block. + * + * @return the size in bytes + */ +size_t +scanner_get_stream_size (scanner_info_t *info_p, /**< scanner info block */ + size_t size) /**< size excluding the stream */ +{ + const uint8_t *data_p = ((const uint8_t *) info_p) + size; + const uint8_t *data_p_start = data_p; + + while (data_p[0] != SCANNER_STREAM_TYPE_END) + { + switch (data_p[0] & SCANNER_STREAM_TYPE_MASK) + { + case SCANNER_STREAM_TYPE_VAR: + case SCANNER_STREAM_TYPE_LET: + case SCANNER_STREAM_TYPE_CONST: + case SCANNER_STREAM_TYPE_LOCAL: +#if JERRY_MODULE_SYSTEM + case SCANNER_STREAM_TYPE_IMPORT: +#endif /* JERRY_MODULE_SYSTEM */ + case SCANNER_STREAM_TYPE_ARG: + case SCANNER_STREAM_TYPE_ARG_VAR: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR: + case SCANNER_STREAM_TYPE_ARG_FUNC: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC: + case SCANNER_STREAM_TYPE_FUNC: + { + break; + } + default: + { + JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE + || SCANNER_STREAM_TYPE_IS_ARGUMENTS (data_p[0] & SCANNER_STREAM_TYPE_MASK)); + data_p++; + continue; + } + } + + data_p += 3; + + if (data_p[-3] & SCANNER_STREAM_UINT16_DIFF) + { + data_p++; + } + else if (data_p[-1] == 0) + { + data_p += sizeof (const uint8_t *); + } + } + + return size + 1 + (size_t) (data_p - data_p_start); +} /* scanner_get_stream_size */ + +/** + * Insert a scanner info block into the scanner info chain. + * + * @return newly allocated scanner info + */ +scanner_info_t * +scanner_insert_info (parser_context_t *context_p, /**< context */ + const uint8_t *source_p, /**< triggering position */ + size_t size) /**< size of the memory block */ +{ + scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size); + scanner_info_t *scanner_info_p = context_p->next_scanner_info_p; + scanner_info_t *prev_scanner_info_p = NULL; + + JERRY_ASSERT (scanner_info_p != NULL); + JERRY_ASSERT (source_p != NULL); + + new_scanner_info_p->source_p = source_p; + + while (source_p < scanner_info_p->source_p) + { + prev_scanner_info_p = scanner_info_p; + scanner_info_p = scanner_info_p->next_p; + + JERRY_ASSERT (scanner_info_p != NULL); + } + + /* Multiple scanner info blocks cannot be assigned to the same position. */ + JERRY_ASSERT (source_p != scanner_info_p->source_p); + + new_scanner_info_p->next_p = scanner_info_p; + + if (JERRY_LIKELY (prev_scanner_info_p == NULL)) + { + context_p->next_scanner_info_p = new_scanner_info_p; + } + else + { + prev_scanner_info_p->next_p = new_scanner_info_p; + } + + return new_scanner_info_p; +} /* scanner_insert_info */ + +/** + * Insert a scanner info block into the scanner info chain before a given info block. + * + * @return newly allocated scanner info + */ +scanner_info_t * +scanner_insert_info_before (parser_context_t *context_p, /**< context */ + const uint8_t *source_p, /**< triggering position */ + scanner_info_t *start_info_p, /**< first info position */ + size_t size) /**< size of the memory block */ +{ + JERRY_ASSERT (start_info_p != NULL); + + scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size); + scanner_info_t *scanner_info_p = start_info_p->next_p; + scanner_info_t *prev_scanner_info_p = start_info_p; + + new_scanner_info_p->source_p = source_p; + + while (source_p < scanner_info_p->source_p) + { + prev_scanner_info_p = scanner_info_p; + scanner_info_p = scanner_info_p->next_p; + + JERRY_ASSERT (scanner_info_p != NULL); + } + + /* Multiple scanner info blocks cannot be assigned to the same position. */ + JERRY_ASSERT (source_p != scanner_info_p->source_p); + + new_scanner_info_p->next_p = scanner_info_p; + + prev_scanner_info_p->next_p = new_scanner_info_p; + return new_scanner_info_p; +} /* scanner_insert_info_before */ + +/** + * Release the next scanner info. + */ +void +scanner_release_next (parser_context_t *context_p, /**< context */ + size_t size) /**< size of the memory block */ +{ + scanner_info_t *next_p = context_p->next_scanner_info_p->next_p; + + jmem_heap_free_block (context_p->next_scanner_info_p, size); + context_p->next_scanner_info_p = next_p; +} /* scanner_release_next */ + +/** + * Set the active scanner info to the next scanner info. + */ +void +scanner_set_active (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *scanner_info_p = context_p->next_scanner_info_p; + + context_p->next_scanner_info_p = scanner_info_p->next_p; + scanner_info_p->next_p = context_p->active_scanner_info_p; + context_p->active_scanner_info_p = scanner_info_p; +} /* scanner_set_active */ + +/** + * Set the next scanner info to the active scanner info. + */ +void +scanner_revert_active (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *scanner_info_p = context_p->active_scanner_info_p; + + context_p->active_scanner_info_p = scanner_info_p->next_p; + scanner_info_p->next_p = context_p->next_scanner_info_p; + context_p->next_scanner_info_p = scanner_info_p; +} /* scanner_revert_active */ + +/** + * Release the active scanner info. + */ +void +scanner_release_active (parser_context_t *context_p, /**< context */ + size_t size) /**< size of the memory block */ +{ + scanner_info_t *next_p = context_p->active_scanner_info_p->next_p; + + jmem_heap_free_block (context_p->active_scanner_info_p, size); + context_p->active_scanner_info_p = next_p; +} /* scanner_release_active */ + +/** + * Release switch cases. + */ +void +scanner_release_switch_cases (scanner_case_info_t *case_p) /**< case list */ +{ + while (case_p != NULL) + { + scanner_case_info_t *next_p = case_p->next_p; + + jmem_heap_free_block (case_p, sizeof (scanner_case_info_t)); + case_p = next_p; + } +} /* scanner_release_switch_cases */ + +/** + * Release private fields. + */ +void +scanner_release_private_fields (scanner_class_private_member_t *member_p) /**< private member list */ +{ + while (member_p != NULL) + { + scanner_class_private_member_t *prev_p = member_p->prev_p; + + jmem_heap_free_block (member_p, sizeof (scanner_class_private_member_t)); + member_p = prev_p; + } +} /* scanner_release_private_fields */ + +/** + * Seek to correct position in the scanner info list. + */ +void +scanner_seek (parser_context_t *context_p) /**< context */ +{ + const uint8_t *source_p = context_p->source_p; + scanner_info_t *prev_p; + + if (context_p->skipped_scanner_info_p != NULL) + { + JERRY_ASSERT (context_p->skipped_scanner_info_p->source_p != NULL); + + context_p->skipped_scanner_info_end_p->next_p = context_p->next_scanner_info_p; + + if (context_p->skipped_scanner_info_end_p->source_p <= source_p) + { + prev_p = context_p->skipped_scanner_info_end_p; + } + else + { + prev_p = context_p->skipped_scanner_info_p; + + if (prev_p->source_p > source_p) + { + context_p->next_scanner_info_p = prev_p; + context_p->skipped_scanner_info_p = NULL; + return; + } + + context_p->skipped_scanner_info_p = prev_p; + } + } + else + { + prev_p = context_p->next_scanner_info_p; + + if (prev_p->source_p == NULL || prev_p->source_p > source_p) + { + return; + } + + context_p->skipped_scanner_info_p = prev_p; + } + + while (prev_p->next_p->source_p != NULL && prev_p->next_p->source_p <= source_p) + { + prev_p = prev_p->next_p; + } + + context_p->skipped_scanner_info_end_p = prev_p; + context_p->next_scanner_info_p = prev_p->next_p; +} /* scanner_seek */ + +/** + * Checks whether a literal is equal to "arguments". + */ +static inline bool +scanner_literal_is_arguments (lexer_lit_location_t *literal_p) /**< literal */ +{ + return lexer_compare_identifier_to_string (literal_p, (const uint8_t *) "arguments", 9); +} /* scanner_literal_is_arguments */ + +/** + * Find if there is a duplicated argument in the given context + * + * @return true - if there are duplicates, false - otherwise + */ +static bool +scanner_find_duplicated_arg (parser_context_t *context_p, lexer_lit_location_t *lit_loc_p) +{ + if (!(context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS)) + { + return false; + } + + if (scanner_literal_is_arguments (lit_loc_p)) + { + return true; + } + + uint16_t register_end, encoding_limit, encoding_delta; + ecma_value_t *literal_p; + ecma_value_t *literal_start_p; + + const ecma_compiled_code_t *bytecode_header_p = JERRY_CONTEXT (vm_top_context_p)->shared_p->bytecode_header_p; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + + register_end = args_p->register_end; + + literal_p = (ecma_value_t *) (args_p + 1); + literal_p -= register_end; + literal_start_p = literal_p; + literal_p += args_p->literal_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + + register_end = args_p->register_end; + + literal_p = (ecma_value_t *) (args_p + 1); + literal_p -= register_end; + literal_start_p = literal_p; + literal_p += args_p->literal_end; + } + + if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) + { + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + else + { + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + + uint8_t *byte_code_p = (uint8_t *) literal_p; + + bool found_duplicate = false; + + while (*byte_code_p == CBC_CREATE_LOCAL) + { + byte_code_p++; + uint16_t literal_index = *byte_code_p++; + + if (literal_index >= encoding_limit) + { + literal_index = (uint16_t) (((literal_index << 8) | *byte_code_p++) - encoding_delta); + } + + ecma_string_t *arg_string = ecma_get_string_from_value (literal_start_p[literal_index]); + uint8_t *destination_p = (uint8_t *) parser_malloc (context_p, lit_loc_p->length); + lexer_convert_ident_to_cesu8 (destination_p, lit_loc_p->char_p, lit_loc_p->length); + ecma_string_t *search_key_p = ecma_new_ecma_string_from_utf8 (destination_p, lit_loc_p->length); + scanner_free (destination_p, lit_loc_p->length); + + found_duplicate = ecma_compare_ecma_strings (arg_string, search_key_p); + ecma_deref_ecma_string (search_key_p); + + if (found_duplicate) + { + break; + } + } + + return found_duplicate; +} /* scanner_find_duplicated_arg */ + +/** + * Find any let/const declaration of a given literal. + * + * @return true - if the literal is found, false - otherwise + */ +static bool +scanner_scope_find_lexical_declaration (parser_context_t *context_p, /**< context */ + lexer_lit_location_t *literal_p) /**< literal */ +{ + ecma_string_t *name_p; + uint32_t flags = context_p->global_status_flags; + + if (!(flags & ECMA_PARSE_EVAL) || (!(flags & ECMA_PARSE_DIRECT_EVAL) && (context_p->status_flags & PARSER_IS_STRICT))) + { + return false; + } + + if (JERRY_LIKELY (!(literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + name_p = ecma_new_ecma_string_from_utf8 (literal_p->char_p, literal_p->length); + } + else + { + uint8_t *destination_p = (uint8_t *) scanner_malloc (context_p, literal_p->length); + + lexer_convert_ident_to_cesu8 (destination_p, literal_p->char_p, literal_p->length); + + name_p = ecma_new_ecma_string_from_utf8 (destination_p, literal_p->length); + + scanner_free (destination_p, literal_p->length); + } + + ecma_object_t *lex_env_p; + + if (flags & ECMA_PARSE_DIRECT_EVAL) + { + lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p; + + while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL && ecma_is_property_enumerable (*property_p)) + { + ecma_deref_ecma_string (name_p); + return true; + } + } + + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + } + else + { + lex_env_p = ecma_get_global_scope (ecma_builtin_get_global ()); + } + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL + && (ecma_is_property_enumerable (*property_p) || scanner_find_duplicated_arg (context_p, literal_p))) + { + ecma_deref_ecma_string (name_p); + return true; + } + } + + ecma_deref_ecma_string (name_p); + return false; +} /* scanner_scope_find_lexical_declaration */ + +/** + * Push a new literal pool. + * + * @return the newly created literal pool + */ +scanner_literal_pool_t * +scanner_push_literal_pool (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + uint16_t status_flags) /**< combination of scanner_literal_pool_flags_t flags */ +{ + scanner_literal_pool_t *prev_literal_pool_p = scanner_context_p->active_literal_pool_p; + scanner_literal_pool_t *literal_pool_p; + + literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t)); + + if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION)) + { + JERRY_ASSERT (prev_literal_pool_p != NULL); + status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS; + + const uint16_t copied_flags = + (SCANNER_LITERAL_POOL_IN_WITH | SCANNER_LITERAL_POOL_GENERATOR | SCANNER_LITERAL_POOL_ASYNC); + + status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags); + } + else + { + context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION); + + if (status_flags & SCANNER_LITERAL_POOL_GENERATOR) + { + context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION; + } + + if (status_flags & SCANNER_LITERAL_POOL_ASYNC) + { + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION; + } + } + + if (prev_literal_pool_p != NULL) + { + const uint16_t copied_flags = SCANNER_LITERAL_POOL_IS_STRICT; + status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags); + + /* The logical value of these flags must be the same. */ + JERRY_ASSERT (!(status_flags & SCANNER_LITERAL_POOL_IS_STRICT) == !(context_p->status_flags & PARSER_IS_STRICT)); + } + + parser_list_init (&literal_pool_p->literal_pool, + sizeof (lexer_lit_location_t), + (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t))); + literal_pool_p->source_p = NULL; + literal_pool_p->status_flags = status_flags; + literal_pool_p->no_declarations = 0; + + literal_pool_p->prev_p = prev_literal_pool_p; + scanner_context_p->active_literal_pool_p = literal_pool_p; + + return literal_pool_p; +} /* scanner_push_literal_pool */ + +JERRY_STATIC_ASSERT (((uint8_t)PARSER_MAXIMUM_IDENT_LENGTH <= UINT8_MAX), maximum_ident_length_must_fit_in_a_byte); + +/** + * Current status of arguments. + */ +typedef enum +{ + SCANNER_ARGUMENTS_NOT_PRESENT, /**< arguments object must not be created */ + SCANNER_ARGUMENTS_MAY_PRESENT, /**< arguments object can be created */ + SCANNER_ARGUMENTS_MAY_PRESENT_IN_EVAL, /**< arguments object must be present unless otherwise declared */ + SCANNER_ARGUMENTS_PRESENT, /**< arguments object must be created */ + SCANNER_ARGUMENTS_PRESENT_NO_REG, /**< arguments object must be created and cannot be stored in registers */ +} scanner_arguments_type_t; + +/** + * Pop the last literal pool from the end. + */ +void +scanner_pop_literal_pool (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p; + + const uint32_t arrow_super_flags = (SCANNER_LITERAL_POOL_ARROW | SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE); + if ((literal_pool_p->status_flags & arrow_super_flags) == arrow_super_flags) + { + prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE; + } + + if (JERRY_UNLIKELY (literal_pool_p->source_p == NULL)) + { + JERRY_ASSERT (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION); + JERRY_ASSERT (literal_pool_p->literal_pool.data.first_p == NULL + && literal_pool_p->literal_pool.data.last_p == NULL); + + scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p; + scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t)); + return; + } + + uint16_t status_flags = literal_pool_p->status_flags; + scanner_arguments_type_t arguments_type = SCANNER_ARGUMENTS_MAY_PRESENT; + + if (status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) + { + arguments_type = SCANNER_ARGUMENTS_NOT_PRESENT; + } + else if (status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) + { + arguments_type = SCANNER_ARGUMENTS_MAY_PRESENT_IN_EVAL; + } + + if (status_flags & SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT; + + if (status_flags & (SCANNER_LITERAL_POOL_NO_ARGUMENTS | SCANNER_LITERAL_POOL_CAN_EVAL)) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT_NO_REG; + status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_NO_ARGUMENTS; + } + } + + uint8_t can_eval_types = 0; + + if (prev_literal_pool_p == NULL && !(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)) + { + can_eval_types |= SCANNER_LITERAL_IS_FUNC; + } + + if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && prev_literal_pool_p != NULL) + { + prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL; + } + + parser_list_iterator_t literal_iterator; + lexer_lit_location_t *literal_p; + int32_t no_declarations = literal_pool_p->no_declarations; + + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + + uint8_t arguments_stream_type = SCANNER_STREAM_TYPE_ARGUMENTS; + const uint8_t *prev_source_p = literal_pool_p->source_p - 1; + lexer_lit_location_t *last_argument_p = NULL; + size_t compressed_size = 1; + + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + uint8_t type = literal_p->type; + + if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)) + { + continue; + } + + if (!(status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) && scanner_literal_is_arguments (literal_p)) + { + JERRY_ASSERT (arguments_type != SCANNER_ARGUMENTS_NOT_PRESENT); + status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS; + + if (type & SCANNER_LITERAL_IS_ARG) + { + JERRY_ASSERT (arguments_type != SCANNER_ARGUMENTS_PRESENT + && arguments_type != SCANNER_ARGUMENTS_PRESENT_NO_REG); + arguments_type = SCANNER_ARGUMENTS_NOT_PRESENT; + last_argument_p = literal_p; + } + else if (type & SCANNER_LITERAL_IS_LOCAL) + { + if (arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT || arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT_IN_EVAL) + { + arguments_type = SCANNER_ARGUMENTS_NOT_PRESENT; + } + else + { + if (arguments_type == SCANNER_ARGUMENTS_PRESENT_NO_REG) + { + type |= SCANNER_LITERAL_NO_REG; + } + else if (type & (SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE)) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT_NO_REG; + } + + if ((type & SCANNER_LITERAL_IS_LOCAL_FUNC) == SCANNER_LITERAL_IS_LOCAL_FUNC) + { + type |= SCANNER_LITERAL_IS_ARG; + literal_p->type = type; + no_declarations--; + arguments_stream_type = SCANNER_STREAM_TYPE_ARGUMENTS_FUNC; + } + else + { + arguments_stream_type |= SCANNER_STREAM_LOCAL_ARGUMENTS; + } + } + } + else + { + if ((type & SCANNER_LITERAL_IS_VAR) + && (arguments_type == SCANNER_ARGUMENTS_PRESENT || arguments_type == SCANNER_ARGUMENTS_PRESENT_NO_REG)) + { + if (arguments_type == SCANNER_ARGUMENTS_PRESENT_NO_REG) + { + type |= SCANNER_LITERAL_NO_REG; + } + else if (type & (SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE)) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT_NO_REG; + } + + type |= SCANNER_LITERAL_IS_ARG; + literal_p->type = type; + no_declarations--; + } + + if ((type & SCANNER_LITERAL_NO_REG) || arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT_IN_EVAL) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT_NO_REG; + } + else if (arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT; + } + + /* The SCANNER_LITERAL_IS_ARG may be set above. */ + if (!(type & SCANNER_LITERAL_IS_ARG)) + { + literal_p->type = 0; + continue; + } + } + } + else if (type & SCANNER_LITERAL_IS_ARG) + { + last_argument_p = literal_p; + } + + if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) + && (type & SCANNER_LITERAL_IS_LOCAL_FUNC) == SCANNER_LITERAL_IS_FUNC) + { + if (prev_literal_pool_p == NULL && scanner_scope_find_lexical_declaration (context_p, literal_p)) + { + literal_p->type = 0; + continue; + } + + if (!(type & SCANNER_LITERAL_IS_ARG)) + { + type |= SCANNER_LITERAL_IS_VAR; + } + + type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC; + literal_p->type = type; + } + + if ((type & SCANNER_LITERAL_IS_LOCAL) + || ((type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)) + && (status_flags & SCANNER_LITERAL_POOL_FUNCTION))) + { + JERRY_ASSERT ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) || !(literal_p->type & SCANNER_LITERAL_IS_ARG)); + + if (literal_p->length == 0) + { + compressed_size += 1; + continue; + } + + no_declarations++; + + if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) || (type & can_eval_types)) + { + type |= SCANNER_LITERAL_NO_REG; + literal_p->type = type; + } + + if (type & SCANNER_LITERAL_IS_FUNC) + { + no_declarations++; + + if ((type & (SCANNER_LITERAL_IS_CONST | SCANNER_LITERAL_IS_ARG)) == SCANNER_LITERAL_IS_CONST) + { + JERRY_ASSERT (type & SCANNER_LITERAL_IS_LET); + + /* Catch parameters cannot be functions. */ + literal_p->type = (uint8_t) (type & ~SCANNER_LITERAL_IS_FUNC); + no_declarations--; + } + } + + intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p); + + if (diff >= 1 && diff <= (intptr_t) UINT8_MAX) + { + compressed_size += 2 + 1; + } + else if (diff >= -(intptr_t) UINT8_MAX && diff <= (intptr_t) UINT16_MAX) + { + compressed_size += 2 + 2; + } + else + { + compressed_size += 2 + 1 + sizeof (const uint8_t *); + } + + prev_source_p = literal_p->char_p + literal_p->length; + + if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) + || ((type & SCANNER_LITERAL_IS_FUNC) && (status_flags & SCANNER_LITERAL_POOL_IS_STRICT)) + || !(type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC))) + { + continue; + } + } + + if (prev_literal_pool_p != NULL && literal_p->length > 0) + { + /* Propagate literal to upper level. */ + lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p, prev_literal_pool_p, literal_p); + uint8_t extended_type = literal_location_p->type; + + if ((status_flags & (SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_CLASS_FIELD)) + || (type & SCANNER_LITERAL_NO_REG)) + { + extended_type |= SCANNER_LITERAL_NO_REG; + } + + extended_type |= SCANNER_LITERAL_IS_USED; + + if (status_flags & SCANNER_LITERAL_POOL_FUNCTION_STATEMENT) + { + extended_type |= SCANNER_LITERAL_EARLY_CREATE; + } + + const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_LOCAL); + + if ((type & SCANNER_LITERAL_IS_ARG) || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_LET + || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_CONST) + { + /* Clears the SCANNER_LITERAL_IS_VAR and SCANNER_LITERAL_IS_FUNC flags + * for speculative arrow parameters and local (non-var) functions. */ + type = 0; + } + + type = (uint8_t) (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC)); + JERRY_ASSERT (type == 0 || !(status_flags & SCANNER_LITERAL_POOL_FUNCTION)); + + literal_location_p->type = (uint8_t) (extended_type | type); + } + } + + if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) || (compressed_size > 1)) + { + if (arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT) + { + arguments_type = SCANNER_ARGUMENTS_NOT_PRESENT; + } + else if (arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT_IN_EVAL) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT_NO_REG; + } + + if (arguments_type != SCANNER_ARGUMENTS_NOT_PRESENT) + { + compressed_size++; + } + + compressed_size += sizeof (scanner_info_t); + + scanner_info_t *info_p; + + if (prev_literal_pool_p != NULL || scanner_context_p->end_arguments_p == NULL) + { + info_p = scanner_insert_info (context_p, literal_pool_p->source_p, compressed_size); + } + else + { + scanner_info_t *start_info_p = scanner_context_p->end_arguments_p; + info_p = scanner_insert_info_before (context_p, literal_pool_p->source_p, start_info_p, compressed_size); + } + + if (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK) + { + no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK; + } + + uint8_t *data_p = (uint8_t *) (info_p + 1); + bool mapped_arguments = false; + + if (status_flags & SCANNER_LITERAL_POOL_FUNCTION) + { + info_p->type = SCANNER_TYPE_FUNCTION; + + uint8_t u8_arg = 0; + + if (arguments_type != SCANNER_ARGUMENTS_NOT_PRESENT) + { + u8_arg |= SCANNER_FUNCTION_ARGUMENTS_NEEDED; + + if (no_declarations < PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK) + { + no_declarations++; + } + + if (!(status_flags & (SCANNER_LITERAL_POOL_IS_STRICT | SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT))) + { + mapped_arguments = true; + } + + if (arguments_type == SCANNER_ARGUMENTS_PRESENT_NO_REG) + { + arguments_stream_type |= SCANNER_STREAM_NO_REG; + } + + if (last_argument_p == NULL) + { + *data_p++ = arguments_stream_type; + } + } + else + { + last_argument_p = NULL; + } + + if (status_flags & (SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT | SCANNER_LITERAL_POOL_ARROW)) + { + u8_arg |= SCANNER_FUNCTION_HAS_COMPLEX_ARGUMENT; + } + + if (status_flags & SCANNER_LITERAL_POOL_ASYNC) + { + u8_arg |= SCANNER_FUNCTION_ASYNC; + + if (status_flags & SCANNER_LITERAL_POOL_FUNCTION_STATEMENT) + { + u8_arg |= SCANNER_FUNCTION_STATEMENT; + } + } + + if (status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) + { + u8_arg |= SCANNER_FUNCTION_LEXICAL_ENV_NEEDED; + } + + if (status_flags & SCANNER_LITERAL_POOL_IS_STRICT) + { + u8_arg |= SCANNER_FUNCTION_IS_STRICT; + } + + info_p->u8_arg = u8_arg; + info_p->u16_arg = (uint16_t) no_declarations; + } + else + { + info_p->type = SCANNER_TYPE_BLOCK; + + JERRY_ASSERT (prev_literal_pool_p != NULL); + } + + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + prev_source_p = literal_pool_p->source_p - 1; + no_declarations = literal_pool_p->no_declarations; + + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK) + || (!(literal_p->type & SCANNER_LITERAL_IS_LOCAL) + && (!(literal_p->type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)) + || !(status_flags & SCANNER_LITERAL_POOL_FUNCTION)))) + { + continue; + } + + if (literal_p->length == 0) + { + *data_p++ = SCANNER_STREAM_TYPE_HOLE; + + if (literal_p == last_argument_p) + { + *data_p++ = arguments_stream_type; + } + continue; + } + + no_declarations++; + + uint8_t type = SCANNER_STREAM_TYPE_VAR; + + if (literal_p->type & SCANNER_LITERAL_IS_FUNC) + { + no_declarations++; + type = SCANNER_STREAM_TYPE_FUNC; + + if (literal_p->type & SCANNER_LITERAL_IS_ARG) + { + type = SCANNER_STREAM_TYPE_ARG_FUNC; + + if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG) + { + type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC; + } + } + } + else if (literal_p->type & SCANNER_LITERAL_IS_ARG) + { + type = SCANNER_STREAM_TYPE_ARG; + + if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG) + { + type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG; + } + + if (literal_p->type & SCANNER_LITERAL_IS_VAR) + { + type = (uint8_t) (type + 1); + + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_ARG_VAR || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR); + } + } + else if (literal_p->type & SCANNER_LITERAL_IS_LET) + { + if (!(literal_p->type & SCANNER_LITERAL_IS_CONST)) + { + type = SCANNER_STREAM_TYPE_LET; + + if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && (literal_p->type & SCANNER_LITERAL_NO_REG)) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + } +#if JERRY_MODULE_SYSTEM + else if (prev_literal_pool_p == NULL) + { + type = SCANNER_STREAM_TYPE_IMPORT; + } +#endif /* JERRY_MODULE_SYSTEM */ + else + { + type = SCANNER_STREAM_TYPE_LOCAL; + } + } + else if (literal_p->type & SCANNER_LITERAL_IS_CONST) + { + type = SCANNER_STREAM_TYPE_CONST; + + if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && (literal_p->type & SCANNER_LITERAL_NO_REG)) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + } + + if (literal_p->type & SCANNER_LITERAL_EARLY_CREATE) + { + type |= SCANNER_STREAM_NO_REG | SCANNER_STREAM_EARLY_CREATE; + } + + if (literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE) + { + type |= SCANNER_STREAM_HAS_ESCAPE; + } + + if ((literal_p->type & SCANNER_LITERAL_NO_REG) + || (mapped_arguments && (literal_p->type & SCANNER_LITERAL_IS_ARG))) + { + type |= SCANNER_STREAM_NO_REG; + } + + data_p[0] = type; + data_p[1] = (uint8_t) literal_p->length; + data_p += 3; + + intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p); + + if (diff >= 1 && diff <= (intptr_t) UINT8_MAX) + { + data_p[-1] = (uint8_t) diff; + } + else if (diff >= -(intptr_t) UINT8_MAX && diff <= (intptr_t) UINT16_MAX) + { + if (diff < 0) + { + diff = -diff; + } + + data_p[-3] |= SCANNER_STREAM_UINT16_DIFF; + data_p[-1] = (uint8_t) diff; + data_p[0] = (uint8_t) (diff >> 8); + data_p += 1; + } + else + { + data_p[-1] = 0; + memcpy (data_p, &literal_p->char_p, sizeof (uintptr_t)); + data_p += sizeof (uintptr_t); + } + + if (literal_p == last_argument_p) + { + *data_p++ = arguments_stream_type; + } + + prev_source_p = literal_p->char_p + literal_p->length; + } + + data_p[0] = SCANNER_STREAM_TYPE_END; + + JERRY_ASSERT (((uint8_t *) info_p) + compressed_size == data_p + 1); + } + + if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION) + && (int32_t) prev_literal_pool_p->no_declarations < no_declarations) + { + prev_literal_pool_p->no_declarations = (uint16_t) no_declarations; + } + + if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) && prev_literal_pool_p != NULL) + { + if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IS_STRICT) + { + context_p->status_flags |= PARSER_IS_STRICT; + } + else + { + context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT; + } + + if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_GENERATOR) + { + context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION; + } + else + { + context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION; + } + + if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_ASYNC) + { + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION; + } + else + { + context_p->status_flags &= (uint32_t) ~PARSER_IS_ASYNC_FUNCTION; + } + } + + scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p; + + parser_list_free (&literal_pool_p->literal_pool); + scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t)); +} /* scanner_pop_literal_pool */ + +/** + * Filter out the arguments from a literal pool. + */ +void +scanner_filter_arguments (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + /* Fast case: check whether all literals are arguments. */ + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p; + parser_list_iterator_t literal_iterator; + lexer_lit_location_t *literal_p; + bool can_eval = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) != 0; + bool has_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0; + + JERRY_ASSERT (SCANNER_LITERAL_POOL_MAY_HAVE_ARGUMENTS (literal_pool_p->status_flags)); + + if (JERRY_UNLIKELY (can_eval)) + { + if (prev_literal_pool_p != NULL) + { + prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL; + } + + literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_CAN_EVAL; + } + else + { + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + + while (true) + { + literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator); + + if (literal_p == NULL) + { + return; + } + + if (can_eval || (literal_p->type & SCANNER_LITERAL_EARLY_CREATE)) + { + literal_p->type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE; + } + + uint8_t type = literal_p->type; + const uint8_t mask = + (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG); + + if ((type & mask) != SCANNER_LITERAL_IS_ARG) + { + break; + } + } + } + + /* Destructured args are placed after the other arguments because of register assignments. */ + bool has_destructured_arg = false; + scanner_literal_pool_t *new_literal_pool_p; + + new_literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t)); + + new_literal_pool_p->prev_p = literal_pool_p; + scanner_context_p->active_literal_pool_p = new_literal_pool_p; + + *new_literal_pool_p = *literal_pool_p; + parser_list_init (&new_literal_pool_p->literal_pool, + sizeof (lexer_lit_location_t), + (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t))); + + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + uint8_t type = literal_p->type; + + if (type & SCANNER_LITERAL_IS_ARG) + { + if (can_eval || (literal_p->type & SCANNER_LITERAL_EARLY_CREATE)) + { + type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE; + literal_p->type = type; + } + + if (has_arguments && scanner_literal_is_arguments (literal_p)) + { + has_arguments = false; + } + + if (type & (SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG)) + { + has_destructured_arg = true; + + if (type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG) + { + continue; + } + + type &= (uint8_t) ~SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG; + type |= SCANNER_LITERAL_IS_DESTRUCTURED_ARG; + + literal_p->type = type; + continue; + } + + lexer_lit_location_t *new_literal_p; + new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool); + *new_literal_p = *literal_p; + } + else if (has_arguments && scanner_literal_is_arguments (literal_p)) + { + /* Arguments object is directly referenced from the function arguments */ + new_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS; + + if (type & SCANNER_LITERAL_NO_REG) + { + new_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS; + } + } + else if (prev_literal_pool_p != NULL) + { + /* Propagate literal to upper level. */ + lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p, prev_literal_pool_p, literal_p); + type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_IS_USED; + literal_location_p->type |= type; + } + } + + if (has_destructured_arg) + { + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + const uint8_t expected_flags = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG; + + if ((literal_p->type & expected_flags) == expected_flags) + { + lexer_lit_location_t *new_literal_p; + new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool); + *new_literal_p = *literal_p; + } + } + } + + if (has_arguments) + { + /* Force the lexically stored arguments object creation */ + new_literal_pool_p->status_flags |= (SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS | SCANNER_LITERAL_POOL_NO_ARGUMENTS); + } + + new_literal_pool_p->prev_p = prev_literal_pool_p; + + parser_list_free (&literal_pool_p->literal_pool); + scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t)); +} /* scanner_filter_arguments */ + +/** + * Add any literal to the specified literal pool. + * + * @return pointer to the literal + */ +lexer_lit_location_t * +scanner_add_custom_literal (parser_context_t *context_p, /**< context */ + scanner_literal_pool_t *literal_pool_p, /**< literal pool */ + const lexer_lit_location_t *literal_location_p) /**< literal */ +{ + while (true) + { + parser_list_iterator_t literal_iterator; + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + lexer_lit_location_t *literal_p; + + const uint8_t *char_p = literal_location_p->char_p; + prop_length_t length = literal_location_p->length; + + if (JERRY_LIKELY (!(literal_location_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (literal_p->length == length) + { + if (JERRY_LIKELY (!(literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + if (memcmp (literal_p->char_p, char_p, length) == 0) + { + return literal_p; + } + } + else if (lexer_compare_identifier_to_string (literal_p, char_p, length)) + { + /* The non-escaped version is preferred. */ + literal_p->char_p = char_p; + literal_p->status_flags = LEXER_LIT_LOCATION_NO_OPTS; + return literal_p; + } + } + } + } + else + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (lexer_compare_identifiers (context_p, literal_p, literal_location_p)) + { + return literal_p; + } + } + } + + if (JERRY_UNLIKELY (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CLASS_NAME)) + { + literal_pool_p = literal_pool_p->prev_p; + continue; + } + + literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool); + *literal_p = *literal_location_p; + + literal_p->type = 0; + + return literal_p; + } +} /* scanner_add_custom_literal */ + +/** + * Add the current literal token to the current literal pool. + * + * @return pointer to the literal + */ +lexer_lit_location_t * +scanner_add_literal (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + return scanner_add_custom_literal (context_p, + scanner_context_p->active_literal_pool_p, + &context_p->token.lit_location); +} /* scanner_add_literal */ + +/** + * Add the current literal token to the current literal pool and + * set SCANNER_LITERAL_NO_REG if it is inside a with statement. + * + * @return pointer to the literal + */ +void +scanner_add_reference (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + lexer_lit_location_t *lit_location_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &context_p->token.lit_location); + lit_location_p->type |= SCANNER_LITERAL_IS_USED; + + if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + lit_location_p->type |= SCANNER_LITERAL_NO_REG; + } + + scanner_detect_eval_call (context_p, scanner_context_p); +} /* scanner_add_reference */ + +/** + * Append an argument to the literal pool. If the argument is already present, make it a "hole". + * + * @return newly created literal + */ +lexer_lit_location_t * +scanner_append_argument (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + parser_list_iterator_t literal_iterator; + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + lexer_lit_location_t *literal_location_p = &context_p->token.lit_location; + lexer_lit_location_t *literal_p; + + const uint8_t *char_p = literal_location_p->char_p; + prop_length_t length = literal_location_p->length; + + JERRY_ASSERT (SCANNER_LITERAL_POOL_MAY_HAVE_ARGUMENTS (literal_pool_p->status_flags)); + + if (JERRY_LIKELY (!(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (literal_p->length == length) + { + if (JERRY_LIKELY (!(literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + if (memcmp (literal_p->char_p, char_p, length) == 0) + { + break; + } + } + else if (lexer_compare_identifier_to_string (literal_p, char_p, length)) + { + break; + } + } + } + } + else + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (lexer_compare_identifiers (context_p, literal_p, literal_location_p)) + { + break; + } + } + } + + uint8_t literal_type = SCANNER_LITERAL_IS_ARG; + + if (literal_p != NULL) + { + literal_p->length = 0; + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_type = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_EARLY_CREATE; + } + } + + literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool); + + *literal_p = context_p->token.lit_location; + literal_p->type = literal_type; + + return literal_p; +} /* scanner_append_argument */ + +/** + * Add private identifiers to private ident pool + */ +void +scanner_add_private_identifier (parser_context_t *context_p, /**< context */ + scanner_private_field_flags_t opts) /**< options */ +{ + scan_stack_modes_t stack_top = (scan_stack_modes_t) context_p->stack_top_uint8; + parser_stack_pop_uint8 (context_p); + scanner_class_info_t *class_info_p; + parser_stack_pop (context_p, &class_info_p, sizeof (scanner_class_info_t *)); + + scanner_class_private_member_t *iter = class_info_p->members; + + scanner_private_field_flags_t search_flag = + (((unsigned int) opts & (unsigned int) SCANNER_PRIVATE_FIELD_PROPERTY) ? SCANNER_PRIVATE_FIELD_PROPERTY_GETTER_SETTER + : (scanner_private_field_flags_t) ((unsigned int) opts & (unsigned int) SCANNER_PRIVATE_FIELD_GETTER_SETTER)); + + while (iter != NULL) + { + if (lexer_compare_identifiers (context_p, &context_p->token.lit_location, &iter->loc) + && (iter->u8_arg & search_flag)) + { + scanner_raise_error (context_p); + } + + iter = iter->prev_p; + } + + scanner_class_private_member_t *p_member; + p_member = (scanner_class_private_member_t *) scanner_malloc (context_p, sizeof (scanner_class_private_member_t)); + p_member->loc = context_p->token.lit_location; + p_member->u8_arg = (uint8_t) opts; + p_member->prev_p = class_info_p->members; + class_info_p->members = p_member; + + parser_stack_push (context_p, &class_info_p, sizeof (scanner_class_info_t *)); + parser_stack_push_uint8 (context_p, (uint8_t) stack_top); +} /* scanner_add_private_identifier */ + +/** + * Check whether an eval call is performed and update the status flags accordingly. + */ +void +scanner_detect_eval_call (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + if (context_p->token.keyword_type == LEXER_KEYW_EVAL && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + scanner_context_p->active_literal_pool_p->status_flags |= + (SCANNER_LITERAL_POOL_CAN_EVAL | SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE); + } +} /* scanner_detect_eval_call */ + +/** + * Throws an error for invalid var statements. + */ +void +scanner_detect_invalid_var (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + lexer_lit_location_t *var_literal_p) /**< var literal */ +{ + if (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL + && !(var_literal_p->type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_ARG)) + && (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL) + { + scanner_raise_redeclaration_error (context_p); + } + + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + + if (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION) + && ((var_literal_p->type & SCANNER_LITERAL_IS_LOCAL_FUNC) == SCANNER_LITERAL_IS_LOCAL_FUNC)) + { + scanner_raise_redeclaration_error (context_p); + } + + const uint8_t *char_p = var_literal_p->char_p; + prop_length_t length = var_literal_p->length; + + while (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION)) + { + literal_pool_p = literal_pool_p->prev_p; + + parser_list_iterator_t literal_iterator; + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + lexer_lit_location_t *literal_p; + + if (JERRY_LIKELY (!(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if ((literal_p->type & SCANNER_LITERAL_IS_LOCAL) && !(literal_p->type & SCANNER_LITERAL_IS_ARG) + && !((literal_p->type & SCANNER_LITERAL_IS_FUNC) + && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION)) + && (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL && literal_p->length == length) + { + if (JERRY_LIKELY (!(literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + if (memcmp (literal_p->char_p, char_p, length) == 0) + { + scanner_raise_redeclaration_error (context_p); + return; + } + } + else if (lexer_compare_identifier_to_string (literal_p, char_p, length)) + { + scanner_raise_redeclaration_error (context_p); + return; + } + } + } + } + else + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if ((literal_p->type & SCANNER_LITERAL_IS_LOCAL) && !(literal_p->type & SCANNER_LITERAL_IS_ARG) + && !((literal_p->type & SCANNER_LITERAL_IS_FUNC) + && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION)) + && (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL + && lexer_compare_identifiers (context_p, literal_p, var_literal_p)) + { + scanner_raise_redeclaration_error (context_p); + return; + } + } + } + } + + if (scanner_scope_find_lexical_declaration (context_p, var_literal_p)) + { + scanner_raise_redeclaration_error (context_p); + } +} /* scanner_detect_invalid_var */ + +/** + * Throws an error for invalid let statements. + */ +void +scanner_detect_invalid_let (parser_context_t *context_p, /**< context */ + lexer_lit_location_t *let_literal_p) /**< let literal */ +{ + if (let_literal_p->type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_LOCAL)) + { + scanner_raise_redeclaration_error (context_p); + } + + if (let_literal_p->type & SCANNER_LITERAL_IS_FUNC) + { + let_literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC; + } +} /* scanner_detect_invalid_let */ + +/** + * Push the values required for class declaration parsing. + * + * @return literal reference created for class statements, NULL otherwise + */ +lexer_lit_location_t * +scanner_push_class_declaration (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /* scanner context */ + uint8_t stack_mode) /**< stack mode */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS); + + const uint8_t *source_p = context_p->source_p; + lexer_lit_location_t *literal_p = NULL; + +#if JERRY_MODULE_SYSTEM + bool is_export_default = context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT; + JERRY_ASSERT (!is_export_default || stack_mode == SCAN_STACK_CLASS_EXPRESSION); +#endif /* JERRY_MODULE_SYSTEM */ + + parser_stack_push_uint8 (context_p, stack_mode); + lexer_next_token (context_p); + + bool class_has_name = + (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + if (class_has_name) + { + literal_p = scanner_add_literal (context_p, scanner_context_p); + scanner_context_p->active_literal_pool_p->no_declarations++; + +#if JERRY_MODULE_SYSTEM + if (is_export_default) + { + scanner_detect_invalid_let (context_p, literal_p); + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + + literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG; + } +#endif /* JERRY_MODULE_SYSTEM */ + } + + scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + + if (class_has_name) + { + scanner_add_literal (context_p, scanner_context_p); + scanner_context_p->active_literal_pool_p->no_declarations++; + } +#if JERRY_MODULE_SYSTEM + else if (is_export_default) + { + lexer_lit_location_t *name_literal_p; + name_literal_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p->prev_p, &lexer_default_literal); + + name_literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG; + scanner_context_p->active_literal_pool_p->no_declarations++; + } +#endif /* JERRY_MODULE_SYSTEM */ + + literal_pool_p->source_p = source_p; + literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CLASS_NAME; + + const uint8_t *class_source_p = scanner_context_p->active_literal_pool_p->source_p; + scanner_class_info_t *class_info_p = + (scanner_class_info_t *) scanner_insert_info (context_p, class_source_p, sizeof (scanner_class_info_t)); + + class_info_p->info.type = SCANNER_TYPE_CLASS_CONSTRUCTOR; + class_info_p->members = NULL; + class_info_p->info.u8_arg = SCANNER_CONSTRUCTOR_IMPLICIT; + + parser_stack_push (context_p, &class_info_p, sizeof (scanner_class_info_t *)); + parser_stack_push_uint8 (context_p, SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR); + scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION; + + return literal_p; +} /* scanner_push_class_declaration */ + +/** + * Push the start of a class field initializer. + */ +void +scanner_push_class_field_initializer (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /* scanner context */ +{ + scanner_source_start_t source_start; + source_start.source_p = context_p->source_p; + + parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_FIELD_INITIALIZER); + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_CLASS_FIELD); + literal_pool_p->source_p = context_p->source_p; + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; +} /* scanner_push_class_field_initializer */ + +/** + * Push the values required for destructuring assignment or binding parsing. + */ +void +scanner_push_destructuring_pattern (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + uint8_t binding_type, /**< type of destructuring binding pattern */ + bool is_nested) /**< nested declaration */ +{ + JERRY_ASSERT (binding_type != SCANNER_BINDING_NONE || !is_nested); + + scanner_source_start_t source_start; + source_start.source_p = context_p->source_p; + + parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t)); + parser_stack_push_uint8 (context_p, scanner_context_p->binding_type); + scanner_context_p->binding_type = binding_type; + + if (SCANNER_NEEDS_BINDING_LIST (binding_type)) + { + scanner_binding_list_t *binding_list_p; + binding_list_p = (scanner_binding_list_t *) scanner_malloc (context_p, sizeof (scanner_binding_list_t)); + + binding_list_p->prev_p = scanner_context_p->active_binding_list_p; + binding_list_p->items_p = NULL; + binding_list_p->is_nested = is_nested; + + scanner_context_p->active_binding_list_p = binding_list_p; + } +} /* scanner_push_destructuring_pattern */ + +/** + * Pop binding list. + */ +void +scanner_pop_binding_list (scanner_context_t *scanner_context_p) /**< scanner context */ +{ + scanner_binding_list_t *binding_list_p = scanner_context_p->active_binding_list_p; + JERRY_ASSERT (binding_list_p != NULL); + + scanner_binding_item_t *item_p = binding_list_p->items_p; + scanner_binding_list_t *prev_binding_list_p = binding_list_p->prev_p; + bool is_nested = binding_list_p->is_nested; + + scanner_free (binding_list_p, sizeof (scanner_binding_list_t)); + scanner_context_p->active_binding_list_p = prev_binding_list_p; + + if (!is_nested) + { + while (item_p != NULL) + { + scanner_binding_item_t *next_p = item_p->next_p; + + JERRY_ASSERT (item_p->literal_p->type & (SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_IS_ARG)); + + scanner_free (item_p, sizeof (scanner_binding_item_t)); + item_p = next_p; + } + return; + } + + JERRY_ASSERT (prev_binding_list_p != NULL); + + while (item_p != NULL) + { + scanner_binding_item_t *next_p = item_p->next_p; + + item_p->next_p = prev_binding_list_p->items_p; + prev_binding_list_p->items_p = item_p; + + item_p = next_p; + } +} /* scanner_pop_binding_list */ + +/** + * Append a hole into the literal pool. + */ +void +scanner_append_hole (parser_context_t *context_p, scanner_context_t *scanner_context_p) +{ + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + + lexer_lit_location_t *literal_p; + literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool); + + literal_p->char_p = NULL; + literal_p->length = 0; + literal_p->type = SCANNER_LITERAL_IS_ARG; + literal_p->status_flags = LEXER_LIT_LOCATION_NO_OPTS; +} /* scanner_append_hole */ + +/** + * Reverse the scanner info chain after the scanning is completed. + */ +void +scanner_reverse_info_list (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *scanner_info_p = context_p->next_scanner_info_p; + scanner_info_t *last_scanner_info_p = NULL; + + if (scanner_info_p->type == SCANNER_TYPE_END) + { + return; + } + + do + { + scanner_info_t *next_scanner_info_p = scanner_info_p->next_p; + scanner_info_p->next_p = last_scanner_info_p; + + last_scanner_info_p = scanner_info_p; + scanner_info_p = next_scanner_info_p; + } while (scanner_info_p->type != SCANNER_TYPE_END); + + context_p->next_scanner_info_p->next_p = scanner_info_p; + context_p->next_scanner_info_p = last_scanner_info_p; +} /* scanner_reverse_info_list */ + +/** + * Release unused scanner info blocks. + * This should happen only if an error is occurred. + */ +void +scanner_cleanup (parser_context_t *context_p) /**< context */ +{ + if (context_p->skipped_scanner_info_p != NULL) + { + context_p->skipped_scanner_info_end_p->next_p = context_p->next_scanner_info_p; + context_p->next_scanner_info_p = context_p->skipped_scanner_info_p; + context_p->skipped_scanner_info_p = NULL; + } + + scanner_info_t *scanner_info_p = context_p->next_scanner_info_p; + + while (scanner_info_p != NULL) + { + scanner_info_t *next_scanner_info_p = scanner_info_p->next_p; + + size_t size = sizeof (scanner_info_t); + + switch (scanner_info_p->type) + { + case SCANNER_TYPE_END: + { + scanner_info_p = context_p->active_scanner_info_p; + continue; + } + case SCANNER_TYPE_FUNCTION: + case SCANNER_TYPE_BLOCK: + { + size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_info_t)); + break; + } + case SCANNER_TYPE_WHILE: + case SCANNER_TYPE_FOR_IN: + case SCANNER_TYPE_FOR_OF: + case SCANNER_TYPE_CASE: + case SCANNER_TYPE_INITIALIZER: + case SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END: + case SCANNER_TYPE_CLASS_STATIC_BLOCK_END: + { + size = sizeof (scanner_location_info_t); + break; + } + case SCANNER_TYPE_FOR: + { + size = sizeof (scanner_for_info_t); + break; + } + case SCANNER_TYPE_SWITCH: + { + scanner_release_switch_cases (((scanner_switch_info_t *) scanner_info_p)->case_p); + size = sizeof (scanner_switch_info_t); + break; + } + case SCANNER_TYPE_CLASS_CONSTRUCTOR: + { + scanner_release_private_fields (((scanner_class_info_t *) scanner_info_p)->members); + size = sizeof (scanner_class_info_t); + break; + } + default: + { + JERRY_ASSERT ( + scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS || scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS + || scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION || scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED + || scanner_info_p->type == SCANNER_TYPE_ERR_ASYNC_FUNCTION + || scanner_info_p->type == SCANNER_TYPE_EXPORT_MODULE_SPECIFIER); + break; + } + } + + scanner_free (scanner_info_p, size); + scanner_info_p = next_scanner_info_p; + } + + context_p->next_scanner_info_p = NULL; + context_p->active_scanner_info_p = NULL; +} /* scanner_cleanup */ + +/** + * Checks whether a context needs to be created for a block. + * + * @return true - if context is needed, + * false - otherwise + */ +bool +scanner_is_context_needed (parser_context_t *context_p, /**< context */ + parser_check_context_type_t check_type) /**< context type */ +{ + scanner_info_t *info_p = context_p->next_scanner_info_p; + const uint8_t *data_p = (const uint8_t *) (info_p + 1); + + JERRY_UNUSED (check_type); + + JERRY_ASSERT ((check_type == PARSER_CHECK_BLOCK_CONTEXT ? info_p->type == SCANNER_TYPE_BLOCK + : info_p->type == SCANNER_TYPE_FUNCTION)); + + uint32_t scope_stack_reg_top = + (check_type != PARSER_CHECK_GLOBAL_CONTEXT ? context_p->scope_stack_reg_top : 1); /* block result */ + + while (data_p[0] != SCANNER_STREAM_TYPE_END) + { + uint8_t data = data_p[0]; + uint32_t type = data & SCANNER_STREAM_TYPE_MASK; + + if (JERRY_UNLIKELY (check_type == PARSER_CHECK_FUNCTION_CONTEXT)) + { + if (JERRY_UNLIKELY (type == SCANNER_STREAM_TYPE_HOLE)) + { + data_p++; + continue; + } + + if (JERRY_UNLIKELY (SCANNER_STREAM_TYPE_IS_ARGUMENTS (type))) + { + if ((data & SCANNER_STREAM_NO_REG) || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + return true; + } + + scope_stack_reg_top++; + data_p++; + continue; + } + } + +#ifndef JERRY_NDEBUG + if (check_type == PARSER_CHECK_BLOCK_CONTEXT) + { + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_LET + || type == SCANNER_STREAM_TYPE_CONST || type == SCANNER_STREAM_TYPE_LOCAL + || type == SCANNER_STREAM_TYPE_FUNC); + } + else if (check_type == PARSER_CHECK_GLOBAL_CONTEXT) + { +#if JERRY_MODULE_SYSTEM + const bool is_import = (type == SCANNER_STREAM_TYPE_IMPORT); +#else /* !JERRY_MODULE_SYSTEM */ + const bool is_import = true; +#endif /* JERRY_MODULE_SYSTEM */ + + /* FIXME: a private declarative lexical environment should always be present + * for modules. Remove SCANNER_STREAM_TYPE_IMPORT after it is implemented. */ + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_LET + || type == SCANNER_STREAM_TYPE_CONST || type == SCANNER_STREAM_TYPE_FUNC || is_import); + + /* Only let/const can be stored in registers */ + JERRY_ASSERT ((data & SCANNER_STREAM_NO_REG) + || (type == SCANNER_STREAM_TYPE_FUNC && (context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)) + || type == SCANNER_STREAM_TYPE_LET || type == SCANNER_STREAM_TYPE_CONST); + } + else + { + JERRY_ASSERT (check_type == PARSER_CHECK_FUNCTION_CONTEXT); + + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_LET + || type == SCANNER_STREAM_TYPE_CONST || type == SCANNER_STREAM_TYPE_LOCAL + || type == SCANNER_STREAM_TYPE_ARG || type == SCANNER_STREAM_TYPE_ARG_VAR + || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR + || type == SCANNER_STREAM_TYPE_ARG_FUNC || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC + || type == SCANNER_STREAM_TYPE_FUNC); + } +#endif /* !JERRY_NDEBUG */ + if (!(data & SCANNER_STREAM_UINT16_DIFF)) + { + if (data_p[2] != 0) + { + data_p += 2 + 1; + } + else + { + data_p += 2 + 1 + sizeof (const uint8_t *); + } + } + else + { + data_p += 2 + 2; + } + +#if JERRY_MODULE_SYSTEM + const bool is_import = (type == SCANNER_STREAM_TYPE_IMPORT); +#else /* !JERRY_MODULE_SYSTEM */ + const bool is_import = false; +#endif /* JERRY_MODULE_SYSTEM */ + + if (JERRY_UNLIKELY (check_type == PARSER_CHECK_GLOBAL_CONTEXT) + && (type == SCANNER_STREAM_TYPE_VAR + || (type == SCANNER_STREAM_TYPE_FUNC && !(context_p->global_status_flags & ECMA_PARSE_EVAL)) || is_import)) + { + continue; + } + + if (JERRY_UNLIKELY (check_type == PARSER_CHECK_FUNCTION_CONTEXT)) + { + if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type) || type == SCANNER_STREAM_TYPE_ARG_VAR + || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR) + { + /* The return value is true, if the variable is stored in the lexical environment + * or all registers have already been used for function arguments. This can be + * inprecise in the latter case, but this is a very rare corner case. A more + * sophisticated check would require to decode the literal. */ + if ((data & SCANNER_STREAM_NO_REG) || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + return true; + } + continue; + } + + if (SCANNER_STREAM_TYPE_IS_ARG (type)) + { + continue; + } + } + + if ((data & SCANNER_STREAM_NO_REG) || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + return true; + } + + scope_stack_reg_top++; + } + + return false; +} /* scanner_is_context_needed */ + +/** + * Try to scan/parse the ".target" part in the "new.target" expression. + * + * Upon exiting with "true" the current token will point to the "target" + * literal. + * + * If the "target" literal is not after the "new." then a scanner/parser + * error will be raised. + * + * @returns true if the ".target" part was found + * false if there is no "." after the new. + */ +bool +scanner_try_scan_new_target (parser_context_t *context_p) /**< parser/scanner context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_NEW); + + if (lexer_check_next_character (context_p, LIT_CHAR_DOT)) + { + lexer_next_token (context_p); + if (context_p->token.type != LEXER_DOT) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); + } + + lexer_next_token (context_p); + if (!lexer_token_is_identifier (context_p, "target", 6)) + { + parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_EXPECTED); + } + + return true; + } + return false; +} /* scanner_try_scan_new_target */ + +/** + * Description of "arguments" literal string. + */ +const lexer_lit_location_t lexer_arguments_literal = { (const uint8_t *) "arguments", + 9, + LEXER_IDENT_LITERAL, + LEXER_LIT_LOCATION_IS_ASCII }; + +/** + * Create an unused literal. + */ +static void +scanner_create_unused_literal (parser_context_t *context_p, /**< context */ + uint8_t status_flags) /**< initial status flags */ +{ + if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + + literal_p->type = LEXER_UNUSED_LITERAL; + literal_p->status_flags = status_flags; + + context_p->literal_count++; +} /* scanner_create_unused_literal */ + +/** + * Emit checks for redeclared bindings in the global lexical scope. + */ +void +scanner_check_variables (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *info_p = context_p->next_scanner_info_p; + const uint8_t *next_data_p = (const uint8_t *) (info_p + 1); + lexer_lit_location_t literal; + + JERRY_ASSERT (info_p->type == SCANNER_TYPE_FUNCTION); + + literal.char_p = info_p->source_p - 1; + + while (next_data_p[0] != SCANNER_STREAM_TYPE_END) + { + uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK; + const uint8_t *data_p = next_data_p; + + JERRY_ASSERT (type != SCANNER_STREAM_TYPE_HOLE && !SCANNER_STREAM_TYPE_IS_ARG (type) + && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)); + JERRY_ASSERT (data_p[0] & SCANNER_STREAM_NO_REG); + + if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF)) + { + if (data_p[2] != 0) + { + literal.char_p += data_p[2]; + next_data_p += 2 + 1; + } + else + { + memcpy (&literal.char_p, data_p + 2 + 1, sizeof (uintptr_t)); + next_data_p += 2 + 1 + sizeof (uintptr_t); + } + } + else + { + int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8; + + if (diff <= (intptr_t) UINT8_MAX) + { + diff = -diff; + } + + literal.char_p += diff; + next_data_p += 2 + 2; + } + + literal.length = data_p[1]; + literal.type = LEXER_IDENT_LITERAL; + literal.status_flags = + ((data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? LEXER_LIT_LOCATION_HAS_ESCAPE : LEXER_LIT_LOCATION_NO_OPTS); + + lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL); + literal.char_p += data_p[1]; + +#if JERRY_MODULE_SYSTEM + if (type == SCANNER_STREAM_TYPE_IMPORT) + { + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED; + + uint16_t opcode; + if (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_FUNC) + { + opcode = CBC_CHECK_VAR; + } + else + { + opcode = CBC_CHECK_LET; + } + + parser_emit_cbc_literal (context_p, opcode, context_p->lit_object.index); + } + + parser_flush_cbc (context_p); +} /* scanner_check_variables */ + +/** + * Create and/or initialize var/let/const/function/etc. variables. + */ +void +scanner_create_variables (parser_context_t *context_p, /**< context */ + uint32_t option_flags) /**< combination of scanner_create_variables_flags_t bits */ +{ + scanner_info_t *info_p = context_p->next_scanner_info_p; + const uint8_t *next_data_p = (const uint8_t *) (info_p + 1); + uint8_t info_type = info_p->type; + uint8_t info_u8_arg = info_p->u8_arg; + lexer_lit_location_t literal; + parser_scope_stack_t *scope_stack_p; + parser_scope_stack_t *scope_stack_end_p; + + JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION || info_type == SCANNER_TYPE_BLOCK); + JERRY_ASSERT (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS) + || !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)); + JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION + || !(option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_ARGS | SCANNER_CREATE_VARS_IS_FUNCTION_BODY))); + + uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top; + + if (info_type == SCANNER_TYPE_FUNCTION && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)) + { + JERRY_ASSERT (context_p->scope_stack_p == NULL); + + size_t stack_size = info_p->u16_arg * sizeof (parser_scope_stack_t); + context_p->scope_stack_size = info_p->u16_arg; + + scope_stack_p = NULL; + + if (stack_size > 0) + { + scope_stack_p = (parser_scope_stack_t *) parser_malloc (context_p, stack_size); + } + + context_p->scope_stack_p = scope_stack_p; + scope_stack_end_p = scope_stack_p + context_p->scope_stack_size; + + if (option_flags & (SCANNER_CREATE_VARS_IS_SCRIPT | SCANNER_CREATE_VARS_IS_MODULE)) + { + scope_stack_reg_top++; /* block result */ + } + } + else + { + JERRY_ASSERT (context_p->scope_stack_p != NULL || context_p->scope_stack_size == 0); + + scope_stack_p = context_p->scope_stack_p; + scope_stack_end_p = scope_stack_p + context_p->scope_stack_size; + scope_stack_p += context_p->scope_stack_top; + } + + literal.char_p = info_p->source_p - 1; + + while (next_data_p[0] != SCANNER_STREAM_TYPE_END) + { + uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK; + const uint8_t *data_p = next_data_p; + + JERRY_ASSERT ((option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_BODY | SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)) + || (type != SCANNER_STREAM_TYPE_HOLE && !SCANNER_STREAM_TYPE_IS_ARG (type) + && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))); + +#if JERRY_MODULE_SYSTEM + JERRY_ASSERT (type != SCANNER_STREAM_TYPE_IMPORT || (data_p[0] & SCANNER_STREAM_NO_REG)); +#endif /* JERRY_MODULE_SYSTEM */ + + if (JERRY_UNLIKELY (type == SCANNER_STREAM_TYPE_HOLE)) + { + JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION); + next_data_p++; + + if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY) + { + continue; + } + + uint8_t mask = SCANNER_FUNCTION_ARGUMENTS_NEEDED | SCANNER_FUNCTION_HAS_COMPLEX_ARGUMENT; + + if (!(context_p->status_flags & PARSER_IS_STRICT) && (info_u8_arg & mask) == SCANNER_FUNCTION_ARGUMENTS_NEEDED) + { + scanner_create_unused_literal (context_p, LEXER_FLAG_FUNCTION_ARGUMENT); + } + + if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + scope_stack_reg_top++; + } + continue; + } + + if (JERRY_UNLIKELY (SCANNER_STREAM_TYPE_IS_ARGUMENTS (type))) + { + JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION); + next_data_p++; + + if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY) + { + continue; + } + + context_p->status_flags |= PARSER_ARGUMENTS_NEEDED; + + if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } + + lexer_construct_literal_object (context_p, &lexer_arguments_literal, LEXER_NEW_IDENT_LITERAL); + scope_stack_p->map_from = context_p->lit_object.index; + + uint16_t map_to; + + if (!(data_p[0] & SCANNER_STREAM_NO_REG) && scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top); + + scope_stack_p->map_to = (uint16_t) (scope_stack_reg_top + 1); + scope_stack_reg_top++; + } + else + { + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED; + map_to = context_p->lit_object.index; + + context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED; + + if (data_p[0] & SCANNER_STREAM_LOCAL_ARGUMENTS) + { + context_p->status_flags |= PARSER_LEXICAL_BLOCK_NEEDED; + } + + scope_stack_p->map_to = 0; + } + + scope_stack_p++; + +#if JERRY_PARSER_DUMP_BYTE_CODE + context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_emit_cbc_ext_literal (context_p, CBC_EXT_CREATE_ARGUMENTS, map_to); + + if (type == SCANNER_STREAM_TYPE_ARGUMENTS_FUNC) + { + if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } + + scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC; + scope_stack_p->map_to = context_p->literal_count; + scope_stack_p++; + + scanner_create_unused_literal (context_p, 0); + } + + if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS) + { + break; + } + continue; + } + + JERRY_ASSERT (context_p->scope_stack_size != 0); + + if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF)) + { + if (data_p[2] != 0) + { + literal.char_p += data_p[2]; + next_data_p += 2 + 1; + } + else + { + memcpy (&literal.char_p, data_p + 2 + 1, sizeof (uintptr_t)); + next_data_p += 2 + 1 + sizeof (uintptr_t); + } + } + else + { + int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8; + + if (diff <= (intptr_t) UINT8_MAX) + { + diff = -diff; + } + + literal.char_p += diff; + next_data_p += 2 + 2; + } + + if (SCANNER_STREAM_TYPE_IS_ARG (type)) + { + if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY) + { + if ((context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED) + && (type == SCANNER_STREAM_TYPE_ARG_VAR || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR)) + { + literal.length = data_p[1]; + literal.type = LEXER_IDENT_LITERAL; + literal.status_flags = + ((data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? LEXER_LIT_LOCATION_HAS_ESCAPE : LEXER_LIT_LOCATION_NO_OPTS); + + /* Literal must be exists. */ + lexer_construct_literal_object (context_p, &literal, LEXER_IDENT_LITERAL); + + if (context_p->lit_object.index < PARSER_REGISTER_START) + { + parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_COPY_FROM_ARG); + } + } + + literal.char_p += data_p[1]; + continue; + } + } + else if ((option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS) && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)) + { + /* Function arguments must come first. */ + break; + } + + literal.length = data_p[1]; + literal.type = LEXER_IDENT_LITERAL; + literal.status_flags = + ((data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? LEXER_LIT_LOCATION_HAS_ESCAPE : LEXER_LIT_LOCATION_NO_OPTS); + + lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL); + literal.char_p += data_p[1]; + + if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type) && (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)) + { + JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p + 2); + JERRY_ASSERT (context_p->status_flags & PARSER_IS_FUNCTION); + JERRY_ASSERT (!(context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS)); + + parser_scope_stack_t *function_map_p = scope_stack_p - 2; + uint16_t literal_index = context_p->lit_object.index; + + while (literal_index != function_map_p->map_from) + { + function_map_p--; + + JERRY_ASSERT (function_map_p >= context_p->scope_stack_p); + } + + JERRY_ASSERT (function_map_p[1].map_from == PARSER_SCOPE_STACK_FUNC); + + cbc_opcode_t opcode = CBC_SET_VAR_FUNC; + + if (JERRY_UNLIKELY (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED) + && (function_map_p[0].map_to & PARSER_SCOPE_STACK_REGISTER_MASK) == 0) + { + opcode = CBC_INIT_ARG_OR_FUNC; + } + + parser_emit_cbc_literal_value (context_p, + (uint16_t) opcode, + function_map_p[1].map_to, + scanner_decode_map_to (function_map_p)); + continue; + } + + if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } + + scope_stack_p->map_from = context_p->lit_object.index; + + if (info_type == SCANNER_TYPE_FUNCTION) + { + if (type != SCANNER_STREAM_TYPE_LET +#if JERRY_MODULE_SYSTEM + && type != SCANNER_STREAM_TYPE_IMPORT +#endif /* JERRY_MODULE_SYSTEM */ + && type != SCANNER_STREAM_TYPE_CONST) + { + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_GLOBAL; + } + } + + uint16_t map_to; + uint16_t func_init_opcode = CBC_INIT_ARG_OR_FUNC; + + if (!(data_p[0] & SCANNER_STREAM_NO_REG) && scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top); + scope_stack_p->map_to = (uint16_t) (scope_stack_reg_top + 1); + scope_stack_reg_top++; + + switch (type) + { + case SCANNER_STREAM_TYPE_CONST: + { + scope_stack_p->map_to |= PARSER_SCOPE_STACK_IS_CONST_REG; + /* FALLTHRU */ + } + case SCANNER_STREAM_TYPE_LET: + case SCANNER_STREAM_TYPE_ARG: + case SCANNER_STREAM_TYPE_ARG_VAR: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR: + case SCANNER_STREAM_TYPE_ARG_FUNC: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC: + { + scope_stack_p->map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY; + break; + } + } + + func_init_opcode = CBC_SET_VAR_FUNC; + } + else + { + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED; + map_to = context_p->lit_object.index; + + uint16_t scope_stack_map_to = 0; + + if (info_type == SCANNER_TYPE_FUNCTION) + { + context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED; + } + + switch (type) + { + case SCANNER_STREAM_TYPE_LET: + case SCANNER_STREAM_TYPE_CONST: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC: + { + scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY; + + if (!(data_p[0] & SCANNER_STREAM_EARLY_CREATE)) + { + break; + } + scope_stack_map_to |= PARSER_SCOPE_STACK_IS_LOCAL_CREATED; + /* FALLTHRU */ + } + case SCANNER_STREAM_TYPE_LOCAL: + case SCANNER_STREAM_TYPE_VAR: + { +#if JERRY_PARSER_DUMP_BYTE_CODE + context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + uint16_t opcode; + + switch (type) + { + case SCANNER_STREAM_TYPE_LET: + { + opcode = CBC_CREATE_LET; + break; + } + case SCANNER_STREAM_TYPE_CONST: + { + opcode = CBC_CREATE_CONST; + break; + } + case SCANNER_STREAM_TYPE_VAR: + { + opcode = CBC_CREATE_VAR; + + if (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT) + { + opcode = CBC_CREATE_VAR_EVAL; + + if ((context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT) + && !(context_p->status_flags & PARSER_IS_STRICT)) + { + opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_EVAL); + } + } + break; + } + default: + { + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_LOCAL || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG + || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR + || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC); + + opcode = CBC_CREATE_LOCAL; + break; + } + } + + parser_emit_cbc_literal (context_p, opcode, map_to); + break; + } + case SCANNER_STREAM_TYPE_ARG: + case SCANNER_STREAM_TYPE_ARG_VAR: + case SCANNER_STREAM_TYPE_ARG_FUNC: + { +#if JERRY_PARSER_DUMP_BYTE_CODE + context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY; + + /* Argument initializers of functions with simple arguments (e.g. function f(a,b,a) {}) are + * generated here. The other initializers are handled by parser_parse_function_arguments(). */ + if (!(info_u8_arg & SCANNER_FUNCTION_HAS_COMPLEX_ARGUMENT)) + { + parser_emit_cbc_literal_value (context_p, + CBC_INIT_ARG_OR_FUNC, + (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top), + map_to); + } + else if (data_p[0] & SCANNER_STREAM_EARLY_CREATE) + { + parser_emit_cbc_literal (context_p, CBC_CREATE_LOCAL, map_to); + scope_stack_map_to |= PARSER_SCOPE_STACK_IS_LOCAL_CREATED; + } + + if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + scope_stack_reg_top++; + } + break; + } + } + + scope_stack_p->map_to = scope_stack_map_to; + } + + scope_stack_p++; + + if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type)) + { + continue; + } + + if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } + +#if JERRY_PARSER_DUMP_BYTE_CODE + context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + if (!SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)) + { + if (func_init_opcode == CBC_INIT_ARG_OR_FUNC && (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT)) + { + literal.char_p -= data_p[1]; + + if (!scanner_scope_find_lexical_declaration (context_p, &literal)) + { + func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL; + + if (context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT) + { + func_init_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL); + } + } + literal.char_p += data_p[1]; + } + + parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to); + } + + scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC; + scope_stack_p->map_to = context_p->literal_count; + scope_stack_p++; + + scanner_create_unused_literal (context_p, 0); + } + + context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); + context_p->scope_stack_reg_top = (uint16_t) scope_stack_reg_top; + + if (info_type == SCANNER_TYPE_FUNCTION) + { + context_p->scope_stack_global_end = context_p->scope_stack_top; + } + + if (context_p->register_count < scope_stack_reg_top) + { + context_p->register_count = (uint16_t) scope_stack_reg_top; + } + + if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)) + { + scanner_release_next (context_p, (size_t) (next_data_p + 1 - ((const uint8_t *) info_p))); + } + parser_flush_cbc (context_p); +} /* scanner_create_variables */ + +/** + * Get location from context. + */ +void +scanner_get_location (scanner_location_t *location_p, /**< location */ + parser_context_t *context_p) /**< context */ +{ + location_p->source_p = context_p->source_p; + location_p->line = context_p->line; + location_p->column = context_p->column; +} /* scanner_get_location */ + +/** + * Set context location. + */ +void +scanner_set_location (parser_context_t *context_p, /**< context */ + scanner_location_t *location_p) /**< location */ +{ + context_p->source_p = location_p->source_p; + context_p->line = location_p->line; + context_p->column = location_p->column; +} /* scanner_set_location */ + +/** + * Get the real map_to value. + */ +uint16_t +scanner_decode_map_to (parser_scope_stack_t *stack_item_p) /**< scope stack item */ +{ + JERRY_ASSERT (stack_item_p->map_from != PARSER_SCOPE_STACK_FUNC); + + uint16_t value = (stack_item_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK); + return (value == 0) ? stack_item_p->map_from : (uint16_t) (value + (PARSER_REGISTER_START - 1)); +} /* scanner_decode_map_to */ + +/** + * Find the given literal index in the scope stack + * and save it the constant literal pool if the literal is register stored + * + * @return given literal index - if literal corresponds to this index is not register stored + * literal index on which literal index has been mapped - otherwise + */ +uint16_t +scanner_save_literal (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< literal index */ +{ + if (literal_index >= PARSER_REGISTER_START) + { + literal_index = (uint16_t) (literal_index - (PARSER_REGISTER_START - 1)); + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + do + { + /* Registers must be found in the scope stack. */ + JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p); + scope_stack_p--; + } while (scope_stack_p->map_from == PARSER_SCOPE_STACK_FUNC + || literal_index != (scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK)); + + literal_index = scope_stack_p->map_from; + PARSER_GET_LITERAL (literal_index)->status_flags |= LEXER_FLAG_USED; + } + + return literal_index; +} /* scanner_save_literal */ + +/** + * Checks whether the literal is a const in the current scope. + * + * @return true if the literal is a const, false otherwise + */ +bool +scanner_literal_is_const_reg (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< literal index */ +{ + if (literal_index < PARSER_REGISTER_START) + { + /* Re-assignment of non-register const bindings are detected elsewhere. */ + return false; + } + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + literal_index = (uint16_t) (literal_index - (PARSER_REGISTER_START - 1)); + + do + { + /* Registers must be found in the scope stack. */ + JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p); + scope_stack_p--; + } while (scope_stack_p->map_from == PARSER_SCOPE_STACK_FUNC + || literal_index != (scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK)); + + return (scope_stack_p->map_to & PARSER_SCOPE_STACK_IS_CONST_REG) != 0; +} /* scanner_literal_is_const_reg */ + +/** + * Checks whether the literal is created before. + * + * @return true if the literal is created before, false otherwise + */ +bool +scanner_literal_is_created (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< literal index */ +{ + JERRY_ASSERT (literal_index < PARSER_REGISTER_START); + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + do + { + /* These literals must be found in the scope stack. */ + JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p); + scope_stack_p--; + } while (literal_index != scope_stack_p->map_from); + + JERRY_ASSERT ((scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK) == 0); + + return (scope_stack_p->map_to & PARSER_SCOPE_STACK_IS_LOCAL_CREATED) != 0; +} /* scanner_literal_is_created */ + +/** + * Checks whether the literal exists. + * + * @return true if the literal exists, false otherwise + */ +bool +scanner_literal_exists (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< literal index */ +{ + JERRY_ASSERT (literal_index < PARSER_REGISTER_START); + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + while (scope_stack_p-- > context_p->scope_stack_p) + { + if (scope_stack_p->map_from != PARSER_SCOPE_STACK_FUNC && scanner_decode_map_to (scope_stack_p) == literal_index) + { + return true; + } + } + + return false; +} /* scanner_literal_exists */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.cpp new file mode 100644 index 00000000..c9759921 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.cpp @@ -0,0 +1,3715 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jcontext.h" +#include "js-parser-internal.h" +#include "js-scanner-internal.h" +#include "lit-char-helpers.h" + +#if JERRY_PARSER + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +/** + * Scan return types. + */ +typedef enum +{ + SCAN_NEXT_TOKEN, /**< get next token after return */ + SCAN_KEEP_TOKEN, /**< keep the current token after return */ +} scan_return_types_t; + +/** + * Checks whether token type is "of". + */ +#define SCANNER_IDENTIFIER_IS_OF() (lexer_token_is_identifier (context_p, "of", 2)) + +JERRY_STATIC_ASSERT ((SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (SCANNER_LITERAL_POOL_GENERATOR) == SCAN_STACK_COMPUTED_GENERATOR), + scanner_invalid_conversion_from_literal_pool_generator_to_computed_generator); +JERRY_STATIC_ASSERT ((SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (SCANNER_LITERAL_POOL_ASYNC) == SCAN_STACK_COMPUTED_ASYNC), + scanner_invalid_conversion_from_literal_pool_async_to_computed_async); + +JERRY_STATIC_ASSERT ((SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (SCAN_STACK_COMPUTED_GENERATOR) == SCANNER_LITERAL_POOL_GENERATOR), + scanner_invalid_conversion_from_computed_generator_to_literal_pool_generator); +JERRY_STATIC_ASSERT ((SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (SCAN_STACK_COMPUTED_ASYNC) == SCANNER_LITERAL_POOL_ASYNC), + scanner_invalid_conversion_from_computed_async_to_literal_pool_async); + +/** + * Change scanner mode from primary expression to post primary expression. + * + * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing + */ +static scan_return_types_t +scanner_primary_to_post_primary_expression (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /* scanner context */ +{ + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + + if (JERRY_UNLIKELY (context_p->stack_top_uint8 == SCAN_STACK_CLASS_FIELD_INITIALIZER + && (context_p->status_flags & PARSER_IS_STRICT))) + { + lexer_scan_identifier (context_p, (lexer_parse_options_t) ((unsigned int) LEXER_PARSE_CHECK_KEYWORDS | (unsigned int) LEXER_PARSE_NO_STRICT_IDENT_ERROR)); + + if (context_p->token.type == LEXER_LITERAL && lexer_compare_literal_to_string (context_p, "static", 6)) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + } + + return SCAN_KEEP_TOKEN; + } + + return SCAN_NEXT_TOKEN; +} /* scanner_primary_to_post_primary_expression */ + +/** + * Scan primary expression. + * + * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing + */ +static scan_return_types_t +scanner_scan_primary_expression (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /* scanner context */ + lexer_token_type_t type, /**< current token type */ + scan_stack_modes_t stack_top) /**< current stack top */ +{ + switch (type) + { + case LEXER_KEYW_NEW: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW; + + if (scanner_try_scan_new_target (context_p)) + { + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } + + break; + } + case LEXER_DIVIDE: + case LEXER_ASSIGN_DIVIDE: + { + lexer_construct_regexp_object (context_p, true); + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } + case LEXER_KEYW_FUNCTION: + { + uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION; +#if JERRY_MODULE_SYSTEM + bool is_export_default = stack_top == SCAN_STACK_EXPORT_DEFAULT; +#endif /* JERRY_MODULE_SYSTEM */ + + if (scanner_context_p->async_source_p != NULL) + { + status_flags |= SCANNER_LITERAL_POOL_ASYNC; + } + + if (lexer_consume_generator (context_p)) + { + status_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + + scanner_push_literal_pool (context_p, scanner_context_p, status_flags); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { +#if JERRY_MODULE_SYSTEM + if (is_export_default) + { + lexer_lit_location_t *location_p; + location_p = scanner_add_custom_literal (context_p, + scanner_context_p->active_literal_pool_p->prev_p, + &context_p->token.lit_location); + + scanner_detect_invalid_let (context_p, location_p); + location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET; + } +#endif /* JERRY_MODULE_SYSTEM */ + lexer_next_token (context_p); + } +#if JERRY_MODULE_SYSTEM + else if (is_export_default) + { + lexer_lit_location_t *location_p; + location_p = scanner_add_custom_literal (context_p, + scanner_context_p->active_literal_pool_p->prev_p, + &lexer_default_literal); + location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET; + } +#endif /* JERRY_MODULE_SYSTEM */ + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_EXPRESSION); + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + case LEXER_LEFT_PAREN: + { + scanner_scan_bracket (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + case LEXER_LEFT_SQUARE: + { + scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_NONE, false); + + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + case LEXER_LEFT_BRACE: + { + scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_NONE, false); + parser_stack_push_uint8 (context_p, 0); + + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; + return SCAN_KEEP_TOKEN; + } + case LEXER_HASHMARK: + { + if (!lexer_scan_private_identifier (context_p)) + { + scanner_raise_error (context_p); + } + + return SCAN_KEEP_TOKEN; + } + case LEXER_TEMPLATE_LITERAL: + { + if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_TEMPLATE_STRING); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + + /* The string is a normal string literal. */ + /* FALLTHRU */ + } + case LEXER_LITERAL: + { + const uint8_t *source_p = context_p->source_p; + + if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL && lexer_check_arrow (context_p)) + { + scanner_scan_simple_arrow (context_p, scanner_context_p, source_p); + return SCAN_KEEP_TOKEN; + } + + if (JERRY_UNLIKELY (lexer_token_is_async (context_p))) + { + scanner_context_p->async_source_p = source_p; + scanner_check_async_function (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { +#if JERRY_MODULE_SYSTEM + if (stack_top == SCAN_STACK_EXPORT_DEFAULT) + { + lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p); + location_p->type |= (SCANNER_LITERAL_IS_USED | SCANNER_LITERAL_IS_VAR); + scanner_detect_eval_call (context_p, scanner_context_p); + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } +#endif /* JERRY_MODULE_SYSTEM */ + + scanner_add_reference (context_p, scanner_context_p); + } + /* FALLTHRU */ + } + case LEXER_KEYW_THIS: + case LEXER_LIT_TRUE: + case LEXER_LIT_FALSE: + case LEXER_LIT_NULL: + { + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } + case LEXER_KEYW_SUPER: + { + scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE; + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } + case LEXER_KEYW_CLASS: + { + scanner_push_class_declaration (context_p, scanner_context_p, SCAN_STACK_CLASS_EXPRESSION); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + return SCAN_KEEP_TOKEN; + } + break; + } + case LEXER_RIGHT_SQUARE: + { + if (stack_top != SCAN_STACK_ARRAY_LITERAL) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return SCAN_KEEP_TOKEN; + } + case LEXER_THREE_DOTS: + { + /* Elision or spread arguments */ + if (stack_top != SCAN_STACK_PAREN_EXPRESSION && stack_top != SCAN_STACK_ARRAY_LITERAL) + { + scanner_raise_error (context_p); + } + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + case LEXER_COMMA: + { + if (stack_top != SCAN_STACK_ARRAY_LITERAL) + { + scanner_raise_error (context_p); + } + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (scanner_context_p->binding_type != SCANNER_BINDING_NONE) + { + scanner_context_p->mode = SCAN_MODE_BINDING; + } + + break; + } + case LEXER_KEYW_YIELD: + { + lexer_next_token (context_p); + + if (lexer_check_yield_no_arg (context_p)) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + } + + if (context_p->token.type == LEXER_MULTIPLY) + { + return SCAN_NEXT_TOKEN; + } + return SCAN_KEEP_TOKEN; + } +#if JERRY_MODULE_SYSTEM + case LEXER_KEYW_IMPORT: + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_DOT) + { + scanner_check_import_meta (context_p); + } + else if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } +#endif /* JERRY_MODULE_SYSTEM */ + case LEXER_RIGHT_PAREN: + { + if (stack_top == SCAN_STACK_PAREN_EXPRESSION) + { + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + scanner_add_async_literal (context_p, scanner_context_p); + } + + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } + /* FALLTHRU */ + } + default: + { + scanner_raise_error (context_p); + } + } + return SCAN_NEXT_TOKEN; +} /* scanner_scan_primary_expression */ + +/** + * Scan the tokens after the primary expression. + * + * @return true for break, false for fall through + */ +static bool +scanner_scan_post_primary_expression (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + lexer_token_type_t type, /**< current token type */ + scan_stack_modes_t stack_top) /**< current stack top */ +{ + switch (type) + { + case LEXER_DOT: + { + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + + if (context_p->token.type == LEXER_HASHMARK) + { + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + lexer_next_token (context_p); + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + return true; + } + case LEXER_LEFT_PAREN: + { + parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return true; + } + case LEXER_TEMPLATE_LITERAL: + { + if (JERRY_UNLIKELY (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT)) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + parser_stack_push_uint8 (context_p, SCAN_STACK_TAGGED_TEMPLATE_LITERAL); + } + return true; + } + case LEXER_LEFT_SQUARE: + { + parser_stack_push_uint8 (context_p, SCAN_STACK_PROPERTY_ACCESSOR); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return true; + } + case LEXER_INCREASE: + case LEXER_DECREASE: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + + if (context_p->token.flags & LEXER_WAS_NEWLINE) + { + return false; + } + + lexer_next_token (context_p); + type = (lexer_token_type_t) context_p->token.type; + + if (type != LEXER_QUESTION_MARK) + { + break; + } + /* FALLTHRU */ + } + case LEXER_QUESTION_MARK: + { + parser_stack_push_uint8 (context_p, SCAN_STACK_COLON_EXPRESSION); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return true; + } + default: + { + break; + } + } + + if (LEXER_IS_BINARY_OP_TOKEN (type) && (type != LEXER_KEYW_IN || !SCANNER_IS_FOR_START (stack_top))) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return true; + } + + return false; +} /* scanner_scan_post_primary_expression */ + +/** + * Scan the tokens after the primary expression. + * + * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing + */ +static scan_return_types_t +scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + lexer_token_type_t type, /**< current token type */ + scan_stack_modes_t stack_top) /**< current stack top */ +{ + if (type == LEXER_COMMA) + { + switch (stack_top) + { + case SCAN_STACK_VAR: + case SCAN_STACK_LET: + case SCAN_STACK_CONST: + case SCAN_STACK_FOR_VAR_START: + case SCAN_STACK_FOR_LET_START: + case SCAN_STACK_FOR_CONST_START: + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_COLON_EXPRESSION: + { + scanner_raise_error (context_p); + break; + } + case SCAN_STACK_BINDING_INIT: + case SCAN_STACK_BINDING_LIST_INIT: + { + break; + } + case SCAN_STACK_ARROW_ARGUMENTS: + { + lexer_next_token (context_p); + scanner_check_arrow_arg (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_ARROW_EXPRESSION: + { + break; + } + case SCAN_STACK_CLASS_FIELD_INITIALIZER: + { + scanner_raise_error (context_p); + break; + } + case SCAN_STACK_FUNCTION_PARAMETERS: + { + scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS; + parser_stack_pop_uint8 (context_p); + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_ARRAY_LITERAL: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (scanner_context_p->binding_type != SCANNER_BINDING_NONE) + { + scanner_context_p->mode = SCAN_MODE_BINDING; + } + + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_OBJECT_LITERAL: + { + scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; + return SCAN_KEEP_TOKEN; + } + default: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + } + } + + switch (stack_top) + { + case SCAN_STACK_WITH_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + parser_stack_pop_uint8 (context_p); + + uint16_t status_flags = scanner_context_p->active_literal_pool_p->status_flags; + parser_stack_push_uint8 (context_p, (status_flags & SCANNER_LITERAL_POOL_IN_WITH) ? 1 : 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_WITH_STATEMENT); + status_flags |= SCANNER_LITERAL_POOL_IN_WITH; + scanner_context_p->active_literal_pool_p->status_flags = status_flags; + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_DO_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_WHILE_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + scanner_source_start_t source_start; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t)); + + scanner_location_info_t *location_info_p; + location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p, + source_start.source_p, + sizeof (scanner_location_info_t)); + location_info_p->info.type = SCANNER_TYPE_WHILE; + + scanner_get_location (&location_info_p->location, context_p); + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_PAREN_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + scanner_add_async_literal (context_p, scanner_context_p); + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_STATEMENT_WITH_EXPR: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == SCAN_STACK_IF_STATEMENT) + { + scanner_check_function_after_if (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_BINDING_LIST_INIT: + { + parser_stack_pop_uint8 (context_p); + + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL + || context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL + || context_p->stack_top_uint8 == SCAN_STACK_LET || context_p->stack_top_uint8 == SCAN_STACK_CONST + || context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START + || context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START + || context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PARAMETERS + || context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS); + + scanner_binding_item_t *item_p = scanner_context_p->active_binding_list_p->items_p; + + while (item_p != NULL) + { + if (item_p->literal_p->type & SCANNER_LITERAL_IS_USED) + { + item_p->literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + item_p = item_p->next_p; + } + + scanner_pop_binding_list (scanner_context_p); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_BINDING_INIT: + { + scanner_binding_literal_t binding_literal; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); + + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL + || context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL + || context_p->stack_top_uint8 == SCAN_STACK_LET || context_p->stack_top_uint8 == SCAN_STACK_CONST + || context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START + || context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START + || context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PARAMETERS + || context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS); + + JERRY_ASSERT (SCANNER_NEEDS_BINDING_LIST (scanner_context_p->binding_type) + || (stack_top != SCAN_STACK_ARRAY_LITERAL && stack_top != SCAN_STACK_OBJECT_LITERAL)); + + if (binding_literal.literal_p->type & SCANNER_LITERAL_IS_USED) + { + binding_literal.literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_VAR: + case SCAN_STACK_LET: + case SCAN_STACK_CONST: + { +#if JERRY_MODULE_SYSTEM + scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT; +#endif /* JERRY_MODULE_SYSTEM */ + + parser_stack_pop_uint8 (context_p); + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_FOR_VAR_START: + case SCAN_STACK_FOR_LET_START: + case SCAN_STACK_FOR_CONST_START: + case SCAN_STACK_FOR_START: + { + if (type == LEXER_KEYW_IN || SCANNER_IDENTIFIER_IS_OF ()) + { + scanner_for_statement_t for_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t)); + + scanner_location_info_t *location_info; + location_info = (scanner_location_info_t *) scanner_insert_info (context_p, + for_statement.u.source_p, + sizeof (scanner_location_info_t)); + location_info->info.type = (type == LEXER_KEYW_IN) ? SCANNER_TYPE_FOR_IN : SCANNER_TYPE_FOR_OF; + + if (stack_top == SCAN_STACK_FOR_LET_START || stack_top == SCAN_STACK_FOR_CONST_START) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK_EARLY); + } + scanner_get_location (&location_info->location, context_p); + + parser_stack_push_uint8 (context_p, SCAN_STACK_STATEMENT_WITH_EXPR); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + + if (type != LEXER_SEMICOLON) + { + break; + } + + scanner_for_statement_t for_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, NULL, sizeof (scanner_for_statement_t)); + + if (stack_top == SCAN_STACK_FOR_LET_START || stack_top == SCAN_STACK_FOR_CONST_START) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK); + } + + for_statement.u.source_p = context_p->source_p; + parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_FOR_CONDITION); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_SEMICOLON) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + type = LEXER_SEMICOLON; + /* FALLTHRU */ + } + case SCAN_STACK_FOR_CONDITION: + { + if (type != LEXER_SEMICOLON) + { + break; + } + + scanner_for_statement_t for_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t)); + + scanner_for_info_t *for_info_p; + for_info_p = + (scanner_for_info_t *) scanner_insert_info (context_p, for_statement.u.source_p, sizeof (scanner_for_info_t)); + for_info_p->info.type = SCANNER_TYPE_FOR; + + scanner_get_location (&for_info_p->expression_location, context_p); + for_info_p->end_location.source_p = NULL; + + for_statement.u.for_info_p = for_info_p; + + parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_FOR_EXPRESSION); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + type = LEXER_RIGHT_PAREN; + /* FALLTHRU */ + } + case SCAN_STACK_FOR_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + scanner_for_statement_t for_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t)); + + scanner_get_location (&for_statement.u.for_info_p->end_location, context_p); + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_SWITCH_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + break; + } + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = context_p->source_p - 1; + + parser_stack_pop_uint8 (context_p); + + scanner_switch_statement_t switch_statement = scanner_context_p->active_switch_statement; + parser_stack_push (context_p, &switch_statement, sizeof (scanner_switch_statement_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_SWITCH_BLOCK); + + scanner_switch_info_t *switch_info_p; + switch_info_p = + (scanner_switch_info_t *) scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_switch_info_t)); + switch_info_p->info.type = SCANNER_TYPE_SWITCH; + switch_info_p->case_p = NULL; + scanner_context_p->active_switch_statement.last_case_p = &switch_info_p->case_p; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_KEYW_CASE + && context_p->token.type != LEXER_KEYW_DEFAULT) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_CASE_STATEMENT: + { + if (type != LEXER_COLON) + { + break; + } + + scanner_source_start_t source_start; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t)); + + scanner_location_info_t *location_info_p; + location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p, + source_start.source_p, + sizeof (scanner_location_info_t)); + location_info_p->info.type = SCANNER_TYPE_CASE; + + scanner_get_location (&location_info_p->location, context_p); + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_COLON_EXPRESSION: + { + if (type != LEXER_COLON) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + parser_stack_pop_uint8 (context_p); + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_ARRAY_LITERAL: + case SCAN_STACK_OBJECT_LITERAL: + { + if ((stack_top == SCAN_STACK_ARRAY_LITERAL && type != LEXER_RIGHT_SQUARE) + || (stack_top == SCAN_STACK_OBJECT_LITERAL && type != LEXER_RIGHT_BRACE)) + { + break; + } + + scanner_source_start_t source_start; + uint8_t binding_type = scanner_context_p->binding_type; + uint8_t object_literal_flags = 0; + + parser_stack_pop_uint8 (context_p); + + if (stack_top == SCAN_STACK_OBJECT_LITERAL) + { + object_literal_flags = context_p->stack_top_uint8; + parser_stack_pop_uint8 (context_p); + } + + scanner_context_p->binding_type = context_p->stack_top_uint8; + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t)); + + lexer_next_token (context_p); + + stack_top = (scan_stack_modes_t) context_p->stack_top_uint8; + + if (binding_type == SCANNER_BINDING_CATCH && stack_top == SCAN_STACK_CATCH_STATEMENT) + { + scanner_pop_binding_list (scanner_context_p); + + if (object_literal_flags != 0) + { + scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_LITERAL_FLAGS; + info_p->u8_arg = object_literal_flags; + } + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + + if (stack_top == SCAN_STACK_FOR_START_PATTERN) + { + JERRY_ASSERT (binding_type == SCANNER_BINDING_NONE); + + parser_stack_change_last_uint8 (context_p, SCAN_STACK_FOR_START); + + if (context_p->token.type == LEXER_KEYW_IN || SCANNER_IDENTIFIER_IS_OF ()) + { + scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_LITERAL_FLAGS; + info_p->u8_arg = object_literal_flags | SCANNER_LITERAL_DESTRUCTURING_FOR; + return SCAN_KEEP_TOKEN; + } + } + + if (context_p->token.type != LEXER_ASSIGN) + { + if (SCANNER_NEEDS_BINDING_LIST (binding_type)) + { + scanner_pop_binding_list (scanner_context_p); + } + + if ((stack_top == SCAN_STACK_ARRAY_LITERAL || stack_top == SCAN_STACK_OBJECT_LITERAL) + && (binding_type == SCANNER_BINDING_NONE || binding_type == SCANNER_BINDING_ARROW_ARG) + && context_p->token.type != LEXER_EOS && context_p->token.type != LEXER_COMMA + && context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_RIGHT_SQUARE) + { + object_literal_flags |= SCANNER_LITERAL_NO_DESTRUCTURING; + } + + if (object_literal_flags != 0) + { + scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_LITERAL_FLAGS; + info_p->u8_arg = object_literal_flags; + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + scanner_location_info_t *location_info_p; + location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p, + source_start.source_p, + sizeof (scanner_location_info_t)); + location_info_p->info.type = SCANNER_TYPE_INITIALIZER; + location_info_p->info.u8_arg = object_literal_flags; + scanner_get_location (&location_info_p->location, context_p); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (SCANNER_NEEDS_BINDING_LIST (binding_type)) + { + scanner_binding_item_t *item_p = scanner_context_p->active_binding_list_p->items_p; + + while (item_p != NULL) + { + item_p->literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_USED; + item_p = item_p->next_p; + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_LIST_INIT); + } + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_PROPERTY_ACCESSOR: + { + if (type != LEXER_RIGHT_SQUARE) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + parser_stack_pop_uint8 (context_p); + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_COMPUTED_PROPERTY: + { + if (type != LEXER_RIGHT_SQUARE) + { + break; + } + + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + + parser_stack_pop_uint8 (context_p); + stack_top = (scan_stack_modes_t) context_p->stack_top_uint8; + + if (stack_top == SCAN_STACK_FUNCTION_PROPERTY) + { + scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION); + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + + if (stack_top == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR || stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR) + { + JERRY_ASSERT (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CLASS_NAME); + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION); + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.type == LEXER_ASSIGN) + { + scanner_push_class_field_initializer (context_p, scanner_context_p); + return SCAN_NEXT_TOKEN; + } + + scanner_context_p->mode = + (context_p->token.type != LEXER_SEMICOLON ? SCAN_MODE_CLASS_BODY_NO_SCAN : SCAN_MODE_CLASS_BODY); + return SCAN_KEEP_TOKEN; + } + + JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL); + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION); + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.type != LEXER_COLON) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (scanner_context_p->binding_type != SCANNER_BINDING_NONE) + { + scanner_context_p->mode = SCAN_MODE_BINDING; + } + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_COMPUTED_GENERATOR: + case SCAN_STACK_COMPUTED_ASYNC: + case SCAN_STACK_COMPUTED_ASYNC_GENERATOR: + { + if (type != LEXER_RIGHT_SQUARE) + { + break; + } + + lexer_next_token (context_p); + parser_stack_pop_uint8 (context_p); + + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL + || context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PROPERTY); + + uint16_t status_flags = (uint16_t) (SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_GENERATOR + | SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (stack_top)); + + scanner_push_literal_pool (context_p, scanner_context_p, status_flags); + + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_TEMPLATE_STRING: + case SCAN_STACK_TAGGED_TEMPLATE_LITERAL: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + context_p->source_p--; + context_p->column--; + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + + if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + } + else + { + parser_stack_pop_uint8 (context_p); + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + } + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_ARROW_ARGUMENTS: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + scanner_check_arrow (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_ARROW_EXPRESSION: + { + scanner_pop_literal_pool (context_p, scanner_context_p); + parser_stack_pop_uint8 (context_p); + lexer_update_await_yield (context_p, context_p->status_flags); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_CLASS_EXTENDS: + { + if (type != LEXER_LEFT_BRACE) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_CLASS_BODY; + parser_stack_pop_uint8 (context_p); + + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_CLASS_FIELD_INITIALIZER: + { + scanner_source_start_t source_start; + const uint8_t *source_p = NULL; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t)); + scanner_pop_literal_pool (context_p, scanner_context_p); + scanner_context_p->mode = SCAN_MODE_CLASS_BODY_NO_SCAN; + + switch (type) + { + case LEXER_SEMICOLON: + { + source_p = context_p->source_p - 1; + scanner_context_p->mode = SCAN_MODE_CLASS_BODY; + break; + } + case LEXER_RIGHT_BRACE: + { + source_p = context_p->source_p - 1; + break; + } + default: + { + if (!(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + break; + } + + if (type == LEXER_LEFT_SQUARE) + { + source_p = context_p->source_p - 1; + break; + } + + if (type == LEXER_LITERAL) + { + if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL + || context_p->token.lit_location.type == LEXER_NUMBER_LITERAL) + { + source_p = context_p->token.lit_location.char_p; + } + else if (context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + source_p = context_p->token.lit_location.char_p - 1; + } + break; + } + + if (type == context_p->token.keyword_type && type != LEXER_EOS) + { + /* Convert keyword to literal. */ + source_p = context_p->token.lit_location.char_p; + context_p->token.type = LEXER_LITERAL; + } + break; + } + } + + if (JERRY_UNLIKELY (source_p == NULL)) + { + scanner_raise_error (context_p); + } + + scanner_location_info_t *location_info_p; + location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p, + source_start.source_p, + sizeof (scanner_location_info_t)); + location_info_p->info.type = SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END; + location_info_p->location.source_p = source_p; + location_info_p->location.line = context_p->token.line; + location_info_p->location.column = context_p->token.column; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_FUNCTION_PARAMETERS: + { + parser_stack_pop_uint8 (context_p); + + if (type != LEXER_RIGHT_PAREN && (type != LEXER_EOS || context_p->stack_top_uint8 != SCAN_STACK_SCRIPT_FUNCTION)) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + default: + { + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + return SCAN_KEEP_TOKEN; + } + } + + scanner_raise_error (context_p); + return SCAN_NEXT_TOKEN; +} /* scanner_scan_primary_expression_end */ + +/** + * Scan statements. + * + * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing + */ +static scan_return_types_t +scanner_scan_statement (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + lexer_token_type_t type, /**< current token type */ + scan_stack_modes_t stack_top) /**< current stack top */ +{ + switch (type) + { + case LEXER_SEMICOLON: + { + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + return SCAN_KEEP_TOKEN; + } + case LEXER_LEFT_BRACE: + { + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = context_p->source_p; + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_DO: + { + scanner_context_p->mode = SCAN_MODE_STATEMENT; + parser_stack_push_uint8 (context_p, SCAN_STACK_DO_STATEMENT); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_TRY: + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = context_p->source_p; + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + parser_stack_push_uint8 (context_p, SCAN_STACK_TRY_STATEMENT); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_DEBUGGER: + { + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_IF: + case LEXER_KEYW_WITH: + case LEXER_KEYW_SWITCH: + { + lexer_next_token (context_p); + if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + uint8_t mode = SCAN_STACK_STATEMENT_WITH_EXPR; + + if (type == LEXER_KEYW_IF) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_IF_STATEMENT); + } + else if (type == LEXER_KEYW_WITH) + { + mode = SCAN_STACK_WITH_EXPRESSION; + } + else if (type == LEXER_KEYW_SWITCH) + { + mode = SCAN_STACK_SWITCH_EXPRESSION; + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + parser_stack_push_uint8 (context_p, mode); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_WHILE: + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + scanner_source_start_t source_start; + source_start.source_p = context_p->source_p; + + parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_WHILE_EXPRESSION); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_FOR: + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_KEYW_AWAIT) + { + lexer_next_token (context_p); + } + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + scanner_for_statement_t for_statement; + for_statement.u.source_p = context_p->source_p; + uint8_t stack_mode = SCAN_STACK_FOR_START; + scan_return_types_t return_type = SCAN_KEEP_TOKEN; + + lexer_next_token (context_p); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + const uint8_t *source_p = context_p->source_p; + + switch (context_p->token.type) + { + case LEXER_SEMICOLON: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + break; + } + case LEXER_KEYW_VAR: + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + stack_mode = SCAN_STACK_FOR_VAR_START; + return_type = SCAN_NEXT_TOKEN; + break; + } + case LEXER_LEFT_BRACE: + case LEXER_LEFT_SQUARE: + { + stack_mode = SCAN_STACK_FOR_START_PATTERN; + break; + } + case LEXER_LITERAL: + { + if (!lexer_token_is_let (context_p)) + { + break; + } + + parser_line_counter_t line = context_p->line; + parser_line_counter_t column = context_p->column; + + if (lexer_check_arrow (context_p)) + { + context_p->source_p = source_p; + context_p->line = line; + context_p->column = column; + context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES; + break; + } + + lexer_next_token (context_p); + + type = (lexer_token_type_t) context_p->token.type; + + if (type != LEXER_LEFT_SQUARE && type != LEXER_LEFT_BRACE + && (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)) + { + scanner_info_t *info_p = scanner_insert_info (context_p, source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_LET_EXPRESSION; + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + break; + } + + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + /* FALLTHRU */ + } + case LEXER_KEYW_LET: + case LEXER_KEYW_CONST: + { + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = source_p; + + if (scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION) + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + return_type = SCAN_NEXT_TOKEN; + } + + stack_mode = + ((context_p->token.type == LEXER_KEYW_CONST) ? SCAN_STACK_FOR_CONST_START : SCAN_STACK_FOR_LET_START); + break; + } + } + + parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t)); + parser_stack_push_uint8 (context_p, stack_mode); + return return_type; + } + case LEXER_KEYW_VAR: + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + parser_stack_push_uint8 (context_p, SCAN_STACK_VAR); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_LET: + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + parser_stack_push_uint8 (context_p, SCAN_STACK_LET); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_CONST: + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + parser_stack_push_uint8 (context_p, SCAN_STACK_CONST); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_THROW: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_RETURN: + { + lexer_next_token (context_p); + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type != LEXER_SEMICOLON + && context_p->token.type != LEXER_EOS && context_p->token.type != LEXER_RIGHT_BRACE) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + return SCAN_KEEP_TOKEN; + } + case LEXER_KEYW_BREAK: + case LEXER_KEYW_CONTINUE: + { + lexer_next_token (context_p); + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + return SCAN_NEXT_TOKEN; + } + return SCAN_KEEP_TOKEN; + } + case LEXER_KEYW_CASE: + case LEXER_KEYW_DEFAULT: + { + if (stack_top != SCAN_STACK_SWITCH_BLOCK) + { + scanner_raise_error (context_p); + } + + scanner_case_info_t *case_info_p; + case_info_p = (scanner_case_info_t *) scanner_malloc (context_p, sizeof (scanner_case_info_t)); + + *(scanner_context_p->active_switch_statement.last_case_p) = case_info_p; + scanner_context_p->active_switch_statement.last_case_p = &case_info_p->next_p; + + case_info_p->next_p = NULL; + scanner_get_location (&case_info_p->location, context_p); + + if (type == LEXER_KEYW_DEFAULT) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_COLON) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + + scanner_source_start_t source_start; + source_start.source_p = context_p->source_p; + + parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_CASE_STATEMENT); + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_FUNCTION: + { + uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_FUNCTION_STATEMENT; + + if (scanner_context_p->async_source_p != NULL) + { + scanner_context_p->status_flags |= SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION; + status_flags |= SCANNER_LITERAL_POOL_ASYNC; + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_MULTIPLY) + { + status_flags |= SCANNER_LITERAL_POOL_GENERATOR; + lexer_next_token (context_p); + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p); + + const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LOCAL); + + if ((literal_p->type & SCANNER_LITERAL_IS_LOCAL) + && (literal_p->type & mask) != (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG) + && (literal_p->type & mask) != SCANNER_LITERAL_IS_LOCAL_FUNC) + { + scanner_raise_redeclaration_error (context_p); + } + + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + + if (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION) + && (literal_p->type & (SCANNER_LITERAL_IS_VAR))) + { + scanner_raise_redeclaration_error (context_p); + } + + literal_p->type |= SCANNER_LITERAL_IS_LOCAL_FUNC; + + scanner_context_p->status_flags &= (uint16_t) ~SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION; + + scanner_push_literal_pool (context_p, scanner_context_p, status_flags); + + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_CLASS: + { + lexer_lit_location_t *literal_p; + literal_p = scanner_push_class_declaration (context_p, scanner_context_p, SCAN_STACK_CLASS_STATEMENT); + + if (literal_p == NULL) + { + scanner_raise_error (context_p); + } + + scanner_detect_invalid_let (context_p, literal_p); + literal_p->type |= SCANNER_LITERAL_IS_LET; + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + +#if JERRY_MODULE_SYSTEM + if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT) + { + literal_p->type |= SCANNER_LITERAL_NO_REG; + scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT; + } +#endif /* JERRY_MODULE_SYSTEM */ + + return SCAN_NEXT_TOKEN; + } +#if JERRY_MODULE_SYSTEM + case LEXER_KEYW_IMPORT: + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_DOT) + { + scanner_check_import_meta (context_p); + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + if (stack_top != SCAN_STACK_SCRIPT) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + + if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + return SCAN_NEXT_TOKEN; + } + + bool parse_imports = true; + + if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p); + + scanner_detect_invalid_let (context_p, literal_p); + literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG; + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + } + else + { + parse_imports = false; + } + } + + if (parse_imports) + { + if (context_p->token.type == LEXER_MULTIPLY) + { + lexer_next_token (context_p); + if (!lexer_token_is_identifier (context_p, "as", 2)) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p); + + scanner_detect_invalid_let (context_p, literal_p); + literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG; + + lexer_next_token (context_p); + } + else if (context_p->token.type == LEXER_LEFT_BRACE) + { + lexer_next_token (context_p); + + while (context_p->token.type != LEXER_RIGHT_BRACE) + { + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + const uint8_t *source_p = context_p->source_p; + + if (lexer_check_next_character (context_p, LIT_CHAR_LOWERCASE_A)) + { + lexer_next_token (context_p); + + if (!lexer_token_is_identifier (context_p, "as", 2)) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + source_p = context_p->source_p; + } + + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p); + + if (literal_p->type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_LOCAL)) + { + context_p->source_p = source_p; + scanner_raise_redeclaration_error (context_p); + } + + if (literal_p->type & SCANNER_LITERAL_IS_FUNC) + { + literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC; + } + + literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + if (context_p->token.type != LEXER_COMMA) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + } + } + + lexer_next_token (context_p); + } + else + { + scanner_raise_error (context_p); + } + } + + if (!lexer_token_is_identifier (context_p, "from", 4)) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type != LEXER_STRING_LITERAL) + { + scanner_raise_error (context_p); + } + + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_EXPORT: + { + if (stack_top != SCAN_STACK_SCRIPT) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_KEYW_DEFAULT) + { + lexer_next_token (context_p); + parser_stack_push_uint8 (context_p, SCAN_STACK_EXPORT_DEFAULT); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + + if (context_p->token.type == LEXER_MULTIPLY) + { + lexer_next_token (context_p); + + if (lexer_token_is_identifier (context_p, "as", 2)) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + } + + if (!lexer_token_is_identifier (context_p, "from", 4)) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + scanner_raise_error (context_p); + } + + return SCAN_NEXT_TOKEN; + } + + scanner_source_start_t source_start; + source_start.source_p = context_p->source_p; + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + lexer_next_token (context_p); + + while (context_p->token.type != LEXER_RIGHT_BRACE) + { + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (lexer_token_is_identifier (context_p, "as", 2)) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + } + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + if (context_p->token.type != LEXER_COMMA) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + } + } + + lexer_next_token (context_p); + + if (!lexer_token_is_identifier (context_p, "from", 4)) + { + return SCAN_KEEP_TOKEN; + } + + scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_EXPORT_MODULE_SPECIFIER; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + scanner_raise_error (context_p); + } + + return SCAN_NEXT_TOKEN; + } + + switch (context_p->token.type) + { + case LEXER_KEYW_CLASS: + case LEXER_KEYW_LET: + case LEXER_KEYW_CONST: + case LEXER_KEYW_VAR: + { + scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_IN_EXPORT; + break; + } + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_KEEP_TOKEN; + } +#endif /* JERRY_MODULE_SYSTEM */ + default: + { + break; + } + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + if (JERRY_UNLIKELY (lexer_check_next_character (context_p, LIT_CHAR_COLON))) + { + lexer_consume_next_character (context_p); + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_NEXT_TOKEN; + } + + JERRY_ASSERT (context_p->token.flags & LEXER_NO_SKIP_SPACES); + + /* The colon needs to be checked first because the parser also checks + * it first, and this check skips the spaces which affects source_p. */ + if (JERRY_UNLIKELY (lexer_check_arrow (context_p))) + { + scanner_scan_simple_arrow (context_p, scanner_context_p, context_p->source_p); + return SCAN_KEEP_TOKEN; + } + + if (JERRY_UNLIKELY (lexer_token_is_let (context_p))) + { + lexer_lit_location_t let_literal = context_p->token.lit_location; + const uint8_t *source_p = context_p->source_p; + + lexer_next_token (context_p); + + type = (lexer_token_type_t) context_p->token.type; + + if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE + || (type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)) + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + parser_stack_push_uint8 (context_p, SCAN_STACK_LET); + return SCAN_KEEP_TOKEN; + } + + scanner_info_t *info_p = scanner_insert_info (context_p, source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_LET_EXPRESSION; + + lexer_lit_location_t *lit_location_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &let_literal); + lit_location_p->type |= SCANNER_LITERAL_IS_USED; + + if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + lit_location_p->type |= SCANNER_LITERAL_NO_REG; + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + if (JERRY_UNLIKELY (lexer_token_is_async (context_p))) + { + scanner_context_p->async_source_p = context_p->source_p; + + if (scanner_check_async_function (context_p, scanner_context_p)) + { + scanner_context_p->mode = SCAN_MODE_STATEMENT; + } + return SCAN_KEEP_TOKEN; + } + + scanner_add_reference (context_p, scanner_context_p); + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + + return SCAN_KEEP_TOKEN; +} /* scanner_scan_statement */ + +/** + * Scan statement terminator. + * + * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing + */ +static scan_return_types_t +scanner_scan_statement_end (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + lexer_token_type_t type) /**< current token type */ +{ + bool terminator_found = false; + + if (type == LEXER_SEMICOLON) + { + lexer_next_token (context_p); + terminator_found = true; + } + + while (true) + { + type = (lexer_token_type_t) context_p->token.type; + + switch (context_p->stack_top_uint8) + { + case SCAN_STACK_SCRIPT: + case SCAN_STACK_SCRIPT_FUNCTION: + { + if (type == LEXER_EOS) + { + return SCAN_NEXT_TOKEN; + } + break; + } + case SCAN_STACK_BLOCK_STATEMENT: + case SCAN_STACK_CLASS_STATEMENT: + case SCAN_STACK_FUNCTION_STATEMENT: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + if (context_p->stack_top_uint8 != SCAN_STACK_CLASS_STATEMENT) + { + scanner_pop_literal_pool (context_p, scanner_context_p); + } + + terminator_found = true; + parser_stack_pop_uint8 (context_p); +#if JERRY_MODULE_SYSTEM + scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT; +#endif /* JERRY_MODULE_SYSTEM */ + lexer_next_token (context_p); + continue; + } + case SCAN_STACK_FUNCTION_EXPRESSION: + case SCAN_STACK_FUNCTION_ARROW: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + + if (context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_ARROW) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + } + + scanner_pop_literal_pool (context_p, scanner_context_p); + parser_stack_pop_uint8 (context_p); + +#if JERRY_MODULE_SYSTEM + if (context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT) + { + terminator_found = true; + parser_stack_pop_uint8 (context_p); + lexer_next_token (context_p); + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_FUNCTION_PROPERTY: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + bool has_super_reference = + (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE) != 0; + + scanner_pop_literal_pool (context_p, scanner_context_p); + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR + || context_p->stack_top_uint8 == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR) + { + scanner_context_p->mode = SCAN_MODE_CLASS_BODY; + return SCAN_KEEP_TOKEN; + } + + if (has_super_reference && context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL) + { + *parser_stack_get_prev_uint8 (context_p) |= SCANNER_LITERAL_OBJECT_HAS_SUPER; + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.type != LEXER_COMMA) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_SWITCH_BLOCK: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + scanner_switch_statement_t switch_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &switch_statement, sizeof (scanner_switch_statement_t)); + + scanner_context_p->active_switch_statement = switch_statement; + + scanner_pop_literal_pool (context_p, scanner_context_p); + + terminator_found = true; + lexer_next_token (context_p); + continue; + } + case SCAN_STACK_IF_STATEMENT: + { + parser_stack_pop_uint8 (context_p); + + if (type == LEXER_KEYW_ELSE && (terminator_found || (context_p->token.flags & LEXER_WAS_NEWLINE))) + { + scanner_check_function_after_if (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + + continue; + } + case SCAN_STACK_WITH_STATEMENT: + { + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + + JERRY_ASSERT (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH); + + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == 0) + { + literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_WITH; + } + + parser_stack_pop_uint8 (context_p); + continue; + } + case SCAN_STACK_DO_STATEMENT: + { + parser_stack_pop_uint8 (context_p); + + if (type != LEXER_KEYW_WHILE || (!terminator_found && !(context_p->token.flags & LEXER_WAS_NEWLINE))) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_DO_EXPRESSION); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_DO_EXPRESSION: + { + parser_stack_pop_uint8 (context_p); + terminator_found = true; + continue; + } + case SCAN_STACK_CLASS_STATIC_BLOCK: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + scanner_pop_literal_pool (context_p, scanner_context_p); + scanner_source_start_t start_range; + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &start_range, sizeof (scanner_source_start_t)); + + scanner_context_p->mode = SCAN_MODE_CLASS_BODY_NO_SCAN; + + scanner_location_info_t *location_info_p; + location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p, + start_range.source_p, + sizeof (scanner_location_info_t)); + + location_info_p->info.type = SCANNER_TYPE_CLASS_STATIC_BLOCK_END; + location_info_p->location.source_p = context_p->source_p; + location_info_p->location.line = context_p->token.line; + location_info_p->location.column = context_p->token.column; + + lexer_scan_identifier (context_p, (lexer_parse_options_t) ((unsigned int) LEXER_PARSE_CHECK_KEYWORDS | (unsigned int) LEXER_PARSE_NO_STRICT_IDENT_ERROR)); + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_PRIVATE_BLOCK_EARLY: + { + parser_list_iterator_t literal_iterator; + lexer_lit_location_t *literal_p; + + parser_list_iterator_init (&scanner_context_p->active_literal_pool_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if ((literal_p->type & (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST)) + && (literal_p->type & SCANNER_LITERAL_IS_USED)) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + } + /* FALLTHRU */ + } + case SCAN_STACK_PRIVATE_BLOCK: + { + parser_stack_pop_uint8 (context_p); + scanner_pop_literal_pool (context_p, scanner_context_p); + continue; + } +#if JERRY_MODULE_SYSTEM + case SCAN_STACK_EXPORT_DEFAULT: + { + parser_stack_pop_uint8 (context_p); + lexer_lit_location_t *location_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &lexer_default_literal); + location_p->type |= SCANNER_LITERAL_IS_VAR; + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + default: + { + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_TRY_STATEMENT + || context_p->stack_top_uint8 == SCAN_STACK_CATCH_STATEMENT); + + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + uint8_t stack_top = context_p->stack_top_uint8; + parser_stack_pop_uint8 (context_p); + lexer_next_token (context_p); + + scanner_pop_literal_pool (context_p, scanner_context_p); + + /* A finally statement is optional after a try or catch statement. */ + if (context_p->token.type == LEXER_KEYW_FINALLY) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = context_p->source_p; + + parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT); + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + + if (stack_top == SCAN_STACK_CATCH_STATEMENT) + { + terminator_found = true; + continue; + } + + /* A catch statement must be present after a try statement unless a finally is provided. */ + if (context_p->token.type != LEXER_KEYW_CATCH) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = context_p->source_p; + parser_stack_push_uint8 (context_p, SCAN_STACK_CATCH_STATEMENT); + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE) + { + scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_CATCH, false); + + if (context_p->token.type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + scanner_context_p->mode = SCAN_MODE_BINDING; + return SCAN_NEXT_TOKEN; + } + + parser_stack_push_uint8 (context_p, 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_lit_location_t *lit_location_p = scanner_add_literal (context_p, scanner_context_p); + lit_location_p->type |= SCANNER_LITERAL_IS_LOCAL; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + } + + if (!terminator_found && !(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_KEEP_TOKEN; + } +} /* scanner_scan_statement_end */ + +/** + * Scan the whole source code. + */ +void JERRY_ATTR_NOINLINE +scanner_scan_all (parser_context_t *context_p) /**< context */ +{ + scanner_context_t scanner_context; + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Scanning start ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + scanner_context.context_status_flags = context_p->status_flags; + scanner_context.status_flags = SCANNER_CONTEXT_NO_FLAGS; + scanner_context.binding_type = SCANNER_BINDING_NONE; + scanner_context.active_binding_list_p = NULL; + scanner_context.active_literal_pool_p = NULL; + scanner_context.active_switch_statement.last_case_p = NULL; + scanner_context.end_arguments_p = NULL; + scanner_context.async_source_p = NULL; + + /* This assignment must be here because of Apple compilers. */ + context_p->u.scanner_context_p = &scanner_context; + context_p->global_status_flags |= ECMA_PARSE_INTERNAL_PRE_SCANNING; + + parser_stack_init (context_p); + + PARSER_TRY (context_p->try_buffer) + { + if (context_p->arguments_start_p == NULL) + { + context_p->source_p = context_p->source_start_p; + context_p->source_end_p = context_p->source_start_p + context_p->source_size; + + uint16_t status_flags = + (SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_NO_ARGUMENTS | SCANNER_LITERAL_POOL_CAN_EVAL); + + if (context_p->status_flags & PARSER_IS_STRICT) + { + status_flags |= SCANNER_LITERAL_POOL_IS_STRICT; + } + + scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, &scanner_context, status_flags); + literal_pool_p->source_p = context_p->source_start_p; + + parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT); + + lexer_next_token (context_p); + scanner_check_directives (context_p, &scanner_context); + } + else + { + context_p->source_p = context_p->arguments_start_p; + context_p->source_end_p = context_p->arguments_start_p + context_p->arguments_size; + + uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION; + + if (context_p->status_flags & PARSER_IS_STRICT) + { + status_flags |= SCANNER_LITERAL_POOL_IS_STRICT; + } + + if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) + { + status_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) + { + status_flags |= SCANNER_LITERAL_POOL_ASYNC; + } + + scanner_push_literal_pool (context_p, &scanner_context, status_flags); + scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; + parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT_FUNCTION); + + /* Faking the first token. */ + context_p->token.type = LEXER_LEFT_PAREN; + } + + while (true) + { + lexer_token_type_t type = (lexer_token_type_t) context_p->token.type; + scan_stack_modes_t stack_top = (scan_stack_modes_t) context_p->stack_top_uint8; + + switch (scanner_context.mode) + { + case SCAN_MODE_PRIMARY_EXPRESSION: + { + if (type == LEXER_ADD || type == LEXER_SUBTRACT || LEXER_IS_UNARY_OP_TOKEN (type)) + { + break; + } + /* FALLTHRU */ + } + case SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW: + { + if (scanner_scan_primary_expression (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN) + { + continue; + } + break; + } + case SCAN_MODE_CLASS_DECLARATION: + { + if (context_p->token.type == LEXER_KEYW_EXTENDS) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_EXTENDS); + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + else if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_context.mode = SCAN_MODE_CLASS_BODY; + /* FALLTHRU */ + } + case SCAN_MODE_CLASS_BODY: + { + lexer_skip_empty_statements (context_p); + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + /* FALLTHRU */ + } + case SCAN_MODE_CLASS_BODY_NO_SCAN: + { + JERRY_ASSERT (stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR + || stack_top == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR); + JERRY_ASSERT (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CLASS_NAME); + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + parser_stack_pop_uint8 (context_p); + + scanner_class_info_t *private_members_p; + parser_stack_pop (context_p, &private_members_p, sizeof (scanner_class_info_t *)); + + private_members_p->info.u8_arg |= SCANNER_SUCCESSFUL_CLASS_SCAN; + + scanner_pop_literal_pool (context_p, &scanner_context); + + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_CLASS_STATEMENT + || context_p->stack_top_uint8 == SCAN_STACK_CLASS_EXPRESSION); + + if (context_p->stack_top_uint8 == SCAN_STACK_CLASS_STATEMENT) + { + /* The token is kept to disallow consuming a semicolon after it. */ + scanner_context.mode = SCAN_MODE_STATEMENT_END; + continue; + } + + scanner_context.mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + parser_stack_pop_uint8 (context_p); + +#if JERRY_MODULE_SYSTEM + if (context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT) + { + /* The token is kept to disallow consuming a semicolon after it. */ + parser_stack_change_last_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT); + scanner_context.mode = SCAN_MODE_STATEMENT_END; + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + break; + } + + bool is_private = false; + scanner_private_field_flags_t private_field_flags = SCANNER_PRIVATE_FIELD_PROPERTY; + + if (context_p->token.type == LEXER_HASHMARK) + { + is_private = true; + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + lexer_next_token (context_p); + } + + bool identifier_found = false; + + if (context_p->token.type == LEXER_LITERAL && LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type) + && lexer_compare_literal_to_string (context_p, "constructor", 11) + && stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR) + { + parser_stack_pop_uint8 (context_p); + scanner_class_info_t *private_members_p; + parser_stack_pop (context_p, &private_members_p, sizeof (scanner_class_info_t *)); + private_members_p->info.u8_arg = SCANNER_CONSTRUCTOR_EXPLICIT; + parser_stack_push (context_p, &private_members_p, sizeof (scanner_class_info_t *)); + parser_stack_push_uint8 (context_p, SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR); + } + else if (lexer_token_is_identifier (context_p, "static", 6)) + { + scanner_source_start_t static_start; + static_start.source_p = context_p->source_p - 1; + + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + identifier_found = true; + private_field_flags = (scanner_private_field_flags_t) ((unsigned int) private_field_flags | (unsigned int) SCANNER_PRIVATE_FIELD_STATIC); + + if (!is_private && context_p->token.type == LEXER_LEFT_BRACE) + { + parser_stack_push (context_p, &static_start, sizeof (scanner_source_start_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATIC_BLOCK); + + scanner_literal_pool_t *literal_pool_p = + scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION); + literal_pool_p->source_p = context_p->source_p - 1; + + lexer_next_token (context_p); + + scanner_context.mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + + continue; + } + } + + scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; + + uint16_t literal_pool_flags = SCANNER_LITERAL_POOL_FUNCTION; + + private_field_flags = ((bool)private_field_flags || lexer_token_is_identifier (context_p, "get", 3) ? SCANNER_PRIVATE_FIELD_GETTER : (scanner_private_field_flags_t) 0); + private_field_flags = ((bool)private_field_flags || lexer_token_is_identifier (context_p, "set", 3) ? SCANNER_PRIVATE_FIELD_SETTER : (scanner_private_field_flags_t) 0); + + if (private_field_flags & SCANNER_PRIVATE_FIELD_GETTER_SETTER) + { + private_field_flags = (scanner_private_field_flags_t) ((uint32_t) private_field_flags & ~(uint32_t) SCANNER_PRIVATE_FIELD_PROPERTY); + + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + identifier_found = true; + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + if (is_private) + { + private_field_flags = (scanner_private_field_flags_t) ((int) private_field_flags | (int) SCANNER_PRIVATE_FIELD_METHOD); + scanner_add_private_identifier (context_p, private_field_flags); + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION); + continue; + } + } + else if (lexer_token_is_identifier (context_p, "async", 5)) + { + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + identifier_found = true; + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + if (context_p->token.type == LEXER_LEFT_PAREN) + { + if (is_private) + { + private_field_flags = (scanner_private_field_flags_t) ((int) private_field_flags | (int) SCANNER_PRIVATE_FIELD_METHOD); + scanner_add_private_identifier (context_p, private_field_flags); + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION); + continue; + } + + literal_pool_flags |= SCANNER_LITERAL_POOL_ASYNC; + + if (context_p->token.type == LEXER_MULTIPLY) + { + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + } + } + else if (context_p->token.type == LEXER_MULTIPLY) + { + if (is_private) + { + scanner_raise_error (context_p); + } + + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + + if (context_p->token.type == LEXER_LEFT_SQUARE) + { + if (is_private) + { + scanner_raise_error (context_p); + } + + if (literal_pool_flags != SCANNER_LITERAL_POOL_FUNCTION) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + } + + parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags)); + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + + if (context_p->token.type == LEXER_HASHMARK) + { + if (is_private) + { + scanner_raise_error (context_p); + } + + is_private = true; + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + lexer_next_token (context_p); + } + + if (is_private) + { + if (lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + private_field_flags = (scanner_private_field_flags_t) ((int) private_field_flags | (int) SCANNER_PRIVATE_FIELD_METHOD); + } + + scanner_add_private_identifier (context_p, private_field_flags); + } + + if (context_p->token.type == LEXER_LITERAL) + { + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + identifier_found = true; + } + + if (!identifier_found) + { + scanner_raise_error (context_p); + } + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + if (literal_pool_flags & SCANNER_LITERAL_POOL_GENERATOR) + { + context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION; + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_push_literal_pool (context_p, &scanner_context, literal_pool_flags); + continue; + } + + if (literal_pool_flags & SCANNER_LITERAL_POOL_GENERATOR) + { + scanner_raise_error (context_p); + } + + if (context_p->token.type == LEXER_ASSIGN) + { + scanner_push_class_field_initializer (context_p, &scanner_context); + break; + } + + if (context_p->token.type == LEXER_SEMICOLON) + { + scanner_context.mode = SCAN_MODE_CLASS_BODY; + continue; + } + + if (context_p->token.type != LEXER_RIGHT_BRACE && !(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + scanner_raise_error (context_p); + } + + scanner_context.mode = SCAN_MODE_CLASS_BODY_NO_SCAN; + continue; + } + case SCAN_MODE_POST_PRIMARY_EXPRESSION: + { + if (scanner_scan_post_primary_expression (context_p, &scanner_context, type, stack_top)) + { + break; + } + type = (lexer_token_type_t) context_p->token.type; + /* FALLTHRU */ + } + case SCAN_MODE_PRIMARY_EXPRESSION_END: + { + if (scanner_scan_primary_expression_end (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN) + { + continue; + } + break; + } + case SCAN_MODE_STATEMENT_OR_TERMINATOR: + { + if (type == LEXER_RIGHT_BRACE || type == LEXER_EOS) + { + scanner_context.mode = SCAN_MODE_STATEMENT_END; + continue; + } + /* FALLTHRU */ + } + case SCAN_MODE_STATEMENT: + { + if (scanner_scan_statement (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN) + { + continue; + } + break; + } + case SCAN_MODE_STATEMENT_END: + { + if (scanner_scan_statement_end (context_p, &scanner_context, type) != SCAN_NEXT_TOKEN) + { + continue; + } + + if (context_p->token.type == LEXER_EOS) + { + goto scan_completed; + } + + break; + } + case SCAN_MODE_VAR_STATEMENT: + { + if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE) + { + uint8_t binding_type = SCANNER_BINDING_VAR; + + if (stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_FOR_LET_START) + { + binding_type = SCANNER_BINDING_LET; + } + else if (stack_top == SCAN_STACK_CONST || stack_top == SCAN_STACK_FOR_CONST_START) + { + binding_type = SCANNER_BINDING_CONST; + } + + scanner_push_destructuring_pattern (context_p, &scanner_context, binding_type, false); + + if (type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + scanner_context.mode = SCAN_MODE_BINDING; + break; + } + + parser_stack_push_uint8 (context_p, 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context.mode = SCAN_MODE_PROPERTY_NAME; + continue; + } + + if (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, &scanner_context); + + if (stack_top != SCAN_STACK_VAR && stack_top != SCAN_STACK_FOR_VAR_START) + { + scanner_detect_invalid_let (context_p, literal_p); + + if (stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_FOR_LET_START) + { + literal_p->type |= SCANNER_LITERAL_IS_LET; + } + else + { + JERRY_ASSERT (stack_top == SCAN_STACK_CONST || stack_top == SCAN_STACK_FOR_CONST_START); + literal_p->type |= SCANNER_LITERAL_IS_CONST; + } + + lexer_next_token (context_p); + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + else if (context_p->token.type == LEXER_ASSIGN) + { + scanner_binding_literal_t binding_literal; + binding_literal.literal_p = literal_p; + + parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT); + } + } + else + { + if (!(literal_p->type & SCANNER_LITERAL_IS_VAR)) + { + scanner_detect_invalid_var (context_p, &scanner_context, literal_p); + literal_p->type |= SCANNER_LITERAL_IS_VAR; + + if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + literal_p->type |= SCANNER_LITERAL_NO_REG; + } + } + + lexer_next_token (context_p); + } + +#if JERRY_MODULE_SYSTEM + if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT) + { + literal_p->type |= SCANNER_LITERAL_NO_REG; + } +#endif /* JERRY_MODULE_SYSTEM */ + + switch (context_p->token.type) + { + case LEXER_ASSIGN: + { + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + /* FALLTHRU */ + } + case LEXER_COMMA: + { + lexer_next_token (context_p); + continue; + } + } + + if (SCANNER_IS_FOR_START (stack_top)) + { +#if JERRY_MODULE_SYSTEM + JERRY_ASSERT (!(scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT)); +#endif /* JERRY_MODULE_SYSTEM */ + + if (context_p->token.type != LEXER_SEMICOLON && context_p->token.type != LEXER_KEYW_IN + && !SCANNER_IDENTIFIER_IS_OF ()) + { + scanner_raise_error (context_p); + } + + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + continue; + } + + JERRY_ASSERT (stack_top == SCAN_STACK_VAR || stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_CONST); + +#if JERRY_MODULE_SYSTEM + scanner_context.active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT; +#endif /* JERRY_MODULE_SYSTEM */ + + scanner_context.mode = SCAN_MODE_STATEMENT_END; + parser_stack_pop_uint8 (context_p); + continue; + } + case SCAN_MODE_FUNCTION_ARGUMENTS: + { + JERRY_ASSERT (stack_top == SCAN_STACK_SCRIPT_FUNCTION || stack_top == SCAN_STACK_FUNCTION_STATEMENT + || stack_top == SCAN_STACK_FUNCTION_EXPRESSION || stack_top == SCAN_STACK_FUNCTION_PROPERTY); + + scanner_literal_pool_t *literal_pool_p = scanner_context.active_literal_pool_p; + + JERRY_ASSERT (literal_pool_p != NULL && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION)); + + literal_pool_p->source_p = context_p->source_p; + + if (JERRY_UNLIKELY (scanner_context.async_source_p != NULL)) + { + literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ASYNC; + literal_pool_p->source_p = scanner_context.async_source_p; + scanner_context.async_source_p = NULL; + } + + if (type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + lexer_next_token (context_p); + + /* FALLTHRU */ + } + case SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS: + { + if (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS) + { + lexer_lit_location_t *argument_literal_p; + + do + { + if (context_p->token.type == LEXER_THREE_DOTS) + { + scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT; + lexer_next_token (context_p); + } + + if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE) + { + argument_literal_p = NULL; + break; + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + argument_literal_p = scanner_append_argument (context_p, &scanner_context); + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_COMMA) + { + break; + } + + lexer_next_token (context_p); + } while (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS); + + if (argument_literal_p == NULL) + { + scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT; + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS); + scanner_append_hole (context_p, &scanner_context); + scanner_push_destructuring_pattern (context_p, &scanner_context, SCANNER_BINDING_ARG, false); + + if (context_p->token.type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + scanner_context.mode = SCAN_MODE_BINDING; + break; + } + + parser_stack_push_uint8 (context_p, 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context.mode = SCAN_MODE_PROPERTY_NAME; + continue; + } + + if (context_p->token.type == LEXER_ASSIGN) + { + scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT; + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS); + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (argument_literal_p->type & SCANNER_LITERAL_IS_USED) + { + JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE); + break; + } + + scanner_binding_literal_t binding_literal; + binding_literal.literal_p = argument_literal_p; + + parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT); + break; + } + } + + if (context_p->token.type == LEXER_EOS && stack_top == SCAN_STACK_SCRIPT_FUNCTION) + { + /* End of argument parsing. */ + scanner_info_t *scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, sizeof (scanner_info_t)); + scanner_info_p->next_p = context_p->next_scanner_info_p; + scanner_info_p->source_p = NULL; + scanner_info_p->type = SCANNER_TYPE_END_ARGUMENTS; + scanner_context.end_arguments_p = scanner_info_p; + + context_p->next_scanner_info_p = scanner_info_p; + context_p->source_p = context_p->source_start_p; + context_p->source_end_p = context_p->source_start_p + context_p->source_size; + lexer_init_line_info (context_p); + + scanner_filter_arguments (context_p, &scanner_context); + lexer_next_token (context_p); + scanner_check_directives (context_p, &scanner_context); + continue; + } + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_filter_arguments (context_p, &scanner_context); + lexer_next_token (context_p); + scanner_check_directives (context_p, &scanner_context); + continue; + } + case SCAN_MODE_PROPERTY_NAME: + { + JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL); + + if (lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS)) + { + lexer_check_property_modifier (context_p); + } + + if (context_p->token.type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_COMPUTED_PROPERTY); + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + + if (context_p->token.type == LEXER_THREE_DOTS) + { + *parser_stack_get_prev_uint8 (context_p) |= SCANNER_LITERAL_OBJECT_HAS_REST; + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (scanner_context.binding_type != SCANNER_BINDING_NONE) + { + scanner_context.mode = SCAN_MODE_BINDING; + } + break; + } + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + continue; + } + + if (context_p->token.type == LEXER_PROPERTY_GETTER || context_p->token.type == LEXER_KEYW_ASYNC + || context_p->token.type == LEXER_MULTIPLY || context_p->token.type == LEXER_PROPERTY_SETTER) + { + uint16_t literal_pool_flags = SCANNER_LITERAL_POOL_FUNCTION; + + if (context_p->token.type == LEXER_MULTIPLY) + { + literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + else if (context_p->token.type == LEXER_KEYW_ASYNC) + { + literal_pool_flags |= SCANNER_LITERAL_POOL_ASYNC; + + if (lexer_consume_generator (context_p)) + { + literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + + if (context_p->token.type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags)); + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + + if (context_p->token.type != LEXER_LITERAL) + { + scanner_raise_error (context_p); + } + + scanner_push_literal_pool (context_p, &scanner_context, literal_pool_flags); + scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; + break; + } + + if (context_p->token.type != LEXER_LITERAL) + { + scanner_raise_error (context_p); + } + + parser_line_counter_t start_line = context_p->token.line; + parser_line_counter_t start_column = context_p->token.column; + bool is_ident = (context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION); + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; + continue; + } + + if (is_ident + && (context_p->token.type == LEXER_COMMA || context_p->token.type == LEXER_RIGHT_BRACE + || context_p->token.type == LEXER_ASSIGN)) + { + context_p->source_p = context_p->token.lit_location.char_p; + context_p->line = start_line; + context_p->column = start_column; + + lexer_next_token (context_p); + + JERRY_ASSERT (context_p->token.type != LEXER_LITERAL + || context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + if (context_p->token.type != LEXER_LITERAL) + { + scanner_raise_error (context_p); + } + + if (scanner_context.binding_type != SCANNER_BINDING_NONE) + { + scanner_context.mode = SCAN_MODE_BINDING; + continue; + } + + scanner_add_reference (context_p, &scanner_context); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_ASSIGN) + { + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + continue; + } + + if (context_p->token.type != LEXER_COLON) + { + scanner_raise_error (context_p); + } + + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (scanner_context.binding_type != SCANNER_BINDING_NONE) + { + scanner_context.mode = SCAN_MODE_BINDING; + } + break; + } + case SCAN_MODE_BINDING: + { + JERRY_ASSERT (scanner_context.binding_type == SCANNER_BINDING_VAR + || scanner_context.binding_type == SCANNER_BINDING_LET + || scanner_context.binding_type == SCANNER_BINDING_CATCH + || scanner_context.binding_type == SCANNER_BINDING_CONST + || scanner_context.binding_type == SCANNER_BINDING_ARG + || scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG); + + if (type == LEXER_THREE_DOTS) + { + lexer_next_token (context_p); + type = (lexer_token_type_t) context_p->token.type; + } + + if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE) + { + scanner_push_destructuring_pattern (context_p, &scanner_context, scanner_context.binding_type, true); + + if (type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + break; + } + + parser_stack_push_uint8 (context_p, 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context.mode = SCAN_MODE_PROPERTY_NAME; + continue; + } + + if (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + continue; + } + + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, &scanner_context); + + scanner_context.mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + + if (scanner_context.binding_type == SCANNER_BINDING_VAR) + { + if (!(literal_p->type & SCANNER_LITERAL_IS_VAR)) + { + scanner_detect_invalid_var (context_p, &scanner_context, literal_p); + literal_p->type |= SCANNER_LITERAL_IS_VAR; + + if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + literal_p->type |= SCANNER_LITERAL_NO_REG; + } + } + break; + } + + if (scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG) + { + literal_p->type |= SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG; + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + break; + } + } + else + { + scanner_detect_invalid_let (context_p, literal_p); + + if (scanner_context.binding_type <= SCANNER_BINDING_CATCH) + { + JERRY_ASSERT ((scanner_context.binding_type == SCANNER_BINDING_LET) + || (scanner_context.binding_type == SCANNER_BINDING_CATCH)); + + literal_p->type |= SCANNER_LITERAL_IS_LET; + } + else + { + literal_p->type |= SCANNER_LITERAL_IS_CONST; + + if (scanner_context.binding_type == SCANNER_BINDING_ARG) + { + literal_p->type |= SCANNER_LITERAL_IS_ARG; + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + break; + } + } + } + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + break; + } + } + + scanner_binding_item_t *binding_item_p; + binding_item_p = (scanner_binding_item_t *) scanner_malloc (context_p, sizeof (scanner_binding_item_t)); + + binding_item_p->next_p = scanner_context.active_binding_list_p->items_p; + binding_item_p->literal_p = literal_p; + + scanner_context.active_binding_list_p->items_p = binding_item_p; + + lexer_next_token (context_p); + if (context_p->token.type != LEXER_ASSIGN) + { + continue; + } + + scanner_binding_literal_t binding_literal; + binding_literal.literal_p = literal_p; + + parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT); + + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + } + + lexer_next_token (context_p); + } + +scan_completed: + if (context_p->stack_top_uint8 != SCAN_STACK_SCRIPT && context_p->stack_top_uint8 != SCAN_STACK_SCRIPT_FUNCTION) + { + scanner_raise_error (context_p); + } + + scanner_pop_literal_pool (context_p, &scanner_context); + + JERRY_ASSERT (scanner_context.active_binding_list_p == NULL); + JERRY_ASSERT (scanner_context.active_literal_pool_p == NULL); + +#ifndef JERRY_NDEBUG + scanner_context.context_status_flags |= PARSER_SCANNING_SUCCESSFUL; +#endif /* !JERRY_NDEBUG */ + } + PARSER_CATCH + { + while (scanner_context.active_binding_list_p != NULL) + { + scanner_pop_binding_list (&scanner_context); + } + + if (JERRY_UNLIKELY (context_p->error != PARSER_ERR_OUT_OF_MEMORY)) + { + /* Ignore the errors thrown by the lexer. */ + context_p->error = PARSER_ERR_NO_ERROR; + + /* The following code may allocate memory, so it is enclosed in a try/catch. */ + PARSER_TRY (context_p->try_buffer) + { + if (scanner_context.status_flags & SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION) + { + JERRY_ASSERT (scanner_context.async_source_p != NULL); + + scanner_info_t *info_p; + info_p = scanner_insert_info (context_p, scanner_context.async_source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_ERR_ASYNC_FUNCTION; + } + + while (scanner_context.active_literal_pool_p != NULL) + { + scanner_pop_literal_pool (context_p, &scanner_context); + } + } + PARSER_CATCH + { + JERRY_ASSERT (context_p->error == PARSER_ERR_OUT_OF_MEMORY); + } + PARSER_TRY_END + } + + JERRY_ASSERT (context_p->error == PARSER_ERR_NO_ERROR || context_p->error == PARSER_ERR_OUT_OF_MEMORY); + + if (context_p->error == PARSER_ERR_OUT_OF_MEMORY) + { + while (scanner_context.active_literal_pool_p != NULL) + { + scanner_literal_pool_t *literal_pool_p = scanner_context.active_literal_pool_p; + + scanner_context.active_literal_pool_p = literal_pool_p->prev_p; + + parser_list_free (&literal_pool_p->literal_pool); + scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t)); + } + + parser_stack_free (context_p); + return; + } + } + PARSER_TRY_END + + context_p->status_flags = scanner_context.context_status_flags; + context_p->global_status_flags &= (uint32_t) ~ECMA_PARSE_INTERNAL_PRE_SCANNING; + scanner_reverse_info_list (context_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + scanner_info_t *info_p = context_p->next_scanner_info_p; + const uint8_t *source_start_p = + (context_p->arguments_start_p == NULL ? context_p->source_start_p : context_p->arguments_start_p); + + while (info_p->type != SCANNER_TYPE_END) + { + const char *name_p = NULL; + bool print_location = false; + + switch (info_p->type) + { + case SCANNER_TYPE_END_ARGUMENTS: + { + JERRY_DEBUG_MSG (" END_ARGUMENTS\n"); + source_start_p = context_p->source_start_p; + break; + } + case SCANNER_TYPE_FUNCTION: + case SCANNER_TYPE_BLOCK: + { + const uint8_t *prev_source_p = info_p->source_p - 1; + const uint8_t *data_p; + + if (info_p->type == SCANNER_TYPE_FUNCTION) + { + data_p = (const uint8_t *) (info_p + 1); + + JERRY_DEBUG_MSG (" FUNCTION: flags: 0x%x declarations: %d", (int) info_p->u8_arg, (int) info_p->u16_arg); + } + else + { + data_p = (const uint8_t *) (info_p + 1); + + JERRY_DEBUG_MSG (" BLOCK:"); + } + + JERRY_DEBUG_MSG (" source:%d\n", (int) (info_p->source_p - source_start_p)); + + while (data_p[0] != SCANNER_STREAM_TYPE_END) + { + switch (data_p[0] & SCANNER_STREAM_TYPE_MASK) + { + case SCANNER_STREAM_TYPE_HOLE: + { + JERRY_DEBUG_MSG (" HOLE\n"); + data_p++; + continue; + } + case SCANNER_STREAM_TYPE_ARGUMENTS: + { + JERRY_DEBUG_MSG (" ARGUMENTS%s%s\n", + (data_p[0] & SCANNER_STREAM_NO_REG) ? " *" : "", + (data_p[0] & SCANNER_STREAM_LOCAL_ARGUMENTS) ? " L" : ""); + data_p++; + continue; + } + case SCANNER_STREAM_TYPE_ARGUMENTS_FUNC: + { + JERRY_DEBUG_MSG (" ARGUMENTS_FUNC%s%s\n", + (data_p[0] & SCANNER_STREAM_NO_REG) ? " *" : "", + (data_p[0] & SCANNER_STREAM_LOCAL_ARGUMENTS) ? " L" : ""); + data_p++; + continue; + } + case SCANNER_STREAM_TYPE_VAR: + { + JERRY_DEBUG_MSG (" VAR "); + break; + } + case SCANNER_STREAM_TYPE_LET: + { + JERRY_DEBUG_MSG (" LET "); + break; + } + case SCANNER_STREAM_TYPE_CONST: + { + JERRY_DEBUG_MSG (" CONST "); + break; + } + case SCANNER_STREAM_TYPE_LOCAL: + { + JERRY_DEBUG_MSG (" LOCAL "); + break; + } +#if JERRY_MODULE_SYSTEM + case SCANNER_STREAM_TYPE_IMPORT: + { + JERRY_DEBUG_MSG (" IMPORT "); + break; + } +#endif /* JERRY_MODULE_SYSTEM */ + case SCANNER_STREAM_TYPE_ARG: + { + JERRY_DEBUG_MSG (" ARG "); + break; + } + case SCANNER_STREAM_TYPE_ARG_VAR: + { + JERRY_DEBUG_MSG (" ARG_VAR "); + break; + } + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG: + { + JERRY_DEBUG_MSG (" DESTRUCTURED_ARG "); + break; + } + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR: + { + JERRY_DEBUG_MSG (" DESTRUCTURED_ARG_VAR "); + break; + } + case SCANNER_STREAM_TYPE_ARG_FUNC: + { + JERRY_DEBUG_MSG (" ARG_FUNC "); + break; + } + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC: + { + JERRY_DEBUG_MSG (" DESTRUCTURED_ARG_FUNC "); + break; + } + case SCANNER_STREAM_TYPE_FUNC: + { + JERRY_DEBUG_MSG (" FUNC "); + break; + } + default: + { + JERRY_UNREACHABLE (); + data_p++; + continue; + } + } + + size_t length; + + if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF)) + { + if (data_p[2] != 0) + { + prev_source_p += data_p[2]; + length = 2 + 1; + } + else + { + memcpy (&prev_source_p, data_p + 2 + 1, sizeof (uintptr_t)); + length = 2 + 1 + sizeof (uintptr_t); + } + } + else + { + int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8; + + if (diff <= UINT8_MAX) + { + diff = -diff; + } + + prev_source_p += diff; + length = 2 + 2; + } + + if (data_p[0] & SCANNER_STREAM_EARLY_CREATE) + { + JERRY_ASSERT (data_p[0] & SCANNER_STREAM_NO_REG); + JERRY_DEBUG_MSG ("*"); + } + + if (data_p[0] & SCANNER_STREAM_NO_REG) + { + JERRY_DEBUG_MSG ("* "); + } + + JERRY_DEBUG_MSG ("'%.*s'\n", data_p[1], (char *) prev_source_p); + prev_source_p += data_p[1]; + data_p += length; + } + break; + } + case SCANNER_TYPE_WHILE: + { + name_p = "WHILE"; + print_location = true; + break; + } + case SCANNER_TYPE_FOR: + { + scanner_for_info_t *for_info_p = (scanner_for_info_t *) info_p; + JERRY_DEBUG_MSG (" FOR: source:%d expression:%d[%d:%d] end:%d[%d:%d]\n", + (int) (for_info_p->info.source_p - source_start_p), + (int) (for_info_p->expression_location.source_p - source_start_p), + (int) for_info_p->expression_location.line, + (int) for_info_p->expression_location.column, + (int) (for_info_p->end_location.source_p - source_start_p), + (int) for_info_p->end_location.line, + (int) for_info_p->end_location.column); + break; + } + case SCANNER_TYPE_FOR_IN: + { + name_p = "FOR-IN"; + print_location = true; + break; + } + case SCANNER_TYPE_FOR_OF: + { + name_p = "FOR-OF"; + print_location = true; + break; + } + case SCANNER_TYPE_SWITCH: + { + JERRY_DEBUG_MSG (" SWITCH: source:%d\n", (int) (info_p->source_p - source_start_p)); + + scanner_case_info_t *current_case_p = ((scanner_switch_info_t *) info_p)->case_p; + + while (current_case_p != NULL) + { + JERRY_DEBUG_MSG (" CASE: location:%d[%d:%d]\n", + (int) (current_case_p->location.source_p - source_start_p), + (int) current_case_p->location.line, + (int) current_case_p->location.column); + + current_case_p = current_case_p->next_p; + } + break; + } + case SCANNER_TYPE_CASE: + { + name_p = "CASE"; + print_location = true; + break; + } + case SCANNER_TYPE_INITIALIZER: + { + scanner_location_info_t *location_info_p = (scanner_location_info_t *) info_p; + JERRY_DEBUG_MSG (" INITIALIZER: flags: 0x%x source:%d location:%d[%d:%d]\n", + (int) info_p->u8_arg, + (int) (location_info_p->info.source_p - source_start_p), + (int) (location_info_p->location.source_p - source_start_p), + (int) location_info_p->location.line, + (int) location_info_p->location.column); + break; + } + case SCANNER_TYPE_CLASS_CONSTRUCTOR: + { + JERRY_DEBUG_MSG (" CLASS: source:%d\n", (int) (info_p->source_p - source_start_p)); + print_location = false; + break; + } + case SCANNER_TYPE_CLASS_STATIC_BLOCK_END: + { + name_p = "SCANNER_TYPE_CLASS_STATIC_BLOCK_END"; + print_location = true; + break; + } + case SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END: + { + name_p = "SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END"; + print_location = true; + break; + } + case SCANNER_TYPE_LET_EXPRESSION: + { + JERRY_DEBUG_MSG (" LET_EXPRESSION: source:%d\n", (int) (info_p->source_p - source_start_p)); + break; + } + case SCANNER_TYPE_ERR_REDECLARED: + { + JERRY_DEBUG_MSG (" JERRY_FATAL_REDECLARED: source:%d\n", (int) (info_p->source_p - source_start_p)); + break; + } + case SCANNER_TYPE_ERR_ASYNC_FUNCTION: + { + JERRY_DEBUG_MSG (" JERRY_FATAL_ASYNC_FUNCTION: source:%d\n", (int) (info_p->source_p - source_start_p)); + break; + } + case SCANNER_TYPE_LITERAL_FLAGS: + { + JERRY_DEBUG_MSG (" SCANNER_TYPE_LITERAL_FLAGS: flags: 0x%x source:%d\n", + (int) info_p->u8_arg, + (int) (info_p->source_p - source_start_p)); + print_location = false; + break; + } + case SCANNER_TYPE_EXPORT_MODULE_SPECIFIER: + { + JERRY_DEBUG_MSG (" EXPORT_WITH_MODULE_SPECIFIER: source:%d\n", (int) (info_p->source_p - source_start_p)); + print_location = false; + break; + } + } + + if (print_location) + { + scanner_location_info_t *location_info_p = (scanner_location_info_t *) info_p; + JERRY_DEBUG_MSG (" %s: source:%d location:%d[%d:%d]\n", + name_p, + (int) (location_info_p->info.source_p - source_start_p), + (int) (location_info_p->location.source_p - source_start_p), + (int) location_info_p->location.line, + (int) location_info_p->location.column); + } + + info_p = info_p->next_p; + } + + JERRY_DEBUG_MSG ("\n--- Scanning end ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_stack_free (context_p); +} /* scanner_scan_all */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.h new file mode 100644 index 00000000..78655685 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.h @@ -0,0 +1,303 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_SCANNER_H +#define JS_SCANNER_H + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +/** + * Allowed types for scanner_info_t structures. + */ +typedef enum +{ + SCANNER_TYPE_END, /**< mark the last info block */ + SCANNER_TYPE_END_ARGUMENTS, /**< mark the end of function arguments + * (only present if a function script is parsed) */ + SCANNER_TYPE_FUNCTION, /**< declarations in a function */ + SCANNER_TYPE_BLOCK, /**< declarations in a code block (usually enclosed in {}) */ + SCANNER_TYPE_WHILE, /**< while statement */ + SCANNER_TYPE_FOR, /**< for statement */ + SCANNER_TYPE_FOR_IN, /**< for-in statement */ + SCANNER_TYPE_FOR_OF, /**< for-of statement */ + SCANNER_TYPE_SWITCH, /**< switch statement */ + SCANNER_TYPE_CASE, /**< case statement */ + SCANNER_TYPE_INITIALIZER, /**< destructuring binding or assignment pattern with initializer */ + SCANNER_TYPE_LITERAL_FLAGS, /**< object or array literal with non-zero flags (stored in u8_arg) */ + SCANNER_TYPE_CLASS_CONSTRUCTOR, /**< class constructor */ + SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END, /**< class field initializer end */ + SCANNER_TYPE_CLASS_STATIC_BLOCK_END, /**< class static block end */ + SCANNER_TYPE_LET_EXPRESSION, /**< let expression */ + SCANNER_TYPE_ERR_REDECLARED, /**< syntax error: a variable is redeclared */ + SCANNER_TYPE_ERR_ASYNC_FUNCTION, /**< an invalid async function follows */ + SCANNER_TYPE_EXPORT_MODULE_SPECIFIER, /**< export with module specifier */ +} scanner_info_type_t; + +/** + * Source code location which can be used to change the position of parsing. + */ +typedef struct +{ + const uint8_t *source_p; /**< next source byte */ + parser_line_counter_t line; /**< token start line */ + parser_line_counter_t column; /**< token start column */ +} scanner_location_t; + +/** + * Source code range with its start and end position. + */ +typedef struct +{ + const uint8_t *source_end_p; /**< end position */ + scanner_location_t start_location; /**< start location */ +} scanner_range_t; + +/** + * Scanner info blocks which provides information for the parser. + */ +typedef struct scanner_info_t +{ + struct scanner_info_t *next_p; /**< next info structure */ + const uint8_t *source_p; /**< triggering position of this scanner info */ + uint8_t type; /**< type of the scanner info */ + uint8_t u8_arg; /**< custom 8-bit value */ + uint16_t u16_arg; /**< custom 16-bit value */ +} scanner_info_t; + +/** + * Scanner info for class private field + */ +typedef struct scanner_class_private_member_t +{ + lexer_lit_location_t loc; /**< loc */ + uint8_t u8_arg; /**< custom 8-bit value */ + struct scanner_class_private_member_t *prev_p; /**< prev private field */ +} scanner_class_private_member_t; + +/** + * Scanner info extended with class private fields. + */ +typedef struct +{ + scanner_info_t info; /**< header */ + scanner_class_private_member_t *members; /**< first private field */ +} scanner_class_info_t; + +/** + * Scanner info extended with a location. + */ +typedef struct +{ + scanner_info_t info; /**< header */ + scanner_location_t location; /**< location */ +} scanner_location_info_t; + +/** + * Scanner info for "for" statements. + */ +typedef struct +{ + scanner_info_t info; /**< header */ + scanner_location_t expression_location; /**< location of expression start */ + scanner_location_t end_location; /**< location of expression end */ +} scanner_for_info_t; + +/** + * Case statement list for scanner_switch_info_t structure. + */ +typedef struct scanner_case_info_t +{ + struct scanner_case_info_t *next_p; /**< next case statement info */ + scanner_location_t location; /**< location of case statement */ +} scanner_case_info_t; + +/** + * Scanner info for "switch" statements. + */ +typedef struct +{ + scanner_info_t info; /**< header */ + scanner_case_info_t *case_p; /**< list of switch cases */ +} scanner_switch_info_t; + +/* + * Description of compressed streams. + * + * The stream is a sequence of commands which encoded as bytes. The first byte + * contains the type of the command (see scanner_function_compressed_stream_types_t). + * + * The variable declaration commands has two arguments: + * - The first represents the length of the declared identifier + * - The second contains the relative distance from the end of the previous declaration + * Usually the distance is between 1 and 255, and represented as a single byte + * Distances between -256 and 65535 are encoded as two bytes + * Larger distances are encoded as pointers + */ + +/** + * Constants for compressed streams. + */ +typedef enum +{ + SCANNER_STREAM_UINT16_DIFF = (1 << 7), /**< relative distance is between -256 and 65535 */ + SCANNER_STREAM_HAS_ESCAPE = (1 << 6), /**< binding has escape */ + SCANNER_STREAM_NO_REG = (1 << 5), /**< binding cannot be stored in register */ + SCANNER_STREAM_EARLY_CREATE = (1 << 4), /**< binding must be created with ECMA_VALUE_UNINITIALIZED */ + SCANNER_STREAM_LOCAL_ARGUMENTS = SCANNER_STREAM_EARLY_CREATE, /**< arguments is redeclared + * as let/const binding later */ + /* Update SCANNER_STREAM_TYPE_MASK macro if more bits are added. */ +} scanner_compressed_stream_flags_t; + +/** + * Types for compressed streams. + */ +typedef enum +{ + SCANNER_STREAM_TYPE_END, /**< end of scanner data */ + SCANNER_STREAM_TYPE_HOLE, /**< no name is assigned to this argument */ + SCANNER_STREAM_TYPE_ARGUMENTS, /**< arguments object should be created */ + SCANNER_STREAM_TYPE_ARGUMENTS_FUNC, /**< arguments object should be created which + * is later initialized with a function */ + SCANNER_STREAM_TYPE_VAR, /**< var declaration */ + SCANNER_STREAM_TYPE_LET, /**< let declaration */ + SCANNER_STREAM_TYPE_CONST, /**< const declaration */ + SCANNER_STREAM_TYPE_LOCAL, /**< local declaration (e.g. catch block) */ +#if JERRY_MODULE_SYSTEM + SCANNER_STREAM_TYPE_IMPORT, /**< module import */ +#endif /* JERRY_MODULE_SYSTEM */ + /* The next four types must be in this order (see SCANNER_STREAM_TYPE_IS_ARG). */ + SCANNER_STREAM_TYPE_ARG, /**< argument declaration */ + SCANNER_STREAM_TYPE_ARG_VAR, /**< argument declaration which is later copied + * into a variable declared by var statement */ + SCANNER_STREAM_TYPE_DESTRUCTURED_ARG, /**< destructuring argument declaration */ + SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR, /**< destructuring argument declaration which is later + * copied into a variable declared by var statement */ + /* Function types should be at the end. See the SCANNER_STREAM_TYPE_IS_FUNCTION macro. */ + SCANNER_STREAM_TYPE_ARG_FUNC, /**< argument declaration which + * is later initialized with a function */ + SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC, /**< destructuring argument declaration which + * is later initialized with a function */ + SCANNER_STREAM_TYPE_FUNC, /**< function declaration */ +} scanner_compressed_stream_types_t; + +/** + * Mask for decoding the type from the compressed stream. + */ +#define SCANNER_STREAM_TYPE_MASK 0xf + +/** + * Checks whether the decoded type represents a function declaration. + */ +#define SCANNER_STREAM_TYPE_IS_FUNCTION(type) ((type) >= SCANNER_STREAM_TYPE_ARG_FUNC) + +/** + * Checks whether the decoded type represents a function argument. + */ +#define SCANNER_STREAM_TYPE_IS_ARG(type) \ + ((type) >= SCANNER_STREAM_TYPE_ARG && (type) <= SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR) + +/** + * Checks whether the decoded type represents both a function argument and a function declaration. + */ +#define SCANNER_STREAM_TYPE_IS_ARG_FUNC(type) \ + ((type) == SCANNER_STREAM_TYPE_ARG_FUNC || (type) == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC) + +/** + * Checks whether the decoded type represents an arguments declaration + */ +#define SCANNER_STREAM_TYPE_IS_ARGUMENTS(type) \ + ((type) == SCANNER_STREAM_TYPE_ARGUMENTS || (type) == SCANNER_STREAM_TYPE_ARGUMENTS_FUNC) + +/** + * Constants for u8_arg flags in scanner_function_info_t. + */ +typedef enum +{ + SCANNER_FUNCTION_ARGUMENTS_NEEDED = (1 << 0), /**< arguments object needs to be created */ + SCANNER_FUNCTION_HAS_COMPLEX_ARGUMENT = (1 << 1), /**< function has complex (ES2015+) argument definition */ + SCANNER_FUNCTION_LEXICAL_ENV_NEEDED = (1 << 2), /**< lexical environment is needed for the function body */ + SCANNER_FUNCTION_STATEMENT = (1 << 3), /**< function is function statement (not arrow expression) + * this flag must be combined with the type of function (e.g. async) */ + SCANNER_FUNCTION_ASYNC = (1 << 4), /**< function is async function */ + SCANNER_FUNCTION_IS_STRICT = (1 << 5), /**< function is strict */ +} scanner_function_flags_t; + +/** + * Constants for u8_arg flags in scanner_class_info_t. + */ +typedef enum +{ + SCANNER_CONSTRUCTOR_IMPLICIT = 0, /**< implicit constructor */ + SCANNER_CONSTRUCTOR_EXPLICIT = (1 << 0), /**< explicit constructor */ + SCANNER_SUCCESSFUL_CLASS_SCAN = (1 << 1), /**< class scan was successful */ + SCANNER_PRIVATE_FIELD_ACTIVE = (1 << 2), /**< private field is active */ +} scanner_constuctor_flags_t; + +/** + * Constants for u8_arg flags in scanner_class_private_member_t. + */ +typedef enum +{ + SCANNER_PRIVATE_FIELD_PROPERTY = (1 << 0), /**< private field initializer */ + SCANNER_PRIVATE_FIELD_METHOD = (1 << 1), /**< private field method */ + SCANNER_PRIVATE_FIELD_STATIC = (1 << 2), /**< static private property */ + SCANNER_PRIVATE_FIELD_GETTER = (1 << 3), /**< private field getter */ + SCANNER_PRIVATE_FIELD_SETTER = (1 << 4), /**< private field setter */ + SCANNER_PRIVATE_FIELD_SEEN = (1 << 5), /**< private field has already been seen */ + SCANNER_PRIVATE_FIELD_IGNORED = SCANNER_PRIVATE_FIELD_METHOD | SCANNER_PRIVATE_FIELD_STATIC, + SCANNER_PRIVATE_FIELD_GETTER_SETTER = (SCANNER_PRIVATE_FIELD_GETTER | SCANNER_PRIVATE_FIELD_SETTER), + SCANNER_PRIVATE_FIELD_PROPERTY_GETTER_SETTER = (SCANNER_PRIVATE_FIELD_PROPERTY | SCANNER_PRIVATE_FIELD_GETTER_SETTER), +} scanner_private_field_flags_t; + +/** + * Object or array literal constants for u8_arg flags in scanner_info_t. + */ +typedef enum +{ + /* These flags affects both array and object literals */ + SCANNER_LITERAL_DESTRUCTURING_FOR = (1 << 0), /**< for loop with destructuring pattern */ + SCANNER_LITERAL_NO_DESTRUCTURING = (1 << 1), /**< this literal cannot be a destructuring pattern */ + /* These flags affects only object literals */ + SCANNER_LITERAL_OBJECT_HAS_SUPER = (1 << 2), /**< super keyword is used in the object literal */ + SCANNER_LITERAL_OBJECT_HAS_REST = (1 << 3), /**< the object literal has a member prefixed with three dots */ +} scanner_literal_flags_t; + +/** + * Option bits for scanner_create_variables function. + */ +typedef enum +{ + SCANNER_CREATE_VARS_NO_OPTS = 0, /**< no options */ + SCANNER_CREATE_VARS_IS_SCRIPT = (1 << 0), /**< create variables for script or direct eval */ + SCANNER_CREATE_VARS_IS_MODULE = (1 << 1), /**< create variables for module */ + SCANNER_CREATE_VARS_IS_FUNCTION_ARGS = (1 << 2), /**< create variables for function arguments */ + SCANNER_CREATE_VARS_IS_FUNCTION_BODY = (1 << 3), /**< create variables for function body */ +} scanner_create_variables_flags_t; + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_SCANNER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/meson.build b/src/loaders/lottie/jerryscript/jerry-core/parser/js/meson.build new file mode 100644 index 00000000..f3fc672e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/meson.build @@ -0,0 +1,33 @@ +source_file = [ + 'byte-code.h', + 'common.h', + 'js-lexer.h', + 'js-parser-limits.h', + 'js-parser.h', + 'js-scanner.h', + 'js-parser-internal.h', + 'js-parser-tagged-template-literal.h', + 'js-scanner-internal.h', + 'parser-errors.h', + 'parser-error-messages.inc.h', + 'byte-code.cpp', + 'common.cpp', + 'js-lexer.cpp', + 'js-parser.cpp', + 'js-parser-expr.cpp', + 'js-parser-line-info-create.cpp', + 'js-parser-mem.cpp', + 'js-parser-module.cpp', + 'js-parser-statm.cpp', + 'js-parser-tagged-template-literal.cpp', + 'js-parser-util.cpp', + 'js-scanner.cpp', + 'js-scanner-ops.cpp', + 'js-scanner-util.cpp', + 'parser-errors.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-error-messages.inc.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-error-messages.inc.h new file mode 100644 index 00000000..cfb96494 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-error-messages.inc.h @@ -0,0 +1,233 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-strings.py script + * from parser-error-messages.ini. Do not edit! */ + +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_LABEL, "Duplicated label") +PARSER_ERROR_DEF (PARSER_ERR_LEFT_PAREN_EXPECTED, "Expected '(' token") +PARSER_ERROR_DEF (PARSER_ERR_RIGHT_PAREN_EXPECTED, "Expected ')' token") +PARSER_ERROR_DEF (PARSER_ERR_COLON_EXPECTED, "Expected ':' token") +PARSER_ERROR_DEF (PARSER_ERR_SEMICOLON_EXPECTED, "Expected ';' token") +PARSER_ERROR_DEF (PARSER_ERR_RIGHT_SQUARE_EXPECTED, "Expected ']' token") +PARSER_ERROR_DEF (PARSER_ERR_LEFT_BRACE_EXPECTED, "Expected '{' token") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM || JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_RIGHT_BRACE_EXPECTED, "Expected '}' token") +#endif /* JERRY_MODULE_SYSTEM \ +|| JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_NUMBER_TOO_LONG, "Number is too long") +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_REGEXP && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_REGEXP_TOO_LONG, "Regexp is too long") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_STATEMENT_EXPECTED, "Statement expected") +PARSER_ERROR_DEF (PARSER_ERR_STRING_TOO_LONG, "String is too long") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_AS_EXPECTED, "Expected 'as' token") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_IN_EXPECTED, "Expected 'in' token") +PARSER_ERROR_DEF (PARSER_ERR_OF_EXPECTED, "Expected 'of' token") +PARSER_ERROR_DEF (PARSER_ERR_EXPRESSION_EXPECTED, "Expression expected") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM || JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_IDENTIFIER_EXPECTED, "Identifier expected") +#endif /* JERRY_MODULE_SYSTEM \ +|| JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_OCTAL_DIGIT, "Invalid octal digit") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_SWITCH, "Invalid switch body") +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_REGEXP && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_UNKNOWN_REGEXP_FLAG, "Unknown regexp flag") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_BIN_DIGIT, "Invalid binary digit") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_RIGHT_SQUARE, "Unexpected '}' token") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_FROM_EXPECTED, "Expected 'from' token") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_MISSING_EXPONENT, "Missing exponent part") +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_REGEXP && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_REGEXP_FLAG, "Duplicated regexp flag") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_ARGUMENT_LIST_EXPECTED, "Expected argument list") +PARSER_ERROR_DEF (PARSER_ERR_IDENTIFIER_TOO_LONG, "Identifier is too long") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_META_EXPECTED, "Expected 'meta' keyword") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_UNEXPECTED_END, "Unexpected end of input") +PARSER_ERROR_DEF (PARSER_ERR_UNEXPECTED_PRIVATE_FIELD, "Unexpected private field") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_LEFT_BRACE_MULTIPLY_EXPECTED, "Expected '{' or '*' token") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM +PARSER_ERROR_DEF (PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED, "Expected '}' or ',' token") +PARSER_ERROR_DEF (PARSER_ERR_STRING_EXPECTED, "Expected a string literal") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_HEX_DIGIT, "Invalid hexadecimal digit") +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_REGEXP && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_UNTERMINATED_REGEXP, "Unterminated regexp literal") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_UNTERMINATED_STRING, "Unterminated string literal") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_FROM_COMMA_EXPECTED, "Expected 'from' or ',' token") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM +PARSER_ERROR_DEF (PARSER_ERR_EXPORT_NOT_DEFINED, "Export not defined in module") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_MODULE_SYSTEM || JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_VARIABLE_REDECLARED, "Local variable is redeclared") +#endif /* JERRY_MODULE_SYSTEM \ +|| JERRY_PARSER */ +#if JERRY_BUILTIN_BIGINT && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_BIGINT, "Number is not a valid BigInt") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_PROPERTY_IDENTIFIER_EXPECTED, "Property identifier expected") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER, "Duplicate exported identifier") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_NEW_TARGET_EXPECTED, "Expected new.target expression") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_CHARACTER, "Invalid (unexpected) character") +PARSER_ERROR_DEF (PARSER_ERR_NON_STRICT_ARG_DEFINITION, "Non-strict argument definition") +PARSER_ERROR_DEF (PARSER_ERR_UNTERMINATED_MULTILINE_COMMENT, "Unterminated multiline comment") +PARSER_ERROR_DEF (PARSER_ERR_CATCH_FINALLY_EXPECTED, "Catch or finally block expected") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE, "Invalid unicode escape sequence") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_IMPORT_BINDING, "Duplicated imported binding name") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_WHILE_EXPECTED, "While expected for do-while loop") +PARSER_ERROR_DEF (PARSER_ERR_DELETE_PRIVATE_FIELD, "Private fields can not be deleted") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_LHS_FOR_LOOP, "Invalid left-hand-side in for-loop") +PARSER_ERROR_DEF (PARSER_ERR_LEFT_HAND_SIDE_EXP_EXPECTED, "Left-hand-side expression expected") +PARSER_ERROR_DEF (PARSER_ERR_LITERAL_LIMIT_REACHED, "Maximum number of literals reached") +PARSER_ERROR_DEF (PARSER_ERR_STACK_LIMIT_REACHED, "Maximum function stack size reached") +PARSER_ERROR_DEF (PARSER_ERR_AWAIT_NOT_ALLOWED, "Await expression is not allowed here") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED, "Expected '{' or '*' or literal token") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_LHS_ASSIGNMENT, "Invalid left-hand side in assignment") +PARSER_ERROR_DEF (PARSER_ERR_SCOPE_STACK_LIMIT_REACHED, "Maximum depth of scope stack reached") +PARSER_ERROR_DEF (PARSER_ERR_UNEXPECTED_SUPER_KEYWORD, "Super is not allowed to be used here") +PARSER_ERROR_DEF (PARSER_ERR_YIELD_NOT_ALLOWED, "Yield expression is not allowed here") +PARSER_ERROR_DEF (PARSER_ERR_MULTIPLE_CLASS_CONSTRUCTORS, "Multiple constructors are not allowed") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM +PARSER_ERROR_DEF (PARSER_ERR_MODULE_UNEXPECTED, "Unexpected import or export statement") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_IDENTIFIER_AFTER_NUMBER, "Identifier cannot start after a number") +PARSER_ERROR_DEF (PARSER_ERR_MULTIPLE_DEFAULTS_NOT_ALLOWED, "Multiple default cases are not allowed") +PARSER_ERROR_DEF (PARSER_ERR_ARRAY_ITEM_SEPARATOR_EXPECTED, "Expected ',' or ']' after an array item") +PARSER_ERROR_DEF (PARSER_ERR_ILLEGAL_PROPERTY_IN_DECLARATION, "Illegal property in declaration context") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_DESTRUCTURING_PATTERN, "Invalid destructuring assignment target") +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_PRIVATE_FIELD, "Private field has already been declared") +PARSER_ERROR_DEF (PARSER_ERR_NO_ARGUMENTS_EXPECTED, "Property getters must have no arguments") +PARSER_ERROR_DEF (PARSER_ERR_ONE_ARGUMENT_EXPECTED, "Property setters must have one argument") +PARSER_ERROR_DEF (PARSER_ERR_CASE_NOT_IN_SWITCH, "Case statement must be in a switch block") +PARSER_ERROR_DEF (PARSER_ERR_CLASS_CONSTRUCTOR_AS_ACCESSOR, "Class constructor may not be an accessor") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_CONTINUE, "Continue statement must be inside a loop") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_IMPORT_META_REQUIRE_MODULE, "Cannot use 'import.meta' outside a module") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_IDENTIFIER_PART, "Character cannot be part of an identifier") +PARSER_ERROR_DEF (PARSER_ERR_EVAL_CANNOT_ASSIGNED, "Eval cannot be assigned to in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_WITH_NOT_ALLOWED, "With statement not allowed in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_NEW_TARGET_NOT_ALLOWED, "new.target expression is not allowed here") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_IDENTIFIER_START, "Character cannot be start of an identifier") +PARSER_ERROR_DEF (PARSER_ERR_STRICT_IDENT_NOT_ALLOWED, "Identifier name is reserved in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_NULLISH_COALESCING, "Cannot chain nullish with logical AND or OR") +PARSER_ERROR_DEF (PARSER_ERR_DEFAULT_NOT_IN_SWITCH, "Default statement must be in a switch block") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_IMPORT_AFTER_NEW, "Module import call is not allowed after new") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_TOO_MANY_CLASS_FIELDS, "Too many computed class fields are declared") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_KEYWORD, "Escape sequences are not allowed in keywords") +PARSER_ERROR_DEF (PARSER_ERR_ARGUMENT_LIMIT_REACHED, "Maximum number of function arguments reached") +PARSER_ERROR_DEF (PARSER_ERR_NEWLINE_NOT_ALLOWED, "Newline is not allowed in strings or regexps") +PARSER_ERROR_DEF (PARSER_ERR_OCTAL_NUMBER_NOT_ALLOWED, "Octal numbers are not allowed in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_CLASS_PRIVATE_CONSTRUCTOR, "Class constructor may not be a private method") +PARSER_ERROR_DEF (PARSER_ERR_FOR_AWAIT_NO_OF, "only 'of' form is allowed for for-await loops") +PARSER_ERROR_DEF (PARSER_ERR_ARGUMENTS_CANNOT_ASSIGNED, "Arguments cannot be assigned to in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_BREAK, "Break statement must be inside a loop or switch") +PARSER_ERROR_DEF (PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED, "Expected ',' or '}' after a property definition") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_BREAK_LABEL, "Labeled statement targeted by a break not found") +#endif /* JERRY_PARSER */ +#if JERRY_PARSER && !(JERRY_BUILTIN_REGEXP) +PARSER_ERROR_DEF (PARSER_ERR_UNSUPPORTED_REGEXP, "Regexp is not supported in the selected profile") +#endif /* JERRY_PARSER && !(JERRY_BUILTIN_REGEXP) */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_RETURN, "Return statement must be inside a function body") +PARSER_ERROR_DEF (PARSER_ERR_COLON_FOR_CONDITIONAL_EXPECTED, "Expected ':' token for ?: conditional expression") +PARSER_ERROR_DEF (PARSER_ERR_FORMAL_PARAM_AFTER_REST_PARAMETER, "Rest parameter must be the last formal parameter") +PARSER_ERROR_DEF (PARSER_ERR_DELETE_IDENT_NOT_ALLOWED, "Deleting identifier is not allowed in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_LABELLED_FUNC_NOT_IN_BLOCK, "Labelled functions are only allowed inside blocks") +PARSER_ERROR_DEF (PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER, "Rest parameter may not have a default initializer") +PARSER_ERROR_DEF (PARSER_ERR_EVAL_NOT_ALLOWED, "Eval is not allowed to be used here in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_CONTINUE_LABEL, "Labeled statement targeted by a continue not found") +PARSER_ERROR_DEF (PARSER_ERR_LEXICAL_LET_BINDING, "Let binding cannot appear in let/const declarations") +PARSER_ERROR_DEF (PARSER_ERR_UNDECLARED_PRIVATE_FIELD, "Private field must be declared in an enclosing class") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_LHS_PREFIX_OP, "Invalid left-hand side expression in prefix operation") +PARSER_ERROR_DEF (PARSER_ERR_OCTAL_ESCAPE_NOT_ALLOWED, "Octal escape sequences are not allowed in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_SETTER_REST_PARAMETER, "Setter function argument must not be a rest parameter") +PARSER_ERROR_DEF (PARSER_ERR_ARGUMENTS_IN_CLASS_FIELD, "In class field declarations 'arguments' is not allowed") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_LHS_POSTFIX_OP, "Invalid left-hand side expression in postfix operation") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER, "Invalid use of underscore character in number literals") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_EXPONENTIATION, "Left operand of ** operator cannot be unary expression") +PARSER_ERROR_DEF (PARSER_ERR_MISSING_ASSIGN_AFTER_CONST, "Value assignment is expected after a const declaration") +PARSER_ERROR_DEF (PARSER_ERR_ARGUMENTS_NOT_ALLOWED, "Arguments is not allowed to be used here in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_ARGUMENT_NAMES, "Duplicated function argument names are not allowed here") +PARSER_ERROR_DEF (PARSER_ERR_CLASS_STATIC_PROTOTYPE, "Classes may not have a static property called 'prototype'") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_CLASS_CONSTRUCTOR, "Class constructor may not be a generator or async function") +PARSER_ERROR_DEF (PARSER_ERR_TEMPLATE_STR_OCTAL_ESCAPE, "Octal escape sequences are not allowed in template strings") +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_PROTO, "Duplicate __proto__ fields are not allowed in object literals") +PARSER_ERROR_DEF (PARSER_ERR_GENERATOR_IN_SINGLE_STATEMENT_POS, + "Generator function cannot appear in a single-statement context") +PARSER_ERROR_DEF (PARSER_ERR_LEXICAL_SINGLE_STATEMENT, + "Lexical declaration cannot appear in a single-statement context") +PARSER_ERROR_DEF (PARSER_ERR_FOR_IN_OF_DECLARATION, "for in-of loop variable declaration may not have an initializer") +PARSER_ERROR_DEF (PARSER_ERR_FOR_AWAIT_NO_ASYNC, "for-await-of is only allowed inside async functions and generators") +PARSER_ERROR_DEF (PARSER_ERR_USE_STRICT_NOT_ALLOWED, + "The 'use strict' directive is not allowed for functions with non-simple arguments") +PARSER_ERROR_DEF (PARSER_ERR_ASSIGNMENT_EXPECTED, + "Unexpected arrow function or yield expression (parentheses around the expression may help)") +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.cpp new file mode 100644 index 00000000..e21f9b0f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.cpp @@ -0,0 +1,71 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "parser-errors.h" + +#if JERRY_ERROR_MESSAGES +/** + * Struct to store parser error message with its size. + */ +typedef struct +{ + lit_utf8_byte_t *text; /* Text of parser error message. */ + uint8_t size; /* Size of parser error message. */ +} parser_error_message_t; + +/* Error message texts with size. */ +static parser_error_message_t parser_error_messages[] JERRY_ATTR_CONST_DATA = { + { (lit_utf8_byte_t *) "", 0 }, /* PARSER_ERR_EMPTY */ +/** @cond doxygen_suppress */ +#define PARSER_ERROR_DEF(id, utf8_string) { (lit_utf8_byte_t *) utf8_string, sizeof (utf8_string) - 1 }, +#include "parser-error-messages.inc.h" +#undef PARSER_ERROR_DEF + /** @endcond */ +}; +#endif /* JERRY_ERROR_MESSAGES */ + +/** + * Get specified parser error as zero-terminated string + * + * @return pointer to zero-terminated parser error + */ +const lit_utf8_byte_t * +parser_get_error_utf8 (uint32_t id) /**< parser error id */ +{ + JERRY_ASSERT (id < PARSER_ERR_OUT_OF_MEMORY); + +#if JERRY_ERROR_MESSAGES + return parser_error_messages[id].text; +#else /* !JERRY_ERROR_MESSAGES */ + return NULL; +#endif /* JERRY_ERROR_MESSAGES */ +} /* parser_get_error_utf8 */ + +/** + * Get size of specified parser error + * + * @return size in bytes + */ +lit_utf8_size_t +parser_get_error_size (uint32_t id) /**< parser error id */ +{ + JERRY_ASSERT (id < PARSER_ERR_OUT_OF_MEMORY); + +#if JERRY_ERROR_MESSAGES + return parser_error_messages[id].size; +#else /* !JERRY_ERROR_MESSAGES */ + return 0; +#endif /* JERRY_ERROR_MESSAGES */ +} /* parser_get_error_size */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.h new file mode 100644 index 00000000..775dee03 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PARSER_ERRORS_H +#define PARSER_ERRORS_H + +#include "lit-globals.h" + +typedef enum +{ + PARSER_ERR_EMPTY, +/** @cond doxygen_suppress */ +#if JERRY_ERROR_MESSAGES +#define PARSER_ERROR_DEF(id, ascii_zt_string) id, +#else /* !JERRY_ERROR_MESSAGES */ +#define PARSER_ERROR_DEF(id, ascii_zt_string) id = PARSER_ERR_EMPTY, +#endif /* JERRY_ERROR_MESSAGES */ +#include "parser-error-messages.inc.h" +#undef PARSER_ERROR_DEF + /** @endcond */ + PARSER_ERR_OUT_OF_MEMORY, + PARSER_ERR_INVALID_REGEXP, +#if (JERRY_STACK_LIMIT != 0) + PARSER_ERR_STACK_OVERFLOW, +#endif /* JERRY_STACK_LIMIT != 0 */ + PARSER_ERR_NO_ERROR, +} parser_error_msg_t; + +const lit_utf8_byte_t* parser_get_error_utf8 (uint32_t id); +lit_utf8_size_t parser_get_error_size (uint32_t id); + +#endif /* !PARSER_ERRORS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/meson.build b/src/loaders/lottie/jerryscript/jerry-core/parser/meson.build new file mode 100644 index 00000000..f0519b25 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/meson.build @@ -0,0 +1,2 @@ +subdir('js') +subdir('regexp') diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/meson.build b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/meson.build new file mode 100644 index 00000000..2bcc0add --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/meson.build @@ -0,0 +1,15 @@ +source_file = [ + 're-bytecode.h', + 're-compiler-context.h', + 're-compiler.h', + 're-parser.h', + 're-token.h', + 're-bytecode.cpp', + 're-compiler.cpp', + 're-parser.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.cpp new file mode 100644 index 00000000..e9b6141e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.cpp @@ -0,0 +1,620 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "re-bytecode.h" + +#include "ecma-globals.h" +#include "ecma-regexp-object.h" + +#include "lit-strings.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_bytecode Bytecode + * @{ + */ + +void +re_initialize_regexp_bytecode (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */ +{ + const size_t initial_size = sizeof (re_compiled_code_t); + re_ctx_p->bytecode_start_p = (uint8_t *) jmem_heap_alloc_block (initial_size); + re_ctx_p->bytecode_size = initial_size; +} /* re_initialize_regexp_bytecode */ + +uint32_t +re_bytecode_size (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */ +{ + return (uint32_t) re_ctx_p->bytecode_size; +} /* re_bytecode_size */ + +/** + * Append a new bytecode to the and of the bytecode container + */ +static uint8_t * +re_bytecode_reserve (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const size_t size) /**< size */ +{ + const size_t old_size = re_ctx_p->bytecode_size; + const size_t new_size = old_size + size; + re_ctx_p->bytecode_start_p = reinterpret_cast(jmem_heap_realloc_block (re_ctx_p->bytecode_start_p, old_size, new_size)); + re_ctx_p->bytecode_size = new_size; + return re_ctx_p->bytecode_start_p + old_size; +} /* re_bytecode_reserve */ + +/** + * Insert a new bytecode to the bytecode container + */ +static uint8_t * +re_bytecode_insert (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const size_t offset, /**< distance from the start of the container */ + const size_t size) /**< size */ +{ + const size_t tail_size = re_ctx_p->bytecode_size - offset; + re_bytecode_reserve (re_ctx_p, size); + + uint8_t *dest_p = re_ctx_p->bytecode_start_p + offset; + memmove (dest_p + size, dest_p, tail_size); + + return dest_p; +} /* re_bytecode_insert */ + +/** + * Append a byte + */ +void +re_append_byte (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint8_t byte) /**< byte value */ +{ + uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, sizeof (uint8_t)); + *dest_p = byte; +} /* re_append_byte */ + +/** + * Insert a byte value + */ +void +re_insert_byte (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint32_t offset, /**< distance from the start of the container */ + const uint8_t byte) /**< byte value */ +{ + uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, sizeof (uint8_t)); + *dest_p = byte; +} /* re_insert_byte */ + +/** + * Get a single byte and icnrease bytecode position. + */ +uint8_t +re_get_byte (const uint8_t **bc_p) /**< pointer to bytecode start */ +{ + return *((*bc_p)++); +} /* re_get_byte */ + +/** + * Append a RegExp opcode + */ +void +re_append_opcode (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const re_opcode_t opcode) /**< input opcode */ +{ + re_append_byte (re_ctx_p, (uint8_t) opcode); +} /* re_append_opcode */ + +/** + * Insert a RegExp opcode + */ +void +re_insert_opcode (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint32_t offset, /**< distance from the start of the container */ + const re_opcode_t opcode) /**< input opcode */ +{ + re_insert_byte (re_ctx_p, offset, (uint8_t) opcode); +} /* re_insert_opcode */ + +/** + * Get a RegExp opcode and increase the bytecode position + * + * @return current RegExp opcode + */ +re_opcode_t +re_get_opcode (const uint8_t **bc_p) /**< pointer to bytecode start */ +{ + return (re_opcode_t) re_get_byte (bc_p); +} /* re_get_opcode */ + +/** + * Encode 2 byte unsigned integer into the bytecode + */ +static void +re_encode_u16 (uint8_t *dest_p, /**< destination */ + const uint16_t value) /**< value */ +{ + *dest_p++ = (uint8_t) ((value >> 8) & 0xFF); + *dest_p = (uint8_t) (value & 0xFF); +} /* re_encode_u16 */ + +/** + * Encode 4 byte unsigned integer into the bytecode + */ +static void +re_encode_u32 (uint8_t *dest_p, /**< destination */ + const uint32_t value) /**< value */ +{ + *dest_p++ = (uint8_t) ((value >> 24) & 0xFF); + *dest_p++ = (uint8_t) ((value >> 16) & 0xFF); + *dest_p++ = (uint8_t) ((value >> 8) & 0xFF); + *dest_p = (uint8_t) (value & 0xFF); +} /* re_encode_u32 */ + +/** + * Decode 2 byte unsigned integer from bytecode + * + * @return uint16_t value + */ +static uint16_t +re_decode_u16 (const uint8_t *src_p) /**< source */ +{ + uint16_t value = (uint16_t) (((uint16_t) *src_p++) << 8); + value = (uint16_t) (value + *src_p++); + return value; +} /* re_decode_u16 */ + +/** + * Decode 4 byte unsigned integer from bytecode + * + * @return uint32_t value + */ +static uint32_t JERRY_ATTR_NOINLINE +re_decode_u32 (const uint8_t *src_p) /**< source */ +{ + uint32_t value = (uint32_t) (((uint32_t) *src_p++) << 24); + value += (uint32_t) (((uint32_t) *src_p++) << 16); + value += (uint32_t) (((uint32_t) *src_p++) << 8); + value += (uint32_t) (*src_p++); + return value; +} /* re_decode_u32 */ + +/** + * Get the encoded size of an uint32_t value. + * + * @return encoded value size + */ +static inline size_t +re_get_encoded_value_size (uint32_t value) /**< value */ +{ + if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX)) + { + return 1; + } + + return 5; +} /* re_get_encoded_value_size */ + +/* + * Encode a value to the specified position in the bytecode. + */ +static void +re_encode_value (uint8_t *dest_p, /**< position in bytecode */ + const uint32_t value) /**< value */ +{ + if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX)) + { + *dest_p = (uint8_t) value; + return; + } + + *dest_p++ = (uint8_t) (RE_VALUE_4BYTE_MARKER); + re_encode_u32 (dest_p, value); +} /* re_encode_value */ + +/** + * Append a value to the end of the bytecode. + */ +void +re_append_value (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint32_t value) /**< value */ +{ + const size_t size = re_get_encoded_value_size (value); + uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, size); + re_encode_value (dest_p, value); +} /* re_append_value */ + +/** + * Insert a value into the bytecode at a specific offset. + */ +void +re_insert_value (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint32_t offset, /**< bytecode offset */ + const uint32_t value) /**< value */ +{ + const size_t size = re_get_encoded_value_size (value); + uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, size); + re_encode_value (dest_p, value); +} /* re_insert_value */ + +/** + * Read an encoded value from the bytecode. + * + * @return decoded value + */ +uint32_t +re_get_value (const uint8_t **bc_p) /** refence to bytecode pointer */ +{ + uint32_t value = *(*bc_p)++; + if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX)) + { + return value; + } + + value = re_decode_u32 (*bc_p); + *bc_p += sizeof (uint32_t); + return value; +} /* re_get_value */ + +/** + * Append a character to the RegExp bytecode + */ +void +re_append_char (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const lit_code_point_t cp) /**< code point */ +{ + const size_t size = (re_ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t); + uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, size); + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + re_encode_u32 (dest_p, cp); + return; + } + + JERRY_ASSERT (cp <= LIT_UTF16_CODE_UNIT_MAX); + re_encode_u16 (dest_p, (ecma_char_t) cp); +} /* re_append_char */ + +/** + * Append a character to the RegExp bytecode + */ +void +re_insert_char (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint32_t offset, /**< bytecode offset */ + const lit_code_point_t cp) /**< code point*/ +{ + const size_t size = (re_ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t); + + uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, size); + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + re_encode_u32 (dest_p, cp); + return; + } + + JERRY_ASSERT (cp <= LIT_UTF16_CODE_UNIT_MAX); + re_encode_u16 (dest_p, (ecma_char_t) cp); +} /* re_insert_char */ + +/** + * Decode a character from the bytecode. + * + * @return decoded character + */ +lit_code_point_t +re_get_char (const uint8_t **bc_p, /**< reference to bytecode pointer */ + bool unicode) /**< full unicode mode */ +{ + lit_code_point_t cp; + + if (unicode) + { + cp = re_decode_u32 (*bc_p); + *bc_p += sizeof (lit_code_point_t); + } + else + { + cp = re_decode_u16 (*bc_p); + *bc_p += sizeof (ecma_char_t); + } + + return cp; +} /* re_get_char */ + +#if JERRY_REGEXP_DUMP_BYTE_CODE +static uint32_t +re_get_bytecode_offset (const uint8_t *start_p, /**< bytecode start pointer */ + const uint8_t *current_p) /**< current bytecode pointer */ +{ + return (uint32_t) ((uintptr_t) current_p - (uintptr_t) start_p); +} /* re_get_bytecode_offset */ + +/** + * RegExp bytecode dumper + */ +void +re_dump_bytecode (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */ +{ + static const char escape_chars[] = { 'd', 'D', 'w', 'W', 's', 'S' }; + + re_compiled_code_t *compiled_code_p = (re_compiled_code_t *) re_ctx_p->bytecode_start_p; + JERRY_DEBUG_MSG ("Flags: 0x%x ", compiled_code_p->header.status_flags); + JERRY_DEBUG_MSG ("Capturing groups: %d ", compiled_code_p->captures_count); + JERRY_DEBUG_MSG ("Non-capturing groups: %d\n", compiled_code_p->non_captures_count); + + const uint8_t *bytecode_start_p = (const uint8_t *) (compiled_code_p + 1); + const uint8_t *bytecode_p = bytecode_start_p; + + while (true) + { + JERRY_DEBUG_MSG ("[%3u] ", (uint32_t) ((uintptr_t) bytecode_p - (uintptr_t) bytecode_start_p)); + re_opcode_t op = *bytecode_p++; + switch (op) + { + case RE_OP_ALTERNATIVE_START: + { + JERRY_DEBUG_MSG ("ALTERNATIVE_START "); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_ALTERNATIVE_NEXT: + { + JERRY_DEBUG_MSG ("ALTERNATIVE_NEXT "); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_NO_ALTERNATIVE: + { + JERRY_DEBUG_MSG ("NO_ALTERNATIVES\n"); + break; + } + case RE_OP_CAPTURING_GROUP_START: + { + JERRY_DEBUG_MSG ("CAPTURING_GROUP_START "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p)); + + const uint32_t qmin = re_get_value (&bytecode_p); + JERRY_DEBUG_MSG ("qmin: %u", qmin); + if (qmin == 0) + { + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG (", tail offset: [%3u]\n", offset); + } + else + { + JERRY_DEBUG_MSG ("\n"); + } + + break; + } + case RE_OP_NON_CAPTURING_GROUP_START: + { + JERRY_DEBUG_MSG ("NON_CAPTURING_GROUP_START "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p)); + + const uint32_t qmin = re_get_value (&bytecode_p); + JERRY_DEBUG_MSG ("qmin: %u", qmin); + if (qmin == 0) + { + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG (", tail offset: [%3u]\n", offset); + } + else + { + JERRY_DEBUG_MSG ("\n"); + } + + break; + } + case RE_OP_GREEDY_CAPTURING_GROUP_END: + { + JERRY_DEBUG_MSG ("GREEDY_CAPTURING_GROUP_END "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + break; + } + case RE_OP_LAZY_CAPTURING_GROUP_END: + { + JERRY_DEBUG_MSG ("LAZY_CAPTURING_GROUP_END "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + break; + } + case RE_OP_GREEDY_NON_CAPTURING_GROUP_END: + { + JERRY_DEBUG_MSG ("GREEDY_NON_CAPTURING_GROUP_END "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + break; + } + case RE_OP_LAZY_NON_CAPTURING_GROUP_END: + { + JERRY_DEBUG_MSG ("LAZY_NON_CAPTURING_GROUP_END "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + break; + } + case RE_OP_GREEDY_ITERATOR: + { + JERRY_DEBUG_MSG ("GREEDY_ITERATOR "); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u, ", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_LAZY_ITERATOR: + { + JERRY_DEBUG_MSG ("LAZY_ITERATOR "); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u, ", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_ITERATOR_END: + { + JERRY_DEBUG_MSG ("ITERATOR_END\n"); + break; + } + case RE_OP_BACKREFERENCE: + { + JERRY_DEBUG_MSG ("BACKREFERENCE "); + JERRY_DEBUG_MSG ("idx: %d\n", re_get_value (&bytecode_p)); + break; + } + case RE_OP_ASSERT_LINE_START: + { + JERRY_DEBUG_MSG ("ASSERT_LINE_START\n"); + break; + } + case RE_OP_ASSERT_LINE_END: + { + JERRY_DEBUG_MSG ("ASSERT_LINE_END\n"); + break; + } + case RE_OP_ASSERT_LOOKAHEAD_POS: + { + JERRY_DEBUG_MSG ("ASSERT_LOOKAHEAD_POS "); + JERRY_DEBUG_MSG ("qmin: %u, ", *bytecode_p++); + JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p)); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_ASSERT_LOOKAHEAD_NEG: + { + JERRY_DEBUG_MSG ("ASSERT_LOOKAHEAD_NEG "); + JERRY_DEBUG_MSG ("qmin: %u, ", *bytecode_p++); + JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p)); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_ASSERT_END: + { + JERRY_DEBUG_MSG ("ASSERT_END\n"); + break; + } + case RE_OP_ASSERT_WORD_BOUNDARY: + { + JERRY_DEBUG_MSG ("ASSERT_WORD_BOUNDARY\n"); + break; + } + case RE_OP_ASSERT_NOT_WORD_BOUNDARY: + { + JERRY_DEBUG_MSG ("ASSERT_NOT_WORD_BOUNDARY\n"); + break; + } + case RE_OP_CLASS_ESCAPE: + { + ecma_class_escape_t escape = (ecma_class_escape_t) *bytecode_p++; + JERRY_DEBUG_MSG ("CLASS_ESCAPE \\%c\n", escape_chars[escape]); + break; + } + case RE_OP_CHAR_CLASS: + { + JERRY_DEBUG_MSG ("CHAR_CLASS "); + uint8_t flags = *bytecode_p++; + uint32_t char_count = (flags & RE_CLASS_HAS_CHARS) ? re_get_value (&bytecode_p) : 0; + uint32_t range_count = (flags & RE_CLASS_HAS_RANGES) ? re_get_value (&bytecode_p) : 0; + + if (flags & RE_CLASS_INVERT) + { + JERRY_DEBUG_MSG ("inverted "); + } + + JERRY_DEBUG_MSG ("escapes: "); + uint8_t escape_count = flags & RE_CLASS_ESCAPE_COUNT_MASK; + while (escape_count--) + { + JERRY_DEBUG_MSG ("\\%c, ", escape_chars[*bytecode_p++]); + } + + JERRY_DEBUG_MSG ("chars: "); + while (char_count--) + { + JERRY_DEBUG_MSG ("\\u%04x, ", re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE)); + } + + JERRY_DEBUG_MSG ("ranges: "); + while (range_count--) + { + const lit_code_point_t begin = re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE); + const lit_code_point_t end = re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE); + JERRY_DEBUG_MSG ("\\u%04x-\\u%04x, ", begin, end); + } + + JERRY_DEBUG_MSG ("\n"); + break; + } + case RE_OP_UNICODE_PERIOD: + { + JERRY_DEBUG_MSG ("UNICODE_PERIOD\n"); + break; + } + case RE_OP_PERIOD: + { + JERRY_DEBUG_MSG ("PERIOD\n"); + break; + } + case RE_OP_CHAR: + { + JERRY_DEBUG_MSG ("CHAR \\u%04x\n", re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE)); + break; + } + case RE_OP_BYTE: + { + const uint8_t ch = *bytecode_p++; + JERRY_DEBUG_MSG ("BYTE \\u%04x '%c'\n", ch, (char) ch); + break; + } + case RE_OP_EOF: + { + JERRY_DEBUG_MSG ("EOF\n"); + return; + } + default: + { + JERRY_DEBUG_MSG ("UNKNOWN(%d)\n", (uint32_t) op); + break; + } + } + } +} /* re_dump_bytecode */ +#endif /* JERRY_REGEXP_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.h b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.h new file mode 100644 index 00000000..9fd8456d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.h @@ -0,0 +1,131 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RE_BYTECODE_H +#define RE_BYTECODE_H + +#include "ecma-globals.h" + +#include "re-compiler-context.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_bytecode Bytecode + * @{ + */ + +/** + * Size of the RegExp bytecode cache + */ +#define RE_CACHE_SIZE 8u + +/** + * Maximum value that can be encoded in the RegExp bytecode as a single byte. + */ +#define RE_VALUE_1BYTE_MAX 0xFE + +/** + * Marker that signals that the actual value is enocded in the following 4 bytes in the bytecode. + */ +#define RE_VALUE_4BYTE_MARKER 0xFF + +/** + * RegExp opcodes + */ +typedef enum +{ + RE_OP_EOF, /**< end of pattern */ + + RE_OP_ALTERNATIVE_START, /**< start of alternatives */ + RE_OP_ALTERNATIVE_NEXT, /**< next alternative */ + RE_OP_NO_ALTERNATIVE, /**< no alternative */ + + RE_OP_CAPTURING_GROUP_START, /**< start of a capturing group */ + RE_OP_NON_CAPTURING_GROUP_START, /**< start of a non-capturing group */ + + RE_OP_GREEDY_CAPTURING_GROUP_END, /**< end of a greedy capturing group */ + RE_OP_GREEDY_NON_CAPTURING_GROUP_END, /**< end of a greedy non-capturing group */ + RE_OP_LAZY_CAPTURING_GROUP_END, /**< end of a lazy capturing group */ + RE_OP_LAZY_NON_CAPTURING_GROUP_END, /**< end of a lazy non-capturing group */ + + RE_OP_GREEDY_ITERATOR, /**< greedy iterator */ + RE_OP_LAZY_ITERATOR, /**< lazy iterator */ + RE_OP_ITERATOR_END, /*** end of an iterator */ + + RE_OP_BACKREFERENCE, /**< backreference */ + + RE_OP_ASSERT_LINE_START, /**< line start assertion */ + RE_OP_ASSERT_LINE_END, /**< line end assertion */ + RE_OP_ASSERT_WORD_BOUNDARY, /**< word boundary assertion */ + RE_OP_ASSERT_NOT_WORD_BOUNDARY, /**< not word boundary assertion */ + RE_OP_ASSERT_LOOKAHEAD_POS, /**< positive lookahead assertion */ + RE_OP_ASSERT_LOOKAHEAD_NEG, /**< negative lookahead assertion */ + RE_OP_ASSERT_END, /**< end of an assertion */ + + RE_OP_CLASS_ESCAPE, /**< class escape */ + RE_OP_CHAR_CLASS, /**< character class */ + RE_OP_UNICODE_PERIOD, /**< period in full unicode mode */ + RE_OP_PERIOD, /**< period in non-unicode mode */ + RE_OP_CHAR, /**< any code point */ + RE_OP_BYTE, /**< 1-byte utf8 character */ +} re_opcode_t; + +/** + * Compiled byte code data. + */ +typedef struct +{ + ecma_compiled_code_t header; /**< compiled code header */ + uint32_t captures_count; /**< number of capturing groups */ + uint32_t non_captures_count; /**< number of non-capturing groups */ + ecma_value_t source; /**< original RegExp pattern */ +} re_compiled_code_t; + +void re_initialize_regexp_bytecode (re_compiler_ctx_t *re_ctx_p); +uint32_t re_bytecode_size (re_compiler_ctx_t *re_ctx_p); + +void re_append_opcode (re_compiler_ctx_t *re_ctx_p, const re_opcode_t opcode); +void re_append_byte (re_compiler_ctx_t *re_ctx_p, const uint8_t byte); +void re_append_char (re_compiler_ctx_t *re_ctx_p, const lit_code_point_t cp); +void re_append_value (re_compiler_ctx_t *re_ctx_p, const uint32_t value); + +void re_insert_opcode (re_compiler_ctx_t *re_ctx_p, const uint32_t offset, const re_opcode_t opcode); +void re_insert_byte (re_compiler_ctx_t *re_ctx_p, const uint32_t offset, const uint8_t byte); +void re_insert_char (re_compiler_ctx_t *re_ctx_p, const uint32_t offset, const lit_code_point_t cp); +void re_insert_value (re_compiler_ctx_t *re_ctx_p, const uint32_t offset, const uint32_t value); + +re_opcode_t re_get_opcode (const uint8_t **bc_p); +uint8_t re_get_byte (const uint8_t **bc_p); +lit_code_point_t re_get_char (const uint8_t **bc_p, bool unicode); +uint32_t re_get_value (const uint8_t **bc_p); + +#if JERRY_REGEXP_DUMP_BYTE_CODE +void re_dump_bytecode (re_compiler_ctx_t *bc_ctx); +#endif /* JERRY_REGEXP_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !RE_BYTECODE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler-context.h b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler-context.h new file mode 100644 index 00000000..b7dbb029 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler-context.h @@ -0,0 +1,60 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RE_COMPILER_CONTEXT_H +#define RE_COMPILER_CONTEXT_H + +#include "re-token.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_compiler Compiler + * @{ + */ + +/** + * RegExp compiler context + */ +typedef struct +{ + const lit_utf8_byte_t *input_start_p; /**< start of input pattern */ + const lit_utf8_byte_t *input_curr_p; /**< current position in input pattern */ + const lit_utf8_byte_t *input_end_p; /**< end of input pattern */ + + uint8_t *bytecode_start_p; /**< start of bytecode block */ + size_t bytecode_size; /**< size of bytecode */ + + uint32_t captures_count; /**< number of capture groups */ + uint32_t non_captures_count; /**< number of non-capture groups */ + + int groups_count; /**< number of groups */ + uint16_t flags; /**< RegExp flags */ + re_token_t token; /**< current token */ +} re_compiler_ctx_t; + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !RE_COMPILER_CONTEXT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.cpp new file mode 100644 index 00000000..a495616b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.cpp @@ -0,0 +1,184 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "re-compiler.h" + +#include "ecma-exceptions.h" +#include "ecma-helpers.h" +#include "ecma-regexp-object.h" + +#include "jcontext.h" +#include "jmem.h" +#include "jrt-libc-includes.h" +#include "lit-char-helpers.h" +#include "re-bytecode.h" +#include "re-compiler-context.h" +#include "re-parser.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_compiler Compiler + * @{ + */ + +/** + * Search for the given pattern in the RegExp cache. + * + * @return pointer to bytecode if found + * NULL - otherwise + */ +static re_compiled_code_t * +re_cache_lookup (ecma_string_t *pattern_str_p, /**< pattern string */ + uint16_t flags) /**< flags */ +{ + re_compiled_code_t **cache_p = JERRY_CONTEXT (re_cache); + + for (uint8_t idx = 0u; idx < RE_CACHE_SIZE; idx++) + { + re_compiled_code_t *cached_bytecode_p = cache_p[idx]; + + if (cached_bytecode_p == NULL) + { + break; + } + + ecma_string_t *cached_pattern_str_p = ecma_get_string_from_value (cached_bytecode_p->source); + + if (cached_bytecode_p->header.status_flags == flags + && ecma_compare_ecma_strings (cached_pattern_str_p, pattern_str_p)) + { + return cached_bytecode_p; + } + } + + return NULL; +} /* re_cache_lookup */ + +/** + * Run garbage collection in RegExp cache. + */ +void +re_cache_gc (void) +{ + re_compiled_code_t **cache_p = JERRY_CONTEXT (re_cache); + + for (uint32_t i = 0u; i < RE_CACHE_SIZE; i++) + { + const re_compiled_code_t *cached_bytecode_p = cache_p[i]; + + if (cached_bytecode_p == NULL) + { + break; + } + + ecma_bytecode_deref ((ecma_compiled_code_t *) cached_bytecode_p); + cache_p[i] = NULL; + } + + JERRY_CONTEXT (re_cache_idx) = 0; +} /* re_cache_gc */ + +/** + * Compilation of RegExp bytecode + * + * @return pointer to bytecode if compilation was successful + * NULL - otherwise + */ +re_compiled_code_t * +re_compile_bytecode (ecma_string_t *pattern_str_p, /**< pattern */ + uint16_t flags) /**< flags */ +{ + re_compiled_code_t *cached_bytecode_p = re_cache_lookup (pattern_str_p, flags); + + if (cached_bytecode_p != NULL) + { + ecma_bytecode_ref ((ecma_compiled_code_t *) cached_bytecode_p); + return cached_bytecode_p; + } + + re_compiler_ctx_t re_ctx; + re_ctx.flags = flags; + re_ctx.captures_count = 1; + re_ctx.non_captures_count = 0; + + re_initialize_regexp_bytecode (&re_ctx); + + ECMA_STRING_TO_UTF8_STRING (pattern_str_p, pattern_start_p, pattern_start_size); + + re_ctx.input_start_p = pattern_start_p; + re_ctx.input_curr_p = (lit_utf8_byte_t *) pattern_start_p; + re_ctx.input_end_p = pattern_start_p + pattern_start_size; + re_ctx.groups_count = -1; + + /* Parse RegExp pattern */ + ecma_value_t result = re_parse_alternative (&re_ctx, true); + + ECMA_FINALIZE_UTF8_STRING (pattern_start_p, pattern_start_size); + + if (ECMA_IS_VALUE_ERROR (result)) + { + /* Compilation failed, free bytecode. */ + jmem_heap_free_block (re_ctx.bytecode_start_p, re_ctx.bytecode_size); + return NULL; + } + + /* Align bytecode size to JMEM_ALIGNMENT so that it can be stored in the bytecode header. */ + const uint32_t final_size = JERRY_ALIGNUP (re_ctx.bytecode_size, JMEM_ALIGNMENT); + re_compiled_code_t *re_compiled_code_p = + (re_compiled_code_t *) jmem_heap_realloc_block (re_ctx.bytecode_start_p, re_ctx.bytecode_size, final_size); + + /* Bytecoded will be inserted into the cache and returned to the caller, so refcount is implicitly set to 2. */ + re_compiled_code_p->header.refs = 2; + re_compiled_code_p->header.size = (uint16_t) (final_size >> JMEM_ALIGNMENT_LOG); + re_compiled_code_p->header.status_flags = re_ctx.flags; + + ecma_ref_ecma_string (pattern_str_p); + re_compiled_code_p->source = ecma_make_string_value (pattern_str_p); + re_compiled_code_p->captures_count = re_ctx.captures_count; + re_compiled_code_p->non_captures_count = re_ctx.non_captures_count; + +#if JERRY_REGEXP_DUMP_BYTE_CODE + if (JERRY_CONTEXT (jerry_init_flags) & JERRY_INIT_SHOW_REGEXP_OPCODES) + { + re_dump_bytecode (&re_ctx); + } +#endif /* JERRY_REGEXP_DUMP_BYTE_CODE */ + + uint8_t cache_idx = JERRY_CONTEXT (re_cache_idx); + + if (JERRY_CONTEXT (re_cache)[cache_idx] != NULL) + { + ecma_bytecode_deref ((ecma_compiled_code_t *) JERRY_CONTEXT (re_cache)[cache_idx]); + } + + JERRY_CONTEXT (re_cache)[cache_idx] = re_compiled_code_p; + JERRY_CONTEXT (re_cache_idx) = (uint8_t) (cache_idx + 1) % RE_CACHE_SIZE; + + return re_compiled_code_p; +} /* re_compile_bytecode */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.h b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.h new file mode 100644 index 00000000..ace781ef --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.h @@ -0,0 +1,46 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RE_COMPILER_H +#define RE_COMPILER_H + +#include "ecma-globals.h" + +#include "re-bytecode.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_compiler Compiler + * @{ + */ + +re_compiled_code_t *re_compile_bytecode (ecma_string_t *pattern_str_p, uint16_t flags); + +void re_cache_gc (void); + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !RE_COMPILER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.cpp new file mode 100644 index 00000000..93114df4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.cpp @@ -0,0 +1,1327 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "re-parser.h" + +#include "ecma-exceptions.h" +#include "ecma-globals.h" + +#include "jcontext.h" +#include "jrt-libc-includes.h" +#include "lit-char-helpers.h" +#include "re-compiler.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_parser Parser + * @{ + */ + +/** + * Get the start opcode for the current group. + * + * @return RegExp opcode + */ +static re_opcode_t +re_get_group_start_opcode (bool is_capturing) /**< is capturing group */ +{ + return (is_capturing) ? RE_OP_CAPTURING_GROUP_START : RE_OP_NON_CAPTURING_GROUP_START; +} /* re_get_group_start_opcode */ + +/** + * Get the end opcode for the current group. + * + * @return RegExp opcode + */ +static re_opcode_t +re_get_group_end_opcode (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + bool is_capturing) /**< is capturing group */ +{ + if (is_capturing) + { + if (re_ctx_p->token.greedy) + { + return RE_OP_GREEDY_CAPTURING_GROUP_END; + } + + return RE_OP_LAZY_CAPTURING_GROUP_END; + } + + if (re_ctx_p->token.greedy) + { + return RE_OP_GREEDY_NON_CAPTURING_GROUP_END; + } + + return RE_OP_LAZY_NON_CAPTURING_GROUP_END; +} /* re_get_group_end_opcode */ + +/** + * Enclose the given bytecode to a group. + */ +static void +re_insert_into_group (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + uint32_t group_start_offset, /**< offset of group start */ + uint32_t idx, /**< index of group */ + uint32_t capture_start, /**< index of first nested capture */ + bool is_capturing) /**< is capturing group */ +{ + uint32_t qmin = re_ctx_p->token.qmin; + uint32_t qmax = re_ctx_p->token.qmax; + + if (JERRY_UNLIKELY (!is_capturing && re_bytecode_size (re_ctx_p) == group_start_offset)) + { + return; + } + + if (qmin == 0) + { + re_insert_value (re_ctx_p, group_start_offset, re_bytecode_size (re_ctx_p) - group_start_offset); + } + + re_insert_value (re_ctx_p, group_start_offset, qmin); + re_insert_value (re_ctx_p, group_start_offset, re_ctx_p->captures_count - capture_start); + + if (!is_capturing) + { + re_insert_value (re_ctx_p, group_start_offset, capture_start); + } + else + { + JERRY_ASSERT (idx == capture_start); + } + + re_insert_value (re_ctx_p, group_start_offset, idx); + re_insert_opcode (re_ctx_p, group_start_offset, re_get_group_start_opcode (is_capturing)); + + re_append_opcode (re_ctx_p, re_get_group_end_opcode (re_ctx_p, is_capturing)); + re_append_value (re_ctx_p, idx); + re_append_value (re_ctx_p, qmin); + re_append_value (re_ctx_p, qmax + RE_QMAX_OFFSET); +} /* re_insert_into_group */ + +/** + * Insert simple atom iterator. + */ +static void +re_insert_atom_iterator (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + uint32_t start_offset) /**< atom start offset */ +{ + const uint32_t qmin = re_ctx_p->token.qmin; + const uint32_t qmax = re_ctx_p->token.qmax; + + if (qmin == 1 && qmax == 1) + { + return; + } + + re_append_opcode (re_ctx_p, RE_OP_ITERATOR_END); + re_insert_value (re_ctx_p, start_offset, re_bytecode_size (re_ctx_p) - start_offset); + re_insert_value (re_ctx_p, start_offset, qmax + RE_QMAX_OFFSET); + re_insert_value (re_ctx_p, start_offset, qmin); + re_insert_opcode (re_ctx_p, start_offset, re_ctx_p->token.greedy ? RE_OP_GREEDY_ITERATOR : RE_OP_LAZY_ITERATOR); +} /* re_insert_atom_iterator */ + +/** + * Insert a lookahead assertion. + */ +static void +re_insert_assertion_lookahead (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + uint32_t start_offset, /**< atom start offset */ + uint32_t capture_start, /**< index of first nested capture */ + bool negative) /** lookahead type */ +{ + const uint32_t qmin = re_ctx_p->token.qmin; + + re_append_opcode (re_ctx_p, RE_OP_ASSERT_END); + re_insert_value (re_ctx_p, start_offset, re_bytecode_size (re_ctx_p) - start_offset); + + /* We need to clear nested capturing group results when a negative assertion or the tail after a positive assertion + * does not match, so we store the begin and end index of nested capturing groups. */ + re_insert_value (re_ctx_p, start_offset, re_ctx_p->captures_count - capture_start); + re_insert_value (re_ctx_p, start_offset, capture_start); + + /* Lookaheads always result in zero length matches, which means iterations will always stop on the first match. + * This allows us to not have to deal with iterations beyond one. Either qmin == 0 which will implicitly match, + * or qmin > 0, in which case the first iteration will decide whether the assertion matches depending on whether + * the iteration matched or not. This also allows us to ignore qmax entirely. */ + re_insert_byte (re_ctx_p, start_offset, (uint8_t) JERRY_MIN (qmin, 1)); + + const re_opcode_t opcode = (negative) ? RE_OP_ASSERT_LOOKAHEAD_NEG : RE_OP_ASSERT_LOOKAHEAD_POS; + re_insert_opcode (re_ctx_p, start_offset, opcode); +} /* re_insert_assertion_lookahead */ + +/** + * Consume non greedy (question mark) character if present. + */ +static void +re_parse_lazy_char (re_compiler_ctx_t *re_ctx_p) /**< RegExp parser context */ +{ + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && *re_ctx_p->input_curr_p == LIT_CHAR_QUESTION) + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.greedy = false; + return; + } + + re_ctx_p->token.greedy = true; +} /* re_parse_lazy_char */ + +/** + * Parse a max 3 digit long octal number from the input string, with a decimal value less than 256. + * + * @return value of the octal number + */ +static uint32_t +re_parse_octal (re_compiler_ctx_t *re_ctx_p) /**< RegExp parser context */ +{ + JERRY_ASSERT (re_ctx_p->input_curr_p < re_ctx_p->input_end_p); + JERRY_ASSERT (lit_char_is_octal_digit (*re_ctx_p->input_curr_p)); + + uint32_t value = (uint32_t) (*re_ctx_p->input_curr_p++) - LIT_CHAR_0; + + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && lit_char_is_octal_digit (*re_ctx_p->input_curr_p)) + { + value = value * 8 + (*re_ctx_p->input_curr_p++) - LIT_CHAR_0; + } + + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && lit_char_is_octal_digit (*re_ctx_p->input_curr_p)) + { + const uint32_t new_value = value * 8 + (*re_ctx_p->input_curr_p) - LIT_CHAR_0; + + if (new_value <= RE_MAX_OCTAL_VALUE) + { + value = new_value; + re_ctx_p->input_curr_p++; + } + } + + return value; +} /* re_parse_octal */ + +/** + * Check that the currently parsed quantifier is valid. + * + * @return ECMA_VALUE_ERROR, if quantifier is invalid + * ECMA_VALUE_EMPTY, otherwise + */ +static ecma_value_t +re_check_quantifier (re_compiler_ctx_t *re_ctx_p) +{ + if (re_ctx_p->token.qmin > re_ctx_p->token.qmax) + { + /* ECMA-262 v5.1 15.10.2.5 */ + return ecma_raise_syntax_error (ECMA_ERR_MIN_GREATER_THAN_MAX); + } + + return ECMA_VALUE_EMPTY; +} /* re_check_quantifier */ + +/** + * Parse RegExp quantifier. + * + * @return ECMA_VALUE_TRUE - if parsed successfully + * ECMA_VALUE_FALSE - otherwise + */ +static ecma_value_t +re_parse_quantifier (re_compiler_ctx_t *re_ctx_p) /**< RegExp compiler context */ +{ + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p) + { + switch (*re_ctx_p->input_curr_p) + { + case LIT_CHAR_QUESTION: + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.qmin = 0; + re_ctx_p->token.qmax = 1; + + re_parse_lazy_char (re_ctx_p); + return ECMA_VALUE_TRUE; + } + case LIT_CHAR_ASTERISK: + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.qmin = 0; + re_ctx_p->token.qmax = RE_INFINITY; + + re_parse_lazy_char (re_ctx_p); + return ECMA_VALUE_TRUE; + } + case LIT_CHAR_PLUS: + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.qmin = 1; + re_ctx_p->token.qmax = RE_INFINITY; + + re_parse_lazy_char (re_ctx_p); + return ECMA_VALUE_TRUE; + } + case LIT_CHAR_LEFT_BRACE: + { + const lit_utf8_byte_t *current_p = re_ctx_p->input_curr_p + 1; + uint32_t qmin = 0; + uint32_t qmax = RE_INFINITY; + + if (current_p >= re_ctx_p->input_end_p) + { + break; + } + + if (!lit_char_is_decimal_digit (*current_p)) + { + break; + } + + qmin = lit_parse_decimal (¤t_p, re_ctx_p->input_end_p); + + if (current_p >= re_ctx_p->input_end_p) + { + break; + } + + lit_utf8_byte_t ch = *current_p++; + if (ch == LIT_CHAR_RIGHT_BRACE) + { + qmax = qmin; + } + else if (ch == LIT_CHAR_COMMA) + { + if (current_p >= re_ctx_p->input_end_p) + { + break; + } + + if (lit_char_is_decimal_digit (*current_p)) + { + qmax = lit_parse_decimal (¤t_p, re_ctx_p->input_end_p); + } + + if (current_p >= re_ctx_p->input_end_p || *current_p++ != LIT_CHAR_RIGHT_BRACE) + { + break; + } + } + else + { + break; + } + + re_ctx_p->token.qmin = qmin; + re_ctx_p->token.qmax = qmax; + re_ctx_p->input_curr_p = current_p; + re_parse_lazy_char (re_ctx_p); + return ECMA_VALUE_TRUE; + } + default: + { + break; + } + } + } + + re_ctx_p->token.qmin = 1; + re_ctx_p->token.qmax = 1; + re_ctx_p->token.greedy = true; + + return ECMA_VALUE_FALSE; +} /* re_parse_quantifier */ + +/** + * Count the number of groups in the current pattern. + */ +static void +re_count_groups (re_compiler_ctx_t *re_ctx_p) /**< RegExp compiler context */ +{ + bool is_char_class = 0; + re_ctx_p->groups_count = 0; + const lit_utf8_byte_t *curr_p = re_ctx_p->input_start_p; + + while (curr_p < re_ctx_p->input_end_p) + { + switch (*curr_p++) + { + case LIT_CHAR_BACKSLASH: + { + if (curr_p < re_ctx_p->input_end_p) + { + lit_utf8_incr (&curr_p); + } + break; + } + case LIT_CHAR_LEFT_SQUARE: + { + is_char_class = true; + break; + } + case LIT_CHAR_RIGHT_SQUARE: + { + is_char_class = false; + break; + } + case LIT_CHAR_LEFT_PAREN: + { + if (curr_p < re_ctx_p->input_end_p && *curr_p != LIT_CHAR_QUESTION && !is_char_class) + { + re_ctx_p->groups_count++; + } + break; + } + } + } +} /* re_count_groups */ + +/** + * Check if a code point is a Syntax character + * + * @return true, if syntax character + * false, otherwise + */ +static bool +re_is_syntax_char (lit_code_point_t cp) /**< code point */ +{ + return (cp == LIT_CHAR_CIRCUMFLEX || cp == LIT_CHAR_DOLLAR_SIGN || cp == LIT_CHAR_BACKSLASH || cp == LIT_CHAR_DOT + || cp == LIT_CHAR_ASTERISK || cp == LIT_CHAR_PLUS || cp == LIT_CHAR_QUESTION || cp == LIT_CHAR_LEFT_PAREN + || cp == LIT_CHAR_RIGHT_PAREN || cp == LIT_CHAR_LEFT_SQUARE || cp == LIT_CHAR_RIGHT_SQUARE + || cp == LIT_CHAR_LEFT_BRACE || cp == LIT_CHAR_RIGHT_BRACE || cp == LIT_CHAR_VLINE); +} /* re_is_syntax_char */ + +/** + * Parse a Character Escape or a Character Class Escape. + * + * @return ECMA_VALUE_EMPTY, if parsed successfully + * ECMA_VALUE_ERROR, otherwise + */ +static ecma_value_t +re_parse_char_escape (re_compiler_ctx_t *re_ctx_p) /**< RegExp compiler context */ +{ + JERRY_ASSERT (re_ctx_p->input_curr_p < re_ctx_p->input_end_p); + re_ctx_p->token.type = RE_TOK_CHAR; + + if (lit_char_is_decimal_digit (*re_ctx_p->input_curr_p)) + { + /* NULL code point escape, only valid if there are no following digits. */ + if (*re_ctx_p->input_curr_p == LIT_CHAR_0 + && (re_ctx_p->input_curr_p + 1 >= re_ctx_p->input_end_p + || !lit_char_is_decimal_digit (re_ctx_p->input_curr_p[1]))) + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.value = LIT_UNICODE_CODE_POINT_NULL; + return ECMA_VALUE_EMPTY; + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_ESCAPE_SEQUENCE); + } + + /* Legacy octal escape sequence */ + if (lit_char_is_octal_digit (*re_ctx_p->input_curr_p)) + { + re_ctx_p->token.value = re_parse_octal (re_ctx_p); + return ECMA_VALUE_EMPTY; + } + + /* Identity escape */ + re_ctx_p->token.value = *re_ctx_p->input_curr_p++; + return ECMA_VALUE_EMPTY; + } + + lit_code_point_t ch = lit_cesu8_read_next (&re_ctx_p->input_curr_p); + switch (ch) + { + /* Character Class escapes */ + case LIT_CHAR_LOWERCASE_D: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_DIGIT; + break; + } + case LIT_CHAR_UPPERCASE_D: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_NOT_DIGIT; + break; + } + case LIT_CHAR_LOWERCASE_S: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_WHITESPACE; + break; + } + case LIT_CHAR_UPPERCASE_S: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_NOT_WHITESPACE; + break; + } + case LIT_CHAR_LOWERCASE_W: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_WORD_CHAR; + break; + } + case LIT_CHAR_UPPERCASE_W: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_NOT_WORD_CHAR; + break; + } + /* Control escapes */ + case LIT_CHAR_LOWERCASE_F: + { + re_ctx_p->token.value = LIT_CHAR_FF; + break; + } + case LIT_CHAR_LOWERCASE_N: + { + re_ctx_p->token.value = LIT_CHAR_LF; + break; + } + case LIT_CHAR_LOWERCASE_R: + { + re_ctx_p->token.value = LIT_CHAR_CR; + break; + } + case LIT_CHAR_LOWERCASE_T: + { + re_ctx_p->token.value = LIT_CHAR_TAB; + break; + } + case LIT_CHAR_LOWERCASE_V: + { + re_ctx_p->token.value = LIT_CHAR_VTAB; + break; + } + /* Control letter */ + case LIT_CHAR_LOWERCASE_C: + { + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p) + { + ch = *re_ctx_p->input_curr_p; + + if ((ch >= LIT_CHAR_ASCII_UPPERCASE_LETTERS_BEGIN && ch <= LIT_CHAR_ASCII_UPPERCASE_LETTERS_END) + || (ch >= LIT_CHAR_ASCII_LOWERCASE_LETTERS_BEGIN && ch <= LIT_CHAR_ASCII_LOWERCASE_LETTERS_END)) + { + re_ctx_p->token.value = (ch % 32); + re_ctx_p->input_curr_p++; + + break; + } + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_CONTROL_ESCAPE_SEQUENCE); + } + + re_ctx_p->token.value = LIT_CHAR_BACKSLASH; + re_ctx_p->input_curr_p--; + + break; + } + /* Hex escape */ + case LIT_CHAR_LOWERCASE_X: + { + uint32_t hex_value = lit_char_hex_lookup (re_ctx_p->input_curr_p, re_ctx_p->input_end_p, 2); + if (hex_value != UINT32_MAX) + { + re_ctx_p->token.value = hex_value; + re_ctx_p->input_curr_p += 2; + break; + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_HEX_ESCAPE_SEQUENCE); + } + + re_ctx_p->token.value = LIT_CHAR_LOWERCASE_X; + break; + } + /* Unicode escape */ + case LIT_CHAR_LOWERCASE_U: + { + uint32_t hex_value = lit_char_hex_lookup (re_ctx_p->input_curr_p, re_ctx_p->input_end_p, 4); + if (hex_value != UINT32_MAX) + { + re_ctx_p->token.value = hex_value; + re_ctx_p->input_curr_p += 4; + + if (re_ctx_p->flags & RE_FLAG_UNICODE && lit_is_code_point_utf16_high_surrogate (re_ctx_p->token.value) + && re_ctx_p->input_curr_p + 6 <= re_ctx_p->input_end_p && re_ctx_p->input_curr_p[0] == '\\' + && re_ctx_p->input_curr_p[1] == 'u') + { + hex_value = lit_char_hex_lookup (re_ctx_p->input_curr_p + 2, re_ctx_p->input_end_p, 4); + if (lit_is_code_point_utf16_low_surrogate (hex_value)) + { + re_ctx_p->token.value = + lit_convert_surrogate_pair_to_code_point ((ecma_char_t) re_ctx_p->token.value, (ecma_char_t) hex_value); + re_ctx_p->input_curr_p += 6; + } + } + + break; + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + if (re_ctx_p->input_curr_p + 1 < re_ctx_p->input_end_p && re_ctx_p->input_curr_p[0] == LIT_CHAR_LEFT_BRACE + && lit_char_is_hex_digit (re_ctx_p->input_curr_p[1])) + { + lit_code_point_t cp = lit_char_hex_to_int (re_ctx_p->input_curr_p[1]); + re_ctx_p->input_curr_p += 2; + + while (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && lit_char_is_hex_digit (*re_ctx_p->input_curr_p)) + { + cp = cp * 16 + lit_char_hex_to_int (*re_ctx_p->input_curr_p++); + + if (JERRY_UNLIKELY (cp > LIT_UNICODE_CODE_POINT_MAX)) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE); + } + } + + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && *re_ctx_p->input_curr_p == LIT_CHAR_RIGHT_BRACE) + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.value = cp; + break; + } + } + + return ecma_raise_syntax_error (ECMA_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE); + } + + re_ctx_p->token.value = LIT_CHAR_LOWERCASE_U; + break; + } + /* Identity escape */ + default: + { + /* Must be '/', or one of SyntaxCharacter */ + if (re_ctx_p->flags & RE_FLAG_UNICODE && ch != LIT_CHAR_SLASH && !re_is_syntax_char (ch)) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_ESCAPE); + } + re_ctx_p->token.value = ch; + } + } + + return ECMA_VALUE_EMPTY; +} /* re_parse_char_escape */ + +/** + * Read the input pattern and parse the next token for the RegExp compiler + * + * @return empty ecma value - if parsed successfully + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +re_parse_next_token (re_compiler_ctx_t *re_ctx_p) /**< RegExp compiler context */ +{ + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + re_ctx_p->token.type = RE_TOK_EOF; + return ECMA_VALUE_EMPTY; + } + + ecma_char_t ch = lit_cesu8_read_next (&re_ctx_p->input_curr_p); + + switch (ch) + { + case LIT_CHAR_CIRCUMFLEX: + { + re_ctx_p->token.type = RE_TOK_ASSERT_START; + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_DOLLAR_SIGN: + { + re_ctx_p->token.type = RE_TOK_ASSERT_END; + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_VLINE: + { + re_ctx_p->token.type = RE_TOK_ALTERNATIVE; + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_DOT: + { + re_ctx_p->token.type = RE_TOK_PERIOD; + /* Check quantifier */ + break; + } + case LIT_CHAR_BACKSLASH: + { + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_ESCAPE); + } + + /* DecimalEscape, Backreferences cannot start with a zero digit. */ + if (*re_ctx_p->input_curr_p > LIT_CHAR_0 && *re_ctx_p->input_curr_p <= LIT_CHAR_9) + { + const lit_utf8_byte_t *digits_p = re_ctx_p->input_curr_p; + const uint32_t value = lit_parse_decimal (&digits_p, re_ctx_p->input_end_p); + + if (re_ctx_p->groups_count < 0) + { + re_count_groups (re_ctx_p); + } + + if (value <= (uint32_t) re_ctx_p->groups_count) + { + /* Valid backreference */ + re_ctx_p->input_curr_p = digits_p; + re_ctx_p->token.type = RE_TOK_BACKREFERENCE; + re_ctx_p->token.value = value; + + /* Check quantifier */ + break; + } + } + + if (*re_ctx_p->input_curr_p == LIT_CHAR_LOWERCASE_B) + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.type = RE_TOK_ASSERT_WORD_BOUNDARY; + return ECMA_VALUE_EMPTY; + } + else if (*re_ctx_p->input_curr_p == LIT_CHAR_UPPERCASE_B) + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.type = RE_TOK_ASSERT_NOT_WORD_BOUNDARY; + return ECMA_VALUE_EMPTY; + } + + const ecma_value_t parse_result = re_parse_char_escape (re_ctx_p); + + if (ECMA_IS_VALUE_ERROR (parse_result)) + { + return parse_result; + } + + /* Check quantifier */ + break; + } + case LIT_CHAR_LEFT_PAREN: + { + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_UNTERMINATED_GROUP); + } + + if (*re_ctx_p->input_curr_p == LIT_CHAR_QUESTION) + { + re_ctx_p->input_curr_p++; + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_GROUP); + } + + ch = *re_ctx_p->input_curr_p++; + + if (ch == LIT_CHAR_EQUALS) + { + re_ctx_p->token.type = RE_TOK_ASSERT_LOOKAHEAD; + re_ctx_p->token.value = false; + } + else if (ch == LIT_CHAR_EXCLAMATION) + { + re_ctx_p->token.type = RE_TOK_ASSERT_LOOKAHEAD; + re_ctx_p->token.value = true; + } + else if (ch == LIT_CHAR_COLON) + { + re_ctx_p->token.type = RE_TOK_START_NON_CAPTURE_GROUP; + } + else + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_GROUP); + } + } + else + { + re_ctx_p->token.type = RE_TOK_START_CAPTURE_GROUP; + } + + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_RIGHT_PAREN: + { + re_ctx_p->token.type = RE_TOK_END_GROUP; + + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_LEFT_SQUARE: + { + re_ctx_p->token.type = RE_TOK_CHAR_CLASS; + + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_UNTERMINATED_CHARACTER_CLASS); + } + + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_QUESTION: + case LIT_CHAR_ASTERISK: + case LIT_CHAR_PLUS: + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_QUANTIFIER); + } + case LIT_CHAR_LEFT_BRACE: + { + re_ctx_p->input_curr_p--; + if (ecma_is_value_true (re_parse_quantifier (re_ctx_p))) + { + return ecma_raise_syntax_error (ECMA_ERR_NOTHING_TO_REPEAT); + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_LONE_QUANTIFIER_BRACKET); + } + + re_ctx_p->input_curr_p++; + re_ctx_p->token.type = RE_TOK_CHAR; + re_ctx_p->token.value = ch; + + /* Check quantifier */ + break; + } + case LIT_CHAR_RIGHT_SQUARE: + case LIT_CHAR_RIGHT_BRACE: + { + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_LONE_QUANTIFIER_BRACKET); + } + + /* FALLTHRU */ + } + default: + { + re_ctx_p->token.type = RE_TOK_CHAR; + re_ctx_p->token.value = ch; + + if (re_ctx_p->flags & RE_FLAG_UNICODE && lit_is_code_point_utf16_high_surrogate (ch) + && re_ctx_p->input_curr_p < re_ctx_p->input_end_p) + { + const ecma_char_t next = lit_cesu8_peek_next (re_ctx_p->input_curr_p); + if (lit_is_code_point_utf16_low_surrogate (next)) + { + re_ctx_p->token.value = lit_convert_surrogate_pair_to_code_point (ch, next); + re_ctx_p->input_curr_p += LIT_UTF8_MAX_BYTES_IN_CODE_UNIT; + } + } + + /* Check quantifier */ + break; + } + } + + re_parse_quantifier (re_ctx_p); + return re_check_quantifier (re_ctx_p); +} /* re_parse_next_token */ + +/** + * Append a character class range to the bytecode. + */ +static void +re_class_add_range (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + lit_code_point_t start, /**< range begin */ + lit_code_point_t end) /**< range end */ +{ + if (re_ctx_p->flags & RE_FLAG_IGNORE_CASE) + { + start = ecma_regexp_canonicalize_char (start, re_ctx_p->flags & RE_FLAG_UNICODE); + end = ecma_regexp_canonicalize_char (end, re_ctx_p->flags & RE_FLAG_UNICODE); + } + + re_append_char (re_ctx_p, start); + re_append_char (re_ctx_p, end); +} /* re_class_add_range */ + +/** + * Add a single character to the character class + */ +static void +re_class_add_char (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + uint32_t class_offset, /**< character class bytecode offset*/ + lit_code_point_t cp) /**< code point */ +{ + if (re_ctx_p->flags & RE_FLAG_IGNORE_CASE) + { + cp = ecma_regexp_canonicalize_char (cp, re_ctx_p->flags & RE_FLAG_UNICODE); + } + + re_insert_char (re_ctx_p, class_offset, cp); +} /* re_class_add_char */ + +/** + * Invalid character code point + */ +#define RE_INVALID_CP 0xFFFFFFFF + +/** + * Read the input pattern and parse the range of character class + * + * @return empty ecma value - if parsed successfully + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +re_parse_char_class (re_compiler_ctx_t *re_ctx_p) /**< RegExp compiler context */ +{ + static const uint8_t escape_flags[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20 }; + const uint32_t class_offset = re_bytecode_size (re_ctx_p); + + uint8_t found_escape_flags = 0; + uint8_t out_class_flags = 0; + + uint32_t range_count = 0; + uint32_t char_count = 0; + bool is_range = false; + + JERRY_ASSERT (re_ctx_p->input_curr_p < re_ctx_p->input_end_p); + if (*re_ctx_p->input_curr_p == LIT_CHAR_CIRCUMFLEX) + { + re_ctx_p->input_curr_p++; + out_class_flags |= RE_CLASS_INVERT; + } + + lit_code_point_t start = RE_INVALID_CP; + + while (true) + { + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_UNTERMINATED_CHARACTER_CLASS); + } + + if (*re_ctx_p->input_curr_p == LIT_CHAR_RIGHT_SQUARE) + { + if (is_range) + { + if (start != RE_INVALID_CP) + { + re_class_add_char (re_ctx_p, class_offset, start); + char_count++; + } + + re_class_add_char (re_ctx_p, class_offset, LIT_CHAR_MINUS); + char_count++; + } + + re_ctx_p->input_curr_p++; + break; + } + + JERRY_ASSERT (re_ctx_p->input_curr_p < re_ctx_p->input_end_p); + lit_code_point_t current; + + if (*re_ctx_p->input_curr_p == LIT_CHAR_BACKSLASH) + { + re_ctx_p->input_curr_p++; + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_ESCAPE); + } + + if (*re_ctx_p->input_curr_p == LIT_CHAR_LOWERCASE_B) + { + re_ctx_p->input_curr_p++; + current = LIT_CHAR_BS; + } + else if (*re_ctx_p->input_curr_p == LIT_CHAR_MINUS) + { + re_ctx_p->input_curr_p++; + current = LIT_CHAR_MINUS; + } + else if ((re_ctx_p->flags & RE_FLAG_UNICODE) == 0 && *re_ctx_p->input_curr_p == LIT_CHAR_LOWERCASE_C + && re_ctx_p->input_curr_p + 1 < re_ctx_p->input_end_p + && (lit_char_is_decimal_digit (*(re_ctx_p->input_curr_p + 1)) + || *(re_ctx_p->input_curr_p + 1) == LIT_CHAR_UNDERSCORE)) + { + current = ((uint8_t) * (re_ctx_p->input_curr_p + 1) % 32); + re_ctx_p->input_curr_p += 2; + } + else + { + if (ECMA_IS_VALUE_ERROR (re_parse_char_escape (re_ctx_p))) + { + return ECMA_VALUE_ERROR; + } + + if (re_ctx_p->token.type == RE_TOK_CLASS_ESCAPE) + { + const uint8_t escape = (uint8_t) re_ctx_p->token.value; + found_escape_flags |= escape_flags[escape]; + current = RE_INVALID_CP; + } + else + { + JERRY_ASSERT (re_ctx_p->token.type == RE_TOK_CHAR); + current = re_ctx_p->token.value; + } + } + } + else if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + current = ecma_regexp_unicode_advance (&re_ctx_p->input_curr_p, re_ctx_p->input_end_p); + } + else + { + current = lit_cesu8_read_next (&re_ctx_p->input_curr_p); + } + + if (is_range) + { + is_range = false; + + if (start != RE_INVALID_CP && current != RE_INVALID_CP) + { + if (start > current) + { + return ecma_raise_syntax_error (ECMA_ERR_RANGE_OUT_OF_ORDER_IN_CHARACTER_CLASS); + } + + re_class_add_range (re_ctx_p, start, current); + range_count++; + continue; + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_CHARACTER_CLASS); + } + + if (start != RE_INVALID_CP) + { + re_class_add_char (re_ctx_p, class_offset, start); + char_count++; + } + else if (current != RE_INVALID_CP) + { + re_class_add_char (re_ctx_p, class_offset, current); + char_count++; + } + + re_class_add_char (re_ctx_p, class_offset, LIT_CHAR_MINUS); + char_count++; + continue; + } + + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && *re_ctx_p->input_curr_p == LIT_CHAR_MINUS) + { + re_ctx_p->input_curr_p++; + start = current; + is_range = true; + continue; + } + + if (current != RE_INVALID_CP) + { + re_class_add_char (re_ctx_p, class_offset, current); + char_count++; + } + } + + uint8_t escape_count = 0; + for (ecma_class_escape_t escape = RE_ESCAPE__START; escape < RE_ESCAPE__COUNT; escape = (ecma_class_escape_t)((int) escape + 1)) + { + if (found_escape_flags & escape_flags[escape]) + { + re_insert_byte (re_ctx_p, class_offset, (uint8_t) escape); + escape_count++; + } + } + + if (range_count > 0) + { + re_insert_value (re_ctx_p, class_offset, range_count); + out_class_flags |= RE_CLASS_HAS_RANGES; + } + + if (char_count > 0) + { + re_insert_value (re_ctx_p, class_offset, char_count); + out_class_flags |= RE_CLASS_HAS_CHARS; + } + + JERRY_ASSERT (escape_count <= RE_CLASS_ESCAPE_COUNT_MASK); + out_class_flags |= escape_count; + + re_insert_byte (re_ctx_p, class_offset, out_class_flags); + re_insert_opcode (re_ctx_p, class_offset, RE_OP_CHAR_CLASS); + + re_parse_quantifier (re_ctx_p); + return re_check_quantifier (re_ctx_p); +} /* re_parse_char_class */ + +/** + * Parse alternatives + * + * @return empty ecma value - if alternative was successfully parsed + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +re_parse_alternative (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + bool expect_eof) /**< expect end of file */ +{ + ECMA_CHECK_STACK_USAGE (); + uint32_t alternative_offset = re_bytecode_size (re_ctx_p); + bool first_alternative = true; + + while (true) + { + ecma_value_t next_token_result = re_parse_next_token (re_ctx_p); + if (ECMA_IS_VALUE_ERROR (next_token_result)) + { + return next_token_result; + } + + JERRY_ASSERT (ecma_is_value_empty (next_token_result)); + + uint32_t atom_offset = re_bytecode_size (re_ctx_p); + + switch (re_ctx_p->token.type) + { + case RE_TOK_START_CAPTURE_GROUP: + { + const uint32_t idx = re_ctx_p->captures_count++; + const uint32_t capture_start = idx; + + ecma_value_t result = re_parse_alternative (re_ctx_p, false); + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + re_parse_quantifier (re_ctx_p); + + if (ECMA_IS_VALUE_ERROR (re_check_quantifier (re_ctx_p))) + { + return ECMA_VALUE_ERROR; + } + + re_insert_into_group (re_ctx_p, atom_offset, idx, capture_start, true); + break; + } + case RE_TOK_START_NON_CAPTURE_GROUP: + { + const uint32_t idx = re_ctx_p->non_captures_count++; + const uint32_t capture_start = re_ctx_p->captures_count; + + ecma_value_t result = re_parse_alternative (re_ctx_p, false); + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + re_parse_quantifier (re_ctx_p); + + if (ECMA_IS_VALUE_ERROR (re_check_quantifier (re_ctx_p))) + { + return ECMA_VALUE_ERROR; + } + + re_insert_into_group (re_ctx_p, atom_offset, idx, capture_start, false); + break; + } + case RE_TOK_PERIOD: + { + re_append_opcode (re_ctx_p, (re_ctx_p->flags & RE_FLAG_UNICODE) ? RE_OP_UNICODE_PERIOD : RE_OP_PERIOD); + re_insert_atom_iterator (re_ctx_p, atom_offset); + break; + } + case RE_TOK_ALTERNATIVE: + { + re_insert_value (re_ctx_p, alternative_offset, re_bytecode_size (re_ctx_p) - alternative_offset); + re_insert_opcode (re_ctx_p, + alternative_offset, + first_alternative ? RE_OP_ALTERNATIVE_START : RE_OP_ALTERNATIVE_NEXT); + + alternative_offset = re_bytecode_size (re_ctx_p); + first_alternative = false; + break; + } + case RE_TOK_ASSERT_START: + { + re_append_opcode (re_ctx_p, RE_OP_ASSERT_LINE_START); + break; + } + case RE_TOK_ASSERT_END: + { + re_append_opcode (re_ctx_p, RE_OP_ASSERT_LINE_END); + break; + } + case RE_TOK_ASSERT_WORD_BOUNDARY: + { + re_append_opcode (re_ctx_p, RE_OP_ASSERT_WORD_BOUNDARY); + break; + } + case RE_TOK_ASSERT_NOT_WORD_BOUNDARY: + { + re_append_opcode (re_ctx_p, RE_OP_ASSERT_NOT_WORD_BOUNDARY); + break; + } + case RE_TOK_ASSERT_LOOKAHEAD: + { + const uint32_t start_capture_count = re_ctx_p->captures_count; + const bool is_negative = !!re_ctx_p->token.value; + + ecma_value_t result = re_parse_alternative (re_ctx_p, false); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + re_ctx_p->token.qmin = 1; + re_ctx_p->token.qmax = 1; + re_ctx_p->token.greedy = true; + } + else + { + re_parse_quantifier (re_ctx_p); + + if (ECMA_IS_VALUE_ERROR (re_check_quantifier (re_ctx_p))) + { + return ECMA_VALUE_ERROR; + } + } + + re_insert_assertion_lookahead (re_ctx_p, atom_offset, start_capture_count, is_negative); + break; + } + case RE_TOK_BACKREFERENCE: + { + const uint32_t backref_idx = re_ctx_p->token.value; + re_append_opcode (re_ctx_p, RE_OP_BACKREFERENCE); + re_append_value (re_ctx_p, backref_idx); + + if (re_ctx_p->token.qmin != 1 || re_ctx_p->token.qmax != 1) + { + const uint32_t group_idx = re_ctx_p->non_captures_count++; + re_insert_into_group (re_ctx_p, atom_offset, group_idx, re_ctx_p->captures_count, false); + } + + break; + } + case RE_TOK_CLASS_ESCAPE: + { + const ecma_class_escape_t escape = (ecma_class_escape_t) re_ctx_p->token.value; + re_append_opcode (re_ctx_p, RE_OP_CLASS_ESCAPE); + re_append_byte (re_ctx_p, (uint8_t) escape); + + re_insert_atom_iterator (re_ctx_p, atom_offset); + break; + } + case RE_TOK_CHAR_CLASS: + { + ecma_value_t result = re_parse_char_class (re_ctx_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + re_insert_atom_iterator (re_ctx_p, atom_offset); + break; + } + case RE_TOK_END_GROUP: + { + if (expect_eof) + { + return ecma_raise_syntax_error (ECMA_ERR_UNMATCHED_CLOSE_BRACKET); + } + + if (!first_alternative) + { + re_insert_value (re_ctx_p, alternative_offset, re_bytecode_size (re_ctx_p) - alternative_offset); + re_insert_opcode (re_ctx_p, alternative_offset, RE_OP_ALTERNATIVE_NEXT); + } + + return ECMA_VALUE_EMPTY; + } + case RE_TOK_EOF: + { + if (!expect_eof) + { + return ecma_raise_syntax_error (ECMA_ERR_UNEXPECTED_END_OF_PATTERN); + } + + if (!first_alternative) + { + re_insert_value (re_ctx_p, alternative_offset, re_bytecode_size (re_ctx_p) - alternative_offset); + re_insert_opcode (re_ctx_p, alternative_offset, RE_OP_ALTERNATIVE_NEXT); + } + + re_append_opcode (re_ctx_p, RE_OP_EOF); + return ECMA_VALUE_EMPTY; + } + default: + { + JERRY_ASSERT (re_ctx_p->token.type == RE_TOK_CHAR); + + lit_code_point_t ch = re_ctx_p->token.value; + + if (ch <= LIT_UTF8_1_BYTE_CODE_POINT_MAX && (re_ctx_p->flags & RE_FLAG_IGNORE_CASE) == 0) + { + re_append_opcode (re_ctx_p, RE_OP_BYTE); + re_append_byte (re_ctx_p, (uint8_t) ch); + + re_insert_atom_iterator (re_ctx_p, atom_offset); + break; + } + + if (re_ctx_p->flags & RE_FLAG_IGNORE_CASE) + { + ch = ecma_regexp_canonicalize_char (ch, re_ctx_p->flags & RE_FLAG_UNICODE); + } + + re_append_opcode (re_ctx_p, RE_OP_CHAR); + re_append_char (re_ctx_p, ch); + + re_insert_atom_iterator (re_ctx_p, atom_offset); + break; + } + } + } + + return ECMA_VALUE_EMPTY; +} /* re_parse_alternative */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.h b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.h new file mode 100644 index 00000000..0c28edc3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.h @@ -0,0 +1,59 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RE_PARSER_H +#define RE_PARSER_H + +#include "re-compiler-context.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_parser Parser + * @{ + */ + +/** + * @} + * + * \addtogroup regexparser_parser Parser + * @{ + */ + +/** + * Value used for infinite quantifier. + */ +#define RE_INFINITY UINT32_MAX + +/** + * Maximum decimal value of an octal escape + */ +#define RE_MAX_OCTAL_VALUE 0xff + +ecma_value_t re_parse_alternative (re_compiler_ctx_t *re_ctx_p, bool expect_eof); + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !RE_PARSER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-token.h b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-token.h new file mode 100644 index 00000000..ad3b5dfe --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-token.h @@ -0,0 +1,74 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RE_TOKEN_H +#define RE_TOKEN_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_parser Parser + * @{ + */ + +/** + * RegExp token type definitions + */ +typedef enum +{ + RE_TOK_EOF, /**< EOF */ + RE_TOK_BACKREFERENCE, /**< "\[0..9]" */ + RE_TOK_ALTERNATIVE, /**< "|" */ + RE_TOK_ASSERT_START, /**< "^" */ + RE_TOK_ASSERT_END, /**< "$" */ + RE_TOK_PERIOD, /**< "." */ + RE_TOK_START_CAPTURE_GROUP, /**< "(" */ + RE_TOK_START_NON_CAPTURE_GROUP, /**< "(?:" */ + RE_TOK_END_GROUP, /**< ")" */ + RE_TOK_ASSERT_LOOKAHEAD, /**< "(?=" */ + RE_TOK_ASSERT_WORD_BOUNDARY, /**< "\b" */ + RE_TOK_ASSERT_NOT_WORD_BOUNDARY, /**< "\B" */ + RE_TOK_CLASS_ESCAPE, /**< "\d \D \w \W \s \S" */ + RE_TOK_CHAR_CLASS, /**< "[ ]" */ + RE_TOK_CHAR, /**< any character */ +} re_token_type_t; + +/** + * RegExp token + */ +typedef struct +{ + uint32_t value; /**< value of the token */ + uint32_t qmin; /**< minimum number of token iterations */ + uint32_t qmax; /**< maximum number of token iterations */ + re_token_type_t type; /**< type of the token */ + bool greedy; /**< type of iteration */ +} re_token_t; + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !RE_TOKEN_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/meson.build b/src/loaders/lottie/jerryscript/jerry-core/vm/meson.build new file mode 100644 index 00000000..b2621bea --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/meson.build @@ -0,0 +1,18 @@ +source_file = [ + 'opcodes.h', + 'vm-defines.h', + 'vm-stack.h', + 'vm.h', + 'opcodes-ecma-arithmetics.cpp', + 'opcodes-ecma-bitwise.cpp', + 'opcodes-ecma-relational-equality.cpp', + 'opcodes.cpp', + 'vm-stack.cpp', + 'vm-utils.cpp', + 'vm.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-arithmetics.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-arithmetics.cpp new file mode 100644 index 00000000..d6503a40 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-arithmetics.cpp @@ -0,0 +1,337 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-bigint.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jrt-libc-includes.h" +#include "opcodes.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_opcodes Opcodes + * @{ + */ + +/** + * Perform ECMA number arithmetic operation. + * + * The algorithm of the operation is following: + * leftNum = ToNumber (leftValue); + * rightNum = ToNumber (rightValue); + * result = leftNum ArithmeticOp rightNum; + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation */ + ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + ecma_number_t left_number; + left_value = ecma_op_to_numeric (left_value, &left_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (left_value)) + { + return left_value; + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))) + { +#endif /* JERRY_BUILTIN_BIGINT */ + + ecma_number_t right_number; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (right_value, &right_number))) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t result = ECMA_NUMBER_ZERO; + + switch (op) + { + case NUMBER_ARITHMETIC_SUBTRACTION: + { + result = left_number - right_number; + break; + } + case NUMBER_ARITHMETIC_MULTIPLICATION: + { + result = left_number * right_number; + break; + } + case NUMBER_ARITHMETIC_DIVISION: + { + result = left_number / right_number; + break; + } + case NUMBER_ARITHMETIC_REMAINDER: + { + if (ecma_number_is_nan (left_number) || ecma_number_is_nan (right_number) + || ecma_number_is_infinity (left_number) || ecma_number_is_zero (right_number)) + { + result = ecma_number_make_nan (); + break; + } + + if (ecma_number_is_infinity (right_number) + || (ecma_number_is_zero (left_number) && !ecma_number_is_zero (right_number))) + { + result = left_number; + break; + } + + result = ecma_number_remainder (left_number, right_number); + break; + } + case NUMBER_ARITHMETIC_EXPONENTIATION: + { + result = ecma_number_pow (left_number, right_number); + break; + } + } + + ret_value = ecma_make_number_value (result); +#if JERRY_BUILTIN_BIGINT + } + else + { + bool free_right_value; + right_value = ecma_bigint_get_bigint (right_value, &free_right_value); + + if (ECMA_IS_VALUE_ERROR (right_value)) + { + ecma_free_value (left_value); + return right_value; + } + + switch (op) + { + case NUMBER_ARITHMETIC_SUBTRACTION: + { + ret_value = ecma_bigint_add_sub (left_value, right_value, false); + break; + } + case NUMBER_ARITHMETIC_MULTIPLICATION: + { + ret_value = ecma_bigint_mul (left_value, right_value); + break; + } + case NUMBER_ARITHMETIC_DIVISION: + { + ret_value = ecma_bigint_div_mod (left_value, right_value, false); + break; + } + case NUMBER_ARITHMETIC_REMAINDER: + { + ret_value = ecma_bigint_div_mod (left_value, right_value, true); + break; + } + case NUMBER_ARITHMETIC_EXPONENTIATION: + { + ret_value = ecma_bigint_pow (left_value, right_value); + break; + } + } + + ecma_free_value (left_value); + if (free_right_value) + { + ecma_free_value (right_value); + } + } +#endif /* JERRY_BUILTIN_BIGINT */ + return ret_value; +} /* do_number_arithmetic */ + +/** + * 'Addition' opcode handler. + * + * See also: ECMA-262 v5, 11.6.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +opfunc_addition (ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + bool free_left_value = false; + bool free_right_value = false; + + if (ecma_is_value_object (left_value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (left_value); + left_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NO); + free_left_value = true; + + if (ECMA_IS_VALUE_ERROR (left_value)) + { + return left_value; + } + } + + if (ecma_is_value_object (right_value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (right_value); + right_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NO); + free_right_value = true; + + if (ECMA_IS_VALUE_ERROR (right_value)) + { + if (free_left_value) + { + ecma_free_value (left_value); + } + return right_value; + } + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if (ecma_is_value_string (left_value) || ecma_is_value_string (right_value)) + { + ecma_string_t *string1_p = ecma_op_to_string (left_value); + + if (JERRY_UNLIKELY (string1_p == NULL)) + { + if (free_left_value) + { + ecma_free_value (left_value); + } + if (free_right_value) + { + ecma_free_value (right_value); + } + return ECMA_VALUE_ERROR; + } + + ecma_string_t *string2_p = ecma_op_to_string (right_value); + + if (JERRY_UNLIKELY (string2_p == NULL)) + { + if (free_right_value) + { + ecma_free_value (right_value); + } + if (free_left_value) + { + ecma_free_value (left_value); + } + ecma_deref_ecma_string (string1_p); + return ECMA_VALUE_ERROR; + } + + string1_p = ecma_concat_ecma_strings (string1_p, string2_p); + ret_value = ecma_make_string_value (string1_p); + + ecma_deref_ecma_string (string2_p); + } +#if JERRY_BUILTIN_BIGINT + else if (JERRY_UNLIKELY (ecma_is_value_bigint (left_value)) && JERRY_UNLIKELY (ecma_is_value_bigint (right_value))) + { + ret_value = ecma_bigint_add_sub (left_value, right_value, true); + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + ecma_number_t num_left; + ecma_number_t num_right; + if (!ECMA_IS_VALUE_ERROR (ecma_op_to_number (left_value, &num_left)) + && !ECMA_IS_VALUE_ERROR (ecma_op_to_number (right_value, &num_right))) + { + ret_value = ecma_make_number_value (num_left + num_right); + } + else + { + ret_value = ECMA_VALUE_ERROR; + } + } + + if (free_left_value) + { + ecma_free_value (left_value); + } + + if (free_right_value) + { + ecma_free_value (right_value); + } + + return ret_value; +} /* opfunc_addition */ + +/** + * Unary operation opcode handler. + * + * See also: ECMA-262 v5, 11.4, 11.4.6, 11.4.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +opfunc_unary_operation (ecma_value_t left_value, /**< left value */ + bool is_plus) /**< unary plus flag */ +{ + ecma_number_t left_number; + left_value = ecma_op_to_numeric (left_value, &left_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (left_value)) + { + return left_value; + } + +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))) + { + return ecma_make_number_value (is_plus ? left_number : -left_number); + } + + ecma_value_t ret_value; + + if (is_plus) + { + ret_value = ecma_raise_type_error (ECMA_ERR_UNARY_PLUS_IS_NOT_ALLOWED_FOR_BIGINTS); + } + else + { + ret_value = left_value; + + if (left_value != ECMA_BIGINT_ZERO) + { + ret_value = ecma_bigint_negate (ecma_get_extended_primitive_from_value (left_value)); + } + } + + ecma_free_value (left_value); + return ret_value; +#else /* !JERRY_BUILTIN_BIGINT */ + return ecma_make_number_value (is_plus ? left_number : -left_number); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* opfunc_unary_operation */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-bitwise.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-bitwise.cpp new file mode 100644 index 00000000..3653f7b1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-bitwise.cpp @@ -0,0 +1,212 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-bigint.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "opcodes.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_opcodes Opcodes + * @{ + */ + +/** + * Perform ECMA number logic operation. + * + * The algorithm of the operation is following: + * leftNum = ToNumber (leftValue); + * rightNum = ToNumber (rightValue); + * result = leftNum BitwiseLogicOp rightNum; + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic operation */ + ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + ecma_number_t left_number; + left_value = ecma_op_to_numeric (left_value, &left_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (left_value)) + { + return left_value; + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))) + { +#endif /* JERRY_BUILTIN_BIGINT */ + ecma_number_t right_number; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (right_value, &right_number))) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t result = ECMA_NUMBER_ZERO; + uint32_t right_uint32 = ecma_number_to_uint32 (right_number); + + switch (op) + { + case NUMBER_BITWISE_LOGIC_AND: + { + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); + result = (ecma_number_t) ((int32_t) (left_uint32 & right_uint32)); + break; + } + case NUMBER_BITWISE_LOGIC_OR: + { + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); + result = (ecma_number_t) ((int32_t) (left_uint32 | right_uint32)); + break; + } + case NUMBER_BITWISE_LOGIC_XOR: + { + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); + result = (ecma_number_t) ((int32_t) (left_uint32 ^ right_uint32)); + break; + } + case NUMBER_BITWISE_SHIFT_LEFT: + { + result = (ecma_number_t) ((int32_t) ((uint32_t) ecma_number_to_int32 (left_number) << (right_uint32 & 0x1F))); + break; + } + case NUMBER_BITWISE_SHIFT_RIGHT: + { + result = (ecma_number_t) (ecma_number_to_int32 (left_number) >> (right_uint32 & 0x1F)); + break; + } + default: + { + JERRY_ASSERT (op == NUMBER_BITWISE_SHIFT_URIGHT); + + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); + result = (ecma_number_t) (left_uint32 >> (right_uint32 & 0x1F)); + break; + } + } + + ret_value = ecma_make_number_value (result); + +#if JERRY_BUILTIN_BIGINT + } + else + { + bool free_right_value; + right_value = ecma_bigint_get_bigint (right_value, &free_right_value); + + if (ECMA_IS_VALUE_ERROR (right_value)) + { + ecma_free_value (left_value); + return right_value; + } + + switch (op) + { + case NUMBER_BITWISE_LOGIC_AND: + { + ret_value = ecma_bigint_and (left_value, right_value); + break; + } + case NUMBER_BITWISE_LOGIC_OR: + { + ret_value = ecma_bigint_or (left_value, right_value); + break; + } + case NUMBER_BITWISE_LOGIC_XOR: + { + ret_value = ecma_bigint_xor (left_value, right_value); + break; + } + case NUMBER_BITWISE_SHIFT_LEFT: + { + ret_value = ecma_bigint_shift (left_value, right_value, true); + break; + } + case NUMBER_BITWISE_SHIFT_RIGHT: + { + ret_value = ecma_bigint_shift (left_value, right_value, false); + break; + } + default: + { + JERRY_ASSERT (op == NUMBER_BITWISE_SHIFT_URIGHT); + + ret_value = ecma_raise_type_error (ECMA_ERR_UNSIGNED_RIGHT_SHIFT_IS_NOT_ALLOWED_FOR_BIGINTS); + break; + } + } + + ecma_free_value (left_value); + if (free_right_value) + { + ecma_free_value (right_value); + } + } +#endif /* JERRY_BUILTIN_BIGINT */ + + return ret_value; +} /* do_number_bitwise_logic */ + +/** + * Perform ECMA number bitwise not operation. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +do_number_bitwise_not (ecma_value_t value) /**< value */ +{ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value)); + + ecma_number_t number; + value = ecma_op_to_numeric (value, &number, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (!ecma_is_value_bigint (value))) + { +#endif /* JERRY_BUILTIN_BIGINT */ + return ecma_make_number_value ((ecma_number_t) ((int32_t) ~ecma_number_to_uint32 (number))); +#if JERRY_BUILTIN_BIGINT + } + + ecma_value_t ret_value = ecma_bigint_unary (value, ECMA_BIGINT_UNARY_BITWISE_NOT); + ecma_free_value (value); + return ret_value; +#endif /* JERRY_BUILTIN_BIGINT */ +} /* do_number_bitwise_not */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-relational-equality.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-relational-equality.cpp new file mode 100644 index 00000000..b3602adf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-relational-equality.cpp @@ -0,0 +1,173 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-comparison.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "opcodes.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_opcodes Opcodes + * @{ + */ + +/** + * Equality opcode handler. + * + * See also: ECMA-262 v5, 11.9.1, 11.9.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +opfunc_equality (ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + ecma_value_t compare_result = ecma_op_abstract_equality_compare (left_value, right_value); + + JERRY_ASSERT (ecma_is_value_boolean (compare_result) || ECMA_IS_VALUE_ERROR (compare_result)); + + return compare_result; +} /* opfunc_equality */ + +/** + * Relation opcode handler. + * + * See also: ECMA-262 v5, 11.8.1, 11.8.2, 11.8.3, 11.8.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +opfunc_relation (ecma_value_t left_value, /**< left value */ + ecma_value_t right_value, /**< right value */ + bool left_first, /**< 'LeftFirst' flag */ + bool is_invert) /**< is invert */ +{ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + ecma_value_t ret_value = ecma_op_abstract_relational_compare (left_value, right_value, left_first); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + + if (ecma_is_value_undefined (ret_value)) + { + ret_value = ECMA_VALUE_FALSE; + } + else + { + JERRY_ASSERT (ecma_is_value_boolean (ret_value)); + + if (is_invert) + { + ret_value = ecma_invert_boolean_value (ret_value); + } + } + + return ret_value; +} /* opfunc_relation */ + +/** + * 'instanceof' opcode handler. + * + * See also: ECMA-262 v5, 11.8.6 + * + * @return ecma value + * returned value must be freed with ecma_free_value. + */ +ecma_value_t +opfunc_instanceof (ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + if (!ecma_is_value_object (right_value)) + { + return ecma_raise_type_error (ECMA_ERR_RIGHT_VALUE_OF_INSTANCEOF_MUST_BE_AN_OBJECT); + } + + ecma_value_t has_instance_method = ecma_op_get_method_by_symbol_id (right_value, LIT_GLOBAL_SYMBOL_HAS_INSTANCE); + if (ECMA_IS_VALUE_ERROR (has_instance_method)) + { + return has_instance_method; + } + + if (JERRY_UNLIKELY (!ecma_is_value_undefined (has_instance_method))) + { + ecma_object_t *method_obj_p = ecma_get_object_from_value (has_instance_method); + ecma_value_t has_instance_result = ecma_op_function_call (method_obj_p, right_value, &left_value, 1); + + ecma_free_value (has_instance_method); + + if (ECMA_IS_VALUE_ERROR (has_instance_result)) + { + return has_instance_result; + } + + bool has_instance = ecma_op_to_boolean (has_instance_result); + ecma_free_value (has_instance_result); + + return ecma_make_boolean_value (has_instance); + } + + ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value); + return ecma_op_object_has_instance (right_value_obj_p, left_value); +} /* opfunc_instanceof */ + +/** + * 'in' opcode handler. + * + * See also: + * * ECMA-262 v5, 11.8.7 + * * ECAM-262 v6, 12.9.3 + * + * @return ecma value + * returned value must be freed with ecma_free_value. + */ +ecma_value_t +opfunc_in (ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + if (!ecma_is_value_object (right_value)) + { + return ecma_raise_type_error (ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT); + } + + ecma_string_t *property_name_p = ecma_op_to_property_key (left_value); + + if (JERRY_UNLIKELY (property_name_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value); + ecma_value_t result = ecma_op_object_has_property (right_value_obj_p, property_name_p); + ecma_deref_ecma_string (property_name_p); + return result; +} /* opfunc_in */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.cpp new file mode 100644 index 00000000..9ce78f91 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.cpp @@ -0,0 +1,2302 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "opcodes.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-lex-env.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" +#include "ecma-proxy-object.h" + +#include "jcontext.h" +#include "vm-defines.h" +#include "vm-stack.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_opcodes Opcodes + * @{ + */ + +/** + * 'typeof' opcode handler. + * + * See also: ECMA-262 v5, 11.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +opfunc_typeof (ecma_value_t left_value) /**< left value */ +{ + return ecma_make_magic_string_value (ecma_get_typeof_lit_id (left_value)); +} /* opfunc_typeof */ + +/** + * Update data property for object literals. + */ +void +opfunc_set_data_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *prop_name_p, /**< data property name */ + ecma_value_t value) /**< new value */ +{ + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + + ecma_property_t *property_p = ecma_find_named_property (object_p, prop_name_p); + ecma_property_value_t *prop_value_p; + + if (property_p == NULL) + { + prop_value_p = + ecma_create_named_data_property (object_p, prop_name_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + } + else + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, + ECMA_PROPERTY_VALUE_PTR (property_p)->getter_setter_pair_cp); + jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t)); +#endif /* JERRY_CPOINTER_32_BIT */ + + *property_p |= ECMA_PROPERTY_FLAG_DATA | ECMA_PROPERTY_FLAG_WRITABLE; + prop_value_p->value = ecma_copy_value_if_not_object (value); + return; + } + } + + ecma_named_data_property_assign_value (object_p, prop_value_p, value); +} /* opfunc_set_data_property */ + +/** + * Update getter or setter for object literals. + */ +void +opfunc_set_accessor (bool is_getter, /**< is getter accessor */ + ecma_value_t object, /**< object value */ + ecma_string_t *accessor_name_p, /**< accessor name */ + ecma_value_t accessor) /**< accessor value */ +{ + ecma_object_t *object_p = ecma_get_object_from_value (object); + + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + + ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p); + ecma_object_t *accessor_p = ecma_get_object_from_value (accessor); + + ecma_object_t *getter_func_p = NULL; + ecma_object_t *setter_func_p = NULL; + + if (is_getter) + { + getter_func_p = accessor_p; + } + else + { + setter_func_p = accessor_p; + } + + if (property_p == NULL) + { + ecma_create_named_accessor_property (object_p, + accessor_name_p, + getter_func_p, + setter_func_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE, + NULL); + } + else + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (*property_p & ECMA_PROPERTY_FLAG_DATA) + { +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t)); +#endif /* JERRY_CPOINTER_32_BIT */ + + ecma_free_value_if_not_object (prop_value_p->value); + *property_p = (uint8_t) (*property_p & ~(ECMA_PROPERTY_FLAG_DATA | ECMA_PROPERTY_FLAG_WRITABLE)); + +#if JERRY_CPOINTER_32_BIT + ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, getter_func_p); + ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, setter_func_p); + ECMA_SET_NON_NULL_POINTER (prop_value_p->getter_setter_pair_cp, getter_setter_pair_p); +#else /* !JERRY_CPOINTER_32_BIT */ + ECMA_SET_POINTER (prop_value_p->getter_setter_pair.getter_cp, getter_func_p); + ECMA_SET_POINTER (prop_value_p->getter_setter_pair.setter_cp, setter_func_p); +#endif /* JERRY_CPOINTER_32_BIT */ + return; + } + + if (is_getter) + { + ecma_set_named_accessor_property_getter (object_p, prop_value_p, accessor_p); + } + else + { + ecma_set_named_accessor_property_setter (object_p, prop_value_p, accessor_p); + } + } +} /* opfunc_set_accessor */ + +/** + * Deletes an object property. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +vm_op_delete_prop (ecma_value_t object, /**< base object */ + ecma_value_t property, /**< property name */ + bool is_strict) /**< strict mode */ +{ + if (!ecma_op_require_object_coercible (object)) + { + return ECMA_VALUE_ERROR; + } + + ecma_string_t *name_string_p = ecma_op_to_property_key (property); + + if (JERRY_UNLIKELY (name_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t obj_value = ecma_op_to_object (object); + /* The ecma_op_require_object_coercible call already checked the op_to_object error cases. */ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (obj_value)); + JERRY_ASSERT (ecma_is_value_object (obj_value)); + ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + + ecma_value_t delete_op_ret = ecma_op_object_delete (obj_p, name_string_p, is_strict); + JERRY_ASSERT (ecma_is_value_boolean (delete_op_ret) || ECMA_IS_VALUE_ERROR (delete_op_ret)); + ecma_deref_object (obj_p); + ecma_deref_ecma_string (name_string_p); + + if (is_strict && ecma_is_value_false (delete_op_ret)) + { + return ecma_raise_type_error (ECMA_ERR_OPERATOR_DELETE_RETURNED_FALSE_IN_STRICT_MODE); + } + + return delete_op_ret; +} /* vm_op_delete_prop */ + +/** + * Deletes a variable. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +vm_op_delete_var (ecma_value_t name_literal, /**< name literal */ + ecma_object_t *lex_env_p) /**< lexical environment */ +{ + ecma_value_t completion_value = ECMA_VALUE_EMPTY; + + ecma_string_t *var_name_str_p = ecma_get_string_from_value (name_literal); + + ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p); + +#if JERRY_BUILTIN_PROXY + if (JERRY_UNLIKELY (ref_base_lex_env_p == ECMA_OBJECT_POINTER_ERROR)) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ref_base_lex_env_p == NULL) + { + completion_value = ECMA_VALUE_TRUE; + } + else + { + JERRY_ASSERT (ecma_is_lexical_environment (ref_base_lex_env_p)); + + completion_value = ecma_op_delete_binding (ref_base_lex_env_p, var_name_str_p); + } + + return completion_value; +} /* vm_op_delete_var */ + +/** + * 'for-in' opcode handler + * + * Note: from ES2015 (ES6) the for-in can trigger error when + * the property names are not available (ex.: via Proxy ownKeys). + * In these cases an error must be returned. + * + * This error is returned as the `result_obj_p` and the + * function's return value is NULL. + * + * See also: + * ECMA-262 v5, 12.6.4 + * + * @return - chain list of property names + * - In case of error: NULL is returned and the `result_obj_p` + * must be checked. + */ +ecma_collection_t * +opfunc_for_in (ecma_value_t iterable_value, /**< ideally an iterable value */ + ecma_value_t *result_obj_p) /**< expression object */ +{ + /* 3. */ + if (ecma_is_value_undefined (iterable_value) || ecma_is_value_null (iterable_value)) + { + return NULL; + } + + /* 4. */ + ecma_value_t obj_expr_value = ecma_op_to_object (iterable_value); + /* ecma_op_to_object will only raise error on null/undefined values but those are handled above. */ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (obj_expr_value)); + ecma_object_t *obj_p = ecma_get_object_from_value (obj_expr_value); + ecma_collection_t *prop_names_p = ecma_op_object_enumerate (obj_p); + + if (JERRY_UNLIKELY (prop_names_p == NULL)) + { + ecma_deref_object (obj_p); + *result_obj_p = ECMA_VALUE_ERROR; + return NULL; + } + + if (prop_names_p->item_count != 0) + { + *result_obj_p = ecma_make_object_value (obj_p); + return prop_names_p; + } + + ecma_deref_object (obj_p); + ecma_collection_destroy (prop_names_p); + + return NULL; +} /* opfunc_for_in */ + +/** + * 'VM_OC_APPEND_ARRAY' opcode handler specialized for spread objects + * + * @return ECMA_VALUE_ERROR - if the operation failed + * ECMA_VALUE_EMPTY, otherwise + */ +static ecma_value_t JERRY_ATTR_NOINLINE +opfunc_append_to_spread_array (ecma_value_t *stack_top_p, /**< current stack top */ + uint16_t values_length) /**< number of elements to set */ +{ + JERRY_ASSERT (!(values_length & OPFUNC_HAS_SPREAD_ELEMENT)); + + ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]); + JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY); + + ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p; + uint32_t old_length = ext_array_obj_p->u.array.length; + + for (uint32_t i = 0, idx = old_length; i < values_length; i++, idx++) + { + if (ecma_is_value_array_hole (stack_top_p[i])) + { + continue; + } + + if (stack_top_p[i] == ECMA_VALUE_SPREAD_ELEMENT) + { + i++; + ecma_value_t ret_value = ECMA_VALUE_ERROR; + ecma_value_t spread_value = stack_top_p[i]; + + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (spread_value, ECMA_VALUE_SYNC_ITERATOR, &next_method); + + if (!ECMA_IS_VALUE_ERROR (iterator)) + { + while (true) + { + ecma_value_t next_value = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + break; + } + + if (ecma_is_value_false (next_value)) + { + idx--; + ret_value = ECMA_VALUE_EMPTY; + break; + } + + ecma_value_t value = ecma_op_iterator_value (next_value); + + ecma_free_value (next_value); + + if (ECMA_IS_VALUE_ERROR (value)) + { + break; + } + + ecma_value_t put_comp; + put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p, + idx++, + value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + JERRY_ASSERT (ecma_is_value_true (put_comp)); + ecma_free_value (value); + } + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + ecma_free_value (spread_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + for (uint32_t k = i + 1; k < values_length; k++) + { + ecma_free_value (stack_top_p[k]); + } + + return ret_value; + } + } + else + { + ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p, + idx, + stack_top_p[i], + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (put_comp)); + ecma_free_value (stack_top_p[i]); + } + } + + return ECMA_VALUE_EMPTY; +} /* opfunc_append_to_spread_array */ + +/** + * Spread function call/construct arguments into an ecma-collection + * + * @return NULL - if the operation failed + * pointer to the ecma-collection with the spreaded arguments, otherwise + */ +JERRY_ATTR_NOINLINE ecma_collection_t * +opfunc_spread_arguments (ecma_value_t *stack_top_p, /**< pointer to the current stack top */ + uint8_t arguments_list_len) /**< number of arguments */ +{ + ecma_collection_t *buff_p = ecma_new_collection (); + + for (uint32_t i = 0; i < arguments_list_len; i++) + { + ecma_value_t arg = *stack_top_p++; + + if (arg != ECMA_VALUE_SPREAD_ELEMENT) + { + ecma_collection_push_back (buff_p, arg); + continue; + } + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + ecma_value_t spread_value = *stack_top_p++; + i++; + + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (spread_value, ECMA_VALUE_SYNC_ITERATOR, &next_method); + + if (!ECMA_IS_VALUE_ERROR (iterator)) + { + while (true) + { + ecma_value_t next_value = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + break; + } + + if (ecma_is_value_false (next_value)) + { + ret_value = ECMA_VALUE_EMPTY; + break; + } + + ecma_value_t value = ecma_op_iterator_value (next_value); + + ecma_free_value (next_value); + + if (ECMA_IS_VALUE_ERROR (value)) + { + break; + } + + ecma_collection_push_back (buff_p, value); + } + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + ecma_free_value (spread_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + for (uint32_t k = i + 1; k < arguments_list_len; k++) + { + ecma_free_value (*stack_top_p++); + } + + ecma_collection_free (buff_p); + buff_p = NULL; + break; + } + } + + return buff_p; +} /* opfunc_spread_arguments */ + +/** + * 'VM_OC_APPEND_ARRAY' opcode handler, for setting array object properties + * + * @return ECMA_VALUE_ERROR - if the operation failed + * ECMA_VALUE_EMPTY, otherwise + */ +ecma_value_t JERRY_ATTR_NOINLINE +opfunc_append_array (ecma_value_t *stack_top_p, /**< current stack top */ + uint16_t values_length) /**< number of elements to set + * with potential OPFUNC_HAS_SPREAD_ELEMENT flag */ +{ + if (values_length >= OPFUNC_HAS_SPREAD_ELEMENT) + { + return opfunc_append_to_spread_array (stack_top_p, (uint16_t) (values_length & ~OPFUNC_HAS_SPREAD_ELEMENT)); + } + + ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]); + JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY); + + ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p; + uint32_t old_length = ext_array_obj_p->u.array.length; + + if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_array_obj_p))) + { + uint32_t filled_holes = 0; + ecma_value_t *values_p = ecma_fast_array_extend (array_obj_p, old_length + values_length); + + for (uint32_t i = 0; i < values_length; i++) + { + values_p[old_length + i] = stack_top_p[i]; + + if (!ecma_is_value_array_hole (stack_top_p[i])) + { + filled_holes++; + + ecma_deref_if_object (stack_top_p[i]); + } + } + + ext_array_obj_p->u.array.length_prop_and_hole_count -= filled_holes * ECMA_FAST_ARRAY_HOLE_ONE; + + if (JERRY_UNLIKELY ((values_length - filled_holes) > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT)) + { + ecma_fast_array_convert_to_normal (array_obj_p); + } + } + else + { + for (uint32_t i = 0; i < values_length; i++) + { + if (!ecma_is_value_array_hole (stack_top_p[i])) + { + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (old_length + i); + + ecma_property_value_t *prop_value_p; + + prop_value_p = ecma_create_named_data_property (array_obj_p, + index_str_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + ecma_deref_ecma_string (index_str_p); + prop_value_p->value = stack_top_p[i]; + ecma_deref_if_object (stack_top_p[i]); + } + } + ext_array_obj_p->u.array.length = old_length + values_length; + } + + return ECMA_VALUE_EMPTY; +} /* opfunc_append_array */ + +/** + * Create an executable object using the current frame context + * + * @return executable object + */ +vm_executable_object_t * +opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + vm_create_executable_object_type_t type) /**< executable object type */ +{ + const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->shared_p->bytecode_header_p; + size_t size, register_end; + + ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_header_p); + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + register_end = (size_t) args_p->register_end; + size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + register_end = (size_t) args_p->register_end; + size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t); + } + + size_t total_size = JERRY_ALIGNUP (sizeof (vm_executable_object_t) + size, sizeof (uintptr_t)); + + ecma_object_t *proto_p = NULL; + /* Async function objects are not accessible, so their class_id is not relevant. */ + uint8_t class_type = ECMA_OBJECT_CLASS_GENERATOR; + + if (type == VM_CREATE_EXECUTABLE_OBJECT_GENERATOR) + { + ecma_builtin_id_t default_proto_id = ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE; + + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR) + { + default_proto_id = ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE; + class_type = ECMA_OBJECT_CLASS_ASYNC_GENERATOR; + } + + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC); + proto_p = ecma_op_get_prototype_from_constructor (frame_ctx_p->shared_p->function_object_p, default_proto_id); + } + + ecma_object_t *object_p = ecma_create_object (proto_p, total_size, ECMA_OBJECT_TYPE_CLASS); + + vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p; + + if (type == VM_CREATE_EXECUTABLE_OBJECT_GENERATOR) + { + ecma_deref_object (proto_p); + } + + executable_object_p->extended_object.u.cls.type = class_type; + executable_object_p->extended_object.u.cls.u2.executable_obj_flags = 0; + ECMA_SET_INTERNAL_VALUE_ANY_POINTER (executable_object_p->extended_object.u.cls.u3.head, NULL); + executable_object_p->iterator = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (!(frame_ctx_p->status_flags & VM_FRAME_CTX_DIRECT_EVAL)); + + /* Copy shared data and frame context. */ + vm_frame_ctx_shared_t *new_shared_p = &(executable_object_p->shared); + *new_shared_p = *(frame_ctx_p->shared_p); + new_shared_p->status_flags &= (uint32_t) ~VM_FRAME_CTX_SHARED_HAS_ARG_LIST; + new_shared_p->status_flags |= VM_FRAME_CTX_SHARED_EXECUTABLE; + + vm_frame_ctx_t *new_frame_ctx_p = &(executable_object_p->frame_ctx); + *new_frame_ctx_p = *frame_ctx_p; + new_frame_ctx_p->shared_p = new_shared_p; + + /* The old register values are discarded. */ + ecma_value_t *new_registers_p = VM_GET_REGISTERS (new_frame_ctx_p); + memcpy (new_registers_p, VM_GET_REGISTERS (frame_ctx_p), size); + + size_t stack_top = (size_t) (frame_ctx_p->stack_top_p - VM_GET_REGISTERS (frame_ctx_p)); + ecma_value_t *new_stack_top_p = new_registers_p + stack_top; + + new_frame_ctx_p->stack_top_p = new_stack_top_p; + + /* Initial state is "not running", so all object references are released. */ + + if (frame_ctx_p->context_depth > 0) + { + JERRY_ASSERT (type != VM_CREATE_EXECUTABLE_OBJECT_GENERATOR); + + ecma_value_t *register_end_p = new_registers_p + register_end; + + JERRY_ASSERT (register_end_p <= new_stack_top_p); + + while (new_registers_p < register_end_p) + { + ecma_deref_if_object (*new_registers_p++); + } + + vm_ref_lex_env_chain (frame_ctx_p->lex_env_p, frame_ctx_p->context_depth, new_registers_p, false); + + new_registers_p += frame_ctx_p->context_depth; + + JERRY_ASSERT (new_registers_p <= new_stack_top_p); + } + + while (new_registers_p < new_stack_top_p) + { + ecma_deref_if_object (*new_registers_p++); + } + + JERRY_ASSERT (*VM_GET_EXECUTABLE_ITERATOR (new_frame_ctx_p) == ECMA_VALUE_UNDEFINED); + + new_frame_ctx_p->this_binding = ecma_copy_value_if_not_object (new_frame_ctx_p->this_binding); + + JERRY_CONTEXT (vm_top_context_p) = new_frame_ctx_p->prev_context_p; + + return executable_object_p; +} /* opfunc_create_executable_object */ + +/** + * Byte code which resumes an executable object with throw + */ +const uint8_t opfunc_resume_executable_object_with_throw[1] = { CBC_THROW }; + +/** + * Byte code which resumes an executable object with return + */ +const uint8_t opfunc_resume_executable_object_with_return[2] = { CBC_EXT_OPCODE, CBC_EXT_RETURN }; + +/** + * Resume the execution of an inactive executable object + * + * @return value provided by the execution + */ +ecma_value_t +opfunc_resume_executable_object (vm_executable_object_t *executable_object_p, /**< executable object */ + ecma_value_t value) /**< value pushed onto the stack (takes the reference) */ +{ + const ecma_compiled_code_t *bytecode_header_p = executable_object_p->shared.bytecode_header_p; + ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx); + ecma_value_t *register_end_p; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + register_end_p = register_p + args_p->register_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + register_end_p = register_p + args_p->register_end; + } + + ecma_value_t *stack_top_p = executable_object_p->frame_ctx.stack_top_p; + + if (value != ECMA_VALUE_EMPTY) + { + *stack_top_p = value; + executable_object_p->frame_ctx.stack_top_p = stack_top_p + 1; + } + + if (executable_object_p->frame_ctx.context_depth > 0) + { + while (register_p < register_end_p) + { + ecma_ref_if_object (*register_p++); + } + + vm_ref_lex_env_chain (executable_object_p->frame_ctx.lex_env_p, + executable_object_p->frame_ctx.context_depth, + register_p, + true); + + register_p += executable_object_p->frame_ctx.context_depth; + } + + while (register_p < stack_top_p) + { + ecma_ref_if_object (*register_p++); + } + + ecma_ref_if_object (executable_object_p->iterator); + + JERRY_ASSERT (ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED (executable_object_p)); + + executable_object_p->extended_object.u.cls.u2.executable_obj_flags |= ECMA_EXECUTABLE_OBJECT_RUNNING; + + executable_object_p->frame_ctx.prev_context_p = JERRY_CONTEXT (vm_top_context_p); + JERRY_CONTEXT (vm_top_context_p) = &executable_object_p->frame_ctx; + + /* inside the generators the "new.target" is always "undefined" as it can't be invoked with "new" */ + ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = NULL; + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = ecma_op_function_get_realm (bytecode_header_p); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_value_t result = vm_execute (&executable_object_p->frame_ctx); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + JERRY_CONTEXT (current_new_target_p) = old_new_target; + executable_object_p->extended_object.u.cls.u2.executable_obj_flags &= (uint8_t) ~ECMA_EXECUTABLE_OBJECT_RUNNING; + + if (executable_object_p->frame_ctx.call_operation != VM_EXEC_RETURN) + { + JERRY_ASSERT (executable_object_p->frame_ctx.call_operation == VM_NO_EXEC_OP); + + /* All resources are released. */ + executable_object_p->extended_object.u.cls.u2.executable_obj_flags |= ECMA_EXECUTABLE_OBJECT_COMPLETED; + return result; + } + + JERRY_CONTEXT (vm_top_context_p) = executable_object_p->frame_ctx.prev_context_p; + + register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx); + stack_top_p = executable_object_p->frame_ctx.stack_top_p; + + if (executable_object_p->frame_ctx.context_depth > 0) + { + while (register_p < register_end_p) + { + ecma_deref_if_object (*register_p++); + } + + vm_ref_lex_env_chain (executable_object_p->frame_ctx.lex_env_p, + executable_object_p->frame_ctx.context_depth, + register_p, + false); + + register_p += executable_object_p->frame_ctx.context_depth; + } + + while (register_p < stack_top_p) + { + ecma_deref_if_object (*register_p++); + } + + ecma_deref_if_object (executable_object_p->iterator); + + return result; +} /* opfunc_resume_executable_object */ + +/** + * Fulfill the next promise of the async generator with the value + */ +void +opfunc_async_generator_yield (ecma_extended_object_t *async_generator_object_p, /**< async generator object */ + ecma_value_t value) /**< value (takes the reference) */ +{ + ecma_async_generator_task_t *task_p; + task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, async_generator_object_p->u.cls.u3.head); + + ecma_value_t iter_result = ecma_create_iter_result_object (value, ECMA_VALUE_FALSE); + ecma_fulfill_promise (task_p->promise, iter_result); + + ecma_free_value (iter_result); + ecma_free_value (value); + + ecma_value_t next = task_p->next; + async_generator_object_p->u.cls.u3.head = next; + + JERRY_ASSERT (task_p->operation_value == ECMA_VALUE_UNDEFINED); + jmem_heap_free_block (task_p, sizeof (ecma_async_generator_task_t)); + + if (!ECMA_IS_INTERNAL_VALUE_NULL (next)) + { + ecma_value_t executable_object = ecma_make_object_value ((ecma_object_t *) async_generator_object_p); + ecma_enqueue_promise_async_generator_job (executable_object); + } +} /* opfunc_async_generator_yield */ + +/** + * Creates a new executable object and awaits for the value + * + * Note: + * extra_flags can be used to set additional extra_info flags + * + * @return a new Promise object on success, error otherwise + */ +ecma_value_t +opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t value, /**< awaited value (takes reference) */ + uint16_t extra_flags) /**< extra flags */ +{ + JERRY_ASSERT ( + CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC + || (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_ARROW)); + + ecma_object_t *promise_p = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE); + ecma_value_t result = ecma_promise_reject_or_resolve (ecma_make_object_value (promise_p), value, true); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + vm_executable_object_t *executable_object_p; + executable_object_p = opfunc_create_executable_object (frame_ctx_p, VM_CREATE_EXECUTABLE_OBJECT_ASYNC); + + executable_object_p->extended_object.u.cls.u2.executable_obj_flags |= extra_flags; + + ecma_promise_async_then (result, ecma_make_object_value ((ecma_object_t *) executable_object_p)); + ecma_deref_object ((ecma_object_t *) executable_object_p); + ecma_free_value (result); + + result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, promise_p); + + JERRY_ASSERT (ecma_is_value_object (result)); + executable_object_p->iterator = result; + + return result; +} /* opfunc_async_create_and_await */ + +/** + * PrivateMethodOrAccessorAdd abstact operation. + * + * See also: ECMAScript v12, 7.3.29. + * + * @return ECMA_VALUE_ERROR - initialization fails + * ECMA_VALUE_UNDEFINED - otherwise + */ +static ecma_value_t +opfunc_private_method_or_accessor_add (ecma_object_t *class_object_p, /**< the function itself */ + ecma_object_t *this_obj_p, /**< this object */ + uint32_t static_flag) /**< static_flag */ +{ + ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS); + ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p); + + if (prop_p == NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_value_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + ecma_value_t *current_p = collection_p + 1; + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + + while (current_p < end_p) + { + uint32_t prop_desc = *current_p++; + ecma_private_property_kind_t kind = ECMA_PRIVATE_PROPERTY_KIND (prop_desc); + + if ((prop_desc & ECMA_PRIVATE_PROPERTY_STATIC_FLAG) != static_flag || kind == ECMA_PRIVATE_FIELD) + { + current_p += 2; + continue; + } + + ecma_string_t *prop_name_p = ecma_get_symbol_from_value (*current_p++); + ecma_value_t method = *current_p++; + + JERRY_ASSERT (prop_name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD); + + prop_p = ecma_find_named_property (this_obj_p, prop_name_p); + ecma_object_t *method_p = ecma_get_object_from_value (method); + + if (kind == ECMA_PRIVATE_METHOD) + { + if (prop_p != NULL) + { + return ecma_raise_type_error (ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE); + } + + ecma_property_value_t *prop_value_p = + ecma_create_named_data_property (this_obj_p, prop_name_p, ECMA_PROPERTY_FIXED, NULL); + prop_value_p->value = method; + continue; + } + + if (prop_p == NULL) + { + ecma_object_t *getter_p = (kind == ECMA_PRIVATE_GETTER) ? method_p : NULL; + ecma_object_t *setter_p = (kind == ECMA_PRIVATE_SETTER) ? method_p : NULL; + ecma_create_named_accessor_property (this_obj_p, prop_name_p, getter_p, setter_p, ECMA_PROPERTY_FIXED, NULL); + continue; + } + + ecma_property_value_t *accessor_objs_p = ECMA_PROPERTY_VALUE_PTR (prop_p); + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (accessor_objs_p); + + if (kind == ECMA_PRIVATE_GETTER) + { + ECMA_SET_POINTER (get_set_pair_p->getter_cp, method_p); + } + else + { + JERRY_ASSERT (kind == ECMA_PRIVATE_SETTER); + ECMA_SET_POINTER (get_set_pair_p->setter_cp, method_p); + } + } + + return ECMA_VALUE_UNDEFINED; +} /* opfunc_private_method_or_accessor_add */ + +/** + * DefineField abstract operation. + * + * See also: ECMAScript v12, 7.3.32. + * + * @return ECMA_VALUE_ERROR - operation fails + * ECMA_VALUE_{TRUE/FALSE} - otherwise + */ +ecma_value_t +opfunc_define_field (ecma_value_t base, /**< base */ + ecma_value_t property, /**< property */ + ecma_value_t value) /**< value */ +{ + ecma_string_t *property_key_p = ecma_op_to_property_key (property); + + JERRY_ASSERT (property_key_p != NULL); + ecma_object_t *obj_p = ecma_get_object_from_value (base); + ecma_property_descriptor_t desc = ecma_make_empty_property_descriptor (); + desc.value = value; + desc.flags = (JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE + | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED + | JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_SHOULD_THROW); + + ecma_value_t result = ecma_op_object_define_own_property (obj_p, property_key_p, &desc); + ecma_deref_ecma_string (property_key_p); + + return result; +} /* opfunc_define_field */ + +/** + * Initialize class fields. + * + * @return ECMA_VALUE_ERROR - initialization fails + * ECMA_VALUE_UNDEFINED - otherwise + */ +ecma_value_t +opfunc_init_class_fields (ecma_object_t *class_object_p, /**< the function itself */ + ecma_value_t this_val) /**< this_arg of the function */ +{ + JERRY_ASSERT (ecma_is_value_object (this_val)); + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_val); + + ecma_value_t result = opfunc_private_method_or_accessor_add (class_object_p, this_obj_p, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT); + ecma_property_t *property_p = ecma_find_named_property (class_object_p, name_p); + + if (property_p == NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + vm_frame_ctx_shared_class_fields_t shared_class_fields; + shared_class_fields.header.status_flags = VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS; + shared_class_fields.computed_class_fields_p = NULL; + + name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED); + ecma_property_t *class_field_property_p = ecma_find_named_property (class_object_p, name_p); + + if (class_field_property_p != NULL) + { + ecma_value_t value = ECMA_PROPERTY_VALUE_PTR (class_field_property_p)->value; + shared_class_fields.computed_class_fields_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value); + } + + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + JERRY_ASSERT (ecma_op_is_callable (property_value_p->value)); + + ecma_extended_object_t *ext_function_p; + ext_function_p = (ecma_extended_object_t *) ecma_get_object_from_value (property_value_p->value); + shared_class_fields.header.bytecode_header_p = ecma_op_function_get_compiled_code (ext_function_p); + shared_class_fields.header.function_object_p = &ext_function_p->object; + + ecma_object_t *scope_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_function_p->u.function.scope_cp); + + result = vm_run (&shared_class_fields.header, this_val, scope_p); + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result) || result == ECMA_VALUE_UNDEFINED); + return result; +} /* opfunc_init_class_fields */ + +/** + * Initialize static class fields. + * + * @return ECMA_VALUE_ERROR - initialization fails + * ECMA_VALUE_UNDEFINED - otherwise + */ +ecma_value_t +opfunc_init_static_class_fields (ecma_value_t function_object, /**< the function itself */ + ecma_value_t this_val) /**< this_arg of the function */ +{ + JERRY_ASSERT (ecma_op_is_callable (function_object)); + JERRY_ASSERT (ecma_is_value_object (this_val)); + + ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED); + ecma_object_t *function_object_p = ecma_get_object_from_value (function_object); + ecma_property_t *class_field_property_p = ecma_find_named_property (function_object_p, name_p); + + vm_frame_ctx_shared_class_fields_t shared_class_fields; + shared_class_fields.header.function_object_p = function_object_p; + shared_class_fields.header.status_flags = VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS; + shared_class_fields.computed_class_fields_p = NULL; + + if (class_field_property_p != NULL) + { + ecma_value_t value = ECMA_PROPERTY_VALUE_PTR (class_field_property_p)->value; + shared_class_fields.computed_class_fields_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value); + } + + ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) function_object_p; + shared_class_fields.header.bytecode_header_p = ecma_op_function_get_compiled_code (ext_function_p); + + ecma_object_t *scope_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_function_p->u.function.scope_cp); + + ecma_value_t result = vm_run (&shared_class_fields.header, this_val, scope_p); + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result) || result == ECMA_VALUE_UNDEFINED); + return result; +} /* opfunc_init_static_class_fields */ + +/** + * Add the name of a computed field to a name list + * + * @return ECMA_VALUE_ERROR - name is not a valid property name + * ECMA_VALUE_UNDEFINED - otherwise + */ +ecma_value_t +opfunc_add_computed_field (ecma_value_t class_object, /**< class object */ + ecma_value_t name) /**< name of the property */ +{ + ecma_string_t *prop_name_p = ecma_op_to_property_key (name); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_prop_name_is_symbol (prop_name_p)) + { + name = ecma_make_symbol_value (prop_name_p); + } + else + { + name = ecma_make_string_value (prop_name_p); + } + + ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED); + ecma_object_t *class_object_p = ecma_get_object_from_value (class_object); + + ecma_property_t *property_p = ecma_find_named_property (class_object_p, name_p); + ecma_value_t *compact_collection_p; + ecma_property_value_t *property_value_p; + + if (property_p == NULL) + { + ECMA_CREATE_INTERNAL_PROPERTY (class_object_p, name_p, property_p, property_value_p); + compact_collection_p = ecma_new_compact_collection (); + } + else + { + property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, property_value_p->value); + } + + compact_collection_p = ecma_compact_collection_push_back (compact_collection_p, name); + ECMA_SET_INTERNAL_VALUE_POINTER (property_value_p->value, compact_collection_p); + return ECMA_VALUE_UNDEFINED; +} /* opfunc_add_computed_field */ + +/** + * Create implicit class constructor + * + * See also: ECMAScript v6, 14.5.14 + * + * @return - new external function ecma-object + */ +ecma_value_t +opfunc_create_implicit_class_constructor (uint8_t opcode, /**< current cbc opcode */ + const ecma_compiled_code_t *bytecode_p) /**< current byte code */ +{ + /* 8. */ + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (JERRY_UNLIKELY (script_p->refs_and_type >= CBC_SCRIPT_REF_MAX)) + { + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } + + ecma_object_t *function_object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE), + sizeof (ecma_extended_object_t), + ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); + + ecma_extended_object_t *constructor_object_p = (ecma_extended_object_t *) function_object_p; + + script_p->refs_and_type += CBC_SCRIPT_REF_ONE; + constructor_object_p->u.constructor_function.script_value = script_value; + constructor_object_p->u.constructor_function.flags = 0; + + /* 10.a.i */ + if (opcode == CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE) + { + constructor_object_p->u.constructor_function.flags |= ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE; + } + + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (function_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + prop_value_p->value = ecma_make_uint32_value (0); + + return ecma_make_object_value (function_object_p); +} /* opfunc_create_implicit_class_constructor */ + +/** + * Set the [[HomeObject]] attribute of the given functon object + * + * @return void + */ +void +opfunc_set_home_object (ecma_object_t *func_p, /**< function object */ + ecma_object_t *parent_env_p) /**< parent environment */ +{ + JERRY_ASSERT (ecma_is_lexical_environment (parent_env_p)); + + if (ecma_get_object_type (func_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p; + ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, + parent_env_p, + JMEM_CP_GET_POINTER_TAG_BITS (ext_func_p->u.function.scope_cp)); + } +} /* opfunc_set_home_object */ + +/** + * Make private key from descriptor + * + * @return pointer to private key + */ +ecma_string_t * +opfunc_make_private_key (ecma_value_t descriptor) /**< descriptor */ +{ + ecma_string_t *private_key_p = ecma_new_symbol_from_descriptor_string (descriptor); + private_key_p->u.hash |= ECMA_SYMBOL_FLAG_PRIVATE_KEY; + + return (ecma_string_t *) private_key_p; +} /* opfunc_make_private_key */ + +/** + * Find a private property in the private elements internal property given the key + * + * @return pointer to the private property - if it is found, + * NULL - othervise + */ +static ecma_property_t * +opfunc_find_private_key (ecma_object_t *class_object_p, /**< class environment */ + ecma_object_t *obj_p, /**< object */ + ecma_string_t *search_key_p, /**< key */ + ecma_string_t **out_private_key_p) /**< [out] private key */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + return NULL; + } + + ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS); + ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p); + + if (prop_p == NULL) + { + return NULL; + } + + ecma_value_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + ecma_value_t *current_p = collection_p + 1; + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + + while (current_p < end_p) + { + current_p++; /* skip kind */ + ecma_string_t *private_key_p = ecma_get_prop_name_from_value (*current_p++); + current_p++; /* skip value */ + + JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p)); + + ecma_string_t *private_key_desc_p = + ecma_get_string_from_value (((ecma_extended_string_t *) private_key_p)->u.symbol_descriptor); + + if (ecma_compare_ecma_strings (private_key_desc_p, search_key_p)) + { + prop_p = ecma_find_named_property (obj_p, private_key_p); + + if (out_private_key_p) + { + *out_private_key_p = private_key_p; + } + + return prop_p; + } + } + + return NULL; +} /* opfunc_find_private_key */ + +/** + * PrivateElementFind abstact operation + * + * See also: ECMAScript v12, 7.3.27 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +static ecma_property_t * +opfunc_find_private_element (ecma_object_t *obj_p, /**< object */ + ecma_string_t *key_p, /**< key */ + ecma_string_t **private_key_p, /**< [out] private key */ + bool allow_heritage) /**< heritage flag */ +{ + JERRY_ASSERT (private_key_p != NULL); + JERRY_ASSERT (*private_key_p == NULL); + ecma_object_t *lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p; + + while (true) + { + JERRY_ASSERT (lex_env_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) != 0 + && !ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + ecma_object_t *class_object_p = ((ecma_lexical_environment_class_t *) lex_env_p)->object_p; + + ecma_property_t *prop_p = opfunc_find_private_key (class_object_p, obj_p, key_p, private_key_p); + + if (prop_p || *private_key_p != NULL) + { + /* Found non shadowed property */ + return prop_p; + } + + if (!allow_heritage) + { + return NULL; + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + return NULL; +} /* opfunc_find_private_element */ + +/** + * In expression runtime evaluation in case of private identifiers + * + * See also: ECMAScript v12, 13.10.1 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if the property was found in the base object + * ECMA_VALUE_FALSE - otherwise + */ +ecma_value_t +opfunc_private_in (ecma_value_t base, /**< base */ + ecma_value_t property) /**< property */ +{ + if (!ecma_is_value_object (base)) + { + return ecma_raise_type_error (ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (base); + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (property); + ecma_string_t *private_key_p = NULL; + + ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, false); + + return ecma_make_boolean_value (prop_p != NULL); +} /* opfunc_private_in */ + +/** + * PrivateFieldAdd abstact operation + * + * See also: ECMAScript v12, 7.3.28 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_private_field_add (ecma_value_t base, /**< base object */ + ecma_value_t property, /**< property name */ + ecma_value_t value) /**< ecma value */ +{ + ecma_object_t *obj_p = ecma_get_object_from_value (base); + ecma_string_t *prop_name_p = ecma_get_string_from_value (property); + ecma_string_t *private_key_p = NULL; + + ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, false); + + if (prop_p != NULL) + { + return ecma_raise_type_error (ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE); + } + + ecma_property_value_t *value_p = + ecma_create_named_data_property (obj_p, private_key_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + + value_p->value = ecma_copy_value_if_not_object (value); + + return ECMA_VALUE_EMPTY; +} /* opfunc_private_field_add */ + +/** + * PrivateSet abstact operation + * + * See also: ECMAScript v12, 7.3.31 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_private_set (ecma_value_t base, /**< this object */ + ecma_value_t property, /**< property name */ + ecma_value_t value) /**< ecma value */ +{ + ecma_value_t base_obj = ecma_op_to_object (base); + + if (ECMA_IS_VALUE_ERROR (base_obj)) + { + return base_obj; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (base_obj); + ecma_string_t *prop_name_p = ecma_get_string_from_value (property); + ecma_string_t *private_key_p = NULL; + + ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, true); + + ecma_value_t result; + + if (prop_p == NULL) + { + result = ecma_raise_type_error (ECMA_ERR_CANNOT_WRITE_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT); + } + else if (*prop_p & ECMA_PROPERTY_FLAG_DATA) + { + JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p)); + + if (private_key_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD) + { + result = ecma_raise_type_error (ECMA_ERR_PRIVATE_METHOD_IS_NOT_WRITABLE); + } + else + { + ecma_value_assign_value (&ECMA_PROPERTY_VALUE_PTR (prop_p)->value, value); + result = ecma_copy_value (value); + } + } + else + { + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (prop_p)); + + if (get_set_pair_p->setter_cp == JMEM_CP_NULL) + { + result = ecma_raise_type_error (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_SETTER); + } + else + { + ecma_object_t *setter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp); + + result = ecma_op_function_call (setter_p, base, &value, 1); + } + } + + ecma_deref_object (obj_p); + + return result; +} /* opfunc_private_set */ + +/** + * PrivateGet abstact operation + * + * See also: ECMAScript v12, 7.3.30 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * private property value - otherwise + */ +ecma_value_t +opfunc_private_get (ecma_value_t base, /**< this object */ + ecma_value_t property) /**< property name */ +{ + ecma_value_t base_obj = ecma_op_to_object (base); + + if (ECMA_IS_VALUE_ERROR (base_obj)) + { + return base_obj; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (base_obj); + ecma_string_t *prop_name_p = ecma_get_string_from_value (property); + ecma_string_t *private_key_p = NULL; + + ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, true); + + ecma_value_t result; + + if (prop_p == NULL) + { + result = ecma_raise_type_error (ECMA_ERR_CANNOT_READ_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT); + } + else if (*prop_p & ECMA_PROPERTY_FLAG_DATA) + { + result = ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + } + else + { + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (prop_p)); + + if (get_set_pair_p->getter_cp == JMEM_CP_NULL) + { + result = ecma_raise_type_error (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_GETTER); + } + else + { + ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); + result = ecma_op_function_call (getter_p, base, NULL, 0); + } + } + + ecma_deref_object (obj_p); + + return result; +} /* opfunc_private_get */ + +/** + * Find the private property in the object who's private key descriptor matches the given key + * + * @return pointer to private key + */ +static ecma_string_t * +opfunc_create_private_key (ecma_value_t *collection_p, /**< collection of private properties */ + ecma_value_t search_key, /**< key */ + ecma_private_property_kind_t search_kind) /**< kind of the property */ +{ + if (search_kind < ECMA_PRIVATE_GETTER) + { + return opfunc_make_private_key (search_key); + } + + ecma_string_t *search_key_p = ecma_get_string_from_value (search_key); + + ecma_value_t *current_p = collection_p + 1; + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + + while (current_p < end_p) + { + ecma_private_property_kind_t kind = ECMA_PRIVATE_PROPERTY_KIND (*current_p++); + ecma_string_t *private_key_p = ecma_get_prop_name_from_value (*current_p++); + current_p++; /* skip value */ + + if (kind < ECMA_PRIVATE_GETTER) + { + continue; + } + + JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p)); + + ecma_string_t *private_key_desc_p = + ecma_get_string_from_value (((ecma_extended_string_t *) private_key_p)->u.symbol_descriptor); + + if (ecma_compare_ecma_strings (private_key_desc_p, search_key_p)) + { + ecma_deref_ecma_string (search_key_p); + ecma_ref_ecma_string (private_key_p); + return private_key_p; + } + } + + return opfunc_make_private_key (search_key); +} /* opfunc_create_private_key */ + +/** + * Collect private members for PrivateMethodOrAccessorAdd and PrivateFieldAdd abstract operations + */ +void +opfunc_collect_private_properties (ecma_value_t constructor, /**< constructor */ + ecma_value_t prop_name, /**< property name */ + ecma_value_t value, /**< value */ + uint8_t opcode) /**< opcode */ +{ + ecma_private_property_kind_t kind = ECMA_PRIVATE_FIELD; + bool is_static = false; + + if (opcode >= CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD) + { + opcode = (uint8_t) (opcode - PARSER_STATIC_PRIVATE_TO_PRIVATE_OFFSET); + is_static = true; + } + + if (opcode == CBC_EXT_COLLECT_PRIVATE_METHOD) + { + prop_name ^= value; + value ^= prop_name; + prop_name ^= value; + kind = ECMA_PRIVATE_METHOD; + } + else if (opcode == CBC_EXT_COLLECT_PRIVATE_GETTER) + { + kind = ECMA_PRIVATE_GETTER; + } + else if (opcode == CBC_EXT_COLLECT_PRIVATE_SETTER) + { + kind = ECMA_PRIVATE_SETTER; + } + + JERRY_ASSERT (ecma_is_value_object (constructor)); + JERRY_ASSERT (ecma_is_value_string (prop_name)); + JERRY_ASSERT (ecma_is_value_object (value) || ecma_is_value_undefined (value)); + + ecma_object_t *constructor_p = ecma_get_object_from_value (constructor); + ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS); + ecma_property_t *prop_p = ecma_find_named_property (constructor_p, internal_string_p); + ecma_value_t *collection_p; + ecma_property_value_t *prop_value_p; + + if (prop_p == NULL) + { + collection_p = ecma_new_compact_collection (); + ECMA_CREATE_INTERNAL_PROPERTY (constructor_p, internal_string_p, prop_p, prop_value_p); + ECMA_SET_INTERNAL_VALUE_POINTER (prop_value_p->value, collection_p); + } + else + { + prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p); + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, prop_value_p->value); + } + + ecma_string_t *key_p = opfunc_create_private_key (collection_p, prop_name, kind); + + if (kind != ECMA_PRIVATE_FIELD) + { + key_p->u.hash |= ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD; + } + + if (is_static) + { + kind = (ecma_private_property_kind_t) ((int) kind | (int) ECMA_PRIVATE_PROPERTY_STATIC_FLAG); + } + + collection_p = ecma_compact_collection_push_back (collection_p, (ecma_value_t) kind); + collection_p = ecma_compact_collection_push_back (collection_p, ecma_make_symbol_value (key_p)); + collection_p = ecma_compact_collection_push_back (collection_p, value); + +#ifndef JERRY_NDEBUG + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + ecma_value_t *current_p = collection_p + 1; + + JERRY_ASSERT ((end_p - current_p) % ECMA_PRIVATE_ELEMENT_LIST_SIZE == 0); +#endif /* !defined (JERRY_NDEBUG) */ + + ECMA_SET_INTERNAL_VALUE_POINTER (prop_value_p->value, collection_p); + + ecma_free_value (value); +} /* opfunc_collect_private_properties */ + +/** + * ClassDefinitionEvaluation environment initialization part + * + * See also: ECMAScript v6, 14.5.14 + */ +void +opfunc_push_class_environment (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t **vm_stack_top, /**< VM stack top */ + ecma_value_t class_name) /**< class name */ +{ + JERRY_ASSERT (ecma_is_value_string (class_name)); + ecma_object_t *class_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p); + + /* 4.a */ + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (class_env_p, + ecma_get_string_from_value (class_name), + ECMA_PROPERTY_FLAG_ENUMERABLE, + NULL); + + property_value_p->value = ECMA_VALUE_UNINITIALIZED; + frame_ctx_p->lex_env_p = class_env_p; + + *(*vm_stack_top)++ = ECMA_VALUE_RELEASE_LEX_ENV; +} /* opfunc_push_class_environment */ + +/** + * ClassDefinitionEvaluation object initialization part + * + * See also: ECMAScript v6, 14.5.14 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_init_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t *stack_top_p) /**< stack top */ +{ + /* 5.b, 6.e.ii */ + ecma_object_t *ctor_parent_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + ecma_object_t *proto_parent_p = NULL; + bool free_proto_parent = false; + + ecma_value_t super_class = stack_top_p[-2]; + ecma_object_t *ctor_p = ecma_get_object_from_value (stack_top_p[-1]); + + bool heritage_present = !ecma_is_value_array_hole (super_class); + + /* 5. ClassHeritage opt is not present */ + if (!heritage_present) + { + /* 5.a */ + proto_parent_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + } + else if (!ecma_is_value_null (super_class)) + { + /* 6.f, 6.g.i */ + if (!ecma_is_constructor (super_class)) + { + return ecma_raise_type_error (ECMA_ERR_CLASS_EXTENDS_NOT_CONSTRUCTOR); + } + + ecma_object_t *parent_p = ecma_get_object_from_value (super_class); + + /* 6.g.ii */ + ecma_value_t proto_parent = ecma_op_object_get_by_magic_id (parent_p, LIT_MAGIC_STRING_PROTOTYPE); + + /* 6.g.iii */ + if (ECMA_IS_VALUE_ERROR (proto_parent)) + { + return proto_parent; + } + + /* 6.g.iv */ + if (ecma_is_value_object (proto_parent)) + { + proto_parent_p = ecma_get_object_from_value (proto_parent); + free_proto_parent = true; + } + else if (ecma_is_value_null (proto_parent)) + { + proto_parent_p = NULL; + } + else + { + ecma_free_value (proto_parent); + return ecma_raise_type_error (ECMA_ERR_PROPERTY_PROTOTYPE_IS_NOT_AN_OBJECT); + } + + /* 6.g.v */ + ctor_parent_p = parent_p; + } + + /* 7. */ + ecma_object_t *proto_p = ecma_create_object (proto_parent_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_value_t proto = ecma_make_object_value (proto_p); + + ECMA_SET_POINTER (ctor_p->u2.prototype_cp, ctor_parent_p); + + if (free_proto_parent) + { + ecma_deref_object (proto_parent_p); + } + ecma_free_value (super_class); + + /* 16. */ + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (ctor_p, + ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE), + ECMA_PROPERTY_FIXED, + NULL); + property_value_p->value = proto; + + /* 18. */ + property_value_p = ecma_create_named_data_property (proto_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR), + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + property_value_p->value = ecma_make_object_value (ctor_p); + + if (ecma_get_object_type (ctor_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + opfunc_bind_class_environment (frame_ctx_p->lex_env_p, proto_p, ctor_p, ctor_p); + + /* 15. set F’s [[ConstructorKind]] internal slot to "derived". */ + if (heritage_present) + { + ECMA_SET_THIRD_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) ctor_p)->u.function.scope_cp); + } + } + + stack_top_p[-2] = stack_top_p[-1]; + stack_top_p[-1] = proto; + + return ECMA_VALUE_EMPTY; +} /* opfunc_init_class */ + +/** + * Creates a new class lexical environment and binds the bound object and the class's object + * + * @return newly created class lexical environment - if func_obj_p is not present + * NULL - otherwise, also the environment is set as the func_obj_p's scope + */ +ecma_object_t * +opfunc_bind_class_environment (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_object_t *home_object_p, /**< bound object */ + ecma_object_t *ctor_p, /**< constructor object */ + ecma_object_t *func_obj_p) /**< function object */ +{ + ecma_object_t *proto_env_p = ecma_create_lex_env_class (lex_env_p, sizeof (ecma_lexical_environment_class_t)); + ECMA_SET_NON_NULL_POINTER (proto_env_p->u1.bound_object_cp, home_object_p); + ((ecma_lexical_environment_class_t *) proto_env_p)->object_p = ctor_p; + ((ecma_lexical_environment_class_t *) proto_env_p)->type = ECMA_LEX_ENV_CLASS_TYPE_CLASS_ENV; + + if (func_obj_p) + { + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); + ECMA_SET_NON_NULL_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp, proto_env_p, 0); + ecma_deref_object (proto_env_p); + return NULL; + } + + return proto_env_p; +} /* opfunc_bind_class_environment */ + +/** + * Set [[Enumerable]] and [[HomeObject]] attributes for all class method + */ +static void +opfunc_set_class_attributes (ecma_object_t *obj_p, /**< object */ + ecma_object_t *parent_env_p) /**< parent environment */ +{ + jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (uint32_t index = 0; index < ECMA_PROPERTY_PAIR_ITEM_COUNT; index++) + { + uint8_t property = property_pair_p->header.types[index]; + + if (!ECMA_PROPERTY_IS_RAW (property)) + { + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_DELETED + || (ECMA_PROPERTY_IS_INTERNAL (property) + && LIT_INTERNAL_MAGIC_STRING_IGNORED (property_pair_p->names_cp[index]))); + continue; + } + + if (property & ECMA_PROPERTY_FLAG_DATA) + { + if (ecma_is_value_object (property_pair_p->values[index].value) && ecma_is_property_enumerable (property)) + { + property_pair_p->header.types[index] = (uint8_t) (property & ~ECMA_PROPERTY_FLAG_ENUMERABLE); + opfunc_set_home_object (ecma_get_object_from_value (property_pair_p->values[index].value), parent_env_p); + } + continue; + } + + property_pair_p->header.types[index] = (uint8_t) (property & ~ECMA_PROPERTY_FLAG_ENUMERABLE); + ecma_property_value_t *accessor_objs_p = property_pair_p->values + index; + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (accessor_objs_p); + + if (get_set_pair_p->getter_cp != JMEM_CP_NULL) + { + opfunc_set_home_object (ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp), parent_env_p); + } + + if (get_set_pair_p->setter_cp != JMEM_CP_NULL) + { + opfunc_set_home_object (ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp), parent_env_p); + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } +} /* opfunc_set_class_attributes */ + +/** + * Set [[HomeObject]] attributes for all class private elements + */ +static void +opfunc_set_private_instance_method_attributes (ecma_object_t *class_object_p, /**< class constructor */ + ecma_object_t *parent_env_p) /**< parent environment */ +{ + ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS); + ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p); + + if (prop_p == NULL) + { + return; + } + + ecma_value_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + ecma_value_t *current_p = collection_p + 1; + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + + while (current_p < end_p) + { + current_p += 2; /* skip kind, name */ + ecma_value_t value = *current_p++; + + if (!ecma_is_value_undefined (value)) + { + opfunc_set_home_object (ecma_get_object_from_value (value), parent_env_p); + } + } +} /* opfunc_set_private_instance_method_attributes */ + +/** + * Pop the current lexical environment referenced by the frame context + */ +void +opfunc_pop_lexical_environment (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + ecma_object_t *outer_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, frame_ctx_p->lex_env_p->u2.outer_reference_cp); + ecma_deref_object (frame_ctx_p->lex_env_p); + frame_ctx_p->lex_env_p = outer_env_p; +} /* opfunc_pop_lexical_environment */ + +/** + * ClassDefinitionEvaluation finalization part + * + * See also: ECMAScript v6, 14.5.14 + */ +void +opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t **vm_stack_top_p, /**< current vm stack top */ + ecma_value_t class_name) /**< class name */ +{ + JERRY_ASSERT (ecma_is_value_undefined (class_name) || ecma_is_value_string (class_name)); + ecma_value_t *stack_top_p = *vm_stack_top_p; + + ecma_object_t *ctor_p = ecma_get_object_from_value (stack_top_p[-2]); + ecma_object_t *proto_p = ecma_get_object_from_value (stack_top_p[-1]); + + ecma_object_t *class_env_p = frame_ctx_p->lex_env_p; + + /* 23.a */ + if (!ecma_is_value_undefined (class_name)) + { + ecma_op_initialize_binding (class_env_p, ecma_get_string_from_value (class_name), stack_top_p[-2]); + } + + ecma_object_t *ctor_env_p = opfunc_bind_class_environment (class_env_p, ctor_p, ctor_p, NULL); + ecma_object_t *proto_env_p = opfunc_bind_class_environment (class_env_p, proto_p, ctor_p, NULL); + + opfunc_set_class_attributes (ctor_p, ctor_env_p); + opfunc_set_class_attributes (proto_p, proto_env_p); + opfunc_set_private_instance_method_attributes (ctor_p, proto_env_p); + + ecma_deref_object (proto_env_p); + ecma_deref_object (ctor_env_p); + ecma_deref_object (proto_p); + + JERRY_ASSERT ((ecma_is_value_undefined (class_name) ? stack_top_p[-3] == ECMA_VALUE_UNDEFINED + : stack_top_p[-3] == ECMA_VALUE_RELEASE_LEX_ENV)); + + /* only the current class remains on the stack */ + if (stack_top_p[-3] == ECMA_VALUE_RELEASE_LEX_ENV) + { + opfunc_pop_lexical_environment (frame_ctx_p); + } + + ecma_value_t result = opfunc_private_method_or_accessor_add (ctor_p, ctor_p, ECMA_PRIVATE_PROPERTY_STATIC_FLAG); + JERRY_ASSERT (ecma_is_value_undefined (result)); + + stack_top_p[-3] = stack_top_p[-2]; + *vm_stack_top_p -= 2; +} /* opfunc_finalize_class */ + +/** + * MakeSuperPropertyReference operation + * + * See also: ECMAScript v6, 12.3.5.3 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stack top */ + vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t prop_name, /**< property name to resolve */ + uint8_t opcode) /**< current cbc opcode */ +{ + ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (frame_ctx_p->lex_env_p); + + if (environment_record_p && !ecma_op_this_binding_is_initialized (environment_record_p)) + { + return ecma_raise_reference_error (ECMA_ERR_CALL_SUPER_CONSTRUCTOR_DERIVED_CLASS_BEFORE_THIS); + } + + ecma_value_t parent = ecma_op_resolve_super_base (frame_ctx_p->lex_env_p); + + if (ECMA_IS_VALUE_ERROR (parent)) + { + return ecma_raise_type_error (ECMA_ERR_INVOKE_NULLABLE_SUPER_METHOD); + } + + if (!ecma_op_require_object_coercible (parent)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t *stack_top_p = *vm_stack_top_p; + + if (opcode >= CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE) + { + JERRY_ASSERT (opcode == CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE + || opcode == CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE); + *stack_top_p++ = parent; + *stack_top_p++ = ecma_copy_value (prop_name); + *vm_stack_top_p = stack_top_p; + + return ECMA_VALUE_EMPTY; + } + + ecma_object_t *parent_p = ecma_get_object_from_value (parent); + ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name); + + if (prop_name_p == NULL) + { + ecma_deref_object (parent_p); + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_op_object_get_with_receiver (parent_p, prop_name_p, frame_ctx_p->this_binding); + ecma_deref_ecma_string (prop_name_p); + ecma_deref_object (parent_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (opcode == CBC_EXT_SUPER_PROP_LITERAL_REFERENCE || opcode == CBC_EXT_SUPER_PROP_REFERENCE) + { + *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding); + *stack_top_p++ = ECMA_VALUE_UNDEFINED; + } + + *stack_top_p++ = result; + *vm_stack_top_p = stack_top_p; + + return ECMA_VALUE_EMPTY; +} /* opfunc_form_super_reference */ + +/** + * Assignment operation for SuperRefence base + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, /**< vm stack top */ + vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + uint32_t opcode_data) /**< opcode data to store the result */ +{ + ecma_value_t *stack_top_p = *vm_stack_top_p; + + ecma_value_t base_obj = ecma_op_to_object (stack_top_p[-3]); + + if (ECMA_IS_VALUE_ERROR (base_obj)) + { + return base_obj; + } + + ecma_object_t *base_obj_p = ecma_get_object_from_value (base_obj); + ecma_string_t *prop_name_p = ecma_op_to_property_key (stack_top_p[-2]); + + if (prop_name_p == NULL) + { + ecma_deref_object (base_obj_p); + return ECMA_VALUE_ERROR; + } + + bool is_strict = (frame_ctx_p->status_flags & VM_FRAME_CTX_IS_STRICT) != 0; + + ecma_value_t result = + ecma_op_object_put_with_receiver (base_obj_p, prop_name_p, stack_top_p[-1], frame_ctx_p->this_binding, is_strict); + + ecma_deref_ecma_string (prop_name_p); + ecma_deref_object (base_obj_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + for (int32_t i = 1; i <= 3; i++) + { + ecma_free_value (stack_top_p[-i]); + } + + stack_top_p -= 3; + + if (opcode_data & VM_OC_PUT_STACK) + { + *stack_top_p++ = result; + } + else if (opcode_data & VM_OC_PUT_BLOCK) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = result; + } + + *vm_stack_top_p = stack_top_p; + + return result; +} /* opfunc_assign_super_reference */ + +/** + * Copy data properties of an object + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_copy_data_properties (ecma_value_t target_object, /**< target object */ + ecma_value_t source_object, /**< source object */ + ecma_value_t filter_array) /**< filter array */ +{ + bool source_to_object = false; + + if (!ecma_is_value_object (source_object)) + { + source_object = ecma_op_to_object (source_object); + + if (ECMA_IS_VALUE_ERROR (source_object)) + { + return source_object; + } + + source_to_object = true; + } + + ecma_object_t *source_object_p = ecma_get_object_from_value (source_object); + ecma_collection_t *names_p = ecma_op_object_own_property_keys (source_object_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (names_p == NULL) + { + JERRY_ASSERT (!source_to_object); + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_object_t *target_object_p = ecma_get_object_from_value (target_object); + ecma_value_t *buffer_p = names_p->buffer_p; + ecma_value_t *buffer_end_p = buffer_p + names_p->item_count; + ecma_value_t *filter_start_p = NULL; + ecma_value_t *filter_end_p = NULL; + ecma_value_t result = ECMA_VALUE_EMPTY; + + if (filter_array != ECMA_VALUE_UNDEFINED) + { + ecma_object_t *filter_array_p = ecma_get_object_from_value (filter_array); + + JERRY_ASSERT (ecma_get_object_type (filter_array_p) == ECMA_OBJECT_TYPE_ARRAY); + JERRY_ASSERT (ecma_op_object_is_fast_array (filter_array_p)); + + if (filter_array_p->u1.property_list_cp != JMEM_CP_NULL) + { + filter_start_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, filter_array_p->u1.property_list_cp); + filter_end_p = filter_start_p + ((ecma_extended_object_t *) filter_array_p)->u.array.length; + } + } + + while (buffer_p < buffer_end_p) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (*buffer_p++); + + if (filter_start_p != NULL) + { + ecma_value_t *filter_p = filter_start_p; + + do + { + if (ecma_compare_ecma_strings (property_name_p, ecma_get_prop_name_from_value (*filter_p))) + { + break; + } + } while (++filter_p < filter_end_p); + + if (filter_p != filter_end_p) + { + continue; + } + } + + ecma_property_descriptor_t descriptor; + result = ecma_op_object_get_own_property_descriptor (source_object_p, property_name_p, &descriptor); + + if (ECMA_IS_VALUE_ERROR (result)) + { + break; + } + + if (result == ECMA_VALUE_FALSE) + { + continue; + } + + if (!(descriptor.flags & JERRY_PROP_IS_ENUMERABLE)) + { + ecma_free_property_descriptor (&descriptor); + continue; + } + + if ((descriptor.flags & JERRY_PROP_IS_VALUE_DEFINED) && !ECMA_OBJECT_IS_PROXY (source_object_p)) + { + result = descriptor.value; + } + else + { + ecma_free_property_descriptor (&descriptor); + + result = ecma_op_object_get (source_object_p, property_name_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + break; + } + } + + opfunc_set_data_property (target_object_p, property_name_p, result); + ecma_free_value (result); + + result = ECMA_VALUE_EMPTY; + } + + if (JERRY_UNLIKELY (source_to_object)) + { + ecma_deref_object (source_object_p); + } + + ecma_collection_free (names_p); + return result; +} /* opfunc_copy_data_properties */ + +/** + * Check whether the current lexical scope has restricted binding declaration with the given name + * + * Steps are include ES11: 8.1.1.4.14 HasRestrictedGlobalProperty abstract operation + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if it has restricted property binding + * ECMA_VALUE_FALSE - otherwise + */ +ecma_value_t +opfunc_lexical_scope_has_restricted_binding (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_string_t *name_p) /**< binding name */ +{ + JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + +#if JERRY_BUILTIN_REALMS + JERRY_ASSERT (frame_ctx_p->this_binding == JERRY_CONTEXT (global_object_p)->this_binding); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_ASSERT (frame_ctx_p->this_binding == ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + ecma_property_t *binding_p = ecma_find_named_property (lex_env_p, name_p); + + if (binding_p != NULL) + { + return ECMA_VALUE_TRUE; + } + +#if JERRY_BUILTIN_REALMS + ecma_object_t *const global_scope_p = ecma_get_global_scope ((ecma_object_t *) JERRY_CONTEXT (global_object_p)); +#else /* !JERRY_BUILTIN_REALMS */ + ecma_object_t *const global_scope_p = ecma_get_global_scope (global_obj_p); +#endif /* JERRY_BUILTIN_REALMS */ + + if (global_scope_p != lex_env_p) + { + return ECMA_VALUE_FALSE; + } + + ecma_object_t *global_obj_p = ecma_get_object_from_value (frame_ctx_p->this_binding); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (global_obj_p)) + { + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_proxy_object_get_own_property_descriptor (global_obj_p, name_p, &prop_desc); + + if (ecma_is_value_true (status)) + { + status = ecma_make_boolean_value ((prop_desc.flags & JERRY_PROP_IS_CONFIGURABLE) == 0); + ecma_free_property_descriptor (&prop_desc); + } + + return status; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_property_t property = ecma_op_object_get_own_property (global_obj_p, name_p, NULL, ECMA_PROPERTY_GET_NO_OPTIONS); + + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND || ECMA_PROPERTY_IS_FOUND (property)); + + return ecma_make_boolean_value (property != ECMA_PROPERTY_TYPE_NOT_FOUND + && !ecma_is_property_configurable (property)); +} /* opfunc_lexical_scope_has_restricted_binding */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.h b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.h new file mode 100644 index 00000000..7a964bc3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.h @@ -0,0 +1,173 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OPCODES_H +#define OPCODES_H + +#include "ecma-globals.h" + +#include "vm-defines.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_opcodes Opcodes + * @{ + */ + +/** + * Number arithmetic operations. + */ +typedef enum +{ + NUMBER_ARITHMETIC_SUBTRACTION, /**< subtraction */ + NUMBER_ARITHMETIC_MULTIPLICATION, /**< multiplication */ + NUMBER_ARITHMETIC_DIVISION, /**< division */ + NUMBER_ARITHMETIC_REMAINDER, /**< remainder calculation */ + NUMBER_ARITHMETIC_EXPONENTIATION, /**< exponentiation */ +} number_arithmetic_op; + +/** + * Number bitwise logic operations. + */ +typedef enum +{ + NUMBER_BITWISE_LOGIC_AND, /**< bitwise AND calculation */ + NUMBER_BITWISE_LOGIC_OR, /**< bitwise OR calculation */ + NUMBER_BITWISE_LOGIC_XOR, /**< bitwise XOR calculation */ + NUMBER_BITWISE_SHIFT_LEFT, /**< bitwise LEFT SHIFT calculation */ + NUMBER_BITWISE_SHIFT_RIGHT, /**< bitwise RIGHT_SHIFT calculation */ + NUMBER_BITWISE_SHIFT_URIGHT, /**< bitwise UNSIGNED RIGHT SHIFT calculation */ +} number_bitwise_logic_op; + +/** + * Types for opfunc_create_executable_object. + */ +typedef enum +{ + VM_CREATE_EXECUTABLE_OBJECT_GENERATOR, /**< create a generator function */ + VM_CREATE_EXECUTABLE_OBJECT_ASYNC, /**< create an async function */ +} vm_create_executable_object_type_t; + +/** + * The stack contains spread object during the upcoming APPEND_ARRAY operation + */ +#define OPFUNC_HAS_SPREAD_ELEMENT (1 << 8) + +ecma_value_t opfunc_equality (ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t do_number_arithmetic (number_arithmetic_op op, ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t opfunc_unary_operation (ecma_value_t left_value, bool is_plus); + +ecma_value_t do_number_bitwise_logic (number_bitwise_logic_op op, ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t do_number_bitwise_not (ecma_value_t value); + +ecma_value_t opfunc_addition (ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t opfunc_relation (ecma_value_t left_value, ecma_value_t right_value, bool left_first, bool is_invert); + +ecma_value_t opfunc_in (ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t opfunc_instanceof (ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t opfunc_typeof (ecma_value_t left_value); + +void opfunc_set_data_property (ecma_object_t *object_p, ecma_string_t *prop_name_p, ecma_value_t value); + +void opfunc_set_accessor (bool is_getter, ecma_value_t object, ecma_string_t *accessor_name_p, ecma_value_t accessor); + +ecma_value_t vm_op_delete_prop (ecma_value_t object, ecma_value_t property, bool is_strict); + +ecma_value_t vm_op_delete_var (ecma_value_t name_literal, ecma_object_t *lex_env_p); + +ecma_collection_t *opfunc_for_in (ecma_value_t left_value, ecma_value_t *result_obj_p); + +ecma_collection_t *opfunc_spread_arguments (ecma_value_t *stack_top_p, uint8_t argument_list_len); + +ecma_value_t opfunc_append_array (ecma_value_t *stack_top_p, uint16_t values_length); + +vm_executable_object_t *opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, + vm_create_executable_object_type_t type); + +extern const uint8_t opfunc_resume_executable_object_with_throw[]; +extern const uint8_t opfunc_resume_executable_object_with_return[]; + +ecma_value_t opfunc_resume_executable_object (vm_executable_object_t *executable_object_p, ecma_value_t value); + +void opfunc_async_generator_yield (ecma_extended_object_t *async_generator_object_p, ecma_value_t value); + +ecma_value_t opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, ecma_value_t value, uint16_t extra_flags); + +ecma_value_t opfunc_init_class_fields (ecma_object_t *class_object_p, ecma_value_t this_val); + +ecma_value_t opfunc_init_static_class_fields (ecma_value_t function_object, ecma_value_t this_val); + +ecma_value_t opfunc_add_computed_field (ecma_value_t class_object, ecma_value_t name); + +ecma_value_t opfunc_create_implicit_class_constructor (uint8_t opcode, const ecma_compiled_code_t *bytecode_p); + +void opfunc_set_home_object (ecma_object_t *func_p, ecma_object_t *parent_env_p); + +ecma_value_t opfunc_define_field (ecma_value_t base, ecma_value_t property, ecma_value_t value); + +ecma_string_t *opfunc_make_private_key (ecma_value_t descriptor); + +ecma_value_t opfunc_private_in (ecma_value_t base, ecma_value_t property); + +ecma_value_t opfunc_private_field_add (ecma_value_t base, ecma_value_t property, ecma_value_t value); + +ecma_value_t opfunc_private_set (ecma_value_t base, ecma_value_t property, ecma_value_t value); + +ecma_value_t opfunc_private_get (ecma_value_t base, ecma_value_t property); + +void opfunc_collect_private_properties (ecma_value_t constructor, + ecma_value_t prop_name, + ecma_value_t method, + uint8_t opcode); + +void opfunc_push_class_environment (vm_frame_ctx_t *frame_ctx_p, ecma_value_t **vm_stack_top, ecma_value_t class_name); + +ecma_value_t opfunc_init_class (vm_frame_ctx_t *frame_context_p, ecma_value_t *stack_top_p); + +ecma_object_t *opfunc_bind_class_environment (ecma_object_t *lex_env_p, + ecma_object_t *home_object_p, + ecma_object_t *ctor_p, + ecma_object_t *func_obj_p); + +void opfunc_pop_lexical_environment (vm_frame_ctx_t *frame_ctx_p); + +void opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, ecma_value_t **vm_stack_top_p, ecma_value_t class_name); + +ecma_value_t opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, + vm_frame_ctx_t *frame_ctx_p, + ecma_value_t prop_name, + uint8_t opcode); + +ecma_value_t +opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, vm_frame_ctx_t *frame_ctx_p, uint32_t opcode_data); + +ecma_value_t +opfunc_copy_data_properties (ecma_value_t target_object, ecma_value_t source_object, ecma_value_t filter_array); + +ecma_value_t opfunc_lexical_scope_has_restricted_binding (vm_frame_ctx_t *vm_frame_ctx_p, ecma_string_t *name_p); + +/** + * @} + * @} + */ + +#endif /* !OPCODES_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm-defines.h b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-defines.h new file mode 100644 index 00000000..7ca78131 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-defines.h @@ -0,0 +1,169 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef VM_DEFINES_H +#define VM_DEFINES_H + +#include "ecma-globals.h" + +#include "byte-code.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_executor Executor + * @{ + */ + +/** + * Helper for += on uint16_t values. + */ +#define VM_PLUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) + (value)) + +/** + * Helper for -= on uint16_t values. + */ +#define VM_MINUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) - (value)) + +/** + * Flag bits of vm_frame_ctx_shared_t + */ +typedef enum +{ + VM_FRAME_CTX_SHARED_HAS_ARG_LIST = (1 << 0), /**< has argument list */ + VM_FRAME_CTX_SHARED_DIRECT_EVAL = (1 << 1), /**< direct eval call */ + VM_FRAME_CTX_SHARED_FREE_THIS = (1 << 2), /**< free this binding */ + VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV = (1 << 3), /**< free local environment */ + VM_FRAME_CTX_SHARED_NON_ARROW_FUNC = (1 << 4), /**< non-arrow function */ + VM_FRAME_CTX_SHARED_HERITAGE_PRESENT = (1 << 5), /**< class heritage present */ + VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS = (1 << 6), /**< has class fields */ + VM_FRAME_CTX_SHARED_EXECUTABLE = (1 << 7), /**< frame is an executable object constructed + * with opfunc_create_executable_object */ +} vm_frame_ctx_shared_flags_t; + +/** + * Shared data between the interpreter and the caller + */ +typedef struct +{ + const ecma_compiled_code_t *bytecode_header_p; /**< currently executed byte-code data */ + ecma_object_t *function_object_p; /**< function obj */ + uint32_t status_flags; /**< combination of vm_frame_ctx_shared_flags_t bits */ +} vm_frame_ctx_shared_t; + +/** + * Shared data extended with arguments + */ +typedef struct +{ + vm_frame_ctx_shared_t header; /**< shared data header */ + const ecma_value_t *arg_list_p; /**< arguments list */ + uint32_t arg_list_len; /**< arguments list length */ +} vm_frame_ctx_shared_args_t; + +/** + * Shared data extended with computed class fields + */ +typedef struct +{ + vm_frame_ctx_shared_t header; /**< shared data header */ + ecma_value_t *computed_class_fields_p; /**< names of the computed class fields */ +} vm_frame_ctx_shared_class_fields_t; + +/** + * Get the computed class field + */ +#define VM_GET_COMPUTED_CLASS_FIELDS(frame_ctx_p) \ + (((vm_frame_ctx_shared_class_fields_t *) ((frame_ctx_p)->shared_p))->computed_class_fields_p) + +/** + * Flag bits of vm_frame_ctx_t + */ +typedef enum +{ + VM_FRAME_CTX_DIRECT_EVAL = (1 << 1), /**< direct eval call */ + VM_FRAME_CTX_IS_STRICT = (1 << 2), /**< strict mode */ +} vm_frame_ctx_flags_t; + +/** + * Context of interpreter, related to a JS stack frame + */ +typedef struct vm_frame_ctx_t +{ + vm_frame_ctx_shared_t *shared_p; /**< shared information */ + const uint8_t *byte_code_p; /**< current byte code pointer */ + const uint8_t *byte_code_start_p; /**< byte code start pointer */ + ecma_value_t *stack_top_p; /**< stack top pointer */ + ecma_value_t *literal_start_p; /**< literal list start pointer */ + ecma_object_t *lex_env_p; /**< current lexical environment */ + struct vm_frame_ctx_t *prev_context_p; /**< previous context */ + ecma_value_t this_binding; /**< this binding */ + uint16_t context_depth; /**< current context depth */ + uint8_t status_flags; /**< combination of vm_frame_ctx_flags_t bits */ + uint8_t call_operation; /**< perform a call or construct operation */ + /* Registers start immediately after the frame context. */ +} vm_frame_ctx_t; + +/** + * Get register list corresponding to the frame context. + */ +#define VM_GET_REGISTERS(frame_ctx_p) ((ecma_value_t *) ((frame_ctx_p) + 1)) + +/** + * Read or write a specific register. + */ +#define VM_GET_REGISTER(frame_ctx_p, i) (((ecma_value_t *) ((frame_ctx_p) + 1))[i]) + +/** + * Calculate the executable object from a vm_executable_object frame context. + */ +#define VM_GET_EXECUTABLE_OBJECT(frame_ctx_p) \ + ((ecma_extended_object_t *) ((uintptr_t) (frame_ctx_p) - (uintptr_t) offsetof (vm_executable_object_t, frame_ctx))) + +/** + * Calculate the shared_part from a vm_executable_object frame context. + */ +#define VM_GET_EXECUTABLE_ITERATOR(frame_ctx_p) \ + ((ecma_value_t *) ((uintptr_t) (frame_ctx_p) - (uintptr_t) offsetof (vm_executable_object_t, frame_ctx) \ + + (uintptr_t) offsetof (vm_executable_object_t, iterator))) + +/** + * Generator frame context. + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + vm_frame_ctx_shared_t shared; /**< shared part */ + ecma_value_t iterator; /**< executable object's iterator */ + vm_frame_ctx_t frame_ctx; /**< frame context part */ +} vm_executable_object_t; + +/** + * Real backtrace frame data passed to the jerry_backtrace_cb_t handler. + */ +struct jerry_frame_internal_t +{ + vm_frame_ctx_t *context_p; /**< context pointer */ + uint8_t frame_type; /**< frame type */ + jerry_frame_location_t location; /**< location information */ + ecma_value_t function; /**< function reference */ + ecma_value_t this_binding; /**< this binding passed to the function */ +}; + +/** + * @} + * @} + */ + +#endif /* !VM_DEFINES_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.cpp new file mode 100644 index 00000000..62f46c7a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.cpp @@ -0,0 +1,546 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "vm-stack.h" + +#include "ecma-alloc.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" +#include "vm-defines.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup stack VM stack + * @{ + */ + +JERRY_STATIC_ASSERT (((int)PARSER_WITH_CONTEXT_STACK_ALLOCATION == (int)PARSER_BLOCK_CONTEXT_STACK_ALLOCATION), + with_context_stack_allocation_must_be_equal_to_block_context_stack_allocation); + +JERRY_STATIC_ASSERT (((int)PARSER_WITH_CONTEXT_STACK_ALLOCATION == (int)PARSER_TRY_CONTEXT_STACK_ALLOCATION), + with_context_stack_allocation_must_be_equal_to_block_context_stack_allocation); + +JERRY_STATIC_ASSERT (((int)PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION == (int)PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION), + for_of_context_stack_allocation_must_be_equal_to_for_await_of_context_stack_allocation); + +/** + * Abort (finalize) the current variable length stack context, and remove it. + * + * @return new stack top + */ +ecma_value_t * +vm_stack_context_abort_variable_length (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t *vm_stack_top_p, /**< current stack top */ + uint32_t context_stack_allocation) /**< 0 - if all context element + * should be released + * context stack allocation - otherwise */ +{ + JERRY_ASSERT (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]))); + + uint32_t context_size = VM_GET_CONTEXT_END (vm_stack_top_p[-1]); + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size); + + JERRY_ASSERT (context_size > 0); + --vm_stack_top_p; + + if (context_stack_allocation == 0) + { + context_stack_allocation = context_size; + } + + for (uint32_t i = 1; i < context_stack_allocation; i++) + { + ecma_free_value (*(--vm_stack_top_p)); + } + + return vm_stack_top_p; +} /* vm_stack_context_abort_variable_length */ + +/** + * Abort (finalize) the current stack context, and remove it. + * + * @return new stack top + */ +ecma_value_t * +vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t *vm_stack_top_p) /**< current stack top */ +{ + ecma_value_t context_info = vm_stack_top_p[-1]; + + if (context_info & VM_CONTEXT_HAS_LEX_ENV) + { + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + ecma_deref_object (lex_env_p); + } + + switch (VM_GET_CONTEXT_TYPE (context_info)) + { + case VM_CONTEXT_FINALLY_THROW: + case VM_CONTEXT_FINALLY_RETURN: + { + ecma_free_value (vm_stack_top_p[-2]); + /* FALLTHRU */ + } + case VM_CONTEXT_FINALLY_JUMP: + { + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); + vm_stack_top_p -= PARSER_FINALLY_CONTEXT_STACK_ALLOCATION; + break; + } + case VM_CONTEXT_TRY: + case VM_CONTEXT_CATCH: + case VM_CONTEXT_BLOCK: + case VM_CONTEXT_WITH: + { + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); + vm_stack_top_p -= PARSER_WITH_CONTEXT_STACK_ALLOCATION; + break; + } + case VM_CONTEXT_ITERATOR: + case VM_CONTEXT_OBJ_INIT: + case VM_CONTEXT_OBJ_INIT_REST: + { + vm_stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p, vm_stack_top_p, 0); + break; + } + case VM_CONTEXT_FOR_OF: + case VM_CONTEXT_FOR_AWAIT_OF: + { + ecma_free_value (vm_stack_top_p[-2]); + ecma_free_value (vm_stack_top_p[-3]); + ecma_free_value (vm_stack_top_p[-4]); + + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); + vm_stack_top_p -= PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION; + break; + } + default: + { + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]) == VM_CONTEXT_FOR_IN); + + ecma_collection_t *collection_p; + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, vm_stack_top_p[-2]); + + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t index = vm_stack_top_p[-3]; index < collection_p->item_count; index++) + { + ecma_free_value (buffer_p[index]); + } + + ecma_collection_destroy (collection_p); + + ecma_free_value (vm_stack_top_p[-4]); + + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION); + vm_stack_top_p -= PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION; + break; + } + } + + return vm_stack_top_p; +} /* vm_stack_context_abort */ + +/** + * Decode branch offset. + * + * @return branch offset + */ +static uint32_t +vm_decode_branch_offset (const uint8_t *branch_offset_p, /**< start offset of byte code */ + uint32_t length) /**< length of the branch */ +{ + uint32_t branch_offset = *branch_offset_p; + + JERRY_ASSERT (length >= 1 && length <= 3); + + switch (length) + { + case 3: + { + branch_offset <<= 8; + branch_offset |= *(++branch_offset_p); + /* FALLTHRU */ + } + case 2: + { + branch_offset <<= 8; + branch_offset |= *(++branch_offset_p); + break; + } + } + + return branch_offset; +} /* vm_decode_branch_offset */ + +/** + * Byte code which resumes an executable object with throw + */ +static const uint8_t vm_stack_resume_executable_object_with_context_end[1] = { CBC_CONTEXT_END }; + +/** + * Find a finally up to the end position. + * + * @return value specified in vm_stack_found_type + */ +vm_stack_found_type +vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t *stack_top_p, /**< current stack top */ + vm_stack_context_type_t finally_type, /**< searching this finally */ + uint32_t search_limit) /**< search up-to this byte code */ +{ + JERRY_ASSERT (finally_type <= VM_CONTEXT_FINALLY_RETURN); + + if (finally_type != VM_CONTEXT_FINALLY_JUMP) + { + search_limit = 0xffffffffu; + } + + while (frame_ctx_p->context_depth > 0) + { + vm_stack_context_type_t context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]); + uint32_t context_end = VM_GET_CONTEXT_END (stack_top_p[-1]); + JERRY_ASSERT (!VM_CONTEXT_IS_VARIABLE_LENGTH (context_type) || finally_type != VM_CONTEXT_FINALLY_JUMP); + + if (!VM_CONTEXT_IS_VARIABLE_LENGTH (context_type) && search_limit < context_end) + { + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_EXPECTED; + } + + if (context_type == VM_CONTEXT_TRY || context_type == VM_CONTEXT_CATCH) + { + const uint8_t *byte_code_p; + uint32_t branch_offset_length; + uint32_t branch_offset; + + if (search_limit == context_end) + { + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_EXPECTED; + } + + if (stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV) + { + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + ecma_deref_object (lex_env_p); + } + + byte_code_p = frame_ctx_p->byte_code_start_p + context_end; + + if (context_type == VM_CONTEXT_TRY) + { + JERRY_ASSERT (byte_code_p[0] == CBC_EXT_OPCODE); + + if (byte_code_p[1] >= CBC_EXT_CATCH && byte_code_p[1] <= CBC_EXT_CATCH_3) + { + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (byte_code_p[1]); + branch_offset = vm_decode_branch_offset (byte_code_p + 2, branch_offset_length); + + if (finally_type == VM_CONTEXT_FINALLY_THROW) + { + branch_offset += (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p); + + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_CATCH, branch_offset); + + byte_code_p += 2 + branch_offset_length; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_FINALLY; + } + + byte_code_p += branch_offset; + + if (*byte_code_p == CBC_CONTEXT_END) + { + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION; + continue; + } + } + } + else + { + JERRY_ASSERT (context_type == VM_CONTEXT_CATCH); + + if (byte_code_p[0] == CBC_CONTEXT_END) + { + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION; + continue; + } + } + + JERRY_ASSERT (byte_code_p[0] == CBC_EXT_OPCODE); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION); + stack_top_p += PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION; + + if (JERRY_UNLIKELY (byte_code_p[1] == CBC_EXT_ASYNC_EXIT)) + { + branch_offset = (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p); + stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, branch_offset); + + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_FINALLY; + } + + JERRY_ASSERT (byte_code_p[1] >= CBC_EXT_FINALLY && byte_code_p[1] <= CBC_EXT_FINALLY_3); + + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (byte_code_p[1]); + branch_offset = vm_decode_branch_offset (byte_code_p + 2, branch_offset_length); + + branch_offset += (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p); + + stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, branch_offset); + + byte_code_p += 2 + branch_offset_length; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_FINALLY; + } + else if (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR) + { + JERRY_ASSERT (context_type == VM_CONTEXT_FOR_OF || context_type == VM_CONTEXT_FOR_AWAIT_OF + || context_type == VM_CONTEXT_ITERATOR); + JERRY_ASSERT (finally_type == VM_CONTEXT_FINALLY_THROW || !jcontext_has_pending_exception ()); + + ecma_value_t exception = ECMA_VALUE_UNDEFINED; + if (finally_type == VM_CONTEXT_FINALLY_THROW) + { + exception = jcontext_take_exception (); + } + + ecma_value_t result; + + if (context_type == VM_CONTEXT_ITERATOR) + { + result = ecma_op_iterator_close (stack_top_p[-2]); + } + else + { + ecma_value_t iterator = stack_top_p[-3]; + result = ecma_op_get_method_by_magic_id (iterator, LIT_MAGIC_STRING_RETURN); + + if (!ECMA_IS_VALUE_ERROR (result) && !ecma_is_value_undefined (result)) + { + ecma_object_t *return_obj_p = ecma_get_object_from_value (result); + result = ecma_op_function_validated_call (result, iterator, NULL, 0); + ecma_deref_object (return_obj_p); + + if (context_type == VM_CONTEXT_FOR_AWAIT_OF && !ECMA_IS_VALUE_ERROR (result)) + { + ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + + result = ecma_promise_async_await (async_generator_object_p, result); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + uint16_t extra_flags = + (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD | (ECMA_AWAIT_FOR_CLOSE << ECMA_AWAIT_STATE_SHIFT)); + async_generator_object_p->u.cls.u2.executable_obj_flags |= extra_flags; + + stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_FINALLY_CONTEXT_STACK_ALLOCATION; + + stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, context_end); + if (finally_type == VM_CONTEXT_FINALLY_THROW) + { + stack_top_p[-2] = exception; + } + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = vm_stack_resume_executable_object_with_context_end; + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_AWAIT; + } + } + + if (!ECMA_IS_VALUE_ERROR (result)) + { + bool is_object = ecma_is_value_object (result); + + ecma_free_value (result); + result = ECMA_VALUE_UNDEFINED; + + if (!is_object) + { + result = ecma_raise_type_error (ECMA_ERR_ITERATOR_RETURN_RESULT_IS_NOT_OBJECT); + } + } + } + } + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result) || result == ECMA_VALUE_UNDEFINED); + + if (ECMA_IS_VALUE_ERROR (result)) + { + if (finally_type != VM_CONTEXT_FINALLY_THROW) + { + frame_ctx_p->stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); + return VM_CONTEXT_FOUND_ERROR; + } + + ecma_free_value (jcontext_take_exception ()); + jcontext_raise_exception (exception); + } + else if (finally_type == VM_CONTEXT_FINALLY_THROW) + { + jcontext_raise_exception (exception); + } + } + + stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); + } + + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_EXPECTED; +} /* vm_stack_find_finally */ + +/** + * Get the offsets of ecma values corresponding to the passed context. + * + * @return array of offsets, last item represents the size of the context item + */ +uint32_t +vm_get_context_value_offsets (ecma_value_t *context_item_p) /**< any item of a context */ +{ + switch (VM_GET_CONTEXT_TYPE (context_item_p[-1])) + { + case VM_CONTEXT_FINALLY_THROW: + case VM_CONTEXT_FINALLY_RETURN: + { + return (PARSER_FINALLY_CONTEXT_STACK_ALLOCATION << VM_CONTEXT_OFFSET_SHIFT) | 2; + } + case VM_CONTEXT_FINALLY_JUMP: + { + return PARSER_FINALLY_CONTEXT_STACK_ALLOCATION; + } + case VM_CONTEXT_TRY: + case VM_CONTEXT_CATCH: + case VM_CONTEXT_BLOCK: + case VM_CONTEXT_WITH: + { + return PARSER_WITH_CONTEXT_STACK_ALLOCATION; + } + case VM_CONTEXT_FOR_IN: + { + return (PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION << VM_CONTEXT_OFFSET_SHIFT) | 4; + } + default: + { + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_item_p[-1]) == VM_CONTEXT_FOR_OF + || VM_GET_CONTEXT_TYPE (context_item_p[-1]) == VM_CONTEXT_FOR_AWAIT_OF); + + return ((PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION << (VM_CONTEXT_OFFSET_SHIFT * 3)) + | (4 << (VM_CONTEXT_OFFSET_SHIFT * 2)) | (3 << VM_CONTEXT_OFFSET_SHIFT) | 2); + } + } +} /* vm_get_context_value_offsets */ + +/** + * Ref / deref lexical environments in the chain using the current context. + */ +void +vm_ref_lex_env_chain (ecma_object_t *lex_env_p, /**< top of lexical environment */ + uint16_t context_depth, /**< depth of function context */ + ecma_value_t *context_end_p, /**< end of function context */ + bool do_ref) /**< ref or deref lexical environments */ +{ + ecma_value_t *context_top_p = context_end_p + context_depth; + JERRY_ASSERT (context_top_p > context_end_p); + + do + { + if (context_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV) + { + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + ecma_object_t *next_lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + + if (do_ref) + { + ecma_ref_object (lex_env_p); + } + else + { + ecma_deref_object (lex_env_p); + } + + lex_env_p = next_lex_env_p; + } + + if (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (context_top_p[-1]))) + { + ecma_value_t *last_item_p = context_top_p - VM_GET_CONTEXT_END (context_top_p[-1]); + JERRY_ASSERT (last_item_p >= context_end_p); + context_top_p--; + + do + { + if (do_ref) + { + ecma_ref_if_object (*(--context_top_p)); + } + else + { + ecma_deref_if_object (*(--context_top_p)); + } + } while (context_top_p > last_item_p); + + continue; + } + + uint32_t offsets = vm_get_context_value_offsets (context_top_p); + + while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets)) + { + int32_t offset = VM_CONTEXT_GET_NEXT_OFFSET (offsets); + + if (do_ref) + { + ecma_ref_if_object (context_top_p[offset]); + } + else + { + ecma_deref_if_object (context_top_p[offset]); + } + + offsets >>= VM_CONTEXT_OFFSET_SHIFT; + } + + JERRY_ASSERT (context_top_p >= context_end_p + offsets); + context_top_p -= offsets; + } while (context_top_p > context_end_p); +} /* vm_ref_lex_env_chain */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.h b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.h new file mode 100644 index 00000000..37fd815a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.h @@ -0,0 +1,140 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VM_STACK_H +#define VM_STACK_H + +#include "ecma-globals.h" + +#include "vm-defines.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup stack VM stack + * @{ + */ + +/** + * Create context on the vm stack. + */ +#define VM_CREATE_CONTEXT(type, end_offset) ((ecma_value_t) ((type) | ((end_offset) << 7))) + +/** + * Create context on the vm stack with environment. + */ +#define VM_CREATE_CONTEXT_WITH_ENV(type, end_offset) (VM_CREATE_CONTEXT ((type), (end_offset)) | VM_CONTEXT_HAS_LEX_ENV) + +/** + * Get type of a vm context. + */ +#define VM_GET_CONTEXT_TYPE(value) ((vm_stack_context_type_t) ((value) &0x1f)) + +/** + * Get the end position of a vm context. + */ +#define VM_GET_CONTEXT_END(value) ((value) >> 7) + +/** + * This flag is set if the context has a lexical environment. + */ +#define VM_CONTEXT_HAS_LEX_ENV 0x20 + +/** + * This flag is set if the iterator close operation should be invoked during a for-of context break. + */ +#define VM_CONTEXT_CLOSE_ITERATOR 0x40 + +/** + * Context types for the vm stack. + */ +typedef enum +{ + /* Update VM_CONTEXT_IS_FINALLY macro if the following three values are changed. */ + VM_CONTEXT_FINALLY_JUMP, /**< finally context with a jump */ + VM_CONTEXT_FINALLY_THROW, /**< finally context with a throw */ + VM_CONTEXT_FINALLY_RETURN, /**< finally context with a return */ + VM_CONTEXT_TRY, /**< try context */ + VM_CONTEXT_CATCH, /**< catch context */ + VM_CONTEXT_BLOCK, /**< block context */ + VM_CONTEXT_WITH, /**< with context */ + VM_CONTEXT_FOR_IN, /**< for-in context */ + VM_CONTEXT_FOR_OF, /**< for-of context */ + VM_CONTEXT_FOR_AWAIT_OF, /**< for-await-of context */ + + /* contexts with variable length */ + VM_CONTEXT_ITERATOR, /**< iterator context */ + VM_CONTEXT_OBJ_INIT, /**< object-initializer context */ + VM_CONTEXT_OBJ_INIT_REST, /**< object-initializer-rest context */ +} vm_stack_context_type_t; + +/** + * Return types for vm_stack_find_finally. + */ +typedef enum +{ + VM_CONTEXT_FOUND_FINALLY, /**< found finally */ + VM_CONTEXT_FOUND_ERROR, /**< found an error */ + VM_CONTEXT_FOUND_AWAIT, /**< found an await operation */ + VM_CONTEXT_FOUND_EXPECTED, /**< found the type specified in finally_type */ +} vm_stack_found_type; + +/** + * Checks whether the context has variable context size + * + * Layout: + * - [context descriptor] + * - [JS values belong to the context] + * - [previous JS values stored by the VM stack] + */ +#define VM_CONTEXT_IS_VARIABLE_LENGTH(context_type) ((context_type) >= VM_CONTEXT_ITERATOR) + +/** + * Checks whether the context type is a finally type. + */ +#define VM_CONTEXT_IS_FINALLY(context_type) ((context_type) <= VM_CONTEXT_FINALLY_RETURN) + +/** + * Shift needs to be applied to get the next item of the offset array. + */ +#define VM_CONTEXT_OFFSET_SHIFT 4 + +/** + * Checks whether an offset is available. + */ +#define VM_CONTEXT_HAS_NEXT_OFFSET(offsets) ((offsets) >= (1 << VM_CONTEXT_OFFSET_SHIFT)) + +/** + * Get the next offset from the offset array. + */ +#define VM_CONTEXT_GET_NEXT_OFFSET(offsets) (-((int32_t) ((offsets) & ((1 << VM_CONTEXT_OFFSET_SHIFT) - 1)))) + +ecma_value_t *vm_stack_context_abort_variable_length (vm_frame_ctx_t *frame_ctx_p, + ecma_value_t *vm_stack_top_p, + uint32_t context_stack_allocation); +ecma_value_t *vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *vm_stack_top_p); +vm_stack_found_type vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, + ecma_value_t *stack_top_p, + vm_stack_context_type_t finally_type, + uint32_t search_limit); +uint32_t vm_get_context_value_offsets (ecma_value_t *context_item_p); +void vm_ref_lex_env_chain (ecma_object_t *lex_env_p, uint16_t context_depth, ecma_value_t *context_end_p, bool do_ref); + +/** + * @} + * @} + */ + +#endif /* !VM_STACK_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm-utils.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-utils.cpp new file mode 100644 index 00000000..ee5b8069 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-utils.cpp @@ -0,0 +1,136 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-array-object.h" +#include "ecma-helpers.h" +#include "ecma-line-info.h" + +#include "jcontext.h" +#include "lit-char-helpers.h" +#include "vm.h" + +/** + * Check whether currently executed code is strict mode code + * + * @return true - current code is executed in strict mode, + * false - otherwise + */ +bool +vm_is_strict_mode (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (vm_top_context_p) != NULL); + + return JERRY_CONTEXT (vm_top_context_p)->status_flags & VM_FRAME_CTX_IS_STRICT; +} /* vm_is_strict_mode */ + +/** + * Check whether currently performed call (on top of call-stack) is performed in form, + * meeting conditions of 'Direct Call to Eval' (see also: ECMA-262 v5, 15.1.2.1.1) + * + * Warning: + * the function should only be called from implementation + * of built-in 'eval' routine of Global object + * + * @return true - currently performed call is performed through 'eval' identifier, + * without 'this' argument, + * false - otherwise + */ +bool +vm_is_direct_eval_form_call (void) +{ + return (JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL) != 0; +} /* vm_is_direct_eval_form_call */ + +/** + * Get backtrace. The backtrace is an array of strings where + * each string contains the position of the corresponding frame. + * The array length is zero if the backtrace is not available. + * + * @return array ecma value + */ +ecma_value_t +vm_get_backtrace (uint32_t max_depth) /**< maximum backtrace depth, 0 = unlimited */ +{ +#if JERRY_LINE_INFO + vm_frame_ctx_t *context_p = JERRY_CONTEXT (vm_top_context_p); + + if (max_depth == 0) + { + max_depth = UINT32_MAX; + } + + ecma_object_t *array_p = ecma_op_new_array_object (0); + JERRY_ASSERT (ecma_op_object_is_fast_array (array_p)); + uint32_t index = 0; + + while (context_p != NULL) + { + const ecma_compiled_code_t *bytecode_header_p = context_p->shared_p->bytecode_header_p; + ecma_value_t source_name = ecma_get_source_name (bytecode_header_p); + ecma_string_t *str_p = ecma_get_string_from_value (source_name); + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + if (ecma_string_is_empty (str_p)) + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) ":", 10); + } + else + { + ecma_stringbuilder_append (&builder, str_p); + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_COLON); + } + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO) + { + jerry_frame_location_t location; + ecma_line_info_get (ecma_compiled_code_get_line_info (bytecode_header_p), + (uint32_t) (context_p->byte_code_p - context_p->byte_code_start_p), + &location); + + ecma_string_t *line_str_p = ecma_new_ecma_string_from_uint32 (location.line); + ecma_stringbuilder_append (&builder, line_str_p); + ecma_deref_ecma_string (line_str_p); + + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_COLON); + + line_str_p = ecma_new_ecma_string_from_uint32 (location.column); + ecma_stringbuilder_append (&builder, line_str_p); + ecma_deref_ecma_string (line_str_p); + } + else + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "1:1", 3); + } + + ecma_string_t *builder_str_p = ecma_stringbuilder_finalize (&builder); + ecma_fast_array_set_property (array_p, index, ecma_make_string_value (builder_str_p)); + ecma_deref_ecma_string (builder_str_p); + + context_p = context_p->prev_context_p; + index++; + + if (index >= max_depth) + { + break; + } + } + + return ecma_make_object_value (array_p); +#else /* !JERRY_LINE_INFO */ + JERRY_UNUSED (max_depth); + + return ecma_make_object_value (ecma_op_new_array_object (0)); +#endif /* JERRY_LINE_INFO */ +} /* vm_get_backtrace */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/vm.cpp new file mode 100644 index 00000000..1fbdd36c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm.cpp @@ -0,0 +1,5156 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "vm.h" + +#include "ecma-alloc.h" +#include "ecma-arguments-object.h" +#include "ecma-array-object.h" +#include "ecma-bigint.h" +#include "ecma-builtin-object.h" +#include "ecma-builtins.h" +#include "ecma-comparison.h" +#include "ecma-conversion.h" +#include "ecma-errors.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-lcache.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" +#include "ecma-regexp-object.h" + +#include "common.h" +#include "jcontext.h" +#include "opcodes.h" +#include "vm-stack.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_executor Executor + * @{ + */ + +JERRY_STATIC_ASSERT ((sizeof (vm_frame_ctx_t) % sizeof (ecma_value_t)) == 0, + sizeof_vm_frame_ctx_must_be_sizeof_ecma_value_t_aligned); + +/** + * Get the value of object[property]. + * + * @return ecma value + */ +static ecma_value_t +vm_op_get_value (ecma_value_t object, /**< base object */ + ecma_value_t property) /**< property name */ +{ + if (ecma_is_value_object (object)) + { + ecma_object_t *object_p = ecma_get_object_from_value (object); + ecma_string_t *property_name_p = NULL; + + if (ecma_is_value_integer_number (property)) + { + ecma_integer_value_t int_value = ecma_get_integer_from_value (property); + + if (int_value >= 0 && int_value <= ECMA_DIRECT_STRING_MAX_IMM) + { + if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p) + && (uint32_t) int_value < ext_object_p->u.array.length)) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + if (JERRY_LIKELY (!ecma_is_value_array_hole (values_p[int_value]))) + { + return ecma_fast_copy_value (values_p[int_value]); + } + } + } + + property_name_p = (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) int_value); + } + } + else if (ecma_is_value_string (property)) + { + property_name_p = ecma_get_string_from_value (property); + } + + if (ecma_is_value_symbol (property)) + { + property_name_p = ecma_get_symbol_from_value (property); + } + + if (property_name_p != NULL) + { +#if JERRY_LCACHE + ecma_property_t *property_p = ecma_lcache_lookup (object_p, property_name_p); + + if (property_p != NULL && (*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + JERRY_ASSERT (!ECMA_PROPERTY_IS_INTERNAL (*property_p)); + return ecma_fast_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + } +#endif /* JERRY_LCACHE */ + + /* There is no need to free the name. */ + return ecma_op_object_get (object_p, property_name_p); + } + } + + if (JERRY_UNLIKELY (ecma_is_value_undefined (object) || ecma_is_value_null (object))) + { +#if JERRY_ERROR_MESSAGES + ecma_value_t error_value = + ecma_raise_standard_error_with_format (JERRY_ERROR_TYPE, "Cannot read property '%' of %", property, object); +#else /* !JERRY_ERROR_MESSAGES */ + ecma_value_t error_value = ecma_raise_type_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + return error_value; + } + + ecma_string_t *property_name_p = ecma_op_to_property_key (property); + + if (property_name_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t get_value_result = ecma_op_get_value_object_base (object, property_name_p); + + ecma_deref_ecma_string (property_name_p); + return get_value_result; +} /* vm_op_get_value */ + +/** + * Set the value of object[property]. + * + * Note: + * this function frees its object and property arguments + * + * @return an ecma value which contains an error + * if the property setting is unsuccessful + */ +static ecma_value_t +vm_op_set_value (ecma_value_t base, /**< base object */ + ecma_value_t property, /**< property name */ + ecma_value_t value, /**< ecma value */ + bool is_strict) /**< strict mode */ +{ + ecma_value_t result = ECMA_VALUE_EMPTY; + ecma_object_t *object_p; + ecma_string_t *property_p; + + if (JERRY_UNLIKELY (!ecma_is_value_object (base))) + { + if (JERRY_UNLIKELY (ecma_is_value_null (base) || ecma_is_value_undefined (base))) + { +#if JERRY_ERROR_MESSAGES + result = ecma_raise_standard_error_with_format (JERRY_ERROR_TYPE, "Cannot set property '%' of %", property, base); +#else /* !JERRY_ERROR_MESSAGES */ + result = ecma_raise_type_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + ecma_free_value (property); + return result; + } + + if (JERRY_UNLIKELY (!ecma_is_value_prop_name (property))) + { + property_p = ecma_op_to_string (property); + ecma_fast_free_value (property); + + if (JERRY_UNLIKELY (property_p == NULL)) + { + ecma_free_value (base); + return ECMA_VALUE_ERROR; + } + } + else + { + property_p = ecma_get_prop_name_from_value (property); + } + + ecma_value_t object = ecma_op_to_object (base); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (object)); + + object_p = ecma_get_object_from_value (object); + ecma_op_ordinary_object_prevent_extensions (object_p); + + result = ecma_op_object_put_with_receiver (object_p, property_p, value, base, is_strict); + + ecma_free_value (base); + } + else + { + object_p = ecma_get_object_from_value (base); + + if (JERRY_UNLIKELY (!ecma_is_value_prop_name (property))) + { + property_p = ecma_op_to_string (property); + ecma_fast_free_value (property); + + if (JERRY_UNLIKELY (property_p == NULL)) + { + ecma_deref_object (object_p); + return ECMA_VALUE_ERROR; + } + } + else + { + property_p = ecma_get_prop_name_from_value (property); + } + + if (!ecma_is_lexical_environment (object_p)) + { + result = ecma_op_object_put_with_receiver (object_p, property_p, value, base, is_strict); + } + else + { + result = ecma_op_set_mutable_binding (object_p, property_p, value, is_strict); + } + } + + ecma_deref_object (object_p); + ecma_deref_ecma_string (property_p); + return result; +} /* vm_op_set_value */ + +/** Compact bytecode define */ +#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg4, + +/** + * Decode table for both opcodes and extended opcodes. + */ +static const uint16_t vm_decode_table[] JERRY_ATTR_CONST_DATA = { CBC_OPCODE_LIST CBC_EXT_OPCODE_LIST }; + +#undef CBC_OPCODE + +/** + * Run global code + * + * Note: + * returned value must be freed with ecma_free_value, when it is no longer needed. + * + * @return ecma value + */ +ecma_value_t +vm_run_global (const ecma_compiled_code_t *bytecode_p, /**< pointer to bytecode to run */ + ecma_object_t *function_object_p) /**< function object if available */ +{ +#if JERRY_BUILTIN_REALMS + ecma_object_t *global_obj_p = (ecma_object_t *) ecma_op_function_get_realm (bytecode_p); +#else /* !JERRY_BUILTIN_REALMS */ + ecma_object_t *global_obj_p = ecma_builtin_get_global (); +#endif /* JERRY_BUILTIN_REALMS */ + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED) + { + ecma_create_global_lexical_block (global_obj_p); + } + + ecma_object_t *const global_scope_p = ecma_get_global_scope (global_obj_p); + + vm_frame_ctx_shared_t shared; + shared.bytecode_header_p = bytecode_p; + shared.function_object_p = function_object_p; + shared.status_flags = 0; + +#if JERRY_BUILTIN_REALMS + ecma_value_t this_binding = ((ecma_global_object_t *) global_obj_p)->this_binding; + + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = (ecma_global_object_t *) global_obj_p; +#else /* !JERRY_BUILTIN_REALMS */ + ecma_value_t this_binding = ecma_make_object_value (global_obj_p); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_value_t result = vm_run (&shared, this_binding, global_scope_p); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + return result; +} /* vm_run_global */ + +/** + * Run specified eval-mode bytecode + * + * @return ecma value + */ +ecma_value_t +vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */ + uint32_t parse_opts) /**< ecma_parse_opts_t option bits */ +{ + ecma_value_t this_binding; + ecma_object_t *lex_env_p; + + /* ECMA-262 v5, 10.4.2 */ + if (parse_opts & ECMA_PARSE_DIRECT_EVAL) + { + this_binding = ecma_copy_value (JERRY_CONTEXT (vm_top_context_p)->this_binding); + lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p; + } + else + { +#if JERRY_BUILTIN_REALMS + ecma_object_t *global_obj_p = (ecma_object_t *) ecma_op_function_get_realm (bytecode_data_p); + this_binding = ((ecma_global_object_t *) global_obj_p)->this_binding; + ecma_ref_object (ecma_get_object_from_value (this_binding)); +#else /* !JERRY_BUILTIN_REALMS */ + ecma_object_t *global_obj_p = ecma_builtin_get_global (); + ecma_ref_object (global_obj_p); + this_binding = ecma_make_object_value (global_obj_p); +#endif /* JERRY_BUILTIN_REALMS */ + lex_env_p = ecma_get_global_scope (global_obj_p); + } + + ecma_ref_object (lex_env_p); + + if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0) + { + ecma_object_t *strict_lex_env_p = ecma_create_decl_lex_env (lex_env_p); + + ecma_deref_object (lex_env_p); + lex_env_p = strict_lex_env_p; + } + + if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED) != 0) + { + ecma_object_t *lex_block_p = ecma_create_decl_lex_env (lex_env_p); + lex_block_p->type_flags_refs |= ECMA_OBJECT_FLAG_BLOCK; + + ecma_deref_object (lex_env_p); + lex_env_p = lex_block_p; + } + + vm_frame_ctx_shared_t shared; + shared.bytecode_header_p = bytecode_data_p; + shared.function_object_p = NULL; + shared.status_flags = (parse_opts & ECMA_PARSE_DIRECT_EVAL) ? VM_FRAME_CTX_SHARED_DIRECT_EVAL : 0; + + ecma_value_t completion_value = vm_run (&shared, this_binding, lex_env_p); + + ecma_deref_object (lex_env_p); + ecma_free_value (this_binding); + +#if JERRY_SNAPSHOT_EXEC + if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + { + ecma_bytecode_deref (bytecode_data_p); + } +#else /* !JERRY_SNAPSHOT_EXEC */ + ecma_bytecode_deref (bytecode_data_p); +#endif /* JERRY_SNAPSHOT_EXEC */ + + return completion_value; +} /* vm_run_eval */ + +#if JERRY_MODULE_SYSTEM + +/** + * Run module code + * + * Note: + * returned value must be freed with ecma_free_value, when it is no longer needed. + * + * @return ecma value + */ +ecma_value_t +vm_run_module (ecma_module_t *module_p) /**< module to be executed */ +{ + const ecma_value_t module_init_result = ecma_module_initialize (module_p); + + if (ECMA_IS_VALUE_ERROR (module_init_result)) + { + return module_init_result; + } + + vm_frame_ctx_shared_t shared; + shared.bytecode_header_p = module_p->u.compiled_code_p; + shared.function_object_p = &module_p->header.object; + shared.status_flags = 0; + + return vm_run (&shared, ECMA_VALUE_UNDEFINED, module_p->scope_p); +} /* vm_run_module */ + +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * Construct object + * + * @return object value + */ +static ecma_value_t +vm_construct_literal_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t lit_value) /**< literal */ +{ + ecma_compiled_code_t *bytecode_p; + +#if JERRY_SNAPSHOT_EXEC + if (JERRY_LIKELY (!(frame_ctx_p->shared_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))) + { +#endif /* JERRY_SNAPSHOT_EXEC */ + bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, lit_value); +#if JERRY_SNAPSHOT_EXEC + } + else + { + uint8_t *byte_p = ((uint8_t *) frame_ctx_p->shared_p->bytecode_header_p) + lit_value; + bytecode_p = (ecma_compiled_code_t *) byte_p; + } +#endif /* JERRY_SNAPSHOT_EXEC */ + +#if JERRY_BUILTIN_REGEXP + if (JERRY_UNLIKELY (!CBC_IS_FUNCTION (bytecode_p->status_flags))) + { + ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL); + + if (JERRY_UNLIKELY (regexp_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + return ecma_op_create_regexp_from_bytecode (regexp_obj_p, (re_compiled_code_t *) bytecode_p); + } +#else /* !JERRY_BUILTIN_REGEXP */ + JERRY_ASSERT (CBC_IS_FUNCTION (bytecode_p->status_flags)); +#endif /* JERRY_BUILTIN_REGEXP */ + + ecma_object_t *func_obj_p; + + if (JERRY_UNLIKELY (CBC_FUNCTION_IS_ARROW (bytecode_p->status_flags))) + { + func_obj_p = ecma_op_create_arrow_function_object (frame_ctx_p->lex_env_p, bytecode_p, frame_ctx_p->this_binding); + } + else + { + func_obj_p = ecma_op_create_any_function_object (frame_ctx_p->lex_env_p, bytecode_p); + } + + return ecma_make_object_value (func_obj_p); +} /* vm_construct_literal_object */ + +/** + * Get implicit this value + * + * @return true - if the implicit 'this' value is updated, + * false - otherwise + */ +static inline bool +vm_get_implicit_this_value (ecma_value_t *this_value_p) /**< [in,out] this value */ +{ + if (ecma_is_value_object (*this_value_p)) + { + ecma_object_t *this_obj_p = ecma_get_object_from_value (*this_value_p); + + if (ecma_is_lexical_environment (this_obj_p)) + { + ecma_value_t completion_value = ecma_op_implicit_this_value (this_obj_p); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion_value)); + + *this_value_p = completion_value; + return true; + } + } + return false; +} /* vm_get_implicit_this_value */ + +/** + * Special bytecode sequence for error handling while the vm_loop + * is preserved for an execute operation + */ +static const uint8_t vm_error_byte_code_p[] = { CBC_EXT_OPCODE, CBC_EXT_ERROR }; + +/** + * Get class function object + * + * @return the pointer to the object + */ +static ecma_object_t * +vm_get_class_function (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + JERRY_ASSERT (frame_ctx_p != NULL); + + if (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC) + { + return frame_ctx_p->shared_p->function_object_p; + } + + ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (frame_ctx_p->lex_env_p); + + JERRY_ASSERT (environment_record_p != NULL); + return ecma_get_object_from_value (environment_record_p->function_object); +} /* vm_get_class_function */ + +/** + * 'super(...)' function call handler. + */ +static void +vm_super_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + JERRY_ASSERT (frame_ctx_p->call_operation == VM_EXEC_SUPER_CALL); + JERRY_ASSERT (frame_ctx_p->byte_code_p[0] == CBC_EXT_OPCODE); + + const uint8_t *byte_code_p = frame_ctx_p->byte_code_p + 3; + uint8_t opcode = byte_code_p[-2]; + uint32_t arguments_list_len; + + bool spread_arguments = opcode >= CBC_EXT_SPREAD_SUPER_CALL; + + ecma_collection_t *collection_p = NULL; + ecma_value_t *arguments_p; + + if (spread_arguments) + { + ecma_value_t collection = *(--frame_ctx_p->stack_top_p); + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, collection); + arguments_p = collection_p->buffer_p; + arguments_list_len = collection_p->item_count; + } + else + { + arguments_list_len = byte_code_p[-1]; + arguments_p = frame_ctx_p->stack_top_p; + } + + ecma_value_t func_value = *(--frame_ctx_p->stack_top_p); + ecma_value_t completion_value; + + ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (frame_ctx_p->lex_env_p); + JERRY_ASSERT (environment_record_p); + + if (!ecma_is_constructor (func_value)) + { + completion_value = ecma_raise_type_error (ECMA_ERR_VALUE_FOR_CLASS_HERITAGE_IS_NOT_A_CONSTRUCTOR); + } + else + { + ecma_object_t *func_obj_p = ecma_get_object_from_value (func_value); + completion_value = + ecma_op_function_construct (func_obj_p, JERRY_CONTEXT (current_new_target_p), arguments_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (completion_value) && ecma_op_this_binding_is_initialized (environment_record_p)) + { + ecma_free_value (completion_value); + completion_value = ecma_raise_reference_error (ECMA_ERR_SUPER_CONSTRUCTOR_MAY_ONLY_BE_CALLED_ONCE); + } + } + + /* Free registers. */ + for (uint32_t i = 0; i < arguments_list_len; i++) + { + ecma_fast_free_value (arguments_p[i]); + } + + if (collection_p != NULL) + { + ecma_collection_destroy (collection_p); + } + + if (ecma_is_value_object (completion_value)) + { + ecma_op_bind_this_value (environment_record_p, completion_value); + frame_ctx_p->this_binding = completion_value; + + ecma_value_t fields_value = opfunc_init_class_fields (vm_get_class_function (frame_ctx_p), completion_value); + + if (ECMA_IS_VALUE_ERROR (fields_value)) + { + ecma_free_value (completion_value); + completion_value = ECMA_VALUE_ERROR; + } + } + + ecma_free_value (func_value); + + if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (completion_value))) + { + frame_ctx_p->byte_code_p = (uint8_t *) vm_error_byte_code_p; + } + else + { + frame_ctx_p->byte_code_p = byte_code_p; + uint32_t opcode_data = vm_decode_table[(CBC_END + 1) + opcode]; + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + ecma_fast_free_value (completion_value); + } + else if (opcode_data & VM_OC_PUT_STACK) + { + *frame_ctx_p->stack_top_p++ = completion_value; + } + else + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = completion_value; + } + } +} /* vm_super_call */ + +/** + * Perform one of the following call/construct operation with spreaded argument list + * - f(...args) + * - o.f(...args) + * - new O(...args) + */ +static void +vm_spread_operation (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + JERRY_ASSERT (frame_ctx_p->byte_code_p[0] == CBC_EXT_OPCODE); + + uint8_t opcode = frame_ctx_p->byte_code_p[1]; + ecma_value_t completion_value; + ecma_value_t collection = *(--frame_ctx_p->stack_top_p); + + ecma_collection_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, collection); + ecma_value_t func_value = *(--frame_ctx_p->stack_top_p); + bool is_call_prop = opcode >= CBC_EXT_SPREAD_CALL_PROP; + + if (frame_ctx_p->byte_code_p[1] == CBC_EXT_SPREAD_NEW) + { + ecma_error_msg_t constructor_message_id = ecma_check_constructor (func_value); + if (constructor_message_id != ECMA_IS_VALID_CONSTRUCTOR) + { + completion_value = ecma_raise_type_error (constructor_message_id); + } + else + { + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (func_value); + + completion_value = ecma_op_function_construct (constructor_obj_p, + constructor_obj_p, + collection_p->buffer_p, + collection_p->item_count); + } + } + else + { + ecma_value_t this_value = is_call_prop ? frame_ctx_p->stack_top_p[-2] : ECMA_VALUE_UNDEFINED; + + if (!ecma_is_value_object (func_value) || !ecma_op_object_is_callable (ecma_get_object_from_value (func_value))) + { + completion_value = ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + } + else + { + ecma_object_t *func_obj_p = ecma_get_object_from_value (func_value); + + completion_value = + ecma_op_function_call (func_obj_p, this_value, collection_p->buffer_p, collection_p->item_count); + } + + if (is_call_prop) + { + ecma_free_value (*(--frame_ctx_p->stack_top_p)); + ecma_free_value (*(--frame_ctx_p->stack_top_p)); + } + } + + ecma_collection_free (collection_p); + ecma_free_value (func_value); + + if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (completion_value))) + { + frame_ctx_p->byte_code_p = (uint8_t *) vm_error_byte_code_p; + } + else + { + uint32_t opcode_data = vm_decode_table[(CBC_END + 1) + opcode]; + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + ecma_fast_free_value (completion_value); + } + else if (opcode_data & VM_OC_PUT_STACK) + { + *frame_ctx_p->stack_top_p++ = completion_value; + } + else + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = completion_value; + } + + /* EXT_OPCODE, SPREAD_OPCODE, BYTE_ARG */ + frame_ctx_p->byte_code_p += 3; + } +} /* vm_spread_operation */ + +/** + * 'Function call' opcode handler. + * + * See also: ECMA-262 v5, 11.2.3 + */ +static void +opfunc_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + const uint8_t *byte_code_p = frame_ctx_p->byte_code_p + 1; + uint8_t opcode = byte_code_p[-1]; + uint32_t arguments_list_len; + + if (opcode >= CBC_CALL0) + { + arguments_list_len = (unsigned int) ((opcode - CBC_CALL0) / 6); + } + else + { + arguments_list_len = *byte_code_p++; + } + + bool is_call_prop = ((opcode - CBC_CALL) % 6) >= 3; + + ecma_value_t *stack_top_p = frame_ctx_p->stack_top_p - arguments_list_len; + ecma_value_t this_value = is_call_prop ? stack_top_p[-3] : ECMA_VALUE_UNDEFINED; + ecma_value_t func_value = stack_top_p[-1]; + + ecma_value_t completion_value = + ecma_op_function_validated_call (func_value, this_value, stack_top_p, arguments_list_len); + + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; + + /* Free registers. */ + for (uint32_t i = 0; i < arguments_list_len; i++) + { + ecma_fast_free_value (stack_top_p[i]); + } + + if (is_call_prop) + { + ecma_free_value (*(--stack_top_p)); + ecma_free_value (*(--stack_top_p)); + } + + if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (completion_value))) + { + frame_ctx_p->byte_code_p = (uint8_t *) vm_error_byte_code_p; + } + else + { + frame_ctx_p->byte_code_p = byte_code_p; + ecma_free_value (*(--stack_top_p)); + uint32_t opcode_data = vm_decode_table[opcode]; + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + ecma_fast_free_value (completion_value); + } + else if (opcode_data & VM_OC_PUT_STACK) + { + *stack_top_p++ = completion_value; + } + else + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = completion_value; + } + } + + frame_ctx_p->stack_top_p = stack_top_p; +} /* opfunc_call */ + +/** + * 'Constructor call' opcode handler. + * + * See also: ECMA-262 v5, 11.2.2 + */ +static void +opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + const uint8_t *byte_code_p = frame_ctx_p->byte_code_p + 1; + uint8_t opcode = byte_code_p[-1]; + unsigned int arguments_list_len; + + if (opcode >= CBC_NEW0) + { + arguments_list_len = (unsigned int) (opcode - CBC_NEW0); + } + else + { + arguments_list_len = *byte_code_p++; + } + + ecma_value_t *stack_top_p = frame_ctx_p->stack_top_p - arguments_list_len; + ecma_value_t constructor_value = stack_top_p[-1]; + ecma_value_t completion_value; + + ecma_error_msg_t constructor_message_id = ecma_check_constructor (constructor_value); + if (constructor_message_id != ECMA_IS_VALID_CONSTRUCTOR) + { + completion_value = ecma_raise_type_error (constructor_message_id); + } + else + { + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor_value); + + completion_value = + ecma_op_function_construct (constructor_obj_p, constructor_obj_p, stack_top_p, arguments_list_len); + } + + /* Free registers. */ + for (uint32_t i = 0; i < arguments_list_len; i++) + { + ecma_fast_free_value (stack_top_p[i]); + } + + if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (completion_value))) + { + frame_ctx_p->byte_code_p = (uint8_t *) vm_error_byte_code_p; + } + else + { + ecma_free_value (stack_top_p[-1]); + frame_ctx_p->byte_code_p = byte_code_p; + stack_top_p[-1] = completion_value; + } + + frame_ctx_p->stack_top_p = stack_top_p; +} /* opfunc_construct */ + +/** + * Read literal index from the byte code stream into destination. + * + * @param destination destination + */ +#define READ_LITERAL_INDEX(destination) \ + do \ + { \ + (destination) = *byte_code_p++; \ + if ((destination) >= encoding_limit) \ + { \ + (destination) = (uint16_t) ((((destination) << 8) | *byte_code_p++) - encoding_delta); \ + } \ + } while (0) + +/** + * Get literal value by literal index. + * + * @param literal_index literal index + * @param target_value target value + * + * TODO: For performance reasons, we define this as a macro. + * When we are able to construct a function with similar speed, + * we can remove this macro. + */ +#define READ_LITERAL(literal_index, target_value) \ + do \ + { \ + if ((literal_index) < ident_end) \ + { \ + if ((literal_index) < register_end) \ + { \ + /* Note: There should be no specialization for arguments. */ \ + (target_value) = ecma_fast_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); \ + } \ + else \ + { \ + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); \ + \ + result = ecma_op_resolve_reference_value (frame_ctx_p->lex_env_p, name_p); \ + \ + if (ECMA_IS_VALUE_ERROR (result)) \ + { \ + goto error; \ + } \ + (target_value) = result; \ + } \ + } \ + else if (literal_index < const_literal_end) \ + { \ + (target_value) = ecma_fast_copy_value (literal_start_p[literal_index]); \ + } \ + else \ + { \ + /* Object construction. */ \ + (target_value) = vm_construct_literal_object (frame_ctx_p, literal_start_p[literal_index]); \ + } \ + } while (0) + +/** + * Store the original value for post increase/decrease operators + * + * @param value original value + */ +#define POST_INCREASE_DECREASE_PUT_RESULT(value) \ + if (opcode_data & VM_OC_PUT_STACK) \ + { \ + if (opcode_flags & VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG) \ + { \ + JERRY_ASSERT (opcode == CBC_POST_INCR_IDENT_PUSH_RESULT || opcode == CBC_POST_DECR_IDENT_PUSH_RESULT); \ + *stack_top_p++ = (value); \ + } \ + else \ + { \ + /* The parser ensures there is enough space for the \ + * extra value on the stack. See js-parser-expr.c. */ \ + JERRY_ASSERT (opcode == CBC_POST_INCR_PUSH_RESULT || opcode == CBC_POST_DECR_PUSH_RESULT); \ + stack_top_p++; \ + stack_top_p[-1] = stack_top_p[-2]; \ + stack_top_p[-2] = stack_top_p[-3]; \ + stack_top_p[-3] = (value); \ + } \ + opcode_data &= (uint32_t) ~VM_OC_PUT_STACK; \ + } \ + else \ + { \ + JERRY_ASSERT (opcode_data &VM_OC_PUT_BLOCK); \ + ecma_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); \ + VM_GET_REGISTERS (frame_ctx_p)[0] = (value); \ + opcode_data &= (uint32_t) ~VM_OC_PUT_BLOCK; \ + } + +/** + * Get the end of the existing topmost context + */ +#define VM_LAST_CONTEXT_END() (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth) + +/** + * Run generic byte code. + * + * @return ecma value + */ +static ecma_value_t JERRY_ATTR_NOINLINE +vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->shared_p->bytecode_header_p; + const uint8_t *byte_code_p = frame_ctx_p->byte_code_p; + ecma_value_t *literal_start_p = frame_ctx_p->literal_start_p; + + ecma_value_t *stack_top_p; + uint16_t encoding_limit; + uint16_t encoding_delta; + uint16_t register_end; + uint16_t ident_end; + uint16_t const_literal_end; + int32_t branch_offset = 0; + uint8_t branch_offset_length = 0; + ecma_value_t left_value; + ecma_value_t right_value; + ecma_value_t result = ECMA_VALUE_EMPTY; + bool is_strict = ((bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0); + + /* Prepare for byte code execution. */ + if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) + { + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + else + { + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) (bytecode_header_p); + register_end = args_p->register_end; + ident_end = args_p->ident_end; + const_literal_end = args_p->const_literal_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) (bytecode_header_p); + register_end = args_p->register_end; + ident_end = args_p->ident_end; + const_literal_end = args_p->const_literal_end; + } + + stack_top_p = frame_ctx_p->stack_top_p; + + /* Outer loop for exception handling. */ + while (true) + { + /* Internal loop for byte code execution. */ + while (true) + { + const uint8_t *byte_code_start_p = byte_code_p; + uint8_t opcode = *byte_code_p++; + uint32_t opcode_data = opcode; + + if (opcode == CBC_EXT_OPCODE) + { + opcode = *byte_code_p++; + opcode_data = (uint32_t) ((CBC_END + 1) + opcode); + } + + opcode_data = vm_decode_table[opcode_data]; + + left_value = ECMA_VALUE_UNDEFINED; + right_value = ECMA_VALUE_UNDEFINED; + + uint32_t operands = VM_OC_GET_ARGS_INDEX (opcode_data); + + if (operands >= VM_OC_GET_LITERAL) + { + uint16_t literal_index; + READ_LITERAL_INDEX (literal_index); + READ_LITERAL (literal_index, left_value); + + if (operands != VM_OC_GET_LITERAL) + { + switch (operands) + { + case VM_OC_GET_LITERAL_LITERAL: + { + uint16_t second_literal_index; + READ_LITERAL_INDEX (second_literal_index); + READ_LITERAL (second_literal_index, right_value); + break; + } + case VM_OC_GET_STACK_LITERAL: + { + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + right_value = left_value; + left_value = *(--stack_top_p); + break; + } + default: + { + JERRY_ASSERT (operands == VM_OC_GET_THIS_LITERAL); + + right_value = left_value; + left_value = ecma_copy_value (frame_ctx_p->this_binding); + break; + } + } + } + } + else if (operands >= VM_OC_GET_STACK) + { + JERRY_ASSERT (operands == VM_OC_GET_STACK || operands == VM_OC_GET_STACK_STACK); + + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + left_value = *(--stack_top_p); + + if (operands == VM_OC_GET_STACK_STACK) + { + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + right_value = left_value; + left_value = *(--stack_top_p); + } + } + else if (operands == VM_OC_GET_BRANCH) + { + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (opcode); + JERRY_ASSERT (branch_offset_length >= 1 && branch_offset_length <= 3); + + branch_offset = *(byte_code_p++); + + if (JERRY_UNLIKELY (branch_offset_length != 1)) + { + branch_offset <<= 8; + branch_offset |= *(byte_code_p++); + + if (JERRY_UNLIKELY (branch_offset_length == 3)) + { + branch_offset <<= 8; + branch_offset |= *(byte_code_p++); + } + } + + if (opcode_data & VM_OC_BACKWARD_BRANCH) + { +#if JERRY_VM_HALT + if (JERRY_CONTEXT (vm_exec_stop_cb) != NULL && --JERRY_CONTEXT (vm_exec_stop_counter) == 0) + { + result = JERRY_CONTEXT (vm_exec_stop_cb) (JERRY_CONTEXT (vm_exec_stop_user_p)); + + if (ecma_is_value_undefined (result)) + { + JERRY_CONTEXT (vm_exec_stop_counter) = JERRY_CONTEXT (vm_exec_stop_frequency); + } + else + { + JERRY_CONTEXT (vm_exec_stop_counter) = 1; + + if (ecma_is_value_exception (result)) + { + ecma_throw_exception (result); + } + else + { + jcontext_raise_exception (result); + } + + JERRY_ASSERT (jcontext_has_pending_exception ()); + jcontext_set_abort_flag (true); + result = ECMA_VALUE_ERROR; + goto error; + } + } +#endif /* JERRY_VM_HALT */ + + branch_offset = -branch_offset; + } + } + + switch (VM_OC_GROUP_GET_INDEX (opcode_data)) + { + case VM_OC_POP: + { + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + ecma_free_value (*(--stack_top_p)); + continue; + } + case VM_OC_POP_BLOCK: + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = *(--stack_top_p); + continue; + } + case VM_OC_PUSH: + { + *stack_top_p++ = left_value; + continue; + } + case VM_OC_PUSH_TWO: + { + *stack_top_p++ = left_value; + *stack_top_p++ = right_value; + continue; + } + case VM_OC_PUSH_THREE: + { + uint16_t literal_index; + + *stack_top_p++ = left_value; + left_value = ECMA_VALUE_UNDEFINED; + + READ_LITERAL_INDEX (literal_index); + READ_LITERAL (literal_index, left_value); + + *stack_top_p++ = right_value; + *stack_top_p++ = left_value; + continue; + } + case VM_OC_PUSH_UNDEFINED: + { + *stack_top_p++ = ECMA_VALUE_UNDEFINED; + continue; + } + case VM_OC_PUSH_TRUE: + { + *stack_top_p++ = ECMA_VALUE_TRUE; + continue; + } + case VM_OC_PUSH_FALSE: + { + *stack_top_p++ = ECMA_VALUE_FALSE; + continue; + } + case VM_OC_PUSH_NULL: + { + *stack_top_p++ = ECMA_VALUE_NULL; + continue; + } + case VM_OC_PUSH_THIS: + { + *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding); + continue; + } + case VM_OC_PUSH_0: + { + *stack_top_p++ = ecma_make_integer_value (0); + continue; + } + case VM_OC_PUSH_POS_BYTE: + { + ecma_integer_value_t number = *byte_code_p++; + *stack_top_p++ = ecma_make_integer_value (number + 1); + continue; + } + case VM_OC_PUSH_NEG_BYTE: + { + ecma_integer_value_t number = *byte_code_p++; + *stack_top_p++ = ecma_make_integer_value (-(number + 1)); + continue; + } + case VM_OC_PUSH_LIT_0: + { + stack_top_p[0] = left_value; + stack_top_p[1] = ecma_make_integer_value (0); + stack_top_p += 2; + continue; + } + case VM_OC_PUSH_LIT_POS_BYTE: + { + ecma_integer_value_t number = *byte_code_p++; + stack_top_p[0] = left_value; + stack_top_p[1] = ecma_make_integer_value (number + 1); + stack_top_p += 2; + continue; + } + case VM_OC_PUSH_LIT_NEG_BYTE: + { + ecma_integer_value_t number = *byte_code_p++; + stack_top_p[0] = left_value; + stack_top_p[1] = ecma_make_integer_value (-(number + 1)); + stack_top_p += 2; + continue; + } + case VM_OC_PUSH_OBJECT: + { + ecma_object_t *obj_p = + ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL); + + *stack_top_p++ = ecma_make_object_value (obj_p); + continue; + } + case VM_OC_PUSH_NAMED_FUNC_EXPR: + { + ecma_object_t *func_p = ecma_get_object_from_value (left_value); + + JERRY_ASSERT (ecma_get_object_type (func_p) == ECMA_OBJECT_TYPE_FUNCTION); + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p; + + JERRY_ASSERT (frame_ctx_p->lex_env_p + == ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp)); + + ecma_object_t *name_lex_env = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p); + + ecma_op_create_immutable_binding (name_lex_env, ecma_get_string_from_value (right_value), left_value); + + ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, name_lex_env, 0); + + ecma_free_value (right_value); + ecma_deref_object (name_lex_env); + *stack_top_p++ = left_value; + continue; + } + case VM_OC_CREATE_BINDING: + { + uint32_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL); + + uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; + + if (opcode == CBC_CREATE_LET) + { + prop_attributes = ECMA_PROPERTY_ENUMERABLE_WRITABLE; + } + else if (opcode == CBC_CREATE_CONST) + { + prop_attributes = ECMA_PROPERTY_FLAG_ENUMERABLE; + } + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, prop_attributes, NULL); + + if (opcode != CBC_CREATE_VAR) + { + property_value_p->value = ECMA_VALUE_UNINITIALIZED; + } + + continue; + } + case VM_OC_VAR_EVAL: + { + uint32_t literal_index; + ecma_value_t lit_value = ECMA_VALUE_UNDEFINED; + + if (opcode == CBC_CREATE_VAR_FUNC_EVAL) + { + uint32_t value_index; + READ_LITERAL_INDEX (value_index); + JERRY_ASSERT (value_index >= const_literal_end); + + lit_value = vm_construct_literal_object (frame_ctx_p, literal_start_p[value_index]); + } + + READ_LITERAL_INDEX (literal_index); + JERRY_ASSERT (literal_index >= register_end); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + + while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { +#if !(defined JERRY_NDEBUG) + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); + } +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + +#if !(defined JERRY_NDEBUG) + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); + } +#endif /* !JERRY_NDEBUG */ + + /* 'Variable declaration' */ + result = ecma_op_has_binding (lex_env_p, name_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_property_t *prop_p = NULL; + + if (ecma_is_value_false (result)) + { + bool is_configurable = (frame_ctx_p->status_flags & VM_FRAME_CTX_DIRECT_EVAL) != 0; + prop_p = ecma_op_create_mutable_binding (lex_env_p, name_p, is_configurable); + + if (JERRY_UNLIKELY (prop_p == ECMA_PROPERTY_POINTER_ERROR)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + } + + if (lit_value != ECMA_VALUE_UNDEFINED) + { + JERRY_ASSERT (ecma_is_value_object (lit_value)); + + if (prop_p != NULL) + { + JERRY_ASSERT (ecma_is_value_undefined (ECMA_PROPERTY_VALUE_PTR (prop_p)->value)); + JERRY_ASSERT (ecma_is_property_writable (*prop_p)); + ECMA_PROPERTY_VALUE_PTR (prop_p)->value = lit_value; + ecma_free_object (lit_value); + } + else + { + result = ecma_op_put_value_lex_env_base (lex_env_p, name_p, is_strict, lit_value); + ecma_free_object (lit_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + } + } + continue; + } + case VM_OC_EXT_VAR_EVAL: + { + uint32_t literal_index; + ecma_value_t lit_value = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE); + + if (opcode == CBC_EXT_CREATE_VAR_FUNC_EVAL) + { + uint32_t value_index; + READ_LITERAL_INDEX (value_index); + JERRY_ASSERT (value_index >= const_literal_end); + + lit_value = vm_construct_literal_object (frame_ctx_p, literal_start_p[value_index]); + } + + READ_LITERAL_INDEX (literal_index); + JERRY_ASSERT (literal_index >= register_end); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + ecma_object_t *prev_lex_env_p = NULL; + + while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { +#if !(defined JERRY_NDEBUG) + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); + } +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + prev_lex_env_p = lex_env_p; + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (prev_lex_env_p != NULL + && ecma_get_lex_env_type (prev_lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + + ecma_property_t *property_p = ecma_find_named_property (prev_lex_env_p, name_p); + ecma_property_value_t *property_value_p; + + if (property_p == NULL) + { + property_value_p = + ecma_create_named_data_property (prev_lex_env_p, name_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE, NULL); + + if (lit_value == ECMA_VALUE_UNDEFINED) + { + continue; + } + } + else + { + if (lit_value == ECMA_VALUE_UNDEFINED) + { + continue; + } + + property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + ecma_free_value_if_not_object (property_value_p->value); + } + + property_value_p->value = lit_value; + ecma_deref_object (ecma_get_object_from_value (lit_value)); + continue; + } + case VM_OC_CREATE_ARGUMENTS: + { + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_ARG_LIST); + + result = ecma_op_create_arguments_object ((vm_frame_ctx_shared_args_t *) (frame_ctx_p->shared_p), + frame_ctx_p->lex_env_p); + + if (literal_index < register_end) + { + JERRY_ASSERT (VM_GET_REGISTER (frame_ctx_p, literal_index) == ECMA_VALUE_UNDEFINED); + VM_GET_REGISTER (frame_ctx_p, literal_index) = result; + continue; + } + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL); + + uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; + ecma_property_value_t *property_value_p; + + property_value_p = ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, prop_attributes, NULL); + property_value_p->value = result; + + ecma_deref_object (ecma_get_object_from_value (result)); + continue; + } +#if JERRY_SNAPSHOT_EXEC + case VM_OC_SET_BYTECODE_PTR: + { + memcpy (&byte_code_p, byte_code_p++, sizeof (uintptr_t)); + frame_ctx_p->byte_code_start_p = byte_code_p; + continue; + } +#endif /* JERRY_SNAPSHOT_EXEC */ + case VM_OC_INIT_ARG_OR_FUNC: + { + uint32_t literal_index, value_index; + ecma_value_t lit_value; + bool release = false; + + READ_LITERAL_INDEX (value_index); + + if (value_index < register_end) + { + /* Take (not copy) the reference. */ + lit_value = ecma_copy_value_if_not_object (VM_GET_REGISTER (frame_ctx_p, value_index)); + } + else + { + lit_value = vm_construct_literal_object (frame_ctx_p, literal_start_p[value_index]); + release = true; + } + + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (value_index != literal_index); + JERRY_ASSERT (value_index >= register_end || literal_index >= register_end); + + if (literal_index < register_end) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + JERRY_ASSERT (release); + VM_GET_REGISTER (frame_ctx_p, literal_index) = lit_value; + continue; + } + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL); + + ecma_property_value_t *property_value_p; + property_value_p = + ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + + JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED); + property_value_p->value = lit_value; + + if (release) + { + ecma_deref_object (ecma_get_object_from_value (lit_value)); + } + continue; + } + case VM_OC_CHECK_VAR: + { + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) + == CBC_FUNCTION_SCRIPT); + + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + + if ((frame_ctx_p->lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) == 0) + { + continue; + } + + ecma_string_t *const literal_name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_property_t *const binding_p = ecma_find_named_property (frame_ctx_p->lex_env_p, literal_name_p); + + if (binding_p != NULL) + { + result = ecma_raise_syntax_error (ECMA_ERR_LOCAL_VARIABLE_IS_REDECLARED); + goto error; + } + + continue; + } + case VM_OC_CHECK_LET: + { + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) + == CBC_FUNCTION_SCRIPT); + + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + + ecma_string_t *literal_name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + + if (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { + result = opfunc_lexical_scope_has_restricted_binding (frame_ctx_p, literal_name_p); + + if (!ecma_is_value_false (result)) + { + if (ecma_is_value_true (result)) + { + result = ecma_raise_syntax_error (ECMA_ERR_LOCAL_VARIABLE_IS_REDECLARED); + } + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result)); + goto error; + } + + continue; + } + + result = ecma_op_has_binding (lex_env_p, literal_name_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (result)) + { + result = ecma_raise_syntax_error (ECMA_ERR_LOCAL_VARIABLE_IS_REDECLARED); + goto error; + } + + continue; + } + case VM_OC_ASSIGN_LET_CONST: + { + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (literal_index >= register_end); + JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE + || (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && ECMA_LEX_ENV_CLASS_IS_MODULE (frame_ctx_p->lex_env_p))); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_property_t *property_p = ecma_find_named_property (frame_ctx_p->lex_env_p, name_p); + + JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*property_p) + && (*property_p & ECMA_PROPERTY_FLAG_DATA)); + JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p)->value == ECMA_VALUE_UNINITIALIZED); + + ECMA_PROPERTY_VALUE_PTR (property_p)->value = left_value; + + if (ecma_is_value_object (left_value)) + { + ecma_deref_object (ecma_get_object_from_value (left_value)); + } + continue; + } + case VM_OC_INIT_BINDING: + { + uint32_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (literal_index >= register_end); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL); + + uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; + + if (opcode == CBC_INIT_LET) + { + prop_attributes = ECMA_PROPERTY_ENUMERABLE_WRITABLE; + } + else if (opcode == CBC_INIT_CONST) + { + prop_attributes = ECMA_PROPERTY_FLAG_ENUMERABLE; + } + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, prop_attributes, NULL); + + JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED); + + ecma_value_t value = *(--stack_top_p); + + property_value_p->value = value; + ecma_deref_if_object (value); + continue; + } + case VM_OC_THROW_CONST_ERROR: + { + result = ecma_raise_type_error (ECMA_ERR_CONSTANT_BINDINGS_CANNOT_BE_REASSIGNED); + goto error; + } + case VM_OC_COPY_TO_GLOBAL: + { + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + + while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { +#ifndef JERRY_NDEBUG + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); + } +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + ecma_property_value_t *prop_value_p; + + if (property_p == NULL) + { + prop_value_p = ecma_create_named_data_property (lex_env_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + } + else + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (!(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); +#endif /* !JERRY_NDEBUG */ + prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + } + + ecma_named_data_property_assign_value (lex_env_p, prop_value_p, left_value); + } + else + { + result = ecma_op_set_mutable_binding (lex_env_p, name_p, left_value, is_strict); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + } + + goto free_left_value; + } + case VM_OC_COPY_FROM_ARG: + { + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + JERRY_ASSERT (literal_index >= register_end); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + ecma_object_t *arg_lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + + JERRY_ASSERT ((lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + && ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (arg_lex_env_p != NULL && !(arg_lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + && ecma_get_lex_env_type (arg_lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (lex_env_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + + ecma_property_t *property_p = ecma_find_named_property (arg_lex_env_p, name_p); + JERRY_ASSERT (property_p != NULL); + + ecma_property_value_t *arg_prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + property_value_p->value = ecma_copy_value_if_not_object (arg_prop_value_p->value); + continue; + } + case VM_OC_CLONE_CONTEXT: + { + JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE); + + bool copy_values = (byte_code_start_p[1] == CBC_EXT_CLONE_FULL_CONTEXT); + frame_ctx_p->lex_env_p = ecma_clone_decl_lexical_environment (frame_ctx_p->lex_env_p, copy_values); + continue; + } + case VM_OC_SET__PROTO__: + { + result = ecma_builtin_object_object_set_proto (stack_top_p[-1], left_value); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + goto free_left_value; + } + case VM_OC_CLASS_CALL_STATIC_BLOCK: + { + result = ecma_op_function_call (ecma_get_object_from_value (left_value), frame_ctx_p->this_binding, NULL, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + goto free_left_value; + } + case VM_OC_PUSH_STATIC_FIELD_FUNC: + { + JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE + && (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_FIELD_FUNC + || byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC)); + + bool push_computed = (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC); + ecma_value_t value = stack_top_p[-1]; + + if (!push_computed) + { + stack_top_p++; + } + + memmove (stack_top_p - 3, stack_top_p - 4, 3 * sizeof (ecma_value_t)); + stack_top_p[-4] = left_value; + + ecma_object_t *class_object_p = ecma_get_object_from_value (stack_top_p[-2]); + ecma_object_t *initializer_func_p = ecma_get_object_from_value (left_value); + opfunc_bind_class_environment (frame_ctx_p->lex_env_p, class_object_p, class_object_p, initializer_func_p); + + if (!push_computed) + { + continue; + } + + left_value = value; + /* FALLTHRU */ + } + case VM_OC_ADD_COMPUTED_FIELD: + { + JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE + && (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC + || byte_code_start_p[1] == CBC_EXT_ADD_COMPUTED_FIELD + || byte_code_start_p[1] == CBC_EXT_ADD_STATIC_COMPUTED_FIELD)); + + int index = (byte_code_start_p[1] == CBC_EXT_ADD_COMPUTED_FIELD) ? -2 : -4; + result = opfunc_add_computed_field (stack_top_p[index], left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + goto free_left_value; + } + case VM_OC_COPY_DATA_PROPERTIES: + { + left_value = *(--stack_top_p); + + if (ecma_is_value_undefined (left_value) || ecma_is_value_null (left_value)) + { + continue; + } + + result = opfunc_copy_data_properties (stack_top_p[-1], left_value, ECMA_VALUE_UNDEFINED); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + goto free_left_value; + } + case VM_OC_SET_COMPUTED_PROPERTY: + { + /* Swap values. */ + left_value ^= right_value; + right_value ^= left_value; + left_value ^= right_value; + /* FALLTHRU */ + } + case VM_OC_SET_PROPERTY: + { + JERRY_STATIC_ASSERT ((VM_OC_NON_STATIC_FLAG == VM_OC_BACKWARD_BRANCH), + vm_oc_non_static_flag_must_be_equal_to_vm_oc_backward_branch); + + JERRY_ASSERT ((opcode_data >> VM_OC_NON_STATIC_SHIFT) <= 0x1); + + ecma_string_t *prop_name_p = ecma_op_to_property_key (right_value); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE)) + && !(opcode_data & VM_OC_NON_STATIC_FLAG)) + { + result = ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE); + goto error; + } + + const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2; + + ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[index]); + + opfunc_set_data_property (object_p, prop_name_p, left_value); + ecma_deref_ecma_string (prop_name_p); + + goto free_both_values; + } + case VM_OC_SET_GETTER: + case VM_OC_SET_SETTER: + { + JERRY_ASSERT ((opcode_data >> VM_OC_NON_STATIC_SHIFT) <= 0x1); + + ecma_string_t *prop_name_p = ecma_op_to_property_key (left_value); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE)) + && !(opcode_data & VM_OC_NON_STATIC_FLAG)) + { + result = ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE); + goto error; + } + + const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2; + opfunc_set_accessor (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_SET_GETTER, + stack_top_p[index], + prop_name_p, + right_value); + + ecma_deref_ecma_string (prop_name_p); + + goto free_both_values; + } + case VM_OC_PUSH_ARRAY: + { + /* Note: this operation cannot throw an exception */ + *stack_top_p++ = ecma_make_object_value (ecma_op_new_array_object (0)); + continue; + } + case VM_OC_LOCAL_EVAL: + { + ECMA_CLEAR_LOCAL_PARSE_OPTS (); + uint8_t parse_opts = *byte_code_p++; + ECMA_SET_LOCAL_PARSE_OPTS (parse_opts); + continue; + } + case VM_OC_SUPER_CALL: + { + uint8_t arguments_list_len = *byte_code_p++; + + if (opcode >= CBC_EXT_SPREAD_SUPER_CALL) + { + stack_top_p -= arguments_list_len; + ecma_collection_t *arguments_p = opfunc_spread_arguments (stack_top_p, arguments_list_len); + + if (JERRY_UNLIKELY (arguments_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + stack_top_p++; + ECMA_SET_INTERNAL_VALUE_POINTER (stack_top_p[-1], arguments_p); + } + else + { + stack_top_p -= arguments_list_len; + } + + frame_ctx_p->call_operation = VM_EXEC_SUPER_CALL; + frame_ctx_p->byte_code_p = byte_code_start_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_PUSH_CLASS_ENVIRONMENT: + { + uint16_t literal_index; + + READ_LITERAL_INDEX (literal_index); + opfunc_push_class_environment (frame_ctx_p, &stack_top_p, literal_start_p[literal_index]); + continue; + } + case VM_OC_PUSH_IMPLICIT_CTOR: + { + *stack_top_p++ = opfunc_create_implicit_class_constructor (opcode, frame_ctx_p->shared_p->bytecode_header_p); + continue; + } + case VM_OC_DEFINE_FIELD: + { + result = opfunc_define_field (frame_ctx_p->this_binding, right_value, left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + goto free_both_values; + } + case VM_OC_ASSIGN_PRIVATE: + { + result = opfunc_private_set (stack_top_p[-3], stack_top_p[-2], stack_top_p[-1]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_free_value (stack_top_p[-3]); + ecma_free_value (stack_top_p[-2]); + ecma_free_value (stack_top_p[-1]); + stack_top_p -= 3; + + if (opcode_data & VM_OC_PUT_STACK) + { + *stack_top_p++ = result; + } + else if (opcode_data & VM_OC_PUT_BLOCK) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = result; + } + else + { + ecma_free_value (result); + } + + goto free_both_values; + } + case VM_OC_PRIVATE_FIELD_ADD: + { + result = opfunc_private_field_add (frame_ctx_p->this_binding, right_value, left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + goto free_both_values; + } + case VM_OC_PRIVATE_PROP_GET: + { + result = opfunc_private_get (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_PRIVATE_PROP_REFERENCE: + { + result = opfunc_private_get (stack_top_p[-1], left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = left_value; + *stack_top_p++ = result; + continue; + } + case VM_OC_PRIVATE_IN: + { + result = opfunc_private_in (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_COLLECT_PRIVATE_PROPERTY: + { + opfunc_collect_private_properties (stack_top_p[-2], left_value, right_value, opcode); + continue; + } + case VM_OC_INIT_CLASS: + { + result = opfunc_init_class (frame_ctx_p, stack_top_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + continue; + } + case VM_OC_FINALIZE_CLASS: + { + JERRY_ASSERT (opcode == CBC_EXT_FINALIZE_NAMED_CLASS || opcode == CBC_EXT_FINALIZE_ANONYMOUS_CLASS); + + if (opcode == CBC_EXT_FINALIZE_NAMED_CLASS) + { + uint16_t literal_index; + READ_LITERAL_INDEX (literal_index); + left_value = literal_start_p[literal_index]; + } + + opfunc_finalize_class (frame_ctx_p, &stack_top_p, left_value); + continue; + } + case VM_OC_SET_FIELD_INIT: + { + ecma_string_t *property_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT); + ecma_object_t *proto_object_p = ecma_get_object_from_value (stack_top_p[-1]); + ecma_object_t *class_object_p = ecma_get_object_from_value (stack_top_p[-2]); + ecma_object_t *initializer_func_p = ecma_get_object_from_value (left_value); + + opfunc_bind_class_environment (frame_ctx_p->lex_env_p, proto_object_p, class_object_p, initializer_func_p); + + ecma_property_value_t *property_value_p = + ecma_create_named_data_property (class_object_p, property_name_p, ECMA_PROPERTY_FIXED, NULL); + property_value_p->value = left_value; + + property_name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED); + ecma_property_t *property_p = ecma_find_named_property (class_object_p, property_name_p); + + if (property_p != NULL) + { + property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + ecma_value_t *compact_collection_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, property_value_p->value); + compact_collection_p = ecma_compact_collection_shrink (compact_collection_p); + ECMA_SET_INTERNAL_VALUE_POINTER (property_value_p->value, compact_collection_p); + } + + goto free_left_value; + } + case VM_OC_RUN_FIELD_INIT: + { + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC); + result = opfunc_init_class_fields (frame_ctx_p->shared_p->function_object_p, frame_ctx_p->this_binding); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + continue; + } + case VM_OC_RUN_STATIC_FIELD_INIT: + { + left_value = stack_top_p[-2]; + stack_top_p[-2] = stack_top_p[-1]; + stack_top_p--; + + result = opfunc_init_static_class_fields (left_value, stack_top_p[-1]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + goto free_left_value; + } + case VM_OC_SET_NEXT_COMPUTED_FIELD: + { + ecma_integer_value_t next_index = ecma_get_integer_from_value (stack_top_p[-2]) + 1; + stack_top_p[-2] = ecma_make_integer_value (next_index); + + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS); + + ecma_value_t *computed_class_fields_p = VM_GET_COMPUTED_CLASS_FIELDS (frame_ctx_p); + JERRY_ASSERT ((ecma_value_t) next_index < ECMA_COMPACT_COLLECTION_GET_SIZE (computed_class_fields_p)); + ecma_value_t prop_name = computed_class_fields_p[next_index]; + + if (opcode == CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC) + { + ecma_object_t *func_obj_p = ecma_get_object_from_value (stack_top_p[-1]); + + JERRY_ASSERT (ecma_find_named_property (func_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_NAME)) == NULL); + ecma_property_value_t *value_p; + value_p = ecma_create_named_data_property (func_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_NAME), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + + if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp); + } + + value_p->value = ecma_copy_value (prop_name); + } + + result = opfunc_define_field (frame_ctx_p->this_binding, prop_name, stack_top_p[-1]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_free_value (*(--stack_top_p)); + continue; + } + case VM_OC_PUSH_SUPER_CONSTRUCTOR: + { + result = ecma_op_function_get_super_constructor (vm_get_class_function (frame_ctx_p)); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + continue; + } + case VM_OC_RESOLVE_LEXICAL_THIS: + { + result = ecma_op_get_this_binding (frame_ctx_p->lex_env_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + continue; + } + case VM_OC_OBJECT_LITERAL_HOME_ENV: + { + if (opcode == CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT) + { + ecma_value_t obj_value = stack_top_p[-1]; + ecma_object_t *obj_env_p = ecma_create_lex_env_class (frame_ctx_p->lex_env_p, 0); + + ECMA_SET_NON_NULL_POINTER (obj_env_p->u1.bound_object_cp, ecma_get_object_from_value (obj_value)); + stack_top_p[-1] = ecma_make_object_value (obj_env_p); + *stack_top_p++ = obj_value; + } + else + { + JERRY_ASSERT (opcode == CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT); + ecma_deref_object (ecma_get_object_from_value (stack_top_p[-2])); + stack_top_p[-2] = stack_top_p[-1]; + stack_top_p--; + } + continue; + } + case VM_OC_SET_HOME_OBJECT: + { + int offset = opcode == CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED ? -1 : 0; + opfunc_set_home_object (ecma_get_object_from_value (stack_top_p[-1]), + ecma_get_object_from_value (stack_top_p[-3 + offset])); + continue; + } + case VM_OC_SUPER_REFERENCE: + { + result = opfunc_form_super_reference (&stack_top_p, frame_ctx_p, left_value, opcode); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + goto free_left_value; + } + case VM_OC_SET_FUNCTION_NAME: + { + const char *prefix_p = NULL; + lit_utf8_size_t prefix_size = 0; + + if (opcode != CBC_EXT_SET_FUNCTION_NAME) + { + ecma_value_t prop_name_value; + + if (opcode == CBC_EXT_SET_CLASS_NAME) + { + uint16_t literal_index; + READ_LITERAL_INDEX (literal_index); + prop_name_value = literal_start_p[literal_index]; + } + else + { + prop_name_value = stack_top_p[-2]; + } + + ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name_value); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + left_value = ecma_make_prop_name_value (prop_name_p); + + if (opcode != CBC_EXT_SET_CLASS_NAME) + { + ecma_ref_ecma_string (prop_name_p); + ecma_free_value (stack_top_p[-2]); + stack_top_p[-2] = left_value; + } + + if (opcode == CBC_EXT_SET_COMPUTED_GETTER_NAME || opcode == CBC_EXT_SET_COMPUTED_SETTER_NAME) + { + prefix_p = (opcode == CBC_EXT_SET_COMPUTED_GETTER_NAME) ? "get " : "set "; + prefix_size = 4; + } + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (stack_top_p[-1]); + + if (ecma_find_named_property (func_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_NAME)) != NULL) + { + ecma_free_value (left_value); + continue; + } + + ecma_property_value_t *value_p; + value_p = ecma_create_named_data_property (func_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_NAME), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + + if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp); + } + + value_p->value = + ecma_op_function_form_name (ecma_get_prop_name_from_value (left_value), (char*) prefix_p, prefix_size); + ecma_free_value (left_value); + continue; + } + case VM_OC_PUSH_SPREAD_ELEMENT: + { + *stack_top_p++ = ECMA_VALUE_SPREAD_ELEMENT; + continue; + } + case VM_OC_PUSH_REST_OBJECT: + { + vm_frame_ctx_shared_t *shared_p = frame_ctx_p->shared_p; + + JERRY_ASSERT (shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_ARG_LIST); + + const ecma_value_t *arg_list_p = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_p; + uint32_t arg_list_len = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_len; + uint16_t argument_end; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + argument_end = ((cbc_uint16_arguments_t *) bytecode_header_p)->argument_end; + } + else + { + argument_end = ((cbc_uint8_arguments_t *) bytecode_header_p)->argument_end; + } + + if (arg_list_len < argument_end) + { + arg_list_len = argument_end; + } + + result = ecma_op_new_array_object_from_buffer (arg_list_p + argument_end, arg_list_len - argument_end); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (result)); + *stack_top_p++ = result; + continue; + } + case VM_OC_ITERATOR_CONTEXT_CREATE: + { + result = ecma_op_get_iterator (stack_top_p[-1], ECMA_VALUE_SYNC_ITERATOR, &left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + uint32_t context_size = + (uint32_t) (stack_top_p + PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION - VM_LAST_CONTEXT_END ()); + stack_top_p += PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION; + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size); + + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_ITERATOR, context_size) | VM_CONTEXT_CLOSE_ITERATOR; + stack_top_p[-2] = result; + stack_top_p[-3] = left_value; + + continue; + } + case VM_OC_ITERATOR_STEP: + { + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); + + ecma_value_t iterator = last_context_end_p[-2]; + ecma_value_t next_method = last_context_end_p[-3]; + + result = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + goto error; + } + + ecma_value_t value = ECMA_VALUE_UNDEFINED; + + if (!ecma_is_value_false (result)) + { + value = ecma_op_iterator_value (result); + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (value)) + { + last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + result = value; + goto error; + } + } + else + { + last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + } + + *stack_top_p++ = value; + continue; + } + case VM_OC_ITERATOR_CONTEXT_END: + { + JERRY_ASSERT (VM_LAST_CONTEXT_END () == stack_top_p); + + if (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR) + { + stack_top_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + result = ecma_op_iterator_close (stack_top_p[-2]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + } + + stack_top_p = + vm_stack_context_abort_variable_length (frame_ctx_p, stack_top_p, PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION); + continue; + } + case VM_OC_DEFAULT_INITIALIZER: + { + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + + if (stack_top_p[-1] != ECMA_VALUE_UNDEFINED) + { + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + + stack_top_p--; + continue; + } + case VM_OC_REST_INITIALIZER: + { + ecma_object_t *array_p = ecma_op_new_array_object (0); + JERRY_ASSERT (ecma_op_object_is_fast_array (array_p)); + + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); + ecma_value_t iterator = last_context_end_p[-2]; + ecma_value_t next_method = last_context_end_p[-3]; + uint32_t index = 0; + + while (true) + { + result = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + ecma_deref_object (array_p); + goto error; + } + + if (ecma_is_value_false (result)) + { + last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + break; + } + + ecma_value_t value = ecma_op_iterator_value (result); + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (value)) + { + ecma_deref_object (array_p); + result = value; + goto error; + } + + bool set_result = ecma_fast_array_set_property (array_p, index++, value); + JERRY_ASSERT (set_result); + ecma_free_value (value); + } + + *stack_top_p++ = ecma_make_object_value (array_p); + continue; + } + case VM_OC_OBJ_INIT_CONTEXT_CREATE: + { + left_value = stack_top_p[-1]; + vm_stack_context_type_t context_type = VM_CONTEXT_OBJ_INIT; + uint32_t context_stack_allocation = PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION; + + if (opcode == CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE) + { + context_type = VM_CONTEXT_OBJ_INIT_REST; + context_stack_allocation = PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION; + } + + uint32_t context_size = (uint32_t) (stack_top_p + context_stack_allocation - VM_LAST_CONTEXT_END ()); + stack_top_p += context_stack_allocation; + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size); + + stack_top_p[-1] = VM_CREATE_CONTEXT (context_type, context_size); + stack_top_p[-2] = left_value; + + if (context_type == VM_CONTEXT_OBJ_INIT_REST) + { + stack_top_p[-3] = ecma_make_object_value (ecma_op_new_array_object (0)); + } + continue; + } + case VM_OC_OBJ_INIT_CONTEXT_END: + { + JERRY_ASSERT (stack_top_p == VM_LAST_CONTEXT_END ()); + + uint32_t context_stack_allocation = PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION; + + if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_OBJ_INIT_REST) + { + context_stack_allocation = PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION; + } + + stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p, stack_top_p, context_stack_allocation); + continue; + } + case VM_OC_OBJ_INIT_PUSH_REST: + { + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); + if (!ecma_op_require_object_coercible (last_context_end_p[-2])) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + ecma_object_t *result_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + + left_value = ecma_make_object_value (result_object_p); + result = opfunc_copy_data_properties (left_value, last_context_end_p[-2], last_context_end_p[-3]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_free_value (last_context_end_p[-3]); + last_context_end_p[-3] = last_context_end_p[-2]; + last_context_end_p[-2] = ECMA_VALUE_UNDEFINED; + + *stack_top_p++ = left_value; + continue; + } + case VM_OC_INITIALIZER_PUSH_NAME: + { + if (JERRY_UNLIKELY (!ecma_is_value_prop_name (left_value))) + { + ecma_string_t *property_key = ecma_op_to_property_key (left_value); + + if (property_key == NULL) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + ecma_free_value (left_value); + left_value = ecma_make_string_value (property_key); + } + + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); + ecma_object_t *array_obj_p = ecma_get_object_from_value (last_context_end_p[-3]); + JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY); + + ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p; + ecma_fast_array_set_property (array_obj_p, ext_array_obj_p->u.array.length, left_value); + /* FALLTHRU */ + } + case VM_OC_INITIALIZER_PUSH_PROP: + { + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); + ecma_value_t base = last_context_end_p[-2]; + + if (opcode == CBC_EXT_INITIALIZER_PUSH_PROP) + { + left_value = *last_context_end_p++; + while (last_context_end_p < stack_top_p) + { + last_context_end_p[-1] = *last_context_end_p; + last_context_end_p++; + } + stack_top_p--; + } + + result = vm_op_get_value (base, left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_left_value; + } + case VM_OC_SPREAD_ARGUMENTS: + { + uint8_t arguments_list_len = *byte_code_p++; + stack_top_p -= arguments_list_len; + + ecma_collection_t *arguments_p = opfunc_spread_arguments (stack_top_p, arguments_list_len); + + if (JERRY_UNLIKELY (arguments_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + stack_top_p++; + ECMA_SET_INTERNAL_VALUE_POINTER (stack_top_p[-1], arguments_p); + + frame_ctx_p->call_operation = VM_EXEC_SPREAD_OP; + frame_ctx_p->byte_code_p = byte_code_start_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_CREATE_GENERATOR: + { + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + + vm_executable_object_t *executable_object_p; + executable_object_p = opfunc_create_executable_object (frame_ctx_p, VM_CREATE_EXECUTABLE_OBJECT_GENERATOR); + + return ecma_make_object_value ((ecma_object_t *) executable_object_p); + } + case VM_OC_YIELD: + { + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = --stack_top_p; + return *stack_top_p; + } + case VM_OC_ASYNC_YIELD: + { + ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + + opfunc_async_generator_yield (async_generator_object_p, stack_top_p[-1]); + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = --stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_ASYNC_YIELD_ITERATOR: + { + ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + + JERRY_ASSERT ( + !(async_generator_object_p->u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD)); + + /* Byte code is executed at the first time. */ + left_value = stack_top_p[-1]; + result = ecma_op_get_iterator (left_value, ECMA_VALUE_ASYNC_ITERATOR, stack_top_p - 1); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_free_value (left_value); + left_value = result; + result = ecma_op_iterator_next (left_value, stack_top_p[-1], ECMA_VALUE_UNDEFINED); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + result = ecma_promise_async_await (async_generator_object_p, result); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + async_generator_object_p->u.cls.u2.executable_obj_flags |= ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD; + *VM_GET_EXECUTABLE_ITERATOR (frame_ctx_p) = left_value; + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_AWAIT: + { + if (JERRY_UNLIKELY (!(frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_EXECUTABLE))) + { + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = --stack_top_p; + + result = opfunc_async_create_and_await (frame_ctx_p, *stack_top_p, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + return result; + } + /* FALLTHRU */ + } + case VM_OC_GENERATOR_AWAIT: + { + ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + + result = ecma_promise_async_await (async_generator_object_p, *(--stack_top_p)); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_EXT_RETURN: + { + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + + ecma_value_t *stack_bottom_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + + while (stack_top_p > stack_bottom_p) + { + ecma_fast_free_value (*(--stack_top_p)); + } + + goto error; + } + case VM_OC_ASYNC_EXIT: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + if (!(frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_EXECUTABLE)) + { + result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL); + } + else + { + result = *VM_GET_EXECUTABLE_ITERATOR (frame_ctx_p); + *VM_GET_EXECUTABLE_ITERATOR (frame_ctx_p) = ECMA_VALUE_UNDEFINED; + } + + vm_stack_context_type_t context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]); + + if (context_type == VM_CONTEXT_TRY) + { + JERRY_ASSERT (frame_ctx_p->context_depth == PARSER_TRY_CONTEXT_STACK_ALLOCATION); + left_value = ECMA_VALUE_UNDEFINED; + } + else + { + JERRY_ASSERT (frame_ctx_p->context_depth == PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); + left_value = stack_top_p[-2]; + } + + if (context_type == VM_CONTEXT_FINALLY_THROW) + { + ecma_reject_promise (result, left_value); + } + else + { + JERRY_ASSERT (context_type == VM_CONTEXT_TRY || context_type == VM_CONTEXT_FINALLY_RETURN); + ecma_fulfill_promise (result, left_value); + } + + ecma_free_value (left_value); + + frame_ctx_p->context_depth = 0; + frame_ctx_p->call_operation = VM_NO_EXEC_OP; + return result; + } + case VM_OC_STRING_CONCAT: + { + ecma_string_t *left_str_p = ecma_op_to_string (left_value); + + if (JERRY_UNLIKELY (left_str_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + ecma_string_t *right_str_p = ecma_op_to_string (right_value); + + if (JERRY_UNLIKELY (right_str_p == NULL)) + { + ecma_deref_ecma_string (left_str_p); + result = ECMA_VALUE_ERROR; + goto error; + } + + ecma_string_t *result_str_p = ecma_concat_ecma_strings (left_str_p, right_str_p); + ecma_deref_ecma_string (right_str_p); + + *stack_top_p++ = ecma_make_string_value (result_str_p); + goto free_both_values; + } + case VM_OC_GET_TEMPLATE_OBJECT: + { + uint8_t tagged_idx = *byte_code_p++; + ecma_collection_t *collection_p = ecma_compiled_code_get_tagged_template_collection (bytecode_header_p); + JERRY_ASSERT (tagged_idx < collection_p->item_count); + + *stack_top_p++ = ecma_copy_value (collection_p->buffer_p[tagged_idx]); + continue; + } + case VM_OC_PUSH_NEW_TARGET: + { + ecma_object_t *new_target_object_p = JERRY_CONTEXT (current_new_target_p); + if (new_target_object_p == NULL) + { + *stack_top_p++ = ECMA_VALUE_UNDEFINED; + } + else + { + ecma_ref_object (new_target_object_p); + *stack_top_p++ = ecma_make_object_value (new_target_object_p); + } + continue; + } + case VM_OC_REQUIRE_OBJECT_COERCIBLE: + { + if (!ecma_op_require_object_coercible (stack_top_p[-1])) + { + result = ECMA_VALUE_ERROR; + goto error; + } + continue; + } + case VM_OC_ASSIGN_SUPER: + { + result = opfunc_assign_super_reference (&stack_top_p, frame_ctx_p, opcode_data); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + continue; + } + case VM_OC_PUSH_ELISON: + { + *stack_top_p++ = ECMA_VALUE_ARRAY_HOLE; + continue; + } + case VM_OC_APPEND_ARRAY: + { + uint16_t values_length = *byte_code_p++; + stack_top_p -= values_length; + + if (*byte_code_start_p == CBC_EXT_OPCODE) + { + values_length = (uint16_t) (values_length | OPFUNC_HAS_SPREAD_ELEMENT); + } + result = opfunc_append_array (stack_top_p, values_length); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + continue; + } + case VM_OC_IDENT_REFERENCE: + { + uint16_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (literal_index < ident_end); + + if (literal_index < register_end) + { + *stack_top_p++ = ECMA_VALUE_REGISTER_REF; + *stack_top_p++ = ecma_make_integer_value (literal_index); + *stack_top_p++ = ecma_fast_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + } + else + { + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + ecma_object_t *ref_base_lex_env_p; + + result = ecma_op_get_value_lex_env_base (frame_ctx_p->lex_env_p, &ref_base_lex_env_p, name_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_ref_object (ref_base_lex_env_p); + ecma_ref_ecma_string (name_p); + *stack_top_p++ = ecma_make_object_value (ref_base_lex_env_p); + *stack_top_p++ = ecma_make_string_value (name_p); + *stack_top_p++ = result; + } + continue; + } + case VM_OC_PROP_GET: + { + result = vm_op_get_value (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_PROP_REFERENCE: + { + /* Forms with reference requires preserving the base and offset. */ + + if (opcode == CBC_PUSH_PROP_REFERENCE) + { + left_value = stack_top_p[-2]; + right_value = stack_top_p[-1]; + } + else if (opcode == CBC_PUSH_PROP_LITERAL_REFERENCE) + { + *stack_top_p++ = left_value; + right_value = left_value; + left_value = stack_top_p[-2]; + } + else + { + JERRY_ASSERT (opcode == CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE + || opcode == CBC_PUSH_PROP_THIS_LITERAL_REFERENCE); + *stack_top_p++ = left_value; + *stack_top_p++ = right_value; + } + /* FALLTHRU */ + } + case VM_OC_PROP_PRE_INCR: + case VM_OC_PROP_PRE_DECR: + case VM_OC_PROP_POST_INCR: + case VM_OC_PROP_POST_DECR: + { + result = vm_op_get_value (left_value, right_value); + + if (opcode < CBC_PRE_INCR) + { + left_value = ECMA_VALUE_UNDEFINED; + right_value = ECMA_VALUE_UNDEFINED; + } + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + if (opcode < CBC_PRE_INCR) + { + break; + } + + stack_top_p += 2; + left_value = result; + right_value = ECMA_VALUE_UNDEFINED; + /* FALLTHRU */ + } + case VM_OC_PRE_INCR: + case VM_OC_PRE_DECR: + case VM_OC_POST_INCR: + case VM_OC_POST_DECR: + { + uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_PROP_PRE_INCR; + ecma_number_t result_number; + + byte_code_p = byte_code_start_p + 1; + + if (ecma_is_value_integer_number (left_value)) + { + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + + ecma_integer_value_t int_value = (ecma_integer_value_t) result; + ecma_integer_value_t int_increase = 0; + + if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) + { + if (int_value > ECMA_INTEGER_NUMBER_MIN_SHIFTED) + { + int_increase = -(1 << ECMA_DIRECT_SHIFT); + } + } + else if (int_value < ECMA_INTEGER_NUMBER_MAX_SHIFTED) + { + int_increase = 1 << ECMA_DIRECT_SHIFT; + } + + if (JERRY_LIKELY (int_increase != 0)) + { + /* Postfix operators require the unmodifed number value. */ + if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) + { + POST_INCREASE_DECREASE_PUT_RESULT (result); + } + + result = (ecma_value_t) (int_value + int_increase); + break; + } + result_number = (ecma_number_t) ecma_get_integer_from_value (result); + } + else if (ecma_is_value_float_number (left_value)) + { + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + result_number = ecma_get_number_from_value (result); + } + else + { + result = ecma_op_to_numeric (left_value, &result_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_free_value (left_value); + left_value = ECMA_VALUE_UNDEFINED; + +#if JERRY_BUILTIN_BIGINT + if (JERRY_UNLIKELY (ecma_is_value_bigint (result))) + { + ecma_bigint_unary_operation_type operation_type = ECMA_BIGINT_UNARY_INCREASE; + + if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) + { + operation_type = ECMA_BIGINT_UNARY_DECREASE; + } + + /* Postfix operators require the unmodifed number value. */ + if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) + { + POST_INCREASE_DECREASE_PUT_RESULT (result); + + result = ecma_bigint_unary (result, operation_type); + } + else + { + ecma_value_t original_value = result; + result = ecma_bigint_unary (original_value, operation_type); + ecma_free_value (original_value); + } + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + break; + } +#endif /* JERRY_BUILTIN_BIGINT */ + + result = ecma_make_number_value (result_number); + } + + ecma_number_t increase = ECMA_NUMBER_ONE; + + if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) + { + /* For decrement operators */ + increase = ECMA_NUMBER_MINUS_ONE; + } + + /* Postfix operators require the unmodifed number value. */ + if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) + { + POST_INCREASE_DECREASE_PUT_RESULT (result); + + result = ecma_make_number_value (result_number + increase); + break; + } + + if (ecma_is_value_integer_number (result)) + { + result = ecma_make_number_value (result_number + increase); + } + else + { + result = ecma_update_float_number (result, result_number + increase); + } + break; + } + case VM_OC_ASSIGN: + { + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + break; + } + case VM_OC_MOV_IDENT: + { + uint32_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (literal_index < register_end); + JERRY_ASSERT (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))); + + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + VM_GET_REGISTER (frame_ctx_p, literal_index) = left_value; + continue; + } + case VM_OC_ASSIGN_PROP: + { + result = stack_top_p[-1]; + stack_top_p[-1] = left_value; + left_value = ECMA_VALUE_UNDEFINED; + break; + } + case VM_OC_ASSIGN_PROP_THIS: + { + result = stack_top_p[-1]; + stack_top_p[-1] = ecma_copy_value (frame_ctx_p->this_binding); + *stack_top_p++ = left_value; + left_value = ECMA_VALUE_UNDEFINED; + break; + } + case VM_OC_RETURN_FUNCTION_END: + { + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) == CBC_FUNCTION_SCRIPT) + { + result = VM_GET_REGISTER (frame_ctx_p, 0); + VM_GET_REGISTERS (frame_ctx_p)[0] = ECMA_VALUE_UNDEFINED; + } + else + { + result = ECMA_VALUE_UNDEFINED; + } + + goto error; + } + case VM_OC_RETURN: + { + JERRY_ASSERT (opcode == CBC_RETURN || opcode == CBC_RETURN_WITH_LITERAL); + + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + goto error; + } + case VM_OC_THROW: + { + jcontext_raise_exception (left_value); + + result = ECMA_VALUE_ERROR; + left_value = ECMA_VALUE_UNDEFINED; + goto error; + } + case VM_OC_THROW_REFERENCE_ERROR: + { + result = ecma_raise_reference_error (ECMA_ERR_UNDEFINED_REFERENCE); + goto error; + } + case VM_OC_EVAL: + { + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_DIRECT_EVAL; + JERRY_ASSERT ((*byte_code_p >= CBC_CALL && *byte_code_p <= CBC_CALL2_PROP_BLOCK) + || (*byte_code_p == CBC_EXT_OPCODE && byte_code_p[1] >= CBC_EXT_SPREAD_CALL + && byte_code_p[1] <= CBC_EXT_SPREAD_CALL_PROP_BLOCK)); + continue; + } + case VM_OC_CALL: + { + frame_ctx_p->call_operation = VM_EXEC_CALL; + frame_ctx_p->byte_code_p = byte_code_start_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_NEW: + { + frame_ctx_p->call_operation = VM_EXEC_CONSTRUCT; + frame_ctx_p->byte_code_p = byte_code_start_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_ERROR: + { + JERRY_ASSERT (frame_ctx_p->byte_code_p[1] == CBC_EXT_ERROR); + + result = ECMA_VALUE_ERROR; + goto error; + } + case VM_OC_RESOLVE_BASE_FOR_CALL: + { + ecma_value_t this_value = stack_top_p[-3]; + + if (this_value == ECMA_VALUE_REGISTER_REF) + { + /* Lexical environment cannot be 'this' value. */ + stack_top_p[-2] = ECMA_VALUE_UNDEFINED; + stack_top_p[-3] = ECMA_VALUE_UNDEFINED; + } + else if (vm_get_implicit_this_value (&this_value)) + { + ecma_free_value (stack_top_p[-3]); + stack_top_p[-3] = this_value; + } + + continue; + } + case VM_OC_PROP_DELETE: + { + result = vm_op_delete_prop (left_value, right_value, is_strict); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + JERRY_ASSERT (ecma_is_value_boolean (result)); + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_DELETE: + { + uint16_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + if (literal_index < register_end) + { + *stack_top_p++ = ECMA_VALUE_FALSE; + continue; + } + + result = vm_op_delete_var (literal_start_p[literal_index], frame_ctx_p->lex_env_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + JERRY_ASSERT (ecma_is_value_boolean (result)); + + *stack_top_p++ = result; + continue; + } + case VM_OC_JUMP: + { + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + case VM_OC_BRANCH_IF_STRICT_EQUAL: + { + ecma_value_t value = *(--stack_top_p); + + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + + if (ecma_op_strict_equality_compare (value, stack_top_p[-1])) + { + byte_code_p = byte_code_start_p + branch_offset; + ecma_free_value (*--stack_top_p); + } + ecma_free_value (value); + continue; + } + case VM_OC_BRANCH_IF_TRUE: + case VM_OC_BRANCH_IF_FALSE: + case VM_OC_BRANCH_IF_LOGICAL_TRUE: + case VM_OC_BRANCH_IF_LOGICAL_FALSE: + { + uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_BRANCH_IF_TRUE; + ecma_value_t value = *(--stack_top_p); + + bool boolean_value = ecma_op_to_boolean (value); + + if (opcode_flags & VM_OC_BRANCH_IF_FALSE_FLAG) + { + boolean_value = !boolean_value; + } + + if (boolean_value) + { + byte_code_p = byte_code_start_p + branch_offset; + if (opcode_flags & VM_OC_LOGICAL_BRANCH_FLAG) + { + /* "Push" the value back to the stack. */ + ++stack_top_p; + continue; + } + } + + ecma_fast_free_value (value); + continue; + } + case VM_OC_POP_REFERENCE: + { + ecma_free_value (stack_top_p[-2]); + ecma_free_value (stack_top_p[-3]); + stack_top_p[-3] = stack_top_p[-1]; + stack_top_p -= 2; + continue; + } + case VM_OC_BRANCH_IF_NULLISH: + { + left_value = stack_top_p[-1]; + + if (!ecma_is_value_null (left_value) && !ecma_is_value_undefined (left_value)) + { + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + --stack_top_p; + continue; + } + case VM_OC_PLUS: + case VM_OC_MINUS: + { + result = opfunc_unary_operation (left_value, VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_PLUS); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_left_value; + } + case VM_OC_NOT: + { + *stack_top_p++ = ecma_make_boolean_value (!ecma_op_to_boolean (left_value)); + JERRY_ASSERT (ecma_is_value_boolean (stack_top_p[-1])); + goto free_left_value; + } + case VM_OC_BIT_NOT: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_is_value_integer_number (left_value)) + { + *stack_top_p++ = (~ECMA_DIRECT_TYPE_MASK) ^ left_value; + goto free_left_value; + } + + result = do_number_bitwise_not (left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_left_value; + } + case VM_OC_VOID: + { + *stack_top_p++ = ECMA_VALUE_UNDEFINED; + goto free_left_value; + } + case VM_OC_TYPEOF_IDENT: + { + uint16_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (literal_index < ident_end); + + if (literal_index < register_end) + { + left_value = ecma_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + } + else + { + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + ecma_object_t *ref_base_lex_env_p; + + result = ecma_op_get_value_lex_env_base (frame_ctx_p->lex_env_p, &ref_base_lex_env_p, name_p); + + if (ref_base_lex_env_p == NULL) + { + jcontext_release_exception (); + result = ECMA_VALUE_UNDEFINED; + } + else if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + left_value = result; + } + /* FALLTHRU */ + } + case VM_OC_TYPEOF: + { + result = opfunc_typeof (left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_left_value; + } + case VM_OC_ADD: + { + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + *stack_top_p++ = ecma_make_int32_value ((int32_t) (left_integer + right_integer)); + continue; + } + + if (ecma_is_value_float_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t new_value = + (ecma_get_float_from_value (left_value) + ecma_get_number_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (left_value, new_value); + ecma_free_number (right_value); + continue; + } + + if (ecma_is_value_float_number (right_value) && ecma_is_value_integer_number (left_value)) + { + ecma_number_t new_value = + ((ecma_number_t) ecma_get_integer_from_value (left_value) + ecma_get_float_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (right_value, new_value); + continue; + } + + result = opfunc_addition (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_SUB: + { + JERRY_STATIC_ASSERT (ECMA_INTEGER_NUMBER_MAX * 2 <= INT32_MAX && ECMA_INTEGER_NUMBER_MIN * 2 >= INT32_MIN, + doubled_ecma_numbers_must_fit_into_int32_range); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + *stack_top_p++ = ecma_make_int32_value ((int32_t) (left_integer - right_integer)); + continue; + } + + if (ecma_is_value_float_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t new_value = + (ecma_get_float_from_value (left_value) - ecma_get_number_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (left_value, new_value); + ecma_free_number (right_value); + continue; + } + + if (ecma_is_value_float_number (right_value) && ecma_is_value_integer_number (left_value)) + { + ecma_number_t new_value = + ((ecma_number_t) ecma_get_integer_from_value (left_value) - ecma_get_float_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (right_value, new_value); + continue; + } + + result = do_number_arithmetic (NUMBER_ARITHMETIC_SUBTRACTION, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_MUL: + { + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + JERRY_STATIC_ASSERT (ECMA_INTEGER_MULTIPLY_MAX * ECMA_INTEGER_MULTIPLY_MAX <= ECMA_INTEGER_NUMBER_MAX + && -(ECMA_INTEGER_MULTIPLY_MAX * ECMA_INTEGER_MULTIPLY_MAX) >= ECMA_INTEGER_NUMBER_MIN, + square_of_integer_multiply_max_must_fit_into_integer_value_range); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + + if (-ECMA_INTEGER_MULTIPLY_MAX <= left_integer && left_integer <= ECMA_INTEGER_MULTIPLY_MAX + && -ECMA_INTEGER_MULTIPLY_MAX <= right_integer && right_integer <= ECMA_INTEGER_MULTIPLY_MAX + && left_integer != 0 && right_integer != 0) + { + *stack_top_p++ = ecma_integer_multiply (left_integer, right_integer); + continue; + } + + ecma_number_t multiply = (ecma_number_t) left_integer * (ecma_number_t) right_integer; + *stack_top_p++ = ecma_make_number_value (multiply); + continue; + } + + if (ecma_is_value_float_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t new_value = + (ecma_get_float_from_value (left_value) * ecma_get_number_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (left_value, new_value); + ecma_free_number (right_value); + continue; + } + + if (ecma_is_value_float_number (right_value) && ecma_is_value_integer_number (left_value)) + { + ecma_number_t new_value = + ((ecma_number_t) ecma_get_integer_from_value (left_value) * ecma_get_float_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (right_value, new_value); + continue; + } + + result = do_number_arithmetic (NUMBER_ARITHMETIC_MULTIPLICATION, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_DIV: + { + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + result = do_number_arithmetic (NUMBER_ARITHMETIC_DIVISION, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_MOD: + { + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + + if (right_integer != 0) + { + ecma_integer_value_t mod_result = left_integer % right_integer; + + if (mod_result != 0 || left_integer >= 0) + { + *stack_top_p++ = ecma_make_integer_value (mod_result); + continue; + } + } + } + + result = do_number_arithmetic (NUMBER_ARITHMETIC_REMAINDER, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_EXP: + { + result = do_number_arithmetic (NUMBER_ARITHMETIC_EXPONENTIATION, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_EQUAL: + { + result = opfunc_equality (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_NOT_EQUAL: + { + result = opfunc_equality (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = ecma_invert_boolean_value (result); + goto free_both_values; + } + case VM_OC_STRICT_EQUAL: + { + bool is_equal = ecma_op_strict_equality_compare (left_value, right_value); + + result = ecma_make_boolean_value (is_equal); + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_STRICT_NOT_EQUAL: + { + bool is_equal = ecma_op_strict_equality_compare (left_value, right_value); + + result = ecma_make_boolean_value (!is_equal); + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_BIT_OR: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + *stack_top_p++ = left_value | right_value; + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_LOGIC_OR, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_BIT_XOR: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + *stack_top_p++ = left_value ^ right_value; + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_LOGIC_XOR, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_BIT_AND: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + *stack_top_p++ = left_value & right_value; + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_LOGIC_AND, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_LEFT_SHIFT: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + + *stack_top_p++ = ecma_make_int32_value ((int32_t) ((uint32_t) left_integer << (right_integer & 0x1f))); + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_SHIFT_LEFT, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_RIGHT_SHIFT: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + *stack_top_p++ = ecma_make_integer_value (left_integer >> (right_integer & 0x1f)); + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_SHIFT_RIGHT, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_UNS_RIGHT_SHIFT: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + uint32_t left_uint32 = (uint32_t) ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + *stack_top_p++ = ecma_make_uint32_value (left_uint32 >> (right_integer & 0x1f)); + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_SHIFT_URIGHT, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_LESS: + { + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + bool is_less = (ecma_integer_value_t) left_value < (ecma_integer_value_t) right_value; +#if !JERRY_VM_HALT + /* This is a lookahead to the next opcode to improve performance. + * If it is CBC_BRANCH_IF_TRUE_BACKWARD, execute it. */ + if (*byte_code_p <= CBC_BRANCH_IF_TRUE_BACKWARD_3 && *byte_code_p >= CBC_BRANCH_IF_TRUE_BACKWARD) + { + byte_code_start_p = byte_code_p++; + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (*byte_code_start_p); + JERRY_ASSERT (branch_offset_length >= 1 && branch_offset_length <= 3); + + if (is_less) + { + branch_offset = *(byte_code_p++); + + if (JERRY_UNLIKELY (branch_offset_length != 1)) + { + branch_offset <<= 8; + branch_offset |= *(byte_code_p++); + if (JERRY_UNLIKELY (branch_offset_length == 3)) + { + branch_offset <<= 8; + branch_offset |= *(byte_code_p++); + } + } + + /* Note: The opcode is a backward branch. */ + byte_code_p = byte_code_start_p - branch_offset; + } + else + { + byte_code_p += branch_offset_length; + } + + continue; + } +#endif /* !JERRY_VM_HALT */ + *stack_top_p++ = ecma_make_boolean_value (is_less); + continue; + } + + if (ecma_is_value_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t left_number = ecma_get_number_from_value (left_value); + ecma_number_t right_number = ecma_get_number_from_value (right_value); + + *stack_top_p++ = ecma_make_boolean_value (left_number < right_number); + goto free_both_values; + } + + result = opfunc_relation (left_value, right_value, true, false); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_GREATER: + { + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value; + ecma_integer_value_t right_integer = (ecma_integer_value_t) right_value; + + *stack_top_p++ = ecma_make_boolean_value (left_integer > right_integer); + continue; + } + + if (ecma_is_value_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t left_number = ecma_get_number_from_value (left_value); + ecma_number_t right_number = ecma_get_number_from_value (right_value); + + *stack_top_p++ = ecma_make_boolean_value (left_number > right_number); + goto free_both_values; + } + + result = opfunc_relation (left_value, right_value, false, false); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_LESS_EQUAL: + { + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value; + ecma_integer_value_t right_integer = (ecma_integer_value_t) right_value; + + *stack_top_p++ = ecma_make_boolean_value (left_integer <= right_integer); + continue; + } + + if (ecma_is_value_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t left_number = ecma_get_number_from_value (left_value); + ecma_number_t right_number = ecma_get_number_from_value (right_value); + + *stack_top_p++ = ecma_make_boolean_value (left_number <= right_number); + goto free_both_values; + } + + result = opfunc_relation (left_value, right_value, false, true); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_GREATER_EQUAL: + { + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value; + ecma_integer_value_t right_integer = (ecma_integer_value_t) right_value; + + *stack_top_p++ = ecma_make_boolean_value (left_integer >= right_integer); + continue; + } + + if (ecma_is_value_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t left_number = ecma_get_number_from_value (left_value); + ecma_number_t right_number = ecma_get_number_from_value (right_value); + + *stack_top_p++ = ecma_make_boolean_value (left_number >= right_number); + goto free_both_values; + } + + result = opfunc_relation (left_value, right_value, true, true); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_IN: + { + result = opfunc_in (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_INSTANCEOF: + { + result = opfunc_instanceof (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_BLOCK_CREATE_CONTEXT: + { + ecma_value_t *stack_context_top_p; + stack_context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + + JERRY_ASSERT (stack_context_top_p == stack_top_p || stack_context_top_p == stack_top_p - 1); + + if (byte_code_start_p[0] != CBC_EXT_OPCODE) + { + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + if (stack_context_top_p != stack_top_p) + { + /* Preserve the value of switch statement. */ + stack_context_top_p[1] = stack_context_top_p[0]; + } + + stack_context_top_p[0] = VM_CREATE_CONTEXT_WITH_ENV (VM_CONTEXT_BLOCK, branch_offset); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_BLOCK_CONTEXT_STACK_ALLOCATION; + } + else + { + JERRY_ASSERT (byte_code_start_p[1] == CBC_EXT_TRY_CREATE_ENV); + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_TRY + || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_CATCH + || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP + || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_THROW + || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_RETURN); + + JERRY_ASSERT (!(stack_context_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)); + + stack_context_top_p[-1] |= VM_CONTEXT_HAS_LEX_ENV; + } + + frame_ctx_p->lex_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p); + frame_ctx_p->lex_env_p->type_flags_refs |= ECMA_OBJECT_FLAG_BLOCK; + + continue; + } + case VM_OC_WITH: + { + ecma_value_t value = *(--stack_top_p); + ecma_object_t *object_p; + ecma_object_t *with_env_p; + + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + result = ecma_op_to_object (value); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + object_p = ecma_get_object_from_value (result); + + with_env_p = ecma_create_object_lex_env (frame_ctx_p->lex_env_p, object_p); + ecma_deref_object (object_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_WITH_CONTEXT_STACK_ALLOCATION; + + stack_top_p[-1] = VM_CREATE_CONTEXT_WITH_ENV (VM_CONTEXT_WITH, branch_offset); + + with_env_p->type_flags_refs |= ECMA_OBJECT_FLAG_BLOCK; + frame_ctx_p->lex_env_p = with_env_p; + continue; + } + case VM_OC_FOR_IN_INIT: + { + ecma_value_t value = *(--stack_top_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + ecma_value_t expr_obj_value = ECMA_VALUE_UNDEFINED; + ecma_collection_t *prop_names_p = opfunc_for_in (value, &expr_obj_value); + ecma_free_value (value); + + if (prop_names_p == NULL) + { + if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (expr_obj_value))) + { + result = expr_obj_value; + goto error; + } + + /* The collection is already released */ + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION; + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FOR_IN, branch_offset); + ECMA_SET_INTERNAL_VALUE_ANY_POINTER (stack_top_p[-2], prop_names_p); + stack_top_p[-3] = 0; + stack_top_p[-4] = expr_obj_value; + + if (byte_code_p[0] == CBC_EXT_OPCODE && byte_code_p[1] == CBC_EXT_CLONE_CONTEXT) + { + /* No need to duplicate the first context. */ + byte_code_p += 2; + } + + continue; + } + case VM_OC_FOR_IN_GET_NEXT: + { + ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + + ecma_collection_t *collection_p; + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, context_top_p[-2]); + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_IN); + + uint32_t index = context_top_p[-3]; + ecma_value_t *buffer_p = collection_p->buffer_p; + + *stack_top_p++ = buffer_p[index]; + context_top_p[-3]++; + continue; + } + case VM_OC_FOR_IN_HAS_NEXT: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + ecma_collection_t *collection_p; + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, stack_top_p[-2]); + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FOR_IN); + + ecma_value_t *buffer_p = collection_p->buffer_p; + ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[-4]); + uint32_t index = stack_top_p[-3]; + + while (index < collection_p->item_count) + { + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (buffer_p[index]); + + result = ecma_op_object_has_property (object_p, prop_name_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + stack_top_p[-3] = index; + goto error; + } + + if (JERRY_LIKELY (ecma_is_value_true (result))) + { + byte_code_p = byte_code_start_p + branch_offset; + break; + } + + ecma_deref_ecma_string (prop_name_p); + index++; + } + + if (index == collection_p->item_count) + { + ecma_deref_object (object_p); + ecma_collection_destroy (collection_p); + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION; + } + else + { + stack_top_p[-3] = index; + } + continue; + } + case VM_OC_FOR_OF_INIT: + { + ecma_value_t value = *(--stack_top_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (value, ECMA_VALUE_SYNC_ITERATOR, &next_method); + + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (iterator)) + { + result = iterator; + goto error; + } + + result = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_free_value (iterator); + ecma_free_value (next_method); + goto error; + } + + if (ecma_is_value_false (result)) + { + ecma_free_value (iterator); + ecma_free_value (next_method); + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + + ecma_value_t next_value = ecma_op_iterator_value (result); + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + result = next_value; + ecma_free_value (iterator); + ecma_free_value (next_method); + goto error; + } + + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION; + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FOR_OF, branch_offset) | VM_CONTEXT_CLOSE_ITERATOR; + stack_top_p[-2] = next_value; + stack_top_p[-3] = iterator; + stack_top_p[-4] = next_method; + + if (byte_code_p[0] == CBC_EXT_OPCODE && byte_code_p[1] == CBC_EXT_CLONE_CONTEXT) + { + /* No need to duplicate the first context. */ + byte_code_p += 2; + } + continue; + } + case VM_OC_FOR_OF_GET_NEXT: + { + ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_OF + || VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_AWAIT_OF); + JERRY_ASSERT (context_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR); + + *stack_top_p++ = context_top_p[-2]; + context_top_p[-2] = ECMA_VALUE_UNDEFINED; + continue; + } + case VM_OC_FOR_OF_HAS_NEXT: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FOR_OF); + JERRY_ASSERT (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR); + + stack_top_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + result = ecma_op_iterator_step (stack_top_p[-3], stack_top_p[-4]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + if (ecma_is_value_false (result)) + { + ecma_free_value (stack_top_p[-2]); + ecma_free_value (stack_top_p[-3]); + ecma_free_value (stack_top_p[-4]); + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION; + continue; + } + + ecma_value_t next_value = ecma_op_iterator_value (result); + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + result = next_value; + goto error; + } + + JERRY_ASSERT (stack_top_p[-2] == ECMA_VALUE_UNDEFINED); + stack_top_p[-1] |= VM_CONTEXT_CLOSE_ITERATOR; + stack_top_p[-2] = next_value; + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + case VM_OC_FOR_AWAIT_OF_INIT: + { + ecma_value_t value = *(--stack_top_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + ecma_value_t next_method; + result = ecma_op_get_iterator (value, ECMA_VALUE_ASYNC_ITERATOR, &next_method); + + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_value_t iterator = result; + result = ecma_op_iterator_next (result, next_method, ECMA_VALUE_EMPTY); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_free_value (iterator); + ecma_free_value (next_method); + goto error; + } + + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION; + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FOR_AWAIT_OF, branch_offset); + stack_top_p[-2] = ECMA_VALUE_UNDEFINED; + stack_top_p[-3] = iterator; + stack_top_p[-4] = next_method; + + if (byte_code_p[0] == CBC_EXT_OPCODE && byte_code_p[1] == CBC_EXT_CLONE_CONTEXT) + { + /* No need to duplicate the first context. */ + byte_code_p += 2; + } + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + + uint16_t extra_flags = + (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD | (ECMA_AWAIT_FOR_NEXT << ECMA_AWAIT_STATE_SHIFT)); + + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR + || (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_EXECUTABLE)) + { + ecma_extended_object_t *executable_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + result = ecma_promise_async_await (executable_object_p, result); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + executable_object_p->u.cls.u2.executable_obj_flags |= extra_flags; + return ECMA_VALUE_UNDEFINED; + } + + result = opfunc_async_create_and_await (frame_ctx_p, result, extra_flags); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + return result; + } + case VM_OC_FOR_AWAIT_OF_HAS_NEXT: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FOR_AWAIT_OF); + JERRY_ASSERT (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR); + + stack_top_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + result = ecma_op_iterator_next (stack_top_p[-3], stack_top_p[-4], ECMA_VALUE_EMPTY); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_extended_object_t *executable_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + result = ecma_promise_async_await (executable_object_p, result); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + uint16_t extra_flags = + (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD | (ECMA_AWAIT_FOR_NEXT << ECMA_AWAIT_STATE_SHIFT)); + executable_object_p->u.cls.u2.executable_obj_flags |= extra_flags; + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_start_p + branch_offset; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_TRY: + { + /* Try opcode simply creates the try context. */ + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_TRY_CONTEXT_STACK_ALLOCATION; + + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_TRY, branch_offset); + continue; + } + case VM_OC_CATCH: + { + /* Catches are ignored and turned to jumps. */ + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY); + + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + case VM_OC_FINALLY: + { + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY + || VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH); + + if (stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV) + { + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + ecma_deref_object (lex_env_p); + } + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION); + stack_top_p += PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION; + + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FINALLY_JUMP, branch_offset); + stack_top_p[-2] = (ecma_value_t) branch_offset; + continue; + } + case VM_OC_CONTEXT_END: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (!(stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR)); + + ecma_value_t context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]); + + if (!VM_CONTEXT_IS_FINALLY (context_type)) + { + stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + continue; + } + + if (stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV) + { + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + ecma_deref_object (lex_env_p); + } + + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_FINALLY_CONTEXT_STACK_ALLOCATION; + + if (context_type == VM_CONTEXT_FINALLY_RETURN) + { + result = *stack_top_p; + goto error; + } + + if (context_type == VM_CONTEXT_FINALLY_THROW) + { + jcontext_raise_exception (*stack_top_p); +#if JERRY_VM_THROW + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_ERROR_THROWN; +#endif /* JERRY_VM_THROW */ + result = ECMA_VALUE_ERROR; + goto error; + } + + JERRY_ASSERT (context_type == VM_CONTEXT_FINALLY_JUMP); + + uint32_t jump_target = *stack_top_p; + + vm_stack_found_type type = + vm_stack_find_finally (frame_ctx_p, stack_top_p, VM_CONTEXT_FINALLY_JUMP, jump_target); + stack_top_p = frame_ctx_p->stack_top_p; + switch (type) + { + case VM_CONTEXT_FOUND_FINALLY: + { + byte_code_p = frame_ctx_p->byte_code_p; + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP); + stack_top_p[-2] = jump_target; + break; + } + case VM_CONTEXT_FOUND_ERROR: + { + JERRY_ASSERT (jcontext_has_pending_exception ()); + result = ECMA_VALUE_ERROR; + goto error; + } + case VM_CONTEXT_FOUND_AWAIT: + { + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP); + stack_top_p[-2] = jump_target; + return ECMA_VALUE_UNDEFINED; + } + default: + { + byte_code_p = frame_ctx_p->byte_code_start_p + jump_target; + break; + } + } + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + continue; + } + case VM_OC_JUMP_AND_EXIT_CONTEXT: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (!jcontext_has_pending_exception ()); + + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + vm_stack_found_type type = + vm_stack_find_finally (frame_ctx_p, stack_top_p, VM_CONTEXT_FINALLY_JUMP, (uint32_t) branch_offset); + stack_top_p = frame_ctx_p->stack_top_p; + switch (type) + { + case VM_CONTEXT_FOUND_FINALLY: + { + byte_code_p = frame_ctx_p->byte_code_p; + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP); + stack_top_p[-2] = (uint32_t) branch_offset; + break; + } + case VM_CONTEXT_FOUND_ERROR: + { + JERRY_ASSERT (jcontext_has_pending_exception ()); + result = ECMA_VALUE_ERROR; + goto error; + } + case VM_CONTEXT_FOUND_AWAIT: + { + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP); + stack_top_p[-2] = (uint32_t) branch_offset; + return ECMA_VALUE_UNDEFINED; + } + default: + { + byte_code_p = frame_ctx_p->byte_code_start_p + branch_offset; + break; + } + } + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + continue; + } +#if JERRY_MODULE_SYSTEM + case VM_OC_MODULE_IMPORT: + { + left_value = *(--stack_top_p); + + ecma_value_t user_value = ECMA_VALUE_UNDEFINED; + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_header_p)->script_value; + +#if JERRY_SNAPSHOT_EXEC + if (JERRY_UNLIKELY (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))) + { +#endif /* JERRY_SNAPSHOT_EXEC */ + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (script_p->refs_and_type & CBC_SCRIPT_HAS_USER_VALUE) + { + user_value = CBC_SCRIPT_GET_USER_VALUE (script_p); + } +#if JERRY_SNAPSHOT_EXEC + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + result = ecma_module_import (left_value, user_value); + ecma_free_value (left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + continue; + } + case VM_OC_MODULE_IMPORT_META: + { + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_header_p)->script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + JERRY_ASSERT (script_p->refs_and_type & CBC_SCRIPT_HAS_IMPORT_META); + + ecma_value_t import_meta = CBC_SCRIPT_GET_IMPORT_META (script_p, script_p->refs_and_type); + ecma_object_t *import_meta_object_p = ecma_get_object_from_value (import_meta); + + if (ecma_get_object_type (import_meta_object_p) != ECMA_OBJECT_TYPE_GENERAL) + { + JERRY_ASSERT (ecma_object_class_is (import_meta_object_p, ECMA_OBJECT_CLASS_MODULE)); + + ecma_value_t module = import_meta; + import_meta_object_p = ecma_create_object (NULL, 0, ECMA_OBJECT_TYPE_GENERAL); + import_meta = ecma_make_object_value (import_meta_object_p); + + if (JERRY_CONTEXT (module_import_meta_callback_p) != NULL) + { + void *user_p = JERRY_CONTEXT (module_import_meta_callback_user_p); + JERRY_CONTEXT (module_import_meta_callback_p) (module, import_meta, user_p); + } + + CBC_SCRIPT_GET_IMPORT_META (script_p, script_p->refs_and_type) = import_meta; + } + else + { + ecma_ref_object (import_meta_object_p); + } + + *stack_top_p++ = import_meta; + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + case VM_OC_NONE: + default: + { + JERRY_ASSERT (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_NONE); + + jerry_fatal (JERRY_FATAL_DISABLED_BYTE_CODE); + } + } + + JERRY_ASSERT (VM_OC_HAS_PUT_RESULT (opcode_data)); + + if (opcode_data & VM_OC_PUT_IDENT) + { + uint16_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + if (literal_index < register_end) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + VM_GET_REGISTER (frame_ctx_p, literal_index) = result; + + if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)) + { + result = ecma_fast_copy_value (result); + } + } + else + { + ecma_string_t *var_name_str_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + ecma_value_t put_value_result = + ecma_op_put_value_lex_env_base (frame_ctx_p->lex_env_p, var_name_str_p, is_strict, result); + + if (ECMA_IS_VALUE_ERROR (put_value_result)) + { + ecma_free_value (result); + result = put_value_result; + goto error; + } + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + ecma_fast_free_value (result); + } + } + } + else if (opcode_data & VM_OC_PUT_REFERENCE) + { + ecma_value_t property = *(--stack_top_p); + ecma_value_t base = *(--stack_top_p); + + if (base == ECMA_VALUE_REGISTER_REF) + { + property = (ecma_value_t) ecma_get_integer_from_value (property); + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, property)); + VM_GET_REGISTER (frame_ctx_p, property) = result; + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + goto free_both_values; + } + result = ecma_fast_copy_value (result); + } + else + { + ecma_value_t set_value_result = vm_op_set_value (base, property, result, is_strict); + + if (ECMA_IS_VALUE_ERROR (set_value_result)) + { + ecma_free_value (result); + result = set_value_result; + goto error; + } + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + ecma_fast_free_value (result); + goto free_both_values; + } + } + } + + if (opcode_data & VM_OC_PUT_STACK) + { + *stack_top_p++ = result; + } + else if (opcode_data & VM_OC_PUT_BLOCK) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = result; + } + +free_both_values: + ecma_fast_free_value (right_value); +free_left_value: + ecma_fast_free_value (left_value); + } + +error: + ecma_fast_free_value (left_value); + ecma_fast_free_value (right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + JERRY_ASSERT (jcontext_has_pending_exception ()); + ecma_value_t *stack_bottom_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + + while (stack_top_p > stack_bottom_p) + { + ecma_value_t stack_item = *(--stack_top_p); + if (stack_item == ECMA_VALUE_RELEASE_LEX_ENV) + { + opfunc_pop_lexical_environment (frame_ctx_p); + continue; + } + + ecma_fast_free_value (stack_item); + } + +#if JERRY_VM_THROW + if (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_ERROR_THROWN)) + { + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_ERROR_THROWN; + + jerry_throw_cb_t vm_throw_callback_p = JERRY_CONTEXT (vm_throw_callback_p); + + if (vm_throw_callback_p != NULL) + { + vm_throw_callback_p (JERRY_CONTEXT (error_value), JERRY_CONTEXT (vm_throw_callback_user_p)); + } + } +#endif /* JERRY_VM_THROW */ + } + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + if (frame_ctx_p->context_depth == 0) + { + /* In most cases there is no context. */ + frame_ctx_p->call_operation = VM_NO_EXEC_OP; + return result; + } + + if (!ECMA_IS_VALUE_ERROR (result)) + { + switch (vm_stack_find_finally (frame_ctx_p, stack_top_p, VM_CONTEXT_FINALLY_RETURN, 0)) + { + case VM_CONTEXT_FOUND_FINALLY: + { + stack_top_p = frame_ctx_p->stack_top_p; + byte_code_p = frame_ctx_p->byte_code_p; + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_RETURN); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + stack_top_p[-2] = result; + continue; + } + case VM_CONTEXT_FOUND_ERROR: + { + JERRY_ASSERT (jcontext_has_pending_exception ()); + + ecma_free_value (result); + stack_top_p = frame_ctx_p->stack_top_p; + result = ECMA_VALUE_ERROR; + break; + } + case VM_CONTEXT_FOUND_AWAIT: + { + stack_top_p = frame_ctx_p->stack_top_p; + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_RETURN); + stack_top_p[-2] = result; + return ECMA_VALUE_UNDEFINED; + } + default: + { + goto finish; + } + } + } + + JERRY_ASSERT (jcontext_has_pending_exception ()); + + if (!jcontext_has_pending_abort ()) + { + switch (vm_stack_find_finally (frame_ctx_p, stack_top_p, VM_CONTEXT_FINALLY_THROW, 0)) + { + case VM_CONTEXT_FOUND_FINALLY: + { + stack_top_p = frame_ctx_p->stack_top_p; + byte_code_p = frame_ctx_p->byte_code_p; + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (!(stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)); + + result = jcontext_take_exception (); + + if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_THROW) + { + stack_top_p[-2] = result; + continue; + } + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH); + + *stack_top_p++ = result; + continue; + } + case VM_CONTEXT_FOUND_AWAIT: + { + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (frame_ctx_p->stack_top_p[-1]) == VM_CONTEXT_FINALLY_THROW); + return ECMA_VALUE_UNDEFINED; + } + default: + { + break; + } + } + } + else + { + do + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); + } while (frame_ctx_p->context_depth > 0); + } + +finish: + frame_ctx_p->call_operation = VM_NO_EXEC_OP; + return result; + } +} /* vm_loop */ + +#if JERRY_MODULE_SYSTEM + +/** + * Create and initialize module scope with all data properties + * + * @return ECMA_VALUE_EMPTY on success, + * ECMA_VALUE_ERROR on failure + */ +ecma_value_t +vm_init_module_scope (ecma_module_t *module_p) /**< module without scope */ +{ + ecma_object_t *global_object_p; +#if JERRY_BUILTIN_REALMS + global_object_p = (ecma_object_t *) ecma_op_function_get_realm (module_p->u.compiled_code_p); +#else /* !JERRY_BUILTIN_REALMS */ + global_object_p = ecma_builtin_get_global (); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *scope_p = ecma_create_lex_env_class (ecma_get_global_environment (global_object_p), + sizeof (ecma_lexical_environment_class_t)); + const ecma_compiled_code_t *compiled_code_p = module_p->u.compiled_code_p; + ecma_value_t *literal_start_p; + uint8_t *byte_code_p; + uint16_t encoding_limit; + uint16_t encoding_delta; + + ((ecma_lexical_environment_class_t *) scope_p)->object_p = (ecma_object_t *) module_p; + ((ecma_lexical_environment_class_t *) scope_p)->type = ECMA_LEX_ENV_CLASS_TYPE_MODULE; + + module_p->scope_p = scope_p; + ecma_deref_object (scope_p); + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p; + + literal_start_p = (ecma_value_t *) (args_p + 1); + literal_start_p -= args_p->register_end; + byte_code_p = (uint8_t *) (literal_start_p + args_p->literal_end); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p; + + literal_start_p = (ecma_value_t *) (args_p + 1); + literal_start_p -= args_p->register_end; + byte_code_p = (uint8_t *) (literal_start_p + args_p->literal_end); + } + + /* Prepare for byte code execution. */ + if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) + { + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + else + { + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + + JERRY_ASSERT (*byte_code_p >= CBC_JUMP_FORWARD && *byte_code_p <= CBC_JUMP_FORWARD_3); + + byte_code_p += 1 + CBC_BRANCH_OFFSET_LENGTH (*byte_code_p); + + while (true) + { + uint8_t opcode = *byte_code_p++; + + switch (opcode) + { + case CBC_CREATE_VAR: + case CBC_CREATE_LET: + case CBC_CREATE_CONST: + { + uint32_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_find_named_property (scope_p, name_p) == NULL); + + uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; + + if (opcode == CBC_CREATE_LET) + { + prop_attributes = ECMA_PROPERTY_ENUMERABLE_WRITABLE; + } + else if (opcode == CBC_CREATE_CONST) + { + prop_attributes = ECMA_PROPERTY_FLAG_ENUMERABLE; + } + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (scope_p, name_p, prop_attributes, NULL); + + if (opcode != CBC_CREATE_VAR) + { + property_value_p->value = ECMA_VALUE_UNINITIALIZED; + } + break; + } + case CBC_INIT_ARG_OR_FUNC: + { + uint32_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + ecma_compiled_code_t *function_bytecode_p; +#if JERRY_SNAPSHOT_EXEC + if (JERRY_LIKELY (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))) + { +#endif /* JERRY_SNAPSHOT_EXEC */ + function_bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, literal_start_p[literal_index]); +#if JERRY_SNAPSHOT_EXEC + } + else + { + uint8_t *byte_p = ((uint8_t *) compiled_code_p) + literal_start_p[literal_index]; + function_bytecode_p = (ecma_compiled_code_t *) byte_p; + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + JERRY_ASSERT (CBC_IS_FUNCTION (function_bytecode_p->status_flags)); + + ecma_object_t *function_obj_p; + + if (JERRY_UNLIKELY (CBC_FUNCTION_IS_ARROW (function_bytecode_p->status_flags))) + { + function_obj_p = ecma_op_create_arrow_function_object (scope_p, function_bytecode_p, ECMA_VALUE_UNDEFINED); + } + else + { + function_obj_p = ecma_op_create_any_function_object (scope_p, function_bytecode_p); + } + + READ_LITERAL_INDEX (literal_index); + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_find_named_property (scope_p, name_p) == NULL); + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (scope_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + + JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED); + property_value_p->value = ecma_make_object_value (function_obj_p); + ecma_deref_object (function_obj_p); + break; + } + default: + { + JERRY_ASSERT (opcode == CBC_RETURN_FUNCTION_END); + return ECMA_VALUE_EMPTY; + } + } + } +} /* vm_init_module_scope */ + +#endif /* JERRY_MODULE_SYSTEM */ + +#undef READ_LITERAL +#undef READ_LITERAL_INDEX + +JERRY_STATIC_ASSERT (((int)VM_FRAME_CTX_SHARED_DIRECT_EVAL == (int)VM_FRAME_CTX_DIRECT_EVAL), + vm_frame_ctx_shared_direct_eval_must_be_equal_to_frame_ctx_direct_eval); + +JERRY_STATIC_ASSERT (((int)CBC_CODE_FLAGS_STRICT_MODE == (int)VM_FRAME_CTX_IS_STRICT), + cbc_code_flags_strict_mode_must_be_equal_to_vm_frame_ctx_is_strict); + +/** + * Initialize code block execution + * + * @return ECMA_VALUE_ERROR - if the initialization fails + * ECMA_VALUE_EMPTY - otherwise + */ +static void JERRY_ATTR_NOINLINE +vm_init_exec (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + vm_frame_ctx_shared_t *shared_p = frame_ctx_p->shared_p; + const ecma_compiled_code_t *bytecode_header_p = shared_p->bytecode_header_p; + + frame_ctx_p->prev_context_p = JERRY_CONTEXT (vm_top_context_p); + frame_ctx_p->context_depth = 0; + frame_ctx_p->status_flags = (uint8_t) ((shared_p->status_flags & VM_FRAME_CTX_DIRECT_EVAL) + | (bytecode_header_p->status_flags & VM_FRAME_CTX_IS_STRICT)); + + uint16_t argument_end, register_end; + ecma_value_t *literal_p; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + + argument_end = args_p->argument_end; + register_end = args_p->register_end; + + literal_p = (ecma_value_t *) (args_p + 1); + literal_p -= register_end; + frame_ctx_p->literal_start_p = literal_p; + literal_p += args_p->literal_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + + argument_end = args_p->argument_end; + register_end = args_p->register_end; + + literal_p = (ecma_value_t *) (args_p + 1); + literal_p -= register_end; + frame_ctx_p->literal_start_p = literal_p; + literal_p += args_p->literal_end; + } + + frame_ctx_p->byte_code_p = (uint8_t *) literal_p; + frame_ctx_p->byte_code_start_p = (uint8_t *) literal_p; + frame_ctx_p->stack_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end; + + uint32_t arg_list_len = 0; + + if (argument_end > 0) + { + JERRY_ASSERT (shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_ARG_LIST); + + const ecma_value_t *arg_list_p = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_p; + arg_list_len = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_len; + + if (arg_list_len > argument_end) + { + arg_list_len = argument_end; + } + + for (uint32_t i = 0; i < arg_list_len; i++) + { + VM_GET_REGISTER (frame_ctx_p, i) = ecma_fast_copy_value (arg_list_p[i]); + } + } + + /* The arg_list_len contains the end of the copied arguments. + * Fill everything else with undefined. */ + if (register_end > arg_list_len) + { + ecma_value_t *stack_p = VM_GET_REGISTERS (frame_ctx_p) + arg_list_len; + + for (uint32_t i = arg_list_len; i < register_end; i++) + { + *stack_p++ = ECMA_VALUE_UNDEFINED; + } + } + + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; + JERRY_CONTEXT (vm_top_context_p) = frame_ctx_p; +} /* vm_init_exec */ + +/** + * Resume execution of a code block. + * + * @return ecma value + */ +ecma_value_t JERRY_ATTR_NOINLINE +vm_execute (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + while (true) + { + ecma_value_t completion_value = vm_loop (frame_ctx_p); + + switch (frame_ctx_p->call_operation) + { + case VM_EXEC_CALL: + { + opfunc_call (frame_ctx_p); + break; + } + case VM_EXEC_SUPER_CALL: + { + vm_super_call (frame_ctx_p); + break; + } + case VM_EXEC_SPREAD_OP: + { + vm_spread_operation (frame_ctx_p); + break; + } + case VM_EXEC_RETURN: + { + return completion_value; + } + case VM_EXEC_CONSTRUCT: + { + opfunc_construct (frame_ctx_p); + break; + } + default: + { + JERRY_ASSERT (frame_ctx_p->call_operation == VM_NO_EXEC_OP); + + const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->shared_p->bytecode_header_p; + uint32_t register_end; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + register_end = ((cbc_uint16_arguments_t *) bytecode_header_p)->register_end; + } + else + { + register_end = ((cbc_uint8_arguments_t *) bytecode_header_p)->register_end; + } + + /* Free arguments and registers */ + ecma_value_t *registers_p = VM_GET_REGISTERS (frame_ctx_p); + for (uint32_t i = 0; i < register_end; i++) + { + ecma_fast_free_value (registers_p[i]); + } + JERRY_CONTEXT (vm_top_context_p) = frame_ctx_p->prev_context_p; + return completion_value; + } + } + } +} /* vm_execute */ + +/** + * Run the code. + * + * @return ecma value + */ +ecma_value_t +vm_run (vm_frame_ctx_shared_t *shared_p, /**< shared data */ + ecma_value_t this_binding_value, /**< value of 'ThisBinding' */ + ecma_object_t *lex_env_p) /**< lexical environment to use */ +{ + const ecma_compiled_code_t *bytecode_header_p = shared_p->bytecode_header_p; + vm_frame_ctx_t *frame_ctx_p; + size_t frame_size; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + frame_size = (size_t) (args_p->register_end + args_p->stack_limit); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + frame_size = (size_t) (args_p->register_end + args_p->stack_limit); + } + + JERRY_VLA (ecma_value_t, stack, frame_size + (sizeof (vm_frame_ctx_t) / sizeof (ecma_value_t))); + + frame_ctx_p = (vm_frame_ctx_t *) stack; + + frame_ctx_p->shared_p = shared_p; + frame_ctx_p->lex_env_p = lex_env_p; + frame_ctx_p->this_binding = this_binding_value; + + vm_init_exec (frame_ctx_p); + return vm_execute (frame_ctx_p); +} /* vm_run */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm.h b/src/loaders/lottie/jerryscript/jerry-core/vm/vm.h new file mode 100644 index 00000000..5384b071 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm.h @@ -0,0 +1,426 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VM_H +#define VM_H + +#include "ecma-globals.h" +#include "ecma-module.h" + +#include "jrt.h" +#include "vm-defines.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_executor Executor + * @{ + */ + +/** + * Each CBC opcode is transformed to three vm opcodes: + * + * - first opcode is a "get arguments" opcode which specifies + * the type (register, literal, stack, etc.) and number + * (from 0 to 2) of input arguments + * - second opcode is a "group" opcode which specifies + * the actual operation (add, increment, call, etc.) + * - third opcode is a "put result" opcode which specifies + * the destination where the result is stored (register, + * stack, etc.) + */ + +/** + * If VM_OC_GET_ARGS_INDEX(opcode) == VM_OC_GET_BRANCH, + * this flag signals that the branch is a backward branch. + */ +#define VM_OC_BACKWARD_BRANCH (1 << 15) + +/** + * Position of "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_SHIFT 8 + +/** + * Mask of "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_MASK 0x7 + +/** + * Generate the binary representation of a "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_CREATE_INDEX(V) (((V) &VM_OC_GET_ARGS_MASK) << VM_OC_GET_ARGS_SHIFT) + +/** + * Extract the "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_INDEX(O) ((O) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT)) + +/** + * Checks whether the result is stored somewhere. + */ +#define VM_OC_HAS_GET_ARGS(V) ((V) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT)) + +/** + * Argument getters that are part of the opcodes. + */ +typedef enum +{ + VM_OC_GET_NONE = VM_OC_GET_ARGS_CREATE_INDEX (0), /**< do nothing */ + VM_OC_GET_BRANCH = VM_OC_GET_ARGS_CREATE_INDEX (1), /**< branch argument */ + VM_OC_GET_STACK = VM_OC_GET_ARGS_CREATE_INDEX (2), /**< pop one element from the stack */ + VM_OC_GET_STACK_STACK = VM_OC_GET_ARGS_CREATE_INDEX (3), /**< pop two elements from the stack */ + + VM_OC_GET_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (4), /**< resolve literal */ + VM_OC_GET_LITERAL_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (5), /**< resolve two literals */ + VM_OC_GET_STACK_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (6), /**< pop one element from the stack + * and resolve a literal */ + VM_OC_GET_THIS_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (7), /**< get this and resolve a literal */ +} vm_oc_get_types; + +/** + * Mask of "group" opcode. + */ +#define VM_OC_GROUP_MASK 0xff + +/** + * Extract the "group" opcode. + */ +#define VM_OC_GROUP_GET_INDEX(O) ((O) &VM_OC_GROUP_MASK) + +/** + * Opcodes. + */ +typedef enum +{ + VM_OC_POP, /**< pop from stack */ + VM_OC_POP_BLOCK, /**< pop block */ + VM_OC_PUSH, /**< push one literal */ + VM_OC_PUSH_TWO, /**< push two literals */ + VM_OC_PUSH_THREE, /**< push three literals */ + VM_OC_PUSH_UNDEFINED, /**< push undefined value */ + VM_OC_PUSH_TRUE, /**< push true value */ + VM_OC_PUSH_FALSE, /**< push false value */ + VM_OC_PUSH_NULL, /**< push null value */ + VM_OC_PUSH_THIS, /**< push this */ + VM_OC_PUSH_0, /**< push number zero */ + VM_OC_PUSH_POS_BYTE, /**< push number between 1 and 256 */ + VM_OC_PUSH_NEG_BYTE, /**< push number between -1 and -256 */ + VM_OC_PUSH_LIT_0, /**< push literal and number zero */ + VM_OC_PUSH_LIT_POS_BYTE, /**< push literal and number between 1 and 256 */ + VM_OC_PUSH_LIT_NEG_BYTE, /**< push literal and number between -1 and -256 */ + VM_OC_PUSH_OBJECT, /**< push object */ + VM_OC_PUSH_NAMED_FUNC_EXPR, /**< push named function expression */ + VM_OC_SET_PROPERTY, /**< set property */ + + VM_OC_SET_GETTER, /**< set getter */ + VM_OC_SET_SETTER, /**< set setter */ + VM_OC_PUSH_ARRAY, /**< push array */ + VM_OC_PUSH_ELISON, /**< push elison */ + VM_OC_APPEND_ARRAY, /**< append array */ + VM_OC_IDENT_REFERENCE, /**< ident reference */ + VM_OC_PROP_REFERENCE, /**< prop reference */ + VM_OC_PROP_GET, /**< prop get */ + + /* These eight opcodes must be in this order. */ + VM_OC_PROP_PRE_INCR, /**< prefix increment of a property */ + VM_OC_PROP_PRE_DECR, /**< prop prefix decrement of a property */ + VM_OC_PROP_POST_INCR, /**< prop postfix increment of a property */ + VM_OC_PROP_POST_DECR, /**< prop postfix decrement of a property */ + VM_OC_PRE_INCR, /**< prefix increment */ + VM_OC_PRE_DECR, /**< prefix decrement */ + VM_OC_POST_INCR, /**< postfix increment */ + VM_OC_POST_DECR, /**< postfix decrement */ + + VM_OC_PROP_DELETE, /**< delete property */ + VM_OC_DELETE, /**< delete */ + + VM_OC_MOV_IDENT, /**< move identifier register reference */ + VM_OC_ASSIGN, /**< assign */ + VM_OC_ASSIGN_PROP, /**< assign property */ + VM_OC_ASSIGN_PROP_THIS, /**< assign prop this */ + + VM_OC_RETURN, /**< return */ + VM_OC_RETURN_FUNCTION_END, /**< return at the end of a function/script */ + VM_OC_THROW, /**< throw */ + VM_OC_THROW_REFERENCE_ERROR, /**< throw reference error */ + + VM_OC_EVAL, /**< eval */ + VM_OC_CALL, /**< call */ + VM_OC_NEW, /**< new */ + VM_OC_RESOLVE_BASE_FOR_CALL, /**< resolve base value before call */ + VM_OC_ERROR, /**< error while the vm_loop is suspended */ + + VM_OC_JUMP, /**< jump */ + VM_OC_BRANCH_IF_NULLISH, /** branch if undefined or null */ + VM_OC_POP_REFERENCE, /** prop identifier or property reference from the stack */ + VM_OC_BRANCH_IF_STRICT_EQUAL, /**< branch if strict equal */ + + /* These four opcodes must be in this order. */ + VM_OC_BRANCH_IF_TRUE, /**< branch if true */ + VM_OC_BRANCH_IF_FALSE, /**< branch if false */ + VM_OC_BRANCH_IF_LOGICAL_TRUE, /**< branch if logical true */ + VM_OC_BRANCH_IF_LOGICAL_FALSE, /**< branch if logical false */ + + VM_OC_PLUS, /**< unary plus */ + VM_OC_MINUS, /**< unary minus */ + VM_OC_NOT, /**< not */ + VM_OC_BIT_NOT, /**< bitwise not */ + VM_OC_VOID, /**< void */ + VM_OC_TYPEOF_IDENT, /**< typeof identifier */ + VM_OC_TYPEOF, /**< typeof */ + + VM_OC_ADD, /**< binary add */ + VM_OC_SUB, /**< binary sub */ + VM_OC_MUL, /**< mul */ + VM_OC_DIV, /**< div */ + VM_OC_MOD, /**< mod */ + VM_OC_EXP, /**< exponentiation */ + + VM_OC_EQUAL, /**< equal */ + VM_OC_NOT_EQUAL, /**< not equal */ + VM_OC_STRICT_EQUAL, /**< strict equal */ + VM_OC_STRICT_NOT_EQUAL, /**< strict not equal */ + VM_OC_LESS, /**< less */ + VM_OC_GREATER, /**< greater */ + VM_OC_LESS_EQUAL, /**< less equal */ + VM_OC_GREATER_EQUAL, /**< greater equal */ + VM_OC_IN, /**< in */ + VM_OC_INSTANCEOF, /**< instanceof */ + + VM_OC_BIT_OR, /**< bitwise or */ + VM_OC_BIT_XOR, /**< bitwise xor */ + VM_OC_BIT_AND, /**< bitwise and */ + VM_OC_LEFT_SHIFT, /**< left shift */ + VM_OC_RIGHT_SHIFT, /**< right shift */ + VM_OC_UNS_RIGHT_SHIFT, /**< unsigned right shift */ + + VM_OC_BLOCK_CREATE_CONTEXT, /**< create lexical environment for blocks enclosed in braces */ + VM_OC_WITH, /**< with */ + VM_OC_FOR_IN_INIT, /**< for-in init context */ + VM_OC_FOR_IN_GET_NEXT, /**< get next */ + VM_OC_FOR_IN_HAS_NEXT, /**< has next */ + + VM_OC_TRY, /**< try */ + VM_OC_CATCH, /**< catch */ + VM_OC_FINALLY, /**< finally */ + VM_OC_CONTEXT_END, /**< context end */ + VM_OC_JUMP_AND_EXIT_CONTEXT, /**< jump and exit context */ + + VM_OC_CREATE_BINDING, /**< create variables */ + VM_OC_CREATE_ARGUMENTS, /**< create arguments object */ + VM_OC_SET_BYTECODE_PTR, /**< setting bytecode pointer */ + VM_OC_VAR_EVAL, /**< variable and function evaluation */ + VM_OC_EXT_VAR_EVAL, /**< variable and function evaluation for + * functions with separate argument context */ + VM_OC_INIT_ARG_OR_FUNC, /**< create and init a function or argument binding */ + + VM_OC_CLASS_CALL_STATIC_BLOCK, /**< call the class static block */ + VM_OC_DEFINE_FIELD, /**< define class field */ + VM_OC_PRIVATE_PROP_REFERENCE, /**< reference to class private method */ + VM_OC_ASSIGN_PRIVATE, /**< assign to private field */ + VM_OC_PRIVATE_FIELD_ADD, /**< add private field */ + VM_OC_PRIVATE_PROP_GET, /**< get private field */ + VM_OC_PRIVATE_IN, /**< 'in' opcode handler for private identifiers */ + VM_OC_COLLECT_PRIVATE_PROPERTY, /**< collect private properties */ + VM_OC_CHECK_VAR, /**< check redeclared vars in the global scope */ + VM_OC_CHECK_LET, /**< check redeclared lets in the global scope */ + VM_OC_ASSIGN_LET_CONST, /**< assign values to let/const declarations */ + VM_OC_INIT_BINDING, /**< create and intialize a binding */ + VM_OC_THROW_CONST_ERROR, /**< throw invalid assignment to const variable error */ + VM_OC_COPY_TO_GLOBAL, /**< copy value to global lex env */ + VM_OC_COPY_FROM_ARG, /**< copy value from arg lex env */ + VM_OC_CLONE_CONTEXT, /**< clone lexical environment with let/const declarations */ + VM_OC_COPY_DATA_PROPERTIES, /**< copy data properties of an object */ + VM_OC_SET_COMPUTED_PROPERTY, /**< set computed property */ + + VM_OC_FOR_OF_INIT, /**< for-of init context */ + VM_OC_FOR_OF_GET_NEXT, /**< for-of get next */ + VM_OC_FOR_OF_HAS_NEXT, /**< for-of has next */ + VM_OC_FOR_AWAIT_OF_INIT, /**< for-await-of init context */ + VM_OC_FOR_AWAIT_OF_HAS_NEXT, /**< for-await-of has next */ + + VM_OC_LOCAL_EVAL, /**< eval in local context */ + VM_OC_SUPER_CALL, /**< call the 'super' constructor */ + VM_OC_PUSH_CLASS_ENVIRONMENT, /**< push class environment */ + VM_OC_PUSH_IMPLICIT_CTOR, /**< create implicit class constructor */ + VM_OC_INIT_CLASS, /**< initialize class */ + VM_OC_FINALIZE_CLASS, /**< finalize class */ + VM_OC_SET_FIELD_INIT, /**< store the class field initializer function */ + VM_OC_SET_STATIC_FIELD_INIT, /**< store the static class field initializer function */ + VM_OC_RUN_FIELD_INIT, /**< run the class field initializer function */ + VM_OC_RUN_STATIC_FIELD_INIT, /**< run the static class field initializer function */ + VM_OC_SET_NEXT_COMPUTED_FIELD, /**< set the next computed field of a class */ + VM_OC_PUSH_SUPER_CONSTRUCTOR, /**< getSuperConstructor operation */ + VM_OC_RESOLVE_LEXICAL_THIS, /**< resolve this_binding from from the lexical environment */ + VM_OC_SUPER_REFERENCE, /**< push super reference */ + VM_OC_SET_HOME_OBJECT, /**< set the [[HomeObject]] environment in an object literal */ + VM_OC_OBJECT_LITERAL_HOME_ENV, /**< create/destroy [[HomeObject]] environment of an object literal */ + VM_OC_SET_FUNCTION_NAME, /**< set function name property */ + + VM_OC_PUSH_SPREAD_ELEMENT, /**< push spread element */ + VM_OC_PUSH_REST_OBJECT, /**< push rest object */ + VM_OC_ITERATOR_CONTEXT_CREATE, /**< create iterator conext */ + VM_OC_ITERATOR_CONTEXT_END, /**< finalize iterator cotnext */ + VM_OC_ITERATOR_STEP, /**< IteratorStep abstract operation */ + VM_OC_OBJ_INIT_CONTEXT_CREATE, /**< create object initializer context */ + VM_OC_OBJ_INIT_CONTEXT_END, /**< finalize object initializer context */ + VM_OC_OBJ_INIT_PUSH_REST, /**< push the object with the rest properties */ + VM_OC_INITIALIZER_PUSH_NAME, /**< append string to name list array and push the string */ + VM_OC_DEFAULT_INITIALIZER, /**< default initializer inside a pattern */ + VM_OC_REST_INITIALIZER, /**< create rest object inside an array pattern */ + VM_OC_INITIALIZER_PUSH_PROP, /**< push property for object initializer */ + VM_OC_SPREAD_ARGUMENTS, /**< perform function call/construct with spreaded arguments */ + VM_OC_CREATE_GENERATOR, /**< create a generator object */ + VM_OC_YIELD, /**< yield operation */ + VM_OC_ASYNC_YIELD, /**< async yield operation */ + VM_OC_ASYNC_YIELD_ITERATOR, /**< async yield iterator operation */ + VM_OC_AWAIT, /**< await operation */ + VM_OC_GENERATOR_AWAIT, /**< generator await operation */ + VM_OC_EXT_RETURN, /**< return which also clears the stack */ + VM_OC_ASYNC_EXIT, /**< return from async function */ + VM_OC_STRING_CONCAT, /**< string concatenation */ + VM_OC_GET_TEMPLATE_OBJECT, /**< GetTemplateObject operation */ + VM_OC_PUSH_NEW_TARGET, /**< push new.target onto the stack */ + VM_OC_REQUIRE_OBJECT_COERCIBLE, /**< RequireObjectCoercible opretaion */ + VM_OC_ASSIGN_SUPER, /**< assign super reference */ + VM_OC_SET__PROTO__, /**< set prototype when __proto__: form is used */ + VM_OC_PUSH_STATIC_FIELD_FUNC, /**< push static field initializer function */ + VM_OC_ADD_COMPUTED_FIELD, /**< add computed field name */ +#if JERRY_MODULE_SYSTEM + VM_OC_MODULE_IMPORT, /**< module dynamic import */ + VM_OC_MODULE_IMPORT_META, /**< module import.meta */ +#endif /* JERRY_MODULE_SYSTEM */ + + VM_OC_NONE, /**< a special opcode for unsupported byte codes */ +} vm_oc_types; + +/** + * Unused opcodes, but required by byte-code types. + */ +typedef enum +{ +#if !JERRY_MODULE_SYSTEM + VM_OC_MODULE_IMPORT = VM_OC_NONE, /**< module dynamic import */ + VM_OC_MODULE_IMPORT_META = VM_OC_NONE, /**< module import.meta */ +#endif /* JERRY_MODULE_SYSTEM */ + + VM_OC_UNUSED = VM_OC_NONE /**< placeholder if the list is empty */ +} vm_oc_unused_types; + +/** + * Decrement operator. + */ +#define VM_OC_DECREMENT_OPERATOR_FLAG 0x1 + +/** + * Postfix increment/decrement operator. + */ +#define VM_OC_POST_INCR_DECR_OPERATOR_FLAG 0x2 + +/** + * An named variable is updated by the increment/decrement operator. + */ +#define VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG 0x4 + +/** + * Jump to target offset if input value is logical false. + */ +#define VM_OC_BRANCH_IF_FALSE_FLAG 0x1 + +/** + * Branch optimized for logical and/or opcodes. + */ +#define VM_OC_LOGICAL_BRANCH_FLAG 0x2 + +/** + * Bit index shift for non-static property initializers. + */ +#define VM_OC_NON_STATIC_SHIFT 15 + +/** + * This flag is set for static property initializers. + */ +#define VM_OC_NON_STATIC_FLAG (0x1 << VM_OC_NON_STATIC_SHIFT) + +/** + * Position of "put result" opcode. + */ +#define VM_OC_PUT_RESULT_SHIFT 11 + +/** + * Mask of "put result" opcode. + */ +#define VM_OC_PUT_RESULT_MASK 0xf + +/** + * Generate a "put result" opcode flag bit. + */ +#define VM_OC_PUT_RESULT_CREATE_FLAG(V) (((V) &VM_OC_PUT_RESULT_MASK) << VM_OC_PUT_RESULT_SHIFT) + +/** + * Checks whether the result is stored somewhere. + */ +#define VM_OC_HAS_PUT_RESULT(V) ((V) & (VM_OC_PUT_RESULT_MASK << VM_OC_PUT_RESULT_SHIFT)) + +/** + * Specify where the result is stored + */ +typedef enum +{ + VM_OC_PUT_IDENT = VM_OC_PUT_RESULT_CREATE_FLAG (0x1), + VM_OC_PUT_REFERENCE = VM_OC_PUT_RESULT_CREATE_FLAG (0x2), + VM_OC_PUT_STACK = VM_OC_PUT_RESULT_CREATE_FLAG (0x4), + VM_OC_PUT_BLOCK = VM_OC_PUT_RESULT_CREATE_FLAG (0x8), +} vm_oc_put_types; + +/** + * Non-recursive vm_loop: the vm_loop can be suspended + * to execute a call /construct operation. These return + * types of the vm_loop tells whether a call operation + * is in progress or the vm_loop is finished. + */ +typedef enum +{ + VM_NO_EXEC_OP, /**< do nothing */ + VM_EXEC_CALL, /**< invoke a function */ + VM_EXEC_SUPER_CALL, /**< invoke a function through 'super' keyword */ + VM_EXEC_SPREAD_OP, /**< call/construct operation with spreaded argument list */ + VM_EXEC_RETURN, /**< return with the completion value without freeing registers */ + VM_EXEC_CONSTRUCT, /**< construct a new object */ +} vm_call_operation; + +ecma_value_t vm_run_global (const ecma_compiled_code_t *bytecode_p, ecma_object_t *function_object_p); +ecma_value_t vm_run_eval (ecma_compiled_code_t *bytecode_data_p, uint32_t parse_opts); + +#if JERRY_MODULE_SYSTEM +ecma_value_t vm_run_module (ecma_module_t *module_p); +ecma_value_t vm_init_module_scope (ecma_module_t *module_p); +#endif /* JERRY_MODULE_SYSTEM */ + +ecma_value_t vm_run (vm_frame_ctx_shared_t *shared_p, ecma_value_t this_binding_value, ecma_object_t *lex_env_p); +ecma_value_t vm_execute (vm_frame_ctx_t *frame_ctx_p); + +bool vm_is_strict_mode (void); +bool vm_is_direct_eval_form_call (void); + +ecma_value_t vm_get_backtrace (uint32_t max_depth); + +/** + * @} + * @} + */ + +#endif /* !VM_H */ diff --git a/src/loaders/lottie/jerryscript/meson.build b/src/loaders/lottie/jerryscript/meson.build new file mode 100644 index 00000000..a8e063bb --- /dev/null +++ b/src/loaders/lottie/jerryscript/meson.build @@ -0,0 +1 @@ +subdir('jerry-core') diff --git a/src/loaders/lottie/meson.build b/src/loaders/lottie/meson.build index bd952a91..0042db5f 100644 --- a/src/loaders/lottie/meson.build +++ b/src/loaders/lottie/meson.build @@ -1,3 +1,7 @@ +if lottie_expressions + subdir('jerryscript') +endif + source_file = [ 'tvgLottieAnimation.cpp', 'tvgLottieBuilder.h',