aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Komissarov <[email protected]>2025-01-06 21:38:13 +0300
committerIvan Komissarov <[email protected]>2025-02-18 18:52:03 +0000
commit5fa7747eadc10e770d54eeff159c800055d10457 (patch)
tree4e9001eadaaf212f56664ff1deb10a1104b62080
parent15af741f7e586c3f45abe62f92ad42587b8ffb58 (diff)
Port to QuickJS-NG
This changes the JavaScript Engine from QuickJS to QuickJS-NG which is actively maintained and accepts patches to the upstream. ========== Performance data for Resolving ========== Old instruction count: 9561510682 New instruction count: 9774483416 Relative change: +2 % Old peak memory usage: 119540088 Bytes New peak memory usage: 119507704 Bytes Relative change: 0 % ========== Performance data for Rule Execution ========== Old instruction count: 4538999624 New instruction count: 4493570765 Relative change: -1 % Old peak memory usage: 53985376 Bytes New peak memory usage: 54019128 Bytes Relative change: 0 % ========== Performance data for Null Build ========== Old instruction count: 1352244475 New instruction count: 1356601207 Relative change: 0 % Old peak memory usage: 43104664 Bytes New peak memory usage: 43045184 Bytes Relative change: 0 % CPU regression was indroduced by https://github.com/quickjs-ng/quickjs/commit/bace4f635e668917712a53c80286c8d2b566a4dc and probably won't be fixed. Change-Id: Ia6f7b2113743b832cff6b2b81e5b3027d0e09fda Reviewed-by: Christian Kandeler <[email protected]>
-rw-r--r--src/lib/corelib/buildgraph/rulecommands.cpp2
-rw-r--r--src/lib/corelib/buildgraph/rulesapplicator.cpp2
-rw-r--r--src/lib/corelib/language/scriptengine.cpp26
-rw-r--r--src/lib/corelib/loader/dependenciesresolver.cpp5
-rw-r--r--src/lib/corelib/tools/error.cpp5
-rw-r--r--src/lib/corelib/tools/scripttools.cpp16
-rw-r--r--src/lib/corelib/tools/scripttools.h11
-rw-r--r--src/shared/quickjs/CMakeLists.txt1
-rw-r--r--src/shared/quickjs/LICENSE10
-rw-r--r--src/shared/quickjs/cutils.c994
-rw-r--r--src/shared/quickjs/cutils.h403
-rw-r--r--src/shared/quickjs/libbf.c223
-rw-r--r--src/shared/quickjs/libbf.h28
-rw-r--r--src/shared/quickjs/libregexp-opcode.h3
-rw-r--r--src/shared/quickjs/libregexp.c429
-rw-r--r--src/shared/quickjs/libregexp.h43
-rw-r--r--src/shared/quickjs/libunicode-table.h3479
-rw-r--r--src/shared/quickjs/libunicode.c216
-rw-r--r--src/shared/quickjs/libunicode.h108
-rw-r--r--src/shared/quickjs/list.h8
-rw-r--r--src/shared/quickjs/quickjs-atom.h31
-rw-r--r--src/shared/quickjs/quickjs-c-atomics.h54
-rw-r--r--src/shared/quickjs/quickjs-opcode.h28
-rw-r--r--src/shared/quickjs/quickjs.c23354
-rw-r--r--src/shared/quickjs/quickjs.h1100
-rw-r--r--src/shared/quickjs/quickjs.qbs1
-rwxr-xr-xsrc/shared/quickjs/sync.sh34
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp2
-rw-r--r--tests/auto/language/tst_language.cpp11
29 files changed, 15766 insertions, 14861 deletions
diff --git a/src/lib/corelib/buildgraph/rulecommands.cpp b/src/lib/corelib/buildgraph/rulecommands.cpp
index 593956046..a6f16a9d8 100644
--- a/src/lib/corelib/buildgraph/rulecommands.cpp
+++ b/src/lib/corelib/buildgraph/rulecommands.cpp
@@ -157,7 +157,7 @@ void AbstractCommand::applyCommandProperties(JSContext *ctx, const JSValue *scri
if (m_predefinedProperties.contains(name))
return;
// TODO: Use script class for command objects, don't allow setting random properties
- if (!isSimpleValue(desc.value)) {
+ if (!JS_IsSimpleValue(ctx, desc.value)) {
throw ErrorInfo(Tr::tr("Property '%1' has a type unsuitable for storing in a command "
"object.").arg(name), m_codeLocation);
}
diff --git a/src/lib/corelib/buildgraph/rulesapplicator.cpp b/src/lib/corelib/buildgraph/rulesapplicator.cpp
index e42b8a529..9daf9f037 100644
--- a/src/lib/corelib/buildgraph/rulesapplicator.cpp
+++ b/src/lib/corelib/buildgraph/rulesapplicator.cpp
@@ -589,7 +589,7 @@ class ArtifactBindingsExtractor
const JSValue value = desc.value;
if (JS_IsObject(value) && !JS_IsArray(m_ctx, value) && !JS_IsError(m_ctx, value)
- && !JS_IsRegExp(m_ctx, value)) {
+ && !JS_IsRegExp(value)) {
QString newModuleName;
if (!moduleName.isEmpty())
newModuleName.append(moduleName + QLatin1Char('.'));
diff --git a/src/lib/corelib/language/scriptengine.cpp b/src/lib/corelib/language/scriptengine.cpp
index 10d2a67fe..282a94ade 100644
--- a/src/lib/corelib/language/scriptengine.cpp
+++ b/src/lib/corelib/language/scriptengine.cpp
@@ -338,15 +338,9 @@ void ScriptEngine::checkContext(const QString &operation,
QBS_ASSERT(false, continue);
break;
}
- if (!m_evalPositions.empty()) {
- const JSValue exVal = JS_NewObject(m_context);
- const auto &[file, line] = m_evalPositions.top();
- build_backtrace(m_context, exVal, file.toUtf8().constData(), line, 0);
- const JsException ex(m_context, exVal, {});
- m_logger.printWarning(ErrorInfo(warning, ex.stackTrace()));
- } else {
- m_logger.printWarning(ErrorInfo(warning));
- }
+ const JSValue exVal = JS_NewError(m_context);
+ const JsException ex(m_context, exVal, JS_GetBacktrace(m_context), {});
+ m_logger.printWarning(ErrorInfo(warning, ex.stackTrace()));
return;
}
}
@@ -582,7 +576,7 @@ JSValue ScriptEngine::asJsValue(const QVariantMap &m, quintptr id, bool frozen)
for (auto it = m.begin(); it != m.end(); ++it)
setJsProperty(m_context, obj, it.key(), asJsValue(it.value(), 0, frozen));
if (frozen)
- JS_ObjectSeal(m_context, obj, true);
+ JS_FreezeObject(m_context, obj);
if (!id)
return obj;
m_jsValueCache[id] = obj;
@@ -606,7 +600,7 @@ JSValue ScriptEngine::asJsValue(const QVariantList &l, quintptr id, bool frozen)
for (int i = 0; i < l.size(); ++i)
JS_SetPropertyUint32(m_context, array, i, asJsValue(l.at(i), 0, frozen));
if (frozen)
- JS_ObjectSeal(m_context, array, true);
+ JS_FreezeObject(m_context, array);
if (!id)
return array;
m_jsValueCache[id] = array;
@@ -839,10 +833,12 @@ JSValue ScriptEngine::evaluate(
{
m_scopeChains.emplace_back(scopeChain);
const QByteArray &codeStr = code.toUtf8();
+ const QByteArray &filePathStr = filePath.toUtf8();
m_evalPositions.emplace(filePath, line);
- const JSValue v = JS_EvalThis(m_context, globalObject(), codeStr.constData(), codeStr.length(),
- filePath.toUtf8().constData(), line, JS_EVAL_TYPE_GLOBAL);
+ JSEvalOptions evalOptions{1, JS_EVAL_TYPE_GLOBAL, filePathStr.constData(), line};
+ const JSValue v = JS_EvalThis2(
+ m_context, globalObject(), codeStr.constData(), codeStr.length(), &evalOptions);
m_evalPositions.pop();
m_scopeChains.pop_back();
if (resultOwner == JsValueOwner::ScriptEngine && JS_VALUE_HAS_REF_COUNT(v))
@@ -871,7 +867,7 @@ JSClassID ScriptEngine::registerClass(const char *name, JSClassCall *constructor
JSClassID id = 0;
const auto classIt = m_classes.constFind(QLatin1String(name));
if (classIt == m_classes.constEnd()) {
- JS_NewClassID(&id);
+ JS_NewClassID(m_jsRuntime, &id);
const auto it = getProperty
? m_exoticMethods.insert(id, JSClassExoticMethods{getProperty, getPropertyNames})
: m_exoticMethods.end();
@@ -1110,7 +1106,7 @@ ScriptEngine::PropertyCacheKey::PropertyCacheKey(QString moduleName,
JsException ScriptEngine::checkAndClearException(const CodeLocation &fallbackLocation) const
{
- return {m_context, JS_GetException(m_context), fallbackLocation};
+ return {m_context, JS_GetException(m_context), JS_GetBacktrace(m_context), fallbackLocation};
}
void ScriptEngine::clearRequestedProperties()
diff --git a/src/lib/corelib/loader/dependenciesresolver.cpp b/src/lib/corelib/loader/dependenciesresolver.cpp
index 8e5ec3888..d9ecbabea 100644
--- a/src/lib/corelib/loader/dependenciesresolver.cpp
+++ b/src/lib/corelib/loader/dependenciesresolver.cpp
@@ -1115,8 +1115,9 @@ QVariantMap safeToVariant(JSContext *ctx, const JSValue &v)
if (JS_IsError(ctx, u))
throw ErrorInfo(getJsString(ctx, u));
const QString name = getJsString(ctx, prop);
- result[name] = (JS_IsObject(u) && !JS_IsArray(ctx, u) && !JS_IsRegExp(ctx, u))
- ? safeToVariant(ctx, u) : getJsVariant(ctx, u);
+ result[name] = (JS_IsObject(u) && !JS_IsArray(ctx, u) && !JS_IsRegExp(u))
+ ? safeToVariant(ctx, u)
+ : getJsVariant(ctx, u);
});
return result;
}
diff --git a/src/lib/corelib/tools/error.cpp b/src/lib/corelib/tools/error.cpp
index 3d996c6a7..5f94601e5 100644
--- a/src/lib/corelib/tools/error.cpp
+++ b/src/lib/corelib/tools/error.cpp
@@ -209,8 +209,9 @@ ErrorInfo::ErrorInfo(const QString &description, const QStringList &backtrace)
for (const QString &traceLine : backtrace) {
if (traceLine.contains(QStringLiteral("<eval>")))
continue;
- static const std::regex regexpWithFunc("^(.+) at [^(]*\\((.+):(\\-?[0-9]+)\\)$");
- static const std::regex regexpWithoutFunc("^(.+) at (.+):(\\-?[0-9]+)$");
+ static const std::regex regexpWithFunc(
+ "^(.+) at [^(]*\\((.+):(\\-?[0-9]+):(\\-?[0-9]+)\\)$");
+ static const std::regex regexpWithoutFunc("^(.+) at (.+):(\\-?[0-9]+):(\\-?[0-9]+)$");
std::smatch match;
const std::string tl = traceLine.toStdString();
bool hasMatch = std::regex_match(tl, match, regexpWithFunc);
diff --git a/src/lib/corelib/tools/scripttools.cpp b/src/lib/corelib/tools/scripttools.cpp
index 6aa44adbb..ccf1f4b53 100644
--- a/src/lib/corelib/tools/scripttools.cpp
+++ b/src/lib/corelib/tools/scripttools.cpp
@@ -83,13 +83,20 @@ TemporaryGlobalObjectSetter::~TemporaryGlobalObjectSetter()
}
JsException::JsException(JsException &&other) noexcept
- : m_ctx(other.m_ctx), m_exception(other.m_exception),
- m_fallbackLocation(std::move(other.m_fallbackLocation))
+ : m_ctx(other.m_ctx)
+ , m_exception(other.m_exception)
+ , m_backtrace(other.m_exception)
+ , m_fallbackLocation(std::move(other.m_fallbackLocation))
{
other.m_exception = JS_NULL;
+ other.m_backtrace = JS_NULL;
}
-JsException::~JsException() { JS_FreeValue(m_ctx, m_exception); }
+JsException::~JsException()
+{
+ JS_FreeValue(m_ctx, m_exception);
+ JS_FreeValue(m_ctx, m_backtrace);
+}
QString JsException::message() const
{
@@ -113,8 +120,7 @@ QString JsException::message() const
const QStringList JsException::stackTrace() const
{
- return getJsStringProperty(m_ctx, m_exception, QLatin1String("stack"))
- .split(QLatin1Char('\n'), Qt::SkipEmptyParts);
+ return getJsString(m_ctx, m_backtrace).split(QLatin1Char('\n'), Qt::SkipEmptyParts);
}
ErrorInfo JsException::toErrorInfo() const
diff --git a/src/lib/corelib/tools/scripttools.h b/src/lib/corelib/tools/scripttools.h
index 20964cae5..0ea2144d6 100644
--- a/src/lib/corelib/tools/scripttools.h
+++ b/src/lib/corelib/tools/scripttools.h
@@ -179,20 +179,25 @@ private:
class QBS_AUTOTEST_EXPORT JsException
{
public:
- JsException(JSContext *ctx, JSValue ex, const CodeLocation &fallbackLocation)
- : m_ctx(ctx), m_exception(ex), m_fallbackLocation(fallbackLocation) {}
+ JsException(JSContext *ctx, JSValue ex, JSValue bt, const CodeLocation &fallbackLocation)
+ : m_ctx(ctx)
+ , m_exception(ex)
+ , m_backtrace(bt)
+ , m_fallbackLocation(fallbackLocation)
+ {}
JsException(JsException && other) noexcept;
~JsException();
JsException(const JsException &) = delete;
JsException &operator=(const JsException &) = delete;
- operator bool() const { return !JS_IsNull(m_exception); }
+ operator bool() const { return m_exception.tag != JS_TAG_UNINITIALIZED; }
QString message() const;
const QStringList stackTrace() const;
ErrorInfo toErrorInfo() const;
private:
JSContext *m_ctx;
JSValue m_exception;
+ JSValue m_backtrace;
CodeLocation m_fallbackLocation;
};
diff --git a/src/shared/quickjs/CMakeLists.txt b/src/shared/quickjs/CMakeLists.txt
index 371079ecc..a76aa7264 100644
--- a/src/shared/quickjs/CMakeLists.txt
+++ b/src/shared/quickjs/CMakeLists.txt
@@ -9,6 +9,7 @@ add_qbs_library(qbsquickjs
libunicode.c libunicode.h
list.h
quickjs-atom.h
+ quickjs-c-atomics.h
quickjs-opcode.h
quickjs.c quickjs.h
DEFINES
diff --git a/src/shared/quickjs/LICENSE b/src/shared/quickjs/LICENSE
index 2cf449dd3..3c78b6929 100644
--- a/src/shared/quickjs/LICENSE
+++ b/src/shared/quickjs/LICENSE
@@ -1,7 +1,9 @@
-QuickJS Javascript Engine
-
-Copyright (c) 2017-2021 Fabrice Bellard
-Copyright (c) 2017-2021 Charlie Gordon
+The MIT License (MIT)
+
+Copyright (c) 2017-2024 Fabrice Bellard
+Copyright (c) 2017-2024 Charlie Gordon
+Copyright (c) 2023-2025 Ben Noordhuis
+Copyright (c) 2023-2025 Saúl Ibarra Corretgé
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/shared/quickjs/cutils.c b/src/shared/quickjs/cutils.c
index 95ae5688d..438087d06 100644
--- a/src/shared/quickjs/cutils.c
+++ b/src/shared/quickjs/cutils.c
@@ -22,14 +22,26 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
+#include <time.h>
+#if !defined(_MSC_VER)
+#include <sys/time.h>
+#endif
#include "cutils.h"
-void pstrcpy(char *buf, int buf_size, const char *str)
+#undef NANOSEC
+#define NANOSEC ((uint64_t) 1e9)
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+
+void js__pstrcpy(char *buf, int buf_size, const char *str)
{
int c;
char *q = buf;
@@ -47,16 +59,16 @@ void pstrcpy(char *buf, int buf_size, const char *str)
}
/* strcat and truncate. */
-char *pstrcat(char *buf, int buf_size, const char *s)
+char *js__pstrcat(char *buf, int buf_size, const char *s)
{
int len;
len = strlen(buf);
if (len < buf_size)
- pstrcpy(buf + len, buf_size - len, s);
+ js__pstrcpy(buf + len, buf_size - len, s);
return buf;
}
-int strstart(const char *str, const char *val, const char **ptr)
+int js__strstart(const char *str, const char *val, const char **ptr)
{
const char *p, *q;
p = str;
@@ -72,7 +84,7 @@ int strstart(const char *str, const char *val, const char **ptr)
return 1;
}
-int has_suffix(const char *str, const char *suffix)
+int js__has_suffix(const char *str, const char *suffix)
{
size_t len = strlen(str);
size_t slen = strlen(suffix);
@@ -113,7 +125,7 @@ int dbuf_realloc(DynBuf *s, size_t new_size)
new_size = size;
new_buf = s->realloc_func(s->opaque, s->buf, new_size);
if (!new_buf) {
- s->error = TRUE;
+ s->error = true;
return -1;
}
s->buf = new_buf;
@@ -122,7 +134,7 @@ int dbuf_realloc(DynBuf *s, size_t new_size)
return 0;
}
-int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
+int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len)
{
size_t end;
end = offset + len;
@@ -134,14 +146,16 @@ int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
return 0;
}
-int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
+int dbuf_put(DynBuf *s, const void *data, size_t len)
{
if (unlikely((s->size + len) > s->allocated_size)) {
if (dbuf_realloc(s, s->size + len))
return -1;
}
- memcpy_no_ub(s->buf + s->size, data, len);
- s->size += len;
+ if (len > 0) {
+ memcpy(s->buf + s->size, data, len);
+ s->size += len;
+ }
return 0;
}
@@ -166,7 +180,7 @@ int dbuf_putstr(DynBuf *s, const char *str)
return dbuf_put(s, (const uint8_t *)str, strlen(str));
}
-int FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, const char *fmt, ...)
+int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...)
{
va_list ap;
char buf[128];
@@ -175,7 +189,7 @@ int FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, const char *fmt, ...)
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
- if (len < sizeof(buf)) {
+ if (len < (int)sizeof(buf)) {
/* fast case */
return dbuf_put(s, (uint8_t *)buf, len);
} else {
@@ -200,56 +214,85 @@ void dbuf_free(DynBuf *s)
memset(s, 0, sizeof(*s));
}
-/* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes
- are output. */
-int unicode_to_utf8(uint8_t *buf, unsigned int c)
+/*--- UTF-8 utility functions --*/
+
+/* Note: only encode valid codepoints (0x0000..0x10FFFF).
+ At most UTF8_CHAR_LEN_MAX bytes are output. */
+
+/* Compute the number of bytes of the UTF-8 encoding for a codepoint
+ `c` is a code-point.
+ Returns the number of bytes. If a codepoint is beyond 0x10FFFF the
+ return value is 3 as the codepoint would be encoded as 0xFFFD.
+ */
+size_t utf8_encode_len(uint32_t c)
{
- uint8_t *q = buf;
+ if (c < 0x80)
+ return 1;
+ if (c < 0x800)
+ return 2;
+ if (c < 0x10000)
+ return 3;
+ if (c < 0x110000)
+ return 4;
+ return 3;
+}
+/* Encode a codepoint in UTF-8
+ `buf` points to an array of at least `UTF8_CHAR_LEN_MAX` bytes
+ `c` is a code-point.
+ Returns the number of bytes. If a codepoint is beyond 0x10FFFF the
+ return value is 3 and the codepoint is encoded as 0xFFFD.
+ No null byte is stored after the encoded bytes.
+ Return value is in range 1..4
+ */
+size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c)
+{
if (c < 0x80) {
- *q++ = c;
- } else {
- if (c < 0x800) {
- *q++ = (c >> 6) | 0xc0;
- } else {
- if (c < 0x10000) {
- *q++ = (c >> 12) | 0xe0;
- } else {
- if (c < 0x00200000) {
- *q++ = (c >> 18) | 0xf0;
- } else {
- if (c < 0x04000000) {
- *q++ = (c >> 24) | 0xf8;
- } else if (c < 0x80000000) {
- *q++ = (c >> 30) | 0xfc;
- *q++ = ((c >> 24) & 0x3f) | 0x80;
- } else {
- return 0;
- }
- *q++ = ((c >> 18) & 0x3f) | 0x80;
- }
- *q++ = ((c >> 12) & 0x3f) | 0x80;
- }
- *q++ = ((c >> 6) & 0x3f) | 0x80;
- }
- *q++ = (c & 0x3f) | 0x80;
+ buf[0] = c;
+ return 1;
}
- return q - buf;
+ if (c < 0x800) {
+ buf[0] = (c >> 6) | 0xC0;
+ buf[1] = (c & 0x3F) | 0x80;
+ return 2;
+ }
+ if (c < 0x10000) {
+ buf[0] = (c >> 12) | 0xE0;
+ buf[1] = ((c >> 6) & 0x3F) | 0x80;
+ buf[2] = (c & 0x3F) | 0x80;
+ return 3;
+ }
+ if (c < 0x110000) {
+ buf[0] = (c >> 18) | 0xF0;
+ buf[1] = ((c >> 12) & 0x3F) | 0x80;
+ buf[2] = ((c >> 6) & 0x3F) | 0x80;
+ buf[3] = (c & 0x3F) | 0x80;
+ return 4;
+ }
+ buf[0] = (0xFFFD >> 12) | 0xE0;
+ buf[1] = ((0xFFFD >> 6) & 0x3F) | 0x80;
+ buf[2] = (0xFFFD & 0x3F) | 0x80;
+ return 3;
}
-static const unsigned int utf8_min_code[5] = {
- 0x80, 0x800, 0x10000, 0x00200000, 0x04000000,
-};
-
-static const unsigned char utf8_first_code_mask[5] = {
- 0x1f, 0xf, 0x7, 0x3, 0x1,
-};
-
-/* return -1 if error. *pp is not updated in this case. max_len must
- be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */
-int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp)
+/* Decode a single code point from a UTF-8 encoded array of bytes
+ `p` is a valid pointer to an array of bytes
+ `pp` is a valid pointer to a `const uint8_t *` to store a pointer
+ to the byte following the current sequence.
+ Return the code point at `p`, in the range `0..0x10FFFF`
+ Return 0xFFFD on error. Only a single byte is consumed in this case
+ The maximum length for a UTF-8 byte sequence is 4 bytes.
+ This implements the algorithm specified in whatwg.org, except it accepts
+ UTF-8 encoded surrogates as JavaScript allows them in strings.
+ The source string is assumed to have at least UTF8_CHAR_LEN_MAX bytes
+ or be null terminated.
+ If `p[0]` is '\0', the return value is `0` and the byte is consumed.
+ cf: https://encoding.spec.whatwg.org/#utf-8-encoder
+ */
+uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp)
{
- int l, c, b, i;
+ uint32_t c;
+ uint8_t lower, upper;
c = *p++;
if (c < 0x80) {
@@ -257,76 +300,538 @@ int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp)
return c;
}
switch(c) {
- case 0xc0: case 0xc1: case 0xc2: case 0xc3:
- case 0xc4: case 0xc5: case 0xc6: case 0xc7:
- case 0xc8: case 0xc9: case 0xca: case 0xcb:
- case 0xcc: case 0xcd: case 0xce: case 0xcf:
- case 0xd0: case 0xd1: case 0xd2: case 0xd3:
- case 0xd4: case 0xd5: case 0xd6: case 0xd7:
- case 0xd8: case 0xd9: case 0xda: case 0xdb:
- case 0xdc: case 0xdd: case 0xde: case 0xdf:
- l = 1;
+ case 0xC2: case 0xC3:
+ case 0xC4: case 0xC5: case 0xC6: case 0xC7:
+ case 0xC8: case 0xC9: case 0xCA: case 0xCB:
+ case 0xCC: case 0xCD: case 0xCE: case 0xCF:
+ case 0xD0: case 0xD1: case 0xD2: case 0xD3:
+ case 0xD4: case 0xD5: case 0xD6: case 0xD7:
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ if (*p >= 0x80 && *p <= 0xBF) {
+ *pp = p + 1;
+ return ((c - 0xC0) << 6) + (*p - 0x80);
+ }
+ // otherwise encoding error
+ break;
+ case 0xE0:
+ lower = 0xA0; /* reject invalid encoding */
+ goto need2;
+ case 0xE1: case 0xE2: case 0xE3:
+ case 0xE4: case 0xE5: case 0xE6: case 0xE7:
+ case 0xE8: case 0xE9: case 0xEA: case 0xEB:
+ case 0xEC: case 0xED: case 0xEE: case 0xEF:
+ lower = 0x80;
+ need2:
+ if (*p >= lower && *p <= 0xBF && p[1] >= 0x80 && p[1] <= 0xBF) {
+ *pp = p + 2;
+ return ((c - 0xE0) << 12) + ((*p - 0x80) << 6) + (p[1] - 0x80);
+ }
+ // otherwise encoding error
+ break;
+ case 0xF0:
+ lower = 0x90; /* reject invalid encoding */
+ upper = 0xBF;
+ goto need3;
+ case 0xF4:
+ lower = 0x80;
+ upper = 0x8F; /* reject values above 0x10FFFF */
+ goto need3;
+ case 0xF1: case 0xF2: case 0xF3:
+ lower = 0x80;
+ upper = 0xBF;
+ need3:
+ if (*p >= lower && *p <= upper && p[1] >= 0x80 && p[1] <= 0xBF
+ && p[2] >= 0x80 && p[2] <= 0xBF) {
+ *pp = p + 3;
+ return ((c - 0xF0) << 18) + ((*p - 0x80) << 12) +
+ ((p[1] - 0x80) << 6) + (p[2] - 0x80);
+ }
+ // otherwise encoding error
break;
- case 0xe0: case 0xe1: case 0xe2: case 0xe3:
- case 0xe4: case 0xe5: case 0xe6: case 0xe7:
- case 0xe8: case 0xe9: case 0xea: case 0xeb:
- case 0xec: case 0xed: case 0xee: case 0xef:
- l = 2;
+ default:
+ // invalid lead byte
break;
- case 0xf0: case 0xf1: case 0xf2: case 0xf3:
- case 0xf4: case 0xf5: case 0xf6: case 0xf7:
- l = 3;
+ }
+ *pp = p;
+ return 0xFFFD;
+}
+
+uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp) {
+ switch (max_len) {
+ case 0:
+ *pp = p;
+ return 0xFFFD;
+ case 1:
+ if (*p < 0x80)
+ goto good;
break;
- case 0xf8: case 0xf9: case 0xfa: case 0xfb:
- l = 4;
+ case 2:
+ if (*p < 0xE0)
+ goto good;
break;
- case 0xfc: case 0xfd:
- l = 5;
+ case 3:
+ if (*p < 0xF0)
+ goto good;
break;
default:
- return -1;
+ good:
+ return utf8_decode(p, pp);
}
- /* check that we have enough characters */
- if (l > (max_len - 1))
- return -1;
- c &= utf8_first_code_mask[l - 1];
- for(i = 0; i < l; i++) {
- b = *p++;
- if (b < 0x80 || b >= 0xc0)
- return -1;
- c = (c << 6) | (b & 0x3f);
+ *pp = p + 1;
+ return 0xFFFD;
+}
+
+/* Scan a UTF-8 encoded buffer for content type
+ `buf` is a valid pointer to a UTF-8 encoded string
+ `len` is the number of bytes to scan
+ `plen` points to a `size_t` variable to receive the number of units
+ Return value is a mask of bits.
+ - `UTF8_PLAIN_ASCII`: return value for 7-bit ASCII plain text
+ - `UTF8_NON_ASCII`: bit for non ASCII code points (8-bit or more)
+ - `UTF8_HAS_16BIT`: bit for 16-bit code points
+ - `UTF8_HAS_NON_BMP1`: bit for non-BMP1 code points, needs UTF-16 surrogate pairs
+ - `UTF8_HAS_ERRORS`: bit for encoding errors
+ */
+int utf8_scan(const char *buf, size_t buf_len, size_t *plen)
+{
+ const uint8_t *p, *p_end, *p_next;
+ size_t i, len;
+ int kind;
+ uint8_t cbits;
+
+ kind = UTF8_PLAIN_ASCII;
+ cbits = 0;
+ len = buf_len;
+ // TODO: handle more than 1 byte at a time
+ for (i = 0; i < buf_len; i++)
+ cbits |= buf[i];
+ if (cbits >= 0x80) {
+ p = (const uint8_t *)buf;
+ p_end = p + buf_len;
+ kind = UTF8_NON_ASCII;
+ len = 0;
+ while (p < p_end) {
+ len++;
+ if (*p++ >= 0x80) {
+ /* parse UTF-8 sequence, check for encoding error */
+ uint32_t c = utf8_decode_len(p - 1, p_end - (p - 1), &p_next);
+ if (p_next == p)
+ kind |= UTF8_HAS_ERRORS;
+ p = p_next;
+ if (c > 0xFF) {
+ kind |= UTF8_HAS_16BIT;
+ if (c > 0xFFFF) {
+ len++;
+ kind |= UTF8_HAS_NON_BMP1;
+ }
+ }
+ }
+ }
}
- if (c < utf8_min_code[l - 1])
- return -1;
- *pp = p;
- return c;
+ *plen = len;
+ return kind;
}
-#if 0
+/* Decode a string encoded in UTF-8 into an array of bytes
+ `src` points to the source string. It is assumed to be correctly encoded
+ and only contains code points below 0x800
+ `src_len` is the length of the source string
+ `dest` points to the destination array, it can be null if `dest_len` is `0`
+ `dest_len` is the length of the destination array. A null
+ terminator is stored at the end of the array unless `dest_len` is `0`.
+ */
+size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len)
+{
+ const uint8_t *p, *p_end;
+ size_t i;
-#if defined(EMSCRIPTEN) || defined(__ANDROID__)
+ p = (const uint8_t *)src;
+ p_end = p + src_len;
+ for (i = 0; p < p_end; i++) {
+ uint32_t c = *p++;
+ if (c >= 0xC0)
+ c = (c << 6) + *p++ - ((0xC0 << 6) + 0x80);
+ if (i < dest_len)
+ dest[i] = c;
+ }
+ if (i < dest_len)
+ dest[i] = '\0';
+ else if (dest_len > 0)
+ dest[dest_len - 1] = '\0';
+ return i;
+}
-static void *rqsort_arg;
-static int (*rqsort_cmp)(const void *, const void *, void *);
+/* Decode a string encoded in UTF-8 into an array of 16-bit words
+ `src` points to the source string. It is assumed to be correctly encoded.
+ `src_len` is the length of the source string
+ `dest` points to the destination array, it can be null if `dest_len` is `0`
+ `dest_len` is the length of the destination array. No null terminator is
+ stored at the end of the array.
+ */
+size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len)
+{
+ const uint8_t *p, *p_end;
+ size_t i;
-static int rqsort_cmp2(const void *p1, const void *p2)
+ p = (const uint8_t *)src;
+ p_end = p + src_len;
+ for (i = 0; p < p_end; i++) {
+ uint32_t c = *p++;
+ if (c >= 0x80) {
+ /* parse utf-8 sequence */
+ c = utf8_decode_len(p - 1, p_end - (p - 1), &p);
+ /* encoding errors are converted as 0xFFFD and use a single byte */
+ if (c > 0xFFFF) {
+ if (i < dest_len)
+ dest[i] = get_hi_surrogate(c);
+ i++;
+ c = get_lo_surrogate(c);
+ }
+ }
+ if (i < dest_len)
+ dest[i] = c;
+ }
+ return i;
+}
+
+/* Encode a buffer of 8-bit bytes as a UTF-8 encoded string
+ `src` points to the source buffer.
+ `src_len` is the length of the source buffer
+ `dest` points to the destination array, it can be null if `dest_len` is `0`
+ `dest_len` is the length in bytes of the destination array. A null
+ terminator is stored at the end of the array unless `dest_len` is `0`.
+ */
+size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len)
{
- return rqsort_cmp(p1, p2, rqsort_arg);
+ size_t i, j;
+ uint32_t c;
+
+ for (i = j = 0; i < src_len; i++) {
+ c = src[i];
+ if (c < 0x80) {
+ if (j + 1 >= dest_len)
+ goto overflow;
+ dest[j++] = c;
+ } else {
+ if (j + 2 >= dest_len)
+ goto overflow;
+ dest[j++] = (c >> 6) | 0xC0;
+ dest[j++] = (c & 0x3F) | 0x80;
+ }
+ }
+ if (j < dest_len)
+ dest[j] = '\0';
+ return j;
+
+overflow:
+ if (j < dest_len)
+ dest[j] = '\0';
+ while (i < src_len)
+ j += 1 + (src[i++] >= 0x80);
+ return j;
}
-/* not reentrant, but not needed with emscripten */
-void rqsort(void *base, size_t nmemb, size_t size,
- int (*cmp)(const void *, const void *, void *),
- void *arg)
+/* Encode a buffer of 16-bit code points as a UTF-8 encoded string
+ `src` points to the source buffer.
+ `src_len` is the length of the source buffer
+ `dest` points to the destination array, it can be null if `dest_len` is `0`
+ `dest_len` is the length in bytes of the destination array. A null
+ terminator is stored at the end of the array unless `dest_len` is `0`.
+ */
+size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len)
{
- rqsort_arg = arg;
- rqsort_cmp = cmp;
- qsort(base, nmemb, size, rqsort_cmp2);
+ size_t i, j;
+ uint32_t c;
+
+ for (i = j = 0; i < src_len;) {
+ c = src[i++];
+ if (c < 0x80) {
+ if (j + 1 >= dest_len)
+ goto overflow;
+ dest[j++] = c;
+ } else {
+ if (is_hi_surrogate(c) && i < src_len && is_lo_surrogate(src[i]))
+ c = from_surrogate(c, src[i++]);
+ if (j + utf8_encode_len(c) >= dest_len)
+ goto overflow;
+ j += utf8_encode((uint8_t *)dest + j, c);
+ }
+ }
+ if (j < dest_len)
+ dest[j] = '\0';
+ return j;
+
+overflow:
+ i -= 1 + (c > 0xFFFF);
+ if (j < dest_len)
+ dest[j] = '\0';
+ while (i < src_len) {
+ c = src[i++];
+ if (c < 0x80) {
+ j++;
+ } else {
+ if (is_hi_surrogate(c) && i < src_len && is_lo_surrogate(src[i]))
+ c = from_surrogate(c, src[i++]);
+ j += utf8_encode_len(c);
+ }
+ }
+ return j;
}
+/*--- integer to string conversions --*/
+
+/* All conversion functions:
+ - require a destination array `buf` of sufficient length
+ - write the string representation at the beginning of `buf`
+ - null terminate the string
+ - return the string length
+ */
+
+/* 2 <= base <= 36 */
+char const digits36[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'
+};
+
+
+#define USE_SPECIAL_RADIX_10 1 // special case base 10 radix conversions
+#define USE_SINGLE_CASE_FAST 1 // special case single digit numbers
+
+/* using u32toa_shift variant */
+
+#define gen_digit(buf, c) if (is_be()) \
+ buf = (buf >> 8) | ((uint64_t)(c) << ((sizeof(buf) - 1) * 8)); \
+ else \
+ buf = (buf << 8) | (c)
+
+static size_t u7toa_shift(char dest[minimum_length(8)], uint32_t n)
+{
+ size_t len = 1;
+ uint64_t buf = 0;
+ while (n >= 10) {
+ uint32_t quo = n % 10;
+ n /= 10;
+ gen_digit(buf, '0' + quo);
+ len++;
+ }
+ gen_digit(buf, '0' + n);
+ memcpy(dest, &buf, sizeof buf);
+ return len;
+}
+
+static size_t u07toa_shift(char dest[minimum_length(8)], uint32_t n, size_t len)
+{
+ size_t i;
+ dest += len;
+ dest[7] = '\0';
+ for (i = 7; i-- > 1;) {
+ uint32_t quo = n % 10;
+ n /= 10;
+ dest[i] = (char)('0' + quo);
+ }
+ dest[i] = (char)('0' + n);
+ return len + 7;
+}
+
+size_t u32toa(char buf[minimum_length(11)], uint32_t n)
+{
+#ifdef USE_SINGLE_CASE_FAST /* 10% */
+ if (n < 10) {
+ buf[0] = (char)('0' + n);
+ buf[1] = '\0';
+ return 1;
+ }
#endif
+#define TEN_POW_7 10000000
+ if (n >= TEN_POW_7) {
+ uint32_t quo = n / TEN_POW_7;
+ n %= TEN_POW_7;
+ size_t len = u7toa_shift(buf, quo);
+ return u07toa_shift(buf, n, len);
+ }
+ return u7toa_shift(buf, n);
+}
-#else
+size_t u64toa(char buf[minimum_length(21)], uint64_t n)
+{
+ if (likely(n < 0x100000000))
+ return u32toa(buf, n);
+
+ size_t len;
+ if (n >= TEN_POW_7) {
+ uint64_t n1 = n / TEN_POW_7;
+ n %= TEN_POW_7;
+ if (n1 >= TEN_POW_7) {
+ uint32_t quo = n1 / TEN_POW_7;
+ n1 %= TEN_POW_7;
+ len = u7toa_shift(buf, quo);
+ len = u07toa_shift(buf, n1, len);
+ } else {
+ len = u7toa_shift(buf, n1);
+ }
+ return u07toa_shift(buf, n, len);
+ }
+ return u7toa_shift(buf, n);
+}
+
+size_t i32toa(char buf[minimum_length(12)], int32_t n)
+{
+ if (likely(n >= 0))
+ return u32toa(buf, n);
+
+ buf[0] = '-';
+ return 1 + u32toa(buf + 1, -(uint32_t)n);
+}
+
+size_t i64toa(char buf[minimum_length(22)], int64_t n)
+{
+ if (likely(n >= 0))
+ return u64toa(buf, n);
+
+ buf[0] = '-';
+ return 1 + u64toa(buf + 1, -(uint64_t)n);
+}
+
+/* using u32toa_radix_length variant */
+
+static uint8_t const radix_shift[64] = {
+ 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned base)
+{
+ int shift;
+
+#ifdef USE_SPECIAL_RADIX_10
+ if (likely(base == 10))
+ return u32toa(buf, n);
+#endif
+ if (n < base) {
+ buf[0] = digits36[n];
+ buf[1] = '\0';
+ return 1;
+ }
+ shift = radix_shift[base & 63];
+ if (shift) {
+ uint32_t mask = (1 << shift) - 1;
+ size_t len = (32 - clz32(n) + shift - 1) / shift;
+ size_t last = n & mask;
+ char *end = buf + len;
+ n >>= shift;
+ *end-- = '\0';
+ *end-- = digits36[last];
+ while (n >= base) {
+ size_t quo = n & mask;
+ n >>= shift;
+ *end-- = digits36[quo];
+ }
+ *end = digits36[n];
+ return len;
+ } else {
+ size_t len = 2;
+ size_t last = n % base;
+ n /= base;
+ uint32_t nbase = base;
+ while (n >= nbase) {
+ nbase *= base;
+ len++;
+ }
+ char *end = buf + len;
+ *end-- = '\0';
+ *end-- = digits36[last];
+ while (n >= base) {
+ size_t quo = n % base;
+ n /= base;
+ *end-- = digits36[quo];
+ }
+ *end = digits36[n];
+ return len;
+ }
+}
+
+size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned base)
+{
+ int shift;
+
+#ifdef USE_SPECIAL_RADIX_10
+ if (likely(base == 10))
+ return u64toa(buf, n);
+#endif
+ shift = radix_shift[base & 63];
+ if (shift) {
+ if (n < base) {
+ buf[0] = digits36[n];
+ buf[1] = '\0';
+ return 1;
+ }
+ uint64_t mask = (1 << shift) - 1;
+ size_t len = (64 - clz64(n) + shift - 1) / shift;
+ size_t last = n & mask;
+ char *end = buf + len;
+ n >>= shift;
+ *end-- = '\0';
+ *end-- = digits36[last];
+ while (n >= base) {
+ size_t quo = n & mask;
+ n >>= shift;
+ *end-- = digits36[quo];
+ }
+ *end = digits36[n];
+ return len;
+ } else {
+ if (likely(n < 0x100000000))
+ return u32toa_radix(buf, n, base);
+ size_t last = n % base;
+ n /= base;
+ uint64_t nbase = base;
+ size_t len = 2;
+ while (n >= nbase) {
+ nbase *= base;
+ len++;
+ }
+ char *end = buf + len;
+ *end-- = '\0';
+ *end-- = digits36[last];
+ while (n >= base) {
+ size_t quo = n % base;
+ n /= base;
+ *end-- = digits36[quo];
+ }
+ *end = digits36[n];
+ return len;
+ }
+}
+
+size_t i32toa_radix(char buf[minimum_length(34)], int32_t n, unsigned int base)
+{
+ if (likely(n >= 0))
+ return u32toa_radix(buf, n, base);
+
+ buf[0] = '-';
+ return 1 + u32toa_radix(buf + 1, -(uint32_t)n, base);
+}
+
+size_t i64toa_radix(char buf[minimum_length(66)], int64_t n, unsigned int base)
+{
+ if (likely(n >= 0))
+ return u64toa_radix(buf, n, base);
+
+ buf[0] = '-';
+ return 1 + u64toa_radix(buf + 1, -(uint64_t)n, base);
+}
+
+#undef gen_digit
+#undef TEN_POW_7
+#undef USE_SPECIAL_RADIX_10
+#undef USE_SINGLE_CASE_FAST
+
+/*---- sorting with opaque argument ----*/
typedef void (*exchange_f)(void *a, void *b, size_t size);
typedef int (*cmp_f)(const void *, const void *, void *opaque);
@@ -627,4 +1132,285 @@ void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
}
}
+/*---- Portable time functions ----*/
+
+#ifdef _WIN32
+ // From: https://stackoverflow.com/a/26085827
+static int gettimeofday_msvc(struct timeval *tp)
+{
+ static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
+
+ SYSTEMTIME system_time;
+ FILETIME file_time;
+ uint64_t time;
+
+ GetSystemTime(&system_time);
+ SystemTimeToFileTime(&system_time, &file_time);
+ time = ((uint64_t)file_time.dwLowDateTime);
+ time += ((uint64_t)file_time.dwHighDateTime) << 32;
+
+ tp->tv_sec = (long)((time - EPOCH) / 10000000L);
+ tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
+
+ return 0;
+}
+
+uint64_t js__hrtime_ns(void) {
+ LARGE_INTEGER counter, frequency;
+ double scaled_freq;
+ double result;
+
+ if (!QueryPerformanceFrequency(&frequency))
+ abort();
+ assert(frequency.QuadPart != 0);
+
+ if (!QueryPerformanceCounter(&counter))
+ abort();
+ assert(counter.QuadPart != 0);
+
+ /* Because we have no guarantee about the order of magnitude of the
+ * performance counter interval, integer math could cause this computation
+ * to overflow. Therefore we resort to floating point math.
+ */
+ scaled_freq = (double) frequency.QuadPart / NANOSEC;
+ result = (double) counter.QuadPart / scaled_freq;
+ return (uint64_t) result;
+}
+#else
+uint64_t js__hrtime_ns(void) {
+ struct timespec t;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &t))
+ abort();
+
+ return t.tv_sec * NANOSEC + t.tv_nsec;
+}
+#endif
+
+int64_t js__gettimeofday_us(void) {
+ struct timeval tv;
+#ifdef _WIN32
+ gettimeofday_msvc(&tv);
+#else
+ gettimeofday(&tv, NULL);
+#endif
+ return ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
+}
+
+/*--- Cross-platform threading APIs. ----*/
+
+#if !defined(EMSCRIPTEN) && !defined(__wasi__)
+
+#if defined(_WIN32)
+typedef void (*js__once_cb)(void);
+
+typedef struct {
+ js__once_cb callback;
+} js__once_data_t;
+
+static int WINAPI js__once_inner(INIT_ONCE *once, void *param, void **context) {
+ js__once_data_t *data = param;
+
+ data->callback();
+
+ return 1;
+}
+
+void js_once(js_once_t *guard, js__once_cb callback) {
+ js__once_data_t data = { .callback = callback };
+ InitOnceExecuteOnce(guard, js__once_inner, (void*) &data, NULL);
+}
+
+void js_mutex_init(js_mutex_t *mutex) {
+ InitializeCriticalSection(mutex);
+}
+
+void js_mutex_destroy(js_mutex_t *mutex) {
+ DeleteCriticalSection(mutex);
+}
+
+void js_mutex_lock(js_mutex_t *mutex) {
+ EnterCriticalSection(mutex);
+}
+
+void js_mutex_unlock(js_mutex_t *mutex) {
+ LeaveCriticalSection(mutex);
+}
+
+void js_cond_init(js_cond_t *cond) {
+ InitializeConditionVariable(cond);
+}
+
+void js_cond_destroy(js_cond_t *cond) {
+ /* nothing to do */
+ (void) cond;
+}
+
+void js_cond_signal(js_cond_t *cond) {
+ WakeConditionVariable(cond);
+}
+
+void js_cond_broadcast(js_cond_t *cond) {
+ WakeAllConditionVariable(cond);
+}
+
+void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) {
+ if (!SleepConditionVariableCS(cond, mutex, INFINITE))
+ abort();
+}
+
+int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) {
+ if (SleepConditionVariableCS(cond, mutex, (DWORD)(timeout / 1e6)))
+ return 0;
+ if (GetLastError() != ERROR_TIMEOUT)
+ abort();
+ return -1;
+}
+
+#else /* !defined(_WIN32) */
+
+void js_once(js_once_t *guard, void (*callback)(void)) {
+ if (pthread_once(guard, callback))
+ abort();
+}
+
+void js_mutex_init(js_mutex_t *mutex) {
+ if (pthread_mutex_init(mutex, NULL))
+ abort();
+}
+
+void js_mutex_destroy(js_mutex_t *mutex) {
+ if (pthread_mutex_destroy(mutex))
+ abort();
+}
+
+void js_mutex_lock(js_mutex_t *mutex) {
+ if (pthread_mutex_lock(mutex))
+ abort();
+}
+
+void js_mutex_unlock(js_mutex_t *mutex) {
+ if (pthread_mutex_unlock(mutex))
+ abort();
+}
+
+void js_cond_init(js_cond_t *cond) {
+#if defined(__APPLE__) && defined(__MACH__)
+ if (pthread_cond_init(cond, NULL))
+ abort();
+#else
+ pthread_condattr_t attr;
+
+ if (pthread_condattr_init(&attr))
+ abort();
+
+ if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
+ abort();
+
+ if (pthread_cond_init(cond, &attr))
+ abort();
+
+ if (pthread_condattr_destroy(&attr))
+ abort();
+#endif
+}
+
+void js_cond_destroy(js_cond_t *cond) {
+#if defined(__APPLE__) && defined(__MACH__)
+ /* It has been reported that destroying condition variables that have been
+ * signalled but not waited on can sometimes result in application crashes.
+ * See https://codereview.chromium.org/1323293005.
+ */
+ pthread_mutex_t mutex;
+ struct timespec ts;
+ int err;
+
+ if (pthread_mutex_init(&mutex, NULL))
+ abort();
+
+ if (pthread_mutex_lock(&mutex))
+ abort();
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1;
+
+ err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts);
+ if (err != 0 && err != ETIMEDOUT)
+ abort();
+
+ if (pthread_mutex_unlock(&mutex))
+ abort();
+
+ if (pthread_mutex_destroy(&mutex))
+ abort();
+#endif /* defined(__APPLE__) && defined(__MACH__) */
+
+ if (pthread_cond_destroy(cond))
+ abort();
+}
+
+void js_cond_signal(js_cond_t *cond) {
+ if (pthread_cond_signal(cond))
+ abort();
+}
+
+void js_cond_broadcast(js_cond_t *cond) {
+ if (pthread_cond_broadcast(cond))
+ abort();
+}
+
+void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) {
+#if defined(__APPLE__) && defined(__MACH__)
+ int r;
+
+ errno = 0;
+ r = pthread_cond_wait(cond, mutex);
+
+ /* Workaround for a bug in OS X at least up to 13.6
+ * See https://github.com/libuv/libuv/issues/4165
+ */
+ if (r == EINVAL && errno == EBUSY)
+ return;
+ if (r)
+ abort();
+#else
+ if (pthread_cond_wait(cond, mutex))
+ abort();
+#endif
+}
+
+int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) {
+ int r;
+ struct timespec ts;
+
+#if !defined(__APPLE__)
+ timeout += js__hrtime_ns();
+#endif
+
+ ts.tv_sec = timeout / NANOSEC;
+ ts.tv_nsec = timeout % NANOSEC;
+#if defined(__APPLE__) && defined(__MACH__)
+ r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
+#else
+ r = pthread_cond_timedwait(cond, mutex, &ts);
+#endif
+
+ if (r == 0)
+ return 0;
+
+ if (r == ETIMEDOUT)
+ return -1;
+
+ abort();
+
+ /* Pacify some compilers. */
+ return -1;
+}
+
+#endif
+
+#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */
+
+#ifdef __GNUC__
+#pragma GCC visibility pop
#endif
diff --git a/src/shared/quickjs/cutils.h b/src/shared/quickjs/cutils.h
index 240f46663..5b98424b5 100644
--- a/src/shared/quickjs/cutils.h
+++ b/src/shared/quickjs/cutils.h
@@ -25,76 +25,109 @@
#ifndef CUTILS_H
#define CUTILS_H
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
+#include <math.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
#if defined(_MSC_VER)
-#include <intrin.h>
-#include <BaseTsd.h>
-typedef SSIZE_T ssize_t;
-#else
-#include <sys/types.h>
+#include <malloc.h>
+#define alloca _alloca
+#define ssize_t ptrdiff_t
+#endif
+#if defined(__APPLE__)
+#include <malloc/malloc.h>
+#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__)
+#include <malloc.h>
+#elif defined(__FreeBSD__)
+#include <malloc_np.h>
+#elif defined(_WIN32)
+#include <windows.h>
+#endif
+#if !defined(_WIN32) && !defined(EMSCRIPTEN) && !defined(__wasi__)
+#include <errno.h>
+#include <pthread.h>
#endif
-#ifdef __GNUC__
-#define likely(x) __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-#define force_inline inline __attribute__((always_inline))
-#define no_inline __attribute__((noinline))
-#define __maybe_unused __attribute__((unused))
+#if defined(_MSC_VER) && !defined(__clang__)
+# define likely(x) (x)
+# define unlikely(x) (x)
+# define force_inline __forceinline
+# define no_inline __declspec(noinline)
+# define __maybe_unused
+# define __attribute__(x)
+# define __attribute(x)
#else
-#define likely(x) (x)
-#define unlikely(x) (x)
-#define force_inline
-#define no_inline
-#define __maybe_unused
+# define likely(x) __builtin_expect(!!(x), 1)
+# define unlikely(x) __builtin_expect(!!(x), 0)
+# define force_inline inline __attribute__((always_inline))
+# define no_inline __attribute__((noinline))
+# define __maybe_unused __attribute__((unused))
#endif
-#ifdef _MSC_VER
-#define alloca _alloca
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <math.h>
+#define INF INFINITY
+#define NEG_INF -INFINITY
+#else
+#define INF (1.0/0.0)
+#define NEG_INF (-1.0/0.0)
#endif
-#define xglue(x, y) x ## y
-#define glue(x, y) xglue(x, y)
-#define stringify(s) tostring(s)
-#define tostring(s) #s
-
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#ifndef countof
#define countof(x) (sizeof(x) / sizeof((x)[0]))
+#ifndef endof
+#define endof(x) ((x) + countof(x))
+#endif
#endif
#ifndef container_of
/* return the pointer of type 'type *' containing 'ptr' as field 'member' */
#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
#endif
-#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-#define minimum_length(n) static n
+#if defined(_MSC_VER)
+#define minimum_length(n) n
#else
-#define minimum_length(n) n
+#define minimum_length(n) static n
#endif
-typedef int BOOL;
-
-#ifndef FALSE
-enum {
- FALSE = 0,
- TRUE = 1,
-};
+/* Borrowed from Folly */
+#ifndef JS_PRINTF_FORMAT
+#ifdef _MSC_VER
+#include <sal.h>
+#define JS_PRINTF_FORMAT _Printf_format_string_
+#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param)
+#else
+#define JS_PRINTF_FORMAT
+#if !defined(__clang__) && defined(__GNUC__)
+#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \
+ __attribute__((format(gnu_printf, format_param, dots_param)))
+#else
+#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \
+ __attribute__((format(printf, format_param, dots_param)))
+#endif
+#endif
#endif
-void pstrcpy(char *buf, int buf_size, const char *str);
-char *pstrcat(char *buf, int buf_size, const char *s);
-int strstart(const char *str, const char *val, const char **ptr);
-int has_suffix(const char *str, const char *suffix);
+void js__pstrcpy(char *buf, int buf_size, const char *str);
+char *js__pstrcat(char *buf, int buf_size, const char *s);
+int js__strstart(const char *str, const char *val, const char **ptr);
+int js__has_suffix(const char *str, const char *suffix);
-/* Prevent UB when n == 0 and (src == NULL or dest == NULL) */
-static inline void memcpy_no_ub(void *dest, const void *src, size_t n) {
- if (n)
- memcpy(dest, src, n);
+static inline uint8_t is_be(void) {
+ union {
+ uint16_t a;
+ uint8_t b;
+ } u = { 0x100 };
+ return u.b;
}
static inline int max_int(int a, int b)
@@ -148,12 +181,10 @@ static inline int64_t min_int64(int64_t a, int64_t b)
/* WARNING: undefined if a = 0 */
static inline int clz32(unsigned int a)
{
-#ifdef _MSC_VER
-#if defined(_M_ARM) || defined(_M_ARM64)
- return _CountLeadingZeros(a);
-#else
- return (int) __lzcnt(a);
-#endif
+#if defined(_MSC_VER) && !defined(__clang__)
+ unsigned long index;
+ _BitScanReverse(&index, a);
+ return 31 - index;
#else
return __builtin_clz(a);
#endif
@@ -162,11 +193,16 @@ static inline int clz32(unsigned int a)
/* WARNING: undefined if a = 0 */
static inline int clz64(uint64_t a)
{
-#ifdef _MSC_VER
-#if defined(_M_ARM) || defined(_M_ARM64)
- return _CountLeadingZeros64(a);
+#if defined(_MSC_VER) && !defined(__clang__)
+#if INTPTR_MAX == INT64_MAX
+ unsigned long index;
+ _BitScanReverse64(&index, a);
+ return 63 - index;
#else
- return (int) __lzcnt64(a);
+ if (a >> 32)
+ return clz32((unsigned)(a >> 32));
+ else
+ return clz32((unsigned)a) + 32;
#endif
#else
return __builtin_clzll(a);
@@ -176,12 +212,10 @@ static inline int clz64(uint64_t a)
/* WARNING: undefined if a = 0 */
static inline int ctz32(unsigned int a)
{
-#ifdef _MSC_VER
-#if defined(_M_ARM) || defined(_M_ARM64)
- return _CountTrailingZeros(a);
-#else
- return (int) _tzcnt_u32(a);
-#endif
+#if defined(_MSC_VER) && !defined(__clang__)
+ unsigned long index;
+ _BitScanForward(&index, a);
+ return index;
#else
return __builtin_ctz(a);
#endif
@@ -190,72 +224,70 @@ static inline int ctz32(unsigned int a)
/* WARNING: undefined if a = 0 */
static inline int ctz64(uint64_t a)
{
-#ifdef _MSC_VER
-#if defined(_M_ARM) || defined(_M_ARM64)
- return _CountTrailingZeros64(a);
-#else
- return (int) _tzcnt_u64(a);
-#endif
+#if defined(_MSC_VER) && !defined(__clang__)
+ unsigned long index;
+ _BitScanForward64(&index, a);
+ return index;
#else
return __builtin_ctzll(a);
#endif
}
-#pragma pack(push, 1)
-struct packed_u64 {
- uint64_t v;
-};
-struct packed_u32 {
- uint32_t v;
-};
-struct packed_u16 {
- uint16_t v;
-};
-#pragma pack(pop)
-
static inline uint64_t get_u64(const uint8_t *tab)
{
- return ((const struct packed_u64 *)tab)->v;
+ uint64_t v;
+ memcpy(&v, tab, sizeof(v));
+ return v;
}
static inline int64_t get_i64(const uint8_t *tab)
{
- return (int64_t)((const struct packed_u64 *)tab)->v;
+ int64_t v;
+ memcpy(&v, tab, sizeof(v));
+ return v;
}
static inline void put_u64(uint8_t *tab, uint64_t val)
{
- ((struct packed_u64 *)tab)->v = val;
+ memcpy(tab, &val, sizeof(val));
}
static inline uint32_t get_u32(const uint8_t *tab)
{
- return ((const struct packed_u32 *)tab)->v;
+ uint32_t v;
+ memcpy(&v, tab, sizeof(v));
+ return v;
}
static inline int32_t get_i32(const uint8_t *tab)
{
- return (int32_t)((const struct packed_u32 *)tab)->v;
+ int32_t v;
+ memcpy(&v, tab, sizeof(v));
+ return v;
}
static inline void put_u32(uint8_t *tab, uint32_t val)
{
- ((struct packed_u32 *)tab)->v = val;
+ memcpy(tab, &val, sizeof(val));
}
static inline uint32_t get_u16(const uint8_t *tab)
{
- return ((const struct packed_u16 *)tab)->v;
+ uint16_t v;
+ memcpy(&v, tab, sizeof(v));
+ return v;
}
static inline int32_t get_i16(const uint8_t *tab)
{
- return (int16_t)((const struct packed_u16 *)tab)->v;
+ int16_t v;
+ memcpy(&v, tab, sizeof(v));
+ return v;
}
static inline void put_u16(uint8_t *tab, uint16_t val)
{
- ((struct packed_u16 *)tab)->v = val;
+ memcpy(tab, &val, sizeof(val));
}
static inline uint32_t get_u8(const uint8_t *tab)
@@ -302,6 +334,89 @@ static inline uint64_t bswap64(uint64_t v)
}
#endif
+static inline void inplace_bswap16(uint8_t *tab) {
+ put_u16(tab, bswap16(get_u16(tab)));
+}
+
+static inline void inplace_bswap32(uint8_t *tab) {
+ put_u32(tab, bswap32(get_u32(tab)));
+}
+
+static inline double fromfp16(uint16_t v) {
+ double d, s;
+ int e;
+ if ((v & 0x7C00) == 0x7C00) {
+ d = (v & 0x3FF) ? NAN : INFINITY;
+ } else {
+ d = (v & 0x3FF) / 1024.;
+ e = (v & 0x7C00) >> 10;
+ if (e == 0) {
+ e = -14;
+ } else {
+ d += 1;
+ e -= 15;
+ }
+ d = scalbn(d, e);
+ }
+ s = (v & 0x8000) ? -1.0 : 1.0;
+ return d * s;
+}
+
+static inline uint16_t tofp16(double d) {
+ uint16_t f, s;
+ double t;
+ int e;
+ s = 0;
+ if (copysign(1, d) < 0) { // preserve sign when |d| is negative zero
+ d = -d;
+ s = 0x8000;
+ }
+ if (isinf(d))
+ return s | 0x7C00;
+ if (isnan(d))
+ return s | 0x7C01;
+ if (d == 0)
+ return s | 0;
+ d = 2 * frexp(d, &e);
+ e--;
+ if (e > 15)
+ return s | 0x7C00; // out of range, return +/-infinity
+ if (e < -25) {
+ d = 0;
+ e = 0;
+ } else if (e < -14) {
+ d = scalbn(d, e + 14);
+ e = 0;
+ } else {
+ d -= 1;
+ e += 15;
+ }
+ d *= 1024.;
+ f = (uint16_t)d;
+ t = d - f;
+ if (t < 0.5)
+ goto done;
+ if (t == 0.5)
+ if ((f & 1) == 0)
+ goto done;
+ // adjust for rounding
+ if (++f == 1024) {
+ f = 0;
+ if (++e == 31)
+ return s | 0x7C00; // out of range, return +/-infinity
+ }
+done:
+ return s | (e << 10) | f;
+}
+
+static inline int isfp16nan(uint16_t v) {
+ return (v & 0x7FFF) > 0x7C00;
+}
+
+static inline int isfp16zero(uint16_t v) {
+ return (v & 0x7FFF) == 0;
+}
+
/* XXX: should take an extra argument to pass slack information to the caller */
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
@@ -309,7 +424,7 @@ typedef struct DynBuf {
uint8_t *buf;
size_t size;
size_t allocated_size;
- BOOL error; /* true if a memory allocation error occurred */
+ bool error; /* true if a memory allocation error occurred */
DynBufReallocFunc *realloc_func;
void *opaque; /* for realloc_func */
} DynBuf;
@@ -317,8 +432,8 @@ typedef struct DynBuf {
void dbuf_init(DynBuf *s);
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
int dbuf_realloc(DynBuf *s, size_t new_size);
-int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
-int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
+int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len);
+int dbuf_put(DynBuf *s, const void *data, size_t len);
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
int dbuf_putc(DynBuf *s, uint8_t c);
int dbuf_putstr(DynBuf *s, const char *str);
@@ -334,40 +449,48 @@ static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
{
return dbuf_put(s, (uint8_t *)&val, 8);
}
-
-#ifdef __GNUC__
-#define FORMAT_ATTR(x, y) __attribute__((format(printf, x, y)))
-#else
-#define FORMAT_ATTR(x, y)
-#endif
-
-int FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, const char *fmt, ...);
-
+int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...);
void dbuf_free(DynBuf *s);
-static inline BOOL dbuf_error(DynBuf *s) {
+static inline bool dbuf_error(DynBuf *s) {
return s->error;
}
static inline void dbuf_set_error(DynBuf *s)
{
- s->error = TRUE;
+ s->error = true;
}
-#define UTF8_CHAR_LEN_MAX 6
+/*---- UTF-8 and UTF-16 handling ----*/
-int unicode_to_utf8(uint8_t *buf, unsigned int c);
-int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
+#define UTF8_CHAR_LEN_MAX 4
-static inline BOOL is_surrogate(uint32_t c)
+enum {
+ UTF8_PLAIN_ASCII = 0, // 7-bit ASCII plain text
+ UTF8_NON_ASCII = 1, // has non ASCII code points (8-bit or more)
+ UTF8_HAS_16BIT = 2, // has 16-bit code points
+ UTF8_HAS_NON_BMP1 = 4, // has non-BMP1 code points, needs UTF-16 surrogate pairs
+ UTF8_HAS_ERRORS = 8, // has encoding errors
+};
+int utf8_scan(const char *buf, size_t len, size_t *plen);
+size_t utf8_encode_len(uint32_t c);
+size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c);
+uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp);
+uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp);
+size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len);
+size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len);
+size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len);
+size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len);
+
+static inline bool is_surrogate(uint32_t c)
{
return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF
}
-static inline BOOL is_hi_surrogate(uint32_t c)
+static inline bool is_hi_surrogate(uint32_t c)
{
return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF
}
-static inline BOOL is_lo_surrogate(uint32_t c)
+static inline bool is_lo_surrogate(uint32_t c)
{
return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF
}
@@ -384,7 +507,7 @@ static inline uint32_t get_lo_surrogate(uint32_t c)
static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo)
{
- return 0x10000 + 0x400 * (hi - 0xD800) + (lo - 0xDC00);
+ return 65536 + 1024 * (hi & 1023) + (lo & 1023);
}
static inline int from_hex(int c)
@@ -399,8 +522,78 @@ static inline int from_hex(int c)
return -1;
}
+static inline uint8_t is_upper_ascii(uint8_t c) {
+ return c >= 'A' && c <= 'Z';
+}
+
+static inline uint8_t to_upper_ascii(uint8_t c) {
+ return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c;
+}
+
+extern char const digits36[36];
+size_t u32toa(char buf[minimum_length(11)], uint32_t n);
+size_t i32toa(char buf[minimum_length(12)], int32_t n);
+size_t u64toa(char buf[minimum_length(21)], uint64_t n);
+size_t i64toa(char buf[minimum_length(22)], int64_t n);
+size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned int base);
+size_t i32toa_radix(char buf[minimum_length(34)], int32_t n, unsigned base);
+size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned int base);
+size_t i64toa_radix(char buf[minimum_length(66)], int64_t n, unsigned int base);
+
void rqsort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *, void *),
void *arg);
+int64_t js__gettimeofday_us(void);
+uint64_t js__hrtime_ns(void);
+
+static inline size_t js__malloc_usable_size(const void *ptr)
+{
+#if defined(__APPLE__)
+ return malloc_size(ptr);
+#elif defined(_WIN32)
+ return _msize((void *)ptr);
+#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__) || defined(__FreeBSD__)
+ return malloc_usable_size((void *)ptr);
+#else
+ return 0;
+#endif
+}
+
+/* Cross-platform threading APIs. */
+
+#if !defined(EMSCRIPTEN) && !defined(__wasi__)
+
+#if defined(_WIN32)
+#define JS_ONCE_INIT INIT_ONCE_STATIC_INIT
+typedef INIT_ONCE js_once_t;
+typedef CRITICAL_SECTION js_mutex_t;
+typedef CONDITION_VARIABLE js_cond_t;
+#else
+#define JS_ONCE_INIT PTHREAD_ONCE_INIT
+typedef pthread_once_t js_once_t;
+typedef pthread_mutex_t js_mutex_t;
+typedef pthread_cond_t js_cond_t;
+#endif
+
+void js_once(js_once_t *guard, void (*callback)(void));
+
+void js_mutex_init(js_mutex_t *mutex);
+void js_mutex_destroy(js_mutex_t *mutex);
+void js_mutex_lock(js_mutex_t *mutex);
+void js_mutex_unlock(js_mutex_t *mutex);
+
+void js_cond_init(js_cond_t *cond);
+void js_cond_destroy(js_cond_t *cond);
+void js_cond_signal(js_cond_t *cond);
+void js_cond_broadcast(js_cond_t *cond);
+void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex);
+int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout);
+
+#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */
+
+#ifdef __cplusplus
+} /* extern "C" { */
+#endif
+
#endif /* CUTILS_H */
diff --git a/src/shared/quickjs/libbf.c b/src/shared/quickjs/libbf.c
index 56b2be861..26872c6df 100644
--- a/src/shared/quickjs/libbf.c
+++ b/src/shared/quickjs/libbf.c
@@ -134,7 +134,6 @@ static inline slimb_t ceil_div(slimb_t a, slimb_t b)
return a / b;
}
-#ifdef USE_BF_DEC
/* b must be >= 1 */
static inline slimb_t floor_div(slimb_t a, slimb_t b)
{
@@ -144,7 +143,6 @@ static inline slimb_t floor_div(slimb_t a, slimb_t b)
return (a - b + 1) / b;
}
}
-#endif
/* return r = a modulo b (0 <= r <= b - 1. b must be >= 1 */
static inline limb_t smod(slimb_t a, slimb_t b)
@@ -309,7 +307,8 @@ int bf_set(bf_t *r, const bf_t *a)
}
r->sign = a->sign;
r->expn = a->expn;
- memcpy_no_ub(r->tab, a->tab, a->len * sizeof(limb_t));
+ if (a->len > 0)
+ memcpy(r->tab, a->tab, a->len * sizeof(limb_t));
return 0;
}
@@ -647,20 +646,20 @@ int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags)
rounding */
int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k)
{
- BOOL is_rndn;
+ bool is_rndn;
slimb_t bit_pos, n;
limb_t bit;
if (a->expn == BF_EXP_INF || a->expn == BF_EXP_NAN)
- return FALSE;
+ return false;
if (rnd_mode == BF_RNDF) {
return (k >= (prec + 1));
}
if (a->expn == BF_EXP_ZERO)
- return FALSE;
+ return false;
is_rndn = (rnd_mode == BF_RNDN || rnd_mode == BF_RNDNA);
if (k < (prec + 2))
- return FALSE;
+ return false;
bit_pos = a->len * LIMB_BITS - 1 - prec;
n = k - prec;
/* bit pattern for RNDN or RNDNA: 0111.. or 1000...
@@ -673,11 +672,11 @@ int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k)
/* XXX: slow, but a few iterations on average */
while (n != 0) {
if (get_bit(a->tab, a->len, bit_pos) != bit)
- return TRUE;
+ return true;
bit_pos--;
n--;
}
- return FALSE;
+ return false;
}
/* Cannot fail with BF_ST_MEM_ERROR. */
@@ -956,20 +955,20 @@ static int bf_add_internal(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
i = r_len - tot_len;
while (i < 0) {
slimb_t ap, bp;
- BOOL inflag;
+ bool inflag;
ap = a_offset + i;
bp = b_bit_offset + i * LIMB_BITS;
- inflag = FALSE;
+ inflag = false;
if (ap >= 0 && ap < a->len) {
v1 = a->tab[ap];
- inflag = TRUE;
+ inflag = true;
} else {
v1 = 0;
}
if (bp + LIMB_BITS > 0 && bp < (slimb_t)(b->len * LIMB_BITS)) {
v2 = get_bits(b->tab, b->len, bp);
- inflag = TRUE;
+ inflag = true;
} else {
v2 = 0;
}
@@ -1602,9 +1601,7 @@ int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
r = &tmp;
}
if (bf_resize(r, a_len + b_len)) {
-#ifdef USE_FFT_MUL
fail:
-#endif
bf_set_nan(r);
ret = BF_ST_MEM_ERROR;
goto done;
@@ -1713,6 +1710,13 @@ static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
slimb_t d;
na = n + nb;
+
+#if LIMB_LOG2_BITS == 6
+ if (na >= (SIZE_MAX / sizeof(limb_t)) - 1) {
+ return BF_ST_MEM_ERROR; /* Return memory error status */
+ }
+#endif
+
taba = bf_malloc(s, (na + 1) * sizeof(limb_t));
if (!taba)
goto fail;
@@ -1754,7 +1758,7 @@ int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
bf_t a1_s, *a1 = &a1_s;
bf_t b1_s, *b1 = &b1_s;
int q_sign, ret;
- BOOL is_ceil, is_rndn;
+ bool is_ceil, is_rndn;
assert(q != a && q != b);
assert(r != a && r != b);
@@ -1781,7 +1785,7 @@ int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
case BF_RNDZ:
case BF_RNDN:
case BF_RNDNA:
- is_ceil = FALSE;
+ is_ceil = false;
break;
case BF_RNDD:
is_ceil = q_sign;
@@ -1790,7 +1794,7 @@ int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
is_ceil = q_sign ^ 1;
break;
case BF_RNDA:
- is_ceil = TRUE;
+ is_ceil = true;
break;
case BF_DIVREM_EUCLIDIAN:
is_ceil = a->sign;
@@ -2301,14 +2305,11 @@ static int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b,
bf_t a;
int ret;
-#ifdef USE_BF_DEC
if (a1 == 10 && b <= LIMB_DIGITS) {
/* use precomputed powers. We do not round at this point
because we expect the caller to do it */
ret = bf_set_ui(r, mp_pow_dec[b]);
- } else
-#endif
- {
+ } else {
bf_init(r->ctx, &a);
ret = bf_set_ui(&a, a1);
ret |= bf_pow_ui(r, &a, b, prec, flags);
@@ -2839,7 +2840,7 @@ int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
return ret;
}
-static inline int to_digit(int c)
+static inline int bf_to_digit(int c)
{
if (c >= '0' && c <= '9')
return c - '0';
@@ -2899,13 +2900,13 @@ static int strcasestart(const char *str, const char *val, const char **ptr)
static int bf_atof_internal(bf_t *r, slimb_t *pexponent,
const char *str, const char **pnext, int radix,
- limb_t prec, bf_flags_t flags, BOOL is_dec)
+ limb_t prec, bf_flags_t flags, bool is_dec)
{
const char *p, *p_start;
int is_neg, radix_bits, exp_is_neg, ret, digits_per_limb, shift;
limb_t cur_limb;
slimb_t pos, expn, int_len, digit_count;
- BOOL has_decpt, is_bin_exp;
+ bool has_decpt, is_bin_exp;
bf_t a_s, *a;
*pexponent = 0;
@@ -2946,7 +2947,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent,
goto no_prefix;
}
/* there must be a digit after the prefix */
- if (to_digit((uint8_t)*p) >= radix) {
+ if (bf_to_digit((uint8_t)*p) >= radix) {
bf_set_nan(r);
ret = 0;
goto done;
@@ -2990,18 +2991,18 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent,
cur_limb = 0;
bf_resize(a, 1);
pos = 0;
- has_decpt = FALSE;
+ has_decpt = false;
int_len = digit_count = 0;
for(;;) {
limb_t c;
- if (*p == '.' && (p > p_start || to_digit(p[1]) < radix)) {
+ if (*p == '.' && (p > p_start || bf_to_digit(p[1]) < radix)) {
if (has_decpt)
break;
- has_decpt = TRUE;
+ has_decpt = true;
int_len = digit_count;
p++;
}
- c = to_digit(*p);
+ c = bf_to_digit(*p);
if (c >= radix)
break;
digit_count++;
@@ -3066,7 +3067,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent,
/* parse the exponent, if any */
expn = 0;
- is_bin_exp = FALSE;
+ is_bin_exp = false;
if (((radix == 10 && (*p == 'e' || *p == 'E')) ||
(radix != 10 && (*p == '@' ||
(radix_bits && (*p == 'p' || *p == 'P'))))) &&
@@ -3082,7 +3083,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent,
}
for(;;) {
int c;
- c = to_digit(*p);
+ c = bf_to_digit(*p);
if (c >= 10)
break;
if (unlikely(expn > ((BF_RAW_EXP_MAX - 2 - 9) / 10))) {
@@ -3161,14 +3162,14 @@ int bf_atof2(bf_t *r, slimb_t *pexponent,
limb_t prec, bf_flags_t flags)
{
return bf_atof_internal(r, pexponent, str, pnext, radix, prec, flags,
- FALSE);
+ false);
}
int bf_atof(bf_t *r, const char *str, const char **pnext, int radix,
limb_t prec, bf_flags_t flags)
{
slimb_t dummy_exp;
- return bf_atof_internal(r, &dummy_exp, str, pnext, radix, prec, flags, FALSE);
+ return bf_atof_internal(r, &dummy_exp, str, pnext, radix, prec, flags, false);
}
/* base conversion to radix */
@@ -3339,7 +3340,7 @@ slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
{
int is_neg;
limb_t a;
- BOOL is_ceil;
+ bool is_ceil;
is_ceil = is_ceil1;
a = a1;
@@ -3509,7 +3510,7 @@ static int bf_integer_to_radix(bf_t *r, const bf_t *a, limb_t radixl)
static int bf_convert_to_radix(bf_t *r, slimb_t *pE,
const bf_t *a, int radix,
limb_t P, bf_rnd_t rnd_mode,
- BOOL is_fixed_exponent)
+ bool is_fixed_exponent)
{
slimb_t E, e, prec, extra_bits, ziv_extra_bits, prec0;
bf_t B_s, *B = &B_s;
@@ -3525,7 +3526,7 @@ static int bf_convert_to_radix(bf_t *r, slimb_t *pE,
E = *pE;
} else {
/* compute the new exponent */
- E = 1 + bf_mul_log2_radix(a->expn - 1, radix, TRUE, FALSE);
+ E = 1 + bf_mul_log2_radix(a->expn - 1, radix, true, false);
}
// bf_print_str("a", a);
// printf("E=%ld P=%ld radix=%d\n", E, P, radix);
@@ -3538,7 +3539,7 @@ static int bf_convert_to_radix(bf_t *r, slimb_t *pE,
e_sign = 1;
}
/* Note: precision for log2(radix) is not critical here */
- prec0 = bf_mul_log2_radix(P, radix, FALSE, TRUE);
+ prec0 = bf_mul_log2_radix(P, radix, false, true);
ziv_extra_bits = 16;
for(;;) {
prec = prec0 + ziv_extra_bits;
@@ -3631,12 +3632,12 @@ static void limb_to_a2(char *buf, limb_t n, unsigned int radix_bits, int len)
}
}
-/* 'a' must be an integer if the is_dec = FALSE or if the radix is not
+/* 'a' must be an integer if the is_dec = false or if the radix is not
a power of two. A dot is added before the 'dot_pos' digit. dot_pos
= n_digits does not display the dot. 0 <= dot_pos <=
n_digits. n_digits >= 1. */
static void output_digits(DynBuf *s, const bf_t *a1, int radix, limb_t n_digits,
- limb_t dot_pos, BOOL is_dec)
+ limb_t dot_pos, bool is_dec)
{
limb_t i, v, l;
slimb_t pos, pos_incr;
@@ -3720,7 +3721,7 @@ static void *bf_dbuf_realloc(void *opaque, void *ptr, size_t size)
/* return the length in bytes. A trailing '\0' is added */
static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix,
- limb_t prec, bf_flags_t flags, BOOL is_dec)
+ limb_t prec, bf_flags_t flags, bool is_dec)
{
bf_context_t *ctx = a2->ctx;
DynBuf s_s, *s = &s_s;
@@ -3809,11 +3810,11 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix,
a->sign = 0;
/* one more digit for the rounding */
- n = 1 + bf_mul_log2_radix(bf_max(a->expn, 0), radix, TRUE, TRUE);
+ n = 1 + bf_mul_log2_radix(bf_max(a->expn, 0), radix, true, true);
n_digits = n + prec;
n1 = n;
if (bf_convert_to_radix(a1, &n1, a, radix, n_digits,
- flags & BF_RND_MASK, TRUE))
+ flags & BF_RND_MASK, true))
goto fail1;
start = s->size;
output_digits(s, a1, radix, n_digits, n, is_dec);
@@ -3896,7 +3897,7 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix,
slimb_t n_digits_max, n_digits_min;
assert(prec != BF_PREC_INF);
- n_digits = 1 + bf_mul_log2_radix(prec, radix, TRUE, TRUE);
+ n_digits = 1 + bf_mul_log2_radix(prec, radix, true, true);
/* max number of digits for non exponential
notation. The rational is to have the same rule
as JS i.e. n_max = 21 for 64 bit float in base 10. */
@@ -3913,7 +3914,7 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix,
while (n_digits_min < n_digits_max) {
n_digits = (n_digits_min + n_digits_max) / 2;
if (bf_convert_to_radix(a1, &n, a, radix, n_digits,
- flags & BF_RND_MASK, FALSE)) {
+ flags & BF_RND_MASK, false)) {
bf_delete(b);
goto fail1;
}
@@ -3937,7 +3938,7 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix,
}
}
if (bf_convert_to_radix(a1, &n, a, radix, n_digits,
- flags & BF_RND_MASK, FALSE)) {
+ flags & BF_RND_MASK, false)) {
fail1:
bf_delete(a1);
goto fail;
@@ -3961,22 +3962,20 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix,
n = 1;
if ((flags & BF_FTOA_FORCE_EXP) ||
n <= -6 || n > n_max) {
- const char *fmt;
/* exponential notation */
output_digits(s, a1, radix, n_digits, 1, is_dec);
if (radix_bits != 0 && radix <= 16) {
+ slimb_t exp_n = (n - 1) * radix_bits;
if (flags & BF_FTOA_JS_QUIRKS)
- fmt = "p%+" PRId_LIMB;
+ dbuf_printf(s, "p%+" PRId_LIMB, exp_n);
else
- fmt = "p%" PRId_LIMB;
- dbuf_printf(s, fmt, (n - 1) * radix_bits);
+ dbuf_printf(s, "p%" PRId_LIMB, exp_n);
} else {
+ const char c = radix <= 10 ? 'e' : '@';
if (flags & BF_FTOA_JS_QUIRKS)
- fmt = "%c%+" PRId_LIMB;
+ dbuf_printf(s, "%c%+" PRId_LIMB, c, n - 1);
else
- fmt = "%c%" PRId_LIMB;
- dbuf_printf(s, fmt,
- radix <= 10 ? 'e' : '@', n - 1);
+ dbuf_printf(s, "%c%" PRId_LIMB, c, n - 1);
}
} else if (n <= 0) {
/* 0.x */
@@ -4016,7 +4015,7 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix,
char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
bf_flags_t flags)
{
- return bf_ftoa_internal(plen, a, radix, prec, flags, FALSE);
+ return bf_ftoa_internal(plen, a, radix, prec, flags, false);
}
/***************************************************************/
@@ -4024,7 +4023,7 @@ char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
/* Note: the algorithm is from MPFR */
static void bf_const_log2_rec(bf_t *T, bf_t *P, bf_t *Q, limb_t n1,
- limb_t n2, BOOL need_P)
+ limb_t n2, bool need_P)
{
bf_context_t *s = T->ctx;
if ((n2 - n1) == 1) {
@@ -4044,7 +4043,7 @@ static void bf_const_log2_rec(bf_t *T, bf_t *P, bf_t *Q, limb_t n1,
bf_t Q1_s, *Q1 = &Q1_s;
m = n1 + ((n2 - n1) >> 1);
- bf_const_log2_rec(T, P, Q, n1, m, TRUE);
+ bf_const_log2_rec(T, P, Q, n1, m, true);
bf_init(s, T1);
bf_init(s, P1);
bf_init(s, Q1);
@@ -4072,7 +4071,7 @@ static void bf_const_log2_internal(bf_t *T, limb_t prec)
N = w / 3 + 1;
bf_init(T->ctx, P);
bf_init(T->ctx, Q);
- bf_const_log2_rec(T, P, Q, 0, N, FALSE);
+ bf_const_log2_rec(T, P, Q, 0, N, false);
bf_div(T, T, Q, prec, BF_RNDN);
bf_delete(P);
bf_delete(Q);
@@ -4634,10 +4633,10 @@ static int bf_pow_int(bf_t *r, const bf_t *x, limb_t prec, void *opaque)
return ret;
}
-/* x must be a finite non zero float. Return TRUE if there is a
+/* x must be a finite non zero float. Return true if there is a
floating point number r such as x=r^(2^n) and return this floating
- point number 'r'. Otherwise return FALSE and r is undefined. */
-static BOOL check_exact_power2n(bf_t *r, const bf_t *x, slimb_t n)
+ point number 'r'. Otherwise return false and r is undefined. */
+static bool check_exact_power2n(bf_t *r, const bf_t *x, slimb_t n)
{
bf_context_t *s = r->ctx;
bf_t T_s, *T = &T_s;
@@ -4649,17 +4648,17 @@ static BOOL check_exact_power2n(bf_t *r, const bf_t *x, slimb_t n)
/* fast check on the exponent */
if (n > (LIMB_BITS - 1)) {
if (e != 0)
- return FALSE;
+ return false;
er = 0;
} else {
if ((e & (((limb_t)1 << n) - 1)) != 0)
- return FALSE;
+ return false;
er = e >> n;
}
/* every perfect odd square = 1 modulo 8 */
v = get_bits(x->tab, x->len, x->len * LIMB_BITS - x->expn + e);
if ((v & 7) != 1)
- return FALSE;
+ return false;
bf_init(s, T);
bf_set(T, x);
@@ -4668,10 +4667,10 @@ static BOOL check_exact_power2n(bf_t *r, const bf_t *x, slimb_t n)
if (i != 0)
bf_set(T, r);
if (bf_sqrtrem(r, NULL, T) != 0)
- return FALSE;
+ return false;
}
r->expn += er;
- return TRUE;
+ return true;
}
/* prec = BF_PREC_INF is accepted for x and y integers and y >= 0 */
@@ -4680,7 +4679,7 @@ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags)
bf_context_t *s = r->ctx;
bf_t T_s, *T = &T_s;
bf_t ytmp_s;
- BOOL y_is_int, y_is_odd;
+ bool y_is_int, y_is_odd;
int r_sign, ret, rnd_mode;
slimb_t y_emin;
@@ -4820,11 +4819,6 @@ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags)
bf_t *y1;
if (y_emin < 0 && check_exact_power2n(r, T, -y_emin)) {
/* the problem is reduced to a power to an integer */
-#if 0
- printf("\nn=%" PRId64 "\n", -(int64_t)y_emin);
- bf_print_str("T", T);
- bf_print_str("r", r);
-#endif
bf_set(T, r);
y1 = &ytmp_s;
y1->tab = y->tab;
@@ -5076,7 +5070,7 @@ static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec,
void *opaque)
{
bf_context_t *s = r->ctx;
- BOOL add_pi2 = (BOOL)(intptr_t)opaque;
+ bool add_pi2 = (bool)(intptr_t)opaque;
bf_t T_s, *T = &T_s;
bf_t U_s, *U = &U_s;
bf_t V_s, *V = &V_s;
@@ -5201,7 +5195,7 @@ int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
}
}
- return bf_ziv_rounding(r, a, prec, flags, bf_atan_internal, (void *)FALSE);
+ return bf_ziv_rounding(r, a, prec, flags, bf_atan_internal, (void *)false);
}
static int bf_atan2_internal(bf_t *r, const bf_t *y, limb_t prec, void *opaque)
@@ -5251,7 +5245,7 @@ int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
static int bf_asin_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque)
{
bf_context_t *s = r->ctx;
- BOOL is_acos = (BOOL)(intptr_t)opaque;
+ bool is_acos = (bool)(intptr_t)opaque;
bf_t T_s, *T = &T_s;
limb_t prec1, prec2;
@@ -5317,7 +5311,7 @@ int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
}
}
- return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)FALSE);
+ return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)false);
}
int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
@@ -5351,7 +5345,7 @@ int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
return 0;
}
- return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)TRUE);
+ return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)true);
}
/***************************************************************/
@@ -5376,19 +5370,20 @@ int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
#if LIMB_BITS == 64
/* Note: we assume __int128 is available */
+/* uint128_t defined in libbf.h */
#define muldq(r1, r0, a, b) \
do { \
- unsigned __int128 __t; \
- __t = (unsigned __int128)(a) * (unsigned __int128)(b); \
+ uint128_t __t; \
+ __t = (uint128_t)(a) * (uint128_t)(b); \
r0 = __t; \
r1 = __t >> 64; \
} while (0)
#define divdq(q, r, a1, a0, b) \
do { \
- unsigned __int128 __t; \
+ uint128_t __t; \
limb_t __b = (b); \
- __t = ((unsigned __int128)(a1) << 64) | (a0); \
+ __t = ((uint128_t)(a1) << 64) | (a0); \
q = __t / __b; \
r = __t % __b; \
} while (0)
@@ -5497,7 +5492,6 @@ static inline limb_t fast_udiv(limb_t a, const FastDivData *s)
return (t1 + t0) >> s->shift2;
}
-#endif // USE_BF_DEC
/* contains 10^i */
const limb_t mp_pow_dec[LIMB_DIGITS + 1] = {
1U,
@@ -5523,7 +5517,6 @@ const limb_t mp_pow_dec[LIMB_DIGITS + 1] = {
10000000000000000000U,
#endif
};
-#ifdef USE_BF_DEC
/* precomputed from fast_udiv_init(10^i) */
static const FastDivData mp_pow_div[LIMB_DIGITS + 1] = {
@@ -6335,34 +6328,6 @@ static limb_t get_digit(const limb_t *tab, limb_t len, slimb_t pos)
return fast_shr_dec(tab[i], shift) % 10;
}
-#if 0
-static limb_t get_digits(const limb_t *tab, limb_t len, slimb_t pos)
-{
- limb_t a0, a1;
- int shift;
- slimb_t i;
-
- i = floor_div(pos, LIMB_DIGITS);
- shift = pos - i * LIMB_DIGITS;
- if (i >= 0 && i < len)
- a0 = tab[i];
- else
- a0 = 0;
- if (shift == 0) {
- return a0;
- } else {
- i++;
- if (i >= 0 && i < len)
- a1 = tab[i];
- else
- a1 = 0;
- return fast_shr_dec(a0, shift) +
- fast_urem(a1, &mp_pow_div[LIMB_DIGITS - shift]) *
- mp_pow_dec[shift];
- }
-}
-#endif
-
/* return the addend for rounding. Note that prec can be <= 0 for bf_rint() */
static int bfdec_get_rnd_add(int *pret, const bfdec_t *r, limb_t l,
slimb_t prec, int rnd_mode)
@@ -6963,7 +6928,7 @@ int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
bfdec_t b1_s, *b1 = &b1_s;
bfdec_t r1_s, *r1 = &r1_s;
int q_sign, res;
- BOOL is_ceil, is_rndn;
+ bool is_ceil, is_rndn;
assert(q != a && q != b);
assert(r != a && r != b);
@@ -6990,7 +6955,7 @@ int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
case BF_RNDZ:
case BF_RNDN:
case BF_RNDNA:
- is_ceil = FALSE;
+ is_ceil = false;
break;
case BF_RNDD:
is_ceil = q_sign;
@@ -6999,7 +6964,7 @@ int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
is_ceil = q_sign ^ 1;
break;
case BF_RNDA:
- is_ceil = TRUE;
+ is_ceil = true;
break;
case BF_DIVREM_EUCLIDIAN:
is_ceil = a->sign;
@@ -7229,7 +7194,7 @@ int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b)
char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags)
{
- return bf_ftoa_internal(plen, (const bf_t *)a, 10, prec, flags, TRUE);
+ return bf_ftoa_internal(plen, (const bf_t *)a, 10, prec, flags, true);
}
int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
@@ -7237,7 +7202,7 @@ int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
{
slimb_t dummy_exp;
return bf_atof_internal((bf_t *)r, &dummy_exp, str, pnext, 10, prec,
- flags, TRUE);
+ flags, true);
}
#endif /* USE_BF_DEC */
@@ -7989,12 +7954,6 @@ static no_inline void limb_to_ntt(BFNTTState *s,
int j, shift;
limb_t base_mask1, a0, a1, a2, r, m, m_inv;
-#if 0
- for(i = 0; i < a_len; i++) {
- printf("%" PRId64 ": " FMT_LIMB "\n",
- (int64_t)i, taba[i]);
- }
-#endif
memset(tabr, 0, sizeof(NTTLimb) * fft_len * nb_mods);
shift = dpl & (LIMB_BITS - 1);
if (shift == 0)
@@ -8121,14 +8080,6 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len,
}
u[l] = r + carry[l];
-#if 0
- printf("%" PRId64 ": ", i);
- for(j = nb_mods - 1; j >= 0; j--) {
- printf(" %019" PRIu64, u[j]);
- }
- printf("\n");
-#endif
-
/* write the digits */
pos = i * dpl;
for(j = 0; j < n_limb1; j++) {
@@ -8222,14 +8173,6 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len,
}
u[l] = r + carry[l];
-#if 0
- printf("%" PRId64 ": ", (int64_t)i);
- for(j = nb_mods - 1; j >= 0; j--) {
- printf(" " FMT_LIMB, u[j]);
- }
- printf("\n");
-#endif
-
/* write the digits */
pos = i * dpl;
for(j = 0; j < n_limb1; j++) {
@@ -8473,3 +8416,7 @@ int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len)
}
#endif /* !USE_FFT_MUL */
+
+#undef malloc
+#undef free
+#undef realloc
diff --git a/src/shared/quickjs/libbf.h b/src/shared/quickjs/libbf.h
index b247952b1..3586532e8 100644
--- a/src/shared/quickjs/libbf.h
+++ b/src/shared/quickjs/libbf.h
@@ -1,6 +1,6 @@
/*
* Tiny arbitrary precision floating point library
- *
+ *
* Copyright (c) 2017-2021 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -31,7 +31,7 @@
extern "C" {
#endif
-#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX)
+#if INTPTR_MAX >= INT64_MAX && !defined(_WIN32) && !defined(__TINYC__)
#define LIMB_LOG2_BITS 6
#else
#define LIMB_LOG2_BITS 5
@@ -40,8 +40,10 @@ extern "C" {
#define LIMB_BITS (1 << LIMB_LOG2_BITS)
#if LIMB_BITS == 64
-typedef __int128 int128_t;
-typedef unsigned __int128 uint128_t;
+#ifndef INT128_MAX
+__extension__ typedef __int128 int128_t;
+__extension__ typedef unsigned __int128 uint128_t;
+#endif
typedef int64_t slimb_t;
typedef uint64_t limb_t;
typedef uint128_t dlimb_t;
@@ -175,7 +177,7 @@ static inline bf_flags_t bf_set_exp_bits(int n)
#define BF_ST_UNDERFLOW (1 << 3)
#define BF_ST_INEXACT (1 << 4)
/* indicate that a memory allocation error occured. NaN is returned */
-#define BF_ST_MEM_ERROR (1 << 5)
+#define BF_ST_MEM_ERROR (1 << 5)
#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
@@ -288,7 +290,7 @@ int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags)
int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
-int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
+int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
@@ -345,12 +347,12 @@ int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
/* fractional format: prec digits after the decimal point rounded with
(flags & BF_RND_MASK) */
#define BF_FTOA_FORMAT_FRAC (1 << 16)
-/* free format:
-
+/* free format:
+
For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum
number of digits to represent 'a'. The precision and the rounding
mode are ignored.
-
+
For the non binary radices with bf_ftoa(): use as many digits as
necessary so that bf_atof() return the same number when using
precision 'prec', rounding to nearest and the subnormal
@@ -377,7 +379,7 @@ char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
bf_flags_t flags);
/* modulo 2^n instead of saturation. NaN and infinity return 0 */
-#define BF_GET_INT_MOD (1 << 0)
+#define BF_GET_INT_MOD (1 << 0)
int bf_get_int32(int *pres, const bf_t *a, int flags);
int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
int bf_get_uint64(uint64_t *pres, const bf_t *a);
@@ -391,10 +393,10 @@ int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
int is_ceil1);
-int mp_mul(bf_context_t *s, limb_t *result,
- const limb_t *op1, limb_t op1_size,
+int mp_mul(bf_context_t *s, limb_t *result,
+ const limb_t *op1, limb_t op1_size,
const limb_t *op2, limb_t op2_size);
-limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
+limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
limb_t n, limb_t carry);
limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n);
int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
diff --git a/src/shared/quickjs/libregexp-opcode.h b/src/shared/quickjs/libregexp-opcode.h
index f255e09f2..5c1714ab0 100644
--- a/src/shared/quickjs/libregexp-opcode.h
+++ b/src/shared/quickjs/libregexp-opcode.h
@@ -25,7 +25,8 @@
#ifdef DEF
DEF(invalid, 1) /* never used */
-DEF(char, 3)
+DEF(char8, 2) /* 7 bits in fact */
+DEF(char16, 3)
DEF(char32, 5)
DEF(dot, 1)
DEF(any, 1) /* same as dot but match any character including line terminator */
diff --git a/src/shared/quickjs/libregexp.c b/src/shared/quickjs/libregexp.c
index 4db042941..04c2888a8 100644
--- a/src/shared/quickjs/libregexp.c
+++ b/src/shared/quickjs/libregexp.c
@@ -30,7 +30,6 @@
#include "cutils.h"
#include "libregexp.h"
-#include "libunicode.h"
/*
TODO:
@@ -61,15 +60,17 @@ typedef enum {
#define TMP_BUF_SIZE 128
+// invariant: is_unicode ^ unicode_sets (or neither, but not both)
typedef struct {
DynBuf byte_code;
const uint8_t *buf_ptr;
const uint8_t *buf_end;
const uint8_t *buf_start;
int re_flags;
- BOOL is_unicode;
- BOOL ignore_case;
- BOOL dotall;
+ bool is_unicode;
+ bool unicode_sets;
+ bool ignore_case;
+ bool dotall;
int capture_count;
int total_capture_count; /* -1 = not computed yet */
int has_named_captures; /* -1 = don't know, 0 = no, 1 = yes */
@@ -99,13 +100,13 @@ static const REOpCode reopcode_info[REOP_COUNT] = {
};
#define RE_HEADER_FLAGS 0
-#define RE_HEADER_CAPTURE_COUNT 1
-#define RE_HEADER_STACK_SIZE 2
-#define RE_HEADER_BYTECODE_LEN 3
+#define RE_HEADER_CAPTURE_COUNT 2
+#define RE_HEADER_STACK_SIZE 3
+#define RE_HEADER_BYTECODE_LEN 4
-#define RE_HEADER_LEN 7
+#define RE_HEADER_LEN 8
-static inline int is_digit(int c) {
+static inline int lre_is_digit(int c) {
return c >= '0' && c <= '9';
}
@@ -142,6 +143,32 @@ static const uint16_t char_range_s[] = {
0xFEFF, 0xFEFF + 1,
};
+bool lre_is_space(int c)
+{
+ int i, n, low, high;
+ n = (countof(char_range_s) - 1) / 2;
+ for(i = 0; i < n; i++) {
+ low = char_range_s[2 * i + 1];
+ if (c < low)
+ return false;
+ high = char_range_s[2 * i + 2];
+ if (c < high)
+ return true;
+ }
+ return false;
+}
+
+uint32_t const lre_id_start_table_ascii[4] = {
+ /* $ A-Z _ a-z */
+ 0x00000000, 0x00000010, 0x87FFFFFE, 0x07FFFFFE
+};
+
+uint32_t const lre_id_continue_table_ascii[4] = {
+ /* $ 0-9 A-Z _ a-z */
+ 0x00000000, 0x03FF0010, 0x87FFFFFE, 0x07FFFFFE
+};
+
+
static const uint16_t char_range_w[] = {
4,
0x0030, 0x0039 + 1,
@@ -161,7 +188,7 @@ typedef enum {
CHAR_RANGE_W,
} CharRangeEnum;
-static const uint16_t * const char_range_table[] = {
+static const uint16_t *char_range_table[] = {
char_range_d,
char_range_s,
char_range_w,
@@ -169,7 +196,7 @@ static const uint16_t * const char_range_table[] = {
static int cr_init_char_range(REParseState *s, CharRange *cr, uint32_t c)
{
- BOOL invert;
+ bool invert;
const uint16_t *c_pt;
int len, i;
@@ -236,15 +263,15 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf,
}
printf("%s", reopcode_info[opcode].name);
switch(opcode) {
- case REOP_char:
+ case REOP_char8:
+ val = get_u8(buf + pos + 1);
+ goto printchar;
+ case REOP_char16:
val = get_u16(buf + pos + 1);
- if (val >= ' ' && val <= 126)
- printf(" '%c'", val);
- else
- printf(" 0x%04x", val);
- break;
+ goto printchar;
case REOP_char32:
val = get_u32(buf + pos + 1);
+ printchar:
if (val >= ' ' && val <= 126)
printf(" '%c'", val);
else
@@ -347,7 +374,7 @@ static void re_emit_op_u16(REParseState *s, int op, uint32_t val)
dbuf_put_u16(&s->byte_code, val);
}
-static int FORMAT_ATTR(2, 3) re_parse_error(REParseState *s, const char *fmt, ...)
+static int JS_PRINTF_FORMAT_ATTR(2, 3) re_parse_error(REParseState *s, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@@ -363,7 +390,7 @@ static int re_parse_out_of_memory(REParseState *s)
/* If allow_overflow is false, return -1 in case of
overflow. Otherwise return INT32_MAX. */
-static int parse_digits(const uint8_t **pp, BOOL allow_overflow)
+static int parse_digits(const uint8_t **pp, bool allow_overflow)
{
const uint8_t *p;
uint64_t v;
@@ -494,7 +521,7 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16)
c -= '0';
if (allow_utf16 == 2) {
/* only accept \0 not followed by digit */
- if (c != 0 || is_digit(*p))
+ if (c != 0 || lre_is_digit(*p))
return -1;
} else {
/* parse a legacy octal sequence */
@@ -520,9 +547,8 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16)
return c;
}
-#ifdef CONFIG_ALL_UNICODE
/* XXX: we use the same chars for name and value */
-static BOOL is_unicode_char(int c)
+static bool is_unicode_char(int c)
{
return ((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
@@ -531,12 +557,12 @@ static BOOL is_unicode_char(int c)
}
static int parse_unicode_property(REParseState *s, CharRange *cr,
- const uint8_t **pp, BOOL is_inv)
+ const uint8_t **pp, bool is_inv)
{
const uint8_t *p;
char name[64], value[64];
char *q;
- BOOL script_ext;
+ bool script_ext;
int ret;
p = *pp;
@@ -566,10 +592,10 @@ static int parse_unicode_property(REParseState *s, CharRange *cr,
// printf("name=%s value=%s\n", name, value);
if (!strcmp(name, "Script") || !strcmp(name, "sc")) {
- script_ext = FALSE;
+ script_ext = false;
goto do_script;
} else if (!strcmp(name, "Script_Extensions") || !strcmp(name, "scx")) {
- script_ext = TRUE;
+ script_ext = true;
do_script:
cr_init(cr, s->opaque, lre_realloc);
ret = unicode_script(cr, value, script_ext);
@@ -623,15 +649,14 @@ static int parse_unicode_property(REParseState *s, CharRange *cr,
out_of_memory:
return re_parse_out_of_memory(s);
}
-#endif /* CONFIG_ALL_UNICODE */
/* return -1 if error otherwise the character or a class range
(CLASS_RANGE_BASE). In case of class range, 'cr' is
initialized. Otherwise, it is ignored. */
static int get_class_atom(REParseState *s, CharRange *cr,
- const uint8_t **pp, BOOL inclass)
+ const uint8_t **pp, bool inclass)
{
- const uint8_t *p;
+ const uint8_t *p, *p_next;
uint32_t c;
int ret;
@@ -683,7 +708,6 @@ static int get_class_atom(REParseState *s, CharRange *cr,
c = '\\';
}
break;
-#ifdef CONFIG_ALL_UNICODE
case 'p':
case 'P':
if (s->is_unicode) {
@@ -693,7 +717,6 @@ static int get_class_atom(REParseState *s, CharRange *cr,
break;
}
/* fall thru */
-#endif
default:
p--;
ret = lre_parse_escape(&p, s->is_unicode * 2);
@@ -704,6 +727,9 @@ static int get_class_atom(REParseState *s, CharRange *cr,
/* always valid to escape these characters */
goto normal_char;
} else if (s->is_unicode) {
+ // special case: allowed inside [] but not outside
+ if (ret == -2 && *p == '-' && inclass)
+ goto normal_char;
invalid_escape:
return re_parse_error(s, "invalid escape sequence in regular expression");
} else {
@@ -722,15 +748,18 @@ static int get_class_atom(REParseState *s, CharRange *cr,
/* fall thru */
default:
normal_char:
- /* normal char */
- if (c >= 128) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
- if ((unsigned)c > 0xffff && !s->is_unicode) {
- /* XXX: should handle non BMP-1 code points */
+ p++;
+ if (c >= 0x80) {
+ c = utf8_decode(p - 1, &p_next);
+ if (p_next == p)
+ return re_parse_error(s, "invalid UTF-8 sequence");
+ p = p_next;
+ if (c > 0xFFFF && !s->is_unicode) {
+ // TODO(chqrlie): should handle non BMP-1 code points in
+ // the calling function and no require the source string
+ // to be CESU-8 encoded if not s->is_unicode
return re_parse_error(s, "malformed unicode char");
}
- } else {
- p++;
}
break;
}
@@ -776,30 +805,56 @@ static int re_emit_range(REParseState *s, const CharRange *cr)
return 0;
}
+// s->unicode turns patterns like []] into syntax errors
+// s->unicode_sets turns more patterns into errors, like [a-] or [[]
static int re_parse_char_class(REParseState *s, const uint8_t **pp)
{
const uint8_t *p;
uint32_t c1, c2;
CharRange cr_s, *cr = &cr_s;
CharRange cr1_s, *cr1 = &cr1_s;
- BOOL invert;
+ bool invert;
cr_init(cr, s->opaque, lre_realloc);
p = *pp;
p++; /* skip '[' */
- invert = FALSE;
+ if (s->unicode_sets) {
+ static const char verboten[] =
+ "()[{}/-|" "\0"
+ "&&!!##$$%%**++,,..::;;<<==>>??@@``~~" "\0"
+ "^^^_^^";
+ const char *s = verboten;
+ int n = 1;
+ do {
+ if (!memcmp(s, p, n))
+ if (p[n] == ']')
+ goto invalid_class_range;
+ s += n;
+ if (!*s) {
+ s++;
+ n++;
+ }
+ } while (n < 4);
+ }
+
+ invert = false;
if (*p == '^') {
p++;
- invert = TRUE;
+ invert = true;
}
for(;;) {
if (*p == ']')
break;
- c1 = get_class_atom(s, cr1, &p, TRUE);
+ c1 = get_class_atom(s, cr1, &p, true);
if ((int)c1 < 0)
goto fail;
+ if (*p == '-' && p[1] == ']' && s->unicode_sets) {
+ if (c1 >= CLASS_RANGE_BASE)
+ cr_free(cr1);
+ goto invalid_class_range;
+ }
if (*p == '-' && p[1] != ']') {
const uint8_t *p0 = p + 1;
if (c1 >= CLASS_RANGE_BASE) {
@@ -810,7 +865,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
/* Annex B: match '-' character */
goto class_atom;
}
- c2 = get_class_atom(s, cr1, &p0, TRUE);
+ c2 = get_class_atom(s, cr1, &p0, true);
if ((int)c2 < 0)
goto fail;
if (c2 >= CLASS_RANGE_BASE) {
@@ -868,14 +923,15 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
- true if the opcodes may not advance the char pointer
- false if the opcodes always advance the char pointer
*/
-static BOOL re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len)
+static bool re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len)
{
int pos, opcode, len;
uint32_t val;
- BOOL ret;
+ bool ret;
- ret = TRUE;
+ ret = true;
pos = 0;
+
while (pos < bc_buf_len) {
opcode = bc_buf[pos];
len = reopcode_info[opcode].size;
@@ -888,12 +944,13 @@ static BOOL re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len)
val = get_u16(bc_buf + pos + 1);
len += val * 8;
goto simple_char;
- case REOP_char:
case REOP_char32:
+ case REOP_char16:
+ case REOP_char8:
case REOP_dot:
case REOP_any:
simple_char:
- ret = FALSE;
+ ret = false;
break;
case REOP_line_start:
case REOP_line_end:
@@ -912,8 +969,8 @@ static BOOL re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len)
case REOP_backward_back_reference:
break;
default:
- /* safe behavior: we cannot predict the outcome */
- return TRUE;
+ /* safe behvior: we cannot predict the outcome */
+ return true;
}
pos += len;
}
@@ -941,8 +998,9 @@ static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len)
val = get_u16(bc_buf + pos + 1);
len += val * 8;
goto simple_char;
- case REOP_char:
case REOP_char32:
+ case REOP_char16:
+ case REOP_char8:
case REOP_dot:
case REOP_any:
simple_char:
@@ -964,35 +1022,35 @@ static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len)
/* '*pp' is the first char after '<' */
static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp)
{
- const uint8_t *p, *p1;
+ const uint8_t *p, *p_next;
uint32_t c, d;
char *q;
p = *pp;
q = buf;
for(;;) {
- c = *p;
+ c = *p++;
if (c == '\\') {
- p++;
if (*p != 'u')
return -1;
c = lre_parse_escape(&p, 2); // accept surrogate pairs
+ if ((int)c < 0)
+ return -1;
} else if (c == '>') {
break;
- } else if (c >= 128) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
+ } else if (c >= 0x80) {
+ c = utf8_decode(p - 1, &p_next);
+ if (p_next == p)
+ return -1;
+ p = p_next;
if (is_hi_surrogate(c)) {
- d = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);
+ d = utf8_decode(p, &p_next);
if (is_lo_surrogate(d)) {
c = from_surrogate(c, d);
- p = p1;
+ p = p_next;
}
}
- } else {
- p++;
}
- if (c > 0x10FFFF)
- return -1;
if (q == buf) {
if (!lre_js_is_ident_first(c))
return -1;
@@ -1002,16 +1060,15 @@ static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp)
}
if ((q - buf + UTF8_CHAR_LEN_MAX + 1) > buf_size)
return -1;
- if (c < 128) {
+ if (c < 0x80) {
*q++ = c;
} else {
- q += unicode_to_utf8((uint8_t*)q, c);
+ q += utf8_encode((uint8_t*)q, c);
}
}
if (q == buf)
return -1;
*q = '\0';
- p++;
*pp = p;
return 0;
}
@@ -1079,7 +1136,7 @@ static int re_count_captures(REParseState *s)
return s->total_capture_count;
}
-static BOOL re_has_named_captures(REParseState *s)
+static bool re_has_named_captures(REParseState *s)
{
if (s->has_named_captures < 0)
re_count_captures(s);
@@ -1107,13 +1164,13 @@ static int find_group_name(REParseState *s, const char *name)
return -1;
}
-static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir);
+static int re_parse_disjunction(REParseState *s, bool is_backward_dir);
-static int re_parse_term(REParseState *s, BOOL is_backward_dir)
+static int re_parse_term(REParseState *s, bool is_backward_dir)
{
const uint8_t *p;
int c, last_atom_start, quant_min, quant_max, last_capture_count;
- BOOL greedy, add_zero_advance_check, is_neg, is_backward_lookahead;
+ bool greedy, add_zero_advance_check, is_neg, is_backward_lookahead;
CharRange cr_s, *cr = &cr_s;
last_atom_start = -1;
@@ -1142,18 +1199,18 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
case '{':
if (s->is_unicode) {
return re_parse_error(s, "syntax error");
- } else if (!is_digit(p[1])) {
+ } else if (!lre_is_digit(p[1])) {
/* Annex B: we accept '{' not followed by digits as a
normal atom */
goto parse_class_atom;
} else {
const uint8_t *p1 = p + 1;
/* Annex B: error if it is like a repetition count */
- parse_digits(&p1, TRUE);
+ parse_digits(&p1, true);
if (*p1 == ',') {
p1++;
- if (is_digit(*p1)) {
- parse_digits(&p1, TRUE);
+ if (lre_is_digit(*p1)) {
+ parse_digits(&p1, true);
}
}
if (*p1 != '}') {
@@ -1179,14 +1236,14 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
return -1;
} else if ((p[2] == '=' || p[2] == '!')) {
is_neg = (p[2] == '!');
- is_backward_lookahead = FALSE;
+ is_backward_lookahead = false;
p += 3;
goto lookahead;
} else if (p[2] == '<' &&
(p[3] == '=' || p[3] == '!')) {
int pos;
is_neg = (p[3] == '!');
- is_backward_lookahead = TRUE;
+ is_backward_lookahead = true;
p += 4;
/* lookahead */
lookahead:
@@ -1300,7 +1357,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
p += 2;
c = 0;
if (s->is_unicode) {
- if (is_digit(*p)) {
+ if (lre_is_digit(*p)) {
return re_parse_error(s, "invalid decimal escape in regular expression");
}
} else {
@@ -1319,7 +1376,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
{
const uint8_t *q = ++p;
- c = parse_digits(&p, FALSE);
+ c = parse_digits(&p, false);
if (c < 0 || (c >= s->capture_count && c >= re_count_captures(s))) {
if (!s->is_unicode) {
/* Annex B.1.4: accept legacy octal */
@@ -1368,7 +1425,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
goto parse_class_atom;
default:
parse_class_atom:
- c = get_class_atom(s, cr, &p, FALSE);
+ c = get_class_atom(s, cr, &p, false);
if ((int)c < 0)
return -1;
normal_char:
@@ -1386,8 +1443,10 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
} else {
if (s->ignore_case)
c = lre_canonicalize(c, s->is_unicode);
- if (c <= 0xffff)
- re_emit_op_u16(s, REOP_char, c);
+ if (c <= 0x7f)
+ re_emit_op_u8(s, REOP_char8, c);
+ else if (c <= 0xffff)
+ re_emit_op_u16(s, REOP_char16, c);
else
re_emit_op_u32(s, REOP_char32, c);
}
@@ -1420,18 +1479,18 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
const uint8_t *p1 = p;
/* As an extension (see ES6 annex B), we accept '{' not
followed by digits as a normal atom */
- if (!is_digit(p[1])) {
+ if (!lre_is_digit(p[1])) {
if (s->is_unicode)
goto invalid_quant_count;
break;
}
p++;
- quant_min = parse_digits(&p, TRUE);
+ quant_min = parse_digits(&p, true);
quant_max = quant_min;
if (*p == ',') {
p++;
- if (is_digit(*p)) {
- quant_max = parse_digits(&p, TRUE);
+ if (lre_is_digit(*p)) {
+ quant_max = parse_digits(&p, true);
if (quant_max < quant_min) {
invalid_quant_count:
return re_parse_error(s, "invalid repetition count");
@@ -1449,10 +1508,10 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
return -1;
}
quantifier:
- greedy = TRUE;
+ greedy = true;
if (*p == '?') {
p++;
- greedy = FALSE;
+ greedy = false;
}
if (last_atom_start < 0) {
return re_parse_error(s, "nothing to repeat");
@@ -1488,15 +1547,13 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
if (dbuf_error(&s->byte_code))
goto out_of_memory;
- /* the spec tells that if there is no advance when
- running the atom after the first quant_min times,
- then there is no match. We remove this test when we
- are sure the atom always advances the position. */
- add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start,
- s->byte_code.size - last_atom_start);
- } else {
- add_zero_advance_check = FALSE;
}
+ /* the spec tells that if there is no advance when
+ running the atom after the first quant_min times,
+ then there is no match. We remove this test when we
+ are sure the atom always advances the position. */
+ add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start,
+ s->byte_code.size - last_atom_start);
{
int len, pos;
@@ -1514,7 +1571,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
if (quant_max == 0) {
s->byte_code.size = last_atom_start;
} else if (quant_max == 1 || quant_max == INT32_MAX) {
- BOOL has_goto = (quant_max == INT32_MAX);
+ bool has_goto = (quant_max == INT32_MAX);
if (dbuf_insert(&s->byte_code, last_atom_start, 5 + add_zero_advance_check))
goto out_of_memory;
s->byte_code.buf[last_atom_start] = REOP_split_goto_first +
@@ -1601,7 +1658,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
return re_parse_out_of_memory(s);
}
-static int re_parse_alternative(REParseState *s, BOOL is_backward_dir)
+static int re_parse_alternative(REParseState *s, bool is_backward_dir)
{
const uint8_t *p;
int ret;
@@ -1635,7 +1692,7 @@ static int re_parse_alternative(REParseState *s, BOOL is_backward_dir)
return 0;
}
-static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir)
+static int re_parse_disjunction(REParseState *s, bool is_backward_dir)
{
int start, len, pos;
@@ -1670,7 +1727,7 @@ static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir)
}
/* the control flow is recursive so the analysis can be linear */
-static int compute_stack_size(const uint8_t *bc_buf, int bc_buf_len)
+static int lre_compute_stack_size(const uint8_t *bc_buf, int bc_buf_len)
{
int stack_size, stack_size_max, pos, opcode, len;
uint32_t val;
@@ -1724,7 +1781,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
{
REParseState s_s, *s = &s_s;
int stack_size;
- BOOL is_sticky;
+ bool is_sticky;
memset(s, 0, sizeof(*s));
s->opaque = opaque;
@@ -1736,6 +1793,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
is_sticky = ((re_flags & LRE_FLAG_STICKY) != 0);
s->ignore_case = ((re_flags & LRE_FLAG_IGNORECASE) != 0);
s->dotall = ((re_flags & LRE_FLAG_DOTALL) != 0);
+ s->unicode_sets = ((re_flags & LRE_FLAG_UNICODE_SETS) != 0);
s->capture_count = 1;
s->total_capture_count = -1;
s->has_named_captures = -1;
@@ -1743,7 +1801,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
dbuf_init2(&s->byte_code, opaque, lre_realloc);
dbuf_init2(&s->group_names, opaque, lre_realloc);
- dbuf_putc(&s->byte_code, re_flags); /* first element is the flags */
+ dbuf_put_u16(&s->byte_code, re_flags); /* first element is the flags */
dbuf_putc(&s->byte_code, 0); /* second element is the number of captures */
dbuf_putc(&s->byte_code, 0); /* stack size */
dbuf_put_u32(&s->byte_code, 0); /* bytecode length */
@@ -1759,11 +1817,11 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
}
re_emit_op_u8(s, REOP_save_start, 0);
- if (re_parse_disjunction(s, FALSE)) {
+ if (re_parse_disjunction(s, false)) {
error:
dbuf_free(&s->byte_code);
dbuf_free(&s->group_names);
- pstrcpy(error_msg, error_msg_size, s->u.error_msg);
+ js__pstrcpy(error_msg, error_msg_size, s->u.error_msg);
*plen = 0;
return NULL;
}
@@ -1782,7 +1840,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
goto error;
}
- stack_size = compute_stack_size(s->byte_code.buf, s->byte_code.size);
+ stack_size = lre_compute_stack_size(s->byte_code.buf, s->byte_code.size);
if (stack_size < 0) {
re_parse_error(s, "too many imbricated quantifiers");
goto error;
@@ -1796,7 +1854,8 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
/* add the named groups if needed */
if (s->group_names.size > (s->capture_count - 1)) {
dbuf_put(&s->byte_code, s->group_names.buf, s->group_names.size);
- s->byte_code.buf[RE_HEADER_FLAGS] |= LRE_FLAG_NAMED_GROUPS;
+ put_u16(s->byte_code.buf + RE_HEADER_FLAGS,
+ LRE_FLAG_NAMED_GROUPS | lre_get_flags(s->byte_code.buf));
}
dbuf_free(&s->group_names);
@@ -1809,12 +1868,12 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
return s->byte_code.buf;
}
-static BOOL is_line_terminator(uint32_t c)
+static bool is_line_terminator(uint32_t c)
{
return (c == '\n' || c == '\r' || c == CP_LS || c == CP_PS);
}
-static BOOL is_word_char(uint32_t c)
+static bool is_word_char(uint32_t c)
{
return ((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
@@ -1830,11 +1889,11 @@ static BOOL is_word_char(uint32_t c)
const uint16_t *_p = (const uint16_t *)cptr; \
const uint16_t *_end = (const uint16_t *)cbuf_end; \
c = *_p++; \
- if (is_hi_surrogate(c) && cbuf_type == 2) { \
- if (_p < _end && is_lo_surrogate(*_p)) { \
- c = from_surrogate(c, *_p++); \
- } \
- } \
+ if (is_hi_surrogate(c)) \
+ if (cbuf_type == 2) \
+ if (_p < _end) \
+ if (is_lo_surrogate(*_p)) \
+ c = from_surrogate(c, *_p++); \
cptr = (const void *)_p; \
} \
} while (0)
@@ -1847,11 +1906,11 @@ static BOOL is_word_char(uint32_t c)
const uint16_t *_p = (const uint16_t *)cptr; \
const uint16_t *_end = (const uint16_t *)cbuf_end; \
c = *_p++; \
- if (is_hi_surrogate(c) && cbuf_type == 2) { \
- if (_p < _end && is_lo_surrogate(*_p)) { \
- c = from_surrogate(c, *_p); \
- } \
- } \
+ if (is_hi_surrogate(c)) \
+ if (cbuf_type == 2) \
+ if (_p < _end) \
+ if (is_lo_surrogate(*_p)) \
+ c = from_surrogate(c, *_p); \
} \
} while (0)
@@ -1863,11 +1922,11 @@ static BOOL is_word_char(uint32_t c)
const uint16_t *_p = (const uint16_t *)cptr - 1; \
const uint16_t *_start = (const uint16_t *)cbuf_start; \
c = *_p; \
- if (is_lo_surrogate(c) && cbuf_type == 2) { \
- if (_p > _start && is_hi_surrogate(_p[-1])) { \
- c = from_surrogate(*--_p, c); \
- } \
- } \
+ if (is_lo_surrogate(c)) \
+ if (cbuf_type == 2) \
+ if (_p > _start) \
+ if (is_hi_surrogate(_p[-1])) \
+ c = from_surrogate(*--_p, c); \
} \
} while (0)
@@ -1880,11 +1939,11 @@ static BOOL is_word_char(uint32_t c)
const uint16_t *_p = (const uint16_t *)cptr - 1; \
const uint16_t *_start = (const uint16_t *)cbuf_start; \
c = *_p; \
- if (is_lo_surrogate(c) && cbuf_type == 2) { \
- if (_p > _start && is_hi_surrogate(_p[-1])) { \
- c = from_surrogate(*--_p, c); \
- } \
- } \
+ if (is_lo_surrogate(c)) \
+ if (cbuf_type == 2) \
+ if (_p > _start) \
+ if (is_hi_surrogate(_p[-1])) \
+ c = from_surrogate(*--_p, c); \
cptr = (const void *)_p; \
} \
} while (0)
@@ -1896,11 +1955,11 @@ static BOOL is_word_char(uint32_t c)
} else { \
const uint16_t *_p = (const uint16_t *)cptr - 1; \
const uint16_t *_start = (const uint16_t *)cbuf_start; \
- if (is_lo_surrogate(*_p) && cbuf_type == 2) { \
- if (_p > _start && is_hi_surrogate(_p[-1])) { \
- --_p; \
- } \
- } \
+ if (is_lo_surrogate(*_p)) \
+ if (cbuf_type == 2) \
+ if (_p > _start) \
+ if (is_hi_surrogate(_p[-1])) \
+ _p--; \
cptr = (const void *)_p; \
} \
} while (0)
@@ -1920,7 +1979,7 @@ typedef struct REExecState {
size_t count; /* only used for RE_EXEC_STATE_GREEDY_QUANT */
const uint8_t *cptr;
const uint8_t *pc;
- void *buf[0];
+ void *buf[];
} REExecState;
typedef struct {
@@ -1930,9 +1989,9 @@ typedef struct {
int cbuf_type;
int capture_count;
int stack_size_max;
- BOOL multi_line;
- BOOL ignore_case;
- BOOL is_unicode;
+ bool multi_line;
+ bool ignore_case;
+ bool is_unicode;
void *opaque; /* used for stack overflow check */
size_t state_size;
@@ -1983,7 +2042,7 @@ static int push_state(REExecContext *s,
static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
StackInt *stack, int stack_len,
const uint8_t *pc, const uint8_t *cptr,
- BOOL no_recurse)
+ bool no_recurse)
{
int opcode, ret;
int cbuf_type;
@@ -2070,9 +2129,13 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
val = get_u32(pc);
pc += 4;
goto test_char;
- case REOP_char:
+ case REOP_char16:
val = get_u16(pc);
pc += 2;
+ goto test_char;
+ case REOP_char8:
+ val = get_u8(pc);
+ pc += 1;
test_char:
if (cptr >= cbuf_end)
goto no_match;
@@ -2193,17 +2256,17 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
case REOP_word_boundary:
case REOP_not_word_boundary:
{
- BOOL v1, v2;
+ bool v1, v2;
/* char before */
if (cptr == s->cbuf) {
- v1 = FALSE;
+ v1 = false;
} else {
PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type);
v1 = is_word_char(c);
}
/* current char */
if (cptr >= cbuf_end) {
- v2 = FALSE;
+ v2 = false;
} else {
PEEK_CHAR(c, cptr, cbuf_end, cbuf_type);
v2 = is_word_char(c);
@@ -2356,7 +2419,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
q = 0;
for(;;) {
res = lre_exec_backtrack(s, capture, stack, stack_len,
- pc1, cptr, TRUE);
+ pc1, cptr, true);
if (res == -1)
return res;
if (!res)
@@ -2421,7 +2484,7 @@ int lre_exec(uint8_t **capture,
alloca_size = s->stack_size_max * sizeof(stack_buf[0]);
stack_buf = alloca(alloca_size);
ret = lre_exec_backtrack(s, capture, stack_buf, 0, bc_buf + RE_HEADER_LEN,
- cbuf + (cindex << cbuf_type), FALSE);
+ cbuf + (cindex << cbuf_type), false);
lre_realloc(s->opaque, s->state_stack, 0);
return ret;
}
@@ -2433,7 +2496,7 @@ int lre_get_capture_count(const uint8_t *bc_buf)
int lre_get_flags(const uint8_t *bc_buf)
{
- return bc_buf[RE_HEADER_FLAGS];
+ return get_u16(bc_buf + RE_HEADER_FLAGS);
}
/* Return NULL if no group names. Otherwise, return a pointer to
@@ -2447,11 +2510,85 @@ const char *lre_get_groupnames(const uint8_t *bc_buf)
return (const char *)(bc_buf + RE_HEADER_LEN + re_bytecode_len);
}
+void lre_byte_swap(uint8_t *buf, size_t len, bool is_byte_swapped)
+{
+ uint8_t *p, *pe;
+ uint32_t n, r, nw;
+
+ p = buf;
+ if (len < RE_HEADER_LEN)
+ abort();
+
+ // format is:
+ // <header>
+ // <bytecode>
+ // <capture group name 1>
+ // <capture group name 2>
+ // etc.
+ inplace_bswap16(&p[RE_HEADER_FLAGS]);
+
+ n = get_u32(&p[RE_HEADER_BYTECODE_LEN]);
+ inplace_bswap32(&p[RE_HEADER_BYTECODE_LEN]);
+ if (is_byte_swapped)
+ n = bswap32(n);
+ if (n > len - RE_HEADER_LEN)
+ abort();
+
+ p = &buf[RE_HEADER_LEN];
+ pe = &p[n];
+
+ while (p < pe) {
+ n = reopcode_info[*p].size;
+ switch (n) {
+ case 1:
+ case 2:
+ break;
+ case 3:
+ switch (*p) {
+ case REOP_save_reset: // has two 8 bit arguments
+ break;
+ case REOP_range32: // variable length
+ nw = get_u16(&p[1]); // number of pairs of uint32_t
+ if (is_byte_swapped)
+ n = bswap16(n);
+ for (r = 3 + 8 * nw; n < r; n += 4)
+ inplace_bswap32(&p[n]);
+ goto doswap16;
+ case REOP_range: // variable length
+ nw = get_u16(&p[1]); // number of pairs of uint16_t
+ if (is_byte_swapped)
+ n = bswap16(n);
+ for (r = 3 + 4 * nw; n < r; n += 2)
+ inplace_bswap16(&p[n]);
+ goto doswap16;
+ default:
+ doswap16:
+ inplace_bswap16(&p[1]);
+ break;
+ }
+ break;
+ case 5:
+ inplace_bswap32(&p[1]);
+ break;
+ case 17:
+ assert(*p == REOP_simple_greedy_quant);
+ inplace_bswap32(&p[1]);
+ inplace_bswap32(&p[5]);
+ inplace_bswap32(&p[9]);
+ inplace_bswap32(&p[13]);
+ break;
+ default:
+ abort();
+ }
+ p = &p[n];
+ }
+}
+
#ifdef TEST
-BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size)
+bool lre_check_stack_overflow(void *opaque, size_t alloca_size)
{
- return FALSE;
+ return false;
}
void *lre_realloc(void *opaque, void *ptr, size_t size)
@@ -2470,7 +2607,7 @@ int main(int argc, char **argv)
if (argc < 4) {
printf("usage: %s regexp flags input\n", argv[0]);
- return 1;
+ exit(1);
}
flags = atoi(argv[2]);
bc = lre_compile(&len, error_msg, sizeof(error_msg), argv[1],
diff --git a/src/shared/quickjs/libregexp.h b/src/shared/quickjs/libregexp.h
index 7af7ece0f..0b8fec52b 100644
--- a/src/shared/quickjs/libregexp.h
+++ b/src/shared/quickjs/libregexp.h
@@ -24,8 +24,14 @@
#ifndef LIBREGEXP_H
#define LIBREGEXP_H
+#include <stdbool.h>
#include <stddef.h>
-#include <stdint.h>
+
+#include "libunicode.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
#define LRE_FLAG_GLOBAL (1 << 0)
#define LRE_FLAG_IGNORECASE (1 << 1)
@@ -35,6 +41,7 @@
#define LRE_FLAG_STICKY (1 << 5)
#define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
+#define LRE_FLAG_UNICODE_SETS (1 << 8)
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
const char *buf, size_t buf_len, int re_flags,
@@ -47,9 +54,39 @@ int lre_exec(uint8_t **capture,
int cbuf_type, void *opaque);
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
+bool lre_is_space(int c);
-/* must be provided by the user, return non zero if overflow */
-int lre_check_stack_overflow(void *opaque, size_t alloca_size);
+void lre_byte_swap(uint8_t *buf, size_t len, bool is_byte_swapped);
+
+/* must be provided by the user */
+bool lre_check_stack_overflow(void *opaque, size_t alloca_size);
void *lre_realloc(void *opaque, void *ptr, size_t size);
+/* JS identifier test */
+extern uint32_t const lre_id_start_table_ascii[4];
+extern uint32_t const lre_id_continue_table_ascii[4];
+
+static inline int lre_js_is_ident_first(int c)
+{
+ if ((uint32_t)c < 128) {
+ return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
+ } else {
+ return lre_is_id_start(c);
+ }
+}
+
+static inline int lre_js_is_ident_next(int c)
+{
+ if ((uint32_t)c < 128) {
+ return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
+ } else {
+ /* ZWNJ and ZWJ are accepted in identifiers */
+ return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
+ }
+}
+
+#ifdef __cplusplus
+} /* extern "C" { */
+#endif
+
#endif /* LIBREGEXP_H */
diff --git a/src/shared/quickjs/libunicode-table.h b/src/shared/quickjs/libunicode-table.h
index 72d495e78..b48a3a746 100644
--- a/src/shared/quickjs/libunicode-table.h
+++ b/src/shared/quickjs/libunicode-table.h
@@ -3,7 +3,7 @@
#include <stdint.h>
-static const uint32_t case_conv_table1[370] = {
+static const uint32_t case_conv_table1[378] = {
0x00209a30, 0x00309a00, 0x005a8173, 0x00601730,
0x006c0730, 0x006f81b3, 0x00701700, 0x007c0700,
0x007f8100, 0x00803040, 0x009801c3, 0x00988190,
@@ -13,140 +13,143 @@ static const uint32_t case_conv_table1[370] = {
0x00c48230, 0x00c58240, 0x00c70130, 0x00c78130,
0x00c80130, 0x00c88240, 0x00c98130, 0x00ca0130,
0x00ca8100, 0x00cb0130, 0x00cb8130, 0x00cc0240,
- 0x00cd0100, 0x00ce0130, 0x00ce8130, 0x00cf0100,
- 0x00cf8130, 0x00d00640, 0x00d30130, 0x00d38240,
- 0x00d48130, 0x00d60240, 0x00d70130, 0x00d78240,
- 0x00d88230, 0x00d98440, 0x00db8130, 0x00dc0240,
- 0x00de0240, 0x00df8100, 0x00e20350, 0x00e38350,
- 0x00e50350, 0x00e69040, 0x00ee8100, 0x00ef1240,
- 0x00f801b4, 0x00f88350, 0x00fa0240, 0x00fb0130,
- 0x00fb8130, 0x00fc2840, 0x01100130, 0x01111240,
- 0x011d0131, 0x011d8240, 0x011e8130, 0x011f0131,
- 0x011f8201, 0x01208240, 0x01218130, 0x01220130,
- 0x01228130, 0x01230a40, 0x01280101, 0x01288101,
- 0x01290101, 0x01298100, 0x012a0100, 0x012b0200,
- 0x012c8100, 0x012d8100, 0x012e0101, 0x01300100,
- 0x01308101, 0x01318100, 0x01328101, 0x01330101,
- 0x01340100, 0x01348100, 0x01350101, 0x01358101,
- 0x01360101, 0x01378100, 0x01388101, 0x01390100,
- 0x013a8100, 0x013e8101, 0x01400100, 0x01410101,
- 0x01418100, 0x01438101, 0x01440100, 0x01448100,
- 0x01450200, 0x01460100, 0x01490100, 0x014e8101,
- 0x014f0101, 0x01a28173, 0x01b80440, 0x01bb0240,
- 0x01bd8300, 0x01bf8130, 0x01c30130, 0x01c40330,
- 0x01c60130, 0x01c70230, 0x01c801d0, 0x01c89130,
- 0x01d18930, 0x01d60100, 0x01d68300, 0x01d801d3,
- 0x01d89100, 0x01e10173, 0x01e18900, 0x01e60100,
- 0x01e68200, 0x01e78130, 0x01e80173, 0x01e88173,
- 0x01ea8173, 0x01eb0173, 0x01eb8100, 0x01ec1840,
- 0x01f80173, 0x01f88173, 0x01f90100, 0x01f98100,
- 0x01fa01a0, 0x01fa8173, 0x01fb8240, 0x01fc8130,
- 0x01fd0240, 0x01fe8330, 0x02001030, 0x02082030,
- 0x02182000, 0x02281000, 0x02302240, 0x02453640,
- 0x02600130, 0x02608e40, 0x02678100, 0x02686040,
- 0x0298a630, 0x02b0a600, 0x02c381b5, 0x08502631,
- 0x08638131, 0x08668131, 0x08682b00, 0x087e8300,
- 0x09d05011, 0x09f80610, 0x09fc0620, 0x0e400174,
- 0x0e408174, 0x0e410174, 0x0e418174, 0x0e420174,
- 0x0e428174, 0x0e430174, 0x0e438180, 0x0e440180,
- 0x0e482b30, 0x0e5e8330, 0x0ebc8101, 0x0ebe8101,
- 0x0ec70101, 0x0f007e40, 0x0f3f1840, 0x0f4b01b5,
- 0x0f4b81b6, 0x0f4c01b6, 0x0f4c81b6, 0x0f4d01b7,
- 0x0f4d8180, 0x0f4f0130, 0x0f506040, 0x0f800800,
- 0x0f840830, 0x0f880600, 0x0f8c0630, 0x0f900800,
- 0x0f940830, 0x0f980800, 0x0f9c0830, 0x0fa00600,
- 0x0fa40630, 0x0fa801b0, 0x0fa88100, 0x0fa901d3,
- 0x0fa98100, 0x0faa01d3, 0x0faa8100, 0x0fab01d3,
- 0x0fab8100, 0x0fac8130, 0x0fad8130, 0x0fae8130,
- 0x0faf8130, 0x0fb00800, 0x0fb40830, 0x0fb80200,
- 0x0fb90400, 0x0fbb0200, 0x0fbc0201, 0x0fbd0201,
- 0x0fbe0201, 0x0fc008b7, 0x0fc40867, 0x0fc808b8,
- 0x0fcc0868, 0x0fd008b8, 0x0fd40868, 0x0fd80200,
- 0x0fd901b9, 0x0fd981b1, 0x0fda01b9, 0x0fdb01b1,
- 0x0fdb81d7, 0x0fdc0230, 0x0fdd0230, 0x0fde0161,
- 0x0fdf0173, 0x0fe101b9, 0x0fe181b2, 0x0fe201ba,
- 0x0fe301b2, 0x0fe381d8, 0x0fe40430, 0x0fe60162,
- 0x0fe80200, 0x0fe901d0, 0x0fe981d0, 0x0feb01b0,
- 0x0feb81d0, 0x0fec0230, 0x0fed0230, 0x0ff00201,
- 0x0ff101d3, 0x0ff181d3, 0x0ff201ba, 0x0ff28101,
- 0x0ff301b0, 0x0ff381d3, 0x0ff40230, 0x0ff50230,
- 0x0ff60131, 0x0ff901ba, 0x0ff981b2, 0x0ffa01bb,
- 0x0ffb01b2, 0x0ffb81d9, 0x0ffc0230, 0x0ffd0230,
- 0x0ffe0162, 0x109301a0, 0x109501a0, 0x109581a0,
- 0x10990131, 0x10a70101, 0x10b01031, 0x10b81001,
- 0x10c18240, 0x125b1a31, 0x12681a01, 0x16003031,
- 0x16183001, 0x16300240, 0x16310130, 0x16318130,
- 0x16320130, 0x16328100, 0x16330100, 0x16338640,
- 0x16368130, 0x16370130, 0x16378130, 0x16380130,
- 0x16390240, 0x163a8240, 0x163f0230, 0x16406440,
- 0x16758440, 0x16790240, 0x16802600, 0x16938100,
- 0x16968100, 0x53202e40, 0x53401c40, 0x53910e40,
- 0x53993e40, 0x53bc8440, 0x53be8130, 0x53bf0a40,
- 0x53c58240, 0x53c68130, 0x53c80440, 0x53ca0101,
- 0x53cb1440, 0x53d50130, 0x53d58130, 0x53d60130,
- 0x53d68130, 0x53d70130, 0x53d80130, 0x53d88130,
- 0x53d90130, 0x53d98131, 0x53da1040, 0x53e20131,
- 0x53e28130, 0x53e30130, 0x53e38440, 0x53e80240,
- 0x53eb0440, 0x53fa8240, 0x55a98101, 0x55b85020,
- 0x7d8001b2, 0x7d8081b2, 0x7d8101b2, 0x7d8181da,
- 0x7d8201da, 0x7d8281b3, 0x7d8301b3, 0x7d8981bb,
- 0x7d8a01bb, 0x7d8a81bb, 0x7d8b01bc, 0x7d8b81bb,
- 0x7f909a31, 0x7fa09a01, 0x82002831, 0x82142801,
- 0x82582431, 0x826c2401, 0x82b80b31, 0x82be0f31,
- 0x82c60731, 0x82ca0231, 0x82cb8b01, 0x82d18f01,
- 0x82d98701, 0x82dd8201, 0x86403331, 0x86603301,
+ 0x00cd0100, 0x00cd8101, 0x00ce0130, 0x00ce8130,
+ 0x00cf0100, 0x00cf8130, 0x00d00640, 0x00d30130,
+ 0x00d38240, 0x00d48130, 0x00d60240, 0x00d70130,
+ 0x00d78240, 0x00d88230, 0x00d98440, 0x00db8130,
+ 0x00dc0240, 0x00de0240, 0x00df8100, 0x00e20350,
+ 0x00e38350, 0x00e50350, 0x00e69040, 0x00ee8100,
+ 0x00ef1240, 0x00f801b4, 0x00f88350, 0x00fa0240,
+ 0x00fb0130, 0x00fb8130, 0x00fc2840, 0x01100130,
+ 0x01111240, 0x011d0131, 0x011d8240, 0x011e8130,
+ 0x011f0131, 0x011f8201, 0x01208240, 0x01218130,
+ 0x01220130, 0x01228130, 0x01230a40, 0x01280101,
+ 0x01288101, 0x01290101, 0x01298100, 0x012a0100,
+ 0x012b0200, 0x012c8100, 0x012d8100, 0x012e0101,
+ 0x01300100, 0x01308101, 0x01318100, 0x01320101,
+ 0x01328101, 0x01330101, 0x01340100, 0x01348100,
+ 0x01350101, 0x01358101, 0x01360101, 0x01378100,
+ 0x01388101, 0x01390100, 0x013a8100, 0x013e8101,
+ 0x01400100, 0x01410101, 0x01418100, 0x01438101,
+ 0x01440100, 0x01448100, 0x01450200, 0x01460100,
+ 0x01490100, 0x014e8101, 0x014f0101, 0x01a28173,
+ 0x01b80440, 0x01bb0240, 0x01bd8300, 0x01bf8130,
+ 0x01c30130, 0x01c40330, 0x01c60130, 0x01c70230,
+ 0x01c801d0, 0x01c89130, 0x01d18930, 0x01d60100,
+ 0x01d68300, 0x01d801d3, 0x01d89100, 0x01e10173,
+ 0x01e18900, 0x01e60100, 0x01e68200, 0x01e78130,
+ 0x01e80173, 0x01e88173, 0x01ea8173, 0x01eb0173,
+ 0x01eb8100, 0x01ec1840, 0x01f80173, 0x01f88173,
+ 0x01f90100, 0x01f98100, 0x01fa01a0, 0x01fa8173,
+ 0x01fb8240, 0x01fc8130, 0x01fd0240, 0x01fe8330,
+ 0x02001030, 0x02082030, 0x02182000, 0x02281000,
+ 0x02302240, 0x02453640, 0x02600130, 0x02608e40,
+ 0x02678100, 0x02686040, 0x0298a630, 0x02b0a600,
+ 0x02c381b5, 0x08502631, 0x08638131, 0x08668131,
+ 0x08682b00, 0x087e8300, 0x09d05011, 0x09f80610,
+ 0x09fc0620, 0x0e400174, 0x0e408174, 0x0e410174,
+ 0x0e418174, 0x0e420174, 0x0e428174, 0x0e430174,
+ 0x0e438180, 0x0e440180, 0x0e448240, 0x0e482b30,
+ 0x0e5e8330, 0x0ebc8101, 0x0ebe8101, 0x0ec70101,
+ 0x0f007e40, 0x0f3f1840, 0x0f4b01b5, 0x0f4b81b6,
+ 0x0f4c01b6, 0x0f4c81b6, 0x0f4d01b7, 0x0f4d8180,
+ 0x0f4f0130, 0x0f506040, 0x0f800800, 0x0f840830,
+ 0x0f880600, 0x0f8c0630, 0x0f900800, 0x0f940830,
+ 0x0f980800, 0x0f9c0830, 0x0fa00600, 0x0fa40630,
+ 0x0fa801b0, 0x0fa88100, 0x0fa901d3, 0x0fa98100,
+ 0x0faa01d3, 0x0faa8100, 0x0fab01d3, 0x0fab8100,
+ 0x0fac8130, 0x0fad8130, 0x0fae8130, 0x0faf8130,
+ 0x0fb00800, 0x0fb40830, 0x0fb80200, 0x0fb90400,
+ 0x0fbb0201, 0x0fbc0201, 0x0fbd0201, 0x0fbe0201,
+ 0x0fc008b7, 0x0fc40867, 0x0fc808b8, 0x0fcc0868,
+ 0x0fd008b8, 0x0fd40868, 0x0fd80200, 0x0fd901b9,
+ 0x0fd981b1, 0x0fda01b9, 0x0fdb01b1, 0x0fdb81d7,
+ 0x0fdc0230, 0x0fdd0230, 0x0fde0161, 0x0fdf0173,
+ 0x0fe101b9, 0x0fe181b2, 0x0fe201ba, 0x0fe301b2,
+ 0x0fe381d8, 0x0fe40430, 0x0fe60162, 0x0fe80201,
+ 0x0fe901d0, 0x0fe981d0, 0x0feb01b0, 0x0feb81d0,
+ 0x0fec0230, 0x0fed0230, 0x0ff00201, 0x0ff101d3,
+ 0x0ff181d3, 0x0ff201ba, 0x0ff28101, 0x0ff301b0,
+ 0x0ff381d3, 0x0ff40231, 0x0ff50230, 0x0ff60131,
+ 0x0ff901ba, 0x0ff981b2, 0x0ffa01bb, 0x0ffb01b2,
+ 0x0ffb81d9, 0x0ffc0230, 0x0ffd0230, 0x0ffe0162,
+ 0x109301a0, 0x109501a0, 0x109581a0, 0x10990131,
+ 0x10a70101, 0x10b01031, 0x10b81001, 0x10c18240,
+ 0x125b1a31, 0x12681a01, 0x16003031, 0x16183001,
+ 0x16300240, 0x16310130, 0x16318130, 0x16320130,
+ 0x16328100, 0x16330100, 0x16338640, 0x16368130,
+ 0x16370130, 0x16378130, 0x16380130, 0x16390240,
+ 0x163a8240, 0x163f0230, 0x16406440, 0x16758440,
+ 0x16790240, 0x16802600, 0x16938100, 0x16968100,
+ 0x53202e40, 0x53401c40, 0x53910e40, 0x53993e40,
+ 0x53bc8440, 0x53be8130, 0x53bf0a40, 0x53c58240,
+ 0x53c68130, 0x53c80440, 0x53ca0101, 0x53cb1440,
+ 0x53d50130, 0x53d58130, 0x53d60130, 0x53d68130,
+ 0x53d70130, 0x53d80130, 0x53d88130, 0x53d90130,
+ 0x53d98131, 0x53da1040, 0x53e20131, 0x53e28130,
+ 0x53e30130, 0x53e38440, 0x53e58130, 0x53e60240,
+ 0x53e80240, 0x53eb0640, 0x53ee0130, 0x53fa8240,
+ 0x55a98101, 0x55b85020, 0x7d8001b2, 0x7d8081b2,
+ 0x7d8101b2, 0x7d8181da, 0x7d8201da, 0x7d8281b3,
+ 0x7d8301b3, 0x7d8981bb, 0x7d8a01bb, 0x7d8a81bb,
+ 0x7d8b01bc, 0x7d8b81bb, 0x7f909a31, 0x7fa09a01,
+ 0x82002831, 0x82142801, 0x82582431, 0x826c2401,
+ 0x82b80b31, 0x82be0f31, 0x82c60731, 0x82ca0231,
+ 0x82cb8b01, 0x82d18f01, 0x82d98701, 0x82dd8201,
+ 0x86403331, 0x86603301, 0x86a81631, 0x86b81601,
0x8c502031, 0x8c602001, 0xb7202031, 0xb7302001,
0xf4802231, 0xf4912201,
};
-static const uint8_t case_conv_table2[370] = {
+static const uint8_t case_conv_table2[378] = {
0x01, 0x00, 0x9c, 0x06, 0x07, 0x4d, 0x03, 0x04,
0x10, 0x00, 0x8f, 0x0b, 0x00, 0x00, 0x11, 0x00,
- 0x08, 0x00, 0x53, 0x4a, 0x51, 0x00, 0x52, 0x00,
- 0x53, 0x00, 0x3a, 0x54, 0x55, 0x00, 0x57, 0x59,
- 0x3f, 0x5d, 0x5c, 0x00, 0x46, 0x61, 0x63, 0x42,
- 0x64, 0x00, 0x66, 0x00, 0x68, 0x00, 0x6a, 0x00,
- 0x6c, 0x00, 0x6e, 0x00, 0x00, 0x40, 0x00, 0x00,
- 0x00, 0x00, 0x1a, 0x00, 0x93, 0x00, 0x00, 0x20,
- 0x35, 0x00, 0x27, 0x00, 0x21, 0x00, 0x24, 0x22,
- 0x2a, 0x00, 0x13, 0x6b, 0x6d, 0x00, 0x26, 0x24,
- 0x27, 0x14, 0x16, 0x18, 0x1b, 0x1c, 0x3e, 0x1e,
- 0x3f, 0x1f, 0x39, 0x3d, 0x22, 0x21, 0x41, 0x1e,
- 0x40, 0x25, 0x25, 0x26, 0x28, 0x20, 0x2a, 0x48,
- 0x2c, 0x43, 0x2e, 0x4b, 0x30, 0x4c, 0x32, 0x44,
- 0x42, 0x99, 0x00, 0x00, 0x95, 0x8f, 0x7d, 0x7e,
- 0x83, 0x84, 0x12, 0x80, 0x82, 0x76, 0x77, 0x12,
- 0x7b, 0xa3, 0x7c, 0x78, 0x79, 0x8a, 0x92, 0x98,
- 0xa6, 0xa0, 0x85, 0x00, 0x9a, 0xa1, 0x93, 0x75,
- 0x33, 0x95, 0x00, 0x8e, 0x00, 0x74, 0x99, 0x98,
- 0x97, 0x96, 0x00, 0x00, 0x9e, 0x00, 0x9c, 0x00,
- 0xa1, 0xa0, 0x15, 0x2e, 0x2f, 0x30, 0xb4, 0xb5,
- 0x4f, 0xaa, 0xa9, 0x12, 0x14, 0x1e, 0x21, 0x22,
- 0x22, 0x2a, 0x34, 0x35, 0xa6, 0xa7, 0x36, 0x1f,
- 0x49, 0x00, 0x00, 0x97, 0x01, 0x5a, 0xda, 0x1d,
- 0x36, 0x05, 0x00, 0xc4, 0xc3, 0xc6, 0xc5, 0xc8,
- 0xc7, 0xca, 0xc9, 0xcc, 0xcb, 0xc4, 0xd5, 0x45,
- 0xd6, 0x42, 0xd7, 0x46, 0xd8, 0xce, 0xd0, 0xd2,
- 0xd4, 0xda, 0xd9, 0xee, 0xf6, 0xfe, 0x0e, 0x07,
- 0x0f, 0x80, 0x9f, 0x00, 0x21, 0x80, 0xa3, 0xed,
- 0x00, 0xc0, 0x40, 0xc6, 0x60, 0xe7, 0xdb, 0xe6,
- 0x99, 0xc0, 0x00, 0x00, 0x06, 0x60, 0xdc, 0x29,
- 0xfd, 0x15, 0x12, 0x06, 0x16, 0xf8, 0xdd, 0x06,
- 0x15, 0x12, 0x84, 0x08, 0xc6, 0x16, 0xff, 0xdf,
- 0x03, 0xc0, 0x40, 0x00, 0x46, 0x60, 0xde, 0xe0,
- 0x6d, 0x37, 0x38, 0x39, 0x15, 0x14, 0x17, 0x16,
- 0x00, 0x1a, 0x19, 0x1c, 0x1b, 0x00, 0x5f, 0xb7,
- 0x65, 0x44, 0x47, 0x00, 0x4f, 0x62, 0x4e, 0x50,
- 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xa3, 0xa4,
- 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00,
- 0x00, 0x5a, 0x00, 0x47, 0x00, 0x5b, 0x56, 0x58,
- 0x60, 0x5e, 0x70, 0x69, 0x6f, 0x4e, 0x00, 0x3b,
- 0x67, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x45, 0xa8,
- 0x8a, 0x8b, 0x8c, 0xab, 0xac, 0x58, 0x58, 0xaf,
- 0x94, 0xb0, 0x6f, 0xb2, 0x5d, 0x5c, 0x5f, 0x5e,
- 0x61, 0x60, 0x66, 0x67, 0x68, 0x69, 0x62, 0x63,
- 0x64, 0x65, 0x6b, 0x6a, 0x6d, 0x6c, 0x6f, 0x6e,
- 0x71, 0x70,
+ 0x08, 0x00, 0x53, 0x4b, 0x52, 0x00, 0x53, 0x00,
+ 0x54, 0x00, 0x3b, 0x55, 0x56, 0x00, 0x58, 0x5a,
+ 0x40, 0x5f, 0x5e, 0x00, 0x47, 0x52, 0x63, 0x65,
+ 0x43, 0x66, 0x00, 0x68, 0x00, 0x6a, 0x00, 0x6c,
+ 0x00, 0x6e, 0x00, 0x70, 0x00, 0x00, 0x41, 0x00,
+ 0x00, 0x00, 0x00, 0x1a, 0x00, 0x93, 0x00, 0x00,
+ 0x20, 0x36, 0x00, 0x28, 0x00, 0x24, 0x00, 0x24,
+ 0x25, 0x2d, 0x00, 0x13, 0x6d, 0x6f, 0x00, 0x29,
+ 0x27, 0x2a, 0x14, 0x16, 0x18, 0x1b, 0x1c, 0x41,
+ 0x1e, 0x42, 0x1f, 0x4e, 0x3c, 0x40, 0x22, 0x21,
+ 0x44, 0x21, 0x43, 0x26, 0x28, 0x27, 0x29, 0x23,
+ 0x2b, 0x4b, 0x2d, 0x46, 0x2f, 0x4c, 0x31, 0x4d,
+ 0x33, 0x47, 0x45, 0x99, 0x00, 0x00, 0x97, 0x91,
+ 0x7f, 0x80, 0x85, 0x86, 0x12, 0x82, 0x84, 0x78,
+ 0x79, 0x12, 0x7d, 0xa3, 0x7e, 0x7a, 0x7b, 0x8c,
+ 0x92, 0x98, 0xa6, 0xa0, 0x87, 0x00, 0x9a, 0xa1,
+ 0x95, 0x77, 0x33, 0x95, 0x00, 0x90, 0x00, 0x76,
+ 0x9b, 0x9a, 0x99, 0x98, 0x00, 0x00, 0xa0, 0x00,
+ 0x9e, 0x00, 0xa3, 0xa2, 0x15, 0x31, 0x32, 0x33,
+ 0xb7, 0xb8, 0x55, 0xac, 0xab, 0x12, 0x14, 0x1e,
+ 0x21, 0x22, 0x22, 0x2a, 0x34, 0x35, 0x00, 0xa8,
+ 0xa9, 0x39, 0x22, 0x4c, 0x00, 0x00, 0x97, 0x01,
+ 0x5a, 0xda, 0x1d, 0x36, 0x05, 0x00, 0xc7, 0xc6,
+ 0xc9, 0xc8, 0xcb, 0xca, 0xcd, 0xcc, 0xcf, 0xce,
+ 0xc4, 0xd8, 0x45, 0xd9, 0x42, 0xda, 0x46, 0xdb,
+ 0xd1, 0xd3, 0xd5, 0xd7, 0xdd, 0xdc, 0xf1, 0xf9,
+ 0x01, 0x11, 0x0a, 0x12, 0x80, 0x9f, 0x00, 0x21,
+ 0x80, 0xa3, 0xf0, 0x00, 0xc0, 0x40, 0xc6, 0x60,
+ 0xea, 0xde, 0xe6, 0x99, 0xc0, 0x00, 0x00, 0x06,
+ 0x60, 0xdf, 0x29, 0x00, 0x15, 0x12, 0x06, 0x16,
+ 0xfb, 0xe0, 0x09, 0x15, 0x12, 0x84, 0x0b, 0xc6,
+ 0x16, 0x02, 0xe2, 0x06, 0xc0, 0x40, 0x00, 0x46,
+ 0x60, 0xe1, 0xe3, 0x6d, 0x37, 0x38, 0x39, 0x18,
+ 0x17, 0x1a, 0x19, 0x00, 0x1d, 0x1c, 0x1f, 0x1e,
+ 0x00, 0x61, 0xba, 0x67, 0x45, 0x48, 0x00, 0x50,
+ 0x64, 0x4f, 0x51, 0x00, 0x00, 0x49, 0x00, 0x00,
+ 0x00, 0xa5, 0xa6, 0xa7, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xb9, 0x00, 0x00, 0x5c, 0x00, 0x4a, 0x00,
+ 0x5d, 0x57, 0x59, 0x62, 0x60, 0x72, 0x6b, 0x71,
+ 0x54, 0x00, 0x3e, 0x69, 0xbb, 0x00, 0x5b, 0x00,
+ 0x00, 0x00, 0x25, 0x00, 0x48, 0xaa, 0x8a, 0x8b,
+ 0x8c, 0xab, 0xac, 0x58, 0x58, 0xaf, 0x94, 0xb0,
+ 0x6f, 0xb2, 0x63, 0x62, 0x65, 0x64, 0x67, 0x66,
+ 0x6c, 0x6d, 0x6e, 0x6f, 0x68, 0x69, 0x6a, 0x6b,
+ 0x71, 0x70, 0x73, 0x72, 0x75, 0x74, 0x77, 0x76,
+ 0x79, 0x78,
};
static const uint16_t case_conv_ext[58] = {
@@ -160,45 +163,41 @@ static const uint16_t case_conv_ext[58] = {
0x006b, 0x00e5,
};
-static const uint8_t unicode_prop_Cased1_table[196] = {
+static const uint8_t unicode_prop_Cased1_table[193] = {
0x40, 0xa9, 0x80, 0x8e, 0x80, 0xfc, 0x80, 0xd3,
- 0x80, 0x8c, 0x80, 0x8d, 0x81, 0x8d, 0x02, 0x80,
- 0xe1, 0x80, 0x91, 0x85, 0x9a, 0x01, 0x00, 0x01,
- 0x11, 0x00, 0x01, 0x04, 0x08, 0x01, 0x08, 0x30,
- 0x08, 0x01, 0x15, 0x20, 0x00, 0x39, 0x99, 0x31,
- 0x9d, 0x84, 0x40, 0x94, 0x80, 0xd6, 0x82, 0xa6,
- 0x80, 0x41, 0x62, 0x80, 0xa6, 0x80, 0x4b, 0x72,
- 0x80, 0x4c, 0x02, 0xf8, 0x02, 0x80, 0x8f, 0x80,
- 0xb0, 0x40, 0xdb, 0x08, 0x80, 0x41, 0xd0, 0x80,
- 0x8c, 0x80, 0x8f, 0x8c, 0xe4, 0x03, 0x01, 0x89,
- 0x00, 0x14, 0x28, 0x10, 0x11, 0x02, 0x01, 0x18,
- 0x0b, 0x24, 0x4b, 0x26, 0x01, 0x01, 0x86, 0xe5,
- 0x80, 0x60, 0x79, 0xb6, 0x81, 0x40, 0x91, 0x81,
- 0xbd, 0x88, 0x94, 0x05, 0x80, 0x98, 0x80, 0xa2,
- 0x00, 0x80, 0x9b, 0x12, 0x82, 0x43, 0x34, 0xa2,
- 0x06, 0x80, 0x8d, 0x60, 0x5c, 0x15, 0x01, 0x10,
- 0xa9, 0x80, 0x88, 0x60, 0xcc, 0x44, 0xd4, 0x80,
- 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, 0x00,
- 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b,
- 0x03, 0x04, 0x00, 0x16, 0x80, 0x41, 0x53, 0x81,
- 0x98, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80,
- 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80,
- 0x9e, 0x80, 0x98, 0x07, 0x47, 0x33, 0x89, 0x80,
- 0x93, 0x2d, 0x41, 0x04, 0xbd, 0x50, 0xc1, 0x99,
- 0x85, 0x99, 0x85, 0x99,
+ 0x80, 0x9b, 0x81, 0x8d, 0x02, 0x80, 0xe1, 0x80,
+ 0x91, 0x85, 0x9a, 0x01, 0x00, 0x01, 0x11, 0x03,
+ 0x04, 0x08, 0x01, 0x08, 0x30, 0x08, 0x01, 0x15,
+ 0x20, 0x00, 0x39, 0x99, 0x31, 0x9d, 0x84, 0x40,
+ 0x94, 0x80, 0xd6, 0x82, 0xa6, 0x80, 0x41, 0x62,
+ 0x80, 0xa6, 0x80, 0x4b, 0x72, 0x80, 0x4c, 0x02,
+ 0xf8, 0x02, 0x80, 0x8f, 0x80, 0xb0, 0x40, 0xdb,
+ 0x08, 0x80, 0x41, 0xd0, 0x80, 0x8c, 0x80, 0x8f,
+ 0x8c, 0xe4, 0x03, 0x01, 0x89, 0x00, 0x14, 0x28,
+ 0x10, 0x11, 0x02, 0x01, 0x18, 0x0b, 0x24, 0x4b,
+ 0x26, 0x01, 0x01, 0x86, 0xe5, 0x80, 0x60, 0x79,
+ 0xb6, 0x81, 0x40, 0x91, 0x81, 0xbd, 0x88, 0x94,
+ 0x05, 0x80, 0x98, 0x80, 0xa2, 0x00, 0x80, 0x9b,
+ 0x12, 0x82, 0x43, 0x34, 0xa2, 0x06, 0x80, 0x8d,
+ 0x60, 0x5c, 0x15, 0x01, 0x10, 0xa9, 0x80, 0x88,
+ 0x60, 0xcc, 0x44, 0xd4, 0x80, 0xc6, 0x01, 0x08,
+ 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0,
+ 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00,
+ 0x16, 0x80, 0x41, 0x53, 0x81, 0x98, 0x80, 0x98,
+ 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98,
+ 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98,
+ 0x07, 0x47, 0x33, 0x89, 0x80, 0x93, 0x2d, 0x41,
+ 0x04, 0xbd, 0x50, 0xc1, 0x99, 0x85, 0x99, 0x85,
+ 0x99,
};
-static const uint8_t unicode_prop_Cased1_index[21] = {
- 0xb9, 0x02, 0xe0, // 002B9 at 39
- 0xc0, 0x1d, 0x20, // 01DC0 at 65
- 0xe5, 0x2c, 0x20, // 02CE5 at 97
- 0xb1, 0x07, 0x21, // 107B1 at 129
- 0xc1, 0xd6, 0x21, // 1D6C1 at 161
- 0x4a, 0xf1, 0x01, // 1F14A at 192
- 0x8a, 0xf1, 0x01, // 1F18A at 224 (upper bound)
+static const uint8_t unicode_prop_Cased1_index[18] = {
+ 0xb9, 0x02, 0x80, 0xa0, 0x1e, 0x40, 0x9e, 0xa6,
+ 0x40, 0xbb, 0x07, 0x01, 0xdb, 0xd6, 0x01, 0x8a,
+ 0xf1, 0x01,
};
-static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
+static const uint8_t unicode_prop_Case_Ignorable_table[764] = {
0xa6, 0x05, 0x80, 0x8a, 0x80, 0xa2, 0x00, 0x80,
0xc6, 0x03, 0x00, 0x03, 0x01, 0x81, 0x41, 0xf6,
0x40, 0xbf, 0x19, 0x18, 0x88, 0x08, 0x80, 0x40,
@@ -207,7 +206,7 @@ static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
0x89, 0x8a, 0x00, 0xa2, 0x80, 0x89, 0x94, 0x8f,
0x80, 0xe4, 0x38, 0x89, 0x03, 0xa0, 0x00, 0x80,
0x9d, 0x9a, 0xda, 0x8a, 0xb9, 0x8a, 0x18, 0x08,
- 0x97, 0x97, 0xaa, 0x82, 0xab, 0x06, 0x0d, 0x87,
+ 0x97, 0x97, 0xaa, 0x82, 0xab, 0x06, 0x0c, 0x88,
0xa8, 0xb9, 0xb6, 0x00, 0x03, 0x3b, 0x02, 0x86,
0x89, 0x81, 0x8c, 0x80, 0x8e, 0x80, 0xb9, 0x03,
0x1f, 0x80, 0x93, 0x81, 0x99, 0x01, 0x81, 0xb8,
@@ -261,26 +260,29 @@ static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
0x80, 0x40, 0x94, 0x84, 0x44, 0x04, 0x28, 0xa9,
0x80, 0x88, 0x42, 0x45, 0x10, 0x0c, 0x83, 0xa7,
0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x83,
- 0x41, 0x82, 0x81, 0xcf, 0x82, 0xc5, 0x8a, 0xb0,
- 0x83, 0xfa, 0x80, 0xb5, 0x8e, 0xa8, 0x01, 0x81,
- 0x89, 0x82, 0xb0, 0x19, 0x09, 0x03, 0x80, 0x89,
- 0x80, 0xb1, 0x82, 0xa3, 0x20, 0x87, 0xbd, 0x80,
- 0x8b, 0x81, 0xb3, 0x88, 0x89, 0x19, 0x80, 0xde,
- 0x11, 0x00, 0x0d, 0x01, 0x80, 0x40, 0x9c, 0x02,
- 0x87, 0x94, 0x81, 0xb8, 0x0a, 0x80, 0xa4, 0x32,
- 0x84, 0x40, 0xc2, 0x39, 0x10, 0x80, 0x96, 0x80,
- 0xd3, 0x28, 0x03, 0x08, 0x81, 0x40, 0xed, 0x1d,
- 0x08, 0x81, 0x9a, 0x81, 0xd4, 0x39, 0x00, 0x81,
- 0xe9, 0x00, 0x01, 0x28, 0x80, 0xe4, 0x11, 0x18,
- 0x84, 0x41, 0x02, 0x88, 0x01, 0x40, 0xff, 0x08,
- 0x03, 0x80, 0x40, 0x8f, 0x19, 0x0b, 0x80, 0x9f,
- 0x89, 0xa7, 0x29, 0x1f, 0x80, 0x88, 0x29, 0x82,
- 0xad, 0x8c, 0x01, 0x41, 0x95, 0x30, 0x28, 0x80,
- 0xd1, 0x95, 0x0e, 0x01, 0x01, 0xf9, 0x2a, 0x00,
- 0x08, 0x30, 0x80, 0xc7, 0x0a, 0x00, 0x80, 0x41,
- 0x5a, 0x81, 0x8a, 0x81, 0xb3, 0x24, 0x00, 0x80,
- 0x54, 0xec, 0x90, 0x85, 0x8e, 0x60, 0x36, 0x99,
- 0x84, 0xba, 0x86, 0x88, 0x83, 0x44, 0x0a, 0x80,
+ 0xa5, 0x80, 0x99, 0x20, 0x80, 0x41, 0x3a, 0x81,
+ 0xce, 0x83, 0xc5, 0x8a, 0xb0, 0x83, 0xfa, 0x80,
+ 0xb5, 0x8e, 0xa8, 0x01, 0x81, 0x89, 0x82, 0xb0,
+ 0x19, 0x09, 0x03, 0x80, 0x89, 0x80, 0xb1, 0x82,
+ 0xa3, 0x20, 0x87, 0xbd, 0x80, 0x8b, 0x81, 0xb3,
+ 0x88, 0x89, 0x19, 0x80, 0xde, 0x11, 0x00, 0x0d,
+ 0x01, 0x80, 0x40, 0x9c, 0x02, 0x87, 0x94, 0x81,
+ 0xb8, 0x0a, 0x80, 0xa4, 0x32, 0x84, 0xc5, 0x85,
+ 0x8c, 0x00, 0x00, 0x80, 0x8d, 0x81, 0xd4, 0x39,
+ 0x10, 0x80, 0x96, 0x80, 0xd3, 0x28, 0x03, 0x08,
+ 0x81, 0x40, 0xed, 0x1d, 0x08, 0x81, 0x9a, 0x81,
+ 0xd4, 0x39, 0x00, 0x81, 0xe9, 0x00, 0x01, 0x28,
+ 0x80, 0xe4, 0x00, 0x01, 0x18, 0x84, 0x41, 0x02,
+ 0x88, 0x01, 0x40, 0xff, 0x08, 0x03, 0x80, 0x40,
+ 0x8f, 0x19, 0x0b, 0x80, 0x9f, 0x89, 0xa7, 0x29,
+ 0x1f, 0x80, 0x88, 0x29, 0x82, 0xad, 0x8c, 0x01,
+ 0x41, 0x95, 0x30, 0x28, 0x80, 0xd1, 0x95, 0x0e,
+ 0x01, 0x01, 0xf9, 0x2a, 0x00, 0x08, 0x30, 0x80,
+ 0xc7, 0x0a, 0x00, 0x80, 0x41, 0x5a, 0x81, 0x8a,
+ 0x81, 0xb3, 0x24, 0x00, 0x80, 0x96, 0x80, 0x54,
+ 0xd4, 0x90, 0x85, 0x8e, 0x60, 0x2c, 0xc7, 0x8b,
+ 0x12, 0x49, 0xbf, 0x84, 0xba, 0x86, 0x88, 0x83,
+ 0x41, 0xfb, 0x82, 0xa7, 0x81, 0x41, 0xe1, 0x80,
0xbe, 0x90, 0xbf, 0x08, 0x81, 0x60, 0x40, 0x0a,
0x18, 0x30, 0x81, 0x4c, 0x9d, 0x08, 0x83, 0x52,
0x5b, 0xad, 0x81, 0x96, 0x42, 0x1f, 0x82, 0x88,
@@ -289,38 +291,24 @@ static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
0x20, 0x8e, 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01,
0x04, 0x84, 0xbd, 0xa0, 0x80, 0x40, 0x9f, 0x8d,
0x41, 0x6f, 0x80, 0xbc, 0x83, 0x41, 0xfa, 0x84,
- 0x43, 0xdf, 0x86, 0xec, 0x87, 0x4a, 0xae, 0x84,
- 0x6c, 0x0c, 0x00, 0x80, 0x9d, 0xdf, 0xff, 0x40,
- 0xef,
+ 0x40, 0xfd, 0x81, 0x42, 0xdf, 0x86, 0xec, 0x87,
+ 0x4a, 0xae, 0x84, 0x6c, 0x0c, 0x00, 0x80, 0x9d,
+ 0xdf, 0xff, 0x40, 0xef,
};
-static const uint8_t unicode_prop_Case_Ignorable_index[69] = {
- 0xbe, 0x05, 0x00, // 005BE at 32
- 0xfe, 0x07, 0x00, // 007FE at 64
- 0x52, 0x0a, 0xa0, // 00A52 at 101
- 0xc1, 0x0b, 0x00, // 00BC1 at 128
- 0x82, 0x0d, 0x00, // 00D82 at 160
- 0x3f, 0x10, 0x80, // 0103F at 196
- 0xd4, 0x17, 0x40, // 017D4 at 226
- 0xcf, 0x1a, 0x20, // 01ACF at 257
- 0xf5, 0x1c, 0x00, // 01CF5 at 288
- 0x80, 0x20, 0x00, // 02080 at 320
- 0x16, 0xa0, 0x00, // 0A016 at 352
- 0xc6, 0xa8, 0x00, // 0A8C6 at 384
- 0xc2, 0xaa, 0x60, // 0AAC2 at 419
- 0x56, 0xfe, 0x20, // 0FE56 at 449
- 0xb1, 0x07, 0x01, // 107B1 at 480
- 0x75, 0x10, 0x01, // 11075 at 512
- 0xeb, 0x12, 0x21, // 112EB at 545
- 0x41, 0x16, 0x01, // 11641 at 576
- 0x5c, 0x1a, 0x01, // 11A5C at 608
- 0x43, 0x1f, 0x01, // 11F43 at 640
- 0x2e, 0xcf, 0x41, // 1CF2E at 674
- 0x25, 0xe0, 0x01, // 1E025 at 704
- 0xf0, 0x01, 0x0e, // E01F0 at 736 (upper bound)
+static const uint8_t unicode_prop_Case_Ignorable_index[72] = {
+ 0xbe, 0x05, 0x00, 0xfe, 0x07, 0x00, 0x52, 0x0a,
+ 0xa0, 0xc1, 0x0b, 0x00, 0x82, 0x0d, 0x00, 0x3f,
+ 0x10, 0x80, 0xd4, 0x17, 0x40, 0xcf, 0x1a, 0x20,
+ 0xf5, 0x1c, 0x00, 0x80, 0x20, 0x00, 0x16, 0xa0,
+ 0x00, 0xc6, 0xa8, 0x00, 0xc2, 0xaa, 0x60, 0x56,
+ 0xfe, 0x20, 0xb1, 0x07, 0x01, 0x02, 0x10, 0x01,
+ 0x42, 0x12, 0x41, 0xc4, 0x14, 0x21, 0xe1, 0x19,
+ 0x81, 0x48, 0x1d, 0x01, 0x44, 0x6b, 0x01, 0x83,
+ 0xd1, 0x21, 0x3e, 0xe1, 0x01, 0xf0, 0x01, 0x0e,
};
-static const uint8_t unicode_prop_ID_Start_table[1100] = {
+static const uint8_t unicode_prop_ID_Start_table[1133] = {
0xc0, 0x99, 0x85, 0x99, 0xae, 0x80, 0x89, 0x03,
0x04, 0x96, 0x80, 0x9e, 0x80, 0x41, 0xc9, 0x83,
0x8b, 0x8d, 0x26, 0x00, 0x80, 0x40, 0x80, 0x20,
@@ -364,7 +352,7 @@ static const uint8_t unicode_prop_ID_Start_table[1100] = {
0x83, 0x99, 0xb5, 0x96, 0x88, 0xb4, 0xd1, 0x80,
0xdc, 0xae, 0x90, 0x87, 0xb5, 0x9d, 0x8c, 0x81,
0x89, 0xab, 0x99, 0xa3, 0xa8, 0x82, 0x89, 0xa3,
- 0x81, 0x88, 0x86, 0xaa, 0x0a, 0xa8, 0x18, 0x28,
+ 0x81, 0x8a, 0x84, 0xaa, 0x0a, 0xa8, 0x18, 0x28,
0x0a, 0x04, 0x40, 0xbf, 0xbf, 0x41, 0x15, 0x0d,
0x81, 0xa5, 0x0d, 0x0f, 0x00, 0x00, 0x00, 0x80,
0x9e, 0x81, 0xb4, 0x06, 0x00, 0x12, 0x06, 0x13,
@@ -380,8 +368,8 @@ static const uint8_t unicode_prop_ID_Start_table[1100] = {
0x41, 0xff, 0x59, 0xbf, 0xbf, 0x60, 0x56, 0x8c,
0xc2, 0xad, 0x81, 0x41, 0x0c, 0x82, 0x8f, 0x89,
0x81, 0x93, 0xae, 0x8f, 0x9e, 0x81, 0xcf, 0xa6,
- 0x88, 0x81, 0xe6, 0x81, 0xbf, 0x21, 0x00, 0x04,
- 0x97, 0x8f, 0x02, 0x03, 0x80, 0x96, 0x9c, 0xb3,
+ 0x88, 0x81, 0xe6, 0x81, 0xc2, 0x09, 0x00, 0x07,
+ 0x94, 0x8f, 0x02, 0x03, 0x80, 0x96, 0x9c, 0xb3,
0x8d, 0xb1, 0xbd, 0x2a, 0x00, 0x81, 0x8a, 0x9b,
0x89, 0x96, 0x98, 0x9c, 0x86, 0xae, 0x9b, 0x80,
0x8f, 0x20, 0x89, 0x89, 0x20, 0xa8, 0x96, 0x10,
@@ -401,112 +389,95 @@ static const uint8_t unicode_prop_ID_Start_table[1100] = {
0xa5, 0x89, 0x9d, 0x81, 0xa3, 0x1f, 0x04, 0xa9,
0x40, 0x9d, 0x91, 0xa3, 0x83, 0xa3, 0x83, 0xa7,
0x87, 0xb3, 0x8b, 0x8a, 0x80, 0x8e, 0x06, 0x01,
- 0x80, 0x8a, 0x80, 0x8e, 0x06, 0x01, 0xc2, 0x41,
- 0x36, 0x88, 0x95, 0x89, 0x87, 0x97, 0x28, 0xa9,
- 0x80, 0x88, 0xc4, 0x29, 0x00, 0xab, 0x01, 0x10,
- 0x81, 0x96, 0x89, 0x96, 0x88, 0x9e, 0xc0, 0x92,
- 0x01, 0x89, 0x95, 0x89, 0x99, 0xc5, 0xb7, 0x29,
- 0xbf, 0x80, 0x8e, 0x18, 0x10, 0x9c, 0xa9, 0x9c,
- 0x82, 0x9c, 0xa2, 0x38, 0x9b, 0x9a, 0xb5, 0x89,
- 0x95, 0x89, 0x92, 0x8c, 0x91, 0xed, 0xc8, 0xb6,
- 0xb2, 0x8c, 0xb2, 0x8c, 0xa3, 0x41, 0x5b, 0xa9,
- 0x29, 0xcd, 0x9c, 0x89, 0x07, 0x95, 0xa9, 0x91,
+ 0x80, 0x8a, 0x80, 0x8e, 0x06, 0x01, 0x82, 0xb3,
+ 0x8b, 0x41, 0x36, 0x88, 0x95, 0x89, 0x87, 0x97,
+ 0x28, 0xa9, 0x80, 0x88, 0xc4, 0x29, 0x00, 0xab,
+ 0x01, 0x10, 0x81, 0x96, 0x89, 0x96, 0x88, 0x9e,
+ 0xc0, 0x92, 0x01, 0x89, 0x95, 0x89, 0x99, 0xc5,
+ 0xb7, 0x29, 0xbf, 0x80, 0x8e, 0x18, 0x10, 0x9c,
+ 0xa9, 0x9c, 0x82, 0x9c, 0xa2, 0x38, 0x9b, 0x9a,
+ 0xb5, 0x89, 0x95, 0x89, 0x92, 0x8c, 0x91, 0xed,
+ 0xc8, 0xb6, 0xb2, 0x8c, 0xb2, 0x8c, 0xa3, 0xa5,
+ 0x9b, 0x88, 0x96, 0x40, 0xf9, 0xa9, 0x29, 0x8f,
+ 0x82, 0xba, 0x9c, 0x89, 0x07, 0x95, 0xa9, 0x91,
0xad, 0x94, 0x9a, 0x96, 0x8b, 0xb4, 0xb8, 0x09,
0x80, 0x8c, 0xac, 0x9f, 0x98, 0x99, 0xa3, 0x9c,
0x01, 0x07, 0xa2, 0x10, 0x8b, 0xaf, 0x8d, 0x83,
0x94, 0x00, 0x80, 0xa2, 0x91, 0x80, 0x98, 0x92,
0x81, 0xbe, 0x30, 0x00, 0x18, 0x8e, 0x80, 0x89,
0x86, 0xae, 0xa5, 0x39, 0x09, 0x95, 0x06, 0x01,
- 0x04, 0x10, 0x91, 0x80, 0x8b, 0x84, 0x40, 0x9d,
- 0xb4, 0x91, 0x83, 0x93, 0x82, 0x9d, 0xaf, 0x93,
- 0x08, 0x80, 0x40, 0xb7, 0xae, 0xa8, 0x83, 0xa3,
- 0xaf, 0x93, 0x80, 0xba, 0xaa, 0x8c, 0x80, 0xc6,
- 0x9a, 0xa4, 0x86, 0x40, 0xb8, 0xab, 0xf3, 0xbf,
- 0x9e, 0x39, 0x01, 0x38, 0x08, 0x97, 0x8e, 0x00,
- 0x80, 0xdd, 0x39, 0xa6, 0x8f, 0x00, 0x80, 0x9b,
- 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a, 0xad,
- 0x92, 0x80, 0x91, 0xc8, 0x41, 0x06, 0x88, 0x80,
- 0xa4, 0x90, 0x80, 0xb0, 0x9d, 0xef, 0x30, 0x08,
- 0xa5, 0x94, 0x80, 0x98, 0x28, 0x08, 0x9f, 0x8d,
- 0x80, 0x41, 0x46, 0x92, 0x8e, 0x00, 0x8c, 0x80,
- 0xa1, 0xfb, 0x80, 0xce, 0x43, 0x99, 0xe5, 0xee,
- 0x90, 0x40, 0xc3, 0x4a, 0x4b, 0xe0, 0x8e, 0x44,
- 0x2f, 0x90, 0x85, 0x4f, 0xb8, 0x42, 0x46, 0x60,
- 0x21, 0xb8, 0x42, 0x38, 0x86, 0x9e, 0x90, 0xce,
- 0x90, 0x9d, 0x91, 0xaf, 0x8f, 0x83, 0x9e, 0x94,
- 0x84, 0x92, 0x42, 0xaf, 0xbf, 0xff, 0xca, 0x20,
- 0xc1, 0x8c, 0xbf, 0x08, 0x80, 0x9b, 0x57, 0xf7,
- 0x87, 0x44, 0xd5, 0xa9, 0x88, 0x60, 0x22, 0xe6,
- 0x18, 0x30, 0x08, 0x41, 0x22, 0x8e, 0x80, 0x9c,
- 0x11, 0x80, 0x8d, 0x1f, 0x41, 0x8b, 0x49, 0x03,
- 0xea, 0x84, 0x8c, 0x82, 0x88, 0x86, 0x89, 0x57,
- 0x65, 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b,
- 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f,
- 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80,
- 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, 0x80, 0x9e,
- 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e,
- 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x07, 0x47,
- 0x33, 0x9e, 0x2d, 0x41, 0x04, 0xbd, 0x40, 0x91,
- 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41, 0x40, 0x9d,
- 0x91, 0xab, 0x41, 0xe3, 0x9b, 0x42, 0xf3, 0x30,
- 0x18, 0x08, 0x8e, 0x80, 0x40, 0xc4, 0xba, 0xc3,
- 0x30, 0x44, 0xb3, 0x18, 0x9a, 0x01, 0x00, 0x08,
- 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, 0x18, 0x00,
- 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00,
- 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90,
- 0x51, 0x43, 0x60, 0xa6, 0xdf, 0x9f, 0x50, 0x39,
- 0x85, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d,
- 0x30, 0x4c, 0x1e, 0x42, 0x1d, 0x45, 0xe1, 0x53,
- 0x4a, 0x84, 0x50, 0x5f,
+ 0x04, 0x10, 0x91, 0x80, 0x8b, 0x84, 0x9d, 0x89,
+ 0x00, 0x08, 0x80, 0xa5, 0x00, 0x98, 0x00, 0x80,
+ 0xab, 0xb4, 0x91, 0x83, 0x93, 0x82, 0x9d, 0xaf,
+ 0x93, 0x08, 0x80, 0x40, 0xb7, 0xae, 0xa8, 0x83,
+ 0xa3, 0xaf, 0x93, 0x80, 0xba, 0xaa, 0x8c, 0x80,
+ 0xc6, 0x9a, 0xa4, 0x86, 0x40, 0xb8, 0xab, 0xf3,
+ 0xbf, 0x9e, 0x39, 0x01, 0x38, 0x08, 0x97, 0x8e,
+ 0x00, 0x80, 0xdd, 0x39, 0xa6, 0x8f, 0x00, 0x80,
+ 0x9b, 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a,
+ 0xad, 0x92, 0x80, 0x91, 0xc8, 0x40, 0xc6, 0xa0,
+ 0x9e, 0x88, 0x80, 0xa4, 0x90, 0x80, 0xb0, 0x9d,
+ 0xef, 0x30, 0x08, 0xa5, 0x94, 0x80, 0x98, 0x28,
+ 0x08, 0x9f, 0x8d, 0x80, 0x41, 0x46, 0x92, 0x8e,
+ 0x00, 0x8c, 0x80, 0xa1, 0xfb, 0x80, 0xce, 0x43,
+ 0x99, 0xe5, 0xee, 0x90, 0x40, 0xc3, 0x4a, 0x4b,
+ 0xe0, 0x8e, 0x44, 0x2f, 0x90, 0x85, 0x98, 0x4f,
+ 0x9a, 0x84, 0x42, 0x46, 0x5a, 0xb8, 0x9d, 0x46,
+ 0xe1, 0x42, 0x38, 0x86, 0x9e, 0x90, 0xce, 0x90,
+ 0x9d, 0x91, 0xaf, 0x8f, 0x83, 0x9e, 0x94, 0x84,
+ 0x92, 0x41, 0xaf, 0xac, 0x40, 0xd2, 0xbf, 0xff,
+ 0xca, 0x20, 0xc1, 0x8c, 0xbf, 0x08, 0x80, 0x9b,
+ 0x57, 0xf7, 0x87, 0x44, 0xd5, 0xa8, 0x89, 0x60,
+ 0x22, 0xe6, 0x18, 0x30, 0x08, 0x41, 0x22, 0x8e,
+ 0x80, 0x9c, 0x11, 0x80, 0x8d, 0x1f, 0x41, 0x8b,
+ 0x49, 0x03, 0xea, 0x84, 0x8c, 0x82, 0x88, 0x86,
+ 0x89, 0x57, 0x65, 0xd4, 0x80, 0xc6, 0x01, 0x08,
+ 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0,
+ 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00,
+ 0x16, 0x80, 0x41, 0x53, 0x81, 0x98, 0x80, 0x98,
+ 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98,
+ 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98,
+ 0x07, 0x47, 0x33, 0x9e, 0x2d, 0x41, 0x04, 0xbd,
+ 0x40, 0x91, 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41,
+ 0x40, 0x9d, 0x91, 0xab, 0x41, 0xe3, 0x9b, 0x40,
+ 0xe3, 0x9d, 0x08, 0x41, 0xee, 0x30, 0x18, 0x08,
+ 0x8e, 0x80, 0x40, 0xc4, 0xba, 0xc3, 0x30, 0x44,
+ 0xb3, 0x18, 0x9a, 0x01, 0x00, 0x08, 0x80, 0x89,
+ 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x02,
+ 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00, 0x80, 0x89,
+ 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, 0x51, 0x43,
+ 0x60, 0xa6, 0xdf, 0x9f, 0x50, 0x39, 0x85, 0x40,
+ 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x8e,
+ 0x42, 0x6d, 0x49, 0xa1, 0x42, 0x1d, 0x45, 0xe1,
+ 0x53, 0x4a, 0x84, 0x50, 0x5f,
};
-static const uint8_t unicode_prop_ID_Start_index[105] = {
- 0xf6, 0x03, 0x20, // 003F6 at 33
- 0xa6, 0x07, 0x00, // 007A6 at 64
- 0xa9, 0x09, 0x20, // 009A9 at 97
- 0xb1, 0x0a, 0x00, // 00AB1 at 128
- 0xba, 0x0b, 0x20, // 00BBA at 161
- 0x3b, 0x0d, 0x20, // 00D3B at 193
- 0xc7, 0x0e, 0x20, // 00EC7 at 225
- 0x49, 0x12, 0x00, // 01249 at 256
- 0x9b, 0x16, 0x00, // 0169B at 288
- 0xac, 0x19, 0x00, // 019AC at 320
- 0xc0, 0x1d, 0x80, // 01DC0 at 356
- 0x80, 0x20, 0x20, // 02080 at 385
- 0x70, 0x2d, 0x00, // 02D70 at 416
- 0x00, 0x32, 0x00, // 03200 at 448
- 0xda, 0xa7, 0x00, // 0A7DA at 480
- 0x4c, 0xaa, 0x20, // 0AA4C at 513
- 0xc7, 0xd7, 0x20, // 0D7C7 at 545
- 0xfc, 0xfd, 0x20, // 0FDFC at 577
- 0x9d, 0x02, 0x21, // 1029D at 609
- 0x96, 0x05, 0x01, // 10596 at 640
- 0xf3, 0x08, 0x01, // 108F3 at 672
- 0xb3, 0x0c, 0x21, // 10CB3 at 705
- 0x73, 0x11, 0x61, // 11173 at 739
- 0x34, 0x13, 0x01, // 11334 at 768
- 0x1b, 0x17, 0x21, // 1171B at 801
- 0x8a, 0x1a, 0x01, // 11A8A at 832
- 0x34, 0x1f, 0x21, // 11F34 at 865
- 0xbf, 0x6a, 0x01, // 16ABF at 896
- 0x23, 0xb1, 0xa1, // 1B123 at 933
- 0xad, 0xd4, 0x01, // 1D4AD at 960
- 0x6f, 0xd7, 0x01, // 1D76F at 992
- 0xff, 0xe7, 0x61, // 1E7FF at 1027
- 0x5e, 0xee, 0x01, // 1EE5E at 1056
- 0xe1, 0xeb, 0x22, // 2EBE1 at 1089
- 0xb0, 0x23, 0x03, // 323B0 at 1120 (upper bound)
+static const uint8_t unicode_prop_ID_Start_index[108] = {
+ 0xf6, 0x03, 0x20, 0xa6, 0x07, 0x00, 0xa9, 0x09,
+ 0x20, 0xb1, 0x0a, 0x00, 0xba, 0x0b, 0x20, 0x3b,
+ 0x0d, 0x20, 0xc7, 0x0e, 0x20, 0x49, 0x12, 0x00,
+ 0x9b, 0x16, 0x00, 0xac, 0x19, 0x00, 0xc0, 0x1d,
+ 0x80, 0x80, 0x20, 0x20, 0x70, 0x2d, 0x00, 0x00,
+ 0x32, 0x00, 0xdd, 0xa7, 0x00, 0x4c, 0xaa, 0x20,
+ 0xc7, 0xd7, 0x20, 0xfc, 0xfd, 0x20, 0x9d, 0x02,
+ 0x21, 0x96, 0x05, 0x01, 0x9f, 0x08, 0x01, 0x49,
+ 0x0c, 0x21, 0x76, 0x10, 0x21, 0xa9, 0x12, 0x01,
+ 0xb0, 0x14, 0x01, 0x42, 0x19, 0x41, 0x90, 0x1c,
+ 0x01, 0xf1, 0x2f, 0x21, 0x90, 0x6b, 0x21, 0x33,
+ 0xb1, 0x21, 0x06, 0xd5, 0x01, 0xc3, 0xd7, 0x01,
+ 0xff, 0xe7, 0x21, 0x63, 0xee, 0x01, 0x5e, 0xee,
+ 0x42, 0xb0, 0x23, 0x03,
};
-static const uint8_t unicode_prop_ID_Continue1_table[660] = {
+static const uint8_t unicode_prop_ID_Continue1_table[695] = {
0xaf, 0x89, 0xa4, 0x80, 0xd6, 0x80, 0x42, 0x47,
0xef, 0x96, 0x80, 0x40, 0xfa, 0x84, 0x41, 0x08,
0xac, 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf,
0x9e, 0x28, 0xe4, 0x31, 0x29, 0x08, 0x19, 0x89,
0x96, 0x80, 0x9d, 0x9a, 0xda, 0x8a, 0x8e, 0x89,
0xa0, 0x88, 0x88, 0x80, 0x97, 0x18, 0x88, 0x02,
- 0x04, 0xaa, 0x82, 0xbb, 0x87, 0xa9, 0x97, 0x80,
+ 0x04, 0xaa, 0x82, 0xba, 0x88, 0xa9, 0x97, 0x80,
0xa0, 0xb5, 0x10, 0x91, 0x06, 0x89, 0x09, 0x89,
0x90, 0x82, 0xb7, 0x00, 0x31, 0x09, 0x82, 0x88,
0x80, 0x89, 0x09, 0x89, 0x8d, 0x01, 0x82, 0xb7,
@@ -535,83 +506,83 @@ static const uint8_t unicode_prop_ID_Continue1_table[660] = {
0xae, 0x90, 0x8a, 0x89, 0x90, 0x88, 0x8b, 0x82,
0x9d, 0x8c, 0x81, 0x89, 0xab, 0x8d, 0xaf, 0x93,
0x87, 0x89, 0x85, 0x89, 0xf5, 0x10, 0x94, 0x18,
- 0x28, 0x0a, 0x40, 0xc5, 0xbf, 0x42, 0x3e, 0x81,
- 0x92, 0x80, 0xfa, 0x8c, 0x18, 0x82, 0x8b, 0x4b,
- 0xfd, 0x82, 0x40, 0x8c, 0x80, 0xdf, 0x9f, 0x42,
- 0x29, 0x85, 0xe8, 0x81, 0x60, 0x75, 0x84, 0x89,
- 0xc4, 0x03, 0x89, 0x9f, 0x81, 0xcf, 0x81, 0x41,
- 0x0f, 0x02, 0x03, 0x80, 0x96, 0x23, 0x80, 0xd2,
- 0x81, 0xb1, 0x91, 0x89, 0x89, 0x85, 0x91, 0x8c,
- 0x8a, 0x9b, 0x87, 0x98, 0x8c, 0xab, 0x83, 0xae,
- 0x8d, 0x8e, 0x89, 0x8a, 0x80, 0x89, 0x89, 0xae,
- 0x8d, 0x8b, 0x07, 0x09, 0x89, 0xa0, 0x82, 0xb1,
- 0x00, 0x11, 0x0c, 0x08, 0x80, 0xa8, 0x24, 0x81,
- 0x40, 0xeb, 0x38, 0x09, 0x89, 0x60, 0x4f, 0x23,
- 0x80, 0x42, 0xe0, 0x8f, 0x8f, 0x8f, 0x11, 0x97,
- 0x82, 0x40, 0xbf, 0x89, 0xa4, 0x80, 0x42, 0xbc,
- 0x80, 0x40, 0xe1, 0x80, 0x40, 0x94, 0x84, 0x41,
- 0x24, 0x89, 0x45, 0x56, 0x10, 0x0c, 0x83, 0xa7,
- 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x1f,
- 0x89, 0x41, 0x70, 0x81, 0xcf, 0x82, 0xc5, 0x8a,
- 0xb0, 0x83, 0xf9, 0x82, 0xb4, 0x8e, 0x9e, 0x8a,
- 0x09, 0x89, 0x83, 0xac, 0x8a, 0x30, 0xac, 0x89,
- 0x2a, 0xa3, 0x8d, 0x80, 0x89, 0x21, 0xab, 0x80,
- 0x8b, 0x82, 0xaf, 0x8d, 0x3b, 0x80, 0x8b, 0xd1,
- 0x8b, 0x28, 0x08, 0x40, 0x9c, 0x8b, 0x84, 0x89,
- 0x2b, 0xb6, 0x08, 0x31, 0x09, 0x82, 0x88, 0x80,
- 0x89, 0x09, 0x32, 0x84, 0x40, 0xbf, 0x91, 0x88,
- 0x89, 0x18, 0xd0, 0x93, 0x8b, 0x89, 0x40, 0xd4,
- 0x31, 0x88, 0x9a, 0x81, 0xd1, 0x90, 0x8e, 0x89,
- 0xd0, 0x8c, 0x87, 0x89, 0xd2, 0x8e, 0x83, 0x89,
- 0x40, 0xf1, 0x8e, 0x40, 0xa4, 0x89, 0xc5, 0x28,
- 0x09, 0x18, 0x00, 0x81, 0x8b, 0x89, 0xf6, 0x31,
- 0x32, 0x80, 0x9b, 0x89, 0xa7, 0x30, 0x1f, 0x80,
- 0x88, 0x8a, 0xad, 0x8f, 0x41, 0x94, 0x38, 0x87,
- 0x8f, 0x89, 0xb7, 0x95, 0x80, 0x8d, 0xf9, 0x2a,
- 0x00, 0x08, 0x30, 0x07, 0x89, 0xaf, 0x20, 0x08,
- 0x27, 0x89, 0x41, 0x48, 0x83, 0x88, 0x08, 0x80,
- 0xaf, 0x32, 0x84, 0x8c, 0x89, 0x54, 0xe5, 0x05,
- 0x8e, 0x60, 0x36, 0x09, 0x89, 0xd5, 0x89, 0xa5,
- 0x84, 0xba, 0x86, 0x98, 0x89, 0x43, 0xf4, 0x00,
- 0xb6, 0x33, 0xd0, 0x80, 0x8a, 0x81, 0x60, 0x4c,
- 0xaa, 0x81, 0x52, 0x60, 0xad, 0x81, 0x96, 0x42,
- 0x1d, 0x22, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x40,
- 0x93, 0x82, 0x45, 0x88, 0xb1, 0x41, 0xff, 0xb6,
- 0x83, 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e,
- 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0xe3,
- 0x80, 0x40, 0x9f, 0x86, 0x88, 0x89, 0x41, 0x63,
- 0x80, 0xbc, 0x8d, 0x41, 0xf1, 0x8d, 0x43, 0xd5,
- 0x86, 0xec, 0x34, 0x89, 0x52, 0x95, 0x89, 0x6c,
- 0x05, 0x05, 0x40, 0xef,
+ 0x28, 0x0a, 0x40, 0xc5, 0xbf, 0x42, 0x0b, 0x81,
+ 0xb0, 0x81, 0x92, 0x80, 0xfa, 0x8c, 0x18, 0x82,
+ 0x8b, 0x4b, 0xfd, 0x82, 0x40, 0x8c, 0x80, 0xdf,
+ 0x9f, 0x42, 0x29, 0x85, 0xe8, 0x81, 0xdf, 0x80,
+ 0x60, 0x75, 0x23, 0x89, 0xc4, 0x03, 0x89, 0x9f,
+ 0x81, 0xcf, 0x81, 0x41, 0x0f, 0x02, 0x03, 0x80,
+ 0x96, 0x23, 0x80, 0xd2, 0x81, 0xb1, 0x91, 0x89,
+ 0x89, 0x85, 0x91, 0x8c, 0x8a, 0x9b, 0x87, 0x98,
+ 0x8c, 0xab, 0x83, 0xae, 0x8d, 0x8e, 0x89, 0x8a,
+ 0x80, 0x89, 0x89, 0xae, 0x8d, 0x8b, 0x07, 0x09,
+ 0x89, 0xa0, 0x82, 0xb1, 0x00, 0x11, 0x0c, 0x08,
+ 0x80, 0xa8, 0x24, 0x81, 0x40, 0xeb, 0x38, 0x09,
+ 0x89, 0x60, 0x4f, 0x23, 0x80, 0x42, 0xe0, 0x8f,
+ 0x8f, 0x8f, 0x11, 0x97, 0x82, 0x40, 0xbf, 0x89,
+ 0xa4, 0x80, 0xa4, 0x80, 0x42, 0x96, 0x80, 0x40,
+ 0xe1, 0x80, 0x40, 0x94, 0x84, 0x41, 0x24, 0x89,
+ 0x45, 0x56, 0x10, 0x0c, 0x83, 0xa7, 0x13, 0x80,
+ 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x1f, 0x89, 0x85,
+ 0x89, 0x9e, 0x84, 0x41, 0x3c, 0x81, 0xce, 0x83,
+ 0xc5, 0x8a, 0xb0, 0x83, 0xf9, 0x82, 0xb4, 0x8e,
+ 0x9e, 0x8a, 0x09, 0x89, 0x83, 0xac, 0x8a, 0x30,
+ 0xac, 0x89, 0x2a, 0xa3, 0x8d, 0x80, 0x89, 0x21,
+ 0xab, 0x80, 0x8b, 0x82, 0xaf, 0x8d, 0x3b, 0x80,
+ 0x8b, 0xd1, 0x8b, 0x28, 0x08, 0x40, 0x9c, 0x8b,
+ 0x84, 0x89, 0x2b, 0xb6, 0x08, 0x31, 0x09, 0x82,
+ 0x88, 0x80, 0x89, 0x09, 0x32, 0x84, 0xc2, 0x88,
+ 0x00, 0x08, 0x03, 0x04, 0x00, 0x8d, 0x81, 0xd1,
+ 0x91, 0x88, 0x89, 0x18, 0xd0, 0x93, 0x8b, 0x89,
+ 0x40, 0xd4, 0x31, 0x88, 0x9a, 0x81, 0xd1, 0x90,
+ 0x8e, 0x89, 0xd0, 0x8c, 0x87, 0x89, 0x85, 0x93,
+ 0xb8, 0x8e, 0x83, 0x89, 0x40, 0xf1, 0x8e, 0x40,
+ 0xa4, 0x89, 0xc5, 0x28, 0x09, 0x18, 0x00, 0x81,
+ 0x8b, 0x89, 0xf6, 0x31, 0x32, 0x80, 0x9b, 0x89,
+ 0xa7, 0x30, 0x1f, 0x80, 0x88, 0x8a, 0xad, 0x8f,
+ 0x41, 0x55, 0x89, 0xb4, 0x38, 0x87, 0x8f, 0x89,
+ 0xb7, 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00, 0x08,
+ 0x30, 0x07, 0x89, 0xaf, 0x20, 0x08, 0x27, 0x89,
+ 0x41, 0x48, 0x83, 0x88, 0x08, 0x80, 0xaf, 0x32,
+ 0x84, 0x8c, 0x8a, 0x54, 0xe4, 0x05, 0x8e, 0x60,
+ 0x2c, 0xc7, 0x9b, 0x49, 0x25, 0x89, 0xd5, 0x89,
+ 0xa5, 0x84, 0xba, 0x86, 0x98, 0x89, 0x42, 0x15,
+ 0x89, 0x41, 0xd4, 0x00, 0xb6, 0x33, 0xd0, 0x80,
+ 0x8a, 0x81, 0x60, 0x4c, 0xaa, 0x81, 0x50, 0x50,
+ 0x89, 0x42, 0x05, 0xad, 0x81, 0x96, 0x42, 0x1d,
+ 0x22, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x40, 0x93,
+ 0x82, 0x45, 0x88, 0xb1, 0x41, 0xff, 0xb6, 0x83,
+ 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e, 0x45,
+ 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0xe3, 0x80,
+ 0x40, 0x9f, 0x86, 0x88, 0x89, 0x41, 0x63, 0x80,
+ 0xbc, 0x8d, 0x41, 0xf1, 0x8d, 0x40, 0xf3, 0x08,
+ 0x89, 0x42, 0xd4, 0x86, 0xec, 0x34, 0x89, 0x52,
+ 0x95, 0x89, 0x6c, 0x05, 0x05, 0x40, 0xef,
+};
+
+static const uint8_t unicode_prop_ID_Continue1_index[66] = {
+ 0xfa, 0x06, 0x00, 0x70, 0x09, 0x00, 0xf0, 0x0a,
+ 0x40, 0x57, 0x0c, 0x00, 0xf0, 0x0d, 0x60, 0xc7,
+ 0x0f, 0x20, 0xea, 0x17, 0x40, 0x05, 0x1b, 0x00,
+ 0x0e, 0x20, 0x00, 0xa0, 0xa6, 0x20, 0xe6, 0xa9,
+ 0x20, 0x10, 0xfe, 0x00, 0x40, 0x0a, 0x01, 0xc3,
+ 0x10, 0x01, 0x4e, 0x13, 0x01, 0x41, 0x16, 0x01,
+ 0x0b, 0x1a, 0x01, 0xaa, 0x1d, 0x01, 0x7a, 0x6d,
+ 0x21, 0x45, 0xd2, 0x21, 0xaf, 0xe2, 0x01, 0xf0,
+ 0x01, 0x0e,
};
-static const uint8_t unicode_prop_ID_Continue1_index[63] = {
- 0xfa, 0x06, 0x00, // 006FA at 32
- 0x70, 0x09, 0x00, // 00970 at 64
- 0xf0, 0x0a, 0x40, // 00AF0 at 98
- 0x57, 0x0c, 0x00, // 00C57 at 128
- 0xf0, 0x0d, 0x60, // 00DF0 at 163
- 0xc7, 0x0f, 0x20, // 00FC7 at 193
- 0xea, 0x17, 0x40, // 017EA at 226
- 0x05, 0x1b, 0x00, // 01B05 at 256
- 0x41, 0x20, 0x00, // 02041 at 288
- 0x0c, 0xa8, 0x80, // 0A80C at 324
- 0x37, 0xaa, 0x20, // 0AA37 at 353
- 0x50, 0xfe, 0x20, // 0FE50 at 385
- 0x3a, 0x0d, 0x21, // 10D3A at 417
- 0x74, 0x11, 0x01, // 11174 at 448
- 0x5a, 0x14, 0x21, // 1145A at 481
- 0x44, 0x19, 0x81, // 11944 at 516
- 0x5a, 0x1d, 0xa1, // 11D5A at 549
- 0xf5, 0x6a, 0x21, // 16AF5 at 577
- 0x45, 0xd2, 0x41, // 1D245 at 610
- 0xaf, 0xe2, 0x21, // 1E2AF at 641
- 0xf0, 0x01, 0x0e, // E01F0 at 672 (upper bound)
+static const uint8_t unicode_prop_White_Space_table[22] = {
+ 0x88, 0x84, 0x91, 0x80, 0xe3, 0x80, 0x99, 0x80,
+ 0x55, 0xde, 0x80, 0x49, 0x7e, 0x8a, 0x9c, 0x0c,
+ 0x80, 0xae, 0x80, 0x4f, 0x9f, 0x80,
};
-#ifdef CONFIG_ALL_UNICODE
+static const uint8_t unicode_prop_White_Space_index[3] = {
+ 0x01, 0x30, 0x00,
+};
-static const uint8_t unicode_cc_table[899] = {
+static const uint8_t unicode_cc_table[916] = {
0xb2, 0xcf, 0xd4, 0x00, 0xe8, 0x03, 0xdc, 0x00,
0xe8, 0x00, 0xd8, 0x04, 0xdc, 0x01, 0xca, 0x03,
0xdc, 0x01, 0xca, 0x0a, 0xdc, 0x04, 0x01, 0x03,
@@ -635,7 +606,7 @@ static const uint8_t unicode_cc_table[899] = {
0xc0, 0x00, 0xdc, 0xc0, 0x00, 0xdc, 0xc1, 0xb0,
0x6f, 0xc6, 0x00, 0xdc, 0xc0, 0x88, 0x00, 0xdc,
0x97, 0xc3, 0x80, 0xc8, 0x80, 0xc2, 0x80, 0xc4,
- 0xaa, 0x02, 0xdc, 0xb0, 0x0b, 0xc0, 0x02, 0xdc,
+ 0xaa, 0x02, 0xdc, 0xb0, 0x0a, 0xc1, 0x02, 0xdc,
0xc3, 0xa9, 0xc4, 0x04, 0xdc, 0xcd, 0x80, 0x00,
0xdc, 0xc1, 0x00, 0xdc, 0xc1, 0x00, 0xdc, 0xc2,
0x02, 0xdc, 0x42, 0x1b, 0xc2, 0x00, 0xdc, 0xc1,
@@ -693,73 +664,57 @@ static const uint8_t unicode_cc_table[899] = {
0xdc, 0xb0, 0xb1, 0x00, 0xdc, 0xb0, 0x64, 0xc4,
0xb6, 0x61, 0x00, 0xdc, 0x80, 0xc0, 0xa7, 0xc0,
0x00, 0x01, 0x00, 0xdc, 0x83, 0x00, 0x09, 0xb0,
- 0x74, 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, 0xb1,
- 0x52, 0xc1, 0xb0, 0x1f, 0x02, 0xdc, 0xb0, 0x15,
- 0x01, 0xdc, 0xc2, 0x00, 0xdc, 0xc0, 0x03, 0xdc,
- 0xb0, 0x00, 0xc0, 0x00, 0xdc, 0xc0, 0x00, 0xdc,
- 0xb0, 0x8f, 0x00, 0x09, 0xa8, 0x00, 0x09, 0x8d,
- 0x00, 0x09, 0xb0, 0x08, 0x00, 0x09, 0x00, 0x07,
- 0xb0, 0x14, 0xc2, 0xaf, 0x01, 0x09, 0xb0, 0x0d,
- 0x00, 0x07, 0xb0, 0x1b, 0x00, 0x09, 0x88, 0x00,
- 0x07, 0xb0, 0x39, 0x00, 0x09, 0x00, 0x07, 0xb0,
- 0x81, 0x00, 0x07, 0x00, 0x09, 0xb0, 0x1f, 0x01,
- 0x07, 0x8f, 0x00, 0x09, 0x97, 0xc6, 0x82, 0xc4,
- 0xb0, 0x9c, 0x00, 0x09, 0x82, 0x00, 0x07, 0x96,
- 0xc0, 0xb0, 0x32, 0x00, 0x09, 0x00, 0x07, 0xb0,
- 0xca, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x4d, 0x00,
- 0x09, 0xb0, 0x45, 0x00, 0x09, 0x00, 0x07, 0xb0,
- 0x42, 0x00, 0x09, 0xb0, 0xdc, 0x00, 0x09, 0x00,
- 0x07, 0xb0, 0xd1, 0x01, 0x09, 0x83, 0x00, 0x07,
- 0xb0, 0x6b, 0x00, 0x09, 0xb0, 0x22, 0x00, 0x09,
- 0x91, 0x00, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1,
- 0x74, 0x00, 0x09, 0xb0, 0xd1, 0x00, 0x07, 0x80,
- 0x01, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, 0x78,
- 0x01, 0x09, 0xb8, 0x43, 0x7c, 0x04, 0x01, 0xb0,
- 0x0a, 0xc6, 0xb4, 0x88, 0x01, 0x06, 0xb8, 0x44,
- 0x7b, 0x00, 0x01, 0xb8, 0x0c, 0x95, 0x01, 0xd8,
- 0x02, 0x01, 0x82, 0x00, 0xe2, 0x04, 0xd8, 0x87,
- 0x07, 0xdc, 0x81, 0xc4, 0x01, 0xdc, 0x9d, 0xc3,
- 0xb0, 0x63, 0xc2, 0xb8, 0x05, 0x8a, 0xc6, 0x80,
- 0xd0, 0x81, 0xc6, 0x80, 0xc1, 0x80, 0xc4, 0xb0,
- 0x33, 0xc0, 0xb0, 0x6f, 0xc6, 0xb1, 0x46, 0xc0,
- 0xb0, 0x0c, 0xc3, 0xb1, 0xcb, 0x01, 0xe8, 0x00,
- 0xdc, 0xc0, 0xb3, 0xaf, 0x06, 0xdc, 0xb0, 0x3c,
- 0xc5, 0x00, 0x07,
+ 0x74, 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, 0xb0,
+ 0x10, 0xc4, 0xb1, 0x0c, 0xc1, 0xb0, 0x1f, 0x02,
+ 0xdc, 0xb0, 0x15, 0x01, 0xdc, 0xc2, 0x00, 0xdc,
+ 0xc0, 0x03, 0xdc, 0xb0, 0x00, 0xc0, 0x00, 0xdc,
+ 0xc0, 0x00, 0xdc, 0xb0, 0x8f, 0x00, 0x09, 0xa8,
+ 0x00, 0x09, 0x8d, 0x00, 0x09, 0xb0, 0x08, 0x00,
+ 0x09, 0x00, 0x07, 0xb0, 0x14, 0xc2, 0xaf, 0x01,
+ 0x09, 0xb0, 0x0d, 0x00, 0x07, 0xb0, 0x1b, 0x00,
+ 0x09, 0x88, 0x00, 0x07, 0xb0, 0x39, 0x00, 0x09,
+ 0x00, 0x07, 0xb0, 0x81, 0x00, 0x07, 0x00, 0x09,
+ 0xb0, 0x1f, 0x01, 0x07, 0x8f, 0x00, 0x09, 0x97,
+ 0xc6, 0x82, 0xc4, 0xb0, 0x28, 0x02, 0x09, 0xb0,
+ 0x40, 0x00, 0x09, 0x82, 0x00, 0x07, 0x96, 0xc0,
+ 0xb0, 0x32, 0x00, 0x09, 0x00, 0x07, 0xb0, 0xca,
+ 0x00, 0x09, 0x00, 0x07, 0xb0, 0x4d, 0x00, 0x09,
+ 0xb0, 0x45, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x42,
+ 0x00, 0x09, 0xb0, 0xdc, 0x00, 0x09, 0x00, 0x07,
+ 0xb0, 0xd1, 0x01, 0x09, 0x83, 0x00, 0x07, 0xb0,
+ 0x6b, 0x00, 0x09, 0xb0, 0x22, 0x00, 0x09, 0x91,
+ 0x00, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, 0x74,
+ 0x00, 0x09, 0xb0, 0xd1, 0x00, 0x07, 0x80, 0x01,
+ 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, 0x78, 0x01,
+ 0x09, 0xb8, 0x39, 0xbb, 0x00, 0x09, 0xb8, 0x01,
+ 0x8f, 0x04, 0x01, 0xb0, 0x0a, 0xc6, 0xb4, 0x88,
+ 0x01, 0x06, 0xb8, 0x44, 0x7b, 0x00, 0x01, 0xb8,
+ 0x0c, 0x95, 0x01, 0xd8, 0x02, 0x01, 0x82, 0x00,
+ 0xe2, 0x04, 0xd8, 0x87, 0x07, 0xdc, 0x81, 0xc4,
+ 0x01, 0xdc, 0x9d, 0xc3, 0xb0, 0x63, 0xc2, 0xb8,
+ 0x05, 0x8a, 0xc6, 0x80, 0xd0, 0x81, 0xc6, 0x80,
+ 0xc1, 0x80, 0xc4, 0xb0, 0x33, 0xc0, 0xb0, 0x6f,
+ 0xc6, 0xb1, 0x46, 0xc0, 0xb0, 0x0c, 0xc3, 0xb1,
+ 0xcb, 0x01, 0xe8, 0x00, 0xdc, 0xc0, 0xb0, 0xcd,
+ 0xc0, 0x00, 0xdc, 0xb2, 0xaf, 0x06, 0xdc, 0xb0,
+ 0x3c, 0xc5, 0x00, 0x07,
};
static const uint8_t unicode_cc_index[87] = {
- 0x4d, 0x03, 0x00, // 0034D at 32
- 0x97, 0x05, 0x20, // 00597 at 65
- 0xc6, 0x05, 0x00, // 005C6 at 96
- 0xe7, 0x06, 0x00, // 006E7 at 128
- 0x45, 0x07, 0x00, // 00745 at 160
- 0x9c, 0x08, 0x00, // 0089C at 192
- 0x4d, 0x09, 0x00, // 0094D at 224
- 0x3c, 0x0b, 0x00, // 00B3C at 256
- 0x3d, 0x0d, 0x00, // 00D3D at 288
- 0x36, 0x0f, 0x00, // 00F36 at 320
- 0x38, 0x10, 0x20, // 01038 at 353
- 0x3a, 0x19, 0x00, // 0193A at 384
- 0xcb, 0x1a, 0x20, // 01ACB at 417
- 0xd3, 0x1c, 0x00, // 01CD3 at 448
- 0xcf, 0x1d, 0x00, // 01DCF at 480
- 0xe2, 0x20, 0x00, // 020E2 at 512
- 0x2e, 0x30, 0x20, // 0302E at 545
- 0x2b, 0xa9, 0x20, // 0A92B at 577
- 0xed, 0xab, 0x00, // 0ABED at 608
- 0x39, 0x0a, 0x01, // 10A39 at 640
- 0x51, 0x0f, 0x01, // 10F51 at 672
- 0x73, 0x11, 0x01, // 11173 at 704
- 0x75, 0x13, 0x01, // 11375 at 736
- 0x2b, 0x17, 0x21, // 1172B at 769
- 0x3f, 0x1c, 0x21, // 11C3F at 801
- 0x9e, 0xbc, 0x21, // 1BC9E at 833
- 0x08, 0xe0, 0x01, // 1E008 at 864
- 0x44, 0xe9, 0x01, // 1E944 at 896
- 0x4b, 0xe9, 0x01, // 1E94B at 928 (upper bound)
+ 0x4d, 0x03, 0x00, 0x97, 0x05, 0x20, 0xc6, 0x05,
+ 0x00, 0xe7, 0x06, 0x00, 0x45, 0x07, 0x00, 0x9c,
+ 0x08, 0x00, 0x4d, 0x09, 0x00, 0x3c, 0x0b, 0x00,
+ 0x3d, 0x0d, 0x00, 0x36, 0x0f, 0x00, 0x38, 0x10,
+ 0x20, 0x3a, 0x19, 0x00, 0xcb, 0x1a, 0x20, 0xd3,
+ 0x1c, 0x00, 0xcf, 0x1d, 0x00, 0xe2, 0x20, 0x00,
+ 0x2e, 0x30, 0x20, 0x2b, 0xa9, 0x20, 0xed, 0xab,
+ 0x00, 0x39, 0x0a, 0x01, 0x4c, 0x0f, 0x01, 0x35,
+ 0x11, 0x21, 0x66, 0x13, 0x01, 0x40, 0x16, 0x01,
+ 0x47, 0x1a, 0x01, 0xf0, 0x6a, 0x21, 0x8a, 0xd1,
+ 0x01, 0xec, 0xe4, 0x21, 0x4b, 0xe9, 0x01,
};
-static const uint32_t unicode_decomp_table1[699] = {
+static const uint32_t unicode_decomp_table1[709] = {
0x00280081, 0x002a0097, 0x002a8081, 0x002bc097,
0x002c8115, 0x002d0097, 0x002d4081, 0x002e0097,
0x002e4115, 0x002f0199, 0x00302016, 0x00400842,
@@ -902,42 +857,45 @@ static const uint32_t unicode_decomp_table1[699] = {
0x3f9c01af, 0x3f9d0085, 0x3f9d852f, 0x3fa03aad,
0x3fbd442f, 0x3fc06f1f, 0x3fd7c11f, 0x3fd85fad,
0x3fe80081, 0x3fe84f1f, 0x3ff0831f, 0x3ff2831f,
- 0x3ff4831f, 0x3ff6819f, 0x3ff80783, 0x41e04d83,
- 0x41e70f91, 0x44268192, 0x442ac092, 0x444b8112,
- 0x44d2c112, 0x452ec212, 0x456e8112, 0x464e0092,
- 0x74578392, 0x746ec312, 0x75000d1f, 0x75068d1f,
- 0x750d0d1f, 0x7513839f, 0x7515891f, 0x751a0d1f,
- 0x75208d1f, 0x75271015, 0x752f439f, 0x7531459f,
- 0x75340d1f, 0x753a8d1f, 0x75410395, 0x7543441f,
- 0x7545839f, 0x75478d1f, 0x754e0795, 0x7552839f,
- 0x75548d1f, 0x755b0d1f, 0x75618d1f, 0x75680d1f,
- 0x756e8d1f, 0x75750d1f, 0x757b8d1f, 0x75820d1f,
- 0x75888d1f, 0x758f0d1f, 0x75958d1f, 0x759c0d1f,
- 0x75a28d1f, 0x75a90103, 0x75aa089f, 0x75ae4081,
- 0x75ae839f, 0x75b04081, 0x75b08c9f, 0x75b6c081,
- 0x75b7032d, 0x75b8889f, 0x75bcc081, 0x75bd039f,
- 0x75bec081, 0x75bf0c9f, 0x75c54081, 0x75c5832d,
- 0x75c7089f, 0x75cb4081, 0x75cb839f, 0x75cd4081,
- 0x75cd8c9f, 0x75d3c081, 0x75d4032d, 0x75d5889f,
- 0x75d9c081, 0x75da039f, 0x75dbc081, 0x75dc0c9f,
- 0x75e24081, 0x75e2832d, 0x75e4089f, 0x75e84081,
- 0x75e8839f, 0x75ea4081, 0x75ea8c9f, 0x75f0c081,
- 0x75f1042d, 0x75f3851f, 0x75f6051f, 0x75f8851f,
- 0x75fb051f, 0x75fd851f, 0x780c049f, 0x780e419f,
- 0x780f059f, 0x7811c203, 0x7812d0ad, 0x781b0103,
- 0x7b80022d, 0x7b814dad, 0x7b884203, 0x7b89c081,
- 0x7b8a452d, 0x7b8d0403, 0x7b908081, 0x7b91dc03,
- 0x7ba0052d, 0x7ba2c8ad, 0x7ba84483, 0x7baac8ad,
- 0x7c400097, 0x7c404521, 0x7c440d25, 0x7c4a8087,
- 0x7c4ac115, 0x7c4b4117, 0x7c4c0d1f, 0x7c528217,
- 0x7c538099, 0x7c53c097, 0x7c5a8197, 0x7c640097,
- 0x7c80012f, 0x7c808081, 0x7c841603, 0x7c9004c1,
- 0x7c940103, 0x7efc051f, 0xbe0001ac, 0xbe00d110,
- 0xbe0947ac, 0xbe0d3910, 0xbe29872c, 0xbe2d022c,
- 0xbe2e3790, 0xbe49ff90, 0xbe69bc10,
+ 0x3ff4831f, 0x3ff6819f, 0x3ff80783, 0x41724092,
+ 0x41790092, 0x41e04d83, 0x41e70f91, 0x44268192,
+ 0x442ac092, 0x444b8112, 0x44d2c112, 0x44e0c192,
+ 0x44e38092, 0x44e44092, 0x44f14212, 0x452ec212,
+ 0x456e8112, 0x464e0092, 0x58484412, 0x5b5a0192,
+ 0x73358d1f, 0x733c051f, 0x74578392, 0x746ec312,
+ 0x75000d1f, 0x75068d1f, 0x750d0d1f, 0x7513839f,
+ 0x7515891f, 0x751a0d1f, 0x75208d1f, 0x75271015,
+ 0x752f439f, 0x7531459f, 0x75340d1f, 0x753a8d1f,
+ 0x75410395, 0x7543441f, 0x7545839f, 0x75478d1f,
+ 0x754e0795, 0x7552839f, 0x75548d1f, 0x755b0d1f,
+ 0x75618d1f, 0x75680d1f, 0x756e8d1f, 0x75750d1f,
+ 0x757b8d1f, 0x75820d1f, 0x75888d1f, 0x758f0d1f,
+ 0x75958d1f, 0x759c0d1f, 0x75a28d1f, 0x75a90103,
+ 0x75aa089f, 0x75ae4081, 0x75ae839f, 0x75b04081,
+ 0x75b08c9f, 0x75b6c081, 0x75b7032d, 0x75b8889f,
+ 0x75bcc081, 0x75bd039f, 0x75bec081, 0x75bf0c9f,
+ 0x75c54081, 0x75c5832d, 0x75c7089f, 0x75cb4081,
+ 0x75cb839f, 0x75cd4081, 0x75cd8c9f, 0x75d3c081,
+ 0x75d4032d, 0x75d5889f, 0x75d9c081, 0x75da039f,
+ 0x75dbc081, 0x75dc0c9f, 0x75e24081, 0x75e2832d,
+ 0x75e4089f, 0x75e84081, 0x75e8839f, 0x75ea4081,
+ 0x75ea8c9f, 0x75f0c081, 0x75f1042d, 0x75f3851f,
+ 0x75f6051f, 0x75f8851f, 0x75fb051f, 0x75fd851f,
+ 0x780c049f, 0x780e419f, 0x780f059f, 0x7811c203,
+ 0x7812d0ad, 0x781b0103, 0x7b80022d, 0x7b814dad,
+ 0x7b884203, 0x7b89c081, 0x7b8a452d, 0x7b8d0403,
+ 0x7b908081, 0x7b91dc03, 0x7ba0052d, 0x7ba2c8ad,
+ 0x7ba84483, 0x7baac8ad, 0x7c400097, 0x7c404521,
+ 0x7c440d25, 0x7c4a8087, 0x7c4ac115, 0x7c4b4117,
+ 0x7c4c0d1f, 0x7c528217, 0x7c538099, 0x7c53c097,
+ 0x7c5a8197, 0x7c640097, 0x7c80012f, 0x7c808081,
+ 0x7c841603, 0x7c9004c1, 0x7c940103, 0x7efc051f,
+ 0xbe0001ac, 0xbe00d110, 0xbe0947ac, 0xbe0d3910,
+ 0xbe29872c, 0xbe2d022c, 0xbe2e3790, 0xbe49ff90,
+ 0xbe69bc10,
};
-static const uint16_t unicode_decomp_table2[699] = {
+static const uint16_t unicode_decomp_table2[709] = {
0x0020, 0x0000, 0x0061, 0x0002, 0x0004, 0x0006, 0x03bc, 0x0008,
0x000a, 0x000c, 0x0015, 0x0095, 0x00a5, 0x00b9, 0x00c1, 0x00c3,
0x00c7, 0x00cb, 0x00d1, 0x00d7, 0x00dd, 0x00e0, 0x00e6, 0x00f8,
@@ -1009,26 +967,27 @@ static const uint16_t unicode_decomp_table2[699] = {
0x1a77, 0x1a7f, 0x1a9d, 0x1aa2, 0x1ab6, 0x1ac0, 0x1ac6, 0x1ada,
0x1adf, 0x1ae5, 0x1af3, 0x1b23, 0x1b30, 0x1b38, 0x1b3c, 0x1b52,
0x1bc9, 0x1bdb, 0x1bdd, 0x1bdf, 0x3164, 0x1c20, 0x1c22, 0x1c24,
- 0x1c26, 0x1c28, 0x1c2a, 0x1c48, 0x1c7e, 0x1cc4, 0x1cd2, 0x1cd7,
- 0x1ce0, 0x1ce9, 0x1cfb, 0x1d04, 0x1d09, 0x1d29, 0x1d44, 0x1d46,
- 0x1d48, 0x1d4a, 0x1d4c, 0x1d4e, 0x1d50, 0x1d52, 0x1d72, 0x1d74,
- 0x1d76, 0x1d78, 0x1d7a, 0x1d81, 0x1d83, 0x1d85, 0x1d87, 0x1d96,
- 0x1d98, 0x1d9a, 0x1d9c, 0x1d9e, 0x1da0, 0x1da2, 0x1da4, 0x1da6,
- 0x1da8, 0x1daa, 0x1dac, 0x1dae, 0x1db0, 0x1db2, 0x1db6, 0x03f4,
- 0x1db8, 0x2207, 0x1dba, 0x2202, 0x1dbc, 0x1dc4, 0x03f4, 0x1dc6,
- 0x2207, 0x1dc8, 0x2202, 0x1dca, 0x1dd2, 0x03f4, 0x1dd4, 0x2207,
- 0x1dd6, 0x2202, 0x1dd8, 0x1de0, 0x03f4, 0x1de2, 0x2207, 0x1de4,
- 0x2202, 0x1de6, 0x1dee, 0x03f4, 0x1df0, 0x2207, 0x1df2, 0x2202,
- 0x1df4, 0x1dfe, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0a,
- 0x1e0c, 0x1e0e, 0x1e16, 0x1e39, 0x1e3d, 0x1e43, 0x1e60, 0x062d,
- 0x1e68, 0x1e74, 0x062c, 0x1e84, 0x1ef4, 0x1f00, 0x1f13, 0x1f25,
- 0x1f38, 0x1f3a, 0x1f3e, 0x1f44, 0x1f4a, 0x1f4c, 0x1f50, 0x1f52,
- 0x1f5a, 0x1f5d, 0x1f5f, 0x1f65, 0x1f67, 0x30b5, 0x1f6d, 0x1fc5,
- 0x1fdb, 0x1fdf, 0x1fe1, 0x1fe6, 0x2033, 0x2044, 0x2145, 0x2155,
- 0x215b, 0x2255, 0x2373,
+ 0x1c26, 0x1c28, 0x1c2a, 0x1c48, 0x1c4d, 0x1c52, 0x1c88, 0x1cce,
+ 0x1cdc, 0x1ce1, 0x1cea, 0x1cf3, 0x1d01, 0x1d06, 0x1d0b, 0x1d1d,
+ 0x1d2f, 0x1d38, 0x1d3d, 0x1d61, 0x1d6f, 0x1d71, 0x1d73, 0x1d93,
+ 0x1dae, 0x1db0, 0x1db2, 0x1db4, 0x1db6, 0x1db8, 0x1dba, 0x1dbc,
+ 0x1ddc, 0x1dde, 0x1de0, 0x1de2, 0x1de4, 0x1deb, 0x1ded, 0x1def,
+ 0x1df1, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0a, 0x1e0c,
+ 0x1e0e, 0x1e10, 0x1e12, 0x1e14, 0x1e16, 0x1e18, 0x1e1a, 0x1e1c,
+ 0x1e20, 0x03f4, 0x1e22, 0x2207, 0x1e24, 0x2202, 0x1e26, 0x1e2e,
+ 0x03f4, 0x1e30, 0x2207, 0x1e32, 0x2202, 0x1e34, 0x1e3c, 0x03f4,
+ 0x1e3e, 0x2207, 0x1e40, 0x2202, 0x1e42, 0x1e4a, 0x03f4, 0x1e4c,
+ 0x2207, 0x1e4e, 0x2202, 0x1e50, 0x1e58, 0x03f4, 0x1e5a, 0x2207,
+ 0x1e5c, 0x2202, 0x1e5e, 0x1e68, 0x1e6a, 0x1e6c, 0x1e6e, 0x1e70,
+ 0x1e72, 0x1e74, 0x1e76, 0x1e78, 0x1e80, 0x1ea3, 0x1ea7, 0x1ead,
+ 0x1eca, 0x062d, 0x1ed2, 0x1ede, 0x062c, 0x1eee, 0x1f5e, 0x1f6a,
+ 0x1f7d, 0x1f8f, 0x1fa2, 0x1fa4, 0x1fa8, 0x1fae, 0x1fb4, 0x1fb6,
+ 0x1fba, 0x1fbc, 0x1fc4, 0x1fc7, 0x1fc9, 0x1fcf, 0x1fd1, 0x30b5,
+ 0x1fd7, 0x202f, 0x2045, 0x2049, 0x204b, 0x2050, 0x209d, 0x20ae,
+ 0x21af, 0x21bf, 0x21c5, 0x22bf, 0x23dd,
};
-static const uint8_t unicode_decomp_data[9345] = {
+static const uint8_t unicode_decomp_data[9451] = {
0x20, 0x88, 0x20, 0x84, 0x32, 0x33, 0x20, 0x81,
0x20, 0xa7, 0x31, 0x6f, 0x31, 0xd0, 0x34, 0x31,
0xd0, 0x32, 0x33, 0xd0, 0x34, 0x41, 0x80, 0x41,
@@ -1934,273 +1893,286 @@ static const uint8_t unicode_decomp_data[9345] = {
0xaf, 0x00, 0xa6, 0x00, 0xa5, 0x00, 0xa9, 0x20,
0x00, 0x00, 0x02, 0x25, 0x90, 0x21, 0x91, 0x21,
0x92, 0x21, 0x93, 0x21, 0xa0, 0x25, 0xcb, 0x25,
- 0xd0, 0x02, 0xd1, 0x02, 0xe6, 0x00, 0x99, 0x02,
- 0x53, 0x02, 0x00, 0x00, 0xa3, 0x02, 0x66, 0xab,
- 0xa5, 0x02, 0xa4, 0x02, 0x56, 0x02, 0x57, 0x02,
- 0x91, 0x1d, 0x58, 0x02, 0x5e, 0x02, 0xa9, 0x02,
- 0x64, 0x02, 0x62, 0x02, 0x60, 0x02, 0x9b, 0x02,
- 0x27, 0x01, 0x9c, 0x02, 0x67, 0x02, 0x84, 0x02,
- 0xaa, 0x02, 0xab, 0x02, 0x6c, 0x02, 0x04, 0xdf,
- 0x8e, 0xa7, 0x6e, 0x02, 0x05, 0xdf, 0x8e, 0x02,
- 0x06, 0xdf, 0xf8, 0x00, 0x76, 0x02, 0x77, 0x02,
- 0x71, 0x00, 0x7a, 0x02, 0x08, 0xdf, 0x7d, 0x02,
- 0x7e, 0x02, 0x80, 0x02, 0xa8, 0x02, 0xa6, 0x02,
- 0x67, 0xab, 0xa7, 0x02, 0x88, 0x02, 0x71, 0x2c,
- 0x00, 0x00, 0x8f, 0x02, 0xa1, 0x02, 0xa2, 0x02,
- 0x98, 0x02, 0xc0, 0x01, 0xc1, 0x01, 0xc2, 0x01,
- 0x0a, 0xdf, 0x1e, 0xdf, 0x41, 0x04, 0x40, 0x00,
- 0x00, 0x00, 0x00, 0x14, 0x99, 0x10, 0xba, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x9b, 0x10, 0xba, 0x10,
- 0x05, 0x05, 0xa5, 0x10, 0xba, 0x10, 0x05, 0x31,
- 0x11, 0x27, 0x11, 0x32, 0x11, 0x27, 0x11, 0x55,
- 0x47, 0x13, 0x3e, 0x13, 0x47, 0x13, 0x57, 0x13,
- 0x55, 0xb9, 0x14, 0xba, 0x14, 0xb9, 0x14, 0xb0,
- 0x14, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x14, 0xbd,
- 0x14, 0x55, 0x50, 0xb8, 0x15, 0xaf, 0x15, 0xb9,
- 0x15, 0xaf, 0x15, 0x55, 0x35, 0x19, 0x30, 0x19,
- 0x05, 0x57, 0xd1, 0x65, 0xd1, 0x58, 0xd1, 0x65,
- 0xd1, 0x5f, 0xd1, 0x6e, 0xd1, 0x5f, 0xd1, 0x6f,
- 0xd1, 0x5f, 0xd1, 0x70, 0xd1, 0x5f, 0xd1, 0x71,
- 0xd1, 0x5f, 0xd1, 0x72, 0xd1, 0x55, 0x55, 0x55,
- 0x05, 0xb9, 0xd1, 0x65, 0xd1, 0xba, 0xd1, 0x65,
- 0xd1, 0xbb, 0xd1, 0x6e, 0xd1, 0xbc, 0xd1, 0x6e,
- 0xd1, 0xbb, 0xd1, 0x6f, 0xd1, 0xbc, 0xd1, 0x6f,
- 0xd1, 0x55, 0x55, 0x55, 0x41, 0x00, 0x61, 0x00,
- 0x41, 0x00, 0x61, 0x00, 0x69, 0x00, 0x41, 0x00,
- 0x61, 0x00, 0x41, 0x00, 0x43, 0x44, 0x00, 0x00,
- 0x47, 0x00, 0x00, 0x4a, 0x4b, 0x00, 0x00, 0x4e,
- 0x4f, 0x50, 0x51, 0x00, 0x53, 0x54, 0x55, 0x56,
- 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64,
- 0x00, 0x66, 0x68, 0x00, 0x70, 0x00, 0x41, 0x00,
- 0x61, 0x00, 0x41, 0x42, 0x00, 0x44, 0x45, 0x46,
- 0x47, 0x4a, 0x00, 0x53, 0x00, 0x61, 0x00, 0x41,
- 0x42, 0x00, 0x44, 0x45, 0x46, 0x47, 0x00, 0x49,
- 0x4a, 0x4b, 0x4c, 0x4d, 0x00, 0x4f, 0x53, 0x00,
- 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00,
- 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00,
- 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00,
- 0x61, 0x00, 0x31, 0x01, 0x37, 0x02, 0x91, 0x03,
+ 0xd2, 0x05, 0x07, 0x03, 0x01, 0xda, 0x05, 0x07,
+ 0x03, 0x01, 0xd0, 0x02, 0xd1, 0x02, 0xe6, 0x00,
+ 0x99, 0x02, 0x53, 0x02, 0x00, 0x00, 0xa3, 0x02,
+ 0x66, 0xab, 0xa5, 0x02, 0xa4, 0x02, 0x56, 0x02,
+ 0x57, 0x02, 0x91, 0x1d, 0x58, 0x02, 0x5e, 0x02,
+ 0xa9, 0x02, 0x64, 0x02, 0x62, 0x02, 0x60, 0x02,
+ 0x9b, 0x02, 0x27, 0x01, 0x9c, 0x02, 0x67, 0x02,
+ 0x84, 0x02, 0xaa, 0x02, 0xab, 0x02, 0x6c, 0x02,
+ 0x04, 0xdf, 0x8e, 0xa7, 0x6e, 0x02, 0x05, 0xdf,
+ 0x8e, 0x02, 0x06, 0xdf, 0xf8, 0x00, 0x76, 0x02,
+ 0x77, 0x02, 0x71, 0x00, 0x7a, 0x02, 0x08, 0xdf,
+ 0x7d, 0x02, 0x7e, 0x02, 0x80, 0x02, 0xa8, 0x02,
+ 0xa6, 0x02, 0x67, 0xab, 0xa7, 0x02, 0x88, 0x02,
+ 0x71, 0x2c, 0x00, 0x00, 0x8f, 0x02, 0xa1, 0x02,
+ 0xa2, 0x02, 0x98, 0x02, 0xc0, 0x01, 0xc1, 0x01,
+ 0xc2, 0x01, 0x0a, 0xdf, 0x1e, 0xdf, 0x41, 0x04,
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x14, 0x99, 0x10,
+ 0xba, 0x10, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x10,
+ 0xba, 0x10, 0x05, 0x05, 0xa5, 0x10, 0xba, 0x10,
+ 0x05, 0x31, 0x11, 0x27, 0x11, 0x32, 0x11, 0x27,
+ 0x11, 0x55, 0x47, 0x13, 0x3e, 0x13, 0x47, 0x13,
+ 0x57, 0x13, 0x55, 0x82, 0x13, 0xc9, 0x13, 0x00,
+ 0x00, 0x00, 0x00, 0x84, 0x13, 0xbb, 0x13, 0x05,
+ 0x05, 0x8b, 0x13, 0xc2, 0x13, 0x05, 0x90, 0x13,
+ 0xc9, 0x13, 0x05, 0xc2, 0x13, 0xc2, 0x13, 0x00,
+ 0x00, 0x00, 0x00, 0xc2, 0x13, 0xb8, 0x13, 0xc2,
+ 0x13, 0xc9, 0x13, 0x05, 0x55, 0xb9, 0x14, 0xba,
+ 0x14, 0xb9, 0x14, 0xb0, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0xb9, 0x14, 0xbd, 0x14, 0x55, 0x50, 0xb8,
+ 0x15, 0xaf, 0x15, 0xb9, 0x15, 0xaf, 0x15, 0x55,
+ 0x35, 0x19, 0x30, 0x19, 0x05, 0x1e, 0x61, 0x1e,
+ 0x61, 0x1e, 0x61, 0x29, 0x61, 0x1e, 0x61, 0x1f,
+ 0x61, 0x29, 0x61, 0x1f, 0x61, 0x1e, 0x61, 0x20,
+ 0x61, 0x21, 0x61, 0x1f, 0x61, 0x22, 0x61, 0x1f,
+ 0x61, 0x21, 0x61, 0x20, 0x61, 0x55, 0x55, 0x55,
+ 0x55, 0x67, 0x6d, 0x67, 0x6d, 0x63, 0x6d, 0x67,
+ 0x6d, 0x69, 0x6d, 0x67, 0x6d, 0x55, 0x05, 0x41,
+ 0x00, 0x30, 0x00, 0x57, 0xd1, 0x65, 0xd1, 0x58,
+ 0xd1, 0x65, 0xd1, 0x5f, 0xd1, 0x6e, 0xd1, 0x5f,
+ 0xd1, 0x6f, 0xd1, 0x5f, 0xd1, 0x70, 0xd1, 0x5f,
+ 0xd1, 0x71, 0xd1, 0x5f, 0xd1, 0x72, 0xd1, 0x55,
+ 0x55, 0x55, 0x05, 0xb9, 0xd1, 0x65, 0xd1, 0xba,
+ 0xd1, 0x65, 0xd1, 0xbb, 0xd1, 0x6e, 0xd1, 0xbc,
+ 0xd1, 0x6e, 0xd1, 0xbb, 0xd1, 0x6f, 0xd1, 0xbc,
+ 0xd1, 0x6f, 0xd1, 0x55, 0x55, 0x55, 0x41, 0x00,
+ 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x69, 0x00,
+ 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x43, 0x44,
+ 0x00, 0x00, 0x47, 0x00, 0x00, 0x4a, 0x4b, 0x00,
+ 0x00, 0x4e, 0x4f, 0x50, 0x51, 0x00, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62,
+ 0x63, 0x64, 0x00, 0x66, 0x68, 0x00, 0x70, 0x00,
+ 0x41, 0x00, 0x61, 0x00, 0x41, 0x42, 0x00, 0x44,
+ 0x45, 0x46, 0x47, 0x4a, 0x00, 0x53, 0x00, 0x61,
+ 0x00, 0x41, 0x42, 0x00, 0x44, 0x45, 0x46, 0x47,
+ 0x00, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x00, 0x4f,
+ 0x53, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00,
+ 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00,
+ 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00,
+ 0x41, 0x00, 0x61, 0x00, 0x31, 0x01, 0x37, 0x02,
+ 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03,
+ 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03,
0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00,
0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03,
0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04,
0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03,
0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05,
0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03,
- 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03,
- 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00,
- 0x1f, 0x04, 0x20, 0x05, 0x0b, 0x0c, 0x30, 0x00,
+ 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x0b, 0x0c,
0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00,
- 0x30, 0x04, 0x3a, 0x04, 0x3e, 0x04, 0x4b, 0x04,
- 0x4d, 0x04, 0x4e, 0x04, 0x89, 0xa6, 0x30, 0x04,
- 0xa9, 0x26, 0x28, 0xb9, 0x7f, 0x9f, 0x00, 0x01,
- 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a,
- 0x0b, 0x0e, 0x0f, 0x11, 0x13, 0x14, 0x15, 0x16,
- 0x17, 0x18, 0x1a, 0x1b, 0x61, 0x26, 0x25, 0x2f,
- 0x7b, 0x51, 0xa6, 0xb1, 0x04, 0x27, 0x06, 0x00,
- 0x01, 0x05, 0x08, 0x2a, 0x06, 0x1e, 0x08, 0x03,
- 0x0d, 0x20, 0x19, 0x1a, 0x1b, 0x1c, 0x09, 0x0f,
- 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04,
- 0x06, 0x0c, 0x0e, 0x10, 0x44, 0x90, 0x77, 0x45,
- 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00, 0x47, 0x06,
- 0x33, 0x06, 0x17, 0x10, 0x11, 0x12, 0x13, 0x00,
- 0x06, 0x0e, 0x02, 0x0f, 0x34, 0x06, 0x2a, 0x06,
- 0x2b, 0x06, 0x2e, 0x06, 0x00, 0x00, 0x36, 0x06,
- 0x00, 0x00, 0x3a, 0x06, 0x2d, 0x06, 0x00, 0x00,
- 0x4a, 0x06, 0x00, 0x00, 0x44, 0x06, 0x00, 0x00,
- 0x46, 0x06, 0x33, 0x06, 0x39, 0x06, 0x00, 0x00,
- 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, 0x34, 0x06,
- 0x00, 0x00, 0x00, 0x00, 0x2e, 0x06, 0x00, 0x00,
- 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, 0x00, 0x00,
- 0xba, 0x06, 0x00, 0x00, 0x6f, 0x06, 0x00, 0x00,
- 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00, 0x47, 0x06,
- 0x00, 0x00, 0x00, 0x00, 0x2d, 0x06, 0x37, 0x06,
- 0x4a, 0x06, 0x43, 0x06, 0x00, 0x00, 0x45, 0x06,
- 0x46, 0x06, 0x33, 0x06, 0x39, 0x06, 0x41, 0x06,
- 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, 0x34, 0x06,
+ 0x30, 0x00, 0x30, 0x04, 0x3a, 0x04, 0x3e, 0x04,
+ 0x4b, 0x04, 0x4d, 0x04, 0x4e, 0x04, 0x89, 0xa6,
+ 0x30, 0x04, 0xa9, 0x26, 0x28, 0xb9, 0x7f, 0x9f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x0a, 0x0b, 0x0e, 0x0f, 0x11, 0x13, 0x14,
+ 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x61, 0x26,
+ 0x25, 0x2f, 0x7b, 0x51, 0xa6, 0xb1, 0x04, 0x27,
+ 0x06, 0x00, 0x01, 0x05, 0x08, 0x2a, 0x06, 0x1e,
+ 0x08, 0x03, 0x0d, 0x20, 0x19, 0x1a, 0x1b, 0x1c,
+ 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00,
+ 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x44, 0x90,
+ 0x77, 0x45, 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00,
+ 0x47, 0x06, 0x33, 0x06, 0x17, 0x10, 0x11, 0x12,
+ 0x13, 0x00, 0x06, 0x0e, 0x02, 0x0f, 0x34, 0x06,
0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, 0x00, 0x00,
- 0x36, 0x06, 0x38, 0x06, 0x3a, 0x06, 0x6e, 0x06,
- 0x00, 0x00, 0xa1, 0x06, 0x27, 0x06, 0x00, 0x01,
- 0x05, 0x08, 0x20, 0x21, 0x0b, 0x06, 0x10, 0x23,
- 0x2a, 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17,
- 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, 0x06,
- 0x0c, 0x0e, 0x10, 0x28, 0x06, 0x2c, 0x06, 0x2f,
- 0x06, 0x00, 0x00, 0x48, 0x06, 0x32, 0x06, 0x2d,
- 0x06, 0x37, 0x06, 0x4a, 0x06, 0x2a, 0x06, 0x1a,
- 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07,
- 0x0a, 0x00, 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10,
- 0x30, 0x2e, 0x30, 0x00, 0x2c, 0x00, 0x28, 0x00,
- 0x41, 0x00, 0x29, 0x00, 0x14, 0x30, 0x53, 0x00,
- 0x15, 0x30, 0x43, 0x52, 0x43, 0x44, 0x57, 0x5a,
- 0x41, 0x00, 0x48, 0x56, 0x4d, 0x56, 0x53, 0x44,
- 0x53, 0x53, 0x50, 0x50, 0x56, 0x57, 0x43, 0x4d,
- 0x43, 0x4d, 0x44, 0x4d, 0x52, 0x44, 0x4a, 0x4b,
- 0x30, 0x30, 0x00, 0x68, 0x68, 0x4b, 0x62, 0x57,
- 0x5b, 0xcc, 0x53, 0xc7, 0x30, 0x8c, 0x4e, 0x1a,
- 0x59, 0xe3, 0x89, 0x29, 0x59, 0xa4, 0x4e, 0x20,
- 0x66, 0x21, 0x71, 0x99, 0x65, 0x4d, 0x52, 0x8c,
- 0x5f, 0x8d, 0x51, 0xb0, 0x65, 0x1d, 0x52, 0x42,
- 0x7d, 0x1f, 0x75, 0xa9, 0x8c, 0xf0, 0x58, 0x39,
- 0x54, 0x14, 0x6f, 0x95, 0x62, 0x55, 0x63, 0x00,
- 0x4e, 0x09, 0x4e, 0x4a, 0x90, 0xe6, 0x5d, 0x2d,
- 0x4e, 0xf3, 0x53, 0x07, 0x63, 0x70, 0x8d, 0x53,
- 0x62, 0x81, 0x79, 0x7a, 0x7a, 0x08, 0x54, 0x80,
- 0x6e, 0x09, 0x67, 0x08, 0x67, 0x33, 0x75, 0x72,
- 0x52, 0xb6, 0x55, 0x4d, 0x91, 0x14, 0x30, 0x15,
- 0x30, 0x2c, 0x67, 0x09, 0x4e, 0x8c, 0x4e, 0x89,
- 0x5b, 0xb9, 0x70, 0x53, 0x62, 0xd7, 0x76, 0xdd,
- 0x52, 0x57, 0x65, 0x97, 0x5f, 0xef, 0x53, 0x30,
- 0x00, 0x38, 0x4e, 0x05, 0x00, 0x09, 0x22, 0x01,
- 0x60, 0x4f, 0xae, 0x4f, 0xbb, 0x4f, 0x02, 0x50,
- 0x7a, 0x50, 0x99, 0x50, 0xe7, 0x50, 0xcf, 0x50,
- 0x9e, 0x34, 0x3a, 0x06, 0x4d, 0x51, 0x54, 0x51,
- 0x64, 0x51, 0x77, 0x51, 0x1c, 0x05, 0xb9, 0x34,
- 0x67, 0x51, 0x8d, 0x51, 0x4b, 0x05, 0x97, 0x51,
- 0xa4, 0x51, 0xcc, 0x4e, 0xac, 0x51, 0xb5, 0x51,
- 0xdf, 0x91, 0xf5, 0x51, 0x03, 0x52, 0xdf, 0x34,
- 0x3b, 0x52, 0x46, 0x52, 0x72, 0x52, 0x77, 0x52,
- 0x15, 0x35, 0x02, 0x00, 0x20, 0x80, 0x80, 0x00,
- 0x08, 0x00, 0x00, 0xc7, 0x52, 0x00, 0x02, 0x1d,
- 0x33, 0x3e, 0x3f, 0x50, 0x82, 0x8a, 0x93, 0xac,
- 0xb6, 0xb8, 0xb8, 0xb8, 0x2c, 0x0a, 0x70, 0x70,
- 0xca, 0x53, 0xdf, 0x53, 0x63, 0x0b, 0xeb, 0x53,
- 0xf1, 0x53, 0x06, 0x54, 0x9e, 0x54, 0x38, 0x54,
- 0x48, 0x54, 0x68, 0x54, 0xa2, 0x54, 0xf6, 0x54,
- 0x10, 0x55, 0x53, 0x55, 0x63, 0x55, 0x84, 0x55,
- 0x84, 0x55, 0x99, 0x55, 0xab, 0x55, 0xb3, 0x55,
- 0xc2, 0x55, 0x16, 0x57, 0x06, 0x56, 0x17, 0x57,
- 0x51, 0x56, 0x74, 0x56, 0x07, 0x52, 0xee, 0x58,
- 0xce, 0x57, 0xf4, 0x57, 0x0d, 0x58, 0x8b, 0x57,
- 0x32, 0x58, 0x31, 0x58, 0xac, 0x58, 0xe4, 0x14,
- 0xf2, 0x58, 0xf7, 0x58, 0x06, 0x59, 0x1a, 0x59,
- 0x22, 0x59, 0x62, 0x59, 0xa8, 0x16, 0xea, 0x16,
- 0xec, 0x59, 0x1b, 0x5a, 0x27, 0x5a, 0xd8, 0x59,
- 0x66, 0x5a, 0xee, 0x36, 0xfc, 0x36, 0x08, 0x5b,
- 0x3e, 0x5b, 0x3e, 0x5b, 0xc8, 0x19, 0xc3, 0x5b,
- 0xd8, 0x5b, 0xe7, 0x5b, 0xf3, 0x5b, 0x18, 0x1b,
- 0xff, 0x5b, 0x06, 0x5c, 0x53, 0x5f, 0x22, 0x5c,
- 0x81, 0x37, 0x60, 0x5c, 0x6e, 0x5c, 0xc0, 0x5c,
- 0x8d, 0x5c, 0xe4, 0x1d, 0x43, 0x5d, 0xe6, 0x1d,
- 0x6e, 0x5d, 0x6b, 0x5d, 0x7c, 0x5d, 0xe1, 0x5d,
- 0xe2, 0x5d, 0x2f, 0x38, 0xfd, 0x5d, 0x28, 0x5e,
- 0x3d, 0x5e, 0x69, 0x5e, 0x62, 0x38, 0x83, 0x21,
- 0x7c, 0x38, 0xb0, 0x5e, 0xb3, 0x5e, 0xb6, 0x5e,
- 0xca, 0x5e, 0x92, 0xa3, 0xfe, 0x5e, 0x31, 0x23,
- 0x31, 0x23, 0x01, 0x82, 0x22, 0x5f, 0x22, 0x5f,
- 0xc7, 0x38, 0xb8, 0x32, 0xda, 0x61, 0x62, 0x5f,
- 0x6b, 0x5f, 0xe3, 0x38, 0x9a, 0x5f, 0xcd, 0x5f,
- 0xd7, 0x5f, 0xf9, 0x5f, 0x81, 0x60, 0x3a, 0x39,
- 0x1c, 0x39, 0x94, 0x60, 0xd4, 0x26, 0xc7, 0x60,
- 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x08,
- 0x00, 0x80, 0x08, 0x00, 0x00, 0x08, 0x80, 0x28,
- 0x80, 0x02, 0x00, 0x00, 0x02, 0x48, 0x61, 0x00,
- 0x04, 0x06, 0x04, 0x32, 0x46, 0x6a, 0x5c, 0x67,
- 0x96, 0xaa, 0xae, 0xc8, 0xd3, 0x5d, 0x62, 0x00,
- 0x54, 0x77, 0xf3, 0x0c, 0x2b, 0x3d, 0x63, 0xfc,
- 0x62, 0x68, 0x63, 0x83, 0x63, 0xe4, 0x63, 0xf1,
- 0x2b, 0x22, 0x64, 0xc5, 0x63, 0xa9, 0x63, 0x2e,
- 0x3a, 0x69, 0x64, 0x7e, 0x64, 0x9d, 0x64, 0x77,
- 0x64, 0x6c, 0x3a, 0x4f, 0x65, 0x6c, 0x65, 0x0a,
- 0x30, 0xe3, 0x65, 0xf8, 0x66, 0x49, 0x66, 0x19,
- 0x3b, 0x91, 0x66, 0x08, 0x3b, 0xe4, 0x3a, 0x92,
- 0x51, 0x95, 0x51, 0x00, 0x67, 0x9c, 0x66, 0xad,
- 0x80, 0xd9, 0x43, 0x17, 0x67, 0x1b, 0x67, 0x21,
- 0x67, 0x5e, 0x67, 0x53, 0x67, 0xc3, 0x33, 0x49,
- 0x3b, 0xfa, 0x67, 0x85, 0x67, 0x52, 0x68, 0x85,
- 0x68, 0x6d, 0x34, 0x8e, 0x68, 0x1f, 0x68, 0x14,
- 0x69, 0x9d, 0x3b, 0x42, 0x69, 0xa3, 0x69, 0xea,
- 0x69, 0xa8, 0x6a, 0xa3, 0x36, 0xdb, 0x6a, 0x18,
- 0x3c, 0x21, 0x6b, 0xa7, 0x38, 0x54, 0x6b, 0x4e,
- 0x3c, 0x72, 0x6b, 0x9f, 0x6b, 0xba, 0x6b, 0xbb,
- 0x6b, 0x8d, 0x3a, 0x0b, 0x1d, 0xfa, 0x3a, 0x4e,
- 0x6c, 0xbc, 0x3c, 0xbf, 0x6c, 0xcd, 0x6c, 0x67,
- 0x6c, 0x16, 0x6d, 0x3e, 0x6d, 0x77, 0x6d, 0x41,
- 0x6d, 0x69, 0x6d, 0x78, 0x6d, 0x85, 0x6d, 0x1e,
- 0x3d, 0x34, 0x6d, 0x2f, 0x6e, 0x6e, 0x6e, 0x33,
- 0x3d, 0xcb, 0x6e, 0xc7, 0x6e, 0xd1, 0x3e, 0xf9,
- 0x6d, 0x6e, 0x6f, 0x5e, 0x3f, 0x8e, 0x3f, 0xc6,
- 0x6f, 0x39, 0x70, 0x1e, 0x70, 0x1b, 0x70, 0x96,
- 0x3d, 0x4a, 0x70, 0x7d, 0x70, 0x77, 0x70, 0xad,
- 0x70, 0x25, 0x05, 0x45, 0x71, 0x63, 0x42, 0x9c,
- 0x71, 0xab, 0x43, 0x28, 0x72, 0x35, 0x72, 0x50,
- 0x72, 0x08, 0x46, 0x80, 0x72, 0x95, 0x72, 0x35,
- 0x47, 0x02, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00,
- 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x02, 0x02,
- 0x80, 0x8a, 0x00, 0x00, 0x20, 0x00, 0x08, 0x0a,
- 0x00, 0x80, 0x88, 0x80, 0x20, 0x14, 0x48, 0x7a,
- 0x73, 0x8b, 0x73, 0xac, 0x3e, 0xa5, 0x73, 0xb8,
- 0x3e, 0xb8, 0x3e, 0x47, 0x74, 0x5c, 0x74, 0x71,
- 0x74, 0x85, 0x74, 0xca, 0x74, 0x1b, 0x3f, 0x24,
- 0x75, 0x36, 0x4c, 0x3e, 0x75, 0x92, 0x4c, 0x70,
- 0x75, 0x9f, 0x21, 0x10, 0x76, 0xa1, 0x4f, 0xb8,
- 0x4f, 0x44, 0x50, 0xfc, 0x3f, 0x08, 0x40, 0xf4,
- 0x76, 0xf3, 0x50, 0xf2, 0x50, 0x19, 0x51, 0x33,
- 0x51, 0x1e, 0x77, 0x1f, 0x77, 0x1f, 0x77, 0x4a,
- 0x77, 0x39, 0x40, 0x8b, 0x77, 0x46, 0x40, 0x96,
- 0x40, 0x1d, 0x54, 0x4e, 0x78, 0x8c, 0x78, 0xcc,
- 0x78, 0xe3, 0x40, 0x26, 0x56, 0x56, 0x79, 0x9a,
- 0x56, 0xc5, 0x56, 0x8f, 0x79, 0xeb, 0x79, 0x2f,
- 0x41, 0x40, 0x7a, 0x4a, 0x7a, 0x4f, 0x7a, 0x7c,
- 0x59, 0xa7, 0x5a, 0xa7, 0x5a, 0xee, 0x7a, 0x02,
- 0x42, 0xab, 0x5b, 0xc6, 0x7b, 0xc9, 0x7b, 0x27,
- 0x42, 0x80, 0x5c, 0xd2, 0x7c, 0xa0, 0x42, 0xe8,
- 0x7c, 0xe3, 0x7c, 0x00, 0x7d, 0x86, 0x5f, 0x63,
- 0x7d, 0x01, 0x43, 0xc7, 0x7d, 0x02, 0x7e, 0x45,
- 0x7e, 0x34, 0x43, 0x28, 0x62, 0x47, 0x62, 0x59,
- 0x43, 0xd9, 0x62, 0x7a, 0x7f, 0x3e, 0x63, 0x95,
- 0x7f, 0xfa, 0x7f, 0x05, 0x80, 0xda, 0x64, 0x23,
- 0x65, 0x60, 0x80, 0xa8, 0x65, 0x70, 0x80, 0x5f,
- 0x33, 0xd5, 0x43, 0xb2, 0x80, 0x03, 0x81, 0x0b,
- 0x44, 0x3e, 0x81, 0xb5, 0x5a, 0xa7, 0x67, 0xb5,
- 0x67, 0x93, 0x33, 0x9c, 0x33, 0x01, 0x82, 0x04,
- 0x82, 0x9e, 0x8f, 0x6b, 0x44, 0x91, 0x82, 0x8b,
- 0x82, 0x9d, 0x82, 0xb3, 0x52, 0xb1, 0x82, 0xb3,
- 0x82, 0xbd, 0x82, 0xe6, 0x82, 0x3c, 0x6b, 0xe5,
- 0x82, 0x1d, 0x83, 0x63, 0x83, 0xad, 0x83, 0x23,
- 0x83, 0xbd, 0x83, 0xe7, 0x83, 0x57, 0x84, 0x53,
- 0x83, 0xca, 0x83, 0xcc, 0x83, 0xdc, 0x83, 0x36,
- 0x6c, 0x6b, 0x6d, 0x02, 0x00, 0x00, 0x20, 0x22,
- 0x2a, 0xa0, 0x0a, 0x00, 0x20, 0x80, 0x28, 0x00,
- 0xa8, 0x20, 0x20, 0x00, 0x02, 0x80, 0x22, 0x02,
- 0x8a, 0x08, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x28, 0xd5, 0x6c, 0x2b, 0x45, 0xf1,
- 0x84, 0xf3, 0x84, 0x16, 0x85, 0xca, 0x73, 0x64,
- 0x85, 0x2c, 0x6f, 0x5d, 0x45, 0x61, 0x45, 0xb1,
- 0x6f, 0xd2, 0x70, 0x6b, 0x45, 0x50, 0x86, 0x5c,
- 0x86, 0x67, 0x86, 0x69, 0x86, 0xa9, 0x86, 0x88,
- 0x86, 0x0e, 0x87, 0xe2, 0x86, 0x79, 0x87, 0x28,
- 0x87, 0x6b, 0x87, 0x86, 0x87, 0xd7, 0x45, 0xe1,
- 0x87, 0x01, 0x88, 0xf9, 0x45, 0x60, 0x88, 0x63,
- 0x88, 0x67, 0x76, 0xd7, 0x88, 0xde, 0x88, 0x35,
- 0x46, 0xfa, 0x88, 0xbb, 0x34, 0xae, 0x78, 0x66,
- 0x79, 0xbe, 0x46, 0xc7, 0x46, 0xa0, 0x8a, 0xed,
- 0x8a, 0x8a, 0x8b, 0x55, 0x8c, 0xa8, 0x7c, 0xab,
- 0x8c, 0xc1, 0x8c, 0x1b, 0x8d, 0x77, 0x8d, 0x2f,
- 0x7f, 0x04, 0x08, 0xcb, 0x8d, 0xbc, 0x8d, 0xf0,
- 0x8d, 0xde, 0x08, 0xd4, 0x8e, 0x38, 0x8f, 0xd2,
- 0x85, 0xed, 0x85, 0x94, 0x90, 0xf1, 0x90, 0x11,
- 0x91, 0x2e, 0x87, 0x1b, 0x91, 0x38, 0x92, 0xd7,
- 0x92, 0xd8, 0x92, 0x7c, 0x92, 0xf9, 0x93, 0x15,
- 0x94, 0xfa, 0x8b, 0x8b, 0x95, 0x95, 0x49, 0xb7,
- 0x95, 0x77, 0x8d, 0xe6, 0x49, 0xc3, 0x96, 0xb2,
- 0x5d, 0x23, 0x97, 0x45, 0x91, 0x1a, 0x92, 0x6e,
- 0x4a, 0x76, 0x4a, 0xe0, 0x97, 0x0a, 0x94, 0xb2,
- 0x4a, 0x96, 0x94, 0x0b, 0x98, 0x0b, 0x98, 0x29,
- 0x98, 0xb6, 0x95, 0xe2, 0x98, 0x33, 0x4b, 0x29,
- 0x99, 0xa7, 0x99, 0xc2, 0x99, 0xfe, 0x99, 0xce,
- 0x4b, 0x30, 0x9b, 0x12, 0x9b, 0x40, 0x9c, 0xfd,
- 0x9c, 0xce, 0x4c, 0xed, 0x4c, 0x67, 0x9d, 0xce,
- 0xa0, 0xf8, 0x4c, 0x05, 0xa1, 0x0e, 0xa2, 0x91,
- 0xa2, 0xbb, 0x9e, 0x56, 0x4d, 0xf9, 0x9e, 0xfe,
- 0x9e, 0x05, 0x9f, 0x0f, 0x9f, 0x16, 0x9f, 0x3b,
- 0x9f, 0x00, 0xa6, 0x02, 0x88, 0xa0, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0x00, 0x28, 0x00, 0x08, 0xa0,
- 0x80, 0xa0, 0x80, 0x00, 0x80, 0x80, 0x00, 0x0a,
- 0x88, 0x80, 0x00, 0x80, 0x00, 0x20, 0x2a, 0x00,
- 0x80,
+ 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, 0x2d, 0x06,
+ 0x00, 0x00, 0x4a, 0x06, 0x00, 0x00, 0x44, 0x06,
+ 0x00, 0x00, 0x46, 0x06, 0x33, 0x06, 0x39, 0x06,
+ 0x00, 0x00, 0x35, 0x06, 0x42, 0x06, 0x00, 0x00,
+ 0x34, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x06,
+ 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06,
+ 0x00, 0x00, 0xba, 0x06, 0x00, 0x00, 0x6f, 0x06,
+ 0x00, 0x00, 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00,
+ 0x47, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x06,
+ 0x37, 0x06, 0x4a, 0x06, 0x43, 0x06, 0x00, 0x00,
+ 0x45, 0x06, 0x46, 0x06, 0x33, 0x06, 0x39, 0x06,
+ 0x41, 0x06, 0x35, 0x06, 0x42, 0x06, 0x00, 0x00,
+ 0x34, 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06,
+ 0x00, 0x00, 0x36, 0x06, 0x38, 0x06, 0x3a, 0x06,
+ 0x6e, 0x06, 0x00, 0x00, 0xa1, 0x06, 0x27, 0x06,
+ 0x00, 0x01, 0x05, 0x08, 0x20, 0x21, 0x0b, 0x06,
+ 0x10, 0x23, 0x2a, 0x06, 0x1a, 0x1b, 0x1c, 0x09,
+ 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01,
+ 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x28, 0x06, 0x2c,
+ 0x06, 0x2f, 0x06, 0x00, 0x00, 0x48, 0x06, 0x32,
+ 0x06, 0x2d, 0x06, 0x37, 0x06, 0x4a, 0x06, 0x2a,
+ 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b,
+ 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, 0x06, 0x0c,
+ 0x0e, 0x10, 0x30, 0x2e, 0x30, 0x00, 0x2c, 0x00,
+ 0x28, 0x00, 0x41, 0x00, 0x29, 0x00, 0x14, 0x30,
+ 0x53, 0x00, 0x15, 0x30, 0x43, 0x52, 0x43, 0x44,
+ 0x57, 0x5a, 0x41, 0x00, 0x48, 0x56, 0x4d, 0x56,
+ 0x53, 0x44, 0x53, 0x53, 0x50, 0x50, 0x56, 0x57,
+ 0x43, 0x4d, 0x43, 0x4d, 0x44, 0x4d, 0x52, 0x44,
+ 0x4a, 0x4b, 0x30, 0x30, 0x00, 0x68, 0x68, 0x4b,
+ 0x62, 0x57, 0x5b, 0xcc, 0x53, 0xc7, 0x30, 0x8c,
+ 0x4e, 0x1a, 0x59, 0xe3, 0x89, 0x29, 0x59, 0xa4,
+ 0x4e, 0x20, 0x66, 0x21, 0x71, 0x99, 0x65, 0x4d,
+ 0x52, 0x8c, 0x5f, 0x8d, 0x51, 0xb0, 0x65, 0x1d,
+ 0x52, 0x42, 0x7d, 0x1f, 0x75, 0xa9, 0x8c, 0xf0,
+ 0x58, 0x39, 0x54, 0x14, 0x6f, 0x95, 0x62, 0x55,
+ 0x63, 0x00, 0x4e, 0x09, 0x4e, 0x4a, 0x90, 0xe6,
+ 0x5d, 0x2d, 0x4e, 0xf3, 0x53, 0x07, 0x63, 0x70,
+ 0x8d, 0x53, 0x62, 0x81, 0x79, 0x7a, 0x7a, 0x08,
+ 0x54, 0x80, 0x6e, 0x09, 0x67, 0x08, 0x67, 0x33,
+ 0x75, 0x72, 0x52, 0xb6, 0x55, 0x4d, 0x91, 0x14,
+ 0x30, 0x15, 0x30, 0x2c, 0x67, 0x09, 0x4e, 0x8c,
+ 0x4e, 0x89, 0x5b, 0xb9, 0x70, 0x53, 0x62, 0xd7,
+ 0x76, 0xdd, 0x52, 0x57, 0x65, 0x97, 0x5f, 0xef,
+ 0x53, 0x30, 0x00, 0x38, 0x4e, 0x05, 0x00, 0x09,
+ 0x22, 0x01, 0x60, 0x4f, 0xae, 0x4f, 0xbb, 0x4f,
+ 0x02, 0x50, 0x7a, 0x50, 0x99, 0x50, 0xe7, 0x50,
+ 0xcf, 0x50, 0x9e, 0x34, 0x3a, 0x06, 0x4d, 0x51,
+ 0x54, 0x51, 0x64, 0x51, 0x77, 0x51, 0x1c, 0x05,
+ 0xb9, 0x34, 0x67, 0x51, 0x8d, 0x51, 0x4b, 0x05,
+ 0x97, 0x51, 0xa4, 0x51, 0xcc, 0x4e, 0xac, 0x51,
+ 0xb5, 0x51, 0xdf, 0x91, 0xf5, 0x51, 0x03, 0x52,
+ 0xdf, 0x34, 0x3b, 0x52, 0x46, 0x52, 0x72, 0x52,
+ 0x77, 0x52, 0x15, 0x35, 0x02, 0x00, 0x20, 0x80,
+ 0x80, 0x00, 0x08, 0x00, 0x00, 0xc7, 0x52, 0x00,
+ 0x02, 0x1d, 0x33, 0x3e, 0x3f, 0x50, 0x82, 0x8a,
+ 0x93, 0xac, 0xb6, 0xb8, 0xb8, 0xb8, 0x2c, 0x0a,
+ 0x70, 0x70, 0xca, 0x53, 0xdf, 0x53, 0x63, 0x0b,
+ 0xeb, 0x53, 0xf1, 0x53, 0x06, 0x54, 0x9e, 0x54,
+ 0x38, 0x54, 0x48, 0x54, 0x68, 0x54, 0xa2, 0x54,
+ 0xf6, 0x54, 0x10, 0x55, 0x53, 0x55, 0x63, 0x55,
+ 0x84, 0x55, 0x84, 0x55, 0x99, 0x55, 0xab, 0x55,
+ 0xb3, 0x55, 0xc2, 0x55, 0x16, 0x57, 0x06, 0x56,
+ 0x17, 0x57, 0x51, 0x56, 0x74, 0x56, 0x07, 0x52,
+ 0xee, 0x58, 0xce, 0x57, 0xf4, 0x57, 0x0d, 0x58,
+ 0x8b, 0x57, 0x32, 0x58, 0x31, 0x58, 0xac, 0x58,
+ 0xe4, 0x14, 0xf2, 0x58, 0xf7, 0x58, 0x06, 0x59,
+ 0x1a, 0x59, 0x22, 0x59, 0x62, 0x59, 0xa8, 0x16,
+ 0xea, 0x16, 0xec, 0x59, 0x1b, 0x5a, 0x27, 0x5a,
+ 0xd8, 0x59, 0x66, 0x5a, 0xee, 0x36, 0xfc, 0x36,
+ 0x08, 0x5b, 0x3e, 0x5b, 0x3e, 0x5b, 0xc8, 0x19,
+ 0xc3, 0x5b, 0xd8, 0x5b, 0xe7, 0x5b, 0xf3, 0x5b,
+ 0x18, 0x1b, 0xff, 0x5b, 0x06, 0x5c, 0x53, 0x5f,
+ 0x22, 0x5c, 0x81, 0x37, 0x60, 0x5c, 0x6e, 0x5c,
+ 0xc0, 0x5c, 0x8d, 0x5c, 0xe4, 0x1d, 0x43, 0x5d,
+ 0xe6, 0x1d, 0x6e, 0x5d, 0x6b, 0x5d, 0x7c, 0x5d,
+ 0xe1, 0x5d, 0xe2, 0x5d, 0x2f, 0x38, 0xfd, 0x5d,
+ 0x28, 0x5e, 0x3d, 0x5e, 0x69, 0x5e, 0x62, 0x38,
+ 0x83, 0x21, 0x7c, 0x38, 0xb0, 0x5e, 0xb3, 0x5e,
+ 0xb6, 0x5e, 0xca, 0x5e, 0x92, 0xa3, 0xfe, 0x5e,
+ 0x31, 0x23, 0x31, 0x23, 0x01, 0x82, 0x22, 0x5f,
+ 0x22, 0x5f, 0xc7, 0x38, 0xb8, 0x32, 0xda, 0x61,
+ 0x62, 0x5f, 0x6b, 0x5f, 0xe3, 0x38, 0x9a, 0x5f,
+ 0xcd, 0x5f, 0xd7, 0x5f, 0xf9, 0x5f, 0x81, 0x60,
+ 0x3a, 0x39, 0x1c, 0x39, 0x94, 0x60, 0xd4, 0x26,
+ 0xc7, 0x60, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00,
+ 0x02, 0x08, 0x00, 0x80, 0x08, 0x00, 0x00, 0x08,
+ 0x80, 0x28, 0x80, 0x02, 0x00, 0x00, 0x02, 0x48,
+ 0x61, 0x00, 0x04, 0x06, 0x04, 0x32, 0x46, 0x6a,
+ 0x5c, 0x67, 0x96, 0xaa, 0xae, 0xc8, 0xd3, 0x5d,
+ 0x62, 0x00, 0x54, 0x77, 0xf3, 0x0c, 0x2b, 0x3d,
+ 0x63, 0xfc, 0x62, 0x68, 0x63, 0x83, 0x63, 0xe4,
+ 0x63, 0xf1, 0x2b, 0x22, 0x64, 0xc5, 0x63, 0xa9,
+ 0x63, 0x2e, 0x3a, 0x69, 0x64, 0x7e, 0x64, 0x9d,
+ 0x64, 0x77, 0x64, 0x6c, 0x3a, 0x4f, 0x65, 0x6c,
+ 0x65, 0x0a, 0x30, 0xe3, 0x65, 0xf8, 0x66, 0x49,
+ 0x66, 0x19, 0x3b, 0x91, 0x66, 0x08, 0x3b, 0xe4,
+ 0x3a, 0x92, 0x51, 0x95, 0x51, 0x00, 0x67, 0x9c,
+ 0x66, 0xad, 0x80, 0xd9, 0x43, 0x17, 0x67, 0x1b,
+ 0x67, 0x21, 0x67, 0x5e, 0x67, 0x53, 0x67, 0xc3,
+ 0x33, 0x49, 0x3b, 0xfa, 0x67, 0x85, 0x67, 0x52,
+ 0x68, 0x85, 0x68, 0x6d, 0x34, 0x8e, 0x68, 0x1f,
+ 0x68, 0x14, 0x69, 0x9d, 0x3b, 0x42, 0x69, 0xa3,
+ 0x69, 0xea, 0x69, 0xa8, 0x6a, 0xa3, 0x36, 0xdb,
+ 0x6a, 0x18, 0x3c, 0x21, 0x6b, 0xa7, 0x38, 0x54,
+ 0x6b, 0x4e, 0x3c, 0x72, 0x6b, 0x9f, 0x6b, 0xba,
+ 0x6b, 0xbb, 0x6b, 0x8d, 0x3a, 0x0b, 0x1d, 0xfa,
+ 0x3a, 0x4e, 0x6c, 0xbc, 0x3c, 0xbf, 0x6c, 0xcd,
+ 0x6c, 0x67, 0x6c, 0x16, 0x6d, 0x3e, 0x6d, 0x77,
+ 0x6d, 0x41, 0x6d, 0x69, 0x6d, 0x78, 0x6d, 0x85,
+ 0x6d, 0x1e, 0x3d, 0x34, 0x6d, 0x2f, 0x6e, 0x6e,
+ 0x6e, 0x33, 0x3d, 0xcb, 0x6e, 0xc7, 0x6e, 0xd1,
+ 0x3e, 0xf9, 0x6d, 0x6e, 0x6f, 0x5e, 0x3f, 0x8e,
+ 0x3f, 0xc6, 0x6f, 0x39, 0x70, 0x1e, 0x70, 0x1b,
+ 0x70, 0x96, 0x3d, 0x4a, 0x70, 0x7d, 0x70, 0x77,
+ 0x70, 0xad, 0x70, 0x25, 0x05, 0x45, 0x71, 0x63,
+ 0x42, 0x9c, 0x71, 0xab, 0x43, 0x28, 0x72, 0x35,
+ 0x72, 0x50, 0x72, 0x08, 0x46, 0x80, 0x72, 0x95,
+ 0x72, 0x35, 0x47, 0x02, 0x20, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00,
+ 0x02, 0x02, 0x80, 0x8a, 0x00, 0x00, 0x20, 0x00,
+ 0x08, 0x0a, 0x00, 0x80, 0x88, 0x80, 0x20, 0x14,
+ 0x48, 0x7a, 0x73, 0x8b, 0x73, 0xac, 0x3e, 0xa5,
+ 0x73, 0xb8, 0x3e, 0xb8, 0x3e, 0x47, 0x74, 0x5c,
+ 0x74, 0x71, 0x74, 0x85, 0x74, 0xca, 0x74, 0x1b,
+ 0x3f, 0x24, 0x75, 0x36, 0x4c, 0x3e, 0x75, 0x92,
+ 0x4c, 0x70, 0x75, 0x9f, 0x21, 0x10, 0x76, 0xa1,
+ 0x4f, 0xb8, 0x4f, 0x44, 0x50, 0xfc, 0x3f, 0x08,
+ 0x40, 0xf4, 0x76, 0xf3, 0x50, 0xf2, 0x50, 0x19,
+ 0x51, 0x33, 0x51, 0x1e, 0x77, 0x1f, 0x77, 0x1f,
+ 0x77, 0x4a, 0x77, 0x39, 0x40, 0x8b, 0x77, 0x46,
+ 0x40, 0x96, 0x40, 0x1d, 0x54, 0x4e, 0x78, 0x8c,
+ 0x78, 0xcc, 0x78, 0xe3, 0x40, 0x26, 0x56, 0x56,
+ 0x79, 0x9a, 0x56, 0xc5, 0x56, 0x8f, 0x79, 0xeb,
+ 0x79, 0x2f, 0x41, 0x40, 0x7a, 0x4a, 0x7a, 0x4f,
+ 0x7a, 0x7c, 0x59, 0xa7, 0x5a, 0xa7, 0x5a, 0xee,
+ 0x7a, 0x02, 0x42, 0xab, 0x5b, 0xc6, 0x7b, 0xc9,
+ 0x7b, 0x27, 0x42, 0x80, 0x5c, 0xd2, 0x7c, 0xa0,
+ 0x42, 0xe8, 0x7c, 0xe3, 0x7c, 0x00, 0x7d, 0x86,
+ 0x5f, 0x63, 0x7d, 0x01, 0x43, 0xc7, 0x7d, 0x02,
+ 0x7e, 0x45, 0x7e, 0x34, 0x43, 0x28, 0x62, 0x47,
+ 0x62, 0x59, 0x43, 0xd9, 0x62, 0x7a, 0x7f, 0x3e,
+ 0x63, 0x95, 0x7f, 0xfa, 0x7f, 0x05, 0x80, 0xda,
+ 0x64, 0x23, 0x65, 0x60, 0x80, 0xa8, 0x65, 0x70,
+ 0x80, 0x5f, 0x33, 0xd5, 0x43, 0xb2, 0x80, 0x03,
+ 0x81, 0x0b, 0x44, 0x3e, 0x81, 0xb5, 0x5a, 0xa7,
+ 0x67, 0xb5, 0x67, 0x93, 0x33, 0x9c, 0x33, 0x01,
+ 0x82, 0x04, 0x82, 0x9e, 0x8f, 0x6b, 0x44, 0x91,
+ 0x82, 0x8b, 0x82, 0x9d, 0x82, 0xb3, 0x52, 0xb1,
+ 0x82, 0xb3, 0x82, 0xbd, 0x82, 0xe6, 0x82, 0x3c,
+ 0x6b, 0xe5, 0x82, 0x1d, 0x83, 0x63, 0x83, 0xad,
+ 0x83, 0x23, 0x83, 0xbd, 0x83, 0xe7, 0x83, 0x57,
+ 0x84, 0x53, 0x83, 0xca, 0x83, 0xcc, 0x83, 0xdc,
+ 0x83, 0x36, 0x6c, 0x6b, 0x6d, 0x02, 0x00, 0x00,
+ 0x20, 0x22, 0x2a, 0xa0, 0x0a, 0x00, 0x20, 0x80,
+ 0x28, 0x00, 0xa8, 0x20, 0x20, 0x00, 0x02, 0x80,
+ 0x22, 0x02, 0x8a, 0x08, 0x00, 0xaa, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x28, 0xd5, 0x6c, 0x2b,
+ 0x45, 0xf1, 0x84, 0xf3, 0x84, 0x16, 0x85, 0xca,
+ 0x73, 0x64, 0x85, 0x2c, 0x6f, 0x5d, 0x45, 0x61,
+ 0x45, 0xb1, 0x6f, 0xd2, 0x70, 0x6b, 0x45, 0x50,
+ 0x86, 0x5c, 0x86, 0x67, 0x86, 0x69, 0x86, 0xa9,
+ 0x86, 0x88, 0x86, 0x0e, 0x87, 0xe2, 0x86, 0x79,
+ 0x87, 0x28, 0x87, 0x6b, 0x87, 0x86, 0x87, 0xd7,
+ 0x45, 0xe1, 0x87, 0x01, 0x88, 0xf9, 0x45, 0x60,
+ 0x88, 0x63, 0x88, 0x67, 0x76, 0xd7, 0x88, 0xde,
+ 0x88, 0x35, 0x46, 0xfa, 0x88, 0xbb, 0x34, 0xae,
+ 0x78, 0x66, 0x79, 0xbe, 0x46, 0xc7, 0x46, 0xa0,
+ 0x8a, 0xed, 0x8a, 0x8a, 0x8b, 0x55, 0x8c, 0xa8,
+ 0x7c, 0xab, 0x8c, 0xc1, 0x8c, 0x1b, 0x8d, 0x77,
+ 0x8d, 0x2f, 0x7f, 0x04, 0x08, 0xcb, 0x8d, 0xbc,
+ 0x8d, 0xf0, 0x8d, 0xde, 0x08, 0xd4, 0x8e, 0x38,
+ 0x8f, 0xd2, 0x85, 0xed, 0x85, 0x94, 0x90, 0xf1,
+ 0x90, 0x11, 0x91, 0x2e, 0x87, 0x1b, 0x91, 0x38,
+ 0x92, 0xd7, 0x92, 0xd8, 0x92, 0x7c, 0x92, 0xf9,
+ 0x93, 0x15, 0x94, 0xfa, 0x8b, 0x8b, 0x95, 0x95,
+ 0x49, 0xb7, 0x95, 0x77, 0x8d, 0xe6, 0x49, 0xc3,
+ 0x96, 0xb2, 0x5d, 0x23, 0x97, 0x45, 0x91, 0x1a,
+ 0x92, 0x6e, 0x4a, 0x76, 0x4a, 0xe0, 0x97, 0x0a,
+ 0x94, 0xb2, 0x4a, 0x96, 0x94, 0x0b, 0x98, 0x0b,
+ 0x98, 0x29, 0x98, 0xb6, 0x95, 0xe2, 0x98, 0x33,
+ 0x4b, 0x29, 0x99, 0xa7, 0x99, 0xc2, 0x99, 0xfe,
+ 0x99, 0xce, 0x4b, 0x30, 0x9b, 0x12, 0x9b, 0x40,
+ 0x9c, 0xfd, 0x9c, 0xce, 0x4c, 0xed, 0x4c, 0x67,
+ 0x9d, 0xce, 0xa0, 0xf8, 0x4c, 0x05, 0xa1, 0x0e,
+ 0xa2, 0x91, 0xa2, 0xbb, 0x9e, 0x56, 0x4d, 0xf9,
+ 0x9e, 0xfe, 0x9e, 0x05, 0x9f, 0x0f, 0x9f, 0x16,
+ 0x9f, 0x3b, 0x9f, 0x00, 0xa6, 0x02, 0x88, 0xa0,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x28, 0x00,
+ 0x08, 0xa0, 0x80, 0xa0, 0x80, 0x00, 0x80, 0x80,
+ 0x00, 0x0a, 0x88, 0x80, 0x00, 0x80, 0x00, 0x20,
+ 0x2a, 0x00, 0x80,
};
-static const uint16_t unicode_comp_table[945] = {
+static const uint16_t unicode_comp_table[965] = {
0x4a01, 0x49c0, 0x4a02, 0x0280, 0x0281, 0x0282, 0x0283, 0x02c0,
0x02c2, 0x0a00, 0x0284, 0x2442, 0x0285, 0x07c0, 0x0980, 0x0982,
0x2440, 0x2280, 0x02c4, 0x2282, 0x2284, 0x2286, 0x02c6, 0x02c8,
@@ -2317,9 +2289,11 @@ static const uint16_t unicode_comp_table[945] = {
0x5704, 0x5706, 0x5708, 0x570a, 0x570c, 0x570e, 0x5710, 0x5712,
0x5714, 0x5716, 0x5740, 0x5742, 0x5744, 0x5780, 0x5781, 0x57c0,
0x57c1, 0x5800, 0x5801, 0x5840, 0x5841, 0x5880, 0x5881, 0x5900,
- 0x5901, 0x5902, 0x5903, 0x5940, 0x8f40, 0x8f42, 0x8f80, 0x8fc0,
- 0x8fc1, 0x9000, 0x9001, 0x9041, 0x9040, 0x9043, 0x9080, 0x9081,
- 0x90c0,
+ 0x5901, 0x5902, 0x5903, 0x5940, 0x8ec0, 0x8f00, 0x8fc0, 0x8fc2,
+ 0x9000, 0x9040, 0x9041, 0x9080, 0x9081, 0x90c0, 0x90c2, 0x9100,
+ 0x9140, 0x9182, 0x9180, 0x9183, 0x91c1, 0x91c0, 0x91c3, 0x9200,
+ 0x9201, 0x9240, 0x9280, 0x9282, 0x9284, 0x9281, 0x9285, 0x9287,
+ 0x9286, 0x9283, 0x92c1, 0x92c0, 0x92c2,
};
typedef enum {
@@ -2405,7 +2379,7 @@ static const char unicode_gc_name_table[] =
"C,Other" "\0"
;
-static const uint8_t unicode_gc_table[3948] = {
+static const uint8_t unicode_gc_table[4070] = {
0xfa, 0x18, 0x17, 0x56, 0x0d, 0x56, 0x12, 0x13,
0x16, 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36,
0x4c, 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e,
@@ -2449,8 +2423,8 @@ static const uint8_t unicode_gc_table[3948] = {
0x2d, 0xe5, 0x0e, 0x66, 0x04, 0xe6, 0x01, 0x04,
0x46, 0x04, 0x86, 0x20, 0xf6, 0x07, 0x00, 0xe5,
0x11, 0x46, 0x20, 0x16, 0x00, 0xe5, 0x03, 0x80,
- 0xe5, 0x10, 0x0e, 0xa5, 0x00, 0x3b, 0xa0, 0xe6,
- 0x00, 0xe5, 0x21, 0x04, 0xe6, 0x10, 0x1b, 0xe6,
+ 0xe5, 0x10, 0x0e, 0xa5, 0x00, 0x3b, 0x80, 0xe6,
+ 0x01, 0xe5, 0x21, 0x04, 0xe6, 0x10, 0x1b, 0xe6,
0x18, 0x07, 0xe5, 0x2e, 0x06, 0x07, 0x06, 0x05,
0x47, 0xe6, 0x00, 0x67, 0x06, 0x27, 0x05, 0xc6,
0xe5, 0x02, 0x26, 0x36, 0xe9, 0x02, 0x16, 0x04,
@@ -2549,82 +2523,82 @@ static const uint8_t unicode_gc_table[3948] = {
0xe9, 0x02, 0xa0, 0xd6, 0x04, 0xb6, 0x20, 0xe6,
0x06, 0x08, 0xe6, 0x08, 0xe0, 0x29, 0x66, 0x07,
0xe5, 0x27, 0x06, 0x07, 0x86, 0x07, 0x06, 0x87,
- 0x06, 0x27, 0xe5, 0x00, 0x40, 0xe9, 0x02, 0xd6,
- 0xef, 0x02, 0xe6, 0x01, 0xef, 0x01, 0x36, 0x00,
+ 0x06, 0x27, 0xe5, 0x00, 0x00, 0x36, 0xe9, 0x02,
+ 0xd6, 0xef, 0x02, 0xe6, 0x01, 0xef, 0x01, 0x56,
0x26, 0x07, 0xe5, 0x16, 0x07, 0x66, 0x27, 0x26,
0x07, 0x46, 0x25, 0xe9, 0x02, 0xe5, 0x24, 0x06,
0x07, 0x26, 0x47, 0x06, 0x07, 0x46, 0x27, 0xe0,
0x00, 0x76, 0xe5, 0x1c, 0xe7, 0x00, 0xe6, 0x00,
0x27, 0x26, 0x40, 0x96, 0xe9, 0x02, 0x40, 0x45,
0xe9, 0x02, 0xe5, 0x16, 0xa4, 0x36, 0xe2, 0x01,
- 0xc0, 0xe1, 0x23, 0x20, 0x41, 0xf6, 0x00, 0xe0,
- 0x00, 0x46, 0x16, 0xe6, 0x05, 0x07, 0xc6, 0x65,
- 0x06, 0xa5, 0x06, 0x25, 0x07, 0x26, 0x05, 0x80,
- 0xe2, 0x24, 0xe4, 0x37, 0xe2, 0x05, 0x04, 0xe2,
- 0x1a, 0xe4, 0x1d, 0xe6, 0x38, 0xff, 0x80, 0x0e,
- 0xe2, 0x00, 0xff, 0x5a, 0xe2, 0x00, 0xe1, 0x00,
- 0xa2, 0x20, 0xa1, 0x20, 0xe2, 0x00, 0xe1, 0x00,
- 0xe2, 0x00, 0xe1, 0x00, 0xa2, 0x20, 0xa1, 0x20,
- 0xe2, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
- 0x00, 0x3f, 0xc2, 0xe1, 0x00, 0xe2, 0x06, 0x20,
- 0xe2, 0x00, 0xe3, 0x00, 0xe2, 0x00, 0xe3, 0x00,
- 0xe2, 0x00, 0xe3, 0x00, 0x82, 0x00, 0x22, 0x61,
- 0x03, 0x0e, 0x02, 0x4e, 0x42, 0x00, 0x22, 0x61,
- 0x03, 0x4e, 0x62, 0x20, 0x22, 0x61, 0x00, 0x4e,
- 0xe2, 0x00, 0x81, 0x4e, 0x20, 0x42, 0x00, 0x22,
- 0x61, 0x03, 0x2e, 0x00, 0xf7, 0x03, 0x9b, 0xb1,
- 0x36, 0x14, 0x15, 0x12, 0x34, 0x15, 0x12, 0x14,
- 0xf6, 0x00, 0x18, 0x19, 0x9b, 0x17, 0xf6, 0x01,
- 0x14, 0x15, 0x76, 0x30, 0x56, 0x0c, 0x12, 0x13,
- 0xf6, 0x03, 0x0c, 0x16, 0x10, 0xf6, 0x02, 0x17,
- 0x9b, 0x00, 0xfb, 0x02, 0x0b, 0x04, 0x20, 0xab,
- 0x4c, 0x12, 0x13, 0x04, 0xeb, 0x02, 0x4c, 0x12,
- 0x13, 0x00, 0xe4, 0x05, 0x40, 0xed, 0x19, 0xe0,
- 0x07, 0xe6, 0x05, 0x68, 0x06, 0x48, 0xe6, 0x04,
- 0xe0, 0x07, 0x2f, 0x01, 0x6f, 0x01, 0x2f, 0x02,
- 0x41, 0x22, 0x41, 0x02, 0x0f, 0x01, 0x2f, 0x0c,
- 0x81, 0xaf, 0x01, 0x0f, 0x01, 0x0f, 0x01, 0x0f,
- 0x61, 0x0f, 0x02, 0x61, 0x02, 0x65, 0x02, 0x2f,
- 0x22, 0x21, 0x8c, 0x3f, 0x42, 0x0f, 0x0c, 0x2f,
- 0x02, 0x0f, 0xeb, 0x08, 0xea, 0x1b, 0x3f, 0x6a,
- 0x0b, 0x2f, 0x60, 0x8c, 0x8f, 0x2c, 0x6f, 0x0c,
- 0x2f, 0x0c, 0x2f, 0x0c, 0xcf, 0x0c, 0xef, 0x17,
- 0x2c, 0x2f, 0x0c, 0x0f, 0x0c, 0xef, 0x17, 0xec,
- 0x80, 0x84, 0xef, 0x00, 0x12, 0x13, 0x12, 0x13,
- 0xef, 0x0c, 0x2c, 0xcf, 0x12, 0x13, 0xef, 0x49,
- 0x0c, 0xef, 0x16, 0xec, 0x11, 0xef, 0x20, 0xac,
- 0xef, 0x3d, 0xe0, 0x11, 0xef, 0x03, 0xe0, 0x0d,
- 0xeb, 0x34, 0xef, 0x46, 0xeb, 0x0e, 0xef, 0x80,
- 0x2f, 0x0c, 0xef, 0x01, 0x0c, 0xef, 0x2e, 0xec,
- 0x00, 0xef, 0x67, 0x0c, 0xef, 0x80, 0x70, 0x12,
- 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12,
- 0x13, 0x12, 0x13, 0x12, 0x13, 0xeb, 0x16, 0xef,
- 0x24, 0x8c, 0x12, 0x13, 0xec, 0x17, 0x12, 0x13,
+ 0x3f, 0x80, 0xe1, 0x23, 0x20, 0x41, 0xf6, 0x00,
+ 0xe0, 0x00, 0x46, 0x16, 0xe6, 0x05, 0x07, 0xc6,
+ 0x65, 0x06, 0xa5, 0x06, 0x25, 0x07, 0x26, 0x05,
+ 0x80, 0xe2, 0x24, 0xe4, 0x37, 0xe2, 0x05, 0x04,
+ 0xe2, 0x1a, 0xe4, 0x1d, 0xe6, 0x38, 0xff, 0x80,
+ 0x0e, 0xe2, 0x00, 0xff, 0x5a, 0xe2, 0x00, 0xe1,
+ 0x00, 0xa2, 0x20, 0xa1, 0x20, 0xe2, 0x00, 0xe1,
+ 0x00, 0xe2, 0x00, 0xe1, 0x00, 0xa2, 0x20, 0xa1,
+ 0x20, 0xe2, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x3f, 0xc2, 0xe1, 0x00, 0xe2, 0x06,
+ 0x20, 0xe2, 0x00, 0xe3, 0x00, 0xe2, 0x00, 0xe3,
+ 0x00, 0xe2, 0x00, 0xe3, 0x00, 0x82, 0x00, 0x22,
+ 0x61, 0x03, 0x0e, 0x02, 0x4e, 0x42, 0x00, 0x22,
+ 0x61, 0x03, 0x4e, 0x62, 0x20, 0x22, 0x61, 0x00,
+ 0x4e, 0xe2, 0x00, 0x81, 0x4e, 0x20, 0x42, 0x00,
+ 0x22, 0x61, 0x03, 0x2e, 0x00, 0xf7, 0x03, 0x9b,
+ 0xb1, 0x36, 0x14, 0x15, 0x12, 0x34, 0x15, 0x12,
+ 0x14, 0xf6, 0x00, 0x18, 0x19, 0x9b, 0x17, 0xf6,
+ 0x01, 0x14, 0x15, 0x76, 0x30, 0x56, 0x0c, 0x12,
+ 0x13, 0xf6, 0x03, 0x0c, 0x16, 0x10, 0xf6, 0x02,
+ 0x17, 0x9b, 0x00, 0xfb, 0x02, 0x0b, 0x04, 0x20,
+ 0xab, 0x4c, 0x12, 0x13, 0x04, 0xeb, 0x02, 0x4c,
+ 0x12, 0x13, 0x00, 0xe4, 0x05, 0x40, 0xed, 0x19,
+ 0xe0, 0x07, 0xe6, 0x05, 0x68, 0x06, 0x48, 0xe6,
+ 0x04, 0xe0, 0x07, 0x2f, 0x01, 0x6f, 0x01, 0x2f,
+ 0x02, 0x41, 0x22, 0x41, 0x02, 0x0f, 0x01, 0x2f,
+ 0x0c, 0x81, 0xaf, 0x01, 0x0f, 0x01, 0x0f, 0x01,
+ 0x0f, 0x61, 0x0f, 0x02, 0x61, 0x02, 0x65, 0x02,
+ 0x2f, 0x22, 0x21, 0x8c, 0x3f, 0x42, 0x0f, 0x0c,
+ 0x2f, 0x02, 0x0f, 0xeb, 0x08, 0xea, 0x1b, 0x3f,
+ 0x6a, 0x0b, 0x2f, 0x60, 0x8c, 0x8f, 0x2c, 0x6f,
+ 0x0c, 0x2f, 0x0c, 0x2f, 0x0c, 0xcf, 0x0c, 0xef,
+ 0x17, 0x2c, 0x2f, 0x0c, 0x0f, 0x0c, 0xef, 0x17,
+ 0xec, 0x80, 0x84, 0xef, 0x00, 0x12, 0x13, 0x12,
+ 0x13, 0xef, 0x0c, 0x2c, 0xcf, 0x12, 0x13, 0xef,
+ 0x49, 0x0c, 0xef, 0x16, 0xec, 0x11, 0xef, 0x20,
+ 0xac, 0xef, 0x40, 0xe0, 0x0e, 0xef, 0x03, 0xe0,
+ 0x0d, 0xeb, 0x34, 0xef, 0x46, 0xeb, 0x0e, 0xef,
+ 0x80, 0x2f, 0x0c, 0xef, 0x01, 0x0c, 0xef, 0x2e,
+ 0xec, 0x00, 0xef, 0x67, 0x0c, 0xef, 0x80, 0x70,
0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
- 0xec, 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b, 0x12,
- 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12,
+ 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xeb, 0x16,
+ 0xef, 0x24, 0x8c, 0x12, 0x13, 0xec, 0x17, 0x12,
0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12,
- 0x13, 0x12, 0x13, 0x12, 0x13, 0xec, 0x37, 0x12,
- 0x13, 0x12, 0x13, 0xec, 0x18, 0x12, 0x13, 0xec,
- 0x80, 0x7a, 0xef, 0x28, 0xec, 0x0d, 0x2f, 0xac,
- 0xef, 0x1f, 0x20, 0xef, 0x18, 0x00, 0xef, 0x61,
- 0xe1, 0x28, 0xe2, 0x28, 0x5f, 0x21, 0x22, 0xdf,
- 0x41, 0x02, 0x3f, 0x02, 0x3f, 0x82, 0x24, 0x41,
- 0x02, 0xff, 0x5a, 0x02, 0xaf, 0x7f, 0x46, 0x3f,
- 0x80, 0x76, 0x0b, 0x36, 0xe2, 0x1e, 0x00, 0x02,
- 0x80, 0x02, 0x20, 0xe5, 0x30, 0xc0, 0x04, 0x16,
- 0xe0, 0x06, 0x06, 0xe5, 0x0f, 0xe0, 0x01, 0xc5,
- 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5,
- 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xe6,
- 0x18, 0x36, 0x14, 0x15, 0x14, 0x15, 0x56, 0x14,
- 0x15, 0x16, 0x14, 0x15, 0xf6, 0x01, 0x11, 0x36,
- 0x11, 0x16, 0x14, 0x15, 0x36, 0x14, 0x15, 0x12,
- 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x96,
- 0x04, 0xf6, 0x02, 0x31, 0x76, 0x11, 0x16, 0x12,
- 0xf6, 0x05, 0x2f, 0x56, 0x12, 0x13, 0x12, 0x13,
- 0x12, 0x13, 0x12, 0x13, 0x11, 0xe0, 0x1a, 0xef,
- 0x12, 0x00, 0xef, 0x51, 0xe0, 0x04, 0xef, 0x80,
- 0x4e, 0xe0, 0x12, 0xef, 0x04, 0x60, 0x17, 0x56,
+ 0x13, 0xec, 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b,
+ 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
+ 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
+ 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xec, 0x37,
+ 0x12, 0x13, 0x12, 0x13, 0xec, 0x18, 0x12, 0x13,
+ 0xec, 0x80, 0x7a, 0xef, 0x28, 0xec, 0x0d, 0x2f,
+ 0xac, 0xef, 0x1f, 0x20, 0xef, 0x18, 0x00, 0xef,
+ 0x61, 0xe1, 0x28, 0xe2, 0x28, 0x5f, 0x21, 0x22,
+ 0xdf, 0x41, 0x02, 0x3f, 0x02, 0x3f, 0x82, 0x24,
+ 0x41, 0x02, 0xff, 0x5a, 0x02, 0xaf, 0x7f, 0x46,
+ 0x3f, 0x80, 0x76, 0x0b, 0x36, 0xe2, 0x1e, 0x00,
+ 0x02, 0x80, 0x02, 0x20, 0xe5, 0x30, 0xc0, 0x04,
+ 0x16, 0xe0, 0x06, 0x06, 0xe5, 0x0f, 0xe0, 0x01,
+ 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00,
+ 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00,
+ 0xe6, 0x18, 0x36, 0x14, 0x15, 0x14, 0x15, 0x56,
+ 0x14, 0x15, 0x16, 0x14, 0x15, 0xf6, 0x01, 0x11,
+ 0x36, 0x11, 0x16, 0x14, 0x15, 0x36, 0x14, 0x15,
+ 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
+ 0x96, 0x04, 0xf6, 0x02, 0x31, 0x76, 0x11, 0x16,
+ 0x12, 0xf6, 0x05, 0x2f, 0x56, 0x12, 0x13, 0x12,
+ 0x13, 0x12, 0x13, 0x12, 0x13, 0x11, 0xe0, 0x1a,
+ 0xef, 0x12, 0x00, 0xef, 0x51, 0xe0, 0x04, 0xef,
+ 0x80, 0x4e, 0xe0, 0x12, 0xef, 0x08, 0x17, 0x56,
0x0f, 0x04, 0x05, 0x0a, 0x12, 0x13, 0x12, 0x13,
0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x2f, 0x12,
0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x11,
@@ -2633,146 +2607,154 @@ static const uint8_t unicode_gc_table[3948] = {
0xe5, 0x4e, 0x20, 0x26, 0x2e, 0x24, 0x05, 0x11,
0xe5, 0x52, 0x16, 0x44, 0x05, 0x80, 0xe5, 0x23,
0x00, 0xe5, 0x56, 0x00, 0x2f, 0x6b, 0xef, 0x02,
- 0xe5, 0x18, 0xef, 0x1c, 0xe0, 0x04, 0xe5, 0x08,
- 0xef, 0x17, 0x00, 0xeb, 0x02, 0xef, 0x16, 0xeb,
- 0x00, 0x0f, 0xeb, 0x07, 0xef, 0x18, 0xeb, 0x02,
- 0xef, 0x1f, 0xeb, 0x07, 0xef, 0x80, 0xb8, 0xe5,
- 0x99, 0x38, 0xef, 0x38, 0xe5, 0xc0, 0x11, 0x8d,
- 0x04, 0xe5, 0x83, 0xef, 0x40, 0xef, 0x2f, 0xe0,
- 0x01, 0xe5, 0x20, 0xa4, 0x36, 0xe5, 0x80, 0x84,
- 0x04, 0x56, 0xe5, 0x08, 0xe9, 0x02, 0x25, 0xe0,
- 0x0c, 0xff, 0x26, 0x05, 0x06, 0x48, 0x16, 0xe6,
- 0x02, 0x16, 0x04, 0xff, 0x14, 0x24, 0x26, 0xe5,
- 0x3e, 0xea, 0x02, 0x26, 0xb6, 0xe0, 0x00, 0xee,
- 0x0f, 0xe4, 0x01, 0x2e, 0xff, 0x06, 0x22, 0xff,
- 0x36, 0x04, 0xe2, 0x00, 0x9f, 0xff, 0x02, 0x04,
- 0x2e, 0x7f, 0x05, 0x7f, 0x22, 0xff, 0x0d, 0x61,
- 0x02, 0x81, 0x02, 0xff, 0x07, 0x41, 0x02, 0x3f,
- 0x80, 0x3f, 0x00, 0x02, 0x00, 0x02, 0x7f, 0xe0,
- 0x10, 0x44, 0x3f, 0x05, 0x24, 0x02, 0xc5, 0x06,
- 0x45, 0x06, 0x65, 0x06, 0xe5, 0x0f, 0x27, 0x26,
- 0x07, 0x6f, 0x06, 0x40, 0xab, 0x2f, 0x0d, 0x0f,
- 0xa0, 0xe5, 0x2c, 0x76, 0xe0, 0x00, 0x27, 0xe5,
- 0x2a, 0xe7, 0x08, 0x26, 0xe0, 0x00, 0x36, 0xe9,
- 0x02, 0xa0, 0xe6, 0x0a, 0xa5, 0x56, 0x05, 0x16,
- 0x25, 0x06, 0xe9, 0x02, 0xe5, 0x14, 0xe6, 0x00,
- 0x36, 0xe5, 0x0f, 0xe6, 0x03, 0x27, 0xe0, 0x03,
- 0x16, 0xe5, 0x15, 0x40, 0x46, 0x07, 0xe5, 0x27,
- 0x06, 0x27, 0x66, 0x27, 0x26, 0x47, 0xf6, 0x05,
- 0x00, 0x04, 0xe9, 0x02, 0x60, 0x36, 0x85, 0x06,
- 0x04, 0xe5, 0x01, 0xe9, 0x02, 0x85, 0x00, 0xe5,
- 0x21, 0xa6, 0x27, 0x26, 0x27, 0x26, 0xe0, 0x01,
- 0x45, 0x06, 0xe5, 0x00, 0x06, 0x07, 0x20, 0xe9,
- 0x02, 0x20, 0x76, 0xe5, 0x08, 0x04, 0xa5, 0x4f,
- 0x05, 0x07, 0x06, 0x07, 0xe5, 0x2a, 0x06, 0x05,
- 0x46, 0x25, 0x26, 0x85, 0x26, 0x05, 0x06, 0x05,
- 0xe0, 0x10, 0x25, 0x04, 0x36, 0xe5, 0x03, 0x07,
- 0x26, 0x27, 0x36, 0x05, 0x24, 0x07, 0x06, 0xe0,
- 0x02, 0xa5, 0x20, 0xa5, 0x20, 0xa5, 0xe0, 0x01,
- 0xc5, 0x00, 0xc5, 0x00, 0xe2, 0x23, 0x0e, 0x64,
- 0xe2, 0x01, 0x04, 0x2e, 0x60, 0xe2, 0x48, 0xe5,
- 0x1b, 0x27, 0x06, 0x27, 0x06, 0x27, 0x16, 0x07,
- 0x06, 0x20, 0xe9, 0x02, 0xa0, 0xe5, 0xab, 0x1c,
- 0xe0, 0x04, 0xe5, 0x0f, 0x60, 0xe5, 0x29, 0x60,
- 0xfc, 0x87, 0x78, 0xfd, 0x98, 0x78, 0xe5, 0x80,
- 0xe6, 0x20, 0xe5, 0x62, 0xe0, 0x1e, 0xc2, 0xe0,
- 0x04, 0x82, 0x80, 0x05, 0x06, 0xe5, 0x02, 0x0c,
- 0xe5, 0x05, 0x00, 0x85, 0x00, 0x05, 0x00, 0x25,
- 0x00, 0x25, 0x00, 0xe5, 0x64, 0xee, 0x09, 0xe0,
- 0x08, 0xe5, 0x80, 0xe3, 0x13, 0x12, 0xef, 0x08,
- 0xe5, 0x38, 0x20, 0xe5, 0x2e, 0xc0, 0x0f, 0xe0,
- 0x18, 0xe5, 0x04, 0x0d, 0x4f, 0xe6, 0x08, 0xd6,
- 0x12, 0x13, 0x16, 0xa0, 0xe6, 0x08, 0x16, 0x31,
- 0x30, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12,
+ 0xe5, 0x18, 0xef, 0x1e, 0xe0, 0x01, 0x0f, 0xe5,
+ 0x08, 0xef, 0x17, 0x00, 0xeb, 0x02, 0xef, 0x16,
+ 0xeb, 0x00, 0x0f, 0xeb, 0x07, 0xef, 0x18, 0xeb,
+ 0x02, 0xef, 0x1f, 0xeb, 0x07, 0xef, 0x80, 0xb8,
+ 0xe5, 0x99, 0x38, 0xef, 0x38, 0xe5, 0xc0, 0x11,
+ 0x8d, 0x04, 0xe5, 0x83, 0xef, 0x40, 0xef, 0x2f,
+ 0xe0, 0x01, 0xe5, 0x20, 0xa4, 0x36, 0xe5, 0x80,
+ 0x84, 0x04, 0x56, 0xe5, 0x08, 0xe9, 0x02, 0x25,
+ 0xe0, 0x0c, 0xff, 0x26, 0x05, 0x06, 0x48, 0x16,
+ 0xe6, 0x02, 0x16, 0x04, 0xff, 0x14, 0x24, 0x26,
+ 0xe5, 0x3e, 0xea, 0x02, 0x26, 0xb6, 0xe0, 0x00,
+ 0xee, 0x0f, 0xe4, 0x01, 0x2e, 0xff, 0x06, 0x22,
+ 0xff, 0x36, 0x04, 0xe2, 0x00, 0x9f, 0xff, 0x02,
+ 0x04, 0x2e, 0x7f, 0x05, 0x7f, 0x22, 0xff, 0x0d,
+ 0x61, 0x02, 0x81, 0x02, 0xff, 0x07, 0x41, 0x02,
+ 0x5f, 0x3f, 0x20, 0x3f, 0x00, 0x02, 0x00, 0x02,
+ 0xdf, 0xe0, 0x0d, 0x44, 0x3f, 0x05, 0x24, 0x02,
+ 0xc5, 0x06, 0x45, 0x06, 0x65, 0x06, 0xe5, 0x0f,
+ 0x27, 0x26, 0x07, 0x6f, 0x06, 0x40, 0xab, 0x2f,
+ 0x0d, 0x0f, 0xa0, 0xe5, 0x2c, 0x76, 0xe0, 0x00,
+ 0x27, 0xe5, 0x2a, 0xe7, 0x08, 0x26, 0xe0, 0x00,
+ 0x36, 0xe9, 0x02, 0xa0, 0xe6, 0x0a, 0xa5, 0x56,
+ 0x05, 0x16, 0x25, 0x06, 0xe9, 0x02, 0xe5, 0x14,
+ 0xe6, 0x00, 0x36, 0xe5, 0x0f, 0xe6, 0x03, 0x27,
+ 0xe0, 0x03, 0x16, 0xe5, 0x15, 0x40, 0x46, 0x07,
+ 0xe5, 0x27, 0x06, 0x27, 0x66, 0x27, 0x26, 0x47,
+ 0xf6, 0x05, 0x00, 0x04, 0xe9, 0x02, 0x60, 0x36,
+ 0x85, 0x06, 0x04, 0xe5, 0x01, 0xe9, 0x02, 0x85,
+ 0x00, 0xe5, 0x21, 0xa6, 0x27, 0x26, 0x27, 0x26,
+ 0xe0, 0x01, 0x45, 0x06, 0xe5, 0x00, 0x06, 0x07,
+ 0x20, 0xe9, 0x02, 0x20, 0x76, 0xe5, 0x08, 0x04,
+ 0xa5, 0x4f, 0x05, 0x07, 0x06, 0x07, 0xe5, 0x2a,
+ 0x06, 0x05, 0x46, 0x25, 0x26, 0x85, 0x26, 0x05,
+ 0x06, 0x05, 0xe0, 0x10, 0x25, 0x04, 0x36, 0xe5,
+ 0x03, 0x07, 0x26, 0x27, 0x36, 0x05, 0x24, 0x07,
+ 0x06, 0xe0, 0x02, 0xa5, 0x20, 0xa5, 0x20, 0xa5,
+ 0xe0, 0x01, 0xc5, 0x00, 0xc5, 0x00, 0xe2, 0x23,
+ 0x0e, 0x64, 0xe2, 0x01, 0x04, 0x2e, 0x60, 0xe2,
+ 0x48, 0xe5, 0x1b, 0x27, 0x06, 0x27, 0x06, 0x27,
+ 0x16, 0x07, 0x06, 0x20, 0xe9, 0x02, 0xa0, 0xe5,
+ 0xab, 0x1c, 0xe0, 0x04, 0xe5, 0x0f, 0x60, 0xe5,
+ 0x29, 0x60, 0xfc, 0x87, 0x78, 0xfd, 0x98, 0x78,
+ 0xe5, 0x80, 0xe6, 0x20, 0xe5, 0x62, 0xe0, 0x1e,
+ 0xc2, 0xe0, 0x04, 0x82, 0x80, 0x05, 0x06, 0xe5,
+ 0x02, 0x0c, 0xe5, 0x05, 0x00, 0x85, 0x00, 0x05,
+ 0x00, 0x25, 0x00, 0x25, 0x00, 0xe5, 0x64, 0xee,
+ 0x09, 0xe0, 0x08, 0xe5, 0x80, 0xe3, 0x13, 0x12,
+ 0xef, 0x08, 0xe5, 0x38, 0x20, 0xe5, 0x2e, 0xc0,
+ 0x0f, 0xe0, 0x18, 0xe5, 0x04, 0x0d, 0x4f, 0xe6,
+ 0x08, 0xd6, 0x12, 0x13, 0x16, 0xa0, 0xe6, 0x08,
+ 0x16, 0x31, 0x30, 0x12, 0x13, 0x12, 0x13, 0x12,
0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12,
- 0x13, 0x36, 0x12, 0x13, 0x76, 0x50, 0x56, 0x00,
- 0x76, 0x11, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
- 0x56, 0x0c, 0x11, 0x4c, 0x00, 0x16, 0x0d, 0x36,
- 0x60, 0x85, 0x00, 0xe5, 0x7f, 0x20, 0x1b, 0x00,
- 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16, 0x0c, 0x16,
- 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c, 0x36, 0xe1,
- 0x12, 0x12, 0x16, 0x13, 0x0e, 0x10, 0x0e, 0xe2,
- 0x12, 0x12, 0x0c, 0x13, 0x0c, 0x12, 0x13, 0x16,
- 0x12, 0x13, 0x36, 0xe5, 0x02, 0x04, 0xe5, 0x25,
- 0x24, 0xe5, 0x17, 0x40, 0xa5, 0x20, 0xa5, 0x20,
- 0xa5, 0x20, 0x45, 0x40, 0x2d, 0x0c, 0x0e, 0x0f,
- 0x2d, 0x00, 0x0f, 0x6c, 0x2f, 0xe0, 0x02, 0x5b,
- 0x2f, 0x20, 0xe5, 0x04, 0x00, 0xe5, 0x12, 0x00,
- 0xe5, 0x0b, 0x00, 0x25, 0x00, 0xe5, 0x07, 0x20,
- 0xe5, 0x06, 0xe0, 0x1a, 0xe5, 0x73, 0x80, 0x56,
- 0x60, 0xeb, 0x25, 0x40, 0xef, 0x01, 0xea, 0x2d,
- 0x6b, 0xef, 0x09, 0x2b, 0x4f, 0x00, 0xef, 0x05,
- 0x40, 0x0f, 0xe0, 0x27, 0xef, 0x25, 0x06, 0xe0,
- 0x7a, 0xe5, 0x15, 0x40, 0xe5, 0x29, 0xe0, 0x07,
- 0x06, 0xeb, 0x13, 0x60, 0xe5, 0x18, 0x6b, 0xe0,
- 0x01, 0xe5, 0x0c, 0x0a, 0xe5, 0x00, 0x0a, 0x80,
- 0xe5, 0x1e, 0x86, 0x80, 0xe5, 0x16, 0x00, 0x16,
- 0xe5, 0x1c, 0x60, 0xe5, 0x00, 0x16, 0x8a, 0xe0,
- 0x22, 0xe1, 0x20, 0xe2, 0x20, 0xe5, 0x46, 0x20,
- 0xe9, 0x02, 0xa0, 0xe1, 0x1c, 0x60, 0xe2, 0x1c,
- 0x60, 0xe5, 0x20, 0xe0, 0x00, 0xe5, 0x2c, 0xe0,
- 0x03, 0x16, 0xe1, 0x03, 0x00, 0xe1, 0x07, 0x00,
- 0xc1, 0x00, 0x21, 0x00, 0xe2, 0x03, 0x00, 0xe2,
- 0x07, 0x00, 0xc2, 0x00, 0x22, 0xe0, 0x3b, 0xe5,
- 0x80, 0xaf, 0xe0, 0x01, 0xe5, 0x0e, 0xe0, 0x02,
- 0xe5, 0x00, 0xe0, 0x10, 0xa4, 0x00, 0xe4, 0x22,
- 0x00, 0xe4, 0x01, 0xe0, 0x3d, 0xa5, 0x20, 0x05,
- 0x00, 0xe5, 0x24, 0x00, 0x25, 0x40, 0x05, 0x20,
- 0xe5, 0x0f, 0x00, 0x16, 0xeb, 0x00, 0xe5, 0x0f,
- 0x2f, 0xcb, 0xe5, 0x17, 0xe0, 0x00, 0xeb, 0x01,
- 0xe0, 0x28, 0xe5, 0x0b, 0x00, 0x25, 0x80, 0x8b,
- 0xe5, 0x0e, 0xab, 0x40, 0x16, 0xe5, 0x12, 0x80,
- 0x16, 0xe0, 0x38, 0xe5, 0x30, 0x60, 0x2b, 0x25,
- 0xeb, 0x08, 0x20, 0xeb, 0x26, 0x05, 0x46, 0x00,
- 0x26, 0x80, 0x66, 0x65, 0x00, 0x45, 0x00, 0xe5,
- 0x15, 0x20, 0x46, 0x60, 0x06, 0xeb, 0x01, 0xc0,
- 0xf6, 0x01, 0xc0, 0xe5, 0x15, 0x2b, 0x16, 0xe5,
- 0x15, 0x4b, 0xe0, 0x18, 0xe5, 0x00, 0x0f, 0xe5,
- 0x14, 0x26, 0x60, 0x8b, 0xd6, 0xe0, 0x01, 0xe5,
- 0x2e, 0x40, 0xd6, 0xe5, 0x0e, 0x20, 0xeb, 0x00,
- 0xe5, 0x0b, 0x80, 0xeb, 0x00, 0xe5, 0x0a, 0xc0,
- 0x76, 0xe0, 0x04, 0xcb, 0xe0, 0x48, 0xe5, 0x41,
- 0xe0, 0x2f, 0xe1, 0x2b, 0xe0, 0x05, 0xe2, 0x2b,
- 0xc0, 0xab, 0xe5, 0x1c, 0x66, 0xe0, 0x00, 0xe9,
- 0x02, 0xe0, 0x80, 0x9e, 0xeb, 0x17, 0x00, 0xe5,
- 0x22, 0x00, 0x26, 0x11, 0x20, 0x25, 0xe0, 0x43,
- 0x46, 0xe5, 0x15, 0xeb, 0x02, 0x05, 0xe0, 0x00,
- 0xe5, 0x0e, 0xe6, 0x03, 0x6b, 0x96, 0xe0, 0x0e,
- 0xe5, 0x0a, 0x66, 0x76, 0xe0, 0x1e, 0xe5, 0x0d,
- 0xcb, 0xe0, 0x0c, 0xe5, 0x0f, 0xe0, 0x01, 0x07,
- 0x06, 0x07, 0xe5, 0x2d, 0xe6, 0x07, 0xd6, 0x60,
- 0xeb, 0x0c, 0xe9, 0x02, 0x06, 0x25, 0x26, 0x05,
- 0xe0, 0x01, 0x46, 0x07, 0xe5, 0x25, 0x47, 0x66,
- 0x27, 0x26, 0x36, 0x1b, 0x76, 0x06, 0xe0, 0x02,
- 0x1b, 0x20, 0xe5, 0x11, 0xc0, 0xe9, 0x02, 0xa0,
- 0x46, 0xe5, 0x1c, 0x86, 0x07, 0xe6, 0x00, 0x00,
- 0xe9, 0x02, 0x76, 0x05, 0x27, 0x05, 0xe0, 0x00,
- 0xe5, 0x1b, 0x06, 0x36, 0x05, 0xe0, 0x01, 0x26,
- 0x07, 0xe5, 0x28, 0x47, 0xe6, 0x01, 0x27, 0x65,
- 0x76, 0x66, 0x16, 0x07, 0x06, 0xe9, 0x02, 0x05,
- 0x16, 0x05, 0x56, 0x00, 0xeb, 0x0c, 0xe0, 0x03,
- 0xe5, 0x0a, 0x00, 0xe5, 0x11, 0x47, 0x46, 0x27,
- 0x06, 0x07, 0x26, 0xb6, 0x06, 0x25, 0x06, 0xe0,
- 0x36, 0xc5, 0x00, 0x05, 0x00, 0x65, 0x00, 0xe5,
- 0x07, 0x00, 0xe5, 0x02, 0x16, 0xa0, 0xe5, 0x27,
- 0x06, 0x47, 0xe6, 0x00, 0x80, 0xe9, 0x02, 0xa0,
- 0x26, 0x27, 0x00, 0xe5, 0x00, 0x20, 0x25, 0x20,
- 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, 0x85,
- 0x00, 0x26, 0x05, 0x27, 0x06, 0x67, 0x20, 0x27,
- 0x20, 0x47, 0x20, 0x05, 0xa0, 0x07, 0x80, 0x85,
- 0x27, 0x20, 0xc6, 0x40, 0x86, 0xe0, 0x80, 0x03,
- 0xe5, 0x2d, 0x47, 0xe6, 0x00, 0x27, 0x46, 0x07,
- 0x06, 0x65, 0x96, 0xe9, 0x02, 0x36, 0x00, 0x16,
- 0x06, 0x45, 0xe0, 0x16, 0xe5, 0x28, 0x47, 0xa6,
- 0x07, 0x06, 0x67, 0x26, 0x07, 0x26, 0x25, 0x16,
- 0x05, 0xe0, 0x00, 0xe9, 0x02, 0xe0, 0x80, 0x1e,
- 0xe5, 0x27, 0x47, 0x66, 0x20, 0x67, 0x26, 0x07,
- 0x26, 0xf6, 0x0f, 0x65, 0x26, 0xe0, 0x1a, 0xe5,
- 0x28, 0x47, 0xe6, 0x00, 0x27, 0x06, 0x07, 0x26,
- 0x56, 0x05, 0xe0, 0x03, 0xe9, 0x02, 0xa0, 0xf6,
- 0x05, 0xe0, 0x0b, 0xe5, 0x23, 0x06, 0x07, 0x06,
- 0x27, 0xa6, 0x07, 0x06, 0x05, 0x16, 0xa0, 0xe9,
- 0x02, 0xe0, 0x2e, 0xe5, 0x13, 0x20, 0x46, 0x27,
+ 0x13, 0x12, 0x13, 0x36, 0x12, 0x13, 0x76, 0x50,
+ 0x56, 0x00, 0x76, 0x11, 0x12, 0x13, 0x12, 0x13,
+ 0x12, 0x13, 0x56, 0x0c, 0x11, 0x4c, 0x00, 0x16,
+ 0x0d, 0x36, 0x60, 0x85, 0x00, 0xe5, 0x7f, 0x20,
+ 0x1b, 0x00, 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16,
+ 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c,
+ 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e, 0x10,
+ 0x0e, 0xe2, 0x12, 0x12, 0x0c, 0x13, 0x0c, 0x12,
+ 0x13, 0x16, 0x12, 0x13, 0x36, 0xe5, 0x02, 0x04,
+ 0xe5, 0x25, 0x24, 0xe5, 0x17, 0x40, 0xa5, 0x20,
+ 0xa5, 0x20, 0xa5, 0x20, 0x45, 0x40, 0x2d, 0x0c,
+ 0x0e, 0x0f, 0x2d, 0x00, 0x0f, 0x6c, 0x2f, 0xe0,
+ 0x02, 0x5b, 0x2f, 0x20, 0xe5, 0x04, 0x00, 0xe5,
+ 0x12, 0x00, 0xe5, 0x0b, 0x00, 0x25, 0x00, 0xe5,
+ 0x07, 0x20, 0xe5, 0x06, 0xe0, 0x1a, 0xe5, 0x73,
+ 0x80, 0x56, 0x60, 0xeb, 0x25, 0x40, 0xef, 0x01,
+ 0xea, 0x2d, 0x6b, 0xef, 0x09, 0x2b, 0x4f, 0x00,
+ 0xef, 0x05, 0x40, 0x0f, 0xe0, 0x27, 0xef, 0x25,
+ 0x06, 0xe0, 0x7a, 0xe5, 0x15, 0x40, 0xe5, 0x29,
+ 0xe0, 0x07, 0x06, 0xeb, 0x13, 0x60, 0xe5, 0x18,
+ 0x6b, 0xe0, 0x01, 0xe5, 0x0c, 0x0a, 0xe5, 0x00,
+ 0x0a, 0x80, 0xe5, 0x1e, 0x86, 0x80, 0xe5, 0x16,
+ 0x00, 0x16, 0xe5, 0x1c, 0x60, 0xe5, 0x00, 0x16,
+ 0x8a, 0xe0, 0x22, 0xe1, 0x20, 0xe2, 0x20, 0xe5,
+ 0x46, 0x20, 0xe9, 0x02, 0xa0, 0xe1, 0x1c, 0x60,
+ 0xe2, 0x1c, 0x60, 0xe5, 0x20, 0xe0, 0x00, 0xe5,
+ 0x2c, 0xe0, 0x03, 0x16, 0xe1, 0x03, 0x00, 0xe1,
+ 0x07, 0x00, 0xc1, 0x00, 0x21, 0x00, 0xe2, 0x03,
+ 0x00, 0xe2, 0x07, 0x00, 0xc2, 0x00, 0x22, 0x40,
+ 0xe5, 0x2c, 0xe0, 0x04, 0xe5, 0x80, 0xaf, 0xe0,
+ 0x01, 0xe5, 0x0e, 0xe0, 0x02, 0xe5, 0x00, 0xe0,
+ 0x10, 0xa4, 0x00, 0xe4, 0x22, 0x00, 0xe4, 0x01,
+ 0xe0, 0x3d, 0xa5, 0x20, 0x05, 0x00, 0xe5, 0x24,
+ 0x00, 0x25, 0x40, 0x05, 0x20, 0xe5, 0x0f, 0x00,
+ 0x16, 0xeb, 0x00, 0xe5, 0x0f, 0x2f, 0xcb, 0xe5,
+ 0x17, 0xe0, 0x00, 0xeb, 0x01, 0xe0, 0x28, 0xe5,
+ 0x0b, 0x00, 0x25, 0x80, 0x8b, 0xe5, 0x0e, 0xab,
+ 0x40, 0x16, 0xe5, 0x12, 0x80, 0x16, 0xe0, 0x38,
+ 0xe5, 0x30, 0x60, 0x2b, 0x25, 0xeb, 0x08, 0x20,
+ 0xeb, 0x26, 0x05, 0x46, 0x00, 0x26, 0x80, 0x66,
+ 0x65, 0x00, 0x45, 0x00, 0xe5, 0x15, 0x20, 0x46,
+ 0x60, 0x06, 0xeb, 0x01, 0xc0, 0xf6, 0x01, 0xc0,
+ 0xe5, 0x15, 0x2b, 0x16, 0xe5, 0x15, 0x4b, 0xe0,
+ 0x18, 0xe5, 0x00, 0x0f, 0xe5, 0x14, 0x26, 0x60,
+ 0x8b, 0xd6, 0xe0, 0x01, 0xe5, 0x2e, 0x40, 0xd6,
+ 0xe5, 0x0e, 0x20, 0xeb, 0x00, 0xe5, 0x0b, 0x80,
+ 0xeb, 0x00, 0xe5, 0x0a, 0xc0, 0x76, 0xe0, 0x04,
+ 0xcb, 0xe0, 0x48, 0xe5, 0x41, 0xe0, 0x2f, 0xe1,
+ 0x2b, 0xe0, 0x05, 0xe2, 0x2b, 0xc0, 0xab, 0xe5,
+ 0x1c, 0x66, 0xe0, 0x00, 0xe9, 0x02, 0xa0, 0xe9,
+ 0x02, 0x65, 0x04, 0x05, 0xe1, 0x0e, 0x40, 0x86,
+ 0x11, 0x04, 0xe2, 0x0e, 0xe0, 0x00, 0x2c, 0xe0,
+ 0x80, 0x48, 0xeb, 0x17, 0x00, 0xe5, 0x22, 0x00,
+ 0x26, 0x11, 0x20, 0x25, 0xe0, 0x08, 0x45, 0xe0,
+ 0x2f, 0x66, 0xe5, 0x15, 0xeb, 0x02, 0x05, 0xe0,
+ 0x00, 0xe5, 0x0e, 0xe6, 0x03, 0x6b, 0x96, 0xe0,
+ 0x0e, 0xe5, 0x0a, 0x66, 0x76, 0xe0, 0x1e, 0xe5,
+ 0x0d, 0xcb, 0xe0, 0x0c, 0xe5, 0x0f, 0xe0, 0x01,
+ 0x07, 0x06, 0x07, 0xe5, 0x2d, 0xe6, 0x07, 0xd6,
+ 0x60, 0xeb, 0x0c, 0xe9, 0x02, 0x06, 0x25, 0x26,
+ 0x05, 0xe0, 0x01, 0x46, 0x07, 0xe5, 0x25, 0x47,
+ 0x66, 0x27, 0x26, 0x36, 0x1b, 0x76, 0x06, 0xe0,
+ 0x02, 0x1b, 0x20, 0xe5, 0x11, 0xc0, 0xe9, 0x02,
+ 0xa0, 0x46, 0xe5, 0x1c, 0x86, 0x07, 0xe6, 0x00,
+ 0x00, 0xe9, 0x02, 0x76, 0x05, 0x27, 0x05, 0xe0,
+ 0x00, 0xe5, 0x1b, 0x06, 0x36, 0x05, 0xe0, 0x01,
+ 0x26, 0x07, 0xe5, 0x28, 0x47, 0xe6, 0x01, 0x27,
+ 0x65, 0x76, 0x66, 0x16, 0x07, 0x06, 0xe9, 0x02,
+ 0x05, 0x16, 0x05, 0x56, 0x00, 0xeb, 0x0c, 0xe0,
+ 0x03, 0xe5, 0x0a, 0x00, 0xe5, 0x11, 0x47, 0x46,
+ 0x27, 0x06, 0x07, 0x26, 0xb6, 0x06, 0x25, 0x06,
+ 0xe0, 0x36, 0xc5, 0x00, 0x05, 0x00, 0x65, 0x00,
+ 0xe5, 0x07, 0x00, 0xe5, 0x02, 0x16, 0xa0, 0xe5,
+ 0x27, 0x06, 0x47, 0xe6, 0x00, 0x80, 0xe9, 0x02,
+ 0xa0, 0x26, 0x27, 0x00, 0xe5, 0x00, 0x20, 0x25,
+ 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00,
+ 0x85, 0x00, 0x26, 0x05, 0x27, 0x06, 0x67, 0x20,
+ 0x27, 0x20, 0x47, 0x20, 0x05, 0xa0, 0x07, 0x80,
+ 0x85, 0x27, 0x20, 0xc6, 0x40, 0x86, 0xe0, 0x03,
+ 0xe5, 0x02, 0x00, 0x05, 0x20, 0x05, 0x00, 0xe5,
+ 0x1e, 0x00, 0x05, 0x47, 0xa6, 0x00, 0x07, 0x20,
+ 0x07, 0x00, 0x67, 0x00, 0x27, 0x06, 0x07, 0x06,
+ 0x05, 0x06, 0x05, 0x36, 0x00, 0x36, 0xe0, 0x00,
+ 0x26, 0xe0, 0x15, 0xe5, 0x2d, 0x47, 0xe6, 0x00,
+ 0x27, 0x46, 0x07, 0x06, 0x65, 0x96, 0xe9, 0x02,
+ 0x36, 0x00, 0x16, 0x06, 0x45, 0xe0, 0x16, 0xe5,
+ 0x28, 0x47, 0xa6, 0x07, 0x06, 0x67, 0x26, 0x07,
+ 0x26, 0x25, 0x16, 0x05, 0xe0, 0x00, 0xe9, 0x02,
+ 0xe0, 0x80, 0x1e, 0xe5, 0x27, 0x47, 0x66, 0x20,
+ 0x67, 0x26, 0x07, 0x26, 0xf6, 0x0f, 0x65, 0x26,
+ 0xe0, 0x1a, 0xe5, 0x28, 0x47, 0xe6, 0x00, 0x27,
+ 0x06, 0x07, 0x26, 0x56, 0x05, 0xe0, 0x03, 0xe9,
+ 0x02, 0xa0, 0xf6, 0x05, 0xe0, 0x0b, 0xe5, 0x23,
+ 0x06, 0x07, 0x06, 0x27, 0xa6, 0x07, 0x06, 0x05,
+ 0x16, 0xa0, 0xe9, 0x02, 0xa0, 0xe9, 0x0c, 0xe0,
+ 0x14, 0xe5, 0x13, 0x20, 0x06, 0x07, 0x06, 0x27,
0x66, 0x07, 0x86, 0x60, 0xe9, 0x02, 0x2b, 0x56,
0x0f, 0xc5, 0xe0, 0x80, 0x31, 0xe5, 0x24, 0x47,
0xe6, 0x01, 0x07, 0x26, 0x16, 0xe0, 0x5c, 0xe1,
@@ -2787,7 +2769,8 @@ static const uint8_t unicode_gc_table[3948] = {
0x05, 0x66, 0xf6, 0x00, 0x06, 0xe0, 0x00, 0x05,
0xa6, 0x27, 0x46, 0xe5, 0x26, 0xe6, 0x05, 0x07,
0x26, 0x56, 0x05, 0x96, 0xe0, 0x05, 0xe5, 0x41,
- 0xc0, 0xf6, 0x02, 0xe0, 0x80, 0x6e, 0xe5, 0x01,
+ 0xc0, 0xf6, 0x02, 0xe0, 0x80, 0x2e, 0xe5, 0x19,
+ 0x16, 0xe0, 0x06, 0xe9, 0x02, 0xa0, 0xe5, 0x01,
0x00, 0xe5, 0x1d, 0x07, 0xc6, 0x00, 0xa6, 0x07,
0x06, 0x05, 0x96, 0xe0, 0x02, 0xe9, 0x02, 0xeb,
0x0b, 0x40, 0x36, 0xe5, 0x16, 0x20, 0xe6, 0x0e,
@@ -2800,106 +2783,112 @@ static const uint8_t unicode_gc_table[3948] = {
0x80, 0xae, 0xe5, 0x0b, 0x26, 0x27, 0x36, 0xc0,
0x26, 0x05, 0x07, 0xe5, 0x05, 0x00, 0xe5, 0x1a,
0x27, 0x86, 0x40, 0x27, 0x06, 0x07, 0x06, 0xf6,
- 0x05, 0xe9, 0x02, 0xe0, 0x4e, 0x05, 0xe0, 0x07,
- 0xeb, 0x0d, 0xef, 0x00, 0x6d, 0xef, 0x09, 0xe0,
- 0x05, 0x16, 0xe5, 0x83, 0x12, 0xe0, 0x5e, 0xea,
- 0x67, 0x00, 0x96, 0xe0, 0x03, 0xe5, 0x80, 0x3c,
- 0xe0, 0x89, 0xc4, 0xe5, 0x59, 0x36, 0xe0, 0x05,
- 0xe5, 0x83, 0xa8, 0xfb, 0x08, 0x06, 0xa5, 0xe6,
- 0x07, 0xe0, 0x8f, 0x22, 0xe5, 0x81, 0xbf, 0xe0,
- 0xa1, 0x31, 0xe5, 0x81, 0xb1, 0xc0, 0xe5, 0x17,
- 0x00, 0xe9, 0x02, 0x60, 0x36, 0xe5, 0x47, 0x00,
- 0xe9, 0x02, 0xa0, 0xe5, 0x16, 0x20, 0x86, 0x16,
- 0xe0, 0x02, 0xe5, 0x28, 0xc6, 0x96, 0x6f, 0x64,
- 0x16, 0x0f, 0xe0, 0x02, 0xe9, 0x02, 0x00, 0xcb,
- 0x00, 0xe5, 0x0d, 0x80, 0xe5, 0x0b, 0xe0, 0x82,
- 0x28, 0xe1, 0x18, 0xe2, 0x18, 0xeb, 0x0f, 0x76,
- 0xe0, 0x5d, 0xe5, 0x43, 0x60, 0x06, 0x05, 0xe7,
- 0x2f, 0xc0, 0x66, 0xe4, 0x05, 0xe0, 0x38, 0x24,
- 0x16, 0x04, 0x06, 0xe0, 0x03, 0x27, 0xe0, 0x06,
- 0xe5, 0x97, 0x70, 0xe0, 0x00, 0xe5, 0x84, 0x4e,
- 0xe0, 0x22, 0xe5, 0x01, 0xe0, 0xa2, 0x5f, 0x64,
- 0x00, 0xc4, 0x00, 0x24, 0x00, 0xe5, 0x80, 0x9b,
- 0xe0, 0x07, 0x05, 0xe0, 0x15, 0x45, 0x20, 0x05,
- 0xe0, 0x06, 0x65, 0xe0, 0x00, 0xe5, 0x81, 0x04,
- 0xe0, 0x88, 0x7c, 0xe5, 0x63, 0x80, 0xe5, 0x05,
- 0x40, 0xe5, 0x01, 0xc0, 0xe5, 0x02, 0x20, 0x0f,
- 0x26, 0x16, 0x7b, 0xe0, 0x91, 0xd4, 0xe6, 0x26,
- 0x20, 0xe6, 0x0f, 0xe0, 0x01, 0xef, 0x6c, 0xe0,
- 0x34, 0xef, 0x80, 0x6e, 0xe0, 0x02, 0xef, 0x1f,
- 0x20, 0xef, 0x34, 0x27, 0x46, 0x4f, 0xa7, 0xfb,
- 0x00, 0xe6, 0x00, 0x2f, 0xc6, 0xef, 0x16, 0x66,
- 0xef, 0x35, 0xe0, 0x0d, 0xef, 0x3a, 0x46, 0x0f,
- 0xe0, 0x72, 0xeb, 0x0c, 0xe0, 0x04, 0xeb, 0x0c,
- 0xe0, 0x04, 0xef, 0x4f, 0xe0, 0x01, 0xeb, 0x11,
- 0xe0, 0x7f, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12,
- 0xc2, 0x00, 0xe2, 0x0a, 0xe1, 0x12, 0xe2, 0x12,
- 0x01, 0x00, 0x21, 0x20, 0x01, 0x20, 0x21, 0x20,
- 0x61, 0x00, 0xe1, 0x00, 0x62, 0x00, 0x02, 0x00,
- 0xc2, 0x00, 0xe2, 0x03, 0xe1, 0x12, 0xe2, 0x12,
- 0x21, 0x00, 0x61, 0x20, 0xe1, 0x00, 0x00, 0xc1,
- 0x00, 0xe2, 0x12, 0x21, 0x00, 0x61, 0x00, 0x81,
- 0x00, 0x01, 0x40, 0xc1, 0x00, 0xe2, 0x12, 0xe1,
+ 0x05, 0xe9, 0x02, 0x06, 0xe0, 0x4d, 0x05, 0xe0,
+ 0x07, 0xeb, 0x0d, 0xef, 0x00, 0x6d, 0xef, 0x09,
+ 0xe0, 0x05, 0x16, 0xe5, 0x83, 0x12, 0xe0, 0x5e,
+ 0xea, 0x67, 0x00, 0x96, 0xe0, 0x03, 0xe5, 0x80,
+ 0x3c, 0xe0, 0x89, 0xc4, 0xe5, 0x59, 0x36, 0xe0,
+ 0x05, 0xe5, 0x83, 0xa8, 0xfb, 0x08, 0x06, 0xa5,
+ 0xe6, 0x07, 0xe0, 0x02, 0xe5, 0x8f, 0x13, 0x80,
+ 0xe5, 0x81, 0xbf, 0xe0, 0x9a, 0x31, 0xe5, 0x16,
+ 0xe6, 0x04, 0x47, 0x46, 0xe9, 0x02, 0xe0, 0x86,
+ 0x3e, 0xe5, 0x81, 0xb1, 0xc0, 0xe5, 0x17, 0x00,
+ 0xe9, 0x02, 0x60, 0x36, 0xe5, 0x47, 0x00, 0xe9,
+ 0x02, 0xa0, 0xe5, 0x16, 0x20, 0x86, 0x16, 0xe0,
+ 0x02, 0xe5, 0x28, 0xc6, 0x96, 0x6f, 0x64, 0x16,
+ 0x0f, 0xe0, 0x02, 0xe9, 0x02, 0x00, 0xcb, 0x00,
+ 0xe5, 0x0d, 0x80, 0xe5, 0x0b, 0xe0, 0x81, 0x28,
+ 0x44, 0xe5, 0x20, 0x24, 0x56, 0xe9, 0x02, 0xe0,
+ 0x80, 0x3e, 0xe1, 0x18, 0xe2, 0x18, 0xeb, 0x0f,
+ 0x76, 0xe0, 0x5d, 0xe5, 0x43, 0x60, 0x06, 0x05,
+ 0xe7, 0x2f, 0xc0, 0x66, 0xe4, 0x05, 0xe0, 0x38,
+ 0x24, 0x16, 0x04, 0x06, 0xe0, 0x03, 0x27, 0xe0,
+ 0x06, 0xe5, 0x97, 0x70, 0xe0, 0x00, 0xe5, 0x84,
+ 0x4e, 0xe0, 0x21, 0xe5, 0x02, 0xe0, 0xa2, 0x5f,
+ 0x64, 0x00, 0xc4, 0x00, 0x24, 0x00, 0xe5, 0x80,
+ 0x9b, 0xe0, 0x07, 0x05, 0xe0, 0x15, 0x45, 0x20,
+ 0x05, 0xe0, 0x06, 0x65, 0xe0, 0x00, 0xe5, 0x81,
+ 0x04, 0xe0, 0x88, 0x7c, 0xe5, 0x63, 0x80, 0xe5,
+ 0x05, 0x40, 0xe5, 0x01, 0xc0, 0xe5, 0x02, 0x20,
+ 0x0f, 0x26, 0x16, 0x7b, 0xe0, 0x8e, 0xd4, 0xef,
+ 0x80, 0x68, 0xe9, 0x02, 0xa0, 0xef, 0x81, 0x2c,
+ 0xe0, 0x44, 0xe6, 0x26, 0x20, 0xe6, 0x0f, 0xe0,
+ 0x01, 0xef, 0x6c, 0xe0, 0x34, 0xef, 0x80, 0x6e,
+ 0xe0, 0x02, 0xef, 0x1f, 0x20, 0xef, 0x34, 0x27,
+ 0x46, 0x4f, 0xa7, 0xfb, 0x00, 0xe6, 0x00, 0x2f,
+ 0xc6, 0xef, 0x16, 0x66, 0xef, 0x35, 0xe0, 0x0d,
+ 0xef, 0x3a, 0x46, 0x0f, 0xe0, 0x72, 0xeb, 0x0c,
+ 0xe0, 0x04, 0xeb, 0x0c, 0xe0, 0x04, 0xef, 0x4f,
+ 0xe0, 0x01, 0xeb, 0x11, 0xe0, 0x7f, 0xe1, 0x12,
+ 0xe2, 0x12, 0xe1, 0x12, 0xc2, 0x00, 0xe2, 0x0a,
+ 0xe1, 0x12, 0xe2, 0x12, 0x01, 0x00, 0x21, 0x20,
+ 0x01, 0x20, 0x21, 0x20, 0x61, 0x00, 0xe1, 0x00,
+ 0x62, 0x00, 0x02, 0x00, 0xc2, 0x00, 0xe2, 0x03,
+ 0xe1, 0x12, 0xe2, 0x12, 0x21, 0x00, 0x61, 0x20,
+ 0xe1, 0x00, 0x00, 0xc1, 0x00, 0xe2, 0x12, 0x21,
+ 0x00, 0x61, 0x00, 0x81, 0x00, 0x01, 0x40, 0xc1,
+ 0x00, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1,
0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1,
0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1,
- 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x14, 0x20,
- 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1,
- 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11,
- 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c,
- 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2,
- 0x11, 0x0c, 0xa2, 0x3f, 0x20, 0xe9, 0x2a, 0xef,
- 0x81, 0x78, 0xe6, 0x2f, 0x6f, 0xe6, 0x2a, 0xef,
- 0x00, 0x06, 0xef, 0x06, 0x06, 0x2f, 0x96, 0xe0,
- 0x07, 0x86, 0x00, 0xe6, 0x07, 0xe0, 0x83, 0xc8,
- 0xe2, 0x02, 0x05, 0xe2, 0x0c, 0xa0, 0xa2, 0xe0,
- 0x80, 0x4d, 0xc6, 0x00, 0xe6, 0x09, 0x20, 0xc6,
- 0x00, 0x26, 0x00, 0x86, 0x80, 0xe4, 0x36, 0xe0,
- 0x19, 0x06, 0xe0, 0x68, 0xe5, 0x25, 0x40, 0xc6,
- 0xc4, 0x20, 0xe9, 0x02, 0x60, 0x05, 0x0f, 0xe0,
- 0x80, 0xb8, 0xe5, 0x16, 0x06, 0xe0, 0x09, 0xe5,
- 0x24, 0x66, 0xe9, 0x02, 0x80, 0x0d, 0xe0, 0x81,
- 0x48, 0xe5, 0x13, 0x04, 0x66, 0xe9, 0x02, 0xe0,
- 0x82, 0x5e, 0xc5, 0x00, 0x65, 0x00, 0x25, 0x00,
- 0xe5, 0x07, 0x00, 0xe5, 0x80, 0x3d, 0x20, 0xeb,
- 0x01, 0xc6, 0xe0, 0x21, 0xe1, 0x1a, 0xe2, 0x1a,
- 0xc6, 0x04, 0x60, 0xe9, 0x02, 0x60, 0x36, 0xe0,
- 0x82, 0x89, 0xeb, 0x33, 0x0f, 0x4b, 0x0d, 0x6b,
- 0xe0, 0x44, 0xeb, 0x25, 0x0f, 0xeb, 0x07, 0xe0,
- 0x80, 0x3a, 0x65, 0x00, 0xe5, 0x13, 0x00, 0x25,
- 0x00, 0x05, 0x20, 0x05, 0x00, 0xe5, 0x02, 0x00,
- 0x65, 0x00, 0x05, 0x00, 0x05, 0xa0, 0x05, 0x60,
- 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x45, 0x00,
- 0x25, 0x00, 0x05, 0x20, 0x05, 0x00, 0x05, 0x00,
- 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x25, 0x00,
- 0x05, 0x20, 0x65, 0x00, 0xc5, 0x00, 0x65, 0x00,
- 0x65, 0x00, 0x05, 0x00, 0xe5, 0x02, 0x00, 0xe5,
- 0x09, 0x80, 0x45, 0x00, 0x85, 0x00, 0xe5, 0x09,
- 0xe0, 0x2c, 0x2c, 0xe0, 0x80, 0x86, 0xef, 0x24,
- 0x60, 0xef, 0x5c, 0xe0, 0x04, 0xef, 0x07, 0x20,
- 0xef, 0x07, 0x00, 0xef, 0x07, 0x00, 0xef, 0x1d,
- 0xe0, 0x02, 0xeb, 0x05, 0xef, 0x80, 0x19, 0xe0,
- 0x30, 0xef, 0x15, 0xe0, 0x05, 0xef, 0x24, 0x60,
- 0xef, 0x01, 0xc0, 0x2f, 0xe0, 0x06, 0xaf, 0xe0,
- 0x80, 0x12, 0xef, 0x80, 0x73, 0x8e, 0xef, 0x82,
- 0x50, 0x60, 0xef, 0x09, 0x40, 0xef, 0x05, 0x40,
- 0xef, 0x6f, 0x60, 0xef, 0x57, 0xa0, 0xef, 0x04,
- 0x60, 0x0f, 0xe0, 0x07, 0xef, 0x04, 0x60, 0xef,
- 0x30, 0xe0, 0x00, 0xef, 0x02, 0xa0, 0xef, 0x20,
- 0xe0, 0x00, 0xef, 0x16, 0x20, 0x2f, 0xe0, 0x46,
- 0xef, 0x80, 0xcc, 0xe0, 0x04, 0xef, 0x06, 0x20,
- 0xef, 0x05, 0x40, 0xef, 0x01, 0xc0, 0xef, 0x26,
- 0x00, 0xcf, 0xe0, 0x00, 0xef, 0x06, 0x60, 0xef,
- 0x01, 0xc0, 0xef, 0x01, 0xc0, 0xef, 0x80, 0x0b,
- 0x00, 0xef, 0x2f, 0xe0, 0x1d, 0xe9, 0x02, 0xe0,
- 0x83, 0x7e, 0xe5, 0xc0, 0x66, 0x58, 0xe0, 0x18,
- 0xe5, 0x8f, 0xb2, 0xa0, 0xe5, 0x80, 0x56, 0x20,
- 0xe5, 0x95, 0xfa, 0xe0, 0x06, 0xe5, 0x9c, 0xa9,
- 0xe0, 0x8b, 0x97, 0xe5, 0x81, 0x96, 0xe0, 0x85,
- 0x5a, 0xe5, 0x92, 0xc3, 0x80, 0xe5, 0x8f, 0xd8,
- 0xe0, 0xca, 0x9b, 0xc9, 0x1b, 0xe0, 0x16, 0xfb,
- 0x58, 0xe0, 0x78, 0xe6, 0x80, 0x68, 0xe0, 0xc0,
- 0xbd, 0x88, 0xfd, 0xc0, 0xbf, 0x76, 0x20, 0xfd,
- 0xc0, 0xbf, 0x76, 0x20,
+ 0x12, 0xe2, 0x14, 0x20, 0xe1, 0x11, 0x0c, 0xe2,
+ 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11,
+ 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c,
+ 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2,
+ 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0x3f,
+ 0x20, 0xe9, 0x2a, 0xef, 0x81, 0x78, 0xe6, 0x2f,
+ 0x6f, 0xe6, 0x2a, 0xef, 0x00, 0x06, 0xef, 0x06,
+ 0x06, 0x2f, 0x96, 0xe0, 0x07, 0x86, 0x00, 0xe6,
+ 0x07, 0xe0, 0x83, 0xc8, 0xe2, 0x02, 0x05, 0xe2,
+ 0x0c, 0xa0, 0xa2, 0xe0, 0x80, 0x4d, 0xc6, 0x00,
+ 0xe6, 0x09, 0x20, 0xc6, 0x00, 0x26, 0x00, 0x86,
+ 0x80, 0xe4, 0x36, 0xe0, 0x19, 0x06, 0xe0, 0x68,
+ 0xe5, 0x25, 0x40, 0xc6, 0xc4, 0x20, 0xe9, 0x02,
+ 0x60, 0x05, 0x0f, 0xe0, 0x80, 0xb8, 0xe5, 0x16,
+ 0x06, 0xe0, 0x09, 0xe5, 0x24, 0x66, 0xe9, 0x02,
+ 0x80, 0x0d, 0xe0, 0x81, 0x48, 0xe5, 0x13, 0x04,
+ 0x66, 0xe9, 0x02, 0xe0, 0x80, 0x4e, 0xe5, 0x16,
+ 0x26, 0x05, 0xe9, 0x02, 0x60, 0x16, 0xe0, 0x81,
+ 0x58, 0xc5, 0x00, 0x65, 0x00, 0x25, 0x00, 0xe5,
+ 0x07, 0x00, 0xe5, 0x80, 0x3d, 0x20, 0xeb, 0x01,
+ 0xc6, 0xe0, 0x21, 0xe1, 0x1a, 0xe2, 0x1a, 0xc6,
+ 0x04, 0x60, 0xe9, 0x02, 0x60, 0x36, 0xe0, 0x82,
+ 0x89, 0xeb, 0x33, 0x0f, 0x4b, 0x0d, 0x6b, 0xe0,
+ 0x44, 0xeb, 0x25, 0x0f, 0xeb, 0x07, 0xe0, 0x80,
+ 0x3a, 0x65, 0x00, 0xe5, 0x13, 0x00, 0x25, 0x00,
+ 0x05, 0x20, 0x05, 0x00, 0xe5, 0x02, 0x00, 0x65,
+ 0x00, 0x05, 0x00, 0x05, 0xa0, 0x05, 0x60, 0x05,
+ 0x00, 0x05, 0x00, 0x05, 0x00, 0x45, 0x00, 0x25,
+ 0x00, 0x05, 0x20, 0x05, 0x00, 0x05, 0x00, 0x05,
+ 0x00, 0x05, 0x00, 0x05, 0x00, 0x25, 0x00, 0x05,
+ 0x20, 0x65, 0x00, 0xc5, 0x00, 0x65, 0x00, 0x65,
+ 0x00, 0x05, 0x00, 0xe5, 0x02, 0x00, 0xe5, 0x09,
+ 0x80, 0x45, 0x00, 0x85, 0x00, 0xe5, 0x09, 0xe0,
+ 0x2c, 0x2c, 0xe0, 0x80, 0x86, 0xef, 0x24, 0x60,
+ 0xef, 0x5c, 0xe0, 0x04, 0xef, 0x07, 0x20, 0xef,
+ 0x07, 0x00, 0xef, 0x07, 0x00, 0xef, 0x1d, 0xe0,
+ 0x02, 0xeb, 0x05, 0xef, 0x80, 0x19, 0xe0, 0x30,
+ 0xef, 0x15, 0xe0, 0x05, 0xef, 0x24, 0x60, 0xef,
+ 0x01, 0xc0, 0x2f, 0xe0, 0x06, 0xaf, 0xe0, 0x80,
+ 0x12, 0xef, 0x80, 0x73, 0x8e, 0xef, 0x82, 0x50,
+ 0x60, 0xef, 0x09, 0x40, 0xef, 0x05, 0x40, 0xef,
+ 0x6f, 0x60, 0xef, 0x57, 0xa0, 0xef, 0x04, 0x60,
+ 0x0f, 0xe0, 0x07, 0xef, 0x04, 0x60, 0xef, 0x30,
+ 0xe0, 0x00, 0xef, 0x02, 0xa0, 0xef, 0x20, 0xe0,
+ 0x00, 0xef, 0x16, 0x20, 0xef, 0x04, 0x60, 0x2f,
+ 0xe0, 0x36, 0xef, 0x80, 0xcc, 0xe0, 0x04, 0xef,
+ 0x06, 0x20, 0xef, 0x05, 0x40, 0xef, 0x02, 0x80,
+ 0xef, 0x30, 0xc0, 0xef, 0x07, 0x20, 0xef, 0x03,
+ 0xa0, 0xef, 0x01, 0xc0, 0xef, 0x80, 0x0b, 0x00,
+ 0xef, 0x54, 0xe9, 0x02, 0xe0, 0x83, 0x7e, 0xe5,
+ 0xc0, 0x66, 0x58, 0xe0, 0x18, 0xe5, 0x8f, 0xb2,
+ 0xa0, 0xe5, 0x80, 0x56, 0x20, 0xe5, 0x95, 0xfa,
+ 0xe0, 0x06, 0xe5, 0x9c, 0xa9, 0xe0, 0x07, 0xe5,
+ 0x81, 0xe6, 0xe0, 0x89, 0x1a, 0xe5, 0x81, 0x96,
+ 0xe0, 0x85, 0x5a, 0xe5, 0x92, 0xc3, 0x80, 0xe5,
+ 0x8f, 0xd8, 0xe0, 0xca, 0x9b, 0xc9, 0x1b, 0xe0,
+ 0x16, 0xfb, 0x58, 0xe0, 0x78, 0xe6, 0x80, 0x68,
+ 0xe0, 0xc0, 0xbd, 0x88, 0xfd, 0xc0, 0xbf, 0x76,
+ 0x20, 0xfd, 0xc0, 0xbf, 0x76, 0x20,
};
typedef enum {
@@ -2946,11 +2935,13 @@ typedef enum {
UNICODE_SCRIPT_Georgian,
UNICODE_SCRIPT_Glagolitic,
UNICODE_SCRIPT_Gothic,
+ UNICODE_SCRIPT_Garay,
UNICODE_SCRIPT_Grantha,
UNICODE_SCRIPT_Greek,
UNICODE_SCRIPT_Gujarati,
UNICODE_SCRIPT_Gunjala_Gondi,
UNICODE_SCRIPT_Gurmukhi,
+ UNICODE_SCRIPT_Gurung_Khema,
UNICODE_SCRIPT_Han,
UNICODE_SCRIPT_Hangul,
UNICODE_SCRIPT_Hanifi_Rohingya,
@@ -2973,6 +2964,7 @@ typedef enum {
UNICODE_SCRIPT_Khojki,
UNICODE_SCRIPT_Khitan_Small_Script,
UNICODE_SCRIPT_Khudawadi,
+ UNICODE_SCRIPT_Kirat_Rai,
UNICODE_SCRIPT_Lao,
UNICODE_SCRIPT_Latin,
UNICODE_SCRIPT_Lepcha,
@@ -3010,6 +3002,7 @@ typedef enum {
UNICODE_SCRIPT_Nyiakeng_Puachue_Hmong,
UNICODE_SCRIPT_Ogham,
UNICODE_SCRIPT_Ol_Chiki,
+ UNICODE_SCRIPT_Ol_Onal,
UNICODE_SCRIPT_Old_Hungarian,
UNICODE_SCRIPT_Old_Italic,
UNICODE_SCRIPT_Old_North_Arabian,
@@ -3041,6 +3034,7 @@ typedef enum {
UNICODE_SCRIPT_Sora_Sompeng,
UNICODE_SCRIPT_Soyombo,
UNICODE_SCRIPT_Sundanese,
+ UNICODE_SCRIPT_Sunuwar,
UNICODE_SCRIPT_Syloti_Nagri,
UNICODE_SCRIPT_Syriac,
UNICODE_SCRIPT_Tagalog,
@@ -3058,7 +3052,9 @@ typedef enum {
UNICODE_SCRIPT_Tifinagh,
UNICODE_SCRIPT_Tirhuta,
UNICODE_SCRIPT_Tangsa,
+ UNICODE_SCRIPT_Todhri,
UNICODE_SCRIPT_Toto,
+ UNICODE_SCRIPT_Tulu_Tigalari,
UNICODE_SCRIPT_Ugaritic,
UNICODE_SCRIPT_Vai,
UNICODE_SCRIPT_Vithkuqi,
@@ -3113,11 +3109,13 @@ static const char unicode_script_name_table[] =
"Georgian,Geor" "\0"
"Glagolitic,Glag" "\0"
"Gothic,Goth" "\0"
+ "Garay,Gara" "\0"
"Grantha,Gran" "\0"
"Greek,Grek" "\0"
"Gujarati,Gujr" "\0"
"Gunjala_Gondi,Gong" "\0"
"Gurmukhi,Guru" "\0"
+ "Gurung_Khema,Gukh" "\0"
"Han,Hani" "\0"
"Hangul,Hang" "\0"
"Hanifi_Rohingya,Rohg" "\0"
@@ -3140,6 +3138,7 @@ static const char unicode_script_name_table[] =
"Khojki,Khoj" "\0"
"Khitan_Small_Script,Kits" "\0"
"Khudawadi,Sind" "\0"
+ "Kirat_Rai,Krai" "\0"
"Lao,Laoo" "\0"
"Latin,Latn" "\0"
"Lepcha,Lepc" "\0"
@@ -3177,6 +3176,7 @@ static const char unicode_script_name_table[] =
"Nyiakeng_Puachue_Hmong,Hmnp" "\0"
"Ogham,Ogam" "\0"
"Ol_Chiki,Olck" "\0"
+ "Ol_Onal,Onao" "\0"
"Old_Hungarian,Hung" "\0"
"Old_Italic,Ital" "\0"
"Old_North_Arabian,Narb" "\0"
@@ -3208,6 +3208,7 @@ static const char unicode_script_name_table[] =
"Sora_Sompeng,Sora" "\0"
"Soyombo,Soyo" "\0"
"Sundanese,Sund" "\0"
+ "Sunuwar,Sunu" "\0"
"Syloti_Nagri,Sylo" "\0"
"Syriac,Syrc" "\0"
"Tagalog,Tglg" "\0"
@@ -3225,7 +3226,9 @@ static const char unicode_script_name_table[] =
"Tifinagh,Tfng" "\0"
"Tirhuta,Tirh" "\0"
"Tangsa,Tnsa" "\0"
+ "Todhri,Todr" "\0"
"Toto,Toto" "\0"
+ "Tulu_Tigalari,Tutg" "\0"
"Ugaritic,Ugar" "\0"
"Vai,Vaii" "\0"
"Vithkuqi,Vith" "\0"
@@ -3236,87 +3239,87 @@ static const char unicode_script_name_table[] =
"Zanabazar_Square,Zanb" "\0"
;
-static const uint8_t unicode_script_table[2720] = {
- 0xc0, 0x19, 0x99, 0x47, 0x85, 0x19, 0x99, 0x47,
- 0xae, 0x19, 0x80, 0x47, 0x8e, 0x19, 0x80, 0x47,
- 0x84, 0x19, 0x96, 0x47, 0x80, 0x19, 0x9e, 0x47,
- 0x80, 0x19, 0xe1, 0x60, 0x47, 0xa6, 0x19, 0x84,
- 0x47, 0x84, 0x19, 0x81, 0x0d, 0x93, 0x19, 0xe0,
- 0x0f, 0x38, 0x83, 0x2c, 0x80, 0x19, 0x82, 0x2c,
- 0x01, 0x83, 0x2c, 0x80, 0x19, 0x80, 0x2c, 0x03,
- 0x80, 0x2c, 0x80, 0x19, 0x80, 0x2c, 0x80, 0x19,
- 0x82, 0x2c, 0x00, 0x80, 0x2c, 0x00, 0x93, 0x2c,
- 0x00, 0xbe, 0x2c, 0x8d, 0x1a, 0x8f, 0x2c, 0xe0,
- 0x24, 0x1d, 0x81, 0x38, 0xe0, 0x48, 0x1d, 0x00,
+static const uint8_t unicode_script_table[2803] = {
+ 0xc0, 0x19, 0x99, 0x4a, 0x85, 0x19, 0x99, 0x4a,
+ 0xae, 0x19, 0x80, 0x4a, 0x8e, 0x19, 0x80, 0x4a,
+ 0x84, 0x19, 0x96, 0x4a, 0x80, 0x19, 0x9e, 0x4a,
+ 0x80, 0x19, 0xe1, 0x60, 0x4a, 0xa6, 0x19, 0x84,
+ 0x4a, 0x84, 0x19, 0x81, 0x0d, 0x93, 0x19, 0xe0,
+ 0x0f, 0x3a, 0x83, 0x2d, 0x80, 0x19, 0x82, 0x2d,
+ 0x01, 0x83, 0x2d, 0x80, 0x19, 0x80, 0x2d, 0x03,
+ 0x80, 0x2d, 0x80, 0x19, 0x80, 0x2d, 0x80, 0x19,
+ 0x82, 0x2d, 0x00, 0x80, 0x2d, 0x00, 0x93, 0x2d,
+ 0x00, 0xbe, 0x2d, 0x8d, 0x1a, 0x8f, 0x2d, 0xe0,
+ 0x24, 0x1d, 0x81, 0x3a, 0xe0, 0x48, 0x1d, 0x00,
0xa5, 0x05, 0x01, 0xb1, 0x05, 0x01, 0x82, 0x05,
- 0x00, 0xb6, 0x35, 0x07, 0x9a, 0x35, 0x03, 0x85,
- 0x35, 0x0a, 0x84, 0x04, 0x80, 0x19, 0x85, 0x04,
+ 0x00, 0xb6, 0x37, 0x07, 0x9a, 0x37, 0x03, 0x85,
+ 0x37, 0x0a, 0x84, 0x04, 0x80, 0x19, 0x85, 0x04,
0x80, 0x19, 0x8d, 0x04, 0x80, 0x19, 0x82, 0x04,
0x80, 0x19, 0x9f, 0x04, 0x80, 0x19, 0x89, 0x04,
- 0x8a, 0x38, 0x99, 0x04, 0x80, 0x38, 0xe0, 0x0b,
- 0x04, 0x80, 0x19, 0xa1, 0x04, 0x8d, 0x8b, 0x00,
- 0xbb, 0x8b, 0x01, 0x82, 0x8b, 0xaf, 0x04, 0xb1,
- 0x95, 0x0d, 0xba, 0x66, 0x01, 0x82, 0x66, 0xad,
- 0x7f, 0x01, 0x8e, 0x7f, 0x00, 0x9b, 0x52, 0x01,
- 0x80, 0x52, 0x00, 0x8a, 0x8b, 0x04, 0x9e, 0x04,
- 0x00, 0x81, 0x04, 0x05, 0xc9, 0x04, 0x80, 0x19,
- 0x9c, 0x04, 0xd0, 0x20, 0x83, 0x38, 0x8e, 0x20,
+ 0x8a, 0x3a, 0x99, 0x04, 0x80, 0x3a, 0xe0, 0x0b,
+ 0x04, 0x80, 0x19, 0xa1, 0x04, 0x8d, 0x90, 0x00,
+ 0xbb, 0x90, 0x01, 0x82, 0x90, 0xaf, 0x04, 0xb1,
+ 0x9a, 0x0d, 0xba, 0x69, 0x01, 0x82, 0x69, 0xad,
+ 0x83, 0x01, 0x8e, 0x83, 0x00, 0x9b, 0x55, 0x01,
+ 0x80, 0x55, 0x00, 0x8a, 0x90, 0x04, 0x9e, 0x04,
+ 0x00, 0x81, 0x04, 0x04, 0xca, 0x04, 0x80, 0x19,
+ 0x9c, 0x04, 0xd0, 0x20, 0x83, 0x3a, 0x8e, 0x20,
0x81, 0x19, 0x99, 0x20, 0x83, 0x0b, 0x00, 0x87,
0x0b, 0x01, 0x81, 0x0b, 0x01, 0x95, 0x0b, 0x00,
0x86, 0x0b, 0x00, 0x80, 0x0b, 0x02, 0x83, 0x0b,
0x01, 0x88, 0x0b, 0x01, 0x81, 0x0b, 0x01, 0x83,
0x0b, 0x07, 0x80, 0x0b, 0x03, 0x81, 0x0b, 0x00,
- 0x84, 0x0b, 0x01, 0x98, 0x0b, 0x01, 0x82, 0x2f,
- 0x00, 0x85, 0x2f, 0x03, 0x81, 0x2f, 0x01, 0x95,
- 0x2f, 0x00, 0x86, 0x2f, 0x00, 0x81, 0x2f, 0x00,
- 0x81, 0x2f, 0x00, 0x81, 0x2f, 0x01, 0x80, 0x2f,
- 0x00, 0x84, 0x2f, 0x03, 0x81, 0x2f, 0x01, 0x82,
- 0x2f, 0x02, 0x80, 0x2f, 0x06, 0x83, 0x2f, 0x00,
- 0x80, 0x2f, 0x06, 0x90, 0x2f, 0x09, 0x82, 0x2d,
- 0x00, 0x88, 0x2d, 0x00, 0x82, 0x2d, 0x00, 0x95,
- 0x2d, 0x00, 0x86, 0x2d, 0x00, 0x81, 0x2d, 0x00,
- 0x84, 0x2d, 0x01, 0x89, 0x2d, 0x00, 0x82, 0x2d,
- 0x00, 0x82, 0x2d, 0x01, 0x80, 0x2d, 0x0e, 0x83,
- 0x2d, 0x01, 0x8b, 0x2d, 0x06, 0x86, 0x2d, 0x00,
- 0x82, 0x74, 0x00, 0x87, 0x74, 0x01, 0x81, 0x74,
- 0x01, 0x95, 0x74, 0x00, 0x86, 0x74, 0x00, 0x81,
- 0x74, 0x00, 0x84, 0x74, 0x01, 0x88, 0x74, 0x01,
- 0x81, 0x74, 0x01, 0x82, 0x74, 0x06, 0x82, 0x74,
- 0x03, 0x81, 0x74, 0x00, 0x84, 0x74, 0x01, 0x91,
- 0x74, 0x09, 0x81, 0x92, 0x00, 0x85, 0x92, 0x02,
- 0x82, 0x92, 0x00, 0x83, 0x92, 0x02, 0x81, 0x92,
- 0x00, 0x80, 0x92, 0x00, 0x81, 0x92, 0x02, 0x81,
- 0x92, 0x02, 0x82, 0x92, 0x02, 0x8b, 0x92, 0x03,
- 0x84, 0x92, 0x02, 0x82, 0x92, 0x00, 0x83, 0x92,
- 0x01, 0x80, 0x92, 0x05, 0x80, 0x92, 0x0d, 0x94,
- 0x92, 0x04, 0x8c, 0x94, 0x00, 0x82, 0x94, 0x00,
- 0x96, 0x94, 0x00, 0x8f, 0x94, 0x01, 0x88, 0x94,
- 0x00, 0x82, 0x94, 0x00, 0x83, 0x94, 0x06, 0x81,
- 0x94, 0x00, 0x82, 0x94, 0x01, 0x80, 0x94, 0x01,
- 0x83, 0x94, 0x01, 0x89, 0x94, 0x06, 0x88, 0x94,
- 0x8c, 0x3d, 0x00, 0x82, 0x3d, 0x00, 0x96, 0x3d,
- 0x00, 0x89, 0x3d, 0x00, 0x84, 0x3d, 0x01, 0x88,
- 0x3d, 0x00, 0x82, 0x3d, 0x00, 0x83, 0x3d, 0x06,
- 0x81, 0x3d, 0x05, 0x81, 0x3d, 0x00, 0x83, 0x3d,
- 0x01, 0x89, 0x3d, 0x00, 0x82, 0x3d, 0x0b, 0x8c,
- 0x51, 0x00, 0x82, 0x51, 0x00, 0xb2, 0x51, 0x00,
- 0x82, 0x51, 0x00, 0x85, 0x51, 0x03, 0x8f, 0x51,
- 0x01, 0x99, 0x51, 0x00, 0x82, 0x85, 0x00, 0x91,
- 0x85, 0x02, 0x97, 0x85, 0x00, 0x88, 0x85, 0x00,
- 0x80, 0x85, 0x01, 0x86, 0x85, 0x02, 0x80, 0x85,
- 0x03, 0x85, 0x85, 0x00, 0x80, 0x85, 0x00, 0x87,
- 0x85, 0x05, 0x89, 0x85, 0x01, 0x82, 0x85, 0x0b,
- 0xb9, 0x96, 0x03, 0x80, 0x19, 0x9b, 0x96, 0x24,
- 0x81, 0x46, 0x00, 0x80, 0x46, 0x00, 0x84, 0x46,
- 0x00, 0x97, 0x46, 0x00, 0x80, 0x46, 0x00, 0x96,
- 0x46, 0x01, 0x84, 0x46, 0x00, 0x80, 0x46, 0x00,
- 0x86, 0x46, 0x00, 0x89, 0x46, 0x01, 0x83, 0x46,
- 0x1f, 0xc7, 0x97, 0x00, 0xa3, 0x97, 0x03, 0xa6,
- 0x97, 0x00, 0xa3, 0x97, 0x00, 0x8e, 0x97, 0x00,
- 0x86, 0x97, 0x83, 0x19, 0x81, 0x97, 0x24, 0xe0,
- 0x3f, 0x60, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04,
+ 0x84, 0x0b, 0x01, 0x98, 0x0b, 0x01, 0x82, 0x30,
+ 0x00, 0x85, 0x30, 0x03, 0x81, 0x30, 0x01, 0x95,
+ 0x30, 0x00, 0x86, 0x30, 0x00, 0x81, 0x30, 0x00,
+ 0x81, 0x30, 0x00, 0x81, 0x30, 0x01, 0x80, 0x30,
+ 0x00, 0x84, 0x30, 0x03, 0x81, 0x30, 0x01, 0x82,
+ 0x30, 0x02, 0x80, 0x30, 0x06, 0x83, 0x30, 0x00,
+ 0x80, 0x30, 0x06, 0x90, 0x30, 0x09, 0x82, 0x2e,
+ 0x00, 0x88, 0x2e, 0x00, 0x82, 0x2e, 0x00, 0x95,
+ 0x2e, 0x00, 0x86, 0x2e, 0x00, 0x81, 0x2e, 0x00,
+ 0x84, 0x2e, 0x01, 0x89, 0x2e, 0x00, 0x82, 0x2e,
+ 0x00, 0x82, 0x2e, 0x01, 0x80, 0x2e, 0x0e, 0x83,
+ 0x2e, 0x01, 0x8b, 0x2e, 0x06, 0x86, 0x2e, 0x00,
+ 0x82, 0x78, 0x00, 0x87, 0x78, 0x01, 0x81, 0x78,
+ 0x01, 0x95, 0x78, 0x00, 0x86, 0x78, 0x00, 0x81,
+ 0x78, 0x00, 0x84, 0x78, 0x01, 0x88, 0x78, 0x01,
+ 0x81, 0x78, 0x01, 0x82, 0x78, 0x06, 0x82, 0x78,
+ 0x03, 0x81, 0x78, 0x00, 0x84, 0x78, 0x01, 0x91,
+ 0x78, 0x09, 0x81, 0x97, 0x00, 0x85, 0x97, 0x02,
+ 0x82, 0x97, 0x00, 0x83, 0x97, 0x02, 0x81, 0x97,
+ 0x00, 0x80, 0x97, 0x00, 0x81, 0x97, 0x02, 0x81,
+ 0x97, 0x02, 0x82, 0x97, 0x02, 0x8b, 0x97, 0x03,
+ 0x84, 0x97, 0x02, 0x82, 0x97, 0x00, 0x83, 0x97,
+ 0x01, 0x80, 0x97, 0x05, 0x80, 0x97, 0x0d, 0x94,
+ 0x97, 0x04, 0x8c, 0x99, 0x00, 0x82, 0x99, 0x00,
+ 0x96, 0x99, 0x00, 0x8f, 0x99, 0x01, 0x88, 0x99,
+ 0x00, 0x82, 0x99, 0x00, 0x83, 0x99, 0x06, 0x81,
+ 0x99, 0x00, 0x82, 0x99, 0x01, 0x80, 0x99, 0x01,
+ 0x83, 0x99, 0x01, 0x89, 0x99, 0x06, 0x88, 0x99,
+ 0x8c, 0x3f, 0x00, 0x82, 0x3f, 0x00, 0x96, 0x3f,
+ 0x00, 0x89, 0x3f, 0x00, 0x84, 0x3f, 0x01, 0x88,
+ 0x3f, 0x00, 0x82, 0x3f, 0x00, 0x83, 0x3f, 0x06,
+ 0x81, 0x3f, 0x05, 0x81, 0x3f, 0x00, 0x83, 0x3f,
+ 0x01, 0x89, 0x3f, 0x00, 0x82, 0x3f, 0x0b, 0x8c,
+ 0x54, 0x00, 0x82, 0x54, 0x00, 0xb2, 0x54, 0x00,
+ 0x82, 0x54, 0x00, 0x85, 0x54, 0x03, 0x8f, 0x54,
+ 0x01, 0x99, 0x54, 0x00, 0x82, 0x89, 0x00, 0x91,
+ 0x89, 0x02, 0x97, 0x89, 0x00, 0x88, 0x89, 0x00,
+ 0x80, 0x89, 0x01, 0x86, 0x89, 0x02, 0x80, 0x89,
+ 0x03, 0x85, 0x89, 0x00, 0x80, 0x89, 0x00, 0x87,
+ 0x89, 0x05, 0x89, 0x89, 0x01, 0x82, 0x89, 0x0b,
+ 0xb9, 0x9b, 0x03, 0x80, 0x19, 0x9b, 0x9b, 0x24,
+ 0x81, 0x49, 0x00, 0x80, 0x49, 0x00, 0x84, 0x49,
+ 0x00, 0x97, 0x49, 0x00, 0x80, 0x49, 0x00, 0x96,
+ 0x49, 0x01, 0x84, 0x49, 0x00, 0x80, 0x49, 0x00,
+ 0x86, 0x49, 0x00, 0x89, 0x49, 0x01, 0x83, 0x49,
+ 0x1f, 0xc7, 0x9c, 0x00, 0xa3, 0x9c, 0x03, 0xa6,
+ 0x9c, 0x00, 0xa3, 0x9c, 0x00, 0x8e, 0x9c, 0x00,
+ 0x86, 0x9c, 0x83, 0x19, 0x81, 0x9c, 0x24, 0xe0,
+ 0x3f, 0x63, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04,
0x80, 0x28, 0x01, 0xaa, 0x28, 0x80, 0x19, 0x83,
- 0x28, 0xe0, 0x9f, 0x31, 0xc8, 0x27, 0x00, 0x83,
+ 0x28, 0xe0, 0x9f, 0x33, 0xc8, 0x27, 0x00, 0x83,
0x27, 0x01, 0x86, 0x27, 0x00, 0x80, 0x27, 0x00,
0x83, 0x27, 0x01, 0xa8, 0x27, 0x00, 0x83, 0x27,
0x01, 0xa0, 0x27, 0x00, 0x83, 0x27, 0x01, 0x86,
@@ -3324,366 +3327,430 @@ static const uint8_t unicode_script_table[2720] = {
0x8e, 0x27, 0x00, 0xb8, 0x27, 0x00, 0x83, 0x27,
0x01, 0xc2, 0x27, 0x01, 0x9f, 0x27, 0x02, 0x99,
0x27, 0x05, 0xd5, 0x17, 0x01, 0x85, 0x17, 0x01,
- 0xe2, 0x1f, 0x12, 0x9c, 0x69, 0x02, 0xca, 0x7e,
- 0x82, 0x19, 0x8a, 0x7e, 0x06, 0x95, 0x8c, 0x08,
- 0x80, 0x8c, 0x94, 0x33, 0x81, 0x19, 0x08, 0x93,
- 0x11, 0x0b, 0x8c, 0x8d, 0x00, 0x82, 0x8d, 0x00,
- 0x81, 0x8d, 0x0b, 0xdd, 0x42, 0x01, 0x89, 0x42,
- 0x05, 0x89, 0x42, 0x05, 0x81, 0x5d, 0x81, 0x19,
- 0x80, 0x5d, 0x80, 0x19, 0x93, 0x5d, 0x05, 0xd8,
- 0x5d, 0x06, 0xaa, 0x5d, 0x04, 0xc5, 0x12, 0x09,
- 0x9e, 0x49, 0x00, 0x8b, 0x49, 0x03, 0x8b, 0x49,
- 0x03, 0x80, 0x49, 0x02, 0x8b, 0x49, 0x9d, 0x8e,
- 0x01, 0x84, 0x8e, 0x0a, 0xab, 0x64, 0x03, 0x99,
- 0x64, 0x05, 0x8a, 0x64, 0x02, 0x81, 0x64, 0x9f,
- 0x42, 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x8f,
- 0x00, 0x9c, 0x8f, 0x01, 0x8a, 0x8f, 0x05, 0x89,
- 0x8f, 0x05, 0x8d, 0x8f, 0x01, 0x9e, 0x38, 0x30,
- 0xcc, 0x07, 0x02, 0xae, 0x07, 0x00, 0xbf, 0x89,
- 0xb3, 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x48, 0x02,
- 0x8e, 0x48, 0x02, 0x82, 0x48, 0xaf, 0x6a, 0x88,
- 0x1d, 0x06, 0xaa, 0x28, 0x01, 0x82, 0x28, 0x87,
- 0x89, 0x07, 0x82, 0x38, 0x80, 0x19, 0x8c, 0x38,
- 0x80, 0x19, 0x86, 0x38, 0x83, 0x19, 0x80, 0x38,
- 0x85, 0x19, 0x80, 0x38, 0x82, 0x19, 0x81, 0x38,
- 0x80, 0x19, 0x04, 0xa5, 0x47, 0x84, 0x2c, 0x80,
- 0x1d, 0xb0, 0x47, 0x84, 0x2c, 0x83, 0x47, 0x84,
- 0x2c, 0x8c, 0x47, 0x80, 0x1d, 0xc5, 0x47, 0x80,
- 0x2c, 0xbf, 0x38, 0xe0, 0x9f, 0x47, 0x95, 0x2c,
- 0x01, 0x85, 0x2c, 0x01, 0xa5, 0x2c, 0x01, 0x85,
- 0x2c, 0x01, 0x87, 0x2c, 0x00, 0x80, 0x2c, 0x00,
- 0x80, 0x2c, 0x00, 0x80, 0x2c, 0x00, 0x9e, 0x2c,
- 0x01, 0xb4, 0x2c, 0x00, 0x8e, 0x2c, 0x00, 0x8d,
- 0x2c, 0x01, 0x85, 0x2c, 0x00, 0x92, 0x2c, 0x01,
- 0x82, 0x2c, 0x00, 0x88, 0x2c, 0x00, 0x8b, 0x19,
- 0x81, 0x38, 0xd6, 0x19, 0x00, 0x8a, 0x19, 0x80,
- 0x47, 0x01, 0x8a, 0x19, 0x80, 0x47, 0x8e, 0x19,
- 0x00, 0x8c, 0x47, 0x02, 0xa0, 0x19, 0x0e, 0xa0,
- 0x38, 0x0e, 0xa5, 0x19, 0x80, 0x2c, 0x82, 0x19,
- 0x81, 0x47, 0x85, 0x19, 0x80, 0x47, 0x9a, 0x19,
- 0x80, 0x47, 0x90, 0x19, 0xa8, 0x47, 0x82, 0x19,
- 0x03, 0xe2, 0x36, 0x19, 0x18, 0x8a, 0x19, 0x14,
- 0xe3, 0x3f, 0x19, 0xe0, 0x9f, 0x0f, 0xe2, 0x13,
- 0x19, 0x01, 0x9f, 0x19, 0x00, 0xe0, 0x08, 0x19,
- 0xdf, 0x29, 0x9f, 0x47, 0xe0, 0x13, 0x1a, 0x04,
- 0x86, 0x1a, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04,
- 0x80, 0x28, 0x01, 0xb7, 0x98, 0x06, 0x81, 0x98,
- 0x0d, 0x80, 0x98, 0x96, 0x27, 0x08, 0x86, 0x27,
+ 0xe2, 0x1f, 0x12, 0x9c, 0x6c, 0x02, 0xca, 0x82,
+ 0x82, 0x19, 0x8a, 0x82, 0x06, 0x95, 0x91, 0x08,
+ 0x80, 0x91, 0x94, 0x35, 0x81, 0x19, 0x08, 0x93,
+ 0x11, 0x0b, 0x8c, 0x92, 0x00, 0x82, 0x92, 0x00,
+ 0x81, 0x92, 0x0b, 0xdd, 0x44, 0x01, 0x89, 0x44,
+ 0x05, 0x89, 0x44, 0x05, 0x81, 0x60, 0x81, 0x19,
+ 0x80, 0x60, 0x80, 0x19, 0x93, 0x60, 0x05, 0xd8,
+ 0x60, 0x06, 0xaa, 0x60, 0x04, 0xc5, 0x12, 0x09,
+ 0x9e, 0x4c, 0x00, 0x8b, 0x4c, 0x03, 0x8b, 0x4c,
+ 0x03, 0x80, 0x4c, 0x02, 0x8b, 0x4c, 0x9d, 0x93,
+ 0x01, 0x84, 0x93, 0x0a, 0xab, 0x67, 0x03, 0x99,
+ 0x67, 0x05, 0x8a, 0x67, 0x02, 0x81, 0x67, 0x9f,
+ 0x44, 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x94,
+ 0x00, 0x9c, 0x94, 0x01, 0x8a, 0x94, 0x05, 0x89,
+ 0x94, 0x05, 0x8d, 0x94, 0x01, 0x9e, 0x3a, 0x30,
+ 0xcc, 0x07, 0x00, 0xb1, 0x07, 0xbf, 0x8d, 0xb3,
+ 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x4b, 0x02, 0x8e,
+ 0x4b, 0x02, 0x82, 0x4b, 0xaf, 0x6d, 0x8a, 0x1d,
+ 0x04, 0xaa, 0x28, 0x01, 0x82, 0x28, 0x87, 0x8d,
+ 0x07, 0x82, 0x3a, 0x80, 0x19, 0x8c, 0x3a, 0x80,
+ 0x19, 0x86, 0x3a, 0x83, 0x19, 0x80, 0x3a, 0x85,
+ 0x19, 0x80, 0x3a, 0x82, 0x19, 0x81, 0x3a, 0x80,
+ 0x19, 0x04, 0xa5, 0x4a, 0x84, 0x2d, 0x80, 0x1d,
+ 0xb0, 0x4a, 0x84, 0x2d, 0x83, 0x4a, 0x84, 0x2d,
+ 0x8c, 0x4a, 0x80, 0x1d, 0xc5, 0x4a, 0x80, 0x2d,
+ 0xbf, 0x3a, 0xe0, 0x9f, 0x4a, 0x95, 0x2d, 0x01,
+ 0x85, 0x2d, 0x01, 0xa5, 0x2d, 0x01, 0x85, 0x2d,
+ 0x01, 0x87, 0x2d, 0x00, 0x80, 0x2d, 0x00, 0x80,
+ 0x2d, 0x00, 0x80, 0x2d, 0x00, 0x9e, 0x2d, 0x01,
+ 0xb4, 0x2d, 0x00, 0x8e, 0x2d, 0x00, 0x8d, 0x2d,
+ 0x01, 0x85, 0x2d, 0x00, 0x92, 0x2d, 0x01, 0x82,
+ 0x2d, 0x00, 0x88, 0x2d, 0x00, 0x8b, 0x19, 0x81,
+ 0x3a, 0xd6, 0x19, 0x00, 0x8a, 0x19, 0x80, 0x4a,
+ 0x01, 0x8a, 0x19, 0x80, 0x4a, 0x8e, 0x19, 0x00,
+ 0x8c, 0x4a, 0x02, 0xa0, 0x19, 0x0e, 0xa0, 0x3a,
+ 0x0e, 0xa5, 0x19, 0x80, 0x2d, 0x82, 0x19, 0x81,
+ 0x4a, 0x85, 0x19, 0x80, 0x4a, 0x9a, 0x19, 0x80,
+ 0x4a, 0x90, 0x19, 0xa8, 0x4a, 0x82, 0x19, 0x03,
+ 0xe2, 0x39, 0x19, 0x15, 0x8a, 0x19, 0x14, 0xe3,
+ 0x3f, 0x19, 0xe0, 0x9f, 0x0f, 0xe2, 0x13, 0x19,
+ 0x01, 0x9f, 0x19, 0x00, 0xe0, 0x08, 0x19, 0xdf,
+ 0x29, 0x9f, 0x4a, 0xe0, 0x13, 0x1a, 0x04, 0x86,
+ 0x1a, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04, 0x80,
+ 0x28, 0x01, 0xb7, 0x9d, 0x06, 0x81, 0x9d, 0x0d,
+ 0x80, 0x9d, 0x96, 0x27, 0x08, 0x86, 0x27, 0x00,
+ 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27,
0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86,
- 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00,
- 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x9f, 0x1d,
- 0xdd, 0x19, 0x21, 0x99, 0x30, 0x00, 0xd8, 0x30,
- 0x0b, 0xe0, 0x75, 0x30, 0x19, 0x8b, 0x19, 0x03,
- 0x84, 0x19, 0x80, 0x30, 0x80, 0x19, 0x80, 0x30,
- 0x98, 0x19, 0x88, 0x30, 0x83, 0x38, 0x81, 0x31,
- 0x87, 0x19, 0x83, 0x30, 0x83, 0x19, 0x00, 0xd5,
- 0x36, 0x01, 0x81, 0x38, 0x81, 0x19, 0x82, 0x36,
- 0x80, 0x19, 0xd9, 0x3e, 0x81, 0x19, 0x82, 0x3e,
- 0x04, 0xaa, 0x0d, 0x00, 0xdd, 0x31, 0x00, 0x8f,
- 0x19, 0x9f, 0x0d, 0xa3, 0x19, 0x0b, 0x8f, 0x3e,
- 0x9e, 0x31, 0x00, 0xbf, 0x19, 0x9e, 0x31, 0xd0,
- 0x19, 0xae, 0x3e, 0x80, 0x19, 0xd7, 0x3e, 0xe0,
- 0x47, 0x19, 0xf0, 0x09, 0x5f, 0x30, 0xbf, 0x19,
- 0xf0, 0x41, 0x9f, 0x30, 0xe4, 0x2c, 0xa2, 0x02,
- 0xb6, 0xa2, 0x08, 0xaf, 0x4c, 0xe0, 0xcb, 0x9d,
- 0x13, 0xdf, 0x1d, 0xd7, 0x08, 0x07, 0xa1, 0x19,
- 0xe0, 0x05, 0x47, 0x82, 0x19, 0xbf, 0x47, 0x04,
- 0x81, 0x47, 0x00, 0x80, 0x47, 0x00, 0x84, 0x47,
- 0x17, 0x8d, 0x47, 0xac, 0x8a, 0x02, 0x89, 0x19,
- 0x05, 0xb7, 0x7a, 0x07, 0xc5, 0x80, 0x07, 0x8b,
- 0x80, 0x05, 0x9f, 0x20, 0xad, 0x40, 0x80, 0x19,
- 0x80, 0x40, 0xa3, 0x7d, 0x0a, 0x80, 0x7d, 0x9c,
- 0x31, 0x02, 0xcd, 0x3b, 0x00, 0x80, 0x19, 0x89,
- 0x3b, 0x03, 0x81, 0x3b, 0x9e, 0x60, 0x00, 0xb6,
- 0x16, 0x08, 0x8d, 0x16, 0x01, 0x89, 0x16, 0x01,
- 0x83, 0x16, 0x9f, 0x60, 0xc2, 0x90, 0x17, 0x84,
- 0x90, 0x96, 0x57, 0x09, 0x85, 0x27, 0x01, 0x85,
- 0x27, 0x01, 0x85, 0x27, 0x08, 0x86, 0x27, 0x00,
- 0x86, 0x27, 0x00, 0xaa, 0x47, 0x80, 0x19, 0x88,
- 0x47, 0x80, 0x2c, 0x83, 0x47, 0x81, 0x19, 0x03,
- 0xcf, 0x17, 0xad, 0x57, 0x01, 0x89, 0x57, 0x05,
- 0xf0, 0x1b, 0x43, 0x31, 0x0b, 0x96, 0x31, 0x03,
- 0xb0, 0x31, 0x70, 0x10, 0xa3, 0xe1, 0x0d, 0x30,
- 0x01, 0xe0, 0x09, 0x30, 0x25, 0x86, 0x47, 0x0b,
- 0x84, 0x05, 0x04, 0x99, 0x35, 0x00, 0x84, 0x35,
- 0x00, 0x80, 0x35, 0x00, 0x81, 0x35, 0x00, 0x81,
- 0x35, 0x00, 0x89, 0x35, 0xe0, 0x12, 0x04, 0x0f,
- 0xe1, 0x0a, 0x04, 0x81, 0x19, 0xcf, 0x04, 0x01,
- 0xb5, 0x04, 0x06, 0x80, 0x04, 0x1f, 0x8f, 0x04,
- 0x8f, 0x38, 0x89, 0x19, 0x05, 0x8d, 0x38, 0x81,
- 0x1d, 0xa2, 0x19, 0x00, 0x92, 0x19, 0x00, 0x83,
- 0x19, 0x03, 0x84, 0x04, 0x00, 0xe0, 0x26, 0x04,
- 0x01, 0x80, 0x19, 0x00, 0x9f, 0x19, 0x99, 0x47,
- 0x85, 0x19, 0x99, 0x47, 0x8a, 0x19, 0x89, 0x3e,
- 0x80, 0x19, 0xac, 0x3e, 0x81, 0x19, 0x9e, 0x31,
- 0x02, 0x85, 0x31, 0x01, 0x85, 0x31, 0x01, 0x85,
- 0x31, 0x01, 0x82, 0x31, 0x02, 0x86, 0x19, 0x00,
- 0x86, 0x19, 0x09, 0x84, 0x19, 0x01, 0x8b, 0x4b,
- 0x00, 0x99, 0x4b, 0x00, 0x92, 0x4b, 0x00, 0x81,
- 0x4b, 0x00, 0x8e, 0x4b, 0x01, 0x8d, 0x4b, 0x21,
- 0xe0, 0x1a, 0x4b, 0x04, 0x82, 0x19, 0x03, 0xac,
- 0x19, 0x02, 0x88, 0x19, 0xce, 0x2c, 0x00, 0x8c,
- 0x19, 0x02, 0x80, 0x2c, 0x2e, 0xac, 0x19, 0x80,
- 0x38, 0x60, 0x21, 0x9c, 0x4d, 0x02, 0xb0, 0x13,
- 0x0e, 0x80, 0x38, 0x9a, 0x19, 0x03, 0xa3, 0x6c,
- 0x08, 0x82, 0x6c, 0x9a, 0x2a, 0x04, 0xaa, 0x6e,
- 0x04, 0x9d, 0x9c, 0x00, 0x80, 0x9c, 0xa3, 0x6f,
- 0x03, 0x8d, 0x6f, 0x29, 0xcf, 0x1f, 0xaf, 0x82,
- 0x9d, 0x76, 0x01, 0x89, 0x76, 0x05, 0xa3, 0x75,
- 0x03, 0xa3, 0x75, 0x03, 0xa7, 0x25, 0x07, 0xb3,
- 0x14, 0x0a, 0x80, 0x14, 0x8a, 0x9e, 0x00, 0x8e,
- 0x9e, 0x00, 0x86, 0x9e, 0x00, 0x81, 0x9e, 0x00,
- 0x8a, 0x9e, 0x00, 0x8e, 0x9e, 0x00, 0x86, 0x9e,
- 0x00, 0x81, 0x9e, 0x42, 0xe0, 0xd6, 0x4a, 0x08,
- 0x95, 0x4a, 0x09, 0x87, 0x4a, 0x17, 0x85, 0x47,
- 0x00, 0xa9, 0x47, 0x00, 0x88, 0x47, 0x44, 0x85,
- 0x1c, 0x01, 0x80, 0x1c, 0x00, 0xab, 0x1c, 0x00,
- 0x81, 0x1c, 0x02, 0x80, 0x1c, 0x01, 0x80, 0x1c,
- 0x95, 0x37, 0x00, 0x88, 0x37, 0x9f, 0x78, 0x9e,
- 0x61, 0x07, 0x88, 0x61, 0x2f, 0x92, 0x34, 0x00,
- 0x81, 0x34, 0x04, 0x84, 0x34, 0x9b, 0x7b, 0x02,
- 0x80, 0x7b, 0x99, 0x4e, 0x04, 0x80, 0x4e, 0x3f,
- 0x9f, 0x5a, 0x97, 0x59, 0x03, 0x93, 0x59, 0x01,
- 0xad, 0x59, 0x83, 0x41, 0x00, 0x81, 0x41, 0x04,
- 0x87, 0x41, 0x00, 0x82, 0x41, 0x00, 0x9c, 0x41,
- 0x01, 0x82, 0x41, 0x03, 0x89, 0x41, 0x06, 0x88,
- 0x41, 0x06, 0x9f, 0x71, 0x9f, 0x6d, 0x1f, 0xa6,
- 0x53, 0x03, 0x8b, 0x53, 0x08, 0xb5, 0x06, 0x02,
- 0x86, 0x06, 0x95, 0x3a, 0x01, 0x87, 0x3a, 0x92,
- 0x39, 0x04, 0x87, 0x39, 0x91, 0x7c, 0x06, 0x83,
- 0x7c, 0x0b, 0x86, 0x7c, 0x4f, 0xc8, 0x72, 0x36,
- 0xb2, 0x6b, 0x0c, 0xb2, 0x6b, 0x06, 0x85, 0x6b,
- 0xa7, 0x32, 0x07, 0x89, 0x32, 0x60, 0xc5, 0x9e,
- 0x04, 0x00, 0xa9, 0xa1, 0x00, 0x82, 0xa1, 0x01,
- 0x81, 0xa1, 0x4a, 0x82, 0x04, 0xa7, 0x70, 0x07,
- 0xa9, 0x86, 0x15, 0x99, 0x73, 0x25, 0x9b, 0x18,
- 0x13, 0x96, 0x26, 0x08, 0xcd, 0x0e, 0x03, 0xa3,
- 0x0e, 0x08, 0x80, 0x0e, 0xc2, 0x3c, 0x09, 0x80,
- 0x3c, 0x01, 0x98, 0x87, 0x06, 0x89, 0x87, 0x05,
- 0xb4, 0x15, 0x00, 0x91, 0x15, 0x07, 0xa6, 0x50,
- 0x08, 0xdf, 0x81, 0x00, 0x93, 0x85, 0x0a, 0x91,
- 0x43, 0x00, 0xae, 0x43, 0x3d, 0x86, 0x5f, 0x00,
- 0x80, 0x5f, 0x00, 0x83, 0x5f, 0x00, 0x8e, 0x5f,
- 0x00, 0x8a, 0x5f, 0x05, 0xba, 0x45, 0x04, 0x89,
- 0x45, 0x05, 0x83, 0x2b, 0x00, 0x87, 0x2b, 0x01,
- 0x81, 0x2b, 0x01, 0x95, 0x2b, 0x00, 0x86, 0x2b,
- 0x00, 0x81, 0x2b, 0x00, 0x84, 0x2b, 0x00, 0x80,
- 0x38, 0x88, 0x2b, 0x01, 0x81, 0x2b, 0x01, 0x82,
- 0x2b, 0x01, 0x80, 0x2b, 0x05, 0x80, 0x2b, 0x04,
- 0x86, 0x2b, 0x01, 0x86, 0x2b, 0x02, 0x84, 0x2b,
- 0x60, 0x2a, 0xdb, 0x65, 0x00, 0x84, 0x65, 0x1d,
- 0xc7, 0x99, 0x07, 0x89, 0x99, 0x60, 0x45, 0xb5,
- 0x83, 0x01, 0xa5, 0x83, 0x21, 0xc4, 0x5c, 0x0a,
- 0x89, 0x5c, 0x05, 0x8c, 0x5d, 0x12, 0xb9, 0x91,
- 0x05, 0x89, 0x91, 0x35, 0x9a, 0x02, 0x01, 0x8e,
+ 0x27, 0x00, 0x86, 0x27, 0x00, 0x9f, 0x1d, 0xdd,
+ 0x19, 0x21, 0x99, 0x32, 0x00, 0xd8, 0x32, 0x0b,
+ 0xe0, 0x75, 0x32, 0x19, 0x94, 0x19, 0x80, 0x32,
+ 0x80, 0x19, 0x80, 0x32, 0x98, 0x19, 0x88, 0x32,
+ 0x83, 0x3a, 0x81, 0x33, 0x87, 0x19, 0x83, 0x32,
+ 0x83, 0x19, 0x00, 0xd5, 0x38, 0x01, 0x81, 0x3a,
+ 0x81, 0x19, 0x82, 0x38, 0x80, 0x19, 0xd9, 0x40,
+ 0x81, 0x19, 0x82, 0x40, 0x04, 0xaa, 0x0d, 0x00,
+ 0xdd, 0x33, 0x00, 0x8f, 0x19, 0x9f, 0x0d, 0xa5,
+ 0x19, 0x08, 0x80, 0x19, 0x8f, 0x40, 0x9e, 0x33,
+ 0x00, 0xbf, 0x19, 0x9e, 0x33, 0xd0, 0x19, 0xae,
+ 0x40, 0x80, 0x19, 0xd7, 0x40, 0xe0, 0x47, 0x19,
+ 0xf0, 0x09, 0x5f, 0x32, 0xbf, 0x19, 0xf0, 0x41,
+ 0x9f, 0x32, 0xe4, 0x2c, 0xa9, 0x02, 0xb6, 0xa9,
+ 0x08, 0xaf, 0x4f, 0xe0, 0xcb, 0xa4, 0x13, 0xdf,
+ 0x1d, 0xd7, 0x08, 0x07, 0xa1, 0x19, 0xe0, 0x05,
+ 0x4a, 0x82, 0x19, 0xc2, 0x4a, 0x01, 0x81, 0x4a,
+ 0x00, 0x80, 0x4a, 0x00, 0x87, 0x4a, 0x14, 0x8d,
+ 0x4a, 0xac, 0x8f, 0x02, 0x89, 0x19, 0x05, 0xb7,
+ 0x7e, 0x07, 0xc5, 0x84, 0x07, 0x8b, 0x84, 0x05,
+ 0x9f, 0x20, 0xad, 0x42, 0x80, 0x19, 0x80, 0x42,
+ 0xa3, 0x81, 0x0a, 0x80, 0x81, 0x9c, 0x33, 0x02,
+ 0xcd, 0x3d, 0x00, 0x80, 0x19, 0x89, 0x3d, 0x03,
+ 0x81, 0x3d, 0x9e, 0x63, 0x00, 0xb6, 0x16, 0x08,
+ 0x8d, 0x16, 0x01, 0x89, 0x16, 0x01, 0x83, 0x16,
+ 0x9f, 0x63, 0xc2, 0x95, 0x17, 0x84, 0x95, 0x96,
+ 0x5a, 0x09, 0x85, 0x27, 0x01, 0x85, 0x27, 0x01,
+ 0x85, 0x27, 0x08, 0x86, 0x27, 0x00, 0x86, 0x27,
+ 0x00, 0xaa, 0x4a, 0x80, 0x19, 0x88, 0x4a, 0x80,
+ 0x2d, 0x83, 0x4a, 0x81, 0x19, 0x03, 0xcf, 0x17,
+ 0xad, 0x5a, 0x01, 0x89, 0x5a, 0x05, 0xf0, 0x1b,
+ 0x43, 0x33, 0x0b, 0x96, 0x33, 0x03, 0xb0, 0x33,
+ 0x70, 0x10, 0xa3, 0xe1, 0x0d, 0x32, 0x01, 0xe0,
+ 0x09, 0x32, 0x25, 0x86, 0x4a, 0x0b, 0x84, 0x05,
+ 0x04, 0x99, 0x37, 0x00, 0x84, 0x37, 0x00, 0x80,
+ 0x37, 0x00, 0x81, 0x37, 0x00, 0x81, 0x37, 0x00,
+ 0x89, 0x37, 0xe0, 0x12, 0x04, 0x0f, 0xe1, 0x0a,
+ 0x04, 0x81, 0x19, 0xcf, 0x04, 0x01, 0xb5, 0x04,
+ 0x06, 0x80, 0x04, 0x1f, 0x8f, 0x04, 0x8f, 0x3a,
+ 0x89, 0x19, 0x05, 0x8d, 0x3a, 0x81, 0x1d, 0xa2,
+ 0x19, 0x00, 0x92, 0x19, 0x00, 0x83, 0x19, 0x03,
+ 0x84, 0x04, 0x00, 0xe0, 0x26, 0x04, 0x01, 0x80,
+ 0x19, 0x00, 0x9f, 0x19, 0x99, 0x4a, 0x85, 0x19,
+ 0x99, 0x4a, 0x8a, 0x19, 0x89, 0x40, 0x80, 0x19,
+ 0xac, 0x40, 0x81, 0x19, 0x9e, 0x33, 0x02, 0x85,
+ 0x33, 0x01, 0x85, 0x33, 0x01, 0x85, 0x33, 0x01,
+ 0x82, 0x33, 0x02, 0x86, 0x19, 0x00, 0x86, 0x19,
+ 0x09, 0x84, 0x19, 0x01, 0x8b, 0x4e, 0x00, 0x99,
+ 0x4e, 0x00, 0x92, 0x4e, 0x00, 0x81, 0x4e, 0x00,
+ 0x8e, 0x4e, 0x01, 0x8d, 0x4e, 0x21, 0xe0, 0x1a,
+ 0x4e, 0x04, 0x82, 0x19, 0x03, 0xac, 0x19, 0x02,
+ 0x88, 0x19, 0xce, 0x2d, 0x00, 0x8c, 0x19, 0x02,
+ 0x80, 0x2d, 0x2e, 0xac, 0x19, 0x80, 0x3a, 0x60,
+ 0x21, 0x9c, 0x50, 0x02, 0xb0, 0x13, 0x0e, 0x80,
+ 0x3a, 0x9a, 0x19, 0x03, 0xa3, 0x70, 0x08, 0x82,
+ 0x70, 0x9a, 0x2a, 0x04, 0xaa, 0x72, 0x04, 0x9d,
+ 0xa3, 0x00, 0x80, 0xa3, 0xa3, 0x73, 0x03, 0x8d,
+ 0x73, 0x29, 0xcf, 0x1f, 0xaf, 0x86, 0x9d, 0x7a,
+ 0x01, 0x89, 0x7a, 0x05, 0xa3, 0x79, 0x03, 0xa3,
+ 0x79, 0x03, 0xa7, 0x25, 0x07, 0xb3, 0x14, 0x0a,
+ 0x80, 0x14, 0x8a, 0xa5, 0x00, 0x8e, 0xa5, 0x00,
+ 0x86, 0xa5, 0x00, 0x81, 0xa5, 0x00, 0x8a, 0xa5,
+ 0x00, 0x8e, 0xa5, 0x00, 0x86, 0xa5, 0x00, 0x81,
+ 0xa5, 0x02, 0xb3, 0xa0, 0x0b, 0xe0, 0xd6, 0x4d,
+ 0x08, 0x95, 0x4d, 0x09, 0x87, 0x4d, 0x17, 0x85,
+ 0x4a, 0x00, 0xa9, 0x4a, 0x00, 0x88, 0x4a, 0x44,
+ 0x85, 0x1c, 0x01, 0x80, 0x1c, 0x00, 0xab, 0x1c,
+ 0x00, 0x81, 0x1c, 0x02, 0x80, 0x1c, 0x01, 0x80,
+ 0x1c, 0x95, 0x39, 0x00, 0x88, 0x39, 0x9f, 0x7c,
+ 0x9e, 0x64, 0x07, 0x88, 0x64, 0x2f, 0x92, 0x36,
+ 0x00, 0x81, 0x36, 0x04, 0x84, 0x36, 0x9b, 0x7f,
+ 0x02, 0x80, 0x7f, 0x99, 0x51, 0x04, 0x80, 0x51,
+ 0x3f, 0x9f, 0x5d, 0x97, 0x5c, 0x03, 0x93, 0x5c,
+ 0x01, 0xad, 0x5c, 0x83, 0x43, 0x00, 0x81, 0x43,
+ 0x04, 0x87, 0x43, 0x00, 0x82, 0x43, 0x00, 0x9c,
+ 0x43, 0x01, 0x82, 0x43, 0x03, 0x89, 0x43, 0x06,
+ 0x88, 0x43, 0x06, 0x9f, 0x75, 0x9f, 0x71, 0x1f,
+ 0xa6, 0x56, 0x03, 0x8b, 0x56, 0x08, 0xb5, 0x06,
+ 0x02, 0x86, 0x06, 0x95, 0x3c, 0x01, 0x87, 0x3c,
+ 0x92, 0x3b, 0x04, 0x87, 0x3b, 0x91, 0x80, 0x06,
+ 0x83, 0x80, 0x0b, 0x86, 0x80, 0x4f, 0xc8, 0x76,
+ 0x36, 0xb2, 0x6f, 0x0c, 0xb2, 0x6f, 0x06, 0x85,
+ 0x6f, 0xa7, 0x34, 0x07, 0x89, 0x34, 0x05, 0xa5,
+ 0x2b, 0x02, 0x9c, 0x2b, 0x07, 0x81, 0x2b, 0x60,
+ 0x6f, 0x9e, 0x04, 0x00, 0xa9, 0xa8, 0x00, 0x82,
+ 0xa8, 0x01, 0x81, 0xa8, 0x0f, 0x82, 0x04, 0x36,
+ 0x83, 0x04, 0xa7, 0x74, 0x07, 0xa9, 0x8a, 0x15,
+ 0x99, 0x77, 0x25, 0x9b, 0x18, 0x13, 0x96, 0x26,
+ 0x08, 0xcd, 0x0e, 0x03, 0xa3, 0x0e, 0x08, 0x80,
+ 0x0e, 0xc2, 0x3e, 0x09, 0x80, 0x3e, 0x01, 0x98,
+ 0x8b, 0x06, 0x89, 0x8b, 0x05, 0xb4, 0x15, 0x00,
+ 0x91, 0x15, 0x07, 0xa6, 0x53, 0x08, 0xdf, 0x85,
+ 0x00, 0x93, 0x89, 0x0a, 0x91, 0x45, 0x00, 0xae,
+ 0x45, 0x3d, 0x86, 0x62, 0x00, 0x80, 0x62, 0x00,
+ 0x83, 0x62, 0x00, 0x8e, 0x62, 0x00, 0x8a, 0x62,
+ 0x05, 0xba, 0x47, 0x04, 0x89, 0x47, 0x05, 0x83,
+ 0x2c, 0x00, 0x87, 0x2c, 0x01, 0x81, 0x2c, 0x01,
+ 0x95, 0x2c, 0x00, 0x86, 0x2c, 0x00, 0x81, 0x2c,
+ 0x00, 0x84, 0x2c, 0x00, 0x80, 0x3a, 0x88, 0x2c,
+ 0x01, 0x81, 0x2c, 0x01, 0x82, 0x2c, 0x01, 0x80,
+ 0x2c, 0x05, 0x80, 0x2c, 0x04, 0x86, 0x2c, 0x01,
+ 0x86, 0x2c, 0x02, 0x84, 0x2c, 0x0a, 0x89, 0xa2,
+ 0x00, 0x80, 0xa2, 0x01, 0x80, 0xa2, 0x00, 0xa5,
+ 0xa2, 0x00, 0x89, 0xa2, 0x00, 0x80, 0xa2, 0x01,
+ 0x80, 0xa2, 0x00, 0x83, 0xa2, 0x00, 0x89, 0xa2,
+ 0x00, 0x81, 0xa2, 0x07, 0x81, 0xa2, 0x1c, 0xdb,
+ 0x68, 0x00, 0x84, 0x68, 0x1d, 0xc7, 0x9e, 0x07,
+ 0x89, 0x9e, 0x60, 0x45, 0xb5, 0x87, 0x01, 0xa5,
+ 0x87, 0x21, 0xc4, 0x5f, 0x0a, 0x89, 0x5f, 0x05,
+ 0x8c, 0x60, 0x12, 0xb9, 0x96, 0x05, 0x89, 0x96,
+ 0x05, 0x93, 0x63, 0x1b, 0x9a, 0x02, 0x01, 0x8e,
0x02, 0x03, 0x96, 0x02, 0x60, 0x58, 0xbb, 0x22,
- 0x60, 0x03, 0xd2, 0xa0, 0x0b, 0x80, 0xa0, 0x86,
+ 0x60, 0x03, 0xd2, 0xa7, 0x0b, 0x80, 0xa7, 0x86,
0x21, 0x01, 0x80, 0x21, 0x01, 0x87, 0x21, 0x00,
0x81, 0x21, 0x00, 0x9d, 0x21, 0x00, 0x81, 0x21,
0x01, 0x8b, 0x21, 0x08, 0x89, 0x21, 0x45, 0x87,
- 0x63, 0x01, 0xad, 0x63, 0x01, 0x8a, 0x63, 0x1a,
- 0xc7, 0xa3, 0x07, 0xd2, 0x88, 0x0c, 0x8f, 0x12,
- 0xb8, 0x79, 0x06, 0x89, 0x20, 0x60, 0x95, 0x88,
- 0x0c, 0x00, 0xac, 0x0c, 0x00, 0x8d, 0x0c, 0x09,
- 0x9c, 0x0c, 0x02, 0x9f, 0x54, 0x01, 0x95, 0x54,
- 0x00, 0x8d, 0x54, 0x48, 0x86, 0x55, 0x00, 0x81,
- 0x55, 0x00, 0xab, 0x55, 0x02, 0x80, 0x55, 0x00,
- 0x81, 0x55, 0x00, 0x88, 0x55, 0x07, 0x89, 0x55,
- 0x05, 0x85, 0x2e, 0x00, 0x81, 0x2e, 0x00, 0xa4,
- 0x2e, 0x00, 0x81, 0x2e, 0x00, 0x85, 0x2e, 0x06,
- 0x89, 0x2e, 0x60, 0xd5, 0x98, 0x4f, 0x06, 0x90,
- 0x3f, 0x00, 0xa8, 0x3f, 0x02, 0x9b, 0x3f, 0x55,
- 0x80, 0x4c, 0x0e, 0xb1, 0x92, 0x0c, 0x80, 0x92,
- 0xe3, 0x39, 0x1b, 0x60, 0x05, 0xe0, 0x0e, 0x1b,
- 0x00, 0x84, 0x1b, 0x0a, 0xe0, 0x63, 0x1b, 0x69,
- 0xeb, 0xe0, 0x02, 0x1e, 0x0c, 0xe3, 0xf5, 0x24,
- 0x6f, 0x49, 0xe1, 0xe6, 0x03, 0x70, 0x11, 0x58,
- 0xe1, 0xd8, 0x08, 0x06, 0x9e, 0x5e, 0x00, 0x89,
- 0x5e, 0x03, 0x81, 0x5e, 0xce, 0x9a, 0x00, 0x89,
- 0x9a, 0x05, 0x9d, 0x09, 0x01, 0x85, 0x09, 0x09,
- 0xc5, 0x77, 0x09, 0x89, 0x77, 0x00, 0x86, 0x77,
- 0x00, 0x94, 0x77, 0x04, 0x92, 0x77, 0x62, 0x4f,
- 0xda, 0x56, 0x60, 0x04, 0xca, 0x5b, 0x03, 0xb8,
- 0x5b, 0x06, 0x90, 0x5b, 0x3f, 0x80, 0x93, 0x80,
- 0x67, 0x81, 0x30, 0x80, 0x44, 0x0a, 0x81, 0x30,
- 0x0d, 0xf0, 0x07, 0x97, 0x93, 0x07, 0xe2, 0x9f,
- 0x93, 0xe1, 0x75, 0x44, 0x29, 0x88, 0x93, 0x70,
- 0x12, 0x86, 0x83, 0x3e, 0x00, 0x86, 0x3e, 0x00,
- 0x81, 0x3e, 0x00, 0x80, 0x3e, 0xe0, 0xbe, 0x36,
- 0x82, 0x3e, 0x0e, 0x80, 0x36, 0x1c, 0x82, 0x36,
- 0x01, 0x80, 0x3e, 0x0d, 0x83, 0x3e, 0x07, 0xe1,
- 0x2b, 0x67, 0x68, 0xa3, 0xe0, 0x0a, 0x23, 0x04,
- 0x8c, 0x23, 0x02, 0x88, 0x23, 0x06, 0x89, 0x23,
- 0x01, 0x83, 0x23, 0x83, 0x19, 0x70, 0x01, 0xfb,
- 0xad, 0x38, 0x01, 0x96, 0x38, 0x08, 0xe0, 0x13,
- 0x19, 0x3b, 0xe0, 0x95, 0x19, 0x09, 0xa6, 0x19,
- 0x01, 0xbd, 0x19, 0x82, 0x38, 0x90, 0x19, 0x87,
- 0x38, 0x81, 0x19, 0x86, 0x38, 0x9d, 0x19, 0x83,
- 0x38, 0xbc, 0x19, 0x14, 0xc5, 0x2c, 0x60, 0x19,
- 0x93, 0x19, 0x0b, 0x93, 0x19, 0x0b, 0xd6, 0x19,
- 0x08, 0x98, 0x19, 0x60, 0x26, 0xd4, 0x19, 0x00,
- 0xc6, 0x19, 0x00, 0x81, 0x19, 0x01, 0x80, 0x19,
- 0x01, 0x81, 0x19, 0x01, 0x83, 0x19, 0x00, 0x8b,
- 0x19, 0x00, 0x80, 0x19, 0x00, 0x86, 0x19, 0x00,
- 0xc0, 0x19, 0x00, 0x83, 0x19, 0x01, 0x87, 0x19,
- 0x00, 0x86, 0x19, 0x00, 0x9b, 0x19, 0x00, 0x83,
- 0x19, 0x00, 0x84, 0x19, 0x00, 0x80, 0x19, 0x02,
- 0x86, 0x19, 0x00, 0xe0, 0xf3, 0x19, 0x01, 0xe0,
- 0xc3, 0x19, 0x01, 0xb1, 0x19, 0xe2, 0x2b, 0x84,
- 0x0e, 0x84, 0x84, 0x00, 0x8e, 0x84, 0x63, 0xef,
- 0x9e, 0x47, 0x05, 0x85, 0x47, 0x60, 0x74, 0x86,
- 0x29, 0x00, 0x90, 0x29, 0x01, 0x86, 0x29, 0x00,
- 0x81, 0x29, 0x00, 0x84, 0x29, 0x04, 0xbd, 0x1d,
- 0x20, 0x80, 0x1d, 0x60, 0x0f, 0xac, 0x68, 0x02,
- 0x8d, 0x68, 0x01, 0x89, 0x68, 0x03, 0x81, 0x68,
- 0x60, 0xdf, 0x9e, 0x9b, 0x10, 0xb9, 0x9f, 0x04,
- 0x80, 0x9f, 0x61, 0x6f, 0xa9, 0x62, 0x62, 0x85,
- 0x86, 0x27, 0x00, 0x83, 0x27, 0x00, 0x81, 0x27,
- 0x00, 0x8e, 0x27, 0x00, 0xe0, 0x64, 0x58, 0x01,
- 0x8f, 0x58, 0x28, 0xcb, 0x01, 0x03, 0x89, 0x01,
- 0x03, 0x81, 0x01, 0x62, 0xb0, 0xc3, 0x19, 0x4b,
- 0xbc, 0x19, 0x60, 0x61, 0x83, 0x04, 0x00, 0x9a,
- 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, 0x01,
- 0x80, 0x04, 0x00, 0x89, 0x04, 0x00, 0x83, 0x04,
- 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x05, 0x80,
- 0x04, 0x03, 0x80, 0x04, 0x00, 0x80, 0x04, 0x00,
- 0x80, 0x04, 0x00, 0x82, 0x04, 0x00, 0x81, 0x04,
- 0x00, 0x80, 0x04, 0x01, 0x80, 0x04, 0x00, 0x80,
- 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x00,
- 0x80, 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04,
- 0x01, 0x83, 0x04, 0x00, 0x86, 0x04, 0x00, 0x83,
- 0x04, 0x00, 0x83, 0x04, 0x00, 0x80, 0x04, 0x00,
- 0x89, 0x04, 0x00, 0x90, 0x04, 0x04, 0x82, 0x04,
- 0x00, 0x84, 0x04, 0x00, 0x90, 0x04, 0x33, 0x81,
- 0x04, 0x60, 0xad, 0xab, 0x19, 0x03, 0xe0, 0x03,
- 0x19, 0x0b, 0x8e, 0x19, 0x01, 0x8e, 0x19, 0x00,
- 0x8e, 0x19, 0x00, 0xa4, 0x19, 0x09, 0xe0, 0x4d,
- 0x19, 0x37, 0x99, 0x19, 0x80, 0x36, 0x81, 0x19,
- 0x0c, 0xab, 0x19, 0x03, 0x88, 0x19, 0x06, 0x81,
- 0x19, 0x0d, 0x85, 0x19, 0x60, 0x39, 0xe3, 0x77,
- 0x19, 0x03, 0x90, 0x19, 0x02, 0x8c, 0x19, 0x02,
- 0xe0, 0x16, 0x19, 0x03, 0xde, 0x19, 0x05, 0x8b,
- 0x19, 0x03, 0x80, 0x19, 0x0e, 0x8b, 0x19, 0x03,
- 0xb7, 0x19, 0x07, 0x89, 0x19, 0x05, 0xa7, 0x19,
- 0x07, 0x9d, 0x19, 0x01, 0x81, 0x19, 0x4d, 0xe0,
- 0xf3, 0x19, 0x0b, 0x8d, 0x19, 0x01, 0x8c, 0x19,
- 0x02, 0x88, 0x19, 0x06, 0xad, 0x19, 0x00, 0x86,
- 0x19, 0x07, 0x8d, 0x19, 0x03, 0x88, 0x19, 0x06,
- 0x88, 0x19, 0x06, 0xe0, 0x32, 0x19, 0x00, 0xb6,
- 0x19, 0x24, 0x89, 0x19, 0x63, 0xa5, 0xf0, 0x96,
- 0x7f, 0x30, 0x1f, 0xef, 0xd9, 0x30, 0x05, 0xe0,
- 0x7d, 0x30, 0x01, 0xf0, 0x06, 0x21, 0x30, 0x0d,
- 0xf0, 0x0c, 0xd0, 0x30, 0x6b, 0xbe, 0xe1, 0xbd,
- 0x30, 0x65, 0x81, 0xf0, 0x02, 0xea, 0x30, 0x04,
- 0xef, 0xff, 0x30, 0x7a, 0xcb, 0xf0, 0x80, 0x19,
- 0x1d, 0xdf, 0x19, 0x60, 0x1f, 0xe0, 0x8f, 0x38,
+ 0x66, 0x01, 0xad, 0x66, 0x01, 0x8a, 0x66, 0x1a,
+ 0xc7, 0xaa, 0x07, 0xd2, 0x8c, 0x0c, 0x8f, 0x12,
+ 0xb8, 0x7d, 0x06, 0x89, 0x20, 0x60, 0x55, 0xa1,
+ 0x8e, 0x0d, 0x89, 0x8e, 0x05, 0x88, 0x0c, 0x00,
+ 0xac, 0x0c, 0x00, 0x8d, 0x0c, 0x09, 0x9c, 0x0c,
+ 0x02, 0x9f, 0x57, 0x01, 0x95, 0x57, 0x00, 0x8d,
+ 0x57, 0x48, 0x86, 0x58, 0x00, 0x81, 0x58, 0x00,
+ 0xab, 0x58, 0x02, 0x80, 0x58, 0x00, 0x81, 0x58,
+ 0x00, 0x88, 0x58, 0x07, 0x89, 0x58, 0x05, 0x85,
+ 0x2f, 0x00, 0x81, 0x2f, 0x00, 0xa4, 0x2f, 0x00,
+ 0x81, 0x2f, 0x00, 0x85, 0x2f, 0x06, 0x89, 0x2f,
+ 0x60, 0xd5, 0x98, 0x52, 0x06, 0x90, 0x41, 0x00,
+ 0xa8, 0x41, 0x02, 0x9c, 0x41, 0x54, 0x80, 0x4f,
+ 0x0e, 0xb1, 0x97, 0x0c, 0x80, 0x97, 0xe3, 0x39,
+ 0x1b, 0x60, 0x05, 0xe0, 0x0e, 0x1b, 0x00, 0x84,
+ 0x1b, 0x0a, 0xe0, 0x63, 0x1b, 0x69, 0xeb, 0xe0,
+ 0x02, 0x1e, 0x0c, 0xe3, 0xf5, 0x24, 0x09, 0xef,
+ 0x3a, 0x24, 0x04, 0xe1, 0xe6, 0x03, 0x70, 0x0a,
+ 0x58, 0xb9, 0x31, 0x66, 0x65, 0xe1, 0xd8, 0x08,
+ 0x06, 0x9e, 0x61, 0x00, 0x89, 0x61, 0x03, 0x81,
+ 0x61, 0xce, 0x9f, 0x00, 0x89, 0x9f, 0x05, 0x9d,
+ 0x09, 0x01, 0x85, 0x09, 0x09, 0xc5, 0x7b, 0x09,
+ 0x89, 0x7b, 0x00, 0x86, 0x7b, 0x00, 0x94, 0x7b,
+ 0x04, 0x92, 0x7b, 0x61, 0x4f, 0xb9, 0x48, 0x60,
+ 0x65, 0xda, 0x59, 0x60, 0x04, 0xca, 0x5e, 0x03,
+ 0xb8, 0x5e, 0x06, 0x90, 0x5e, 0x3f, 0x80, 0x98,
+ 0x80, 0x6a, 0x81, 0x32, 0x80, 0x46, 0x0a, 0x81,
+ 0x32, 0x0d, 0xf0, 0x07, 0x97, 0x98, 0x07, 0xe2,
+ 0x9f, 0x98, 0xe1, 0x75, 0x46, 0x28, 0x80, 0x46,
+ 0x88, 0x98, 0x70, 0x12, 0x86, 0x83, 0x40, 0x00,
+ 0x86, 0x40, 0x00, 0x81, 0x40, 0x00, 0x80, 0x40,
+ 0xe0, 0xbe, 0x38, 0x82, 0x40, 0x0e, 0x80, 0x38,
+ 0x1c, 0x82, 0x38, 0x01, 0x80, 0x40, 0x0d, 0x83,
+ 0x40, 0x07, 0xe1, 0x2b, 0x6a, 0x68, 0xa3, 0xe0,
+ 0x0a, 0x23, 0x04, 0x8c, 0x23, 0x02, 0x88, 0x23,
+ 0x06, 0x89, 0x23, 0x01, 0x83, 0x23, 0x83, 0x19,
+ 0x6e, 0xfb, 0xe0, 0x99, 0x19, 0x05, 0xe1, 0x53,
+ 0x19, 0x4b, 0xad, 0x3a, 0x01, 0x96, 0x3a, 0x08,
+ 0xe0, 0x13, 0x19, 0x3b, 0xe0, 0x95, 0x19, 0x09,
+ 0xa6, 0x19, 0x01, 0xbd, 0x19, 0x82, 0x3a, 0x90,
+ 0x19, 0x87, 0x3a, 0x81, 0x19, 0x86, 0x3a, 0x9d,
+ 0x19, 0x83, 0x3a, 0xbc, 0x19, 0x14, 0xc5, 0x2d,
+ 0x60, 0x19, 0x93, 0x19, 0x0b, 0x93, 0x19, 0x0b,
+ 0xd6, 0x19, 0x08, 0x98, 0x19, 0x60, 0x26, 0xd4,
+ 0x19, 0x00, 0xc6, 0x19, 0x00, 0x81, 0x19, 0x01,
+ 0x80, 0x19, 0x01, 0x81, 0x19, 0x01, 0x83, 0x19,
+ 0x00, 0x8b, 0x19, 0x00, 0x80, 0x19, 0x00, 0x86,
+ 0x19, 0x00, 0xc0, 0x19, 0x00, 0x83, 0x19, 0x01,
+ 0x87, 0x19, 0x00, 0x86, 0x19, 0x00, 0x9b, 0x19,
+ 0x00, 0x83, 0x19, 0x00, 0x84, 0x19, 0x00, 0x80,
+ 0x19, 0x02, 0x86, 0x19, 0x00, 0xe0, 0xf3, 0x19,
+ 0x01, 0xe0, 0xc3, 0x19, 0x01, 0xb1, 0x19, 0xe2,
+ 0x2b, 0x88, 0x0e, 0x84, 0x88, 0x00, 0x8e, 0x88,
+ 0x63, 0xef, 0x9e, 0x4a, 0x05, 0x85, 0x4a, 0x60,
+ 0x74, 0x86, 0x29, 0x00, 0x90, 0x29, 0x01, 0x86,
+ 0x29, 0x00, 0x81, 0x29, 0x00, 0x84, 0x29, 0x04,
+ 0xbd, 0x1d, 0x20, 0x80, 0x1d, 0x60, 0x0f, 0xac,
+ 0x6b, 0x02, 0x8d, 0x6b, 0x01, 0x89, 0x6b, 0x03,
+ 0x81, 0x6b, 0x60, 0xdf, 0x9e, 0xa1, 0x10, 0xb9,
+ 0xa6, 0x04, 0x80, 0xa6, 0x61, 0x6f, 0xa9, 0x65,
+ 0x60, 0x75, 0xaa, 0x6e, 0x03, 0x80, 0x6e, 0x61,
+ 0x7f, 0x86, 0x27, 0x00, 0x83, 0x27, 0x00, 0x81,
+ 0x27, 0x00, 0x8e, 0x27, 0x00, 0xe0, 0x64, 0x5b,
+ 0x01, 0x8f, 0x5b, 0x28, 0xcb, 0x01, 0x03, 0x89,
+ 0x01, 0x03, 0x81, 0x01, 0x62, 0xb0, 0xc3, 0x19,
+ 0x4b, 0xbc, 0x19, 0x60, 0x61, 0x83, 0x04, 0x00,
+ 0x9a, 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04,
+ 0x01, 0x80, 0x04, 0x00, 0x89, 0x04, 0x00, 0x83,
+ 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x05,
+ 0x80, 0x04, 0x03, 0x80, 0x04, 0x00, 0x80, 0x04,
+ 0x00, 0x80, 0x04, 0x00, 0x82, 0x04, 0x00, 0x81,
+ 0x04, 0x00, 0x80, 0x04, 0x01, 0x80, 0x04, 0x00,
+ 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04,
+ 0x00, 0x80, 0x04, 0x00, 0x81, 0x04, 0x00, 0x80,
+ 0x04, 0x01, 0x83, 0x04, 0x00, 0x86, 0x04, 0x00,
+ 0x83, 0x04, 0x00, 0x83, 0x04, 0x00, 0x80, 0x04,
+ 0x00, 0x89, 0x04, 0x00, 0x90, 0x04, 0x04, 0x82,
+ 0x04, 0x00, 0x84, 0x04, 0x00, 0x90, 0x04, 0x33,
+ 0x81, 0x04, 0x60, 0xad, 0xab, 0x19, 0x03, 0xe0,
+ 0x03, 0x19, 0x0b, 0x8e, 0x19, 0x01, 0x8e, 0x19,
+ 0x00, 0x8e, 0x19, 0x00, 0xa4, 0x19, 0x09, 0xe0,
+ 0x4d, 0x19, 0x37, 0x99, 0x19, 0x80, 0x38, 0x81,
+ 0x19, 0x0c, 0xab, 0x19, 0x03, 0x88, 0x19, 0x06,
+ 0x81, 0x19, 0x0d, 0x85, 0x19, 0x60, 0x39, 0xe3,
+ 0x77, 0x19, 0x03, 0x90, 0x19, 0x02, 0x8c, 0x19,
+ 0x02, 0xe0, 0x16, 0x19, 0x03, 0xde, 0x19, 0x05,
+ 0x8b, 0x19, 0x03, 0x80, 0x19, 0x0e, 0x8b, 0x19,
+ 0x03, 0xb7, 0x19, 0x07, 0x89, 0x19, 0x05, 0xa7,
+ 0x19, 0x07, 0x9d, 0x19, 0x01, 0x8b, 0x19, 0x03,
+ 0x81, 0x19, 0x3d, 0xe0, 0xf3, 0x19, 0x0b, 0x8d,
+ 0x19, 0x01, 0x8c, 0x19, 0x02, 0x89, 0x19, 0x04,
+ 0xb7, 0x19, 0x06, 0x8e, 0x19, 0x01, 0x8a, 0x19,
+ 0x05, 0x88, 0x19, 0x06, 0xe0, 0x32, 0x19, 0x00,
+ 0xe0, 0x05, 0x19, 0x63, 0xa5, 0xf0, 0x96, 0x7f,
+ 0x32, 0x1f, 0xef, 0xd9, 0x32, 0x05, 0xe0, 0x7d,
+ 0x32, 0x01, 0xf0, 0x06, 0x21, 0x32, 0x0d, 0xf0,
+ 0x0c, 0xd0, 0x32, 0x0e, 0xe2, 0x0d, 0x32, 0x69,
+ 0x41, 0xe1, 0xbd, 0x32, 0x65, 0x81, 0xf0, 0x02,
+ 0xea, 0x32, 0x04, 0xef, 0xff, 0x32, 0x7a, 0xcb,
+ 0xf0, 0x80, 0x19, 0x1d, 0xdf, 0x19, 0x60, 0x1f,
+ 0xe0, 0x8f, 0x3a,
};
-static const uint8_t unicode_script_ext_table[828] = {
- 0x82, 0xc1, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x00,
- 0x00, 0x01, 0x2c, 0x1c, 0x00, 0x0c, 0x01, 0x47,
- 0x80, 0x92, 0x00, 0x00, 0x02, 0x1d, 0x6e, 0x00,
- 0x02, 0x1d, 0x29, 0x01, 0x02, 0x1d, 0x47, 0x00,
- 0x02, 0x1d, 0x29, 0x81, 0x03, 0x00, 0x00, 0x06,
- 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1, 0x0d, 0x00,
- 0x00, 0x06, 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1,
- 0x00, 0x03, 0x04, 0x8b, 0x95, 0x01, 0x00, 0x00,
- 0x07, 0x01, 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1,
- 0x1f, 0x00, 0x00, 0x09, 0x01, 0x04, 0x52, 0x53,
- 0x73, 0x7c, 0x32, 0x86, 0x8b, 0x09, 0x00, 0x0a,
- 0x02, 0x04, 0x8b, 0x09, 0x00, 0x09, 0x03, 0x04,
- 0x95, 0xa1, 0x05, 0x00, 0x00, 0x02, 0x04, 0x8b,
- 0x62, 0x00, 0x00, 0x02, 0x04, 0x32, 0x81, 0xfb,
- 0x00, 0x00, 0x0d, 0x0b, 0x20, 0x2b, 0x2d, 0x2f,
- 0x3d, 0x47, 0x51, 0x74, 0x81, 0x92, 0x94, 0x99,
- 0x00, 0x0c, 0x0b, 0x20, 0x2b, 0x2d, 0x2f, 0x3d,
- 0x47, 0x51, 0x74, 0x92, 0x94, 0x99, 0x10, 0x00,
- 0x00, 0x14, 0x0b, 0x20, 0x22, 0x2e, 0x55, 0x2b,
- 0x2d, 0x2f, 0x3d, 0x50, 0x51, 0x63, 0x74, 0x45,
- 0x85, 0x8a, 0x91, 0x92, 0x94, 0x99, 0x00, 0x15,
- 0x0b, 0x20, 0x22, 0x2e, 0x55, 0x2b, 0x2d, 0x2f,
- 0x3d, 0x49, 0x50, 0x51, 0x63, 0x74, 0x45, 0x85,
- 0x8a, 0x91, 0x92, 0x94, 0x99, 0x09, 0x04, 0x20,
- 0x22, 0x3c, 0x50, 0x75, 0x00, 0x09, 0x03, 0x0b,
- 0x15, 0x8a, 0x75, 0x00, 0x09, 0x02, 0x2f, 0x5f,
- 0x75, 0x00, 0x09, 0x02, 0x2d, 0x43, 0x80, 0x75,
- 0x00, 0x0d, 0x02, 0x2b, 0x92, 0x80, 0x71, 0x00,
- 0x09, 0x02, 0x3d, 0x63, 0x82, 0xcf, 0x00, 0x09,
- 0x03, 0x15, 0x60, 0x8e, 0x80, 0x30, 0x00, 0x00,
- 0x02, 0x28, 0x47, 0x85, 0xb8, 0x00, 0x01, 0x04,
- 0x11, 0x33, 0x8d, 0x8c, 0x80, 0x4a, 0x00, 0x01,
- 0x02, 0x5d, 0x7a, 0x00, 0x00, 0x00, 0x02, 0x5d,
- 0x7a, 0x84, 0x49, 0x00, 0x00, 0x04, 0x0b, 0x20,
- 0x2b, 0x3d, 0x00, 0x01, 0x20, 0x00, 0x04, 0x0b,
- 0x20, 0x2b, 0x3d, 0x00, 0x02, 0x20, 0x2b, 0x00,
- 0x01, 0x20, 0x01, 0x02, 0x0b, 0x20, 0x00, 0x02,
- 0x20, 0x81, 0x00, 0x02, 0x0b, 0x20, 0x00, 0x02,
- 0x20, 0x81, 0x00, 0x06, 0x20, 0x3d, 0x51, 0x74,
- 0x92, 0x94, 0x00, 0x01, 0x20, 0x01, 0x02, 0x20,
- 0x81, 0x01, 0x01, 0x20, 0x00, 0x02, 0x20, 0x81,
- 0x00, 0x02, 0x0b, 0x20, 0x06, 0x01, 0x20, 0x00,
- 0x02, 0x20, 0x63, 0x00, 0x02, 0x0b, 0x20, 0x01,
- 0x01, 0x20, 0x00, 0x02, 0x0b, 0x20, 0x03, 0x01,
- 0x20, 0x00, 0x08, 0x0b, 0x20, 0x2b, 0x3d, 0x63,
- 0x74, 0x94, 0x99, 0x00, 0x02, 0x20, 0x2b, 0x00,
- 0x03, 0x20, 0x2b, 0x3d, 0x01, 0x02, 0x0b, 0x20,
- 0x00, 0x01, 0x0b, 0x01, 0x02, 0x20, 0x2b, 0x00,
- 0x01, 0x63, 0x80, 0x44, 0x00, 0x01, 0x01, 0x2c,
- 0x35, 0x00, 0x00, 0x02, 0x1d, 0x8b, 0x00, 0x00,
- 0x00, 0x01, 0x8b, 0x81, 0xb3, 0x00, 0x00, 0x02,
- 0x47, 0x5d, 0x80, 0x3f, 0x00, 0x00, 0x03, 0x20,
- 0x2b, 0x47, 0x8c, 0xd1, 0x00, 0x00, 0x02, 0x1d,
- 0x29, 0x81, 0x3c, 0x00, 0x01, 0x06, 0x0d, 0x31,
- 0x30, 0x36, 0x3e, 0xa2, 0x00, 0x05, 0x0d, 0x31,
- 0x30, 0x36, 0x3e, 0x01, 0x00, 0x00, 0x01, 0x30,
- 0x00, 0x00, 0x09, 0x06, 0x0d, 0x31, 0x30, 0x36,
- 0x3e, 0xa2, 0x00, 0x00, 0x00, 0x05, 0x0d, 0x31,
- 0x30, 0x36, 0x3e, 0x07, 0x06, 0x0d, 0x31, 0x30,
- 0x36, 0x3e, 0xa2, 0x03, 0x05, 0x0d, 0x31, 0x30,
- 0x36, 0x3e, 0x09, 0x00, 0x03, 0x02, 0x0d, 0x30,
- 0x01, 0x00, 0x00, 0x05, 0x0d, 0x31, 0x30, 0x36,
- 0x3e, 0x04, 0x02, 0x36, 0x3e, 0x00, 0x00, 0x00,
- 0x05, 0x0d, 0x31, 0x30, 0x36, 0x3e, 0x03, 0x00,
- 0x01, 0x03, 0x30, 0x36, 0x3e, 0x01, 0x01, 0x30,
- 0x58, 0x00, 0x03, 0x02, 0x36, 0x3e, 0x02, 0x00,
- 0x00, 0x02, 0x36, 0x3e, 0x59, 0x00, 0x00, 0x06,
- 0x0d, 0x31, 0x30, 0x36, 0x3e, 0xa2, 0x00, 0x02,
- 0x36, 0x3e, 0x80, 0x12, 0x00, 0x0f, 0x01, 0x30,
- 0x1f, 0x00, 0x23, 0x01, 0x30, 0x3b, 0x00, 0x27,
- 0x01, 0x30, 0x37, 0x00, 0x30, 0x01, 0x30, 0x0e,
- 0x00, 0x0b, 0x01, 0x30, 0x32, 0x00, 0x00, 0x01,
- 0x30, 0x57, 0x00, 0x18, 0x01, 0x30, 0x09, 0x00,
- 0x04, 0x01, 0x30, 0x5f, 0x00, 0x1e, 0x01, 0x30,
- 0xc0, 0x31, 0xef, 0x00, 0x00, 0x02, 0x1d, 0x29,
- 0x80, 0x0f, 0x00, 0x07, 0x02, 0x30, 0x47, 0x80,
- 0xa7, 0x00, 0x02, 0x0e, 0x20, 0x22, 0x2d, 0x2f,
- 0x43, 0x3d, 0x3c, 0x50, 0x51, 0x5c, 0x63, 0x45,
- 0x91, 0x99, 0x02, 0x0d, 0x20, 0x22, 0x2d, 0x2f,
- 0x43, 0x3d, 0x3c, 0x50, 0x5c, 0x63, 0x45, 0x91,
- 0x99, 0x03, 0x0b, 0x20, 0x22, 0x2d, 0x2f, 0x43,
- 0x3c, 0x50, 0x5c, 0x45, 0x91, 0x99, 0x80, 0x36,
- 0x00, 0x00, 0x02, 0x0b, 0x20, 0x00, 0x00, 0x00,
- 0x02, 0x20, 0x92, 0x39, 0x00, 0x00, 0x03, 0x40,
- 0x47, 0x60, 0x80, 0x1f, 0x00, 0x00, 0x02, 0x10,
- 0x3b, 0xc0, 0x12, 0xed, 0x00, 0x01, 0x02, 0x04,
- 0x66, 0x80, 0x31, 0x00, 0x00, 0x02, 0x04, 0x95,
- 0x09, 0x00, 0x00, 0x02, 0x04, 0x95, 0x46, 0x00,
- 0x01, 0x05, 0x0d, 0x31, 0x30, 0x36, 0x3e, 0x80,
- 0x99, 0x00, 0x04, 0x06, 0x0d, 0x31, 0x30, 0x36,
- 0x3e, 0xa2, 0x09, 0x00, 0x00, 0x02, 0x36, 0x3e,
- 0x2c, 0x00, 0x01, 0x02, 0x36, 0x3e, 0x80, 0xdf,
- 0x00, 0x01, 0x03, 0x1e, 0x1c, 0x4b, 0x00, 0x02,
- 0x1c, 0x4b, 0x03, 0x00, 0x2c, 0x03, 0x1c, 0x4a,
- 0x4b, 0x02, 0x00, 0x08, 0x02, 0x1c, 0x4b, 0x81,
- 0x1f, 0x00, 0x1b, 0x02, 0x04, 0x1a, 0x87, 0x75,
- 0x00, 0x00, 0x02, 0x53, 0x73, 0x87, 0x8d, 0x00,
- 0x00, 0x02, 0x2b, 0x92, 0x00, 0x00, 0x00, 0x02,
- 0x2b, 0x92, 0x36, 0x00, 0x01, 0x02, 0x2b, 0x92,
- 0x8c, 0x12, 0x00, 0x01, 0x02, 0x2b, 0x92, 0x00,
- 0x00, 0x00, 0x02, 0x2b, 0x92, 0xc0, 0x5c, 0x4b,
- 0x00, 0x03, 0x01, 0x23, 0x96, 0x3b, 0x00, 0x11,
- 0x01, 0x30, 0x9e, 0x5d, 0x00, 0x01, 0x01, 0x30,
- 0xce, 0xcd, 0x2d, 0x00,
+static const uint8_t unicode_script_ext_table[1253] = {
+ 0x80, 0x36, 0x00, 0x00, 0x10, 0x06, 0x13, 0x1a,
+ 0x23, 0x25, 0x28, 0x29, 0x2f, 0x2a, 0x2d, 0x32,
+ 0x4a, 0x51, 0x53, 0x72, 0x86, 0x81, 0x83, 0x00,
+ 0x00, 0x07, 0x0b, 0x1d, 0x20, 0x4a, 0x4f, 0x9b,
+ 0xa1, 0x09, 0x00, 0x00, 0x02, 0x0d, 0x4a, 0x00,
+ 0x00, 0x02, 0x02, 0x0d, 0x4a, 0x00, 0x00, 0x00,
+ 0x02, 0x4a, 0x4f, 0x08, 0x00, 0x00, 0x02, 0x4a,
+ 0x9b, 0x00, 0x00, 0x00, 0x02, 0x0d, 0x4a, 0x25,
+ 0x00, 0x00, 0x08, 0x17, 0x1a, 0x1d, 0x2d, 0x4a,
+ 0x72, 0x8e, 0x93, 0x00, 0x08, 0x17, 0x1d, 0x2d,
+ 0x4a, 0x79, 0x8e, 0x93, 0xa0, 0x00, 0x04, 0x17,
+ 0x1d, 0x4a, 0x9d, 0x00, 0x05, 0x29, 0x4a, 0x8e,
+ 0x90, 0x9b, 0x00, 0x0b, 0x14, 0x17, 0x1a, 0x1d,
+ 0x2a, 0x2d, 0x4a, 0x79, 0x90, 0x9d, 0xa0, 0x00,
+ 0x06, 0x1a, 0x25, 0x29, 0x2a, 0x40, 0x4a, 0x00,
+ 0x04, 0x1d, 0x2d, 0x4a, 0x72, 0x00, 0x09, 0x1a,
+ 0x23, 0x37, 0x4a, 0x72, 0x90, 0x93, 0x9d, 0xa0,
+ 0x00, 0x0a, 0x05, 0x1d, 0x23, 0x2a, 0x2d, 0x37,
+ 0x4a, 0x72, 0x90, 0x93, 0x00, 0x02, 0x4a, 0x9d,
+ 0x00, 0x03, 0x23, 0x4a, 0x90, 0x00, 0x04, 0x17,
+ 0x1d, 0x4a, 0x79, 0x00, 0x03, 0x17, 0x4a, 0x93,
+ 0x00, 0x02, 0x4a, 0x8e, 0x00, 0x02, 0x27, 0x4a,
+ 0x00, 0x00, 0x00, 0x02, 0x4a, 0x8e, 0x00, 0x03,
+ 0x1d, 0x4a, 0xa0, 0x00, 0x00, 0x00, 0x04, 0x2d,
+ 0x4a, 0x72, 0xa0, 0x0b, 0x00, 0x00, 0x02, 0x4a,
+ 0x90, 0x01, 0x00, 0x00, 0x05, 0x17, 0x23, 0x40,
+ 0x4a, 0x90, 0x00, 0x04, 0x17, 0x23, 0x4a, 0x90,
+ 0x00, 0x02, 0x4a, 0x90, 0x06, 0x00, 0x00, 0x03,
+ 0x4a, 0x8e, 0x90, 0x00, 0x02, 0x4a, 0x90, 0x00,
+ 0x00, 0x00, 0x03, 0x17, 0x4a, 0x90, 0x00, 0x06,
+ 0x14, 0x17, 0x2a, 0x4a, 0x8e, 0x9b, 0x0f, 0x00,
+ 0x00, 0x01, 0x2d, 0x01, 0x00, 0x00, 0x01, 0x2d,
+ 0x11, 0x00, 0x00, 0x02, 0x4a, 0x79, 0x04, 0x00,
+ 0x00, 0x03, 0x14, 0x4a, 0xa0, 0x03, 0x00, 0x0c,
+ 0x01, 0x4a, 0x03, 0x00, 0x01, 0x02, 0x1a, 0x2d,
+ 0x80, 0x8c, 0x00, 0x00, 0x02, 0x1d, 0x72, 0x00,
+ 0x02, 0x1d, 0x29, 0x01, 0x02, 0x1d, 0x4a, 0x00,
+ 0x02, 0x1d, 0x29, 0x80, 0x80, 0x00, 0x00, 0x03,
+ 0x05, 0x28, 0x29, 0x80, 0x01, 0x00, 0x00, 0x07,
+ 0x04, 0x2b, 0x69, 0x34, 0x90, 0x9a, 0xa8, 0x0d,
+ 0x00, 0x00, 0x07, 0x04, 0x2b, 0x69, 0x34, 0x90,
+ 0x9a, 0xa8, 0x00, 0x03, 0x04, 0x90, 0x9a, 0x01,
+ 0x00, 0x00, 0x08, 0x01, 0x04, 0x2b, 0x69, 0x34,
+ 0x90, 0x9a, 0xa8, 0x1f, 0x00, 0x00, 0x09, 0x01,
+ 0x04, 0x55, 0x56, 0x77, 0x80, 0x34, 0x8a, 0x90,
+ 0x09, 0x00, 0x0a, 0x02, 0x04, 0x90, 0x09, 0x00,
+ 0x09, 0x03, 0x04, 0x9a, 0xa8, 0x05, 0x00, 0x00,
+ 0x02, 0x04, 0x90, 0x62, 0x00, 0x00, 0x02, 0x04,
+ 0x34, 0x81, 0xfb, 0x00, 0x00, 0x0d, 0x0b, 0x20,
+ 0x2c, 0x2e, 0x30, 0x3f, 0x4a, 0x54, 0x78, 0x85,
+ 0x97, 0x99, 0x9e, 0x00, 0x0c, 0x0b, 0x20, 0x2c,
+ 0x2e, 0x30, 0x3f, 0x4a, 0x54, 0x78, 0x97, 0x99,
+ 0x9e, 0x10, 0x00, 0x00, 0x15, 0x0b, 0x20, 0x22,
+ 0x2f, 0x58, 0x2c, 0x2e, 0x30, 0x3f, 0x53, 0x54,
+ 0x66, 0x6e, 0x78, 0x47, 0x89, 0x8f, 0x96, 0x97,
+ 0x99, 0x9e, 0x00, 0x17, 0x0b, 0x20, 0x22, 0x2f,
+ 0x58, 0x2c, 0x2e, 0x31, 0x30, 0x3f, 0x4c, 0x53,
+ 0x54, 0x66, 0x6e, 0x78, 0x47, 0x89, 0x8f, 0x96,
+ 0x97, 0x99, 0x9e, 0x09, 0x04, 0x20, 0x22, 0x3e,
+ 0x53, 0x75, 0x00, 0x09, 0x03, 0x0b, 0x15, 0x8f,
+ 0x75, 0x00, 0x09, 0x02, 0x30, 0x62, 0x75, 0x00,
+ 0x09, 0x02, 0x2e, 0x45, 0x80, 0x75, 0x00, 0x0d,
+ 0x02, 0x2c, 0x97, 0x80, 0x71, 0x00, 0x09, 0x03,
+ 0x3f, 0x66, 0xa2, 0x82, 0xcf, 0x00, 0x09, 0x03,
+ 0x15, 0x63, 0x93, 0x80, 0x30, 0x00, 0x00, 0x03,
+ 0x28, 0x29, 0x4a, 0x85, 0x6e, 0x00, 0x02, 0x01,
+ 0x82, 0x46, 0x00, 0x01, 0x04, 0x11, 0x35, 0x92,
+ 0x91, 0x80, 0x4a, 0x00, 0x01, 0x02, 0x60, 0x7e,
+ 0x00, 0x00, 0x00, 0x02, 0x60, 0x7e, 0x84, 0x49,
+ 0x00, 0x00, 0x04, 0x0b, 0x20, 0x2c, 0x3f, 0x00,
+ 0x01, 0x20, 0x00, 0x04, 0x0b, 0x20, 0x2c, 0x3f,
+ 0x00, 0x03, 0x20, 0x2c, 0x3f, 0x00, 0x01, 0x20,
+ 0x01, 0x02, 0x0b, 0x20, 0x00, 0x02, 0x20, 0x85,
+ 0x00, 0x02, 0x0b, 0x20, 0x00, 0x02, 0x20, 0x85,
+ 0x00, 0x06, 0x20, 0x3f, 0x54, 0x78, 0x97, 0x99,
+ 0x00, 0x01, 0x20, 0x01, 0x02, 0x20, 0x85, 0x01,
+ 0x01, 0x20, 0x00, 0x02, 0x20, 0x85, 0x00, 0x02,
+ 0x0b, 0x20, 0x06, 0x01, 0x20, 0x00, 0x02, 0x20,
+ 0x66, 0x00, 0x02, 0x0b, 0x20, 0x01, 0x01, 0x20,
+ 0x00, 0x02, 0x0b, 0x20, 0x03, 0x01, 0x20, 0x00,
+ 0x0b, 0x0b, 0x20, 0x2c, 0x3f, 0x54, 0x66, 0x78,
+ 0x89, 0x99, 0x9e, 0xa2, 0x00, 0x02, 0x20, 0x2c,
+ 0x00, 0x04, 0x20, 0x2c, 0x3f, 0xa2, 0x01, 0x02,
+ 0x0b, 0x20, 0x00, 0x01, 0x0b, 0x01, 0x02, 0x20,
+ 0x2c, 0x00, 0x01, 0x66, 0x80, 0x44, 0x00, 0x01,
+ 0x01, 0x2d, 0x35, 0x00, 0x00, 0x03, 0x1d, 0x4a,
+ 0x90, 0x00, 0x00, 0x00, 0x01, 0x90, 0x81, 0xb3,
+ 0x00, 0x00, 0x03, 0x4a, 0x60, 0x7e, 0x1e, 0x00,
+ 0x00, 0x02, 0x01, 0x04, 0x09, 0x00, 0x00, 0x06,
+ 0x13, 0x28, 0x29, 0x6f, 0x50, 0x76, 0x01, 0x00,
+ 0x00, 0x04, 0x13, 0x2d, 0x6f, 0x5d, 0x80, 0x11,
+ 0x00, 0x00, 0x03, 0x20, 0x2c, 0x4a, 0x8c, 0xa5,
+ 0x00, 0x00, 0x02, 0x1a, 0x4a, 0x17, 0x00, 0x00,
+ 0x02, 0x06, 0x76, 0x00, 0x07, 0x06, 0x13, 0x28,
+ 0x6f, 0x3e, 0x51, 0x83, 0x09, 0x00, 0x00, 0x01,
+ 0x23, 0x03, 0x00, 0x00, 0x03, 0x01, 0x04, 0x6f,
+ 0x00, 0x00, 0x00, 0x02, 0x1d, 0x29, 0x81, 0x2b,
+ 0x00, 0x0f, 0x02, 0x32, 0x98, 0x00, 0x00, 0x00,
+ 0x07, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60, 0xa9,
+ 0x00, 0x08, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60,
+ 0x7e, 0xa9, 0x00, 0x05, 0x0d, 0x33, 0x32, 0x38,
+ 0x40, 0x01, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00,
+ 0x01, 0x08, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60,
+ 0x9c, 0xa9, 0x01, 0x09, 0x0d, 0x33, 0x32, 0x38,
+ 0x40, 0x4f, 0x60, 0x9c, 0xa9, 0x05, 0x06, 0x0d,
+ 0x33, 0x32, 0x38, 0x40, 0xa9, 0x00, 0x00, 0x00,
+ 0x05, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x07, 0x06,
+ 0x0d, 0x33, 0x32, 0x38, 0x40, 0xa9, 0x03, 0x05,
+ 0x0d, 0x33, 0x32, 0x38, 0x40, 0x09, 0x00, 0x03,
+ 0x02, 0x0d, 0x32, 0x01, 0x00, 0x00, 0x05, 0x0d,
+ 0x33, 0x32, 0x38, 0x40, 0x04, 0x02, 0x38, 0x40,
+ 0x00, 0x00, 0x00, 0x05, 0x0d, 0x33, 0x32, 0x38,
+ 0x40, 0x03, 0x00, 0x01, 0x03, 0x32, 0x38, 0x40,
+ 0x01, 0x01, 0x32, 0x58, 0x00, 0x03, 0x02, 0x38,
+ 0x40, 0x02, 0x00, 0x00, 0x02, 0x38, 0x40, 0x59,
+ 0x00, 0x00, 0x06, 0x0d, 0x33, 0x32, 0x38, 0x40,
+ 0xa9, 0x00, 0x02, 0x38, 0x40, 0x80, 0x12, 0x00,
+ 0x0f, 0x01, 0x32, 0x1f, 0x00, 0x25, 0x01, 0x32,
+ 0x08, 0x00, 0x00, 0x02, 0x32, 0x98, 0x2f, 0x00,
+ 0x27, 0x01, 0x32, 0x37, 0x00, 0x30, 0x01, 0x32,
+ 0x0e, 0x00, 0x0b, 0x01, 0x32, 0x32, 0x00, 0x00,
+ 0x01, 0x32, 0x57, 0x00, 0x18, 0x01, 0x32, 0x09,
+ 0x00, 0x04, 0x01, 0x32, 0x5f, 0x00, 0x1e, 0x01,
+ 0x32, 0xc0, 0x31, 0xef, 0x00, 0x00, 0x02, 0x1d,
+ 0x29, 0x80, 0x0f, 0x00, 0x07, 0x02, 0x32, 0x4a,
+ 0x80, 0xa7, 0x00, 0x02, 0x10, 0x20, 0x22, 0x2e,
+ 0x30, 0x45, 0x3f, 0x3e, 0x53, 0x54, 0x5f, 0x66,
+ 0x85, 0x47, 0x96, 0x9e, 0xa2, 0x02, 0x0f, 0x20,
+ 0x22, 0x2e, 0x30, 0x45, 0x3f, 0x3e, 0x53, 0x5f,
+ 0x66, 0x85, 0x47, 0x96, 0x9e, 0xa2, 0x01, 0x0b,
+ 0x20, 0x22, 0x2e, 0x30, 0x45, 0x3e, 0x53, 0x5f,
+ 0x47, 0x96, 0x9e, 0x00, 0x0c, 0x20, 0x22, 0x2e,
+ 0x30, 0x45, 0x3e, 0x53, 0x5f, 0x85, 0x47, 0x96,
+ 0x9e, 0x00, 0x0b, 0x20, 0x22, 0x2e, 0x30, 0x45,
+ 0x3e, 0x53, 0x5f, 0x47, 0x96, 0x9e, 0x80, 0x36,
+ 0x00, 0x00, 0x03, 0x0b, 0x20, 0xa2, 0x00, 0x00,
+ 0x00, 0x02, 0x20, 0x97, 0x39, 0x00, 0x00, 0x03,
+ 0x42, 0x4a, 0x63, 0x80, 0x1f, 0x00, 0x00, 0x02,
+ 0x10, 0x3d, 0xc0, 0x12, 0xed, 0x00, 0x01, 0x02,
+ 0x04, 0x69, 0x80, 0x31, 0x00, 0x00, 0x02, 0x04,
+ 0x9a, 0x09, 0x00, 0x00, 0x02, 0x04, 0x9a, 0x46,
+ 0x00, 0x01, 0x05, 0x0d, 0x33, 0x32, 0x38, 0x40,
+ 0x80, 0x99, 0x00, 0x04, 0x06, 0x0d, 0x33, 0x32,
+ 0x38, 0x40, 0xa9, 0x09, 0x00, 0x00, 0x02, 0x38,
+ 0x40, 0x2c, 0x00, 0x01, 0x02, 0x38, 0x40, 0x80,
+ 0xdf, 0x00, 0x01, 0x03, 0x1e, 0x1c, 0x4e, 0x00,
+ 0x02, 0x1c, 0x4e, 0x03, 0x00, 0x2c, 0x03, 0x1c,
+ 0x4d, 0x4e, 0x02, 0x00, 0x08, 0x02, 0x1c, 0x4e,
+ 0x81, 0x1f, 0x00, 0x1b, 0x02, 0x04, 0x1a, 0x87,
+ 0x75, 0x00, 0x00, 0x02, 0x56, 0x77, 0x87, 0x8d,
+ 0x00, 0x00, 0x02, 0x2c, 0x97, 0x00, 0x00, 0x00,
+ 0x02, 0x2c, 0x97, 0x36, 0x00, 0x01, 0x02, 0x2c,
+ 0x97, 0x8c, 0x12, 0x00, 0x01, 0x02, 0x2c, 0x97,
+ 0x00, 0x00, 0x00, 0x02, 0x2c, 0x97, 0xc0, 0x5c,
+ 0x4b, 0x00, 0x03, 0x01, 0x23, 0x96, 0x3b, 0x00,
+ 0x11, 0x01, 0x32, 0x9e, 0x5d, 0x00, 0x01, 0x01,
+ 0x32, 0xce, 0xcd, 0x2d, 0x00,
};
static const uint8_t unicode_prop_Hyphen_table[28] = {
@@ -3721,61 +3788,63 @@ static const uint8_t unicode_prop_Other_Math_table[200] = {
0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90,
};
-static const uint8_t unicode_prop_Other_Alphabetic_table[428] = {
- 0x43, 0x44, 0x80, 0x42, 0x69, 0x8d, 0x00, 0x01,
- 0x01, 0x00, 0xc7, 0x8a, 0xaf, 0x8c, 0x06, 0x8f,
- 0x80, 0xe4, 0x33, 0x19, 0x0b, 0x80, 0xa2, 0x80,
- 0x9d, 0x8f, 0xe5, 0x8a, 0xe4, 0x0a, 0x88, 0x02,
- 0x03, 0x40, 0xa6, 0x8b, 0x16, 0x85, 0x93, 0xb5,
- 0x09, 0x8e, 0x01, 0x22, 0x89, 0x81, 0x9c, 0x82,
- 0xb9, 0x31, 0x09, 0x81, 0x89, 0x80, 0x89, 0x81,
- 0x9c, 0x82, 0xb9, 0x23, 0x09, 0x0b, 0x80, 0x9d,
- 0x0a, 0x80, 0x8a, 0x82, 0xb9, 0x38, 0x10, 0x81,
- 0x94, 0x81, 0x95, 0x13, 0x82, 0xb9, 0x31, 0x09,
- 0x81, 0x88, 0x81, 0x89, 0x81, 0x9d, 0x80, 0xba,
- 0x22, 0x10, 0x82, 0x89, 0x80, 0xa7, 0x84, 0xb8,
- 0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x9c, 0x82,
- 0xb9, 0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x8e,
- 0x80, 0x8b, 0x83, 0xb9, 0x30, 0x10, 0x82, 0x89,
- 0x80, 0x89, 0x81, 0x9c, 0x82, 0xca, 0x28, 0x00,
- 0x87, 0x91, 0x81, 0xbc, 0x01, 0x86, 0x91, 0x80,
- 0xe2, 0x01, 0x28, 0x81, 0x8f, 0x80, 0x40, 0xa2,
- 0x92, 0x88, 0x8a, 0x80, 0xa3, 0xed, 0x8b, 0x00,
- 0x0b, 0x96, 0x1b, 0x10, 0x11, 0x32, 0x83, 0x8c,
- 0x8b, 0x00, 0x89, 0x83, 0x46, 0x73, 0x81, 0x9d,
- 0x81, 0x9d, 0x81, 0x9d, 0x81, 0xc1, 0x92, 0x40,
- 0xbb, 0x81, 0xa1, 0x80, 0xf5, 0x8b, 0x83, 0x88,
- 0x40, 0xdd, 0x84, 0xb8, 0x89, 0x81, 0x93, 0xc9,
- 0x81, 0x8a, 0x82, 0xb0, 0x84, 0xaf, 0x8e, 0xbb,
- 0x82, 0x9d, 0x88, 0x09, 0xb8, 0x8a, 0xb1, 0x92,
- 0x41, 0xaf, 0x8d, 0x46, 0xc0, 0xb3, 0x48, 0xf5,
- 0x9f, 0x60, 0x78, 0x73, 0x87, 0xa1, 0x81, 0x41,
- 0x61, 0x07, 0x80, 0x96, 0x84, 0xd7, 0x81, 0xb1,
- 0x8f, 0x00, 0xb8, 0x80, 0xa5, 0x84, 0x9b, 0x8b,
- 0xac, 0x83, 0xaf, 0x8b, 0xa4, 0x80, 0xc2, 0x8d,
- 0x8b, 0x07, 0x81, 0xac, 0x82, 0xb1, 0x00, 0x11,
- 0x0c, 0x80, 0xab, 0x24, 0x80, 0x40, 0xec, 0x87,
- 0x60, 0x4f, 0x32, 0x80, 0x48, 0x56, 0x84, 0x46,
- 0x85, 0x10, 0x0c, 0x83, 0x43, 0x13, 0x83, 0x41,
- 0x82, 0x81, 0x41, 0x52, 0x82, 0xb4, 0x8d, 0xac,
- 0x81, 0x8a, 0x82, 0xac, 0x88, 0x88, 0x80, 0xbc,
- 0x82, 0xa3, 0x8b, 0x91, 0x81, 0xb8, 0x82, 0xaf,
- 0x8c, 0x8d, 0x81, 0xdb, 0x88, 0x08, 0x28, 0x08,
- 0x40, 0x9c, 0x89, 0x96, 0x83, 0xb9, 0x31, 0x09,
- 0x81, 0x89, 0x80, 0x89, 0x81, 0x40, 0xd0, 0x8c,
- 0x02, 0xe9, 0x91, 0x40, 0xec, 0x31, 0x86, 0x9c,
- 0x81, 0xd1, 0x8e, 0x00, 0xe9, 0x8a, 0xe6, 0x8d,
- 0x41, 0x00, 0x8c, 0x40, 0xf6, 0x28, 0x09, 0x0a,
- 0x00, 0x80, 0x40, 0x8d, 0x31, 0x2b, 0x80, 0x9b,
- 0x89, 0xa9, 0x20, 0x83, 0x91, 0x8a, 0xad, 0x8d,
- 0x41, 0x96, 0x38, 0x86, 0xd2, 0x95, 0x80, 0x8d,
- 0xf9, 0x2a, 0x00, 0x08, 0x10, 0x02, 0x80, 0xc1,
- 0x20, 0x08, 0x83, 0x41, 0x5b, 0x83, 0x88, 0x08,
- 0x80, 0xaf, 0x32, 0x82, 0x60, 0x50, 0x0d, 0x00,
- 0xb6, 0x33, 0xdc, 0x81, 0x60, 0x4c, 0xab, 0x80,
- 0x60, 0x23, 0x60, 0x30, 0x90, 0x0e, 0x01, 0x04,
- 0xe3, 0x80, 0x48, 0xb6, 0x80, 0x47, 0xe7, 0x99,
- 0x85, 0x99, 0x85, 0x99,
+static const uint8_t unicode_prop_Other_Alphabetic_table[443] = {
+ 0x43, 0x44, 0x80, 0x9c, 0x8c, 0x42, 0x3f, 0x8d,
+ 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf, 0x8c,
+ 0x06, 0x8f, 0x80, 0xe4, 0x33, 0x19, 0x0b, 0x80,
+ 0xa2, 0x80, 0x9d, 0x8f, 0xe5, 0x8a, 0xe4, 0x0a,
+ 0x88, 0x02, 0x03, 0xe9, 0x80, 0xbb, 0x8b, 0x16,
+ 0x85, 0x93, 0xb5, 0x09, 0x8e, 0x01, 0x22, 0x89,
+ 0x81, 0x9c, 0x82, 0xb9, 0x31, 0x09, 0x81, 0x89,
+ 0x80, 0x89, 0x81, 0x9c, 0x82, 0xb9, 0x23, 0x09,
+ 0x0b, 0x80, 0x9d, 0x0a, 0x80, 0x8a, 0x82, 0xb9,
+ 0x38, 0x10, 0x81, 0x94, 0x81, 0x95, 0x13, 0x82,
+ 0xb9, 0x31, 0x09, 0x81, 0x88, 0x81, 0x89, 0x81,
+ 0x9d, 0x80, 0xba, 0x22, 0x10, 0x82, 0x89, 0x80,
+ 0xa7, 0x84, 0xb8, 0x30, 0x10, 0x17, 0x81, 0x8a,
+ 0x81, 0x9c, 0x82, 0xb9, 0x30, 0x10, 0x17, 0x81,
+ 0x8a, 0x81, 0x8e, 0x80, 0x8b, 0x83, 0xb9, 0x30,
+ 0x10, 0x82, 0x89, 0x80, 0x89, 0x81, 0x9c, 0x82,
+ 0xca, 0x28, 0x00, 0x87, 0x91, 0x81, 0xbc, 0x01,
+ 0x86, 0x91, 0x80, 0xe2, 0x01, 0x28, 0x81, 0x8f,
+ 0x80, 0x40, 0xa2, 0x92, 0x88, 0x8a, 0x80, 0xa3,
+ 0xed, 0x8b, 0x00, 0x0b, 0x96, 0x1b, 0x10, 0x11,
+ 0x32, 0x83, 0x8c, 0x8b, 0x00, 0x89, 0x83, 0x46,
+ 0x73, 0x81, 0x9d, 0x81, 0x9d, 0x81, 0x9d, 0x81,
+ 0xc1, 0x92, 0x40, 0xbb, 0x81, 0xa1, 0x80, 0xf5,
+ 0x8b, 0x83, 0x88, 0x40, 0xdd, 0x84, 0xb8, 0x89,
+ 0x81, 0x93, 0xc9, 0x81, 0x8a, 0x82, 0xb0, 0x84,
+ 0xaf, 0x8e, 0xbb, 0x82, 0x9d, 0x88, 0x09, 0xb8,
+ 0x8a, 0xb1, 0x92, 0x41, 0x9b, 0xa1, 0x46, 0xc0,
+ 0xb3, 0x48, 0xf5, 0x9f, 0x60, 0x78, 0x73, 0x87,
+ 0xa1, 0x81, 0x41, 0x61, 0x07, 0x80, 0x96, 0x84,
+ 0xd7, 0x81, 0xb1, 0x8f, 0x00, 0xb8, 0x80, 0xa5,
+ 0x84, 0x9b, 0x8b, 0xac, 0x83, 0xaf, 0x8b, 0xa4,
+ 0x80, 0xc2, 0x8d, 0x8b, 0x07, 0x81, 0xac, 0x82,
+ 0xb1, 0x00, 0x11, 0x0c, 0x80, 0xab, 0x24, 0x80,
+ 0x40, 0xec, 0x87, 0x60, 0x4f, 0x32, 0x80, 0x48,
+ 0x56, 0x84, 0x46, 0x85, 0x10, 0x0c, 0x83, 0x43,
+ 0x13, 0x83, 0xc0, 0x80, 0x41, 0x40, 0x81, 0xce,
+ 0x80, 0x41, 0x02, 0x82, 0xb4, 0x8d, 0xac, 0x81,
+ 0x8a, 0x82, 0xac, 0x88, 0x88, 0x80, 0xbc, 0x82,
+ 0xa3, 0x8b, 0x91, 0x81, 0xb8, 0x82, 0xaf, 0x8c,
+ 0x8d, 0x81, 0xdb, 0x88, 0x08, 0x28, 0x08, 0x40,
+ 0x9c, 0x89, 0x96, 0x83, 0xb9, 0x31, 0x09, 0x81,
+ 0x89, 0x80, 0x89, 0x81, 0xd3, 0x88, 0x00, 0x08,
+ 0x03, 0x01, 0xe6, 0x8c, 0x02, 0xe9, 0x91, 0x40,
+ 0xec, 0x31, 0x86, 0x9c, 0x81, 0xd1, 0x8e, 0x00,
+ 0xe9, 0x8a, 0xe6, 0x8d, 0x41, 0x00, 0x8c, 0x40,
+ 0xf6, 0x28, 0x09, 0x0a, 0x00, 0x80, 0x40, 0x8d,
+ 0x31, 0x2b, 0x80, 0x9b, 0x89, 0xa9, 0x20, 0x83,
+ 0x91, 0x8a, 0xad, 0x8d, 0x41, 0x96, 0x38, 0x86,
+ 0xd2, 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00, 0x08,
+ 0x10, 0x02, 0x80, 0xc1, 0x20, 0x08, 0x83, 0x41,
+ 0x5b, 0x83, 0x88, 0x08, 0x80, 0xaf, 0x32, 0x82,
+ 0x60, 0x41, 0xdc, 0x90, 0x4e, 0x1f, 0x00, 0xb6,
+ 0x33, 0xdc, 0x81, 0x60, 0x4c, 0xab, 0x80, 0x60,
+ 0x23, 0x60, 0x30, 0x90, 0x0e, 0x01, 0x04, 0xe3,
+ 0x80, 0x48, 0xb6, 0x80, 0x47, 0xe7, 0x99, 0x85,
+ 0x99, 0x85, 0x99,
};
static const uint8_t unicode_prop_Other_Lowercase_table[69] = {
@@ -3795,16 +3864,21 @@ static const uint8_t unicode_prop_Other_Uppercase_table[15] = {
0xcc, 0x5f, 0x99, 0x85, 0x99, 0x85, 0x99,
};
-static const uint8_t unicode_prop_Other_Grapheme_Extend_table[65] = {
+static const uint8_t unicode_prop_Other_Grapheme_Extend_table[112] = {
0x49, 0xbd, 0x80, 0x97, 0x80, 0x41, 0x65, 0x80,
- 0x97, 0x80, 0xe5, 0x80, 0x97, 0x80, 0x40, 0xe9,
- 0x80, 0x91, 0x81, 0xe6, 0x80, 0x97, 0x80, 0xf6,
- 0x80, 0x8e, 0x80, 0x4d, 0x54, 0x80, 0x44, 0xd5,
- 0x80, 0x50, 0x20, 0x81, 0x60, 0xcf, 0x6d, 0x81,
- 0x53, 0x9d, 0x80, 0x97, 0x80, 0x41, 0x57, 0x80,
- 0x8b, 0x80, 0x40, 0xf0, 0x80, 0x43, 0x7f, 0x80,
- 0x60, 0xb8, 0x33, 0x07, 0x84, 0x6c, 0x2e, 0xac,
- 0xdf,
+ 0x97, 0x80, 0xe5, 0x80, 0x97, 0x80, 0x40, 0xe7,
+ 0x00, 0x03, 0x08, 0x81, 0x88, 0x81, 0xe6, 0x80,
+ 0x97, 0x80, 0xf6, 0x80, 0x8e, 0x80, 0x49, 0x34,
+ 0x80, 0x9d, 0x80, 0x43, 0xff, 0x04, 0x00, 0x04,
+ 0x81, 0xe4, 0x80, 0xc6, 0x81, 0x44, 0x17, 0x80,
+ 0x50, 0x20, 0x81, 0x60, 0x79, 0x22, 0x80, 0xeb,
+ 0x80, 0x60, 0x55, 0xdc, 0x81, 0x52, 0x1f, 0x80,
+ 0xf3, 0x80, 0x41, 0x07, 0x80, 0x8d, 0x80, 0x88,
+ 0x80, 0xdf, 0x80, 0x88, 0x01, 0x00, 0x14, 0x80,
+ 0x40, 0xdf, 0x80, 0x8b, 0x80, 0x40, 0xf0, 0x80,
+ 0x41, 0x05, 0x80, 0x42, 0x78, 0x80, 0x8b, 0x80,
+ 0x46, 0x02, 0x80, 0x60, 0x50, 0xad, 0x81, 0x60,
+ 0x61, 0x72, 0x0d, 0x85, 0x6c, 0x2e, 0xac, 0xdf,
};
static const uint8_t unicode_prop_Other_Default_Ignorable_Code_Point_table[32] = {
@@ -3819,9 +3893,10 @@ static const uint8_t unicode_prop_Other_ID_Start_table[11] = {
0x4f, 0x6b, 0x81,
};
-static const uint8_t unicode_prop_Other_ID_Continue_table[12] = {
+static const uint8_t unicode_prop_Other_ID_Continue_table[22] = {
0x40, 0xb6, 0x80, 0x42, 0xce, 0x80, 0x4f, 0xe0,
- 0x88, 0x46, 0x67, 0x80,
+ 0x88, 0x46, 0x67, 0x80, 0x46, 0x30, 0x81, 0x50,
+ 0xec, 0x80, 0x60, 0xce, 0x68, 0x80,
};
static const uint8_t unicode_prop_Prepended_Concatenation_Mark_table[19] = {
@@ -3856,7 +3931,7 @@ static const uint8_t unicode_prop_Changes_When_Casefolded1_table[29] = {
0x89, 0x10, 0x81, 0x8d, 0x80,
};
-static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[447] = {
+static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[450] = {
0x40, 0x9f, 0x06, 0x00, 0x01, 0x00, 0x01, 0x12,
0x10, 0x82, 0xf3, 0x80, 0x8b, 0x80, 0x40, 0x84,
0x01, 0x01, 0x80, 0xa2, 0x01, 0x80, 0x40, 0xbb,
@@ -3898,21 +3973,22 @@ static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[447] = {
0x92, 0x03, 0x1a, 0x00, 0x80, 0x40, 0x86, 0x08,
0x80, 0x9f, 0x99, 0x40, 0x83, 0x15, 0x0d, 0x0d,
0x0a, 0x16, 0x06, 0x80, 0x88, 0x47, 0x87, 0x20,
- 0xa9, 0x80, 0x88, 0x60, 0xb4, 0xe4, 0x83, 0x54,
- 0xb9, 0x86, 0x8d, 0x87, 0xbf, 0x85, 0x42, 0x3e,
- 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80,
- 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06,
- 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80, 0x41,
- 0x53, 0x81, 0x41, 0x23, 0x81, 0xb1, 0x48, 0x2f,
- 0xbd, 0x4d, 0x91, 0x18, 0x9a, 0x01, 0x00, 0x08,
- 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, 0x18, 0x00,
- 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00,
- 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90,
- 0x42, 0x43, 0x8a, 0x84, 0x9e, 0x80, 0x9f, 0x99,
- 0x82, 0xa2, 0x80, 0xee, 0x82, 0x8c, 0xab, 0x83,
- 0x88, 0x31, 0x49, 0x9d, 0x89, 0x60, 0xfc, 0x05,
- 0x42, 0x1d, 0x6b, 0x05, 0xe1, 0x4f, 0xff,
+ 0xa9, 0x80, 0x88, 0x60, 0xb4, 0xe4, 0x83, 0x50,
+ 0x31, 0xa3, 0x44, 0x63, 0x86, 0x8d, 0x87, 0xbf,
+ 0x85, 0x42, 0x3e, 0xd4, 0x80, 0xc6, 0x01, 0x08,
+ 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0,
+ 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00,
+ 0x16, 0x80, 0x41, 0x53, 0x81, 0x41, 0x23, 0x81,
+ 0xb1, 0x48, 0x2f, 0xbd, 0x4d, 0x91, 0x18, 0x9a,
+ 0x01, 0x00, 0x08, 0x80, 0x89, 0x03, 0x00, 0x00,
+ 0x28, 0x18, 0x00, 0x00, 0x02, 0x01, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x06,
+ 0x03, 0x03, 0x00, 0x80, 0x89, 0x80, 0x90, 0x22,
+ 0x04, 0x80, 0x90, 0x42, 0x43, 0x8a, 0x84, 0x9e,
+ 0x80, 0x9f, 0x99, 0x82, 0xa2, 0x80, 0xee, 0x82,
+ 0x8c, 0xab, 0x83, 0x88, 0x31, 0x49, 0x9d, 0x89,
+ 0x60, 0xfc, 0x05, 0x42, 0x1d, 0x6b, 0x05, 0xe1,
+ 0x4f, 0xff,
};
static const uint8_t unicode_prop_ASCII_Hex_Digit_table[5] = {
@@ -3924,14 +4000,15 @@ static const uint8_t unicode_prop_Bidi_Control_table[10] = {
0xb6, 0x83,
};
-static const uint8_t unicode_prop_Dash_table[55] = {
+static const uint8_t unicode_prop_Dash_table[58] = {
0xac, 0x80, 0x45, 0x5b, 0x80, 0xb2, 0x80, 0x4e,
0x40, 0x80, 0x44, 0x04, 0x80, 0x48, 0x08, 0x85,
0xbc, 0x80, 0xa6, 0x80, 0x8e, 0x80, 0x41, 0x85,
0x80, 0x4c, 0x03, 0x01, 0x80, 0x9e, 0x0b, 0x80,
0x9b, 0x80, 0x41, 0xbd, 0x80, 0x92, 0x80, 0xee,
0x80, 0x60, 0xcd, 0x8f, 0x81, 0xa4, 0x80, 0x89,
- 0x80, 0x40, 0xa8, 0x80, 0x4f, 0x9e, 0x80,
+ 0x80, 0x40, 0xa8, 0x80, 0x4e, 0x5f, 0x80, 0x41,
+ 0x3d, 0x80,
};
static const uint8_t unicode_prop_Deprecated_table[23] = {
@@ -3940,7 +4017,7 @@ static const uint8_t unicode_prop_Deprecated_table[23] = {
0x42, 0xb8, 0x81, 0x6d, 0xdc, 0xd5, 0x80,
};
-static const uint8_t unicode_prop_Diacritic_table[399] = {
+static const uint8_t unicode_prop_Diacritic_table[438] = {
0xdd, 0x00, 0x80, 0xc6, 0x05, 0x03, 0x01, 0x81,
0x41, 0xf6, 0x40, 0x9e, 0x07, 0x25, 0x90, 0x0b,
0x80, 0x88, 0x81, 0x40, 0xfc, 0x84, 0x40, 0xd0,
@@ -3953,59 +4030,66 @@ static const uint8_t unicode_prop_Diacritic_table[399] = {
0x8f, 0x80, 0xae, 0x82, 0xbb, 0x80, 0x8f, 0x06,
0x80, 0xf6, 0x80, 0xed, 0x80, 0x8f, 0x80, 0xed,
0x80, 0x8f, 0x80, 0xec, 0x81, 0x8f, 0x80, 0xfb,
- 0x80, 0xfb, 0x28, 0x80, 0xea, 0x80, 0x8c, 0x84,
- 0xca, 0x81, 0x9a, 0x00, 0x00, 0x03, 0x81, 0xc1,
- 0x10, 0x81, 0xbd, 0x80, 0xef, 0x00, 0x81, 0xa7,
- 0x0b, 0x84, 0x98, 0x30, 0x80, 0x89, 0x81, 0x42,
- 0xc0, 0x82, 0x43, 0xb3, 0x81, 0x40, 0xb2, 0x8a,
- 0x88, 0x80, 0x41, 0x5a, 0x82, 0x41, 0x38, 0x39,
- 0x80, 0xaf, 0x8e, 0x81, 0x8a, 0xe7, 0x80, 0x8e,
- 0x80, 0xa5, 0x88, 0xb5, 0x81, 0x40, 0x89, 0x81,
- 0xbf, 0x85, 0xd1, 0x98, 0x18, 0x28, 0x0a, 0xb1,
- 0xbe, 0xd8, 0x8b, 0xa4, 0x8a, 0x41, 0xbc, 0x00,
- 0x82, 0x8a, 0x82, 0x8c, 0x82, 0x8c, 0x82, 0x8c,
- 0x81, 0x4c, 0xef, 0x82, 0x41, 0x3c, 0x80, 0x41,
- 0xf9, 0x85, 0xe8, 0x83, 0xde, 0x80, 0x60, 0x75,
- 0x71, 0x80, 0x8b, 0x08, 0x80, 0x9b, 0x81, 0xd1,
- 0x81, 0x8d, 0xa1, 0xe5, 0x82, 0xec, 0x81, 0x40,
- 0xc9, 0x80, 0x9a, 0x91, 0xb8, 0x83, 0xa3, 0x80,
- 0xde, 0x80, 0x8b, 0x80, 0xa3, 0x80, 0x40, 0x94,
- 0x82, 0xc0, 0x83, 0xb2, 0x80, 0xe3, 0x84, 0x88,
- 0x82, 0xff, 0x81, 0x60, 0x4f, 0x2f, 0x80, 0x43,
- 0x00, 0x8f, 0x41, 0x0d, 0x00, 0x80, 0xae, 0x80,
- 0xac, 0x81, 0xc2, 0x80, 0x42, 0xfb, 0x80, 0x44,
- 0x9e, 0x28, 0xa9, 0x80, 0x88, 0x43, 0x29, 0x81,
- 0x42, 0x3a, 0x85, 0x41, 0xd4, 0x82, 0xc5, 0x8a,
- 0xb0, 0x83, 0x40, 0xbf, 0x80, 0xa8, 0x80, 0xc7,
- 0x81, 0xf7, 0x81, 0xbd, 0x80, 0xcb, 0x80, 0x88,
- 0x82, 0xe7, 0x81, 0x40, 0xb1, 0x81, 0xd0, 0x80,
- 0x8f, 0x80, 0x97, 0x32, 0x84, 0x40, 0xcc, 0x02,
- 0x80, 0xfa, 0x81, 0x40, 0xfa, 0x81, 0xfd, 0x80,
- 0xf5, 0x81, 0xf2, 0x80, 0x41, 0x0c, 0x81, 0x41,
- 0x01, 0x0b, 0x80, 0x40, 0x9b, 0x80, 0xd2, 0x80,
- 0x91, 0x80, 0xd0, 0x80, 0x41, 0xa4, 0x80, 0x41,
- 0x01, 0x00, 0x81, 0xd0, 0x80, 0x56, 0xae, 0x8e,
- 0x60, 0x36, 0x99, 0x84, 0xba, 0x86, 0x44, 0x57,
- 0x90, 0xcf, 0x81, 0x60, 0x3f, 0xfd, 0x18, 0x30,
- 0x81, 0x5f, 0x00, 0xad, 0x81, 0x96, 0x42, 0x1f,
- 0x12, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x4e, 0x81,
- 0xbd, 0x40, 0xc1, 0x86, 0x41, 0x76, 0x80, 0xbc,
- 0x83, 0x45, 0xdf, 0x86, 0xec, 0x10, 0x82,
+ 0x80, 0xee, 0x80, 0x8b, 0x28, 0x80, 0xea, 0x80,
+ 0x8c, 0x84, 0xca, 0x81, 0x9a, 0x00, 0x00, 0x03,
+ 0x81, 0xc1, 0x10, 0x81, 0xbd, 0x80, 0xef, 0x00,
+ 0x81, 0xa7, 0x0b, 0x84, 0x98, 0x30, 0x80, 0x89,
+ 0x81, 0x42, 0xc0, 0x82, 0x43, 0xb3, 0x81, 0x9d,
+ 0x80, 0x40, 0x93, 0x8a, 0x88, 0x80, 0x41, 0x5a,
+ 0x82, 0x41, 0x23, 0x80, 0x93, 0x39, 0x80, 0xaf,
+ 0x8e, 0x81, 0x8a, 0xe7, 0x80, 0x8e, 0x80, 0xa5,
+ 0x88, 0xb5, 0x81, 0xb9, 0x80, 0x8a, 0x81, 0xc1,
+ 0x81, 0xbf, 0x85, 0xd1, 0x98, 0x18, 0x28, 0x0a,
+ 0xb1, 0xbe, 0xd8, 0x8b, 0xa4, 0x8a, 0x41, 0xbc,
+ 0x00, 0x82, 0x8a, 0x82, 0x8c, 0x82, 0x8c, 0x82,
+ 0x8c, 0x81, 0x4c, 0xef, 0x82, 0x41, 0x3c, 0x80,
+ 0x41, 0xf9, 0x85, 0xe8, 0x83, 0xde, 0x80, 0x60,
+ 0x75, 0x71, 0x80, 0x8b, 0x08, 0x80, 0x9b, 0x81,
+ 0xd1, 0x81, 0x8d, 0xa1, 0xe5, 0x82, 0xec, 0x81,
+ 0x8b, 0x80, 0xa4, 0x80, 0x40, 0x96, 0x80, 0x9a,
+ 0x91, 0xb8, 0x83, 0xa3, 0x80, 0xde, 0x80, 0x8b,
+ 0x80, 0xa3, 0x80, 0x40, 0x94, 0x82, 0xc0, 0x83,
+ 0xb2, 0x80, 0xe3, 0x84, 0x88, 0x82, 0xff, 0x81,
+ 0x60, 0x4f, 0x2f, 0x80, 0x43, 0x00, 0x8f, 0x41,
+ 0x0d, 0x00, 0x80, 0xae, 0x80, 0xac, 0x81, 0xc2,
+ 0x80, 0x42, 0xfb, 0x80, 0x44, 0x9e, 0x28, 0xa9,
+ 0x80, 0x88, 0x42, 0x7c, 0x13, 0x80, 0x40, 0xa4,
+ 0x81, 0x42, 0x3a, 0x85, 0xa5, 0x80, 0x99, 0x84,
+ 0x41, 0x8e, 0x82, 0xc5, 0x8a, 0xb0, 0x83, 0x40,
+ 0xbf, 0x80, 0xa8, 0x80, 0xc7, 0x81, 0xf7, 0x81,
+ 0xbd, 0x80, 0xcb, 0x80, 0x88, 0x82, 0xe7, 0x81,
+ 0x40, 0xb1, 0x81, 0xcf, 0x81, 0x8f, 0x80, 0x97,
+ 0x32, 0x84, 0xd8, 0x10, 0x81, 0x8c, 0x81, 0xde,
+ 0x02, 0x80, 0xfa, 0x81, 0x40, 0xfa, 0x81, 0xfd,
+ 0x80, 0xf5, 0x81, 0xf2, 0x80, 0x41, 0x0c, 0x81,
+ 0x41, 0x01, 0x0b, 0x80, 0x40, 0x9b, 0x80, 0xd2,
+ 0x80, 0x91, 0x80, 0xd0, 0x80, 0x41, 0xa4, 0x80,
+ 0x41, 0x01, 0x00, 0x81, 0xd0, 0x80, 0x41, 0xa8,
+ 0x81, 0x96, 0x80, 0x54, 0xeb, 0x8e, 0x60, 0x2c,
+ 0xd8, 0x80, 0x49, 0xbf, 0x84, 0xba, 0x86, 0x42,
+ 0x33, 0x81, 0x42, 0x21, 0x90, 0xcf, 0x81, 0x60,
+ 0x3f, 0xfd, 0x18, 0x30, 0x81, 0x5f, 0x00, 0xad,
+ 0x81, 0x96, 0x42, 0x1f, 0x12, 0x2f, 0x39, 0x86,
+ 0x9d, 0x83, 0x4e, 0x81, 0xbd, 0x40, 0xc1, 0x86,
+ 0x41, 0x76, 0x80, 0xbc, 0x83, 0x42, 0xfd, 0x81,
+ 0x42, 0xdf, 0x86, 0xec, 0x10, 0x82,
};
-static const uint8_t unicode_prop_Extender_table[92] = {
+static const uint8_t unicode_prop_Extender_table[111] = {
0x40, 0xb6, 0x80, 0x42, 0x17, 0x81, 0x43, 0x6d,
- 0x80, 0x41, 0xb8, 0x80, 0x43, 0x59, 0x80, 0x42,
- 0xef, 0x80, 0xfe, 0x80, 0x49, 0x42, 0x80, 0xb7,
- 0x80, 0x42, 0x62, 0x80, 0x41, 0x8d, 0x80, 0xc3,
- 0x80, 0x53, 0x88, 0x80, 0xaa, 0x84, 0xe6, 0x81,
- 0xdc, 0x82, 0x60, 0x6f, 0x15, 0x80, 0x45, 0xf5,
- 0x80, 0x43, 0xc1, 0x80, 0x95, 0x80, 0x40, 0x88,
- 0x80, 0xeb, 0x80, 0x94, 0x81, 0x60, 0x54, 0x7a,
- 0x80, 0x48, 0x0f, 0x81, 0x4b, 0xd9, 0x80, 0x42,
- 0x67, 0x82, 0x44, 0xce, 0x80, 0x60, 0x50, 0xa8,
+ 0x80, 0x41, 0xb8, 0x80, 0x42, 0x75, 0x80, 0x40,
+ 0x88, 0x80, 0xd8, 0x80, 0x42, 0xef, 0x80, 0xfe,
+ 0x80, 0x49, 0x42, 0x80, 0xb7, 0x80, 0x42, 0x62,
+ 0x80, 0x41, 0x8d, 0x80, 0xc3, 0x80, 0x53, 0x88,
+ 0x80, 0xaa, 0x84, 0xe6, 0x81, 0xdc, 0x82, 0x60,
+ 0x6f, 0x15, 0x80, 0x45, 0xf5, 0x80, 0x43, 0xc1,
+ 0x80, 0x95, 0x80, 0x40, 0x88, 0x80, 0xeb, 0x80,
+ 0x94, 0x81, 0x60, 0x54, 0x7a, 0x80, 0x48, 0x0f,
+ 0x81, 0x45, 0xca, 0x80, 0x9a, 0x03, 0x80, 0x44,
+ 0xc6, 0x80, 0x41, 0x24, 0x80, 0xf3, 0x81, 0x41,
+ 0xf1, 0x82, 0x44, 0xce, 0x80, 0x60, 0x50, 0xa8,
0x81, 0x44, 0x9b, 0x08, 0x80, 0x60, 0x71, 0x57,
- 0x81, 0x48, 0x05, 0x82,
+ 0x81, 0x44, 0xb0, 0x80, 0x43, 0x53, 0x82,
};
static const uint8_t unicode_prop_Hex_Digit_table[12] = {
@@ -4013,24 +4097,28 @@ static const uint8_t unicode_prop_Hex_Digit_table[12] = {
0x89, 0x35, 0x99, 0x85,
};
-static const uint8_t unicode_prop_IDS_Binary_Operator_table[5] = {
- 0x60, 0x2f, 0xef, 0x09, 0x87,
+static const uint8_t unicode_prop_IDS_Unary_Operator_table[4] = {
+ 0x60, 0x2f, 0xfd, 0x81,
+};
+
+static const uint8_t unicode_prop_IDS_Binary_Operator_table[8] = {
+ 0x60, 0x2f, 0xef, 0x09, 0x89, 0x41, 0xf0, 0x80,
};
static const uint8_t unicode_prop_IDS_Trinary_Operator_table[4] = {
0x60, 0x2f, 0xf1, 0x81,
};
-static const uint8_t unicode_prop_Ideographic_table[69] = {
+static const uint8_t unicode_prop_Ideographic_table[72] = {
0x60, 0x30, 0x05, 0x81, 0x98, 0x88, 0x8d, 0x82,
0x43, 0xc4, 0x59, 0xbf, 0xbf, 0x60, 0x51, 0xff,
0x60, 0x58, 0xff, 0x41, 0x6d, 0x81, 0xe9, 0x60,
0x75, 0x09, 0x80, 0x9a, 0x57, 0xf7, 0x87, 0x44,
- 0xd5, 0xa9, 0x88, 0x60, 0x24, 0x66, 0x41, 0x8b,
+ 0xd5, 0xa8, 0x89, 0x60, 0x24, 0x66, 0x41, 0x8b,
0x60, 0x4d, 0x03, 0x60, 0xa6, 0xdf, 0x9f, 0x50,
0x39, 0x85, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d,
- 0x5d, 0x30, 0x4c, 0x1e, 0x42, 0x1d, 0x45, 0xe1,
- 0x53, 0x4a, 0x84, 0x50, 0x5f,
+ 0x5d, 0x30, 0x8e, 0x42, 0x6d, 0x49, 0xa1, 0x42,
+ 0x1d, 0x45, 0xe1, 0x53, 0x4a, 0x84, 0x50, 0x5f,
};
static const uint8_t unicode_prop_Join_Control_table[4] = {
@@ -4042,6 +4130,11 @@ static const uint8_t unicode_prop_Logical_Order_Exception_table[15] = {
0x80, 0x60, 0x90, 0xf9, 0x09, 0x00, 0x81,
};
+static const uint8_t unicode_prop_Modifier_Combining_Mark_table[16] = {
+ 0x46, 0x53, 0x09, 0x80, 0x40, 0x82, 0x05, 0x02,
+ 0x81, 0x41, 0xe0, 0x08, 0x12, 0x80, 0x9e, 0x80,
+};
+
static const uint8_t unicode_prop_Noncharacter_Code_Point_table[71] = {
0x60, 0xfd, 0xcf, 0x9f, 0x42, 0x0d, 0x81, 0x60,
0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60,
@@ -4086,32 +4179,34 @@ static const uint8_t unicode_prop_Regional_Indicator_table[4] = {
0x61, 0xf1, 0xe5, 0x99,
};
-static const uint8_t unicode_prop_Sentence_Terminal_table[196] = {
+static const uint8_t unicode_prop_Sentence_Terminal_table[213] = {
0xa0, 0x80, 0x8b, 0x80, 0x8f, 0x80, 0x45, 0x48,
0x80, 0x40, 0x92, 0x82, 0x40, 0xb3, 0x80, 0xaa,
0x82, 0x40, 0xf5, 0x80, 0xbc, 0x00, 0x02, 0x81,
0x41, 0x24, 0x81, 0x46, 0xe3, 0x81, 0x43, 0x15,
0x03, 0x81, 0x43, 0x04, 0x80, 0x40, 0xc5, 0x81,
- 0x40, 0xcb, 0x04, 0x80, 0x41, 0x39, 0x81, 0x41,
- 0x61, 0x83, 0x40, 0xad, 0x09, 0x81, 0x9c, 0x81,
- 0x40, 0xbb, 0x81, 0xc0, 0x81, 0x43, 0xbb, 0x81,
- 0x88, 0x82, 0x4d, 0xe3, 0x80, 0x8c, 0x80, 0x95,
- 0x81, 0x41, 0xac, 0x80, 0x60, 0x74, 0xfb, 0x80,
- 0x41, 0x0d, 0x81, 0x40, 0xe2, 0x02, 0x80, 0x41,
- 0x7d, 0x81, 0xd5, 0x81, 0xde, 0x80, 0x40, 0x97,
- 0x81, 0x40, 0x92, 0x82, 0x40, 0x8f, 0x81, 0x40,
- 0xf8, 0x80, 0x60, 0x52, 0x65, 0x02, 0x81, 0x40,
- 0xa8, 0x80, 0x8b, 0x80, 0x8f, 0x80, 0xc0, 0x80,
- 0x4a, 0xf3, 0x81, 0x44, 0xfc, 0x84, 0xab, 0x83,
- 0x40, 0xbc, 0x81, 0xf4, 0x83, 0xfe, 0x82, 0x40,
- 0x80, 0x0d, 0x80, 0x8f, 0x81, 0xd7, 0x08, 0x81,
- 0xeb, 0x80, 0x41, 0xa0, 0x81, 0x41, 0x74, 0x0c,
- 0x8e, 0xe8, 0x81, 0x40, 0xf8, 0x82, 0x42, 0x04,
- 0x00, 0x80, 0x40, 0xfa, 0x81, 0xd6, 0x81, 0x41,
- 0xa3, 0x81, 0x42, 0xb3, 0x81, 0xc9, 0x81, 0x60,
- 0x4b, 0x28, 0x81, 0x40, 0x84, 0x80, 0xc0, 0x81,
- 0x8a, 0x80, 0x43, 0x52, 0x80, 0x60, 0x4e, 0x05,
- 0x80, 0x5d, 0xe7, 0x80,
+ 0x40, 0x9c, 0x81, 0xac, 0x04, 0x80, 0x41, 0x39,
+ 0x81, 0x41, 0x61, 0x83, 0x40, 0xa1, 0x81, 0x89,
+ 0x09, 0x81, 0x9c, 0x82, 0x40, 0xba, 0x81, 0xc0,
+ 0x81, 0x43, 0xa3, 0x80, 0x96, 0x81, 0x88, 0x82,
+ 0x4c, 0xae, 0x82, 0x41, 0x31, 0x80, 0x8c, 0x80,
+ 0x95, 0x81, 0x41, 0xac, 0x80, 0x60, 0x74, 0xfb,
+ 0x80, 0x41, 0x0d, 0x81, 0x40, 0xe2, 0x02, 0x80,
+ 0x41, 0x7d, 0x81, 0xd5, 0x81, 0xde, 0x80, 0x40,
+ 0x97, 0x81, 0x40, 0x92, 0x82, 0x40, 0x8f, 0x81,
+ 0x40, 0xf8, 0x80, 0x60, 0x52, 0x25, 0x01, 0x81,
+ 0xba, 0x02, 0x81, 0x40, 0xa8, 0x80, 0x8b, 0x80,
+ 0x8f, 0x80, 0xc0, 0x80, 0x4a, 0xf3, 0x81, 0x44,
+ 0xfc, 0x84, 0xab, 0x83, 0x40, 0xbc, 0x81, 0xf4,
+ 0x83, 0xfe, 0x82, 0x40, 0x80, 0x0d, 0x80, 0x8f,
+ 0x81, 0xd7, 0x08, 0x81, 0xeb, 0x80, 0x41, 0x29,
+ 0x81, 0xf4, 0x81, 0x41, 0x74, 0x0c, 0x8e, 0xe8,
+ 0x81, 0x40, 0xf8, 0x82, 0x42, 0x04, 0x00, 0x80,
+ 0x40, 0xfa, 0x81, 0xd6, 0x81, 0x41, 0xa3, 0x81,
+ 0x42, 0xb3, 0x81, 0xc9, 0x81, 0x60, 0x4b, 0x28,
+ 0x81, 0x40, 0x84, 0x80, 0xc0, 0x81, 0x8a, 0x80,
+ 0x42, 0x28, 0x81, 0x41, 0x27, 0x80, 0x60, 0x4e,
+ 0x05, 0x80, 0x5d, 0xe7, 0x80,
};
static const uint8_t unicode_prop_Soft_Dotted_table[79] = {
@@ -4127,47 +4222,49 @@ static const uint8_t unicode_prop_Soft_Dotted_table[79] = {
0x85, 0x80, 0x41, 0x30, 0x81, 0x99, 0x80,
};
-static const uint8_t unicode_prop_Terminal_Punctuation_table[248] = {
+static const uint8_t unicode_prop_Terminal_Punctuation_table[264] = {
0xa0, 0x80, 0x89, 0x00, 0x80, 0x8a, 0x0a, 0x80,
0x43, 0x3d, 0x07, 0x80, 0x42, 0x00, 0x80, 0xb8,
0x80, 0xc7, 0x80, 0x8d, 0x00, 0x82, 0x40, 0xb3,
0x80, 0xaa, 0x8a, 0x00, 0x40, 0xea, 0x81, 0xb5,
- 0x8e, 0x9e, 0x80, 0x41, 0x04, 0x81, 0x44, 0xf3,
- 0x81, 0x40, 0xab, 0x03, 0x85, 0x41, 0x36, 0x81,
- 0x43, 0x14, 0x87, 0x43, 0x04, 0x80, 0xfb, 0x82,
- 0xc6, 0x81, 0x40, 0x9c, 0x12, 0x80, 0xa6, 0x19,
- 0x81, 0x41, 0x39, 0x81, 0x41, 0x61, 0x83, 0x40,
- 0xad, 0x08, 0x82, 0x9c, 0x81, 0x40, 0xbb, 0x84,
- 0xbd, 0x81, 0x43, 0xbb, 0x81, 0x88, 0x82, 0x4d,
- 0xe3, 0x80, 0x8c, 0x03, 0x80, 0x89, 0x00, 0x0a,
+ 0x28, 0x87, 0x9e, 0x80, 0x41, 0x04, 0x81, 0x44,
+ 0xf3, 0x81, 0x40, 0xab, 0x03, 0x85, 0x41, 0x36,
+ 0x81, 0x43, 0x14, 0x87, 0x43, 0x04, 0x80, 0xfb,
+ 0x82, 0xc6, 0x81, 0x40, 0x9c, 0x12, 0x80, 0xa6,
+ 0x19, 0x81, 0x41, 0x39, 0x81, 0x41, 0x61, 0x83,
+ 0x40, 0xa1, 0x81, 0x89, 0x08, 0x82, 0x9c, 0x82,
+ 0x40, 0xba, 0x84, 0xbd, 0x81, 0x43, 0xa3, 0x80,
+ 0x96, 0x81, 0x88, 0x82, 0x4c, 0xae, 0x82, 0x41,
+ 0x31, 0x80, 0x8c, 0x03, 0x80, 0x89, 0x00, 0x0a,
0x81, 0x41, 0xab, 0x81, 0x60, 0x74, 0xfa, 0x81,
0x41, 0x0c, 0x82, 0x40, 0xe2, 0x84, 0x41, 0x7d,
0x81, 0xd5, 0x81, 0xde, 0x80, 0x40, 0x96, 0x82,
0x40, 0x92, 0x82, 0xfe, 0x80, 0x8f, 0x81, 0x40,
- 0xf8, 0x80, 0x60, 0x52, 0x63, 0x10, 0x83, 0x40,
- 0xa8, 0x80, 0x89, 0x00, 0x80, 0x8a, 0x0a, 0x80,
- 0xc0, 0x01, 0x80, 0x44, 0x39, 0x80, 0xaf, 0x80,
- 0x44, 0x85, 0x80, 0x40, 0xc6, 0x80, 0x41, 0x35,
- 0x81, 0x40, 0x97, 0x85, 0xc3, 0x85, 0xd8, 0x83,
- 0x43, 0xb7, 0x84, 0xab, 0x83, 0x40, 0xbc, 0x86,
- 0xef, 0x83, 0xfe, 0x82, 0x40, 0x80, 0x0d, 0x80,
- 0x8f, 0x81, 0xd7, 0x84, 0xeb, 0x80, 0x41, 0xa0,
- 0x82, 0x8b, 0x81, 0x41, 0x65, 0x1a, 0x8e, 0xe8,
- 0x81, 0x40, 0xf8, 0x82, 0x42, 0x04, 0x00, 0x80,
- 0x40, 0xfa, 0x81, 0xd6, 0x0b, 0x81, 0x41, 0x9d,
- 0x82, 0xac, 0x80, 0x42, 0x84, 0x81, 0xc9, 0x81,
- 0x45, 0x2a, 0x84, 0x60, 0x45, 0xf8, 0x81, 0x40,
- 0x84, 0x80, 0xc0, 0x82, 0x89, 0x80, 0x43, 0x51,
+ 0xf8, 0x80, 0x60, 0x52, 0x25, 0x01, 0x81, 0xb8,
+ 0x10, 0x83, 0x40, 0xa8, 0x80, 0x89, 0x00, 0x80,
+ 0x8a, 0x0a, 0x80, 0xc0, 0x01, 0x80, 0x44, 0x39,
+ 0x80, 0xaf, 0x80, 0x44, 0x85, 0x80, 0x40, 0xc6,
+ 0x80, 0x41, 0x35, 0x81, 0x40, 0x97, 0x85, 0xc3,
+ 0x85, 0xd8, 0x83, 0x43, 0xb7, 0x84, 0xab, 0x83,
+ 0x40, 0xbc, 0x86, 0xef, 0x83, 0xfe, 0x82, 0x40,
+ 0x80, 0x0d, 0x80, 0x8f, 0x81, 0xd7, 0x84, 0xeb,
+ 0x80, 0x41, 0x29, 0x81, 0xf4, 0x82, 0x8b, 0x81,
+ 0x41, 0x65, 0x1a, 0x8e, 0xe8, 0x81, 0x40, 0xf8,
+ 0x82, 0x42, 0x04, 0x00, 0x80, 0x40, 0xfa, 0x81,
+ 0xd6, 0x0b, 0x81, 0x41, 0x9d, 0x82, 0xac, 0x80,
+ 0x42, 0x84, 0x81, 0xc9, 0x81, 0x45, 0x2a, 0x84,
+ 0x60, 0x45, 0xf8, 0x81, 0x40, 0x84, 0x80, 0xc0,
+ 0x82, 0x89, 0x80, 0x42, 0x28, 0x81, 0x41, 0x26,
0x81, 0x60, 0x4e, 0x05, 0x80, 0x5d, 0xe6, 0x83,
};
-static const uint8_t unicode_prop_Unified_Ideograph_table[45] = {
+static const uint8_t unicode_prop_Unified_Ideograph_table[48] = {
0x60, 0x33, 0xff, 0x59, 0xbf, 0xbf, 0x60, 0x51,
0xff, 0x60, 0x5a, 0x0d, 0x08, 0x00, 0x81, 0x89,
0x00, 0x00, 0x09, 0x82, 0x61, 0x05, 0xd5, 0x60,
0xa6, 0xdf, 0x9f, 0x50, 0x39, 0x85, 0x40, 0xdd,
- 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x54, 0x1e,
- 0x53, 0x4a, 0x84, 0x50, 0x5f,
+ 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x8e, 0x42,
+ 0x6d, 0x51, 0xa1, 0x53, 0x4a, 0x84, 0x50, 0x5f,
};
static const uint8_t unicode_prop_Variation_Selector_table[13] = {
@@ -4175,12 +4272,6 @@ static const uint8_t unicode_prop_Variation_Selector_table[13] = {
0x6d, 0x02, 0xef, 0x40, 0xef,
};
-static const uint8_t unicode_prop_White_Space_table[22] = {
- 0x88, 0x84, 0x91, 0x80, 0xe3, 0x80, 0x99, 0x80,
- 0x55, 0xde, 0x80, 0x49, 0x7e, 0x8a, 0x9c, 0x0c,
- 0x80, 0xae, 0x80, 0x4f, 0x9f, 0x80,
-};
-
static const uint8_t unicode_prop_Bidi_Mirrored_table[173] = {
0xa7, 0x81, 0x91, 0x00, 0x80, 0x9b, 0x00, 0x80,
0x9c, 0x00, 0x80, 0xac, 0x80, 0x8e, 0x80, 0x4e,
@@ -4188,7 +4279,7 @@ static const uint8_t unicode_prop_Bidi_Mirrored_table[173] = {
0x89, 0x81, 0xb5, 0x81, 0x8d, 0x81, 0x40, 0xb0,
0x80, 0x40, 0xbf, 0x1a, 0x2a, 0x02, 0x0a, 0x18,
0x18, 0x00, 0x03, 0x88, 0x20, 0x80, 0x91, 0x23,
- 0x88, 0x08, 0x00, 0x39, 0x9e, 0x0b, 0x20, 0x88,
+ 0x88, 0x08, 0x00, 0x38, 0x9f, 0x0b, 0x20, 0x88,
0x09, 0x92, 0x21, 0x88, 0x21, 0x0b, 0x97, 0x81,
0x8f, 0x3b, 0x93, 0x0e, 0x81, 0x44, 0x3c, 0x8d,
0xc9, 0x01, 0x18, 0x08, 0x14, 0x1c, 0x12, 0x8d,
@@ -4206,7 +4297,7 @@ static const uint8_t unicode_prop_Bidi_Mirrored_table[173] = {
0x80, 0xb8, 0x80, 0xb8, 0x80,
};
-static const uint8_t unicode_prop_Emoji_table[239] = {
+static const uint8_t unicode_prop_Emoji_table[238] = {
0xa2, 0x05, 0x04, 0x89, 0xee, 0x03, 0x80, 0x5f,
0x8c, 0x80, 0x8b, 0x80, 0x40, 0xd7, 0x80, 0x95,
0x80, 0xd9, 0x85, 0x8e, 0x81, 0x41, 0x6e, 0x81,
@@ -4235,8 +4326,8 @@ static const uint8_t unicode_prop_Emoji_table[239] = {
0x02, 0x05, 0xd5, 0xaf, 0xc5, 0x27, 0x0a, 0x83,
0x89, 0x10, 0x01, 0x10, 0x81, 0x89, 0x40, 0xe2,
0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80, 0x89, 0x80,
- 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x88, 0x86, 0xad,
- 0x06, 0x87, 0x8d, 0x83, 0x88, 0x86, 0x88,
+ 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x89, 0x84, 0xb7,
+ 0x86, 0x8e, 0x81, 0x8a, 0x85, 0x88,
};
static const uint8_t unicode_prop_Emoji_Component_table[28] = {
@@ -4262,7 +4353,7 @@ static const uint8_t unicode_prop_Emoji_Modifier_Base_table[71] = {
0x10, 0x8c, 0x40, 0xe4, 0x82, 0xa9, 0x88,
};
-static const uint8_t unicode_prop_Emoji_Presentation_table[145] = {
+static const uint8_t unicode_prop_Emoji_Presentation_table[144] = {
0x60, 0x23, 0x19, 0x81, 0x40, 0xcc, 0x1a, 0x01,
0x80, 0x42, 0x08, 0x81, 0x94, 0x81, 0xb1, 0x8b,
0xaa, 0x80, 0x92, 0x80, 0x8c, 0x07, 0x81, 0x90,
@@ -4279,9 +4370,8 @@ static const uint8_t unicode_prop_Emoji_Presentation_table[145] = {
0x80, 0x99, 0x81, 0x8c, 0x80, 0xd5, 0xd4, 0xaf,
0xc5, 0x28, 0x12, 0x0a, 0x1b, 0x8a, 0x0e, 0x88,
0x40, 0xe2, 0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80,
- 0x89, 0x80, 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x88,
- 0x86, 0xad, 0x06, 0x87, 0x8d, 0x83, 0x88, 0x86,
- 0x88,
+ 0x89, 0x80, 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x89,
+ 0x84, 0xb7, 0x86, 0x8e, 0x81, 0x8a, 0x85, 0x88,
};
static const uint8_t unicode_prop_Extended_Pictographic_table[156] = {
@@ -4341,11 +4431,13 @@ typedef enum {
UNICODE_PROP_Diacritic,
UNICODE_PROP_Extender,
UNICODE_PROP_Hex_Digit,
+ UNICODE_PROP_IDS_Unary_Operator,
UNICODE_PROP_IDS_Binary_Operator,
UNICODE_PROP_IDS_Trinary_Operator,
UNICODE_PROP_Ideographic,
UNICODE_PROP_Join_Control,
UNICODE_PROP_Logical_Order_Exception,
+ UNICODE_PROP_Modifier_Combining_Mark,
UNICODE_PROP_Noncharacter_Code_Point,
UNICODE_PROP_Pattern_Syntax,
UNICODE_PROP_Pattern_White_Space,
@@ -4382,12 +4474,15 @@ typedef enum {
UNICODE_PROP_Grapheme_Base,
UNICODE_PROP_Grapheme_Extend,
UNICODE_PROP_ID_Continue,
+ UNICODE_PROP_ID_Compat_Math_Start,
+ UNICODE_PROP_ID_Compat_Math_Continue,
UNICODE_PROP_Lowercase,
UNICODE_PROP_Math,
UNICODE_PROP_Uppercase,
UNICODE_PROP_XID_Continue,
UNICODE_PROP_XID_Start,
UNICODE_PROP_Cased1,
+ UNICODE_PROP_InCB,
UNICODE_PROP_COUNT,
} UnicodePropertyEnum;
@@ -4399,11 +4494,13 @@ static const char unicode_prop_name_table[] =
"Diacritic,Dia" "\0"
"Extender,Ext" "\0"
"Hex_Digit,Hex" "\0"
+ "IDS_Unary_Operator,IDSU" "\0"
"IDS_Binary_Operator,IDSB" "\0"
"IDS_Trinary_Operator,IDST" "\0"
"Ideographic,Ideo" "\0"
"Join_Control,Join_C" "\0"
"Logical_Order_Exception,LOE" "\0"
+ "Modifier_Combining_Mark,MCM" "\0"
"Noncharacter_Code_Point,NChar" "\0"
"Pattern_Syntax,Pat_Syn" "\0"
"Pattern_White_Space,Pat_WS" "\0"
@@ -4440,6 +4537,8 @@ static const char unicode_prop_name_table[] =
"Grapheme_Base,Gr_Base" "\0"
"Grapheme_Extend,Gr_Ext" "\0"
"ID_Continue,IDC" "\0"
+ "ID_Compat_Math_Start" "\0"
+ "ID_Compat_Math_Continue" "\0"
"Lowercase,Lower" "\0"
"Math" "\0"
"Uppercase,Upper" "\0"
@@ -4471,11 +4570,13 @@ static const uint8_t * const unicode_prop_table[] = {
unicode_prop_Diacritic_table,
unicode_prop_Extender_table,
unicode_prop_Hex_Digit_table,
+ unicode_prop_IDS_Unary_Operator_table,
unicode_prop_IDS_Binary_Operator_table,
unicode_prop_IDS_Trinary_Operator_table,
unicode_prop_Ideographic_table,
unicode_prop_Join_Control_table,
unicode_prop_Logical_Order_Exception_table,
+ unicode_prop_Modifier_Combining_Mark_table,
unicode_prop_Noncharacter_Code_Point_table,
unicode_prop_Pattern_Syntax_table,
unicode_prop_Pattern_White_Space_table,
@@ -4524,11 +4625,13 @@ static const uint16_t unicode_prop_len_table[] = {
countof(unicode_prop_Diacritic_table),
countof(unicode_prop_Extender_table),
countof(unicode_prop_Hex_Digit_table),
+ countof(unicode_prop_IDS_Unary_Operator_table),
countof(unicode_prop_IDS_Binary_Operator_table),
countof(unicode_prop_IDS_Trinary_Operator_table),
countof(unicode_prop_Ideographic_table),
countof(unicode_prop_Join_Control_table),
countof(unicode_prop_Logical_Order_Exception_table),
+ countof(unicode_prop_Modifier_Combining_Mark_table),
countof(unicode_prop_Noncharacter_Code_Point_table),
countof(unicode_prop_Pattern_Syntax_table),
countof(unicode_prop_Pattern_White_Space_table),
@@ -4553,5 +4656,3 @@ static const uint16_t unicode_prop_len_table[] = {
countof(unicode_prop_Case_Ignorable_table),
};
-#endif /* CONFIG_ALL_UNICODE */
-/* 62 tables / 32261 bytes, 5 index / 345 bytes */
diff --git a/src/shared/quickjs/libunicode.c b/src/shared/quickjs/libunicode.c
index 482c51944..a621c5235 100644
--- a/src/shared/quickjs/libunicode.c
+++ b/src/shared/quickjs/libunicode.c
@@ -31,6 +31,7 @@
#include "libunicode.h"
#include "libunicode-table.h"
+// note: stored as 4 bit tag, not much room left
enum {
RUN_TYPE_U,
RUN_TYPE_L,
@@ -189,7 +190,7 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
return 1;
}
-static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, BOOL is_unicode)
+static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, bool is_unicode)
{
uint32_t res[LRE_CC_RES_LEN_MAX];
int len;
@@ -215,7 +216,7 @@ static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, BOOL is_
c = c - 'a' + 'A';
} else {
/* legacy regexp: to upper case if single char >= 128 */
- len = lre_case_conv_entry(res, c, FALSE, idx, v);
+ len = lre_case_conv_entry(res, c, false, idx, v);
if (len == 1 && res[0] >= 128)
c = res[0];
}
@@ -224,7 +225,7 @@ static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, BOOL is_
}
/* JS regexp specific rules for case folding */
-int lre_canonicalize(uint32_t c, BOOL is_unicode)
+int lre_canonicalize(uint32_t c, bool is_unicode)
{
if (c < 128) {
/* fast case */
@@ -301,7 +302,7 @@ static int get_index_pos(uint32_t *pcode, uint32_t c,
return (idx_min + 1) * UNICODE_INDEX_BLOCK_LEN + (v >> 21);
}
-static BOOL lre_is_in_table(uint32_t c, const uint8_t *table,
+static bool lre_is_in_table(uint32_t c, const uint8_t *table,
const uint8_t *index_table, int index_table_len)
{
uint32_t code, b, bit;
@@ -310,17 +311,9 @@ static BOOL lre_is_in_table(uint32_t c, const uint8_t *table,
pos = get_index_pos(&code, c, index_table, index_table_len);
if (pos < 0)
- return FALSE; /* outside the table */
+ return false; /* outside the table */
p = table + pos;
bit = 0;
- /* Compressed run length encoding:
- 00..3F: 2 packed lengths: 3-bit + 3-bit
- 40..5F: 5-bits plus extra byte for length
- 60..7F: 5-bits plus 2 extra bytes for length
- 80..FF: 7-bit length
- lengths must be incremented to get character count
- Ranges alternate between false and true return value.
- */
for(;;) {
b = *p++;
if (b < 64) {
@@ -344,7 +337,7 @@ static BOOL lre_is_in_table(uint32_t c, const uint8_t *table,
}
}
-BOOL lre_is_cased(uint32_t c)
+bool lre_is_cased(uint32_t c)
{
uint32_t v, code, len;
int idx, idx_min, idx_max;
@@ -361,7 +354,7 @@ BOOL lre_is_cased(uint32_t c)
} else if (c >= code + len) {
idx_min = idx + 1;
} else {
- return TRUE;
+ return true;
}
}
return lre_is_in_table(c, unicode_prop_Cased1_table,
@@ -369,7 +362,7 @@ BOOL lre_is_cased(uint32_t c)
sizeof(unicode_prop_Cased1_index) / 3);
}
-BOOL lre_is_case_ignorable(uint32_t c)
+bool lre_is_case_ignorable(uint32_t c)
{
return lre_is_in_table(c, unicode_prop_Case_Ignorable_table,
unicode_prop_Case_Ignorable_index,
@@ -537,16 +530,14 @@ int cr_invert(CharRange *cr)
return 0;
}
-#ifdef CONFIG_ALL_UNICODE
-
-BOOL lre_is_id_start(uint32_t c)
+bool lre_is_id_start(uint32_t c)
{
return lre_is_in_table(c, unicode_prop_ID_Start_table,
unicode_prop_ID_Start_index,
sizeof(unicode_prop_ID_Start_index) / 3);
}
-BOOL lre_is_id_continue(uint32_t c)
+bool lre_is_id_continue(uint32_t c)
{
return lre_is_id_start(c) ||
lre_is_in_table(c, unicode_prop_ID_Continue1_table,
@@ -554,6 +545,13 @@ BOOL lre_is_id_continue(uint32_t c)
sizeof(unicode_prop_ID_Continue1_index) / 3);
}
+bool lre_is_white_space(uint32_t c)
+{
+ return lre_is_in_table(c, unicode_prop_White_Space_table,
+ unicode_prop_White_Space_index,
+ sizeof(unicode_prop_White_Space_index) / 3);
+}
+
#define UNICODE_DECOMP_LEN_MAX 18
typedef enum {
@@ -761,7 +759,7 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c,
/* return the length of the decomposition (length <=
UNICODE_DECOMP_LEN_MAX) or 0 if no decomposition */
-static int unicode_decomp_char(uint32_t *res, uint32_t c, BOOL is_compat1)
+static int unicode_decomp_char(uint32_t *res, uint32_t c, bool is_compat1)
{
uint32_t v, type, is_compat, code, len;
int idx_min, idx_max, idx;
@@ -837,13 +835,6 @@ static int unicode_get_cc(uint32_t c)
if (pos < 0)
return 0;
p = unicode_cc_table + pos;
- /* Compressed run length encoding:
- - 2 high order bits are combining class type
- - 0:0, 1:230, 2:extra byte linear progression, 3:extra byte
- - 00..2F: range length (add 1)
- - 30..37: 3-bit range-length + 1 extra byte
- - 38..3F: 3-bit range-length + 2 extra byte
- */
for(;;) {
b = *p++;
type = b >> 6;
@@ -908,13 +899,6 @@ static void sort_cc(int *buf, int len)
buf[k + 1] = ch1;
j++;
}
-#if 0
- printf("cc:");
- for(k = start; k < j; k++) {
- printf(" %3d", unicode_get_cc(buf[k]));
- }
- printf("\n");
-#endif
i = j;
}
}
@@ -969,7 +953,7 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
void *opaque, DynBufReallocFunc *realloc_func)
{
int *buf, buf_len, i, p, starter_pos, cc, last_cc, out_len;
- BOOL is_compat;
+ bool is_compat;
DynBuf dbuf_s, *dbuf = &dbuf_s;
is_compat = n_type >> 1;
@@ -1069,14 +1053,14 @@ static int unicode_find_name(const char *name_table, const char *name)
/* 'cr' must be initialized and empty. Return 0 if OK, -1 if error, -2
if not found */
int unicode_script(CharRange *cr,
- const char *script_name, BOOL is_ext)
+ const char *script_name, bool is_ext)
{
int script_idx;
const uint8_t *p, *p_end;
uint32_t c, c1, b, n, v, v_len, i, type;
- CharRange cr1_s, *cr1;
- CharRange cr2_s, *cr2 = &cr2_s;
- BOOL is_common;
+ CharRange cr1_s = { 0 }, *cr1 = NULL;
+ CharRange cr2_s = { 0 }, *cr2 = &cr2_s;
+ bool is_common;
script_idx = unicode_find_name(unicode_script_name_table, script_name);
if (script_idx < 0)
@@ -1196,15 +1180,6 @@ static int unicode_general_category1(CharRange *cr, uint32_t gc_mask)
p = unicode_gc_table;
p_end = unicode_gc_table + countof(unicode_gc_table);
c = 0;
- /* Compressed range encoding:
- initial byte:
- bits 0..4: category number (special case 31)
- bits 5..7: range length (add 1)
- special case bits 5..7 == 7: read an extra byte
- - 00..7F: range length (add 7 + 1)
- - 80..BF: 6-bits plus extra byte for range length (add 7 + 128)
- - C0..FF: 6-bits plus 2 extra bytes for range length (add 7 + 128 + 16384)
- */
while (p < p_end) {
b = *p++;
n = b >> 5;
@@ -1258,14 +1233,6 @@ static int unicode_prop1(CharRange *cr, int prop_idx)
p_end = p + unicode_prop_len_table[prop_idx];
c = 0;
bit = 0;
- /* Compressed range encoding:
- 00..3F: 2 packed lengths: 3-bit + 3-bit
- 40..5F: 5-bits plus extra byte for length
- 60..7F: 5-bits plus 2 extra bytes for length
- 80..FF: 7-bit length
- lengths must be incremented to get character count
- Ranges alternate between false and true return value.
- */
while (p < p_end) {
c0 = c;
b = *p++;
@@ -1413,7 +1380,7 @@ static void cr_sort_and_remove_overlap(CharRange *cr)
/* canonicalize a character set using the JS regex case folding rules
(see lre_canonicalize()) */
-int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode)
+int cr_regexp_canonicalize(CharRange *cr, bool is_unicode)
{
CharRange cr_inter, cr_mask, cr_result, cr_sub;
uint32_t v, code, len, i, idx, start, end, c, d_start, d_end, d;
@@ -1761,42 +1728,6 @@ int unicode_prop(CharRange *cr, const char *prop_name)
POP_XOR,
POP_END);
break;
-#if 0
- case UNICODE_PROP_ID_Start:
- ret = unicode_prop_ops(cr,
- POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl),
- POP_PROP, UNICODE_PROP_Other_ID_Start,
- POP_UNION,
- POP_PROP, UNICODE_PROP_Pattern_Syntax,
- POP_PROP, UNICODE_PROP_Pattern_White_Space,
- POP_UNION,
- POP_INVERT,
- POP_INTER,
- POP_END);
- break;
- case UNICODE_PROP_ID_Continue:
- ret = unicode_prop_ops(cr,
- POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl) |
- M(Mn) | M(Mc) | M(Nd) | M(Pc),
- POP_PROP, UNICODE_PROP_Other_ID_Start,
- POP_UNION,
- POP_PROP, UNICODE_PROP_Other_ID_Continue,
- POP_UNION,
- POP_PROP, UNICODE_PROP_Pattern_Syntax,
- POP_PROP, UNICODE_PROP_Pattern_White_Space,
- POP_UNION,
- POP_INVERT,
- POP_INTER,
- POP_END);
- break;
- case UNICODE_PROP_Case_Ignorable:
- ret = unicode_prop_ops(cr,
- POP_GC, M(Mn) | M(Cf) | M(Lm) | M(Sk),
- POP_PROP, UNICODE_PROP_Case_Ignorable1,
- POP_XOR,
- POP_END);
- break;
-#else
/* we use the existing tables */
case UNICODE_PROP_ID_Continue:
ret = unicode_prop_ops(cr,
@@ -1805,7 +1736,6 @@ int unicode_prop(CharRange *cr, const char *prop_name)
POP_XOR,
POP_END);
break;
-#endif
default:
if (prop_idx >= countof(unicode_prop_table))
return -2;
@@ -1814,99 +1744,3 @@ int unicode_prop(CharRange *cr, const char *prop_name)
}
return ret;
}
-
-#endif /* CONFIG_ALL_UNICODE */
-
-/*---- lre codepoint categorizing functions ----*/
-
-#define S UNICODE_C_SPACE
-#define D UNICODE_C_DIGIT
-#define X UNICODE_C_XDIGIT
-#define U UNICODE_C_UPPER
-#define L UNICODE_C_LOWER
-#define _ UNICODE_C_UNDER
-#define d UNICODE_C_DOLLAR
-
-uint8_t const lre_ctype_bits[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, S, S, S, S, S, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-
- S, 0, 0, 0, d, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- X|D, X|D, X|D, X|D, X|D, X|D, X|D, X|D,
- X|D, X|D, 0, 0, 0, 0, 0, 0,
-
- 0, X|U, X|U, X|U, X|U, X|U, X|U, U,
- U, U, U, U, U, U, U, U,
- U, U, U, U, U, U, U, U,
- U, U, U, 0, 0, 0, 0, _,
-
- 0, X|L, X|L, X|L, X|L, X|L, X|L, L,
- L, L, L, L, L, L, L, L,
- L, L, L, L, L, L, L, L,
- L, L, L, 0, 0, 0, 0, 0,
-
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-
- S, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-#undef S
-#undef D
-#undef X
-#undef U
-#undef L
-#undef _
-#undef d
-
-/* code point ranges for Zs,Zl or Zp property */
-static const uint16_t char_range_s[] = {
- 10,
- 0x0009, 0x000D + 1,
- 0x0020, 0x0020 + 1,
- 0x00A0, 0x00A0 + 1,
- 0x1680, 0x1680 + 1,
- 0x2000, 0x200A + 1,
- /* 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; */
- /* 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; */
- 0x2028, 0x2029 + 1,
- 0x202F, 0x202F + 1,
- 0x205F, 0x205F + 1,
- 0x3000, 0x3000 + 1,
- /* FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; */
- 0xFEFF, 0xFEFF + 1,
-};
-
-BOOL lre_is_space_non_ascii(uint32_t c)
-{
- size_t i, n;
-
- n = countof(char_range_s);
- for(i = 5; i < n; i += 2) {
- uint32_t low = char_range_s[i];
- uint32_t high = char_range_s[i + 1];
- if (c < low)
- return FALSE;
- if (c < high)
- return TRUE;
- }
- return FALSE;
-}
diff --git a/src/shared/quickjs/libunicode.h b/src/shared/quickjs/libunicode.h
index cc2f244c7..8e6f2a01d 100644
--- a/src/shared/quickjs/libunicode.h
+++ b/src/shared/quickjs/libunicode.h
@@ -24,13 +24,28 @@
#ifndef LIBUNICODE_H
#define LIBUNICODE_H
-#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <inttypes.h>
-/* define it to include all the unicode tables (40KB larger) */
-#define CONFIG_ALL_UNICODE
+#ifdef __cplusplus
+extern "C" {
+#endif
#define LRE_CC_RES_LEN_MAX 3
+typedef enum {
+ UNICODE_NFC,
+ UNICODE_NFD,
+ UNICODE_NFKC,
+ UNICODE_NFKD,
+} UnicodeNormalizationEnum;
+
+int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
+int lre_canonicalize(uint32_t c, bool is_unicode);
+bool lre_is_cased(uint32_t c);
+bool lre_is_case_ignorable(uint32_t c);
+
/* char ranges */
typedef struct {
@@ -87,15 +102,11 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
const uint32_t *b_pt, int b_len, int op);
int cr_invert(CharRange *cr);
+int cr_regexp_canonicalize(CharRange *cr, bool is_unicode);
-int cr_regexp_canonicalize(CharRange *cr, int is_unicode);
-
-typedef enum {
- UNICODE_NFC,
- UNICODE_NFD,
- UNICODE_NFKC,
- UNICODE_NFKD,
-} UnicodeNormalizationEnum;
+bool lre_is_id_start(uint32_t c);
+bool lre_is_id_continue(uint32_t c);
+bool lre_is_white_space(uint32_t c);
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
UnicodeNormalizationEnum n_type,
@@ -103,80 +114,13 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
/* Unicode character range functions */
-int unicode_script(CharRange *cr, const char *script_name, int is_ext);
+int unicode_script(CharRange *cr,
+ const char *script_name, bool is_ext);
int unicode_general_category(CharRange *cr, const char *gc_name);
int unicode_prop(CharRange *cr, const char *prop_name);
-int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
-int lre_canonicalize(uint32_t c, int is_unicode);
-
-/* Code point type categories */
-enum {
- UNICODE_C_SPACE = (1 << 0),
- UNICODE_C_DIGIT = (1 << 1),
- UNICODE_C_UPPER = (1 << 2),
- UNICODE_C_LOWER = (1 << 3),
- UNICODE_C_UNDER = (1 << 4),
- UNICODE_C_DOLLAR = (1 << 5),
- UNICODE_C_XDIGIT = (1 << 6),
-};
-extern uint8_t const lre_ctype_bits[256];
-
-/* zero or non-zero return value */
-int lre_is_cased(uint32_t c);
-int lre_is_case_ignorable(uint32_t c);
-int lre_is_id_start(uint32_t c);
-int lre_is_id_continue(uint32_t c);
-
-static inline int lre_is_space_byte(uint8_t c) {
- return lre_ctype_bits[c] & UNICODE_C_SPACE;
-}
-
-static inline int lre_is_id_start_byte(uint8_t c) {
- return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER |
- UNICODE_C_UNDER | UNICODE_C_DOLLAR);
-}
-
-static inline int lre_is_id_continue_byte(uint8_t c) {
- return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER |
- UNICODE_C_UNDER | UNICODE_C_DOLLAR |
- UNICODE_C_DIGIT);
-}
-
-int lre_is_space_non_ascii(uint32_t c);
-
-static inline int lre_is_space(uint32_t c) {
- if (c < 256)
- return lre_is_space_byte(c);
- else
- return lre_is_space_non_ascii(c);
-}
-
-static inline int lre_js_is_ident_first(uint32_t c) {
- if (c < 128) {
- return lre_is_id_start_byte(c);
- } else {
-#ifdef CONFIG_ALL_UNICODE
- return lre_is_id_start(c);
-#else
- return !lre_is_space_non_ascii(c);
-#endif
- }
-}
-
-static inline int lre_js_is_ident_next(uint32_t c) {
- if (c < 128) {
- return lre_is_id_continue_byte(c);
- } else {
- /* ZWNJ and ZWJ are accepted in identifiers */
- if (c >= 0x200C && c <= 0x200D)
- return TRUE;
-#ifdef CONFIG_ALL_UNICODE
- return lre_is_id_continue(c);
-#else
- return !lre_is_space_non_ascii(c);
+#ifdef __cplusplus
+} /* extern "C" { */
#endif
- }
-}
#endif /* LIBUNICODE_H */
diff --git a/src/shared/quickjs/list.h b/src/shared/quickjs/list.h
index 809831115..b8dd71681 100644
--- a/src/shared/quickjs/list.h
+++ b/src/shared/quickjs/list.h
@@ -28,6 +28,10 @@
#include <stddef.h>
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct list_head {
struct list_head *prev;
struct list_head *next;
@@ -96,4 +100,8 @@ static inline int list_empty(struct list_head *el)
for(el = (head)->prev, el1 = el->prev; el != (head); \
el = el1, el1 = el->prev)
+#ifdef __cplusplus
+} /* extern "C" { */
+#endif
+
#endif /* LIST_H */
diff --git a/src/shared/quickjs/quickjs-atom.h b/src/shared/quickjs/quickjs-atom.h
index f4d5838d4..358fe2306 100644
--- a/src/shared/quickjs/quickjs-atom.h
+++ b/src/shared/quickjs/quickjs-atom.h
@@ -78,9 +78,9 @@ DEF(await, "await")
/* empty string */
DEF(empty_string, "")
/* identifiers */
+DEF(keys, "keys")
+DEF(size, "size")
DEF(length, "length")
-DEF(fileName, "fileName")
-DEF(lineNumber, "lineNumber")
DEF(message, "message")
DEF(cause, "cause")
DEF(errors, "errors")
@@ -172,19 +172,11 @@ DEF(status, "status")
DEF(reason, "reason")
DEF(globalThis, "globalThis")
DEF(bigint, "bigint")
-#ifdef CONFIG_BIGNUM
-DEF(bigfloat, "bigfloat")
-DEF(bigdecimal, "bigdecimal")
-DEF(roundingMode, "roundingMode")
-DEF(maximumSignificantDigits, "maximumSignificantDigits")
-DEF(maximumFractionDigits, "maximumFractionDigits")
-#endif
-/* the following 3 atoms are only used with CONFIG_ATOMICS */
DEF(not_equal, "not-equal")
DEF(timed_out, "timed-out")
DEF(ok, "ok")
-/* */
DEF(toJSON, "toJSON")
+DEF(maxByteLength, "maxByteLength")
/* class names */
DEF(Object, "Object")
DEF(Array, "Array")
@@ -213,21 +205,20 @@ DEF(Int32Array, "Int32Array")
DEF(Uint32Array, "Uint32Array")
DEF(BigInt64Array, "BigInt64Array")
DEF(BigUint64Array, "BigUint64Array")
+DEF(Float16Array, "Float16Array")
DEF(Float32Array, "Float32Array")
DEF(Float64Array, "Float64Array")
DEF(DataView, "DataView")
DEF(BigInt, "BigInt")
-#ifdef CONFIG_BIGNUM
-DEF(BigFloat, "BigFloat")
-DEF(BigFloatEnv, "BigFloatEnv")
-DEF(BigDecimal, "BigDecimal")
-DEF(OperatorSet, "OperatorSet")
-DEF(Operators, "Operators")
-#endif
+DEF(WeakRef, "WeakRef")
+DEF(FinalizationRegistry, "FinalizationRegistry")
DEF(Map, "Map")
DEF(Set, "Set") /* Map + 1 */
DEF(WeakMap, "WeakMap") /* Map + 2 */
DEF(WeakSet, "WeakSet") /* Map + 3 */
+DEF(Iterator, "Iterator")
+DEF(IteratorHelper, "Iterator Helper")
+DEF(IteratorWrap, "Iterator Wrap")
DEF(Map_Iterator, "Map Iterator")
DEF(Set_Iterator, "Set Iterator")
DEF(Array_Iterator, "Array Iterator")
@@ -250,6 +241,7 @@ DEF(SyntaxError, "SyntaxError")
DEF(TypeError, "TypeError")
DEF(URIError, "URIError")
DEF(InternalError, "InternalError")
+DEF(CallSite, "CallSite")
/* private symbols */
DEF(Private_brand, "<brand>")
/* symbols */
@@ -266,8 +258,5 @@ DEF(Symbol_hasInstance, "Symbol.hasInstance")
DEF(Symbol_species, "Symbol.species")
DEF(Symbol_unscopables, "Symbol.unscopables")
DEF(Symbol_asyncIterator, "Symbol.asyncIterator")
-#ifdef CONFIG_BIGNUM
-DEF(Symbol_operatorSet, "Symbol.operatorSet")
-#endif
#endif /* DEF */
diff --git a/src/shared/quickjs/quickjs-c-atomics.h b/src/shared/quickjs/quickjs-c-atomics.h
new file mode 100644
index 000000000..8fc6b7203
--- /dev/null
+++ b/src/shared/quickjs/quickjs-c-atomics.h
@@ -0,0 +1,54 @@
+/*
+ * QuickJS C atomics definitions
+ *
+ * Copyright (c) 2023 Marcin Kolny
+ *
+ * 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.
+ */
+
+#if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__clang__)
+ // Use GCC builtins for version < 4.9
+# if((__GNUC__ << 16) + __GNUC_MINOR__ < ((4) << 16) + 9)
+# define GCC_BUILTIN_ATOMICS
+# endif
+#endif
+
+#ifdef GCC_BUILTIN_ATOMICS
+#define atomic_fetch_add(obj, arg) \
+ __atomic_fetch_add(obj, arg, __ATOMIC_SEQ_CST)
+#define atomic_compare_exchange_strong(obj, expected, desired) \
+ __atomic_compare_exchange_n(obj, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+#define atomic_exchange(obj, desired) \
+ __atomic_exchange_n (obj, desired, __ATOMIC_SEQ_CST)
+#define atomic_load(obj) \
+ __atomic_load_n(obj, __ATOMIC_SEQ_CST)
+#define atomic_store(obj, desired) \
+ __atomic_store_n(obj, desired, __ATOMIC_SEQ_CST)
+#define atomic_fetch_or(obj, arg) \
+ __atomic_fetch_or(obj, arg, __ATOMIC_SEQ_CST)
+#define atomic_fetch_xor(obj, arg) \
+ __atomic_fetch_xor(obj, arg, __ATOMIC_SEQ_CST)
+#define atomic_fetch_and(obj, arg) \
+ __atomic_fetch_and(obj, arg, __ATOMIC_SEQ_CST)
+#define atomic_fetch_sub(obj, arg) \
+ __atomic_fetch_sub(obj, arg, __ATOMIC_SEQ_CST)
+#define _Atomic
+#else
+#include <stdatomic.h>
+#endif
diff --git a/src/shared/quickjs/quickjs-opcode.h b/src/shared/quickjs/quickjs-opcode.h
index 1e1821259..42c3faee3 100644
--- a/src/shared/quickjs/quickjs-opcode.h
+++ b/src/shared/quickjs/quickjs-opcode.h
@@ -44,6 +44,7 @@ FMT(loc)
FMT(arg)
FMT(var_ref)
FMT(u32)
+FMT(u32x2)
FMT(i32)
FMT(const)
FMT(label)
@@ -110,6 +111,7 @@ DEF( return, 1, 1, 0, none)
DEF( return_undef, 1, 0, 0, none)
DEF(check_ctor_return, 1, 1, 2, none)
DEF( check_ctor, 1, 0, 0, none)
+DEF( init_ctor, 1, 0, 1, none)
DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */
DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
DEF( return_async, 1, 1, 0, none)
@@ -135,9 +137,12 @@ DEF( put_ref_value, 1, 3, 0, none)
DEF( define_var, 6, 0, 0, atom_u8)
DEF(check_define_var, 6, 0, 0, atom_u8)
DEF( define_func, 6, 1, 0, atom_u8)
+
+// order matters, see IC counterparts
DEF( get_field, 5, 1, 1, atom)
DEF( get_field2, 5, 1, 2, atom)
DEF( put_field, 5, 2, 0, atom)
+
DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */
DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */
DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */
@@ -172,7 +177,6 @@ DEF(set_loc_uninitialized, 3, 0, 0, loc)
DEF( get_loc_check, 3, 0, 1, loc)
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
DEF( put_loc_check_init, 3, 1, 0, loc)
-DEF(get_loc_checkthis, 3, 0, 1, loc)
DEF(get_var_ref_check, 3, 0, 1, var_ref)
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
@@ -234,15 +238,20 @@ DEF( typeof, 1, 1, 1, none)
DEF( delete, 1, 2, 1, none)
DEF( delete_var, 5, 0, 1, atom)
+/* warning: order matters (see js_parse_assign_expr) */
DEF( mul, 1, 2, 1, none)
DEF( div, 1, 2, 1, none)
DEF( mod, 1, 2, 1, none)
DEF( add, 1, 2, 1, none)
DEF( sub, 1, 2, 1, none)
-DEF( pow, 1, 2, 1, none)
DEF( shl, 1, 2, 1, none)
DEF( sar, 1, 2, 1, none)
DEF( shr, 1, 2, 1, none)
+DEF( and, 1, 2, 1, none)
+DEF( xor, 1, 2, 1, none)
+DEF( or, 1, 2, 1, none)
+DEF( pow, 1, 2, 1, none)
+
DEF( lt, 1, 2, 1, none)
DEF( lte, 1, 2, 1, none)
DEF( gt, 1, 2, 1, none)
@@ -253,15 +262,8 @@ DEF( eq, 1, 2, 1, none)
DEF( neq, 1, 2, 1, none)
DEF( strict_eq, 1, 2, 1, none)
DEF( strict_neq, 1, 2, 1, none)
-DEF( and, 1, 2, 1, none)
-DEF( xor, 1, 2, 1, none)
-DEF( or, 1, 2, 1, none)
DEF(is_undefined_or_null, 1, 1, 1, none)
DEF( private_in, 1, 2, 1, none)
-#ifdef CONFIG_BIGNUM
-DEF( mul_pow10, 1, 2, 1, none)
-DEF( math_mod, 1, 2, 1, none)
-#endif
/* must be the last non short and non temporary opcode */
DEF( nop, 1, 0, 0, none)
@@ -272,8 +274,6 @@ def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */
-/* the following opcodes must be in the same order as the 'with_x' and
- get_var_undef, get_var and put_var opcodes */
def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */
@@ -281,7 +281,6 @@ def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase
def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
-def(scope_get_var_checkthis, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2, only used to return 'this' in derived class constructors */
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
def(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
@@ -290,9 +289,8 @@ def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase
def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
-def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
+def( source_loc, 9, 0, 0, u32x2) /* emitted in phase 1, removed in phase 3 */
-#if SHORT_OPCODES
DEF( push_minus1, 1, 0, 1, none_int)
DEF( push_0, 1, 0, 1, none_int)
DEF( push_1, 1, 0, 1, none_int)
@@ -312,6 +310,7 @@ DEF( get_loc8, 2, 0, 1, loc8)
DEF( put_loc8, 2, 1, 0, loc8)
DEF( set_loc8, 2, 1, 1, loc8)
+DEF( get_loc0_loc1, 1, 0, 2, none_loc)
DEF( get_loc0, 1, 0, 1, none_loc)
DEF( get_loc1, 1, 0, 1, none_loc)
DEF( get_loc2, 1, 0, 1, none_loc)
@@ -365,7 +364,6 @@ DEF( is_undefined, 1, 1, 1, none)
DEF( is_null, 1, 1, 1, none)
DEF(typeof_is_undefined, 1, 1, 1, none)
DEF( typeof_is_function, 1, 1, 1, none)
-#endif
#undef DEF
#undef def
diff --git a/src/shared/quickjs/quickjs.c b/src/shared/quickjs/quickjs.c
index 3bafe6948..b48c5a9ab 100644
--- a/src/shared/quickjs/quickjs.c
+++ b/src/shared/quickjs/quickjs.c
@@ -1,8 +1,10 @@
/*
* QuickJS Javascript Engine
*
- * Copyright (c) 2017-2021 Fabrice Bellard
- * Copyright (c) 2017-2021 Charlie Gordon
+ * Copyright (c) 2017-2024 Fabrice Bellard
+ * Copyright (c) 2017-2024 Charlie Gordon
+ * Copyright (c) 2023-2025 Ben Noordhuis
+ * Copyright (c) 2023-2025 Saúl Ibarra Corretgé
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,25 +30,23 @@
#include <inttypes.h>
#include <string.h>
#include <assert.h>
-#ifndef _MSC_VER
+#if !defined(_MSC_VER)
#include <sys/time.h>
+#if defined(_WIN32)
+#include <timezoneapi.h>
+#endif
+#endif
+#if defined(_WIN32)
+#include <intrin.h>
#endif
#include <time.h>
#include <fenv.h>
#include <math.h>
-#if defined(__APPLE__)
-#include <malloc/malloc.h>
-#elif defined(__linux__)
-#include <malloc.h>
-#elif defined(__FreeBSD__)
-#include <malloc_np.h>
-#endif
#ifdef _MSC_VER
#include <intrin.h>
#include <windows.h>
#endif
-
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
|| defined(__APPLE__)
#include <xlocale.h>
@@ -58,11 +58,8 @@
#include "list.h"
#include "quickjs.h"
#include "libregexp.h"
-#include "libunicode.h"
#include "libbf.h"
-#define OPTIMIZE 0
-#define SHORT_OPCODES 1
#if defined(EMSCRIPTEN) || defined(_MSC_VER)
#define DIRECT_DISPATCH 0
#else
@@ -75,59 +72,43 @@
#define MALLOC_OVERHEAD 8
#endif
-#if !defined(_WIN32)
-/* define it if printf uses the RNDN rounding mode instead of RNDNA */
-#define CONFIG_PRINTF_RNDN
+#if defined(__NEWLIB__)
+#define NO_TM_GMTOFF
#endif
-/* define to include Atomics.* operations which depend on the OS
- threads */
-#if !defined(EMSCRIPTEN) && !defined(_MSC_VER)
+// atomic_store etc. are completely busted in recent versions of tcc;
+// somehow the compiler forgets to load |ptr| into %rdi when calling
+// the __atomic_*() helpers in its lib/stdatomic.c and lib/atomic.S
+#if !defined(__TINYC__) && !defined(EMSCRIPTEN) && !defined(__wasi__) && !__STDC_NO_ATOMICS__
+#include "quickjs-c-atomics.h"
#define CONFIG_ATOMICS
#endif
-#if !defined(EMSCRIPTEN)
-/* enable stack limitation */
-#define CONFIG_STACK_CHECK
+#ifndef __GNUC__
+#define __extension__
#endif
-/* dump object free */
-//#define DUMP_FREE
-//#define DUMP_CLOSURE
-/* dump the bytecode of the compiled functions: combination of bits
- 1: dump pass 3 final byte code
- 2: dump pass 2 code
- 4: dump pass 1 code
- 8: dump stdlib functions
- 16: dump bytecode in hex
- 32: dump line number table
- 64: dump compute_stack_size
- */
-//#define DUMP_BYTECODE (1)
-/* dump the occurence of the automatic GC */
-//#define DUMP_GC
-/* dump objects freed by the garbage collector */
-//#define DUMP_GC_FREE
-/* dump objects leaking when freeing the runtime */
-//#define DUMP_LEAKS 1
-/* dump memory usage before running the garbage collector */
-//#define DUMP_MEM
-//#define DUMP_OBJECTS /* dump objects in JS_FreeContext */
-//#define DUMP_ATOMS /* dump atoms in JS_FreeContext */
-//#define DUMP_SHAPES /* dump shapes in JS_FreeContext */
-//#define DUMP_MODULE_RESOLVE
-//#define DUMP_PROMISE
-//#define DUMP_READ_OBJECT
-
-/* test the GC by forcing it before each object allocation */
-//#define FORCE_GC_AT_MALLOC
-
-#ifdef CONFIG_ATOMICS
-#include <pthread.h>
-#include <stdatomic.h>
-#include <errno.h>
+#ifndef NDEBUG
+#define ENABLE_DUMPS
#endif
+//#define FORCE_GC_AT_MALLOC /* test the GC by forcing it before each object allocation */
+
+#define check_dump_flag(rt, flag) ((rt->dump_flags & (flag +0)) == (flag +0))
+
+#define STRINGIFY_(x) #x
+#define STRINGIFY(x) STRINGIFY_(x)
+
+#define QJS_VERSION_STRING \
+ STRINGIFY(QJS_VERSION_MAJOR) "." STRINGIFY(QJS_VERSION_MINOR) "." STRINGIFY(QJS_VERSION_PATCH) QJS_VERSION_SUFFIX
+
+const char* JS_GetVersion(void) {
+ return QJS_VERSION_STRING;
+}
+
+#undef STRINFIGY_
+#undef STRINGIFY
+
static double safe_strtod(const char *restrict nptr, char **restrict endptr)
{
#if defined(_MSC_VER) || defined(__MINGW32__)
@@ -178,20 +159,18 @@ enum {
JS_CLASS_UINT32_ARRAY, /* u.array (typed_array) */
JS_CLASS_BIG_INT64_ARRAY, /* u.array (typed_array) */
JS_CLASS_BIG_UINT64_ARRAY, /* u.array (typed_array) */
+ JS_CLASS_FLOAT16_ARRAY, /* u.array (typed_array) */
JS_CLASS_FLOAT32_ARRAY, /* u.array (typed_array) */
JS_CLASS_FLOAT64_ARRAY, /* u.array (typed_array) */
JS_CLASS_DATAVIEW, /* u.typed_array */
JS_CLASS_BIG_INT, /* u.object_data */
-#ifdef CONFIG_BIGNUM
- JS_CLASS_BIG_FLOAT, /* u.object_data */
- JS_CLASS_FLOAT_ENV, /* u.float_env */
- JS_CLASS_BIG_DECIMAL, /* u.object_data */
- JS_CLASS_OPERATOR_SET, /* u.operator_set */
-#endif
JS_CLASS_MAP, /* u.map_state */
JS_CLASS_SET, /* u.map_state */
JS_CLASS_WEAKMAP, /* u.map_state */
JS_CLASS_WEAKSET, /* u.map_state */
+ JS_CLASS_ITERATOR,
+ JS_CLASS_ITERATOR_HELPER, /* u.iterator_helper_data */
+ JS_CLASS_ITERATOR_WRAP, /* u.iterator_wrap_data */
JS_CLASS_MAP_ITERATOR, /* u.map_iterator_data */
JS_CLASS_SET_ITERATOR, /* u.map_iterator_data */
JS_CLASS_ARRAY_ITERATOR, /* u.array_iterator_data */
@@ -208,6 +187,9 @@ enum {
JS_CLASS_ASYNC_FROM_SYNC_ITERATOR, /* u.async_from_sync_iterator_data */
JS_CLASS_ASYNC_GENERATOR_FUNCTION, /* u.func */
JS_CLASS_ASYNC_GENERATOR, /* u.async_generator_data */
+ JS_CLASS_WEAK_REF,
+ JS_CLASS_FINALIZATION_REGISTRY,
+ JS_CLASS_CALL_SITE,
JS_CLASS_INIT_COUNT, /* last entry for predefined classes */
};
@@ -228,47 +210,39 @@ typedef enum JSErrorEnum {
JS_AGGREGATE_ERROR,
JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */
+ JS_PLAIN_ERROR = JS_NATIVE_ERROR_COUNT
} JSErrorEnum;
#define JS_MAX_LOCAL_VARS 65535
#define JS_STACK_SIZE_MAX 65534
#define JS_STRING_LEN_MAX ((1 << 30) - 1)
-#ifdef __GNUC__
#define __exception __attribute__((warn_unused_result))
-#else
-#define __exception
-#endif
typedef struct JSShape JSShape;
typedef struct JSString JSString;
typedef struct JSString JSAtomStruct;
+#define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v))
+
typedef enum {
JS_GC_PHASE_NONE,
JS_GC_PHASE_DECREF,
JS_GC_PHASE_REMOVE_CYCLES,
} JSGCPhaseEnum;
-typedef enum OPCodeEnum OPCodeEnum;
+typedef struct JSMallocState {
+ size_t malloc_count;
+ size_t malloc_size;
+ size_t malloc_limit;
+ void *opaque; /* user opaque */
+} JSMallocState;
-/* function pointers are used for numeric operations so that it is
- possible to remove some numeric types */
-typedef struct {
- JSValue (*to_string)(JSContext *ctx, JSValueConst val);
- JSValue (*from_string)(JSContext *ctx, const char *buf,
- int radix, int flags, slimb_t *pexponent);
- int (*unary_arith)(JSContext *ctx,
- JSValue *pres, OPCodeEnum op, JSValue op1);
- int (*binary_arith)(JSContext *ctx, OPCodeEnum op,
- JSValue *pres, JSValue op1, JSValue op2);
- int (*compare)(JSContext *ctx, OPCodeEnum op,
- JSValue op1, JSValue op2);
- /* only for bigfloat: */
- JSValue (*mul_pow10_to_float64)(JSContext *ctx, const bf_t *a,
- int64_t exponent);
- int (*mul_pow10)(JSContext *ctx, JSValue *sp);
-} JSNumericOperations;
+typedef struct JSRuntimeFinalizerState {
+ struct JSRuntimeFinalizerState *next;
+ JSRuntimeFinalizer *finalizer;
+ void *arg;
+} JSRuntimeFinalizerState;
struct JSRuntime {
JSMallocFunctions mf;
@@ -283,6 +257,7 @@ struct JSRuntime {
JSAtomStruct **atom_array;
int atom_free_index; /* 0 = none */
+ JSClassID js_class_id_alloc; /* counter for user defined classes */
int class_count; /* size of class_array */
JSClass *class_array;
@@ -295,7 +270,7 @@ struct JSRuntime {
struct list_head tmp_obj_list; /* used during GC */
JSGCPhaseEnum gc_phase : 8;
size_t malloc_gc_threshold;
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
struct list_head string_list; /* list of JSString.link */
#endif
/* stack limitation */
@@ -305,7 +280,11 @@ struct JSRuntime {
JSValue current_exception;
/* true if inside an out of memory error, to avoid recursing */
- BOOL in_out_of_memory : 8;
+ bool in_out_of_memory;
+ /* true if inside build_backtrace, to avoid recursing */
+ bool in_build_stack_trace;
+ /* true if inside JS_FreeRuntime */
+ bool in_free;
struct JSStackFrame *current_stack_frame;
@@ -323,23 +302,21 @@ struct JSRuntime {
/* timestamp for internal use in module evaluation */
int64_t module_async_evaluation_next_timestamp;
- BOOL can_block : 8; /* TRUE if Atomics.wait can block */
/* used to allocate, free and clone SharedArrayBuffers */
JSSharedArrayBufferFunctions sab_funcs;
+ bool can_block; /* true if Atomics.wait can block */
+ uint32_t dump_flags : 24;
+
/* Shape hash table */
int shape_hash_bits;
int shape_hash_size;
int shape_hash_count; /* number of hashed shapes */
JSShape **shape_hash;
bf_context_t bf_ctx;
- JSNumericOperations bigint_ops;
-#ifdef CONFIG_BIGNUM
- JSNumericOperations bigfloat_ops;
- JSNumericOperations bigdecimal_ops;
- uint32_t operator_count;
-#endif
void *user_opaque;
+ void *libc_opaque;
+ JSRuntimeFinalizerState *finalizers;
};
struct JSClass {
@@ -352,21 +329,16 @@ struct JSClass {
const JSClassExoticMethods *exotic;
};
-#define JS_MODE_STRICT (1 << 0)
-#define JS_MODE_STRIP (1 << 1)
-#define JS_MODE_MATH (1 << 2)
-#define JS_MODE_ASYNC (1 << 3) /* async function */
-
typedef struct JSStackFrame {
struct JSStackFrame *prev_frame; /* NULL if first stack frame */
JSValue cur_func; /* current function, JS_UNDEFINED if the frame is detached */
JSValue *arg_buf; /* arguments */
JSValue *var_buf; /* variables */
- struct list_head var_ref_list; /* list of JSVarRef.var_ref_link */
- const uint8_t *cur_pc; /* only used in bytecode functions : PC of the
+ struct list_head var_ref_list; /* list of JSVarRef.link */
+ uint8_t *cur_pc; /* only used in bytecode functions : PC of the
instruction after the call */
- int arg_count;
- int js_mode; /* for C functions, only JS_MODE_MATH may be set */
+ uint32_t arg_count : 31;
+ uint32_t is_strict_mode : 1;
/* only used in generators. Current stack pointer value. NULL if
the function is running. */
JSValue *cur_sp;
@@ -399,6 +371,11 @@ typedef struct JSVarRef {
struct {
int __gc_ref_count; /* corresponds to header.ref_count */
uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */
+
+ /* 0 : the JSVarRef is on the stack. header.link is an element
+ of JSStackFrame.var_ref_list.
+ 1 : the JSVarRef is detached. header.link has the normal meanning
+ */
uint8_t is_detached : 1;
uint8_t is_arg : 1;
uint16_t var_idx; /* index of the corresponding function variable on
@@ -407,34 +384,19 @@ typedef struct JSVarRef {
};
JSValue *pvalue; /* pointer to the value, either on the stack or
to 'value' */
- union {
- JSValue value; /* used when is_detached = TRUE */
- struct {
- struct list_head var_ref_link; /* JSStackFrame.var_ref_list list */
- struct JSAsyncFunctionState *async_func; /* != NULL if async stack frame */
- }; /* used when is_detached = FALSE */
- };
+ JSValue value; /* used when the variable is no longer on the stack */
} JSVarRef;
-/* the same structure is used for big integers and big floats. Big
- integers are never infinite or NaNs */
-typedef struct JSBigFloat {
- JSRefCountHeader header; /* must come first, 32-bit */
- bf_t num;
-} JSBigFloat;
-
-#ifdef CONFIG_BIGNUM
-typedef struct JSFloatEnv {
- limb_t prec;
- bf_flags_t flags;
- unsigned int status;
-} JSFloatEnv;
+typedef struct JSRefCountHeader {
+ int ref_count;
+} JSRefCountHeader;
-typedef struct JSBigDecimal {
+/* the same structure is used for big integers.
+ Big integers are never infinite or NaNs */
+typedef struct JSBigInt {
JSRefCountHeader header; /* must come first, 32-bit */
- bfdec_t num;
-} JSBigDecimal;
-#endif
+ bf_t num;
+} JSBigInt;
typedef enum {
JS_AUTOINIT_ID_PROTOTYPE,
@@ -463,6 +425,11 @@ struct JSContext {
JSValue regexp_ctor;
JSValue promise_ctor;
JSValue native_error_proto[JS_NATIVE_ERROR_COUNT];
+ JSValue error_ctor;
+ JSValue error_back_trace;
+ JSValue error_prepare_stack;
+ JSValue error_stack_trace_limit;
+ JSValue iterator_ctor;
JSValue iterator_proto;
JSValue async_iterator_proto;
JSValue array_proto_values;
@@ -472,23 +439,20 @@ struct JSContext {
JSValue global_obj; /* global object */
JSValue global_var_obj; /* contains the global let/const definitions */
+ double time_origin;
+
uint64_t random_state;
bf_context_t *bf_ctx; /* points to rt->bf_ctx, shared by all contexts */
-#ifdef CONFIG_BIGNUM
- JSFloatEnv fp_env; /* global FP environment */
- BOOL bignum_ext : 8; /* enable math mode */
- BOOL allow_operator_overloading : 8;
-#endif
/* when the counter reaches zero, JSRutime.interrupt_handler is called */
int interrupt_counter;
struct list_head loaded_modules; /* list of JSModuleDef.link */
/* if NULL, RegExp compilation is not supported */
- JSValue (*compile_regexp)(JSContext *ctx, JSValueConst pattern,
- JSValueConst flags);
+ JSValue (*compile_regexp)(JSContext *ctx, JSValue pattern,
+ JSValue flags);
/* if NULL, eval is not supported */
- JSValue (*eval_internal)(JSContext *ctx, JSValueConst this_obj,
+ JSValue (*eval_internal)(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
const char *filename, int line, int flags, int scope_idx);
void *user_opaque;
@@ -504,6 +468,22 @@ typedef union JSFloat64Union {
uint32_t u32[2];
} JSFloat64Union;
+typedef enum {
+ JS_WEAK_REF_KIND_MAP,
+ JS_WEAK_REF_KIND_WEAK_REF,
+ JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY,
+} JSWeakRefKindEnum;
+
+typedef struct JSWeakRefRecord {
+ JSWeakRefKindEnum kind;
+ struct JSWeakRefRecord *next_weak_ref;
+ union {
+ struct JSMapRecord *map_record;
+ struct JSWeakRefData *weak_ref_data;
+ struct JSFinRecEntry *fin_rec_entry;
+ } u;
+} JSWeakRefRecord;
+
enum {
JS_ATOM_TYPE_STRING = 1,
JS_ATOM_TYPE_GLOBAL_SYMBOL,
@@ -534,12 +514,13 @@ struct JSString {
uint32_t hash : 30;
uint8_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */
uint32_t hash_next; /* atom_index for JS_ATOM_TYPE_SYMBOL */
-#ifdef DUMP_LEAKS
+ JSWeakRefRecord *first_weak_ref;
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
struct list_head link; /* string list */
#endif
union {
- uint8_t str8[0]; /* 8 bit strings will get an extra null terminator */
- uint16_t str16[0];
+ __extension__ uint8_t str8[0]; /* 8 bit strings will get an extra null terminator */
+ __extension__ uint16_t str16[0];
} u;
};
@@ -550,7 +531,7 @@ typedef struct JSClosureVar {
uint8_t is_lexical : 1;
uint8_t var_kind : 4; /* see JSVarKindEnum */
/* 8 bits available */
- uint16_t var_idx; /* is_local = TRUE: index to a normal variable of the
+ uint16_t var_idx; /* is_local = true: index to a normal variable of the
parent function. otherwise: index to a closure
variable of the parent function */
JSAtom var_name;
@@ -624,7 +605,7 @@ typedef enum JSFunctionKindEnum {
typedef struct JSFunctionBytecode {
JSGCObjectHeader header; /* must come first */
- uint8_t js_mode;
+ uint8_t is_strict_mode : 1;
uint8_t has_prototype : 1; /* true if a prototype field is necessary */
uint8_t has_simple_parameter_list : 1;
uint8_t is_derived_class_constructor : 1;
@@ -635,11 +616,8 @@ typedef struct JSFunctionBytecode {
uint8_t super_call_allowed : 1;
uint8_t super_allowed : 1;
uint8_t arguments_allowed : 1;
- uint8_t has_debug : 1;
uint8_t backtrace_barrier : 1; /* stop backtrace on this function */
- uint8_t read_only_bytecode : 1;
- uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */
- /* XXX: 10 bits available */
+ /* XXX: 5 bits available */
uint8_t *byte_code_buf; /* (self pointer) */
int byte_code_len;
JSAtom func_name;
@@ -653,22 +631,20 @@ typedef struct JSFunctionBytecode {
JSValue *cpool; /* constant pool (self pointer) */
int cpool_count;
int closure_var_count;
- struct {
- /* debug info, move to separate structure to save memory? */
- JSAtom filename;
- int line_num;
- int source_len;
- int pc2line_len;
- uint8_t *pc2line_buf;
- char *source;
- } debug;
+ JSAtom filename;
+ int line_num;
+ int col_num;
+ int source_len;
+ int pc2line_len;
+ uint8_t *pc2line_buf;
+ char *source;
} JSFunctionBytecode;
typedef struct JSBoundFunction {
JSValue func_obj;
JSValue this_val;
int argc;
- JSValue argv[0];
+ JSValue argv[];
} JSBoundFunction;
typedef enum JSIteratorKindEnum {
@@ -677,13 +653,23 @@ typedef enum JSIteratorKindEnum {
JS_ITERATOR_KIND_KEY_AND_VALUE,
} JSIteratorKindEnum;
+typedef enum JSIteratorHelperKindEnum {
+ JS_ITERATOR_HELPER_KIND_DROP,
+ JS_ITERATOR_HELPER_KIND_EVERY,
+ JS_ITERATOR_HELPER_KIND_FILTER,
+ JS_ITERATOR_HELPER_KIND_FIND,
+ JS_ITERATOR_HELPER_KIND_FLAT_MAP,
+ JS_ITERATOR_HELPER_KIND_FOR_EACH,
+ JS_ITERATOR_HELPER_KIND_MAP,
+ JS_ITERATOR_HELPER_KIND_SOME,
+ JS_ITERATOR_HELPER_KIND_TAKE,
+} JSIteratorHelperKindEnum;
+
typedef struct JSForInIterator {
JSValue obj;
+ bool is_array;
+ uint32_t array_length;
uint32_t idx;
- uint32_t atom_count;
- uint8_t in_prototype_chain;
- uint8_t is_array;
- JSPropertyEnum *tab_atom; /* is_array = FALSE */
} JSForInIterator;
typedef struct JSRegExp {
@@ -700,6 +686,7 @@ typedef struct JSProxyData {
typedef struct JSArrayBuffer {
int byte_length; /* 0 if detached */
+ int max_byte_length; /* -1 if not resizable; >= byte_length otherwise */
uint8_t detached;
uint8_t shared; /* if shared, the array buffer cannot be detached */
uint8_t *data; /* NULL if detached */
@@ -712,67 +699,26 @@ typedef struct JSTypedArray {
struct list_head link; /* link to arraybuffer */
JSObject *obj; /* back pointer to the TypedArray/DataView object */
JSObject *buffer; /* based array buffer */
- uint32_t offset; /* offset in the array buffer */
- uint32_t length; /* length in the array buffer */
+ uint32_t offset; /* byte offset in the array buffer */
+ uint32_t length; /* byte length in the array buffer */
+ bool track_rab; /* auto-track length of backing array buffer */
} JSTypedArray;
typedef struct JSAsyncFunctionState {
- JSGCObjectHeader header;
- JSValue this_val; /* 'this' argument */
+ JSValue this_val; /* 'this' generator argument */
int argc; /* number of function arguments */
- BOOL throw_flag; /* used to throw an exception in JS_CallInternal() */
- BOOL is_completed; /* TRUE if the function has returned. The stack
- frame is no longer valid */
- JSValue resolving_funcs[2]; /* only used in JS async functions */
+ bool throw_flag; /* used to throw an exception in JS_CallInternal() */
JSStackFrame frame;
} JSAsyncFunctionState;
-typedef enum {
- /* binary operators */
- JS_OVOP_ADD,
- JS_OVOP_SUB,
- JS_OVOP_MUL,
- JS_OVOP_DIV,
- JS_OVOP_MOD,
- JS_OVOP_POW,
- JS_OVOP_OR,
- JS_OVOP_AND,
- JS_OVOP_XOR,
- JS_OVOP_SHL,
- JS_OVOP_SAR,
- JS_OVOP_SHR,
- JS_OVOP_EQ,
- JS_OVOP_LESS,
-
- JS_OVOP_BINARY_COUNT,
- /* unary operators */
- JS_OVOP_POS = JS_OVOP_BINARY_COUNT,
- JS_OVOP_NEG,
- JS_OVOP_INC,
- JS_OVOP_DEC,
- JS_OVOP_NOT,
-
- JS_OVOP_COUNT,
-} JSOverloadableOperatorEnum;
-
-typedef struct {
- uint32_t operator_index;
- JSObject *ops[JS_OVOP_BINARY_COUNT]; /* self operators */
-} JSBinaryOperatorDefEntry;
-
-typedef struct {
- int count;
- JSBinaryOperatorDefEntry *tab;
-} JSBinaryOperatorDef;
-
-typedef struct {
- uint32_t operator_counter;
- BOOL is_primitive; /* OperatorSet for a primitive type */
- /* NULL if no operator is defined */
- JSObject *self_ops[JS_OVOP_COUNT]; /* self operators */
- JSBinaryOperatorDef left;
- JSBinaryOperatorDef right;
-} JSOperatorSetData;
+/* XXX: could use an object instead to avoid the
+ JS_TAG_ASYNC_FUNCTION tag for the GC */
+typedef struct JSAsyncFunctionData {
+ JSGCObjectHeader header; /* must come first */
+ JSValue resolving_funcs[2];
+ bool is_active; /* true if the async function state is valid */
+ JSAsyncFunctionState func_state;
+} JSAsyncFunctionData;
typedef struct JSReqModuleEntry {
JSAtom module_name;
@@ -841,9 +787,9 @@ struct JSModuleDef {
JSValue module_ns;
JSValue func_obj; /* only used for JS modules */
JSModuleInitFunc *init_func; /* only used for C modules */
- BOOL has_tla : 8; /* true if func_obj contains await */
- BOOL resolved : 8;
- BOOL func_created : 8;
+ bool has_tla; /* true if func_obj contains await */
+ bool resolved;
+ bool func_created;
JSModuleStatus status : 8;
/* temp use during js_module_link() & js_module_evaluate() */
int dfs_index, dfs_ancestor_index;
@@ -853,15 +799,14 @@ struct JSModuleDef {
int async_parent_modules_count;
int async_parent_modules_size;
int pending_async_dependencies;
- BOOL async_evaluation;
+ bool async_evaluation;
int64_t async_evaluation_timestamp;
JSModuleDef *cycle_root;
JSValue promise; /* corresponds to spec field: capability */
JSValue resolving_funcs[2]; /* corresponds to spec field: capability */
-
/* true if evaluation yielded an exception. It is saved in
eval_exception */
- BOOL eval_has_exception : 8;
+ bool eval_has_exception;
JSValue eval_exception;
JSValue meta_obj; /* for import.meta */
};
@@ -871,7 +816,7 @@ typedef struct JSJobEntry {
JSContext *ctx;
JSJobFunc *job_func;
int argc;
- JSValue argv[0];
+ JSValue argv[];
} JSJobEntry;
typedef struct JSProperty {
@@ -920,7 +865,7 @@ struct JSShape {
int deleted_prop_count;
JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */
JSObject *proto;
- JSShapeProperty prop[0]; /* prop_size elements */
+ JSShapeProperty prop[]; /* prop_size elements */
};
struct JSObject {
@@ -932,10 +877,10 @@ struct JSObject {
uint8_t extensible : 1;
uint8_t free_mark : 1; /* only used when freeing objects with cycles */
- uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */
- uint8_t fast_array : 1; /* TRUE if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */
- uint8_t is_constructor : 1; /* TRUE if object is a constructor function */
- uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */
+ uint8_t is_exotic : 1; /* true if object has exotic property handlers */
+ uint8_t fast_array : 1; /* true if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */
+ uint8_t is_constructor : 1; /* true if object is a constructor function */
+ uint8_t is_uncatchable_error : 1; /* if true, error is not catchable */
uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */
uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */
uint16_t class_id; /* see JS_CLASS_x */
@@ -945,7 +890,7 @@ struct JSObject {
JSShape *shape; /* prototype and property names + flag */
JSProperty *prop; /* array of properties */
/* byte offsets: 24/40 */
- struct JSMapRecord *first_weak_ref; /* XXX: use a bit and an external hash table? */
+ JSWeakRefRecord *first_weak_ref;
/* byte offsets: 28/48 */
union {
void *opaque;
@@ -954,19 +899,17 @@ struct JSObject {
struct JSForInIterator *for_in_iterator; /* JS_CLASS_FOR_IN_ITERATOR */
struct JSArrayBuffer *array_buffer; /* JS_CLASS_ARRAY_BUFFER, JS_CLASS_SHARED_ARRAY_BUFFER */
struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_DATAVIEW */
-#ifdef CONFIG_BIGNUM
- struct JSFloatEnv *float_env; /* JS_CLASS_FLOAT_ENV */
- struct JSOperatorSetData *operator_set; /* JS_CLASS_OPERATOR_SET */
-#endif
struct JSMapState *map_state; /* JS_CLASS_MAP..JS_CLASS_WEAKSET */
struct JSMapIteratorData *map_iterator_data; /* JS_CLASS_MAP_ITERATOR, JS_CLASS_SET_ITERATOR */
struct JSArrayIteratorData *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, JS_CLASS_STRING_ITERATOR */
struct JSRegExpStringIteratorData *regexp_string_iterator_data; /* JS_CLASS_REGEXP_STRING_ITERATOR */
struct JSGeneratorData *generator_data; /* JS_CLASS_GENERATOR */
+ struct JSIteratorHelperData *iterator_helper_data; /* JS_CLASS_ITERATOR_HELPER */
+ struct JSIteratorWrapData *iterator_wrap_data; /* JS_CLASS_ITERATOR_WRAP */
struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */
struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */
struct JSPromiseFunctionData *promise_function_data; /* JS_CLASS_PROMISE_RESOLVE_FUNCTION, JS_CLASS_PROMISE_REJECT_FUNCTION */
- struct JSAsyncFunctionState *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */
+ struct JSAsyncFunctionData *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */
struct JSAsyncFromSyncIteratorData *async_from_sync_iterator_data; /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR */
struct JSAsyncGeneratorData *async_generator_data; /* JS_CLASS_ASYNC_GENERATOR */
struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */
@@ -999,6 +942,7 @@ struct JSObject {
uint32_t *uint32_ptr; /* JS_CLASS_UINT32_ARRAY */
int64_t *int64_ptr; /* JS_CLASS_INT64_ARRAY */
uint64_t *uint64_ptr; /* JS_CLASS_UINT64_ARRAY */
+ uint16_t *fp16_ptr; /* JS_CLASS_FLOAT16_ARRAY */
float *float_ptr; /* JS_CLASS_FLOAT32_ARRAY */
double *double_ptr; /* JS_CLASS_FLOAT64_ARRAY */
} u;
@@ -1010,6 +954,15 @@ struct JSObject {
/* byte sizes: 40/48/72 */
};
+typedef struct JSCallSiteData {
+ JSValue filename;
+ JSValue func;
+ JSValue func_name;
+ bool native;
+ int line_num;
+ int col_num;
+} JSCallSiteData;
+
enum {
__JS_ATOM_NULL = JS_ATOM_NULL,
#define DEF(name, str) JS_ATOM_ ## name,
@@ -1034,7 +987,7 @@ typedef enum OPCodeFormat {
#undef FMT
} OPCodeFormat;
-enum OPCodeEnum {
+typedef enum OPCodeEnum {
#define FMT(f)
#define DEF(id, size, n_pop, n_push, f) OP_ ## id,
#define def(id, size, n_pop, n_push, f)
@@ -1054,96 +1007,99 @@ enum OPCodeEnum {
#undef DEF
#undef FMT
OP_TEMP_END,
-};
+} OPCodeEnum;
static int JS_InitAtoms(JSRuntime *rt);
static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
int atom_type);
static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p);
static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b);
-static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_obj,
- int argc, JSValueConst *argv, int flags);
-static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_obj,
- int argc, JSValueConst *argv, int flags);
-static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_obj, JSValueConst new_target,
+static JSValue js_call_c_function(JSContext *ctx, JSValue func_obj,
+ JSValue this_obj,
+ int argc, JSValue *argv, int flags);
+static JSValue js_call_bound_function(JSContext *ctx, JSValue func_obj,
+ JSValue this_obj,
+ int argc, JSValue *argv, int flags);
+static JSValue JS_CallInternal(JSContext *ctx, JSValue func_obj,
+ JSValue this_obj, JSValue new_target,
int argc, JSValue *argv, int flags);
static JSValue JS_CallConstructorInternal(JSContext *ctx,
- JSValueConst func_obj,
- JSValueConst new_target,
+ JSValue func_obj,
+ JSValue new_target,
int argc, JSValue *argv, int flags);
-static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv);
+static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValue this_obj,
+ int argc, JSValue *argv);
static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
- int argc, JSValueConst *argv);
+ int argc, JSValue *argv);
static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
- JSValue val, BOOL is_array_ctor);
-static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
- JSValueConst val, int flags, int scope_idx);
-static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);
+ JSValue val, bool is_array_ctor);
+static JSValue JS_EvalObject(JSContext *ctx, JSValue this_obj,
+ JSValue val, int flags, int scope_idx);
+JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...);
+
static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p);
static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
-static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, JSValueConst val);
-static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
-static __maybe_unused void JS_PrintValue(JSContext *ctx,
- const char *str,
- JSValueConst val);
+static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValue val);
+static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);
static __maybe_unused void JS_DumpShapes(JSRuntime *rt);
-static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic);
+
+static JSValue js_function_apply(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic);
static void js_array_finalizer(JSRuntime *rt, JSValue val);
-static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
+static void js_array_mark(JSRuntime *rt, JSValue val,
+ JS_MarkFunc *mark_func);
static void js_object_data_finalizer(JSRuntime *rt, JSValue val);
-static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
+static void js_object_data_mark(JSRuntime *rt, JSValue val,
+ JS_MarkFunc *mark_func);
static void js_c_function_finalizer(JSRuntime *rt, JSValue val);
-static void js_c_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
+static void js_c_function_mark(JSRuntime *rt, JSValue val,
+ JS_MarkFunc *mark_func);
static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val);
-static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,
+static void js_bytecode_function_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static void js_bound_function_finalizer(JSRuntime *rt, JSValue val);
-static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,
+static void js_bound_function_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val);
-static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val,
+static void js_for_in_iterator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static void js_regexp_finalizer(JSRuntime *rt, JSValue val);
static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val);
static void js_typed_array_finalizer(JSRuntime *rt, JSValue val);
-static void js_typed_array_mark(JSRuntime *rt, JSValueConst val,
+static void js_typed_array_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static void js_proxy_finalizer(JSRuntime *rt, JSValue val);
-static void js_proxy_mark(JSRuntime *rt, JSValueConst val,
+static void js_proxy_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static void js_map_finalizer(JSRuntime *rt, JSValue val);
-static void js_map_mark(JSRuntime *rt, JSValueConst val,
+static void js_map_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static void js_map_iterator_finalizer(JSRuntime *rt, JSValue val);
-static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val,
+static void js_map_iterator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val);
-static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val,
+static void js_array_iterator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
+static void js_iterator_helper_finalizer(JSRuntime *rt, JSValue val);
+static void js_iterator_helper_mark(JSRuntime *rt, JSValue val,
+ JS_MarkFunc *mark_func);
+static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValue val);
+static void js_iterator_wrap_mark(JSRuntime *rt, JSValue val,
+ JS_MarkFunc *mark_func);
static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val);
-static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val,
+static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static void js_generator_finalizer(JSRuntime *rt, JSValue obj);
-static void js_generator_mark(JSRuntime *rt, JSValueConst val,
+static void js_generator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static void js_promise_finalizer(JSRuntime *rt, JSValue val);
-static void js_promise_mark(JSRuntime *rt, JSValueConst val,
+static void js_promise_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValue val);
-static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val,
+static void js_promise_resolve_function_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
-#ifdef CONFIG_BIGNUM
-static void js_operator_set_finalizer(JSRuntime *rt, JSValue val);
-static void js_operator_set_mark(JSRuntime *rt, JSValueConst val,
- JS_MarkFunc *mark_func);
-#endif
#define HINT_STRING 0
#define HINT_NUMBER 1
@@ -1155,13 +1111,16 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val);
static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val);
static int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val);
static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val);
-static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
- JSValueConst flags);
-static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor,
+static JSValue js_new_string8_len(JSContext *ctx, const char *buf, int len);
+static JSValue js_compile_regexp(JSContext *ctx, JSValue pattern,
+ JSValue flags);
+static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValue ctor,
JSValue pattern, JSValue bc);
static void gc_decref(JSRuntime *rt);
static int JS_NewClass1(JSRuntime *rt, JSClassID class_id,
const JSClassDef *class_def, JSAtom name);
+static JSValue js_array_push(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int unshift);
typedef enum JSStrictEqModeEnum {
JS_EQ_STRICT,
@@ -1169,120 +1128,106 @@ typedef enum JSStrictEqModeEnum {
JS_EQ_SAME_VALUE_ZERO,
} JSStrictEqModeEnum;
-static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
+static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
JSStrictEqModeEnum eq_mode);
-static BOOL js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2);
-static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2);
-static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2);
-static JSValue JS_ToObject(JSContext *ctx, JSValueConst val);
+static bool js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2);
+static bool js_same_value(JSContext *ctx, JSValue op1, JSValue op2);
+static bool js_same_value_zero(JSContext *ctx, JSValue op1, JSValue op2);
static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val);
static JSProperty *add_property(JSContext *ctx,
JSObject *p, JSAtom prop, int prop_flags);
static JSValue JS_NewBigInt(JSContext *ctx);
-static inline bf_t *JS_GetBigInt(JSValueConst val)
+static inline bf_t *JS_GetBigInt(JSValue val)
{
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
+ JSBigInt *p = JS_VALUE_GET_PTR(val);
return &p->num;
}
-static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,
- BOOL convert_to_safe_integer);
+static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val);
static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val);
static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val);
-static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val);
+static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValue val);
+static bf_t *JS_ToBigInt1(JSContext *ctx, bf_t *buf, JSValue val);
static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf);
-#ifdef CONFIG_BIGNUM
-static void js_float_env_finalizer(JSRuntime *rt, JSValue val);
-static JSValue JS_NewBigFloat(JSContext *ctx);
-static inline bf_t *JS_GetBigFloat(JSValueConst val)
-{
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- return &p->num;
-}
-static JSValue JS_NewBigDecimal(JSContext *ctx);
-static inline bfdec_t *JS_GetBigDecimal(JSValueConst val)
-{
- JSBigDecimal *p = JS_VALUE_GET_PTR(val);
- return &p->num;
-}
-static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val);
-static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,
- BOOL allow_null_or_undefined);
-static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val);
-#endif
+JSValue JS_ThrowOutOfMemory(JSContext *ctx);
static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);
-static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);
-static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
- JSValueConst proto_val, BOOL throw_flag);
-
-static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, int throw_exception);
-static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj);
-static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj);
+static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValue obj);
+static int js_proxy_setPrototypeOf(JSContext *ctx, JSValue obj,
+ JSValue proto_val, bool throw_flag);
+static int js_proxy_isExtensible(JSContext *ctx, JSValue obj);
+static int js_proxy_preventExtensions(JSContext *ctx, JSValue obj);
+static int js_proxy_isArray(JSContext *ctx, JSValue obj);
static int JS_CreateProperty(JSContext *ctx, JSObject *p,
- JSAtom prop, JSValueConst val,
- JSValueConst getter, JSValueConst setter,
+ JSAtom prop, JSValue val,
+ JSValue getter, JSValue setter,
int flags);
static int js_string_memcmp(const JSString *p1, const JSString *p2, int len);
-static void reset_weak_ref(JSRuntime *rt, JSObject *p);
+static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref);
+static bool is_valid_weakref_target(JSValue val);
+static void insert_weakref_record(JSValue target, struct JSWeakRefRecord *wr);
static JSValue js_array_buffer_constructor3(JSContext *ctx,
- JSValueConst new_target,
- uint64_t len, JSClassID class_id,
+ JSValue new_target,
+ uint64_t len, uint64_t *max_len,
+ JSClassID class_id,
uint8_t *buf,
JSFreeArrayBufferDataFunc *free_func,
- void *opaque, BOOL alloc_flag);
-static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj);
+ void *opaque, bool alloc_flag);
+static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr);
+static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValue obj);
+static bool array_buffer_is_resizable(const JSArrayBuffer *abuf);
static JSValue js_typed_array_constructor(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv,
+ JSValue this_val,
+ int argc, JSValue *argv,
int classid);
static JSValue js_typed_array_constructor_ta(JSContext *ctx,
- JSValueConst new_target,
- JSValueConst src_obj,
- int classid);
-static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p);
+ JSValue new_target,
+ JSValue src_obj,
+ int classid, uint32_t len);
+static bool is_typed_array(JSClassID class_id);
+static bool typed_array_is_oob(JSObject *p);
static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p);
static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx);
+static JSValue JS_ThrowTypeErrorArrayBufferOOB(JSContext *ctx);
static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx,
- BOOL is_arg);
-static void __async_func_free(JSRuntime *rt, JSAsyncFunctionState *s);
-static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s);
-static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_obj,
- int argc, JSValueConst *argv,
+ bool is_arg);
+static JSValue js_generator_function_call(JSContext *ctx, JSValue func_obj,
+ JSValue this_obj,
+ int argc, JSValue *argv,
int flags);
static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val);
-static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,
+static void js_async_function_resolve_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
-static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
+static JSValue JS_EvalInternal(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
const char *filename, int line, int flags, int scope_idx);
static void js_free_module_def(JSContext *ctx, JSModuleDef *m);
static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
JS_MarkFunc *mark_func);
static JSValue js_import_meta(JSContext *ctx);
-static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier);
+static JSValue js_dynamic_import(JSContext *ctx, JSValue specifier);
static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref);
static JSValue js_new_promise_capability(JSContext *ctx,
JSValue *resolving_funcs,
- JSValueConst ctor);
+ JSValue ctor);
static __exception int perform_promise_then(JSContext *ctx,
- JSValueConst promise,
- JSValueConst *resolve_reject,
- JSValueConst *cap_resolving_funcs);
-static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic);
-static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv);
-static int js_string_compare(JSContext *ctx,
- const JSString *p1, const JSString *p2);
-static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val);
-static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
+ JSValue promise,
+ JSValue *resolve_reject,
+ JSValue *cap_resolving_funcs);
+static JSValue js_promise_resolve(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic);
+static JSValue js_promise_then(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv);
+static bool js_string_eq(const JSString *p1, const JSString *p2);
+static int js_string_compare(const JSString *p1, const JSString *p2);
+static int JS_SetPropertyValue(JSContext *ctx, JSValue this_obj,
JSValue prop, JSValue val, int flags);
-static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val);
-static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val);
+static int JS_NumberIsInteger(JSContext *ctx, JSValue val);
+static bool JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValue val);
static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val);
static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc,
JSObject *p, JSAtom prop);
static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc);
+static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s,
+ JS_MarkFunc *mark_func);
static void JS_AddIntrinsicBasicObjects(JSContext *ctx);
static void js_free_shape(JSRuntime *rt, JSShape *sh);
static void js_free_shape_null(JSRuntime *rt, JSShape *sh);
@@ -1290,53 +1235,154 @@ static int js_shape_prepare_update(JSContext *ctx, JSObject *p,
JSShapeProperty **pprs);
static int init_shape_hash(JSRuntime *rt);
static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
- JSValueConst obj);
+ JSValue obj);
static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
- JSValueConst obj);
+ JSValue obj);
+static __exception int js_set_length64(JSContext *ctx, JSValue obj,
+ int64_t len);
static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len);
static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
- JSValueConst array_arg);
-static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
+ JSValue array_arg);
+static JSValue js_create_array(JSContext *ctx, int len, JSValue *tab);
+static bool js_get_fast_array(JSContext *ctx, JSValue obj,
JSValue **arrpp, uint32_t *countp);
+static int expand_fast_array(JSContext *ctx, JSObject *p, uint32_t new_len);
static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx,
- JSValueConst sync_iter);
+ JSValue sync_iter);
static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val);
-static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val,
+static void js_c_function_data_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
-static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_val,
- int argc, JSValueConst *argv, int flags);
+static JSValue js_c_function_data_call(JSContext *ctx, JSValue func_obj,
+ JSValue this_val,
+ int argc, JSValue *argv, int flags);
static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val);
static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,
JSGCObjectTypeEnum type);
static void remove_gc_object(JSGCObjectHeader *h);
+static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s);
static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,
void *opaque);
static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p,
JSAtom atom, void *opaque);
-static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int is_map);
+
+static void js_set_uncatchable_error(JSContext *ctx, JSValue val, bool flag);
+
+static JSValue js_new_callsite(JSContext *ctx, JSCallSiteData *csd);
+static void js_new_callsite_data(JSContext *ctx, JSCallSiteData *csd, JSStackFrame *sf);
+static void js_new_callsite_data2(JSContext *ctx, JSCallSiteData *csd, const char *filename, int line_num, int col_num);
+static void _JS_AddIntrinsicCallSite(JSContext *ctx);
+
+static void JS_SetOpaqueInternal(JSValue obj, void *opaque);
static const JSClassExoticMethods js_arguments_exotic_methods;
static const JSClassExoticMethods js_string_exotic_methods;
static const JSClassExoticMethods js_proxy_exotic_methods;
static const JSClassExoticMethods js_module_ns_exotic_methods;
-static JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT;
+
+static inline bool double_is_int32(double d)
+{
+ uint64_t u, e;
+ JSFloat64Union t;
+
+ t.d = d;
+ u = t.u64;
+
+ e = ((u >> 52) & 0x7FF) - 1023;
+ if (e > 30) {
+ // accept 0, INT32_MIN, reject too large, too small, nan, inf, -0
+ return !u || (u == 0xc1e0000000000000);
+ } else {
+ // shift out sign, exponent and whole part bits
+ // value is fractional if remaining low bits are non-zero
+ return !(u << 12 << e);
+ }
+}
+
+static JSValue js_float64(double d)
+{
+ return __JS_NewFloat64(d);
+}
+
+static int compare_u32(uint32_t a, uint32_t b)
+{
+ return -(a < b) + (b < a); // -1, 0 or 1
+}
+
+static JSValue js_int32(int32_t v)
+{
+ return JS_MKVAL(JS_TAG_INT, v);
+}
+
+static JSValue js_uint32(uint32_t v)
+{
+ if (v <= INT32_MAX)
+ return js_int32(v);
+ else
+ return js_float64(v);
+}
+
+static JSValue js_int64(int64_t v)
+{
+ if (v >= INT32_MIN && v <= INT32_MAX)
+ return js_int32(v);
+ else
+ return js_float64(v);
+}
+
+#define JS_NewInt64(ctx, val) js_int64(val)
+
+static JSValue js_number(double d)
+{
+ if (double_is_int32(d))
+ return js_int32((int32_t)d);
+ else
+ return js_float64(d);
+}
+
+JSValue JS_NewNumber(JSContext *ctx, double d)
+{
+ return js_number(d);
+}
+
+static JSValue js_bool(bool v)
+{
+ return JS_MKVAL(JS_TAG_BOOL, (v != 0));
+}
+
+static JSValue js_dup(JSValue v)
+{
+ if (JS_VALUE_HAS_REF_COUNT(v)) {
+ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
+ p->ref_count++;
+ }
+ return v;
+}
+
+JSValue JS_DupValue(JSContext *ctx, JSValue v)
+{
+ return js_dup(v);
+}
+
+JSValue JS_DupValueRT(JSRuntime *rt, JSValue v)
+{
+ return js_dup(v);
+}
static void js_trigger_gc(JSRuntime *rt, size_t size)
{
- BOOL force_gc;
+ bool force_gc;
#ifdef FORCE_GC_AT_MALLOC
- force_gc = TRUE;
+ force_gc = true;
#else
force_gc = ((rt->malloc_state.malloc_size + size) >
rt->malloc_gc_threshold);
#endif
if (force_gc) {
-#ifdef DUMP_GC
- printf("GC: size=%" PRIu64 "\n",
- (uint64_t)rt->malloc_state.malloc_size);
+#ifdef ENABLE_DUMPS // JS_DUMP_GC
+ if (check_dump_flag(rt, JS_DUMP_GC)) {
+ printf("GC: size=%zd\n", rt->malloc_state.malloc_size);
+ }
#endif
JS_RunGC(rt);
rt->malloc_gc_threshold = rt->malloc_state.malloc_size +
@@ -1349,19 +1395,93 @@ static size_t js_malloc_usable_size_unknown(const void *ptr)
return 0;
}
+void *js_calloc_rt(JSRuntime *rt, size_t count, size_t size)
+{
+ void *ptr;
+ JSMallocState *s;
+
+ /* Do not allocate zero bytes: behavior is platform dependent */
+ assert(count != 0 && size != 0);
+
+ if (size > 0)
+ if (unlikely(count != (count * size) / size))
+ return NULL;
+
+ s = &rt->malloc_state;
+ /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */
+ if (unlikely(s->malloc_size + (count * size) > s->malloc_limit - 1))
+ return NULL;
+
+ ptr = rt->mf.js_calloc(s->opaque, count, size);
+ if (!ptr)
+ return NULL;
+
+ s->malloc_count++;
+ s->malloc_size += rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
+ return ptr;
+}
+
void *js_malloc_rt(JSRuntime *rt, size_t size)
{
- return rt->mf.js_malloc(&rt->malloc_state, size);
+ void *ptr;
+ JSMallocState *s;
+
+ /* Do not allocate zero bytes: behavior is platform dependent */
+ assert(size != 0);
+
+ s = &rt->malloc_state;
+ /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */
+ if (unlikely(s->malloc_size + size > s->malloc_limit - 1))
+ return NULL;
+
+ ptr = rt->mf.js_malloc(s->opaque, size);
+ if (!ptr)
+ return NULL;
+
+ s->malloc_count++;
+ s->malloc_size += rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
+ return ptr;
}
void js_free_rt(JSRuntime *rt, void *ptr)
{
- rt->mf.js_free(&rt->malloc_state, ptr);
+ JSMallocState *s;
+
+ if (!ptr)
+ return;
+
+ s = &rt->malloc_state;
+ s->malloc_count--;
+ s->malloc_size -= rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
+ rt->mf.js_free(s->opaque, ptr);
}
void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size)
{
- return rt->mf.js_realloc(&rt->malloc_state, ptr, size);
+ size_t old_size;
+ JSMallocState *s;
+
+ if (!ptr) {
+ if (size == 0)
+ return NULL;
+ return js_malloc_rt(rt, size);
+ }
+ if (unlikely(size == 0)) {
+ js_free_rt(rt, ptr);
+ return NULL;
+ }
+ old_size = rt->mf.js_malloc_usable_size(ptr);
+ s = &rt->malloc_state;
+ /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */
+ if (s->malloc_size + size - old_size > s->malloc_limit - 1)
+ return NULL;
+
+ ptr = rt->mf.js_realloc(s->opaque, ptr, size);
+ if (!ptr)
+ return NULL;
+
+ s->malloc_size += rt->mf.js_malloc_usable_size(ptr) - old_size;
+ return ptr;
}
size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr)
@@ -1369,13 +1489,16 @@ size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr)
return rt->mf.js_malloc_usable_size(ptr);
}
+/**
+ * This used to be implemented as malloc + memset, but using calloc
+ * yields better performance in initial, bursty allocations, something useful
+ * for QuickJS.
+ *
+ * More information: https://github.com/quickjs-ng/quickjs/pull/519
+ */
void *js_mallocz_rt(JSRuntime *rt, size_t size)
{
- void *ptr;
- ptr = js_malloc_rt(rt, size);
- if (!ptr)
- return NULL;
- return memset(ptr, 0, size);
+ return js_calloc_rt(rt, 1, size);
}
/* called by libbf */
@@ -1386,6 +1509,18 @@ static void *js_bf_realloc(void *opaque, void *ptr, size_t size)
}
/* Throw out of memory in case of error */
+void *js_calloc(JSContext *ctx, size_t count, size_t size)
+{
+ void *ptr;
+ ptr = js_calloc_rt(ctx->rt, count, size);
+ if (unlikely(!ptr)) {
+ JS_ThrowOutOfMemory(ctx);
+ return NULL;
+ }
+ return ptr;
+}
+
+/* Throw out of memory in case of error */
void *js_malloc(JSContext *ctx, size_t size)
{
void *ptr;
@@ -1491,9 +1626,14 @@ static inline int js_resize_array(JSContext *ctx, void **parray, int elem_size,
return 0;
}
+static void *js_dbuf_realloc(void *ctx, void *ptr, size_t size)
+{
+ return js_realloc(ctx, ptr, size);
+}
+
static inline void js_dbuf_init(JSContext *ctx, DynBuf *s)
{
- dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt);
+ dbuf_init2(s, ctx, js_dbuf_realloc);
}
static inline int is_digit(int c) {
@@ -1540,20 +1680,18 @@ static JSClassShortDef const js_std_class_def[] = {
{ JS_ATOM_Uint32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT32_ARRAY */
{ JS_ATOM_BigInt64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_INT64_ARRAY */
{ JS_ATOM_BigUint64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_UINT64_ARRAY */
+ { JS_ATOM_Float16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT16_ARRAY */
{ JS_ATOM_Float32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT32_ARRAY */
{ JS_ATOM_Float64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT64_ARRAY */
{ JS_ATOM_DataView, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_DATAVIEW */
{ JS_ATOM_BigInt, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_INT */
-#ifdef CONFIG_BIGNUM
- { JS_ATOM_BigFloat, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_FLOAT */
- { JS_ATOM_BigFloatEnv, js_float_env_finalizer, NULL }, /* JS_CLASS_FLOAT_ENV */
- { JS_ATOM_BigDecimal, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_DECIMAL */
- { JS_ATOM_OperatorSet, js_operator_set_finalizer, js_operator_set_mark }, /* JS_CLASS_OPERATOR_SET */
-#endif
{ JS_ATOM_Map, js_map_finalizer, js_map_mark }, /* JS_CLASS_MAP */
{ JS_ATOM_Set, js_map_finalizer, js_map_mark }, /* JS_CLASS_SET */
{ JS_ATOM_WeakMap, js_map_finalizer, js_map_mark }, /* JS_CLASS_WEAKMAP */
{ JS_ATOM_WeakSet, js_map_finalizer, js_map_mark }, /* JS_CLASS_WEAKSET */
+ { JS_ATOM_Iterator, NULL, NULL }, /* JS_CLASS_ITERATOR */
+ { JS_ATOM_IteratorHelper, js_iterator_helper_finalizer, js_iterator_helper_mark }, /* JS_CLASS_ITERATOR_HELPER */
+ { JS_ATOM_IteratorWrap, js_iterator_wrap_finalizer, js_iterator_wrap_mark }, /* JS_CLASS_ITERATOR_WRAP */
{ JS_ATOM_Map_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_MAP_ITERATOR */
{ JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */
{ JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */
@@ -1579,84 +1717,13 @@ static int init_class_range(JSRuntime *rt, JSClassShortDef const *tab,
return 0;
}
-static JSValue JS_ThrowUnsupportedOperation(JSContext *ctx)
-{
- return JS_ThrowTypeError(ctx, "unsupported operation");
-}
-
-static JSValue invalid_to_string(JSContext *ctx, JSValueConst val)
-{
- return JS_ThrowUnsupportedOperation(ctx);
-}
-
-static JSValue invalid_from_string(JSContext *ctx, const char *buf,
- int radix, int flags, slimb_t *pexponent)
-{
- return JS_NAN;
-}
-
-static int invalid_unary_arith(JSContext *ctx,
- JSValue *pres, OPCodeEnum op, JSValue op1)
-{
- JS_FreeValue(ctx, op1);
- JS_ThrowUnsupportedOperation(ctx);
- return -1;
-}
-
-static int invalid_binary_arith(JSContext *ctx, OPCodeEnum op,
- JSValue *pres, JSValue op1, JSValue op2)
-{
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- JS_ThrowUnsupportedOperation(ctx);
- return -1;
-}
-
-static JSValue invalid_mul_pow10_to_float64(JSContext *ctx, const bf_t *a,
- int64_t exponent)
-{
- return JS_ThrowUnsupportedOperation(ctx);
-}
-
-static int invalid_mul_pow10(JSContext *ctx, JSValue *sp)
-{
- JS_ThrowUnsupportedOperation(ctx);
- return -1;
-}
-
-static void set_dummy_numeric_ops(JSNumericOperations *ops)
-{
- ops->to_string = invalid_to_string;
- ops->from_string = invalid_from_string;
- ops->unary_arith = invalid_unary_arith;
- ops->binary_arith = invalid_binary_arith;
- ops->mul_pow10_to_float64 = invalid_mul_pow10_to_float64;
- ops->mul_pow10 = invalid_mul_pow10;
-}
-
-#if !defined(CONFIG_STACK_CHECK)
-/* no stack limitation */
-static inline uintptr_t js_get_stack_pointer(void)
-{
- return 0;
-}
-
-static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
-{
- return FALSE;
-}
-#else
-// Uses code from LLVM project.
+/* Uses code from LLVM project. */
static inline uintptr_t js_get_stack_pointer(void)
{
-#ifdef _MSC_VER
- return (uintptr_t) _AddressOfReturnAddress();
-#elif defined __has_builtin
-#if __has_builtin(__builtin_frame_address)
- return (uintptr_t) __builtin_frame_address(0);
-#endif
-#elif defined __GNUC__
- return (uintptr_t) __builtin_frame_address(0);
+#if defined(__clang__) || defined(__GNUC__)
+ return (uintptr_t)__builtin_frame_address(0);
+#elif defined(_MSC_VER)
+ return (uintptr_t)_AddressOfReturnAddress();
#else
char CharOnStack = 0;
// The volatile store here is intended to escape the local variable, to
@@ -1669,13 +1736,12 @@ static inline uintptr_t js_get_stack_pointer(void)
#endif
}
-static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
+static inline bool js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
{
uintptr_t sp;
sp = js_get_stack_pointer() - alloca_size;
return unlikely(sp < rt->stack_limit);
}
-#endif
JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
{
@@ -1684,33 +1750,30 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
memset(&ms, 0, sizeof(ms));
ms.opaque = opaque;
- ms.malloc_limit = -1;
+ ms.malloc_limit = 0;
- rt = mf->js_malloc(&ms, sizeof(JSRuntime));
+ rt = mf->js_calloc(opaque, 1, sizeof(JSRuntime));
if (!rt)
return NULL;
- memset(rt, 0, sizeof(*rt));
rt->mf = *mf;
if (!rt->mf.js_malloc_usable_size) {
/* use dummy function if none provided */
rt->mf.js_malloc_usable_size = js_malloc_usable_size_unknown;
}
+ /* Inline what js_malloc_rt does since we cannot use it here. */
+ ms.malloc_count++;
+ ms.malloc_size += rt->mf.js_malloc_usable_size(rt) + MALLOC_OVERHEAD;
rt->malloc_state = ms;
rt->malloc_gc_threshold = 256 * 1024;
bf_context_init(&rt->bf_ctx, js_bf_realloc, rt);
- set_dummy_numeric_ops(&rt->bigint_ops);
-#ifdef CONFIG_BIGNUM
- set_dummy_numeric_ops(&rt->bigfloat_ops);
- set_dummy_numeric_ops(&rt->bigdecimal_ops);
-#endif
init_list_head(&rt->context_list);
init_list_head(&rt->gc_obj_list);
init_list_head(&rt->gc_zero_ref_count_list);
rt->gc_phase = JS_GC_PHASE_NONE;
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
init_list_head(&rt->string_list);
#endif
init_list_head(&rt->job_list);
@@ -1733,10 +1796,16 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
if (init_shape_hash(rt))
goto fail;
+ rt->js_class_id_alloc = JS_CLASS_INIT_COUNT;
+
rt->stack_size = JS_DEFAULT_STACK_SIZE;
+#ifdef __wasi__
+ rt->stack_size = 0;
+#endif
+
JS_UpdateStackTop(rt);
- rt->current_exception = JS_NULL;
+ rt->current_exception = JS_UNINITIALIZED;
return rt;
fail:
@@ -1754,84 +1823,45 @@ void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque)
rt->user_opaque = opaque;
}
-/* default memory allocation functions with memory limitation */
-static size_t js_def_malloc_usable_size(const void *ptr)
+int JS_AddRuntimeFinalizer(JSRuntime *rt, JSRuntimeFinalizer *finalizer,
+ void *arg)
{
-#if defined(__APPLE__)
- return malloc_size(ptr);
-#elif defined(_WIN32)
- return _msize((void *)ptr);
-#elif defined(EMSCRIPTEN)
+ JSRuntimeFinalizerState *fs = js_malloc_rt(rt, sizeof(*fs));
+ if (!fs)
+ return -1;
+ fs->next = rt->finalizers;
+ fs->finalizer = finalizer;
+ fs->arg = arg;
+ rt->finalizers = fs;
return 0;
-#elif defined(__linux__)
- return malloc_usable_size((void *)ptr);
-#else
- /* change this to `return 0;` if compilation fails */
- return malloc_usable_size((void *)ptr);
-#endif
}
-static void *js_def_malloc(JSMallocState *s, size_t size)
+static void *js_def_calloc(void *opaque, size_t count, size_t size)
{
- void *ptr;
-
- /* Do not allocate zero bytes: behavior is platform dependent */
- assert(size != 0);
-
- if (unlikely(s->malloc_size + size > s->malloc_limit))
- return NULL;
-
- ptr = malloc(size);
- if (!ptr)
- return NULL;
-
- s->malloc_count++;
- s->malloc_size += js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
- return ptr;
+ return calloc(count, size);
}
-static void js_def_free(JSMallocState *s, void *ptr)
+static void *js_def_malloc(void *opaque, size_t size)
{
- if (!ptr)
- return;
+ return malloc(size);
+}
- s->malloc_count--;
- s->malloc_size -= js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
+static void js_def_free(void *opaque, void *ptr)
+{
free(ptr);
}
-static void *js_def_realloc(JSMallocState *s, void *ptr, size_t size)
+static void *js_def_realloc(void *opaque, void *ptr, size_t size)
{
- size_t old_size;
-
- if (!ptr) {
- if (size == 0)
- return NULL;
- return js_def_malloc(s, size);
- }
- old_size = js_def_malloc_usable_size(ptr);
- if (size == 0) {
- s->malloc_count--;
- s->malloc_size -= old_size + MALLOC_OVERHEAD;
- free(ptr);
- return NULL;
- }
- if (s->malloc_size + size - old_size > s->malloc_limit)
- return NULL;
-
- ptr = realloc(ptr, size);
- if (!ptr)
- return NULL;
-
- s->malloc_size += js_def_malloc_usable_size(ptr) - old_size;
- return ptr;
+ return realloc(ptr, size);
}
static const JSMallocFunctions def_malloc_funcs = {
+ js_def_calloc,
js_def_malloc,
js_def_free,
js_def_realloc,
- js_def_malloc_usable_size,
+ js__malloc_usable_size
};
JSRuntime *JS_NewRuntime(void)
@@ -1844,6 +1874,26 @@ void JS_SetMemoryLimit(JSRuntime *rt, size_t limit)
rt->malloc_state.malloc_limit = limit;
}
+void JS_SetDumpFlags(JSRuntime *rt, uint64_t flags)
+{
+#ifdef ENABLE_DUMPS
+ rt->dump_flags = flags;
+#endif
+}
+
+uint64_t JS_GetDumpFlags(JSRuntime *rt)
+{
+#ifdef ENABLE_DUMPS
+ return rt->dump_flags;
+#else
+ return 0;
+#endif
+}
+
+size_t JS_GetGCThreshold(JSRuntime *rt) {
+ return rt->malloc_gc_threshold;
+}
+
/* use -1 to disable automatic GC */
void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold)
{
@@ -1860,7 +1910,7 @@ void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque)
rt->interrupt_opaque = opaque;
}
-void JS_SetCanBlock(JSRuntime *rt, BOOL can_block)
+void JS_SetCanBlock(JSRuntime *rt, bool can_block)
{
rt->can_block = can_block;
}
@@ -1873,12 +1923,14 @@ void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,
/* return 0 if OK, < 0 if exception */
int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func,
- int argc, JSValueConst *argv)
+ int argc, JSValue *argv)
{
JSRuntime *rt = ctx->rt;
JSJobEntry *e;
int i;
+ assert(!rt->in_free);
+
e = js_malloc(ctx, sizeof(*e) + argc * sizeof(JSValue));
if (!e)
return -1;
@@ -1886,13 +1938,13 @@ int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func,
e->job_func = job_func;
e->argc = argc;
for(i = 0; i < argc; i++) {
- e->argv[i] = JS_DupValue(ctx, argv[i]);
+ e->argv[i] = js_dup(argv[i]);
}
list_add_tail(&e->link, &rt->job_list);
return 0;
}
-BOOL JS_IsJobPending(JSRuntime *rt)
+bool JS_IsJobPending(JSRuntime *rt)
{
return !list_empty(&rt->job_list);
}
@@ -1915,7 +1967,7 @@ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)
e = list_entry(rt->job_list.next, JSJobEntry, link);
list_del(&e->link);
ctx = e->ctx;
- res = e->job_func(e->ctx, e->argc, (JSValueConst *)e->argv);
+ res = e->job_func(e->ctx, e->argc, e->argv);
for(i = 0; i < e->argc; i++)
JS_FreeValue(ctx, e->argv[i]);
if (JS_IsException(res))
@@ -1933,7 +1985,7 @@ static inline uint32_t atom_get_free(const JSAtomStruct *p)
return (uintptr_t)p >> 1;
}
-static inline BOOL atom_is_free(const JSAtomStruct *p)
+static inline bool atom_is_free(const JSAtomStruct *p)
{
return (uintptr_t)p & 1;
}
@@ -1956,7 +2008,7 @@ static JSString *js_alloc_string_rt(JSRuntime *rt, int max_len, int is_wide_char
str->atom_type = 0;
str->hash = 0; /* optional but costless */
str->hash_next = 0; /* optional */
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
list_add_tail(&str->link, &rt->string_list);
#endif
return str;
@@ -1980,7 +2032,7 @@ static inline void js_free_string(JSRuntime *rt, JSString *str)
if (str->atom_type) {
JS_FreeAtomStruct(rt, str);
} else {
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
list_del(&str->link);
#endif
js_free_rt(rt, str);
@@ -1999,6 +2051,7 @@ void JS_FreeRuntime(JSRuntime *rt)
struct list_head *el, *el1;
int i;
+ rt->in_free = true;
JS_FreeValueRT(rt, rt->current_exception);
list_for_each_safe(el, el1, &rt->job_list) {
@@ -2011,10 +2064,10 @@ void JS_FreeRuntime(JSRuntime *rt)
JS_RunGC(rt);
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
/* leaking objects */
- {
- BOOL header_done;
+ if (check_dump_flag(rt, JS_DUMP_LEAKS)) {
+ bool header_done;
JSGCObjectHeader *p;
int count;
@@ -2026,14 +2079,14 @@ void JS_FreeRuntime(JSRuntime *rt)
}
gc_decref(rt);
- header_done = FALSE;
+ header_done = false;
list_for_each(el, &rt->gc_obj_list) {
p = list_entry(el, JSGCObjectHeader, link);
if (p->ref_count != 0) {
if (!header_done) {
printf("Object leaks:\n");
JS_DumpObjectHeader(rt);
- header_done = TRUE;
+ header_done = true;
}
JS_DumpGCObject(rt, p);
}
@@ -2050,7 +2103,7 @@ void JS_FreeRuntime(JSRuntime *rt)
printf("Secondary object leaks: %d\n", count);
}
#endif
- fflush(stdout);
+
assert(list_empty(&rt->gc_obj_list));
/* free the classes */
@@ -2064,17 +2117,17 @@ void JS_FreeRuntime(JSRuntime *rt)
bf_context_end(&rt->bf_ctx);
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_ATOM_LEAKS
/* only the atoms defined in JS_InitAtoms() should be left */
- {
- BOOL header_done = FALSE;
+ if (check_dump_flag(rt, JS_DUMP_ATOM_LEAKS)) {
+ bool header_done = false;
for(i = 0; i < rt->atom_size; i++) {
JSAtomStruct *p = rt->atom_array[i];
if (!atom_is_free(p) /* && p->str*/) {
if (i >= JS_ATOM_END || p->header.ref_count != 1) {
if (!header_done) {
- header_done = TRUE;
+ header_done = true;
if (rt->rt_info) {
printf("%s:1: atom leakage:", rt->rt_info);
} else {
@@ -2126,7 +2179,7 @@ void JS_FreeRuntime(JSRuntime *rt)
for(i = 0; i < rt->atom_size; i++) {
JSAtomStruct *p = rt->atom_array[i];
if (!atom_is_free(p)) {
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
list_del(&p->link);
#endif
js_free_rt(rt, p);
@@ -2135,8 +2188,8 @@ void JS_FreeRuntime(JSRuntime *rt)
js_free_rt(rt, rt->atom_array);
js_free_rt(rt, rt->atom_hash);
js_free_rt(rt, rt->shape_hash);
-#ifdef DUMP_LEAKS
- if (!list_empty(&rt->string_list)) {
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
+ if (check_dump_flag(rt, JS_DUMP_LEAKS) && !list_empty(&rt->string_list)) {
if (rt->rt_info) {
printf("%s:1: string leakage:", rt->rt_info);
} else {
@@ -2163,22 +2216,33 @@ void JS_FreeRuntime(JSRuntime *rt)
if (rt->rt_info)
printf("\n");
}
- {
+#endif
+
+ while (rt->finalizers) {
+ JSRuntimeFinalizerState *fs = rt->finalizers;
+ rt->finalizers = fs->next;
+ fs->finalizer(rt, fs->arg);
+ js_free_rt(rt, fs);
+ }
+
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
+ if (check_dump_flag(rt, JS_DUMP_LEAKS)) {
JSMallocState *s = &rt->malloc_state;
if (s->malloc_count > 1) {
if (rt->rt_info)
printf("%s:1: ", rt->rt_info);
- printf("Memory leak: %"PRIu64" bytes lost in %"PRIu64" block%s\n",
- (uint64_t)(s->malloc_size - sizeof(JSRuntime)),
- (uint64_t)(s->malloc_count - 1), &"s"[s->malloc_count == 2]);
+ printf("Memory leak: %zd bytes lost in %zd block%s\n",
+ s->malloc_size - sizeof(JSRuntime),
+ s->malloc_count - 1, &"s"[s->malloc_count == 2]);
}
}
#endif
{
- JSMallocState ms = rt->malloc_state;
- rt->mf.js_free(&ms, rt);
+ JSMallocState *ms = &rt->malloc_state;
+ rt->mf.js_free(ms->opaque, rt);
}
+ fflush(stdout);
}
JSContext *JS_NewContextRaw(JSRuntime *rt)
@@ -2201,15 +2265,16 @@ JSContext *JS_NewContextRaw(JSRuntime *rt)
ctx->rt = rt;
list_add_tail(&ctx->link, &rt->context_list);
ctx->bf_ctx = &rt->bf_ctx;
-#ifdef CONFIG_BIGNUM
- ctx->fp_env.prec = 113;
- ctx->fp_env.flags = bf_set_exp_bits(15) | BF_RNDN | BF_FLAG_SUBNORMAL;
-#endif
for(i = 0; i < rt->class_count; i++)
ctx->class_proto[i] = JS_NULL;
ctx->array_ctor = JS_NULL;
+ ctx->iterator_ctor = JS_NULL;
ctx->regexp_ctor = JS_NULL;
ctx->promise_ctor = JS_NULL;
+ ctx->error_ctor = JS_NULL;
+ ctx->error_back_trace = JS_UNDEFINED;
+ ctx->error_prepare_stack = JS_UNDEFINED;
+ ctx->error_stack_trace_limit = js_int32(10);
init_list_head(&ctx->loaded_modules);
JS_AddIntrinsicBasicObjects(ctx);
@@ -2227,7 +2292,6 @@ JSContext *JS_NewContext(JSRuntime *rt)
JS_AddIntrinsicBaseObjects(ctx);
JS_AddIntrinsicDate(ctx);
JS_AddIntrinsicEval(ctx);
- JS_AddIntrinsicStringNormalize(ctx);
JS_AddIntrinsicRegExp(ctx);
JS_AddIntrinsicJSON(ctx);
JS_AddIntrinsicProxy(ctx);
@@ -2235,6 +2299,10 @@ JSContext *JS_NewContext(JSRuntime *rt)
JS_AddIntrinsicTypedArrays(ctx);
JS_AddIntrinsicPromise(ctx);
JS_AddIntrinsicBigInt(ctx);
+ JS_AddIntrinsicWeakRef(ctx);
+
+ JS_AddPerformance(ctx);
+
return ctx;
}
@@ -2260,16 +2328,19 @@ static inline void set_value(JSContext *ctx, JSValue *pval, JSValue new_val)
void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj)
{
- JSRuntime *rt = ctx->rt;
- assert(class_id < rt->class_count);
+ assert(class_id < ctx->rt->class_count);
set_value(ctx, &ctx->class_proto[class_id], obj);
}
JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id)
{
- JSRuntime *rt = ctx->rt;
- assert(class_id < rt->class_count);
- return JS_DupValue(ctx, ctx->class_proto[class_id]);
+ assert(class_id < ctx->rt->class_count);
+ return js_dup(ctx->class_proto[class_id]);
+}
+
+JSValue JS_GetFunctionProto(JSContext *ctx)
+{
+ return js_dup(ctx->function_proto);
}
typedef enum JSFreeModuleEnum {
@@ -2320,10 +2391,14 @@ static void JS_MarkContext(JSRuntime *rt, JSContext *ctx,
for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
JS_MarkValue(rt, ctx->native_error_proto[i], mark_func);
}
+ JS_MarkValue(rt, ctx->error_ctor, mark_func);
+ JS_MarkValue(rt, ctx->error_back_trace, mark_func);
+ JS_MarkValue(rt, ctx->error_prepare_stack, mark_func);
+ JS_MarkValue(rt, ctx->error_stack_trace_limit, mark_func);
for(i = 0; i < rt->class_count; i++) {
JS_MarkValue(rt, ctx->class_proto[i], mark_func);
}
- JS_MarkValue(rt, ctx->iterator_proto, mark_func);
+ JS_MarkValue(rt, ctx->iterator_ctor, mark_func);
JS_MarkValue(rt, ctx->async_iterator_proto, mark_func);
JS_MarkValue(rt, ctx->promise_ctor, mark_func);
JS_MarkValue(rt, ctx->array_ctor, mark_func);
@@ -2344,14 +2419,16 @@ void JS_FreeContext(JSContext *ctx)
return;
assert(ctx->header.ref_count == 0);
-#ifdef DUMP_ATOMS
- JS_DumpAtoms(ctx->rt);
+#ifdef ENABLE_DUMPS // JS_DUMP_ATOMS
+ if (check_dump_flag(rt, JS_DUMP_ATOMS))
+ JS_DumpAtoms(ctx->rt);
#endif
-#ifdef DUMP_SHAPES
- JS_DumpShapes(ctx->rt);
+#ifdef ENABLE_DUMPS // JS_DUMP_SHAPES
+ if (check_dump_flag(rt, JS_DUMP_SHAPES))
+ JS_DumpShapes(ctx->rt);
#endif
-#ifdef DUMP_OBJECTS
- {
+#ifdef ENABLE_DUMPS // JS_DUMP_OBJECTS
+ if (check_dump_flag(rt, JS_DUMP_OBJECTS)) {
struct list_head *el;
JSGCObjectHeader *p;
printf("JSObjects: {\n");
@@ -2363,8 +2440,8 @@ void JS_FreeContext(JSContext *ctx)
printf("}\n");
}
#endif
-#ifdef DUMP_MEM
- {
+#ifdef ENABLE_DUMPS // JS_DUMP_MEM
+ if (check_dump_flag(rt, JS_DUMP_MEM)) {
JSMemoryUsage stats;
JS_ComputeMemoryUsage(rt, &stats);
JS_DumpMemoryUsage(stdout, &stats, rt);
@@ -2383,11 +2460,15 @@ void JS_FreeContext(JSContext *ctx)
for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
JS_FreeValue(ctx, ctx->native_error_proto[i]);
}
+ JS_FreeValue(ctx, ctx->error_ctor);
+ JS_FreeValue(ctx, ctx->error_back_trace);
+ JS_FreeValue(ctx, ctx->error_prepare_stack);
+ JS_FreeValue(ctx, ctx->error_stack_trace_limit);
for(i = 0; i < rt->class_count; i++) {
JS_FreeValue(ctx, ctx->class_proto[i]);
}
js_free_rt(rt, ctx->class_proto);
- JS_FreeValue(ctx, ctx->iterator_proto);
+ JS_FreeValue(ctx, ctx->iterator_ctor);
JS_FreeValue(ctx, ctx->async_iterator_proto);
JS_FreeValue(ctx, ctx->promise_ctor);
JS_FreeValue(ctx, ctx->array_ctor);
@@ -2409,11 +2490,15 @@ JSRuntime *JS_GetRuntime(JSContext *ctx)
static void update_stack_limit(JSRuntime *rt)
{
+#if defined(__wasi__)
+ rt->stack_limit = 0; /* no limit */
+#else
if (rt->stack_size == 0) {
rt->stack_limit = 0; /* no limit */
} else {
rt->stack_limit = rt->stack_top - rt->stack_size;
}
+#endif
}
void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size)
@@ -2428,25 +2513,12 @@ void JS_UpdateStackTop(JSRuntime *rt)
update_stack_limit(rt);
}
-static inline BOOL is_strict_mode(JSContext *ctx)
+static inline bool is_strict_mode(JSContext *ctx)
{
JSStackFrame *sf = ctx->rt->current_stack_frame;
- return (sf && (sf->js_mode & JS_MODE_STRICT));
+ return sf && sf->is_strict_mode;
}
-#ifdef CONFIG_BIGNUM
-static inline BOOL is_math_mode(JSContext *ctx)
-{
- JSStackFrame *sf = ctx->rt->current_stack_frame;
- return (sf && (sf->js_mode & JS_MODE_MATH));
-}
-#else
-static inline BOOL is_math_mode(JSContext *ctx)
-{
- return FALSE;
-}
-#endif
-
/* JSAtom support */
#define JS_ATOM_TAG_INT (1U << 31)
@@ -2456,16 +2528,12 @@ static inline BOOL is_math_mode(JSContext *ctx)
/* return the max count from the hash size */
#define JS_ATOM_COUNT_RESIZE(n) ((n) * 2)
-static inline BOOL __JS_AtomIsConst(JSAtom v)
+static inline bool __JS_AtomIsConst(JSAtom v)
{
-#if defined(DUMP_LEAKS) && DUMP_LEAKS > 1
- return (int32_t)v <= 0;
-#else
- return (int32_t)v < JS_ATOM_END;
-#endif
+ return (int32_t)v < JS_ATOM_END;
}
-static inline BOOL __JS_AtomIsTaggedInt(JSAtom v)
+static inline bool __JS_AtomIsTaggedInt(JSAtom v)
{
return (v & JS_ATOM_TAG_INT) != 0;
}
@@ -2485,8 +2553,8 @@ static inline int is_num(int c)
return c >= '0' && c <= '9';
}
-/* return TRUE if the string is a number n with 0 <= n <= 2^32-1 */
-static inline BOOL is_num_string(uint32_t *pval, const JSString *p)
+/* return true if the string is a number n with 0 <= n <= 2^32-1 */
+static inline bool is_num_string(uint32_t *pval, const JSString *p)
{
uint32_t n;
uint64_t n64;
@@ -2494,29 +2562,29 @@ static inline BOOL is_num_string(uint32_t *pval, const JSString *p)
len = p->len;
if (len == 0 || len > 10)
- return FALSE;
+ return false;
c = string_get(p, 0);
if (is_num(c)) {
if (c == '0') {
if (len != 1)
- return FALSE;
+ return false;
n = 0;
} else {
n = c - '0';
for(i = 1; i < len; i++) {
c = string_get(p, i);
if (!is_num(c))
- return FALSE;
+ return false;
n64 = (uint64_t)n * 10 + (c - '0');
if ((n64 >> 32) != 0)
- return FALSE;
+ return false;
n = n64;
}
}
*pval = n;
- return TRUE;
+ return true;
} else {
- return FALSE;
+ return false;
}
}
@@ -2549,34 +2617,34 @@ static uint32_t hash_string(const JSString *str, uint32_t h)
return h;
}
-static __maybe_unused void JS_DumpChar(JSRuntime *rt, int c, int sep)
-{
- if (c == sep || c == '\\') {
- putchar('\\');
- putchar(c);
- } else if (c >= ' ' && c <= 126) {
- putchar(c);
- } else if (c == '\n') {
- putchar('\\');
- putchar('n');
- } else {
- printf("\\u%04x", c);
- }
-}
-
-static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p)
+static __maybe_unused void JS_DumpString(JSRuntime *rt,
+ const JSString *p)
{
- int i, sep;
+ int i, c, sep;
if (p == NULL) {
printf("<null>");
return;
}
- printf("%d", p->header.ref_count);
- sep = (p->header.ref_count == 1) ? '\"' : '\'';
+ if (p->header.ref_count != 1)
+ printf("%d", p->header.ref_count);
+ if (p->is_wide_char)
+ putchar('L');
+ sep = '\"';
putchar(sep);
for(i = 0; i < p->len; i++) {
- JS_DumpChar(rt, string_get(p, i), sep);
+ c = string_get(p, i);
+ if (c == sep || c == '\\') {
+ putchar('\\');
+ putchar(c);
+ } else if (c >= ' ' && c <= 126) {
+ putchar(c);
+ } else if (c == '\n') {
+ putchar('\\');
+ putchar('n');
+ } else {
+ printf("\\u%04x", c);
+ }
}
putchar(sep);
}
@@ -2725,11 +2793,7 @@ static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v)
default:
abort();
}
-}
-
-static BOOL JS_AtomIsString(JSContext *ctx, JSAtom v)
-{
- return JS_AtomGetKind(ctx, v) == JS_ATOM_KIND_STRING;
+ return (JSAtomKindEnum){-1}; // pacify compiler
}
static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p)
@@ -2757,9 +2821,6 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
JSAtomStruct *p;
int len;
-#if 0
- printf("__JS_NewAtom: "); JS_DumpString(rt, str); printf("\n");
-#endif
if (atom_type < JS_ATOM_TYPE_SYMBOL) {
/* str is not NULL */
if (str->atom_type == atom_type) {
@@ -2825,7 +2886,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
}
p->header.ref_count = 1; /* not refcounted */
p->atom_type = JS_ATOM_TYPE_SYMBOL;
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
list_add_tail(&p->link, &rt->string_list);
#endif
new_array[0] = p;
@@ -2858,7 +2919,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
p->header.ref_count = 1;
p->is_wide_char = str->is_wide_char;
p->len = str->len;
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
list_add_tail(&p->link, &rt->string_list);
#endif
memcpy(p->u.str8, str->u.str8, (str->len << str->is_wide_char) +
@@ -2872,7 +2933,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
p->header.ref_count = 1;
p->is_wide_char = 1; /* Hack to represent NULL as a JSString */
p->len = 0;
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
list_add_tail(&p->link, &rt->string_list);
#endif
}
@@ -2885,6 +2946,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
p->hash = h;
p->hash_next = i; /* atom_index */
p->atom_type = atom_type;
+ p->first_weak_ref = NULL;
rt->atom_count++;
@@ -2906,7 +2968,8 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
return i;
}
-/* only works with zero terminated 8 bit strings */
+// XXX: `str` must be pure ASCII. No UTF-8 encoded strings
+// XXX: `str` must not be the string representation of a small integer
static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
int atom_type)
{
@@ -2919,7 +2982,7 @@ static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
return __JS_NewAtom(rt, p, atom_type);
}
-/* Warning: str must be ASCII only */
+// XXX: `str` must be raw 8-bit contents. No UTF-8 encoded strings
static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
int atom_type)
{
@@ -2948,12 +3011,6 @@ static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p)
{
-#if 0 /* JS_ATOM_NULL is not refcounted: __JS_AtomIsConst() includes 0 */
- if (unlikely(i == JS_ATOM_NULL)) {
- p->header.ref_count = INT32_MAX / 2;
- return;
- }
-#endif
uint32_t i = p->hash_next; /* atom_index */
if (p->atom_type != JS_ATOM_TYPE_SYMBOL) {
JSAtomStruct *p0, *p1;
@@ -2980,8 +3037,11 @@ static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p)
/* insert in free atom list */
rt->atom_array[i] = atom_set_free(rt->atom_free_index);
rt->atom_free_index = i;
+ if (unlikely(p->first_weak_ref)) {
+ reset_weak_ref(rt, &p->first_weak_ref);
+ }
/* free the string structure */
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
list_del(&p->link);
#endif
js_free_rt(rt, p);
@@ -3014,13 +3074,14 @@ static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p)
return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING);
}
-/* str is UTF-8 encoded */
+/* `str` may be pure ASCII or UTF-8 encoded */
JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len)
{
JSValue val;
if (len == 0 || !is_digit(*str)) {
- // XXX: this will not work if UTF-8 encoded str contains non ASCII bytes
+ // TODO(chqrlie): this does not work if `str` has UTF-8 encoded contents
+ // bug example: `({ "\u00c3\u00a9": 1 }).\u00e9` evaluates to `1`.
JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);
if (atom)
return atom;
@@ -3031,6 +3092,7 @@ JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len)
return JS_NewAtomStr(ctx, JS_VALUE_GET_STRING(val));
}
+/* `str` may be pure ASCII or UTF-8 encoded */
JSAtom JS_NewAtom(JSContext *ctx, const char *str)
{
return JS_NewAtomLen(ctx, str, strlen(str));
@@ -3041,10 +3103,9 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
if (n <= JS_ATOM_MAX_INT) {
return __JS_AtomFromUInt32(n);
} else {
- char buf[11];
- JSValue val;
- snprintf(buf, sizeof(buf), "%u", n);
- val = JS_NewString(ctx, buf);
+ char buf[16];
+ size_t len = u32toa(buf, n);
+ JSValue val = js_new_string8_len(ctx, buf, len);
if (JS_IsException(val))
return JS_ATOM_NULL;
return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),
@@ -3058,9 +3119,8 @@ static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)
return __JS_AtomFromUInt32((uint32_t)n);
} else {
char buf[24];
- JSValue val;
- snprintf(buf, sizeof(buf), "%" PRId64 , n);
- val = JS_NewString(ctx, buf);
+ size_t len = i64toa(buf, n);
+ JSValue val = js_new_string8_len(ctx, buf, len);
if (JS_IsException(val))
return JS_ATOM_NULL;
return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),
@@ -3069,7 +3129,7 @@ static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)
}
/* 'p' is freed */
-static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type)
+static JSValue JS_NewSymbolInternal(JSContext *ctx, JSString *p, int atom_type)
{
JSRuntime *rt = ctx->rt;
JSAtom atom;
@@ -3089,54 +3149,45 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,
assert(!__JS_AtomIsTaggedInt(descr));
assert(descr < rt->atom_size);
p = rt->atom_array[descr];
- JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
- return JS_NewSymbol(ctx, p, atom_type);
+ js_dup(JS_MKPTR(JS_TAG_STRING, p));
+ return JS_NewSymbolInternal(ctx, p, atom_type);
+}
+
+/* `description` may be pure ASCII or UTF-8 encoded */
+JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global)
+{
+ JSAtom atom = JS_NewAtom(ctx, description);
+ if (atom == JS_ATOM_NULL)
+ return JS_EXCEPTION;
+ return JS_NewSymbolFromAtom(ctx, atom, is_global ? JS_ATOM_TYPE_GLOBAL_SYMBOL : JS_ATOM_TYPE_SYMBOL);
}
#define ATOM_GET_STR_BUF_SIZE 64
-/* Should only be used for debug. */
static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size,
JSAtom atom)
{
if (__JS_AtomIsTaggedInt(atom)) {
snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom));
- } else {
- JSAtomStruct *p;
+ } else if (atom == JS_ATOM_NULL) {
+ snprintf(buf, buf_size, "<null>");
+ } else if (atom >= rt->atom_size) {
assert(atom < rt->atom_size);
- if (atom == JS_ATOM_NULL) {
- snprintf(buf, buf_size, "<null>");
- } else {
- int i, c;
- char *q;
- JSString *str;
-
- q = buf;
- p = rt->atom_array[atom];
+ snprintf(buf, buf_size, "<invalid %x>", atom);
+ } else {
+ JSAtomStruct *p = rt->atom_array[atom];
+ *buf = '\0';
+ if (atom_is_free(p)) {
assert(!atom_is_free(p));
- str = p;
- if (str) {
- if (!str->is_wide_char) {
- /* special case ASCII strings */
- c = 0;
- for(i = 0; i < str->len; i++) {
- c |= str->u.str8[i];
- }
- if (c < 0x80)
- return (const char *)str->u.str8;
- }
- for(i = 0; i < str->len; i++) {
- c = string_get(str, i);
- if ((q - buf) >= buf_size - UTF8_CHAR_LEN_MAX)
- break;
- if (c < 128) {
- *q++ = c;
- } else {
- q += unicode_to_utf8((uint8_t *)q, c);
- }
- }
+ snprintf(buf, buf_size, "<free %x>", atom);
+ } else if (p != NULL) {
+ JSString *str = p;
+ if (str->is_wide_char) {
+ /* encode surrogates correctly */
+ utf8_encode_buf16(buf, buf_size, str->u.str16, str->len);
+ } else {
+ utf8_encode_buf8(buf, buf_size, str->u.str8, str->len);
}
- *q = '\0';
}
}
return buf;
@@ -3147,13 +3198,13 @@ static const char *JS_AtomGetStr(JSContext *ctx, char *buf, int buf_size, JSAtom
return JS_AtomGetStrRT(ctx->rt, buf, buf_size, atom);
}
-static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string)
+static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, bool force_string)
{
char buf[ATOM_GET_STR_BUF_SIZE];
if (__JS_AtomIsTaggedInt(atom)) {
- snprintf(buf, sizeof(buf), "%u", __JS_AtomToUInt32(atom));
- return JS_NewString(ctx, buf);
+ size_t len = u32toa(buf, __JS_AtomToUInt32(atom));
+ return js_new_string8_len(ctx, buf, len);
} else {
JSRuntime *rt = ctx->rt;
JSAtomStruct *p;
@@ -3167,30 +3218,30 @@ static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string)
p = rt->atom_array[JS_ATOM_empty_string];
}
ret_string:
- return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
+ return js_dup(JS_MKPTR(JS_TAG_STRING, p));
} else {
- return JS_DupValue(ctx, JS_MKPTR(JS_TAG_SYMBOL, p));
+ return js_dup(JS_MKPTR(JS_TAG_SYMBOL, p));
}
}
}
JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom)
{
- return __JS_AtomToValue(ctx, atom, FALSE);
+ return __JS_AtomToValue(ctx, atom, false);
}
JSValue JS_AtomToString(JSContext *ctx, JSAtom atom)
{
- return __JS_AtomToValue(ctx, atom, TRUE);
+ return __JS_AtomToValue(ctx, atom, true);
}
-/* return TRUE if the atom is an array index (i.e. 0 <= index <=
+/* return true if the atom is an array index (i.e. 0 <= index <=
2^32-2 and return its value */
-static BOOL JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom)
+static bool JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom)
{
if (__JS_AtomIsTaggedInt(atom)) {
*pval = __JS_AtomToUInt32(atom);
- return TRUE;
+ return true;
} else {
JSRuntime *rt = ctx->rt;
JSAtomStruct *p;
@@ -3201,10 +3252,10 @@ static BOOL JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom)
if (p->atom_type == JS_ATOM_TYPE_STRING &&
is_num_string(&val, p) && val != -1) {
*pval = val;
- return TRUE;
+ return true;
} else {
*pval = 0;
- return FALSE;
+ return false;
}
}
}
@@ -3221,7 +3272,7 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
JSValue num, str;
if (__JS_AtomIsTaggedInt(atom))
- return JS_NewInt32(ctx, __JS_AtomToUInt32(atom));
+ return js_int32(__JS_AtomToUInt32(atom));
assert(atom < rt->atom_size);
p1 = rt->atom_array[atom];
if (p1->atom_type != JS_ATOM_TYPE_STRING)
@@ -3263,7 +3314,7 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
/* -0 case is specific */
if (c == '0' && len == 2) {
minus_zero:
- return __JS_NewFloat64(ctx, -0.0);
+ return js_float64(-0.0);
}
}
if (!is_num(c)) {
@@ -3272,8 +3323,6 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
return JS_UNDEFINED;
}
}
- /* XXX: bignum: would be better to only accept integer to avoid
- relying on current floating point precision */
/* this is ECMA CanonicalNumericIndexString primitive */
num = JS_ToNumber(ctx, JS_MKPTR(JS_TAG_STRING, p));
if (JS_IsException(num))
@@ -3283,9 +3332,9 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
JS_FreeValue(ctx, num);
return str;
}
- ret = js_string_compare(ctx, p, JS_VALUE_GET_STRING(str));
+ ret = js_string_eq(p, JS_VALUE_GET_STRING(str));
JS_FreeValue(ctx, str);
- if (ret == 0) {
+ if (ret) {
return num;
} else {
JS_FreeValue(ctx, num);
@@ -3293,17 +3342,17 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
}
}
-/* return -1 if exception or TRUE/FALSE */
+/* return -1 if exception or true/false */
static int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom)
{
JSValue num;
num = JS_AtomIsNumericIndex1(ctx, atom);
if (likely(JS_IsUndefined(num)))
- return FALSE;
+ return false;
if (JS_IsException(num))
return -1;
JS_FreeValue(ctx, num);
- return TRUE;
+ return true;
}
void JS_FreeAtom(JSContext *ctx, JSAtom v)
@@ -3318,15 +3367,15 @@ void JS_FreeAtomRT(JSRuntime *rt, JSAtom v)
__JS_FreeAtom(rt, v);
}
-/* return TRUE if 'v' is a symbol with a string description */
-static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
+/* return true if 'v' is a symbol with a string description */
+static bool JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
{
JSRuntime *rt;
JSAtomStruct *p;
rt = ctx->rt;
if (__JS_AtomIsTaggedInt(v))
- return FALSE;
+ return false;
p = rt->atom_array[v];
return (((p->atom_type == JS_ATOM_TYPE_SYMBOL &&
p->hash == JS_ATOM_HASH_SYMBOL) ||
@@ -3387,6 +3436,8 @@ const char *JS_AtomToCString(JSContext *ctx, JSAtom atom)
}
/* return a string atom containing name concatenated with str1 */
+/* `str1` may be pure ASCII or UTF-8 encoded */
+// TODO(chqrlie): use string concatenation instead of UTF-8 conversion
static JSAtom js_atom_concat_str(JSContext *ctx, JSAtom name, const char *str1)
{
JSValue str;
@@ -3422,49 +3473,38 @@ static JSAtom js_atom_concat_str(JSContext *ctx, JSAtom name, const char *str1)
static JSAtom js_atom_concat_num(JSContext *ctx, JSAtom name, uint32_t n)
{
char buf[16];
- snprintf(buf, sizeof(buf), "%u", n);
+ u32toa(buf, n);
return js_atom_concat_str(ctx, name, buf);
}
-static inline BOOL JS_IsEmptyString(JSValueConst v)
+static inline bool JS_IsEmptyString(JSValue v)
{
return JS_VALUE_GET_TAG(v) == JS_TAG_STRING && JS_VALUE_GET_STRING(v)->len == 0;
}
/* JSClass support */
-#ifdef CONFIG_ATOMICS
-static pthread_mutex_t js_class_id_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-/* a new class ID is allocated if *pclass_id != 0 */
-JSClassID JS_NewClassID(JSClassID *pclass_id)
+/* a new class ID is allocated if *pclass_id == 0, otherwise *pclass_id is left unchanged */
+JSClassID JS_NewClassID(JSRuntime *rt, JSClassID *pclass_id)
{
- JSClassID class_id;
-#ifdef CONFIG_ATOMICS
- pthread_mutex_lock(&js_class_id_mutex);
-#endif
- class_id = *pclass_id;
+ JSClassID class_id = *pclass_id;
if (class_id == 0) {
- class_id = js_class_id_alloc++;
+ class_id = rt->js_class_id_alloc++;
*pclass_id = class_id;
}
-#ifdef CONFIG_ATOMICS
- pthread_mutex_unlock(&js_class_id_mutex);
-#endif
return class_id;
}
JSClassID JS_GetClassID(JSValue v)
{
- JSObject *p;
- if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
- return JS_INVALID_CLASS_ID;
- p = JS_VALUE_GET_OBJ(v);
- return p->class_id;
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
+ return JS_INVALID_CLASS_ID;
+ p = JS_VALUE_GET_OBJ(v);
+ return p->class_id;
}
-BOOL JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id)
+bool JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id)
{
return (class_id < rt->class_count &&
rt->class_array[class_id].class_id != 0);
@@ -3526,6 +3566,7 @@ int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def)
int ret, len;
JSAtom name;
+ // XXX: class_def->class_name must be raw 8-bit contents. No UTF-8 encoded strings
len = strlen(class_def->class_name);
name = __JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
if (name == JS_ATOM_NULL) {
@@ -3538,13 +3579,11 @@ int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def)
return ret;
}
-static JSValue js_new_string8(JSContext *ctx, const uint8_t *buf, int len)
+// XXX: `buf` contains raw 8-bit data, no UTF-8 decoding is performed
+// XXX: no special case for len == 0
+static JSValue js_new_string8_len(JSContext *ctx, const char *buf, int len)
{
JSString *str;
-
- if (len <= 0) {
- return JS_AtomToString(ctx, JS_ATOM_empty_string);
- }
str = js_alloc_string(ctx, len, 0);
if (!str)
return JS_EXCEPTION;
@@ -3553,7 +3592,14 @@ static JSValue js_new_string8(JSContext *ctx, const uint8_t *buf, int len)
return JS_MKPTR(JS_TAG_STRING, str);
}
-static JSValue js_new_string16(JSContext *ctx, const uint16_t *buf, int len)
+// XXX: `buf` contains raw 8-bit data, no UTF-8 decoding is performed
+// XXX: no special case for the empty string
+static inline JSValue js_new_string8(JSContext *ctx, const char *str)
+{
+ return js_new_string8_len(ctx, str, strlen(str));
+}
+
+static JSValue js_new_string16_len(JSContext *ctx, const uint16_t *buf, int len)
{
JSString *str;
str = js_alloc_string(ctx, len, 1);
@@ -3566,11 +3612,11 @@ static JSValue js_new_string16(JSContext *ctx, const uint16_t *buf, int len)
static JSValue js_new_string_char(JSContext *ctx, uint16_t c)
{
if (c < 0x100) {
- uint8_t ch8 = c;
- return js_new_string8(ctx, &ch8, 1);
+ char ch8 = c;
+ return js_new_string8_len(ctx, &ch8, 1);
} else {
uint16_t ch16 = c;
- return js_new_string16(ctx, &ch16, 1);
+ return js_new_string16_len(ctx, &ch16, 1);
}
}
@@ -3578,9 +3624,12 @@ static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end)
{
int len = end - start;
if (start == 0 && end == p->len) {
- return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
+ return js_dup(JS_MKPTR(JS_TAG_STRING, p));
}
- if (p->is_wide_char && len > 0) {
+ if (len <= 0) {
+ return JS_AtomToString(ctx, JS_ATOM_empty_string);
+ }
+ if (p->is_wide_char) {
JSString *str;
int i;
uint16_t c = 0;
@@ -3588,7 +3637,7 @@ static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end)
c |= p->u.str16[i];
}
if (c > 0xFF)
- return js_new_string16(ctx, p->u.str16 + start, len);
+ return js_new_string16_len(ctx, p->u.str16 + start, len);
str = js_alloc_string(ctx, len, 0);
if (!str)
@@ -3599,7 +3648,7 @@ static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end)
str->u.str8[len] = '\0';
return JS_MKPTR(JS_TAG_STRING, str);
} else {
- return js_new_string8(ctx, p->u.str8 + start, len);
+ return js_new_string8_len(ctx, (const char *)(p->u.str8 + start), len);
}
}
@@ -3629,7 +3678,7 @@ static int string_buffer_init2(JSContext *ctx, StringBuffer *s, int size,
s->size = 0;
return s->error_status = -1;
}
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
/* the StringBuffer may reallocate the JSString, only link it at the end */
list_del(&s->str->link);
#endif
@@ -3688,7 +3737,7 @@ static no_inline int string_buffer_realloc(StringBuffer *s, int new_len, int c)
return -1;
if (new_len > JS_STRING_LEN_MAX) {
- JS_ThrowInternalError(s->ctx, "string too long");
+ JS_ThrowRangeError(s->ctx, "invalid string length");
return string_buffer_set_error(s);
}
new_size = min_int(max_int(new_len, s->size * 3 / 2), JS_STRING_LEN_MAX);
@@ -3848,7 +3897,7 @@ static int string_buffer_concat(StringBuffer *s, const JSString *p,
return string_buffer_write8(s, p->u.str8 + from, to - from);
}
-static int string_buffer_concat_value(StringBuffer *s, JSValueConst v)
+static int string_buffer_concat_value(StringBuffer *s, JSValue v)
{
JSString *p;
JSValue v1;
@@ -3929,7 +3978,7 @@ static JSValue string_buffer_end(StringBuffer *s)
}
if (!s->is_wide_char)
str->u.str8[s->len] = 0;
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
list_add_tail(&str->link, &s->ctx->rt->string_list);
#endif
str->is_wide_char = s->is_wide_char;
@@ -3941,61 +3990,44 @@ static JSValue string_buffer_end(StringBuffer *s)
/* create a string from a UTF-8 buffer */
JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len)
{
- const uint8_t *p, *p_end, *p_start, *p_next;
- uint32_t c;
- StringBuffer b_s, *b = &b_s;
- size_t len1;
+ JSString *str;
+ size_t len;
+ int kind;
- p_start = (const uint8_t *)buf;
- p_end = p_start + buf_len;
- p = p_start;
- while (p < p_end && *p < 128)
- p++;
- len1 = p - p_start;
- if (len1 > JS_STRING_LEN_MAX)
- return JS_ThrowInternalError(ctx, "string too long");
- if (p == p_end) {
- /* ASCII string */
- return js_new_string8(ctx, (const uint8_t *)buf, buf_len);
- } else {
- if (string_buffer_init(ctx, b, buf_len))
- goto fail;
- string_buffer_write8(b, p_start, len1);
- while (p < p_end) {
- if (*p < 128) {
- string_buffer_putc8(b, *p++);
- } else {
- /* parse utf-8 sequence, return 0xFFFFFFFF for error */
- c = unicode_from_utf8(p, p_end - p, &p_next);
- if (c < 0x10000) {
- p = p_next;
- } else if (c <= 0x10FFFF) {
- p = p_next;
- /* surrogate pair */
- string_buffer_putc16(b, get_hi_surrogate(c));
- c = get_lo_surrogate(c);
- } else {
- /* invalid char */
- c = 0xfffd;
- /* skip the invalid chars */
- /* XXX: seems incorrect. Why not just use c = *p++; ? */
- while (p < p_end && (*p >= 0x80 && *p < 0xc0))
- p++;
- if (p < p_end) {
- p++;
- while (p < p_end && (*p >= 0x80 && *p < 0xc0))
- p++;
- }
- }
- string_buffer_putc16(b, c);
- }
- }
+ if (buf_len <= 0) {
+ return JS_AtomToString(ctx, JS_ATOM_empty_string);
}
- return string_buffer_end(b);
+ /* Compute string kind and length: 7-bit, 8-bit, 16-bit, 16-bit UTF-16 */
+ kind = utf8_scan(buf, buf_len, &len);
+ if (len > JS_STRING_LEN_MAX)
+ return JS_ThrowRangeError(ctx, "invalid string length");
- fail:
- string_buffer_free(b);
- return JS_EXCEPTION;
+ switch (kind) {
+ case UTF8_PLAIN_ASCII:
+ str = js_alloc_string(ctx, len, 0);
+ if (!str)
+ return JS_EXCEPTION;
+ memcpy(str->u.str8, buf, len);
+ str->u.str8[len] = '\0';
+ break;
+ case UTF8_NON_ASCII:
+ /* buf contains non-ASCII code-points, but limited to 8-bit values */
+ str = js_alloc_string(ctx, len, 0);
+ if (!str)
+ return JS_EXCEPTION;
+ utf8_decode_buf8(str->u.str8, len + 1, buf, buf_len);
+ break;
+ default:
+ // This causes a potential problem in JS_ThrowError if message is invalid
+ //if (kind & UTF8_HAS_ERRORS)
+ // return JS_ThrowRangeError(ctx, "invalid UTF-8 sequence");
+ str = js_alloc_string(ctx, len, 1);
+ if (!str)
+ return JS_EXCEPTION;
+ utf8_decode_buf16(str->u.str16, len, buf, buf_len);
+ break;
+ }
+ return JS_MKPTR(JS_TAG_STRING, str);
}
static JSValue JS_ConcatString3(JSContext *ctx, const char *str1,
@@ -4029,11 +4061,7 @@ static JSValue JS_ConcatString3(JSContext *ctx, const char *str1,
return JS_EXCEPTION;
}
-JSValue JS_NewString(JSContext *ctx, const char *str)
-{
- return JS_NewStringLen(ctx, str, strlen(str));
-}
-
+/* `str` may be pure ASCII or UTF-8 encoded */
JSValue JS_NewAtomString(JSContext *ctx, const char *str)
{
JSAtom atom = JS_NewAtom(ctx, str);
@@ -4047,21 +4075,41 @@ JSValue JS_NewAtomString(JSContext *ctx, const char *str)
/* return (NULL, 0) if exception. */
/* return pointer into a JSString with a live ref_count */
/* cesu8 determines if non-BMP1 codepoints are encoded as 1 or 2 utf-8 sequences */
-const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, BOOL cesu8)
+const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValue val1, bool cesu8)
{
JSValue val;
JSString *str, *str_new;
int pos, len, c, c1;
+ JSObject *p;
uint8_t *q;
- if (JS_VALUE_GET_TAG(val1) != JS_TAG_STRING) {
- val = JS_ToString(ctx, val1);
- if (JS_IsException(val))
- goto fail;
- } else {
- val = JS_DupValue(ctx, val1);
+ if (JS_VALUE_GET_TAG(val1) == JS_TAG_STRING) {
+ val = js_dup(val1);
+ goto go;
+ }
+
+ val = JS_ToString(ctx, val1);
+ if (!JS_IsException(val))
+ goto go;
+
+ // Stringification can fail when there is an exception pending,
+ // e.g. a stack overflow InternalError. Special-case exception
+ // objects to make debugging easier, look up the .message property
+ // and stringify that.
+ if (JS_VALUE_GET_TAG(val1) != JS_TAG_OBJECT)
+ goto fail;
+
+ p = JS_VALUE_GET_OBJ(val1);
+ if (p->class_id != JS_CLASS_ERROR)
+ goto fail;
+
+ val = JS_GetProperty(ctx, val1, JS_ATOM_message);
+ if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) {
+ JS_FreeValue(ctx, val);
+ goto fail;
}
+go:
str = JS_VALUE_GET_STRING(val);
len = str->len;
if (!str->is_wide_char) {
@@ -4126,7 +4174,7 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, BO
/* c = 0xfffd; */ /* error */
}
}
- q += unicode_to_utf8(q, c);
+ q += utf8_encode(q, c);
}
}
}
@@ -4193,21 +4241,20 @@ static int js_string_memcmp(const JSString *p1, const JSString *p2, int len)
return res;
}
+static bool js_string_eq(const JSString *p1, const JSString *p2) {
+ if (p1->len != p2->len)
+ return false;
+ return js_string_memcmp(p1, p2, p1->len) == 0;
+}
+
/* return < 0, 0 or > 0 */
-static int js_string_compare(JSContext *ctx,
- const JSString *p1, const JSString *p2)
+static int js_string_compare(const JSString *p1, const JSString *p2)
{
int res, len;
len = min_int(p1->len, p2->len);
res = js_string_memcmp(p1, p2, len);
- if (res == 0) {
- if (p1->len == p2->len)
- res = 0;
- else if (p1->len < p2->len)
- res = -1;
- else
- res = 1;
- }
+ if (res == 0)
+ res = compare_u32(p1->len, p2->len);
return res;
}
@@ -4233,7 +4280,7 @@ static JSValue JS_ConcatString1(JSContext *ctx,
len = p1->len + p2->len;
if (len > JS_STRING_LEN_MAX)
- return JS_ThrowInternalError(ctx, "string too long");
+ return JS_ThrowRangeError(ctx, "invalid string length");
is_wide_char = p1->is_wide_char | p2->is_wide_char;
p = js_alloc_string(ctx, len, is_wide_char);
if (!p)
@@ -4249,43 +4296,7 @@ static JSValue JS_ConcatString1(JSContext *ctx,
return JS_MKPTR(JS_TAG_STRING, p);
}
-static BOOL JS_ConcatStringInPlace(JSContext *ctx, JSString *p1, JSValueConst op2) {
- if (JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) {
- JSString *p2 = JS_VALUE_GET_STRING(op2);
- size_t size1;
-
- if (p2->len == 0)
- return TRUE;
- if (p1->header.ref_count != 1)
- return FALSE;
- size1 = js_malloc_usable_size(ctx, p1);
- if (p1->is_wide_char) {
- if (size1 >= sizeof(*p1) + ((p1->len + p2->len) << 1)) {
- if (p2->is_wide_char) {
- memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1);
- p1->len += p2->len;
- return TRUE;
- } else {
- size_t i;
- for (i = 0; i < p2->len; i++) {
- p1->u.str16[p1->len++] = p2->u.str8[i];
- }
- return TRUE;
- }
- }
- } else if (!p2->is_wide_char) {
- if (size1 >= sizeof(*p1) + p1->len + p2->len + 1) {
- memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len);
- p1->len += p2->len;
- p1->u.str8[p1->len] = '\0';
- return TRUE;
- }
- }
- }
- return FALSE;
-}
-
-/* op1 and op2 are converted to strings. For convenience, op1 or op2 =
+/* op1 and op2 are converted to strings. For convience, op1 or op2 =
JS_EXCEPTION are accepted and return JS_EXCEPTION. */
static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2)
{
@@ -4307,11 +4318,27 @@ static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2)
}
}
p1 = JS_VALUE_GET_STRING(op1);
- if (JS_ConcatStringInPlace(ctx, p1, op2)) {
+ p2 = JS_VALUE_GET_STRING(op2);
+
+ /* XXX: could also check if p1 is empty */
+ if (p2->len == 0) {
+ goto ret_op1;
+ }
+ if (p1->header.ref_count == 1 && p1->is_wide_char == p2->is_wide_char
+ && js_malloc_usable_size(ctx, p1) >= sizeof(*p1) + ((p1->len + p2->len) << p2->is_wide_char) + 1 - p1->is_wide_char) {
+ /* Concatenate in place in available space at the end of p1 */
+ if (p1->is_wide_char) {
+ memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1);
+ p1->len += p2->len;
+ } else {
+ memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len);
+ p1->len += p2->len;
+ p1->u.str8[p1->len] = '\0';
+ }
+ ret_op1:
JS_FreeValue(ctx, op2);
return op1;
}
- p2 = JS_VALUE_GET_STRING(op2);
ret = JS_ConcatString1(ctx, p1, p2);
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
@@ -4447,7 +4474,7 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto,
sh->header.ref_count = 1;
add_gc_object(rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE);
if (proto)
- JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, proto));
+ js_dup(JS_MKPTR(JS_TAG_OBJECT, proto));
sh->proto = proto;
memset(prop_hash_end(sh) - hash_size, 0, sizeof(prop_hash_end(sh)[0]) *
hash_size);
@@ -4458,8 +4485,8 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto,
/* insert in the hash table */
sh->hash = shape_initial_hash(proto);
- sh->is_hashed = TRUE;
- sh->has_small_array_index = FALSE;
+ sh->is_hashed = true;
+ sh->has_small_array_index = false;
js_shape_hash_link(ctx->rt, sh);
return sh;
}
@@ -4490,9 +4517,9 @@ static JSShape *js_clone_shape(JSContext *ctx, JSShape *sh1)
sh = get_shape_from_alloc(sh_alloc, hash_size);
sh->header.ref_count = 1;
add_gc_object(ctx->rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE);
- sh->is_hashed = FALSE;
+ sh->is_hashed = false;
if (sh->proto) {
- JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto));
+ js_dup(JS_MKPTR(JS_TAG_OBJECT, sh->proto));
}
for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) {
JS_DupAtom(ctx, pr->atom);
@@ -4548,7 +4575,6 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
JSShapeProperty *pr;
void *sh_alloc;
intptr_t h;
- JSShape *old_sh;
sh = *psh;
new_size = max_int(count, sh->prop_size * 3 / 2);
@@ -4564,21 +4590,19 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
new_hash_size = sh->prop_hash_mask + 1;
while (new_hash_size < new_size)
new_hash_size = 2 * new_hash_size;
- /* resize the property shapes. Using js_realloc() is not possible in
- case the GC runs during the allocation */
- old_sh = sh;
- sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));
- if (!sh_alloc)
- return -1;
- sh = get_shape_from_alloc(sh_alloc, new_hash_size);
- list_del(&old_sh->header.link);
- /* copy all the shape properties */
- memcpy(sh, old_sh,
- sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);
- list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
-
if (new_hash_size != (sh->prop_hash_mask + 1)) {
+ JSShape *old_sh;
/* resize the hash table and the properties */
+ old_sh = sh;
+ sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));
+ if (!sh_alloc)
+ return -1;
+ sh = get_shape_from_alloc(sh_alloc, new_hash_size);
+ list_del(&old_sh->header.link);
+ /* copy all the fields and the properties */
+ memcpy(sh, old_sh,
+ sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);
+ list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
new_hash_mask = new_hash_size - 1;
sh->prop_hash_mask = new_hash_mask;
memset(prop_hash_end(sh) - new_hash_size, 0,
@@ -4590,12 +4614,20 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
prop_hash_end(sh)[-h - 1] = i + 1;
}
}
+ js_free(ctx, get_alloc_from_shape(old_sh));
} else {
- /* just copy the previous hash table */
- memcpy(prop_hash_end(sh) - new_hash_size, prop_hash_end(old_sh) - new_hash_size,
- sizeof(prop_hash_end(sh)[0]) * new_hash_size);
+ /* only resize the properties */
+ list_del(&sh->header.link);
+ sh_alloc = js_realloc(ctx, get_alloc_from_shape(sh),
+ get_shape_size(new_hash_size, new_size));
+ if (unlikely(!sh_alloc)) {
+ /* insert again in the GC list */
+ list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
+ return -1;
+ }
+ sh = get_shape_from_alloc(sh_alloc, new_hash_size);
+ list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
}
- js_free(ctx, get_alloc_from_shape(old_sh));
*psh = sh;
sh->prop_size = new_size;
return 0;
@@ -4819,7 +4851,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
if (unlikely(!p))
goto fail;
p->class_id = class_id;
- p->extensible = TRUE;
+ p->extensible = true;
p->free_mark = 0;
p->is_exotic = 0;
p->fast_array = 0;
@@ -4858,7 +4890,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
pr = add_property(ctx, p, JS_ATOM_length,
JS_PROP_WRITABLE | JS_PROP_LENGTH);
}
- pr->u.value = JS_NewInt32(ctx, 0);
+ pr->u.value = js_int32(0);
}
break;
case JS_CLASS_C_FUNCTION:
@@ -4874,6 +4906,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
case JS_CLASS_UINT32_ARRAY:
case JS_CLASS_BIG_INT64_ARRAY:
case JS_CLASS_BIG_UINT64_ARRAY:
+ case JS_CLASS_FLOAT16_ARRAY:
case JS_CLASS_FLOAT32_ARRAY:
case JS_CLASS_FLOAT64_ARRAY:
p->is_exotic = 1;
@@ -4891,10 +4924,6 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
case JS_CLASS_SYMBOL:
case JS_CLASS_DATE:
case JS_CLASS_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_CLASS_BIG_FLOAT:
- case JS_CLASS_BIG_DECIMAL:
-#endif
p->u.object_data = JS_UNDEFINED;
goto set_exotic;
case JS_CLASS_REGEXP:
@@ -4913,7 +4942,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
return JS_MKPTR(JS_TAG_OBJECT, p);
}
-static JSObject *get_proto_obj(JSValueConst proto_val)
+static JSObject *get_proto_obj(JSValue proto_val)
{
if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_OBJECT)
return NULL;
@@ -4922,7 +4951,7 @@ static JSObject *get_proto_obj(JSValueConst proto_val)
}
/* WARNING: proto must be an object or JS_NULL */
-JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val,
+JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValue proto_val,
JSClassID class_id)
{
JSShape *sh;
@@ -4940,8 +4969,7 @@ JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val,
return JS_NewObjectFromShape(ctx, sh, class_id);
}
-#if 0
-static JSValue JS_GetObjectData(JSContext *ctx, JSValueConst obj)
+static int JS_SetObjectData(JSContext *ctx, JSValue obj, JSValue val)
{
JSObject *p;
@@ -4954,34 +4982,6 @@ static JSValue JS_GetObjectData(JSContext *ctx, JSValueConst obj)
case JS_CLASS_SYMBOL:
case JS_CLASS_DATE:
case JS_CLASS_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_CLASS_BIG_FLOAT:
- case JS_CLASS_BIG_DECIMAL:
-#endif
- return JS_DupValue(ctx, p->u.object_data);
- }
- }
- return JS_UNDEFINED;
-}
-#endif
-
-static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val)
-{
- JSObject *p;
-
- if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
- p = JS_VALUE_GET_OBJ(obj);
- switch(p->class_id) {
- case JS_CLASS_NUMBER:
- case JS_CLASS_STRING:
- case JS_CLASS_BOOLEAN:
- case JS_CLASS_SYMBOL:
- case JS_CLASS_DATE:
- case JS_CLASS_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_CLASS_BIG_FLOAT:
- case JS_CLASS_BIG_DECIMAL:
-#endif
JS_FreeValue(ctx, p->u.object_data);
p->u.object_data = val;
return 0;
@@ -4998,34 +4998,134 @@ JSValue JS_NewObjectClass(JSContext *ctx, int class_id)
return JS_NewObjectProtoClass(ctx, ctx->class_proto[class_id], class_id);
}
-JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto)
+JSValue JS_NewObjectProto(JSContext *ctx, JSValue proto)
{
return JS_NewObjectProtoClass(ctx, proto, JS_CLASS_OBJECT);
}
+JSValue JS_NewObjectFrom(JSContext *ctx, int count, const JSAtom *props,
+ const JSValue *values)
+{
+ JSShapeProperty *pr;
+ uint32_t *hash;
+ JSRuntime *rt;
+ JSObject *p;
+ JSShape *sh;
+ JSValue obj;
+ JSAtom atom;
+ intptr_t h;
+ int i;
+
+ rt = ctx->rt;
+ obj = JS_NewObject(ctx);
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+ if (count > 0) {
+ p = JS_VALUE_GET_OBJ(obj);
+ sh = p->shape;
+ assert(sh->is_hashed);
+ assert(sh->header.ref_count == 1);
+ js_shape_hash_unlink(rt, sh);
+ if (resize_properties(ctx, &sh, p, count)) {
+ js_shape_hash_link(rt, sh);
+ JS_FreeValue(ctx, obj);
+ return JS_EXCEPTION;
+ }
+ p->shape = sh;
+ for (i = 0; i < count; i++) {
+ atom = props[i];
+ pr = &sh->prop[i];
+ sh->hash = shape_hash(shape_hash(sh->hash, atom), JS_PROP_C_W_E);
+ sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom);
+ h = atom & sh->prop_hash_mask;
+ hash = &prop_hash_end(sh)[-h - 1];
+ pr->hash_next = *hash;
+ *hash = i + 1;
+ pr->atom = JS_DupAtom(ctx, atom);
+ pr->flags = JS_PROP_C_W_E;
+ p->prop[i].u.value = values[i];
+ }
+ js_shape_hash_link(rt, sh);
+ sh->prop_count = count;
+ }
+ return obj;
+}
+
+JSValue JS_NewObjectFromStr(JSContext *ctx, int count, const char **props,
+ const JSValue *values)
+{
+ JSAtom atoms_s[16], *atoms = atoms_s;
+ JSValue ret;
+ int i;
+
+ i = 0;
+ ret = JS_EXCEPTION;
+ if (count < 1)
+ goto out;
+ if (count > (int)countof(atoms_s)) {
+ atoms = js_malloc(ctx, count * sizeof(*atoms));
+ if (!atoms)
+ return JS_EXCEPTION;
+ }
+ for (i = 0; i < count; i++) {
+ atoms[i] = JS_NewAtom(ctx, props[i]);
+ if (atoms[i] == JS_ATOM_NULL)
+ goto out;
+ }
+ ret = JS_NewObjectFrom(ctx, count, atoms, values);
+out:
+ while (i-- > 0)
+ JS_FreeAtom(ctx, atoms[i]);
+ if (atoms != atoms_s)
+ js_free(ctx, atoms);
+ return ret;
+}
+
JSValue JS_NewArray(JSContext *ctx)
{
return JS_NewObjectFromShape(ctx, js_dup_shape(ctx->array_shape),
JS_CLASS_ARRAY);
}
+// note: takes ownership of |values|, unlike js_create_array
+JSValue JS_NewArrayFrom(JSContext *ctx, int count, const JSValue *values)
+{
+ JSObject *p;
+ JSValue obj;
+
+ obj = JS_NewArray(ctx);
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+ if (count > 0) {
+ p = JS_VALUE_GET_OBJ(obj);
+ if (expand_fast_array(ctx, p, count)) {
+ JS_FreeValue(ctx, obj);
+ return JS_EXCEPTION;
+ }
+ p->u.array.count = count;
+ p->prop[0].u.value = js_int32(count);
+ memcpy(p->u.array.u.values, values, count * sizeof(*values));
+ }
+ return obj;
+}
+
JSValue JS_NewObject(JSContext *ctx)
{
/* inline JS_NewObjectClass(ctx, JS_CLASS_OBJECT); */
return JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_OBJECT);
}
-static void js_function_set_properties(JSContext *ctx, JSValueConst func_obj,
+static void js_function_set_properties(JSContext *ctx, JSValue func_obj,
JSAtom name, int len)
{
/* ES6 feature non compatible with ES5.1: length is configurable */
- JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, JS_NewInt32(ctx, len),
+ JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, js_int32(len),
JS_PROP_CONFIGURABLE);
JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name,
JS_AtomToString(ctx, name), JS_PROP_CONFIGURABLE);
}
-static BOOL js_class_has_bytecode(JSClassID class_id)
+static bool js_class_has_bytecode(JSClassID class_id)
{
return (class_id == JS_CLASS_BYTECODE_FUNCTION ||
class_id == JS_CLASS_GENERATOR_FUNCTION ||
@@ -5034,7 +5134,7 @@ static BOOL js_class_has_bytecode(JSClassID class_id)
}
/* return NULL without exception if not a function or no bytecode */
-static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val)
+static JSFunctionBytecode *JS_GetFunctionBytecode(JSValue val)
{
JSObject *p;
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
@@ -5045,8 +5145,8 @@ static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val)
return p->u.func.function_bytecode;
}
-static void js_method_set_home_object(JSContext *ctx, JSValueConst func_obj,
- JSValueConst home_obj)
+static void js_method_set_home_object(JSContext *ctx, JSValue func_obj,
+ JSValue home_obj)
{
JSObject *p, *p1;
JSFunctionBytecode *b;
@@ -5063,7 +5163,7 @@ static void js_method_set_home_object(JSContext *ctx, JSValueConst func_obj,
JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));
}
if (JS_VALUE_GET_TAG(home_obj) == JS_TAG_OBJECT)
- p1 = JS_VALUE_GET_OBJ(JS_DupValue(ctx, home_obj));
+ p1 = JS_VALUE_GET_OBJ(js_dup(home_obj));
else
p1 = NULL;
p->u.func.home_object = p1;
@@ -5085,8 +5185,8 @@ static JSValue js_get_function_name(JSContext *ctx, JSAtom name)
'flags'. 'flags' is a bitmask of JS_PROP_HAS_GET and
JS_PROP_HAS_SET. Also set the home object of the method.
Return < 0 if exception. */
-static int js_method_set_properties(JSContext *ctx, JSValueConst func_obj,
- JSAtom name, int flags, JSValueConst home_obj)
+static int js_method_set_properties(JSContext *ctx, JSValue func_obj,
+ JSAtom name, int flags, JSValue home_obj)
{
JSValue name_str;
@@ -5106,10 +5206,11 @@ static int js_method_set_properties(JSContext *ctx, JSValueConst func_obj,
}
/* Note: at least 'length' arguments will be readable in 'argv' */
-static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
- const char *name,
- int length, JSCFunctionEnum cproto, int magic,
- JSValueConst proto_val)
+/* `name` may be NULL, pure ASCII or UTF-8 encoded */
+JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
+ const char *name,
+ int length, JSCFunctionEnum cproto, int magic,
+ JSValue proto_val)
{
JSValue func_obj;
JSObject *p;
@@ -5150,7 +5251,7 @@ typedef struct JSCFunctionDataRecord {
uint8_t length;
uint8_t data_len;
uint16_t magic;
- JSValue data[0];
+ JSValue data[];
} JSCFunctionDataRecord;
static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val)
@@ -5166,7 +5267,7 @@ static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val)
}
}
-static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val,
+static void js_c_function_data_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA);
@@ -5179,12 +5280,12 @@ static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val,
}
}
-static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_val,
- int argc, JSValueConst *argv, int flags)
+static JSValue js_c_function_data_call(JSContext *ctx, JSValue func_obj,
+ JSValue this_val,
+ int argc, JSValue *argv, int flags)
{
JSCFunctionDataRecord *s = JS_GetOpaque(func_obj, JS_CLASS_C_FUNCTION_DATA);
- JSValueConst *arg_buf;
+ JSValue *arg_buf;
int i;
/* XXX: could add the function on the stack for debug */
@@ -5203,7 +5304,7 @@ static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
int length, int magic, int data_len,
- JSValueConst *data)
+ JSValue *data)
{
JSCFunctionDataRecord *s;
JSValue func_obj;
@@ -5223,8 +5324,8 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
s->data_len = data_len;
s->magic = magic;
for(i = 0; i < data_len; i++)
- s->data[i] = JS_DupValue(ctx, data[i]);
- JS_SetOpaque(func_obj, s);
+ s->data[i] = js_dup(data[i]);
+ JS_SetOpaqueInternal(func_obj, s);
js_function_set_properties(ctx, func_obj,
JS_ATOM_empty_string, length);
return func_obj;
@@ -5314,7 +5415,7 @@ static force_inline JSShapeProperty *find_own_property(JSProperty **ppr,
}
/* indicate that the object may be part of a function prototype cycle */
-static void set_cycle_flag(JSContext *ctx, JSValueConst obj)
+static void set_cycle_flag(JSContext *ctx, JSValue obj)
{
}
@@ -5325,12 +5426,10 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref)
if (--var_ref->header.ref_count == 0) {
if (var_ref->is_detached) {
JS_FreeValueRT(rt, var_ref->value);
+ remove_gc_object(&var_ref->header);
} else {
- list_del(&var_ref->var_ref_link); /* still on the stack */
- if (var_ref->async_func)
- async_func_free(rt, var_ref->async_func);
+ list_del(&var_ref->header.link); /* still on the stack */
}
- remove_gc_object(&var_ref->header);
js_free_rt(rt, var_ref);
}
}
@@ -5347,7 +5446,7 @@ static void js_array_finalizer(JSRuntime *rt, JSValue val)
js_free_rt(rt, p->u.array.u.values);
}
-static void js_array_mark(JSRuntime *rt, JSValueConst val,
+static void js_array_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -5365,7 +5464,7 @@ static void js_object_data_finalizer(JSRuntime *rt, JSValue val)
p->u.object_data = JS_UNDEFINED;
}
-static void js_object_data_mark(JSRuntime *rt, JSValueConst val,
+static void js_object_data_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -5380,7 +5479,7 @@ static void js_c_function_finalizer(JSRuntime *rt, JSValue val)
JS_FreeContext(p->u.cfunc.realm);
}
-static void js_c_function_mark(JSRuntime *rt, JSValueConst val,
+static void js_c_function_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -5412,7 +5511,7 @@ static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val)
}
}
-static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,
+static void js_bytecode_function_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -5428,7 +5527,7 @@ static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,
if (var_refs) {
for(i = 0; i < b->closure_var_count; i++) {
JSVarRef *var_ref = var_refs[i];
- if (var_ref) {
+ if (var_ref && var_ref->is_detached) {
mark_func(rt, &var_ref->header);
}
}
@@ -5453,7 +5552,7 @@ static void js_bound_function_finalizer(JSRuntime *rt, JSValue val)
js_free_rt(rt, bf);
}
-static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,
+static void js_bound_function_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -5470,19 +5569,11 @@ static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
JSForInIterator *it = p->u.for_in_iterator;
- int i;
-
JS_FreeValueRT(rt, it->obj);
- if (!it->is_array) {
- for(i = 0; i < it->atom_count; i++) {
- JS_FreeAtomRT(rt, it->tab_atom[i].atom);
- }
- js_free_rt(rt, it->tab_atom);
- }
js_free_rt(rt, it);
}
-static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val,
+static void js_for_in_iterator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -5516,7 +5607,7 @@ static void free_object(JSRuntime *rt, JSObject *p)
p->prop = NULL;
if (unlikely(p->first_weak_ref)) {
- reset_weak_ref(rt, p);
+ reset_weak_ref(rt, &p->first_weak_ref);
}
finalizer = rt->class_array[p->class_id].finalizer;
@@ -5546,9 +5637,6 @@ static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp)
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
free_function_bytecode(rt, (JSFunctionBytecode *)gp);
break;
- case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
- __async_func_free(rt, (JSAsyncFunctionState *)gp);
- break;
default:
abort();
}
@@ -5572,18 +5660,22 @@ static void free_zero_refcount(JSRuntime *rt)
}
/* called with the ref_count of 'v' reaches zero. */
-static void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
+static void js_free_value_rt(JSRuntime *rt, JSValue v)
{
uint32_t tag = JS_VALUE_GET_TAG(v);
-#ifdef DUMP_FREE
- {
- printf("Freeing ");
- if (tag == JS_TAG_OBJECT) {
- JS_DumpObject(rt, JS_VALUE_GET_OBJ(v));
- } else {
- JS_DumpValueShort(rt, v);
- printf("\n");
+#ifdef ENABLE_DUMPS // JS_DUMP_FREE
+ if (check_dump_flag(rt, JS_DUMP_FREE)) {
+ /* Prevent invalid object access during GC */
+ if ((rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES)
+ || (tag != JS_TAG_OBJECT && tag != JS_TAG_FUNCTION_BYTECODE)) {
+ printf("Freeing ");
+ if (tag == JS_TAG_OBJECT) {
+ JS_DumpObject(rt, JS_VALUE_GET_OBJ(v));
+ } else {
+ JS_DumpValue(rt, v);
+ printf("\n");
+ }
}
}
#endif
@@ -5595,7 +5687,7 @@ static void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
if (p->atom_type) {
JS_FreeAtomStruct(rt, p);
} else {
-#ifdef DUMP_LEAKS
+#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS
list_del(&p->link);
#endif
js_free_rt(rt, p);
@@ -5619,24 +5711,12 @@ static void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
abort(); /* never freed here */
break;
case JS_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
-#endif
{
- JSBigFloat *bf = JS_VALUE_GET_PTR(v);
+ JSBigInt *bf = JS_VALUE_GET_PTR(v);
bf_delete(&bf->num);
js_free_rt(rt, bf);
}
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_DECIMAL:
- {
- JSBigDecimal *bf = JS_VALUE_GET_PTR(v);
- bfdec_delete(&bf->num);
- js_free_rt(rt, bf);
- }
- break;
-#endif
case JS_TAG_SYMBOL:
{
JSAtomStruct *p = JS_VALUE_GET_PTR(v);
@@ -5644,14 +5724,24 @@ static void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
}
break;
default:
- printf("__JS_FreeValue: unknown tag=%d\n", tag);
+ printf("js_free_value_rt: unknown tag=%d\n", tag);
abort();
}
}
-static void __JS_FreeValue(JSContext *ctx, JSValue v)
+void JS_FreeValueRT(JSRuntime *rt, JSValue v)
+{
+ if (JS_VALUE_HAS_REF_COUNT(v)) {
+ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
+ if (--p->ref_count <= 0) {
+ js_free_value_rt(rt, v);
+ }
+ }
+}
+
+void JS_FreeValue(JSContext *ctx, JSValue v)
{
- __JS_FreeValueRT(ctx->rt, v);
+ JS_FreeValueRT(ctx->rt, v);
}
/* garbage collection */
@@ -5669,7 +5759,7 @@ static void remove_gc_object(JSGCObjectHeader *h)
list_del(&h->link);
}
-void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)
+void JS_MarkValue(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func)
{
if (JS_VALUE_HAS_REF_COUNT(val)) {
switch(JS_VALUE_GET_TAG(val)) {
@@ -5707,9 +5797,11 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
if (pr->u.getset.setter)
mark_func(rt, &pr->u.getset.setter->header);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
- /* Note: the tag does not matter
- provided it is a GC object */
- mark_func(rt, &pr->u.var_ref->header);
+ if (pr->u.var_ref->is_detached) {
+ /* Note: the tag does not matter
+ provided it is a GC object */
+ mark_func(rt, &pr->u.var_ref->header);
+ }
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
js_autoinit_mark(rt, pr, mark_func);
}
@@ -5743,32 +5835,16 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
case JS_GC_OBJ_TYPE_VAR_REF:
{
JSVarRef *var_ref = (JSVarRef *)gp;
- if (var_ref->is_detached) {
- JS_MarkValue(rt, *var_ref->pvalue, mark_func);
- } else if (var_ref->async_func) {
- mark_func(rt, &var_ref->async_func->header);
- }
+ /* only detached variable referenced are taken into account */
+ assert(var_ref->is_detached);
+ JS_MarkValue(rt, *var_ref->pvalue, mark_func);
}
break;
case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
{
- JSAsyncFunctionState *s = (JSAsyncFunctionState *)gp;
- JSStackFrame *sf = &s->frame;
- JSValue *sp;
-
- if (!s->is_completed) {
- JS_MarkValue(rt, sf->cur_func, mark_func);
- JS_MarkValue(rt, s->this_val, mark_func);
- /* sf->cur_sp = NULL if the function is running */
- if (sf->cur_sp) {
- /* if the function is running, cur_sp is not known so we
- cannot mark the stack. Marking the variables is not needed
- because a running function cannot be part of a removable
- cycle */
- for(sp = sf->arg_buf; sp < sf->cur_sp; sp++)
- JS_MarkValue(rt, *sp, mark_func);
- }
- }
+ JSAsyncFunctionData *s = (JSAsyncFunctionData *)gp;
+ if (s->is_active)
+ async_func_mark(rt, &s->func_state, mark_func);
JS_MarkValue(rt, s->resolving_funcs[0], mark_func);
JS_MarkValue(rt, s->resolving_funcs[1], mark_func);
}
@@ -5865,8 +5941,8 @@ static void gc_free_cycles(JSRuntime *rt)
{
struct list_head *el, *el1;
JSGCObjectHeader *p;
-#ifdef DUMP_GC_FREE
- BOOL header_done = FALSE;
+#ifdef ENABLE_DUMPS // JS_DUMP_GC_FREE
+ bool header_done = false;
#endif
rt->gc_phase = JS_GC_PHASE_REMOVE_CYCLES;
@@ -5876,20 +5952,21 @@ static void gc_free_cycles(JSRuntime *rt)
if (el == &rt->tmp_obj_list)
break;
p = list_entry(el, JSGCObjectHeader, link);
- /* Only need to free the GC object associated with JS values
- or async functions. The rest will be automatically removed
- because they must be referenced by them. */
+ /* Only need to free the GC object associated with JS
+ values. The rest will be automatically removed because they
+ must be referenced by them. */
switch(p->gc_obj_type) {
case JS_GC_OBJ_TYPE_JS_OBJECT:
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
- case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
-#ifdef DUMP_GC_FREE
- if (!header_done) {
- printf("Freeing cycles:\n");
- JS_DumpObjectHeader(rt);
- header_done = TRUE;
+#ifdef ENABLE_DUMPS // JS_DUMP_GC_FREE
+ if (check_dump_flag(rt, JS_DUMP_GC_FREE)) {
+ if (!header_done) {
+ printf("Freeing cycles:\n");
+ JS_DumpObjectHeader(rt);
+ header_done = true;
+ }
+ JS_DumpGCObject(rt, p);
}
- JS_DumpGCObject(rt, p);
#endif
free_gc_object(rt, p);
break;
@@ -5904,8 +5981,7 @@ static void gc_free_cycles(JSRuntime *rt)
list_for_each_safe(el, el1, &rt->gc_zero_ref_count_list) {
p = list_entry(el, JSGCObjectHeader, link);
assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT ||
- p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE ||
- p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
+ p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
js_free_rt(rt, p);
}
@@ -5928,11 +6004,11 @@ void JS_RunGC(JSRuntime *rt)
/* Return false if not an object or if the object has already been
freed (zombie objects are visible in finalizers when freeing
cycles). */
-BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj)
+bool JS_IsLiveObject(JSRuntime *rt, JSValue obj)
{
JSObject *p;
if (!JS_IsObject(obj))
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(obj);
return !p->free_mark;
}
@@ -5950,7 +6026,7 @@ typedef struct JSMemoryUsage_helper {
int64_t js_func_pc2line_size;
} JSMemoryUsage_helper;
-static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp);
+static void compute_value_size(JSValue val, JSMemoryUsage_helper *hp);
static void compute_jsstring_size(JSString *str, JSMemoryUsage_helper *hp)
{
@@ -5967,52 +6043,43 @@ static void compute_bytecode_size(JSFunctionBytecode *b, JSMemoryUsage_helper *h
int memory_used_count, js_func_size, i;
memory_used_count = 0;
- js_func_size = offsetof(JSFunctionBytecode, debug);
+ js_func_size = sizeof(*b);
if (b->vardefs) {
js_func_size += (b->arg_count + b->var_count) * sizeof(*b->vardefs);
}
if (b->cpool) {
js_func_size += b->cpool_count * sizeof(*b->cpool);
for (i = 0; i < b->cpool_count; i++) {
- JSValueConst val = b->cpool[i];
+ JSValue val = b->cpool[i];
compute_value_size(val, hp);
}
}
if (b->closure_var) {
js_func_size += b->closure_var_count * sizeof(*b->closure_var);
}
- if (!b->read_only_bytecode && b->byte_code_buf) {
+ if (b->byte_code_buf) {
hp->js_func_code_size += b->byte_code_len;
}
- if (b->has_debug) {
- js_func_size += sizeof(*b) - offsetof(JSFunctionBytecode, debug);
- if (b->debug.source) {
- memory_used_count++;
- js_func_size += b->debug.source_len + 1;
- }
- if (b->debug.pc2line_len) {
- memory_used_count++;
- hp->js_func_pc2line_count += 1;
- hp->js_func_pc2line_size += b->debug.pc2line_len;
- }
+ memory_used_count++;
+ js_func_size += b->source_len + 1;
+ if (b->pc2line_len) {
+ memory_used_count++;
+ hp->js_func_pc2line_count += 1;
+ hp->js_func_pc2line_size += b->pc2line_len;
}
hp->js_func_size += js_func_size;
hp->js_func_count += 1;
hp->memory_used_count += memory_used_count;
}
-static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp)
+static void compute_value_size(JSValue val, JSMemoryUsage_helper *hp)
{
switch(JS_VALUE_GET_TAG(val)) {
case JS_TAG_STRING:
compute_jsstring_size(JS_VALUE_GET_STRING(val), hp);
break;
case JS_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- case JS_TAG_BIG_DECIMAL:
-#endif
- /* should track JSBigFloat usage */
+ /* should track JSBigInt usage */
break;
}
}
@@ -6029,7 +6096,7 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
s->malloc_limit = rt->malloc_state.malloc_limit;
s->memory_used_count = 2; /* rt + rt->class_array */
- s->memory_used_size = sizeof(JSRuntime) + sizeof(JSValue) * rt->class_count;
+ s->memory_used_size = sizeof(JSRuntime) + sizeof(JSClass) * rt->class_count;
list_for_each(el, &rt->context_list) {
JSContext *ctx = list_entry(el, JSContext, link);
@@ -6138,10 +6205,6 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
case JS_CLASS_SYMBOL: /* u.object_data */
case JS_CLASS_DATE: /* u.object_data */
case JS_CLASS_BIG_INT: /* u.object_data */
-#ifdef CONFIG_BIGNUM
- case JS_CLASS_BIG_FLOAT: /* u.object_data */
- case JS_CLASS_BIG_DECIMAL: /* u.object_data */
-#endif
compute_value_size(p->u.object_data, hp);
break;
case JS_CLASS_C_FUNCTION: /* u.cfunc */
@@ -6232,12 +6295,10 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
case JS_CLASS_UINT32_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_BIG_INT64_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_BIG_UINT64_ARRAY: /* u.typed_array / u.array */
+ case JS_CLASS_FLOAT16_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_FLOAT32_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_FLOAT64_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_DATAVIEW: /* u.typed_array */
-#ifdef CONFIG_BIGNUM
- case JS_CLASS_FLOAT_ENV: /* u.float_env */
-#endif
case JS_CLASS_MAP: /* u.map_state */
case JS_CLASS_SET: /* u.map_state */
case JS_CLASS_WEAKMAP: /* u.map_state */
@@ -6307,13 +6368,8 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
{
- fprintf(fp, "QuickJS memory usage -- "
-#ifdef CONFIG_BIGNUM
- "BigNum "
-#endif
- CONFIG_VERSION " version, %d-bit, malloc limit: %"PRId64"\n\n",
- (int)sizeof(void *) * 8, s->malloc_limit);
-#if 1
+ fprintf(fp, "QuickJS-ng memory usage -- %s version, %d-bit, %s Endian, malloc limit: %"PRId64"\n\n",
+ JS_GetVersion(), (int)sizeof(void *) * 8, is_be() ? "Big" : "Little", s->malloc_limit);
if (rt) {
static const struct {
const char *name;
@@ -6358,10 +6414,10 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
if (obj_classes[0])
fprintf(fp, " %5d %2.0d %s\n", obj_classes[0], 0, "none");
for (class_id = 1; class_id < JS_CLASS_INIT_COUNT; class_id++) {
- if (obj_classes[class_id] && class_id < rt->class_count) {
+ if (obj_classes[class_id]) {
char buf[ATOM_GET_STR_BUF_SIZE];
fprintf(fp, " %5d %2.0d %s\n", obj_classes[class_id], class_id,
- JS_AtomGetStrRT(rt, buf, sizeof(buf), rt->class_array[class_id].class_name));
+ JS_AtomGetStrRT(rt, buf, sizeof(buf), js_std_class_def[class_id - 1].class_name));
}
}
if (obj_classes[JS_CLASS_INIT_COUNT])
@@ -6369,7 +6425,6 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
}
fprintf(fp, "\n");
}
-#endif
fprintf(fp, "%-20s %8s %8s\n", "NAME", "COUNT", "SIZE");
if (s->malloc_count) {
@@ -6436,7 +6491,7 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
JSValue JS_GetGlobalObject(JSContext *ctx)
{
- return JS_DupValue(ctx, ctx->global_obj);
+ return js_dup(ctx->global_obj);
}
/* WARNING: obj is freed */
@@ -6454,13 +6509,21 @@ JSValue JS_GetException(JSContext *ctx)
JSValue val;
JSRuntime *rt = ctx->rt;
val = rt->current_exception;
- rt->current_exception = JS_NULL;
+ rt->current_exception = JS_UNINITIALIZED;
return val;
}
-JS_BOOL JS_HasException(JSContext *ctx)
+bool JS_HasException(JSContext *ctx)
{
- return !JS_IsNull(ctx->rt->current_exception);
+ return !JS_IsUninitialized(ctx->rt->current_exception);
+}
+
+/* returns the pending backtrace (cannot be called twice). */
+JSValue JS_GetBacktrace(JSContext *ctx)
+{
+ JSValue val = ctx->error_back_trace;
+ ctx->error_back_trace = JS_UNDEFINED;
+ return val;
}
static void dbuf_put_leb128(DynBuf *s, uint32_t v)
@@ -6519,21 +6582,20 @@ static int get_sleb128(int32_t *pval, const uint8_t *buf,
}
static int find_line_num(JSContext *ctx, JSFunctionBytecode *b,
- uint32_t pc_value)
+ uint32_t pc_value, int *col)
{
const uint8_t *p_end, *p;
- int new_line_num, line_num, pc, v, ret;
+ int new_line_num, new_col_num, line_num, col_num, pc, v, ret;
unsigned int op;
- if (!b->has_debug || !b->debug.pc2line_buf) {
- /* function was stripped */
- return -1;
- }
-
- p = b->debug.pc2line_buf;
- p_end = p + b->debug.pc2line_len;
+ *col = 1;
+ p = b->pc2line_buf;
+ if (!p)
+ goto fail;
+ p_end = p + b->pc2line_len;
pc = 0;
- line_num = b->debug.line_num;
+ line_num = b->line_num;
+ col_num = b->col_num;
while (p < p_end) {
op = *p++;
if (op == 0) {
@@ -6544,11 +6606,8 @@ static int find_line_num(JSContext *ctx, JSFunctionBytecode *b,
pc += val;
p += ret;
ret = get_sleb128(&v, p, p_end);
- if (ret < 0) {
- fail:
- /* should never happen */
- return b->debug.line_num;
- }
+ if (ret < 0)
+ goto fail;
p += ret;
new_line_num = line_num + v;
} else {
@@ -6556,21 +6615,31 @@ static int find_line_num(JSContext *ctx, JSFunctionBytecode *b,
pc += (op / PC2LINE_RANGE);
new_line_num = line_num + (op % PC2LINE_RANGE) + PC2LINE_BASE;
}
+ ret = get_sleb128(&v, p, p_end);
+ if (ret < 0)
+ goto fail;
+ p += ret;
+ new_col_num = col_num + v;
if (pc_value < pc)
- return line_num;
+ break;
line_num = new_line_num;
+ col_num = new_col_num;
}
+ *col = col_num;
return line_num;
+fail:
+ /* should never happen */
+ return b->line_num;
}
/* in order to avoid executing arbitrary code during the stack trace
generation, we only look at simple 'name' properties containing a
string. */
-static const char *get_func_name(JSContext *ctx, JSValueConst func)
+static const char *get_func_name(JSContext *ctx, JSValue func)
{
JSProperty *pr;
JSShapeProperty *prs;
- JSValueConst val;
+ JSValue val;
if (JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)
return NULL;
@@ -6585,148 +6654,303 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func)
return JS_ToCString(ctx, val);
}
+/* Note: it is important that no exception is returned by this function */
+static bool can_add_backtrace(JSValue obj)
+{
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
+ return false;
+ p = JS_VALUE_GET_OBJ(obj);
+ if (p->class_id != JS_CLASS_ERROR)
+ return false;
+ if (find_own_property1(p, JS_ATOM_stack))
+ return false;
+ return true;
+}
+
#define JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL (1 << 0)
/* only taken into account if filename is provided */
#define JS_BACKTRACE_FLAG_SINGLE_LEVEL (1 << 1)
+#define JS_BACKTRACE_FLAG_FILTER_FUNC (1 << 2)
/* if filename != NULL, an additional level is added with the filename
and line number information (used for parse error). */
-void build_backtrace(JSContext *ctx, JSValueConst error_obj,
- const char *filename, int line_num,
+static void build_backtrace(JSContext *ctx, JSValue error_val, JSValue filter_func,
+ const char *filename, int line_num, int col_num,
int backtrace_flags)
{
- JSStackFrame *sf;
- JSValue str;
+ JSStackFrame *sf, *sf_start;
+ JSValue stack, prepare, saved_exception;
DynBuf dbuf;
const char *func_name_str;
const char *str1;
JSObject *p;
- BOOL backtrace_barrier;
-
- js_dbuf_init(ctx, &dbuf);
- if (filename) {
- dbuf_printf(&dbuf, " at %s", filename);
- if (line_num != -1)
- dbuf_printf(&dbuf, ":%d", line_num);
- dbuf_putc(&dbuf, '\n');
- str = JS_NewString(ctx, filename);
- JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_fileName, str,
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num),
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- if (backtrace_flags & JS_BACKTRACE_FLAG_SINGLE_LEVEL)
+ JSFunctionBytecode *b;
+ bool backtrace_barrier, has_prepare, has_filter_func;
+ JSRuntime *rt;
+ JSCallSiteData csd[64];
+ uint32_t i;
+ double d;
+ int stack_trace_limit;
+
+ rt = ctx->rt;
+ if (rt->in_build_stack_trace)
+ return;
+ rt->in_build_stack_trace = true;
+
+ // Save exception because conversion to double may fail.
+ saved_exception = JS_GetException(ctx);
+
+ // Extract stack trace limit.
+ // Ignore error since it sets d to NAN anyway.
+ // coverity[check_return]
+ JS_ToFloat64(ctx, &d, ctx->error_stack_trace_limit);
+ if (isnan(d) || d < 0.0)
+ stack_trace_limit = 0;
+ else if (d > INT32_MAX)
+ stack_trace_limit = INT32_MAX;
+ else
+ stack_trace_limit = fabs(d);
+
+ // Restore current exception.
+ JS_Throw(ctx, saved_exception);
+ saved_exception = JS_UNINITIALIZED;
+
+ stack_trace_limit = min_int(stack_trace_limit, countof(csd));
+ stack_trace_limit = max_int(stack_trace_limit, 0);
+ has_prepare = false;
+ has_filter_func = backtrace_flags & JS_BACKTRACE_FLAG_FILTER_FUNC;
+ i = 0;
+
+ if (!JS_IsNull(ctx->error_ctor)) {
+ prepare = js_dup(ctx->error_prepare_stack);
+ has_prepare = JS_IsFunction(ctx, prepare);
+ }
+
+ if (has_prepare) {
+ saved_exception = JS_GetException(ctx);
+ if (stack_trace_limit == 0)
+ goto done;
+ if (filename)
+ js_new_callsite_data2(ctx, &csd[i++], filename, line_num, col_num);
+ } else {
+ js_dbuf_init(ctx, &dbuf);
+ if (stack_trace_limit == 0)
goto done;
+ if (filename) {
+ i++;
+ dbuf_printf(&dbuf, " at %s", filename);
+ if (line_num != -1)
+ dbuf_printf(&dbuf, ":%d:%d", line_num, col_num);
+ dbuf_putc(&dbuf, '\n');
+ }
+ }
+
+ if (filename && (backtrace_flags & JS_BACKTRACE_FLAG_SINGLE_LEVEL))
+ goto done;
+
+ sf_start = rt->current_stack_frame;
+
+ /* Find the frame we want to start from. Note that when a filter is used the filter
+ function will be the first, but we also specify we want to skip the first one. */
+ if (has_filter_func) {
+ for (sf = sf_start; sf != NULL && i < stack_trace_limit; sf = sf->prev_frame) {
+ if (js_same_value(ctx, sf->cur_func, filter_func)) {
+ sf_start = sf;
+ break;
+ }
+ }
}
- for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
+
+ for (sf = sf_start; sf != NULL && i < stack_trace_limit; sf = sf->prev_frame) {
if (backtrace_flags & JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL) {
backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL;
continue;
}
- func_name_str = get_func_name(ctx, sf->cur_func);
- if (!func_name_str || func_name_str[0] == '\0')
- str1 = "<anonymous>";
- else
- str1 = func_name_str;
- dbuf_printf(&dbuf, " at %s", str1);
- JS_FreeCString(ctx, func_name_str);
p = JS_VALUE_GET_OBJ(sf->cur_func);
- backtrace_barrier = FALSE;
- if (js_class_has_bytecode(p->class_id)) {
- JSFunctionBytecode *b;
- const char *atom_str;
- int line_num1;
+ b = NULL;
+ backtrace_barrier = false;
+ if (js_class_has_bytecode(p->class_id)) {
b = p->u.func.function_bytecode;
backtrace_barrier = b->backtrace_barrier;
- if (b->has_debug) {
- line_num1 = find_line_num(ctx, b,
- sf->cur_pc - b->byte_code_buf - 1);
- atom_str = JS_AtomToCString(ctx, b->debug.filename);
- dbuf_printf(&dbuf, " (%s",
- atom_str ? atom_str : "<null>");
+ }
+
+ if (has_prepare) {
+ js_new_callsite_data(ctx, &csd[i], sf);
+ } else {
+ /* func_name_str is UTF-8 encoded if needed */
+ func_name_str = get_func_name(ctx, sf->cur_func);
+ if (!func_name_str || func_name_str[0] == '\0')
+ str1 = "<anonymous>";
+ else
+ str1 = func_name_str;
+ dbuf_printf(&dbuf, " at %s", str1);
+ JS_FreeCString(ctx, func_name_str);
+
+ if (b && sf->cur_pc) {
+ const char *atom_str;
+ int line_num1, col_num1;
+ uint32_t pc;
+
+ pc = sf->cur_pc - b->byte_code_buf - 1;
+ line_num1 = find_line_num(ctx, b, pc, &col_num1);
+ atom_str = b->filename ? JS_AtomToCString(ctx, b->filename) : NULL;
+ dbuf_printf(&dbuf, " (%s", atom_str ? atom_str : "<null>");
JS_FreeCString(ctx, atom_str);
if (line_num1 != -1)
- dbuf_printf(&dbuf, ":%d", line_num1);
+ dbuf_printf(&dbuf, ":%d:%d", line_num1, col_num1);
dbuf_putc(&dbuf, ')');
+ } else if (b) {
+ // FIXME(bnoordhuis) Missing `sf->cur_pc = pc` in bytecode
+ // handler in JS_CallInternal. Almost never user observable
+ // except with intercepting JS proxies that throw exceptions.
+ dbuf_printf(&dbuf, " (missing)");
+ } else {
+ dbuf_printf(&dbuf, " (native)");
}
- } else {
- dbuf_printf(&dbuf, " (native)");
+ dbuf_putc(&dbuf, '\n');
}
- dbuf_putc(&dbuf, '\n');
+ i++;
+
/* stop backtrace if JS_EVAL_FLAG_BACKTRACE_BARRIER was used */
if (backtrace_barrier)
break;
}
done:
- dbuf_putc(&dbuf, '\0');
- if (dbuf_error(&dbuf))
- str = JS_NULL;
- else
- str = JS_NewString(ctx, (char *)dbuf.buf);
- dbuf_free(&dbuf);
- JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_stack, str,
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
+ if (has_prepare) {
+ int j = 0, k;
+ stack = JS_NewArray(ctx);
+ if (JS_IsException(stack)) {
+ stack = JS_NULL;
+ } else {
+ for (; j < i; j++) {
+ JSValue v = js_new_callsite(ctx, &csd[j]);
+ if (JS_IsException(v))
+ break;
+ if (JS_DefinePropertyValueUint32(ctx, stack, j, v, JS_PROP_C_W_E) < 0) {
+ JS_FreeValue(ctx, v);
+ break;
+ }
+ }
+ }
+ // Clear the csd's we didn't use in case of error.
+ for (k = j; k < i; k++) {
+ JS_FreeValue(ctx, csd[k].filename);
+ JS_FreeValue(ctx, csd[k].func);
+ JS_FreeValue(ctx, csd[k].func_name);
+ }
+ JSValue args[] = {
+ error_val,
+ stack,
+ };
+ JSValue stack2 = JS_Call(ctx, prepare, ctx->error_ctor, countof(args), args);
+ JS_FreeValue(ctx, stack);
+ if (JS_IsException(stack2))
+ stack = JS_NULL;
+ else
+ stack = stack2;
+ JS_FreeValue(ctx, prepare);
+ JS_Throw(ctx, saved_exception);
+ } else {
+ if (dbuf_error(&dbuf))
+ stack = JS_NULL;
+ else
+ stack = JS_NewStringLen(ctx, (char *)dbuf.buf, dbuf.size);
+ dbuf_free(&dbuf);
+ }
+
+ if (JS_IsUndefined(ctx->error_back_trace))
+ ctx->error_back_trace = js_dup(stack);
+ if (has_filter_func || can_add_backtrace(error_val)) {
+ JS_DefinePropertyValue(ctx, error_val, JS_ATOM_stack, stack,
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
+ } else {
+ JS_FreeValue(ctx, stack);
+ }
+
+ rt->in_build_stack_trace = false;
}
-/* Note: it is important that no exception is returned by this function */
-static BOOL is_backtrace_needed(JSContext *ctx, JSValueConst obj)
+JSValue JS_NewError(JSContext *ctx)
{
- JSObject *p;
- if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
- return FALSE;
- p = JS_VALUE_GET_OBJ(obj);
- if (p->class_id != JS_CLASS_ERROR)
- return FALSE;
- if (find_own_property1(p, JS_ATOM_stack))
- return FALSE;
- return TRUE;
+ JSValue obj = JS_NewObjectClass(ctx, JS_CLASS_ERROR);
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+ build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, 0);
+ return obj;
}
-JSValue JS_NewError(JSContext *ctx)
+static JSValue JS_MakeError(JSContext *ctx, JSErrorEnum error_num,
+ const char *message, bool add_backtrace)
{
- return JS_NewObjectClass(ctx, JS_CLASS_ERROR);
+ JSValue obj, msg;
+
+ if (error_num == JS_PLAIN_ERROR) {
+ obj = JS_NewObjectClass(ctx, JS_CLASS_ERROR);
+ } else {
+ obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[error_num],
+ JS_CLASS_ERROR);
+ }
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+ msg = JS_NewString(ctx, message);
+ if (JS_IsException(msg))
+ msg = JS_NewString(ctx, "Invalid error message");
+ if (!JS_IsException(msg)) {
+ JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg,
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
+ }
+ if (add_backtrace)
+ build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, 0);
+ return obj;
}
-static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num,
- const char *fmt, va_list ap, BOOL add_backtrace)
+/* fmt and arguments may be pure ASCII or UTF-8 encoded contents */
+static JSValue JS_PRINTF_FORMAT_ATTR(4, 0)
+JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num,
+ bool add_backtrace, JS_PRINTF_FORMAT const char *fmt, va_list ap)
{
- char buf[8192];
- JSValue obj, ret;
+ char buf[256];
+ JSValue obj;
vsnprintf(buf, sizeof(buf), fmt, ap);
- obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[error_num],
- JS_CLASS_ERROR);
+ obj = JS_MakeError(ctx, error_num, buf, add_backtrace);
if (unlikely(JS_IsException(obj))) {
/* out of memory: throw JS_NULL to avoid recursing */
obj = JS_NULL;
- } else {
- JS_DefinePropertyValue(ctx, obj, JS_ATOM_message,
- JS_NewString(ctx, buf),
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- }
- if (add_backtrace) {
- build_backtrace(ctx, obj, NULL, 0, 0);
}
- ret = JS_Throw(ctx, obj);
- return ret;
+ return JS_Throw(ctx, obj);
}
-static JSValue JS_ThrowError(JSContext *ctx, JSErrorEnum error_num,
- const char *fmt, va_list ap)
+static JSValue JS_PRINTF_FORMAT_ATTR(3, 0)
+JS_ThrowError(JSContext *ctx, JSErrorEnum error_num,
+ JS_PRINTF_FORMAT const char *fmt, va_list ap)
{
JSRuntime *rt = ctx->rt;
JSStackFrame *sf;
- BOOL add_backtrace;
+ bool add_backtrace;
/* the backtrace is added later if called from a bytecode function */
sf = rt->current_stack_frame;
add_backtrace = !rt->in_out_of_memory &&
(!sf || (JS_GetFunctionBytecode(sf->cur_func) == NULL));
- return JS_ThrowError2(ctx, error_num, fmt, ap, add_backtrace);
+ return JS_ThrowError2(ctx, error_num, add_backtrace, fmt, ap);
}
-JSValue FORMAT_ATTR(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...)
+JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowPlainError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...)
+{
+ JSValue val;
+ va_list ap;
+
+ va_start(ap, fmt);
+ val = JS_ThrowError(ctx, JS_PLAIN_ERROR, fmt, ap);
+ va_end(ap);
+ return val;
+}
+
+JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowSyntaxError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...)
{
JSValue val;
va_list ap;
@@ -6737,7 +6961,7 @@ JSValue FORMAT_ATTR(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, .
return val;
}
-JSValue FORMAT_ATTR(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...)
+JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowTypeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...)
{
JSValue val;
va_list ap;
@@ -6748,7 +6972,7 @@ JSValue FORMAT_ATTR(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...
return val;
}
-static int FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char *fmt, ...)
+static int JS_PRINTF_FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, JS_PRINTF_FORMAT const char *fmt, ...)
{
va_list ap;
@@ -6759,30 +6983,30 @@ static int FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags,
va_end(ap);
return -1;
} else {
- return FALSE;
+ return false;
}
}
-/* never use it directly */
-static JSValue FORMAT_ATTR(3, 4) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif // __GNUC__
+static JSValue JS_ThrowTypeErrorAtom(JSContext *ctx, const char *fmt, JSAtom atom)
{
char buf[ATOM_GET_STR_BUF_SIZE];
- return JS_ThrowTypeError(ctx, fmt,
- JS_AtomGetStr(ctx, buf, sizeof(buf), atom));
+ JS_AtomGetStr(ctx, buf, sizeof(buf), atom);
+ return JS_ThrowTypeError(ctx, fmt, buf);
}
-/* never use it directly */
-static JSValue FORMAT_ATTR(3, 4) __JS_ThrowSyntaxErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
+static JSValue JS_ThrowSyntaxErrorAtom(JSContext *ctx, const char *fmt, JSAtom atom)
{
char buf[ATOM_GET_STR_BUF_SIZE];
- return JS_ThrowSyntaxError(ctx, fmt,
- JS_AtomGetStr(ctx, buf, sizeof(buf), atom));
+ JS_AtomGetStr(ctx, buf, sizeof(buf), atom);
+ return JS_ThrowSyntaxError(ctx, fmt, buf);
}
-
-/* %s is replaced by 'atom'. The macro is used so that gcc can check
- the format string. */
-#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "")
-#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "")
+#ifdef __GNUC__
+#pragma GCC diagnostic pop // ignored "-Wformat-nonliteral"
+#endif // __GNUC__
static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)
{
@@ -6791,11 +7015,11 @@ static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)
JS_ThrowTypeErrorAtom(ctx, "'%s' is read-only", atom);
return -1;
} else {
- return FALSE;
+ return false;
}
}
-JSValue FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...)
+JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...)
{
JSValue val;
va_list ap;
@@ -6806,7 +7030,7 @@ JSValue FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt
return val;
}
-JSValue FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...)
+JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...)
{
JSValue val;
va_list ap;
@@ -6817,7 +7041,7 @@ JSValue FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ..
return val;
}
-JSValue FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...)
+JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...)
{
JSValue val;
va_list ap;
@@ -6832,16 +7056,21 @@ JSValue JS_ThrowOutOfMemory(JSContext *ctx)
{
JSRuntime *rt = ctx->rt;
if (!rt->in_out_of_memory) {
- rt->in_out_of_memory = TRUE;
+ rt->in_out_of_memory = true;
JS_ThrowInternalError(ctx, "out of memory");
- rt->in_out_of_memory = FALSE;
+ rt->in_out_of_memory = false;
}
return JS_EXCEPTION;
}
static JSValue JS_ThrowStackOverflow(JSContext *ctx)
{
- return JS_ThrowInternalError(ctx, "stack overflow");
+ return JS_ThrowRangeError(ctx, "Maximum call stack size exceeded");
+}
+
+static JSValue JS_ThrowTypeErrorNotAFunction(JSContext *ctx)
+{
+ return JS_ThrowTypeError(ctx, "not a function");
}
static JSValue JS_ThrowTypeErrorNotAnObject(JSContext *ctx)
@@ -6857,7 +7086,7 @@ static JSValue JS_ThrowTypeErrorNotASymbol(JSContext *ctx)
static JSValue JS_ThrowReferenceErrorNotDefined(JSContext *ctx, JSAtom name)
{
char buf[ATOM_GET_STR_BUF_SIZE];
- return JS_ThrowReferenceError(ctx, "'%s' is not defined",
+ return JS_ThrowReferenceError(ctx, "%s is not defined",
JS_AtomGetStr(ctx, buf, sizeof(buf), name));
}
@@ -6871,7 +7100,7 @@ static JSValue JS_ThrowReferenceErrorUninitialized(JSContext *ctx, JSAtom name)
static JSValue JS_ThrowReferenceErrorUninitialized2(JSContext *ctx,
JSFunctionBytecode *b,
- int idx, BOOL is_ref)
+ int idx, bool is_ref)
{
JSAtom atom = JS_ATOM_NULL;
if (is_ref) {
@@ -6900,7 +7129,7 @@ static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
if (rt->interrupt_handler(rt, rt->interrupt_opaque)) {
/* XXX: should set a specific flag to avoid catching */
JS_ThrowInternalError(ctx, "interrupted");
- JS_SetUncatchableError(ctx, ctx->rt->current_exception, TRUE);
+ js_set_uncatchable_error(ctx, ctx->rt->current_exception, true);
return -1;
}
}
@@ -6916,10 +7145,10 @@ static inline __exception int js_poll_interrupts(JSContext *ctx)
}
}
-/* return -1 (exception) or TRUE/FALSE */
-static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
- JSValueConst proto_val,
- BOOL throw_flag)
+/* return -1 (exception) or true/false */
+static int JS_SetPrototypeInternal(JSContext *ctx, JSValue obj,
+ JSValue proto_val,
+ bool throw_flag)
{
JSObject *proto, *p, *p1;
JSShape *sh;
@@ -6945,19 +7174,26 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
}
if (throw_flag && JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
- return TRUE;
+ return true;
if (unlikely(p->class_id == JS_CLASS_PROXY))
return js_proxy_setPrototypeOf(ctx, obj, proto_val, throw_flag);
sh = p->shape;
if (sh->proto == proto)
- return TRUE;
+ return true;
+ if (p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_OBJECT])) {
+ if (throw_flag) {
+ JS_ThrowTypeError(ctx, "'Immutable prototype object \'Object.prototype\' cannot have their prototype set'");
+ return -1;
+ }
+ return false;
+ }
if (!p->extensible) {
if (throw_flag) {
JS_ThrowTypeError(ctx, "object is not extensible");
return -1;
} else {
- return FALSE;
+ return false;
}
}
if (proto) {
@@ -6969,13 +7205,13 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
JS_ThrowTypeError(ctx, "circular prototype chain");
return -1;
} else {
- return FALSE;
+ return false;
}
}
/* Note: for Proxy objects, proto is NULL */
p1 = p1->shape->proto;
} while (p1 != NULL);
- JS_DupValue(ctx, proto_val);
+ js_dup(proto_val);
}
if (js_shape_prepare_update(ctx, p, NULL))
@@ -6984,30 +7220,22 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
if (sh->proto)
JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto));
sh->proto = proto;
- return TRUE;
+ return true;
}
-/* return -1 (exception) or TRUE/FALSE */
-int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val)
+/* return -1 (exception) or true/false */
+int JS_SetPrototype(JSContext *ctx, JSValue obj, JSValue proto_val)
{
- return JS_SetPrototypeInternal(ctx, obj, proto_val, TRUE);
+ return JS_SetPrototypeInternal(ctx, obj, proto_val, true);
}
/* Only works for primitive types, otherwise return JS_NULL. */
-static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val)
+static JSValue JS_GetPrototypePrimitive(JSContext *ctx, JSValue val)
{
switch(JS_VALUE_GET_NORM_TAG(val)) {
case JS_TAG_BIG_INT:
val = ctx->class_proto[JS_CLASS_BIG_INT];
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- val = ctx->class_proto[JS_CLASS_BIG_FLOAT];
- break;
- case JS_TAG_BIG_DECIMAL:
- val = ctx->class_proto[JS_CLASS_BIG_DECIMAL];
- break;
-#endif
case JS_TAG_INT:
case JS_TAG_FLOAT64:
val = ctx->class_proto[JS_CLASS_NUMBER];
@@ -7032,7 +7260,7 @@ static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val)
}
/* Return an Object, JS_NULL or JS_EXCEPTION in case of Proxy object. */
-JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj)
+JSValue JS_GetPrototype(JSContext *ctx, JSValue obj)
{
JSValue val;
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
@@ -7045,10 +7273,10 @@ JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj)
if (!p)
val = JS_NULL;
else
- val = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
+ val = js_dup(JS_MKPTR(JS_TAG_OBJECT, p));
}
} else {
- val = JS_DupValue(ctx, JS_GetPrototypePrimitive(ctx, obj));
+ val = js_dup(JS_GetPrototypePrimitive(ctx, obj));
}
return val;
}
@@ -7061,17 +7289,25 @@ static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj)
return obj1;
}
-/* return TRUE, FALSE or (-1) in case of exception */
-static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val,
- JSValueConst obj)
+int JS_GetLength(JSContext *ctx, JSValue obj, int64_t *pres) {
+ return js_get_length64(ctx, pres, obj);
+}
+
+int JS_SetLength(JSContext *ctx, JSValue obj, int64_t len) {
+ return js_set_length64(ctx, obj, len);
+}
+
+/* return true, false or (-1) in case of exception */
+static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValue val,
+ JSValue obj)
{
JSValue obj_proto;
JSObject *proto;
const JSObject *p, *proto1;
- BOOL ret;
+ int ret;
if (!JS_IsFunction(ctx, obj))
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(obj);
if (p->class_id == JS_CLASS_BOUND_FUNCTION) {
JSBoundFunction *s = p->u.bound_function;
@@ -7080,7 +7316,7 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val,
/* Only explicitly boxed values are instances of constructors */
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
- return FALSE;
+ return false;
obj_proto = JS_GetProperty(ctx, obj, JS_ATOM_prototype);
if (JS_VALUE_GET_TAG(obj_proto) != JS_TAG_OBJECT) {
if (!JS_IsException(obj_proto))
@@ -7096,7 +7332,7 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val,
/* slow case if proxy in the prototype chain */
if (unlikely(p->class_id == JS_CLASS_PROXY)) {
JSValue obj1;
- obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p));
+ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p));
for(;;) {
obj1 = JS_GetPrototypeFree(ctx, obj1);
if (JS_IsException(obj1)) {
@@ -7104,12 +7340,12 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val,
break;
}
if (JS_IsNull(obj1)) {
- ret = FALSE;
+ ret = false;
break;
}
if (proto == JS_VALUE_GET_OBJ(obj1)) {
JS_FreeValue(ctx, obj1);
- ret = TRUE;
+ ret = true;
break;
}
/* must check for timeout to avoid infinite loop */
@@ -7120,13 +7356,13 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val,
}
}
} else {
- ret = FALSE;
+ ret = false;
}
break;
}
p = proto1;
if (proto == p) {
- ret = TRUE;
+ ret = true;
break;
}
}
@@ -7135,8 +7371,8 @@ done:
return ret;
}
-/* return TRUE, FALSE or (-1) in case of exception */
-int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj)
+/* return true, false or (-1) in case of exception */
+int JS_IsInstanceOf(JSContext *ctx, JSValue val, JSValue obj)
{
JSValue method;
@@ -7193,15 +7429,16 @@ static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop,
return 0;
}
-JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
- JSAtom prop, JSValueConst this_obj,
- BOOL throw_ref_error)
+static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValue obj,
+ JSAtom prop, JSValue this_obj,
+ bool throw_ref_error)
{
JSObject *p;
JSProperty *pr;
JSShapeProperty *prs;
- uint32_t tag;
+ uint32_t tag, proto_depth;
+ proto_depth = 0;
tag = JS_VALUE_GET_TAG(obj);
if (unlikely(tag != JS_TAG_OBJECT)) {
switch(tag) {
@@ -7218,14 +7455,11 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
uint32_t idx, ch;
idx = __JS_AtomToUInt32(prop);
if (idx < p1->len) {
- if (p1->is_wide_char)
- ch = p1->u.str16[idx];
- else
- ch = p1->u.str8[idx];
+ ch = string_get(p1, idx);
return js_new_string_char(ctx, ch);
}
} else if (prop == JS_ATOM_length) {
- return JS_NewInt32(ctx, p1->len);
+ return js_int32(p1->len);
}
}
break;
@@ -7251,14 +7485,14 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
} else {
JSValue func = JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter);
/* Note: the field could be removed in the getter */
- func = JS_DupValue(ctx, func);
+ func = js_dup(func);
return JS_CallFree(ctx, func, this_obj, 0, NULL);
}
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
JSValue val = *pr->u.var_ref->pvalue;
if (unlikely(JS_IsUninitialized(val)))
return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);
- return JS_DupValue(ctx, val);
+ return js_dup(val);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
/* Instantiate property and retry */
if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
@@ -7268,7 +7502,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
} else {
if (JS_IsUndefined(pr->u.value) && ctx->handleUndefined)
ctx->handleUndefined(ctx);
- return JS_DupValue(ctx, pr->u.value);
+ return js_dup(pr->u.value);
}
}
if (unlikely(p->is_exotic)) {
@@ -7279,12 +7513,10 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
if (idx < p->u.array.count) {
/* we avoid duplicating the code */
return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);
- } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
+ } else if (is_typed_array(p->class_id)) {
return JS_UNDEFINED;
}
- } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
+ } else if (is_typed_array(p->class_id)) {
int ret;
ret = JS_AtomIsNumericIndex(ctx, prop);
if (ret != 0) {
@@ -7301,7 +7533,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
/* XXX: should pass throw_ref_error */
/* Note: if 'p' is a prototype, it can be
freed in the called function */
- obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
+ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p));
retval = em->get_property(ctx, obj1, prop, this_obj);
JS_FreeValue(ctx, obj1);
return retval;
@@ -7313,7 +7545,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
/* Note: if 'p' is a prototype, it can be
freed in the called function */
- obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
+ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p));
ret = em->get_own_property(ctx, &desc, obj1, prop);
JS_FreeValue(ctx, obj1);
if (ret < 0)
@@ -7330,6 +7562,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
}
}
}
+ proto_depth++;
p = p->shape->proto;
if (!p)
break;
@@ -7341,6 +7574,11 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
}
}
+JSValue JS_GetProperty(JSContext *ctx, JSValue this_obj, JSAtom prop)
+{
+ return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, false);
+}
+
static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom)
{
return JS_ThrowTypeErrorAtom(ctx, "private class field '%s' does not exist",
@@ -7349,8 +7587,8 @@ static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom)
/* Private fields can be added even on non extensible objects or
Proxies */
-static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj,
- JSValueConst name, JSValue val)
+static int JS_DefinePrivateField(JSContext *ctx, JSValue obj,
+ JSValue name, JSValue val)
{
JSObject *p;
JSShapeProperty *prs;
@@ -7384,8 +7622,8 @@ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj,
return 0;
}
-static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj,
- JSValueConst name)
+static JSValue JS_GetPrivateField(JSContext *ctx, JSValue obj,
+ JSValue name)
{
JSObject *p;
JSShapeProperty *prs;
@@ -7404,11 +7642,11 @@ static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj,
JS_ThrowTypeErrorPrivateNotFound(ctx, prop);
return JS_EXCEPTION;
}
- return JS_DupValue(ctx, pr->u.value);
+ return js_dup(pr->u.value);
}
-static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj,
- JSValueConst name, JSValue val)
+static int JS_SetPrivateField(JSContext *ctx, JSValue obj,
+ JSValue name, JSValue val)
{
JSObject *p;
JSShapeProperty *prs;
@@ -7439,7 +7677,7 @@ static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj,
/* add a private brand field to 'home_obj' if not already present and
if obj is != null add a private brand to it */
-static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
+static int JS_AddBrand(JSContext *ctx, JSValue obj, JSValue home_obj)
{
JSObject *p, *p1;
JSShapeProperty *prs;
@@ -7463,9 +7701,9 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
JS_FreeValue(ctx, brand);
return -1;
}
- pr->u.value = JS_DupValue(ctx, brand);
+ pr->u.value = js_dup(brand);
} else {
- brand = JS_DupValue(ctx, pr->u.value);
+ brand = js_dup(pr->u.value);
}
brand_atom = js_symbol_to_atom(ctx, brand);
@@ -7485,17 +7723,18 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
} else {
JS_FreeAtom(ctx, brand_atom);
}
+
return 0;
}
/* return a boolean telling if the brand of the home object of 'func'
is present on 'obj' or -1 in case of exception */
-static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
+static int JS_CheckBrand(JSContext *ctx, JSValue obj, JSValue func)
{
JSObject *p, *p1, *home_obj;
JSShapeProperty *prs;
JSProperty *pr;
- JSValueConst brand;
+ JSValue brand;
/* get the home object of 'func' */
if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT))
@@ -7528,7 +7767,7 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
}
static uint32_t js_string_obj_get_length(JSContext *ctx,
- JSValueConst obj)
+ JSValue obj)
{
JSObject *p;
JSString *p1;
@@ -7549,7 +7788,7 @@ static int num_keys_cmp(const void *p1, const void *p2, void *opaque)
JSAtom atom1 = ((const JSPropertyEnum *)p1)->atom;
JSAtom atom2 = ((const JSPropertyEnum *)p2)->atom;
uint32_t v1, v2;
- BOOL atom1_is_integer, atom2_is_integer;
+ bool atom1_is_integer, atom2_is_integer;
atom1_is_integer = JS_AtomIsArrayIndex(ctx, &v1, atom1);
atom2_is_integer = JS_AtomIsArrayIndex(ctx, &v2, atom2);
@@ -7586,7 +7825,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
JSAtom atom;
uint32_t num_keys_count, str_keys_count, sym_keys_count, atom_count;
uint32_t num_index, str_index, sym_index, exotic_count, exotic_keys_count;
- BOOL is_enumerable, num_sorted;
+ bool is_enumerable, num_sorted;
uint32_t num_key;
JSAtomKindEnum kind;
@@ -7649,7 +7888,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
atom = tab_exotic[i].atom;
kind = JS_AtomGetKind(ctx, atom);
if (((flags >> kind) & 1) != 0) {
- is_enumerable = FALSE;
+ is_enumerable = false;
if (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY)) {
JSPropertyDescriptor desc;
int res;
@@ -7689,7 +7928,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
str_index = num_keys_count;
sym_index = str_index + str_keys_count;
- num_sorted = TRUE;
+ num_sorted = true;
sh = p->shape;
for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {
atom = prs->atom;
@@ -7700,7 +7939,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
((flags >> kind) & 1) != 0) {
if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) {
j = num_index++;
- num_sorted = FALSE;
+ num_sorted = false;
} else if (kind == JS_ATOM_KIND_STRING) {
j = str_index++;
} else {
@@ -7729,7 +7968,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
js_free_prop_enum(ctx, tab_atom, num_index);
return -1;
}
- tab_atom[num_index].is_enumerable = TRUE;
+ tab_atom[num_index].is_enumerable = true;
num_index++;
}
}
@@ -7766,7 +8005,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
}
int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab,
- uint32_t *plen, JSValueConst obj, int flags)
+ uint32_t *plen, JSValue obj, int flags)
{
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {
JS_ThrowTypeErrorNotAnObject(ctx);
@@ -7777,7 +8016,7 @@ int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab,
}
/* Return -1 if exception,
- FALSE if the property does not exist, TRUE if it exists. If TRUE is
+ false if the property does not exist, true if it exists. If true is
returned, the property descriptor 'desc' is filled present. */
static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc,
JSObject *p, JSAtom prop)
@@ -7797,16 +8036,16 @@ retry:
if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {
desc->flags |= JS_PROP_GETSET;
if (pr->u.getset.getter)
- desc->getter = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));
+ desc->getter = js_dup(JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));
if (pr->u.getset.setter)
- desc->setter = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));
+ desc->setter = js_dup(JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
JSValue val = *pr->u.var_ref->pvalue;
if (unlikely(JS_IsUninitialized(val))) {
JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);
return -1;
}
- desc->value = JS_DupValue(ctx, val);
+ desc->value = js_dup(val);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
/* Instantiate property and retry */
if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
@@ -7814,7 +8053,7 @@ retry:
goto retry;
}
} else {
- desc->value = JS_DupValue(ctx, pr->u.value);
+ desc->value = js_dup(pr->u.value);
}
} else {
/* for consistency, send the exception even if desc is NULL */
@@ -7827,7 +8066,7 @@ retry:
/* nothing to do: delay instantiation until actual value and/or attributes are read */
}
}
- return TRUE;
+ return true;
}
if (p->is_exotic) {
if (p->fast_array) {
@@ -7843,7 +8082,7 @@ retry:
desc->setter = JS_UNDEFINED;
desc->value = JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);
}
- return TRUE;
+ return true;
}
}
} else {
@@ -7854,11 +8093,11 @@ retry:
}
}
}
- return FALSE;
+ return false;
}
int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc,
- JSValueConst obj, JSAtom prop)
+ JSValue obj, JSAtom prop)
{
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {
JS_ThrowTypeErrorNotAnObject(ctx);
@@ -7867,13 +8106,19 @@ int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc,
return JS_GetOwnPropertyInternal(ctx, desc, JS_VALUE_GET_OBJ(obj), prop);
}
-/* return -1 if exception (Proxy object only) or TRUE/FALSE */
-int JS_IsExtensible(JSContext *ctx, JSValueConst obj)
+void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab,
+ uint32_t len)
+{
+ js_free_prop_enum(ctx, tab, len);
+}
+
+/* return -1 if exception (Proxy object only) or true/false */
+int JS_IsExtensible(JSContext *ctx, JSValue obj)
{
JSObject *p;
if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(obj);
if (unlikely(p->class_id == JS_CLASS_PROXY))
return js_proxy_isExtensible(ctx, obj);
@@ -7881,61 +8126,60 @@ int JS_IsExtensible(JSContext *ctx, JSValueConst obj)
return p->extensible;
}
-/* return -1 if exception (Proxy object only) or TRUE/FALSE */
-int JS_PreventExtensions(JSContext *ctx, JSValueConst obj)
+/* return -1 if exception (Proxy object only) or true/false */
+int JS_PreventExtensions(JSContext *ctx, JSValue obj)
{
JSObject *p;
if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(obj);
if (unlikely(p->class_id == JS_CLASS_PROXY))
return js_proxy_preventExtensions(ctx, obj);
- p->extensible = FALSE;
- return TRUE;
+ p->extensible = false;
+ return true;
}
-/* return -1 if exception otherwise TRUE or FALSE */
-int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop)
+/* return -1 if exception otherwise true or false */
+int JS_HasProperty(JSContext *ctx, JSValue obj, JSAtom prop)
{
JSObject *p;
int ret;
JSValue obj1;
if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(obj);
for(;;) {
if (p->is_exotic) {
const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
if (em && em->has_property) {
/* has_property can free the prototype */
- obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
+ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p));
ret = em->has_property(ctx, obj1, prop);
JS_FreeValue(ctx, obj1);
return ret;
}
}
/* JS_GetOwnPropertyInternal can free the prototype */
- JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
+ js_dup(JS_MKPTR(JS_TAG_OBJECT, p));
ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop);
JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
if (ret != 0)
return ret;
- if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
+ if (is_typed_array(p->class_id)) {
ret = JS_AtomIsNumericIndex(ctx, prop);
if (ret != 0) {
if (ret < 0)
return -1;
- return FALSE;
+ return false;
}
}
p = p->shape->proto;
if (!p)
break;
}
- return FALSE;
+ return false;
}
/* val must be a symbol */
@@ -7946,7 +8190,7 @@ static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val)
}
/* return JS_ATOM_NULL in case of exception */
-JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val)
+JSAtom JS_ValueToAtom(JSContext *ctx, JSValue val)
{
JSAtom atom;
uint32_t tag;
@@ -7972,120 +8216,154 @@ JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val)
return atom;
}
-static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
+static bool js_get_fast_array_element(JSContext *ctx, JSObject *p,
+ uint32_t idx, JSValue *pval)
+{
+ switch(p->class_id) {
+ case JS_CLASS_ARRAY:
+ case JS_CLASS_ARGUMENTS:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = js_dup(p->u.array.u.values[idx]);
+ return true;
+ case JS_CLASS_INT8_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = js_int32(p->u.array.u.int8_ptr[idx]);
+ return true;
+ case JS_CLASS_UINT8C_ARRAY:
+ case JS_CLASS_UINT8_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = js_int32(p->u.array.u.uint8_ptr[idx]);
+ return true;
+ case JS_CLASS_INT16_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = js_int32(p->u.array.u.int16_ptr[idx]);
+ return true;
+ case JS_CLASS_UINT16_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = js_int32(p->u.array.u.uint16_ptr[idx]);
+ return true;
+ case JS_CLASS_INT32_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = js_int32(p->u.array.u.int32_ptr[idx]);
+ return true;
+ case JS_CLASS_UINT32_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = js_uint32(p->u.array.u.uint32_ptr[idx]);
+ return true;
+ case JS_CLASS_BIG_INT64_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]);
+ return true;
+ case JS_CLASS_BIG_UINT64_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]);
+ return true;
+ case JS_CLASS_FLOAT16_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = js_float64(fromfp16(p->u.array.u.fp16_ptr[idx]));
+ return true;
+ case JS_CLASS_FLOAT32_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = js_float64(p->u.array.u.float_ptr[idx]);
+ return true;
+ case JS_CLASS_FLOAT64_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) return false;
+ *pval = js_float64(p->u.array.u.double_ptr[idx]);
+ return true;
+ default:
+ return false;
+ }
+}
+
+static JSValue JS_GetPropertyValue(JSContext *ctx, JSValue this_obj,
JSValue prop)
{
JSAtom atom;
JSValue ret;
+ uint32_t tag;
- if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT &&
- JS_VALUE_GET_TAG(prop) == JS_TAG_INT)) {
- JSObject *p;
- uint32_t idx;
- /* fast path for array access */
- p = JS_VALUE_GET_OBJ(this_obj);
- idx = JS_VALUE_GET_INT(prop);
- switch(p->class_id) {
- case JS_CLASS_ARRAY:
- case JS_CLASS_ARGUMENTS:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return JS_DupValue(ctx, p->u.array.u.values[idx]);
- case JS_CLASS_INT8_ARRAY:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return JS_NewInt32(ctx, p->u.array.u.int8_ptr[idx]);
- case JS_CLASS_UINT8C_ARRAY:
- case JS_CLASS_UINT8_ARRAY:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return JS_NewInt32(ctx, p->u.array.u.uint8_ptr[idx]);
- case JS_CLASS_INT16_ARRAY:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return JS_NewInt32(ctx, p->u.array.u.int16_ptr[idx]);
- case JS_CLASS_UINT16_ARRAY:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return JS_NewInt32(ctx, p->u.array.u.uint16_ptr[idx]);
- case JS_CLASS_INT32_ARRAY:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return JS_NewInt32(ctx, p->u.array.u.int32_ptr[idx]);
- case JS_CLASS_UINT32_ARRAY:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return JS_NewUint32(ctx, p->u.array.u.uint32_ptr[idx]);
- case JS_CLASS_BIG_INT64_ARRAY:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]);
- case JS_CLASS_BIG_UINT64_ARRAY:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]);
- case JS_CLASS_FLOAT32_ARRAY:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return __JS_NewFloat64(ctx, p->u.array.u.float_ptr[idx]);
- case JS_CLASS_FLOAT64_ARRAY:
- if (unlikely(idx >= p->u.array.count)) goto slow_path;
- return __JS_NewFloat64(ctx, p->u.array.u.double_ptr[idx]);
- default:
- goto slow_path;
+ tag = JS_VALUE_GET_TAG(this_obj);
+ if (likely(tag == JS_TAG_OBJECT)) {
+ if (JS_VALUE_GET_TAG(prop) == JS_TAG_INT) {
+ JSObject *p = JS_VALUE_GET_OBJ(this_obj);
+ uint32_t idx = JS_VALUE_GET_INT(prop);
+ JSValue val;
+ /* fast path for array and typed array access */
+ if (js_get_fast_array_element(ctx, p, idx, &val))
+ return val;
}
} else {
- slow_path:
- atom = JS_ValueToAtom(ctx, prop);
- JS_FreeValue(ctx, prop);
- if (unlikely(atom == JS_ATOM_NULL))
- return JS_EXCEPTION;
- ret = JS_GetProperty(ctx, this_obj, atom);
- JS_FreeAtom(ctx, atom);
- return ret;
+ switch(tag) {
+ case JS_TAG_NULL:
+ JS_FreeValue(ctx, prop);
+ return JS_ThrowTypeError(ctx, "cannot read property of null");
+ case JS_TAG_UNDEFINED:
+ JS_FreeValue(ctx, prop);
+ return JS_ThrowTypeError(ctx, "cannot read property of undefined");
+ }
}
+ atom = JS_ValueToAtom(ctx, prop);
+ JS_FreeValue(ctx, prop);
+ if (unlikely(atom == JS_ATOM_NULL))
+ return JS_EXCEPTION;
+ ret = JS_GetProperty(ctx, this_obj, atom);
+ JS_FreeAtom(ctx, atom);
+ return ret;
}
-JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
+JSValue JS_GetPropertyUint32(JSContext *ctx, JSValue this_obj,
uint32_t idx)
{
- return JS_GetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx));
+ return JS_GetPropertyInt64(ctx, this_obj, idx);
}
/* Check if an object has a generalized numeric property. Return value:
- -1 for exception,
- TRUE if property exists, stored into *pval,
- FALSE if proprty does not exist.
+ -1 for exception, *pval set to JS_EXCEPTION
+ true if property exists, stored into *pval,
+ false if property does not exist. *pval set to JS_UNDEFINED.
*/
-static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, JSValue *pval)
+static int JS_TryGetPropertyInt64(JSContext *ctx, JSValue obj, int64_t idx, JSValue *pval)
{
- JSValue val = JS_UNDEFINED;
+ JSValue val;
JSAtom prop;
int present;
- if (likely((uint64_t)idx <= JS_ATOM_MAX_INT)) {
- /* fast path */
- present = JS_HasProperty(ctx, obj, __JS_AtomFromUInt32(idx));
+ if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT &&
+ (uint64_t)idx <= INT32_MAX)) {
+ /* fast path for array and typed array access */
+ JSObject *p = JS_VALUE_GET_OBJ(obj);
+ if (js_get_fast_array_element(ctx, p, idx, pval))
+ return true;
+ }
+ val = JS_EXCEPTION;
+ present = -1;
+ prop = JS_NewAtomInt64(ctx, idx);
+ if (likely(prop != JS_ATOM_NULL)) {
+ present = JS_HasProperty(ctx, obj, prop);
if (present > 0) {
- val = JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx));
+ val = JS_GetProperty(ctx, obj, prop);
if (unlikely(JS_IsException(val)))
present = -1;
+ } else if (present == false) {
+ val = JS_UNDEFINED;
}
- } else {
- prop = JS_NewAtomInt64(ctx, idx);
- present = -1;
- if (likely(prop != JS_ATOM_NULL)) {
- present = JS_HasProperty(ctx, obj, prop);
- if (present > 0) {
- val = JS_GetProperty(ctx, obj, prop);
- if (unlikely(JS_IsException(val)))
- present = -1;
- }
- JS_FreeAtom(ctx, prop);
- }
+ JS_FreeAtom(ctx, prop);
}
*pval = val;
return present;
}
-static JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx)
+JSValue JS_GetPropertyInt64(JSContext *ctx, JSValue obj, int64_t idx)
{
JSAtom prop;
JSValue val;
- if ((uint64_t)idx <= INT32_MAX) {
- /* fast path for fast arrays */
- return JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx));
+ if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT &&
+ (uint64_t)idx <= INT32_MAX)) {
+ /* fast path for array and typed array access */
+ JSObject *p = JS_VALUE_GET_OBJ(obj);
+ if (js_get_fast_array_element(ctx, p, idx, &val))
+ return val;
}
prop = JS_NewAtomInt64(ctx, idx);
if (prop == JS_ATOM_NULL)
@@ -8096,7 +8374,8 @@ static JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx
return val;
}
-JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,
+/* `prop` may be pure ASCII or UTF-8 encoded */
+JSValue JS_GetPropertyStr(JSContext *ctx, JSValue this_obj,
const char *prop)
{
JSAtom atom;
@@ -8138,7 +8417,7 @@ static JSProperty *add_property(JSContext *ctx,
if (!new_sh)
return NULL;
/* hash the cloned shape */
- new_sh->is_hashed = TRUE;
+ new_sh->is_hashed = true;
js_shape_hash_link(ctx->rt, new_sh);
js_free_shape(ctx->rt, p->shape);
p->shape = new_sh;
@@ -8206,7 +8485,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom)
if (likely(pr->atom == atom)) {
/* found ! */
if (!(pr->flags & JS_PROP_CONFIGURABLE))
- return FALSE;
+ return false;
/* realloc the shape if needed */
if (lpr)
lpr_idx = lpr - get_shape_prop(sh);
@@ -8235,7 +8514,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom)
sh->deleted_prop_count >= ((unsigned)sh->prop_count / 2)) {
compact_properties(ctx, p);
}
- return TRUE;
+ return true;
}
lpr = pr;
h = pr->hash_next;
@@ -8252,13 +8531,13 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom)
if (idx == p->u.array.count - 1) {
JS_FreeValue(ctx, p->u.array.u.values[idx]);
p->u.array.count = idx;
- return TRUE;
+ return true;
}
if (convert_fast_array_to_array(ctx, p))
return -1;
goto redo;
} else {
- return FALSE;
+ return false;
}
}
} else {
@@ -8269,23 +8548,23 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom)
}
}
/* not found */
- return TRUE;
+ return true;
}
static int call_setter(JSContext *ctx, JSObject *setter,
- JSValueConst this_obj, JSValue val, int flags)
+ JSValue this_obj, JSValue val, int flags)
{
JSValue ret, func;
if (likely(setter)) {
func = JS_MKPTR(JS_TAG_OBJECT, setter);
/* Note: the field could be removed in the setter */
- func = JS_DupValue(ctx, func);
- ret = JS_CallFree(ctx, func, this_obj, 1, (JSValueConst *)&val);
+ func = js_dup(func);
+ ret = JS_CallFree(ctx, func, this_obj, 1, &val);
JS_FreeValue(ctx, val);
if (JS_IsException(ret))
return -1;
JS_FreeValue(ctx, ret);
- return TRUE;
+ return true;
} else {
JS_FreeValue(ctx, val);
if ((flags & JS_PROP_THROW) ||
@@ -8293,7 +8572,7 @@ static int call_setter(JSContext *ctx, JSObject *setter,
JS_ThrowTypeError(ctx, "no setter for property");
return -1;
}
- return FALSE;
+ return false;
}
}
@@ -8305,7 +8584,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val,
int i, ret;
/* Note: this call can reallocate the properties of 'p' */
- ret = JS_ToArrayLengthFree(ctx, &len, val, FALSE);
+ ret = JS_ToArrayLengthFree(ctx, &len, val, false);
if (ret)
return -1;
/* JS_ToArrayLengthFree() must be done before the read-only test */
@@ -8320,7 +8599,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val,
}
p->u.array.count = len;
}
- p->prop[0].u.value = JS_NewUint32(ctx, len);
+ p->prop[0].u.value = js_uint32(len);
} else {
/* Note: length is always a uint32 because the object is an
array */
@@ -8380,12 +8659,12 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val,
} else {
cur_len = len;
}
- set_value(ctx, &p->prop[0].u.value, JS_NewUint32(ctx, cur_len));
+ set_value(ctx, &p->prop[0].u.value, js_uint32(cur_len));
if (unlikely(cur_len > len)) {
return JS_ThrowTypeErrorOrFalse(ctx, flags, "not configurable");
}
}
- return TRUE;
+ return true;
}
/* return -1 if exception */
@@ -8406,7 +8685,7 @@ static int expand_fast_array(JSContext *ctx, JSObject *p, uint32_t new_len)
}
/* Preconditions: 'p' must be of class JS_CLASS_ARRAY, p->fast_array =
- TRUE and p->extensible = TRUE */
+ true and p->extensible = true */
static int add_fast_array_element(JSContext *ctx, JSObject *p,
JSValue val, int flags)
{
@@ -8423,7 +8702,7 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p,
JS_FreeValue(ctx, val);
return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length);
}
- p->prop[0].u.value = JS_NewInt32(ctx, new_len);
+ p->prop[0].u.value = js_int32(new_len);
}
}
if (unlikely(new_len > p->u.array.u1.size)) {
@@ -8434,31 +8713,7 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p,
}
p->u.array.u.values[new_len - 1] = val;
p->u.array.count = new_len;
- return TRUE;
-}
-
-/* Allocate a new fast array. Its 'length' property is set to zero. It
- maximum size is 2^31-1 elements. For convenience, 'len' is a 64 bit
- integer. WARNING: the content of the array is not initialized. */
-static JSValue js_allocate_fast_array(JSContext *ctx, int64_t len)
-{
- JSValue arr;
- JSObject *p;
-
- if (len > INT32_MAX)
- return JS_ThrowRangeError(ctx, "invalid array length");
- arr = JS_NewArray(ctx);
- if (JS_IsException(arr))
- return arr;
- if (len > 0) {
- p = JS_VALUE_GET_OBJ(arr);
- if (expand_fast_array(ctx, p, len) < 0) {
- JS_FreeValue(ctx, arr);
- return JS_EXCEPTION;
- }
- p->u.array.count = len;
- }
- return arr;
+ return true;
}
static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc)
@@ -8468,63 +8723,50 @@ static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc)
JS_FreeValue(ctx, desc->value);
}
-/* return -1 in case of exception or TRUE or FALSE. Warning: 'val' is
+/* return -1 in case of exception or true or false. Warning: 'val' is
freed by the function. 'flags' is a bitmask of JS_PROP_NO_ADD,
JS_PROP_THROW or JS_PROP_THROW_STRICT. If JS_PROP_NO_ADD is set,
- the new property is not added and an error is raised. 'this_obj' is
- the receiver. If obj != this_obj, then obj must be an object
- (Reflect.set case). */
-int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
- JSAtom prop, JSValue val, JSValueConst this_obj, int flags)
+ the new property is not added and an error is raised.
+ 'obj' must be an object when obj != this_obj.
+ */
+static int JS_SetPropertyInternal2(JSContext *ctx, JSValue obj, JSAtom prop,
+ JSValue val, JSValue this_obj, int flags)
{
JSObject *p, *p1;
JSShapeProperty *prs;
JSProperty *pr;
- uint32_t tag;
JSPropertyDescriptor desc;
int ret;
-#if 0
- printf("JS_SetPropertyInternal: "); print_atom(ctx, prop); printf("\n");
-#endif
- tag = JS_VALUE_GET_TAG(this_obj);
- if (unlikely(tag != JS_TAG_OBJECT)) {
- if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
- p = NULL;
- p1 = JS_VALUE_GET_OBJ(obj);
- goto prototype_lookup;
- } else {
- switch(tag) {
- case JS_TAG_NULL:
- JS_FreeValue(ctx, val);
- JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop);
- return -1;
- case JS_TAG_UNDEFINED:
- JS_FreeValue(ctx, val);
- JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop);
- return -1;
- default:
- /* even on a primitive type we can have setters on the prototype */
- p = NULL;
- p1 = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, obj));
- goto prototype_lookup;
- }
- }
- } else {
+
+ switch(JS_VALUE_GET_TAG(this_obj)) {
+ case JS_TAG_NULL:
+ JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop);
+ goto fail;
+ case JS_TAG_UNDEFINED:
+ JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop);
+ goto fail;
+ case JS_TAG_OBJECT:
p = JS_VALUE_GET_OBJ(this_obj);
p1 = JS_VALUE_GET_OBJ(obj);
- if (unlikely(p != p1))
- goto retry2;
+ if (p == p1)
+ break;
+ goto retry2;
+ default:
+ if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
+ obj = JS_GetPrototypePrimitive(ctx, obj);
+ p = NULL;
+ p1 = JS_VALUE_GET_OBJ(obj);
+ goto prototype_lookup;
}
- /* fast path if obj == this_obj */
- retry:
+retry:
prs = find_own_property(&pr, p1, prop);
if (prs) {
if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE |
JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) {
/* fast case */
set_value(ctx, &pr->u.value, val);
- return TRUE;
+ return true;
} else if (prs->flags & JS_PROP_LENGTH) {
assert(p->class_id == JS_CLASS_ARRAY);
assert(prop == JS_ATOM_length);
@@ -8538,13 +8780,11 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
if (p->class_id == JS_CLASS_MODULE_NS)
goto read_only_prop;
set_value(ctx, pr->u.var_ref->pvalue, val);
- return TRUE;
+ return true;
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
/* Instantiate property and retry (potentially useless) */
- if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) {
- JS_FreeValue(ctx, val);
- return -1;
- }
+ if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
+ goto fail;
goto retry;
} else {
goto read_only_prop;
@@ -8558,23 +8798,19 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
uint32_t idx = __JS_AtomToUInt32(prop);
if (idx < p1->u.array.count) {
if (unlikely(p == p1))
- return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags);
+ return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), val, flags);
else
break;
- } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p1->class_id <= JS_CLASS_FLOAT64_ARRAY) {
+ } else if (is_typed_array(p1->class_id)) {
goto typed_array_oob;
}
- } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p1->class_id <= JS_CLASS_FLOAT64_ARRAY) {
+ } else if (is_typed_array(p1->class_id)) {
ret = JS_AtomIsNumericIndex(ctx, prop);
if (ret != 0) {
- if (ret < 0) {
- JS_FreeValue(ctx, val);
- return -1;
- }
+ if (ret < 0)
+ goto fail;
typed_array_oob:
- /* must convert the argument even if out of bound access */
+ // per spec: evaluate value for side effects
if (p1->class_id == JS_CLASS_BIG_INT64_ARRAY ||
p1->class_id == JS_CLASS_BIG_UINT64_ARRAY) {
int64_t v;
@@ -8586,7 +8822,7 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
if (JS_IsException(val))
return -1;
}
- return TRUE;
+ return true;
}
}
} else {
@@ -8595,7 +8831,7 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
JSValue obj1;
if (em->set_property) {
/* set_property can free the prototype */
- obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));
+ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1));
ret = em->set_property(ctx, obj1, prop,
val, this_obj, flags);
JS_FreeValue(ctx, obj1);
@@ -8604,14 +8840,12 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
}
if (em->get_own_property) {
/* get_own_property can free the prototype */
- obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));
+ obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1));
ret = em->get_own_property(ctx, &desc,
obj1, prop);
JS_FreeValue(ctx, obj1);
- if (ret < 0) {
- JS_FreeValue(ctx, val);
- return ret;
- }
+ if (ret < 0)
+ goto fail;
if (ret) {
if (desc.flags & JS_PROP_GETSET) {
JSObject *setter;
@@ -8664,22 +8898,21 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
}
if (unlikely(flags & JS_PROP_NO_ADD)) {
- JS_FreeValue(ctx, val);
JS_ThrowReferenceErrorNotDefined(ctx, prop);
- return -1;
+ goto fail;
}
if (unlikely(!p)) {
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "not an object");
+ ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "not an object");
+ goto done;
}
if (unlikely(!p->extensible)) {
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible");
+ ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible");
+ goto done;
}
- if (likely(p == JS_VALUE_GET_OBJ(obj))) {
+ if (p == JS_VALUE_GET_OBJ(obj)) {
if (p->is_exotic) {
if (p->class_id == JS_CLASS_ARRAY && p->fast_array &&
__JS_AtomIsTaggedInt(prop)) {
@@ -8687,65 +8920,73 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
if (idx == p->u.array.count) {
/* fast case */
return add_fast_array_element(ctx, p, val, flags);
- } else {
- goto generic_create_prop;
}
- } else {
- goto generic_create_prop;
}
+ goto generic_create_prop;
} else {
pr = add_property(ctx, p, prop, JS_PROP_C_W_E);
- if (unlikely(!pr)) {
- JS_FreeValue(ctx, val);
- return -1;
- }
+ if (!pr)
+ goto fail;
pr->u.value = val;
- return TRUE;
+ return true;
}
- } else {
- /* generic case: modify the property in this_obj if it already exists */
- ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);
- if (ret < 0) {
- JS_FreeValue(ctx, val);
- return ret;
- }
- if (ret) {
- if (desc.flags & JS_PROP_GETSET) {
- JS_FreeValue(ctx, desc.getter);
- JS_FreeValue(ctx, desc.setter);
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden");
- } else {
- JS_FreeValue(ctx, desc.value);
- if (!(desc.flags & JS_PROP_WRITABLE) ||
- p->class_id == JS_CLASS_MODULE_NS) {
- read_only_prop:
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);
- }
- }
- ret = JS_DefineProperty(ctx, this_obj, prop, val,
- JS_UNDEFINED, JS_UNDEFINED,
- JS_PROP_HAS_VALUE);
- JS_FreeValue(ctx, val);
- return ret;
- } else {
- generic_create_prop:
- ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED,
- flags |
- JS_PROP_HAS_VALUE |
- JS_PROP_HAS_ENUMERABLE |
- JS_PROP_HAS_WRITABLE |
- JS_PROP_HAS_CONFIGURABLE |
- JS_PROP_C_W_E);
- JS_FreeValue(ctx, val);
- return ret;
+ }
+
+ // TODO(bnoordhuis) return JSProperty slot and update in place
+ // when plain property (not is_exotic/setter/etc.) to avoid
+ // calling find_own_property() thrice?
+ ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);
+ if (ret < 0)
+ goto fail;
+
+ if (ret) {
+ JS_FreeValue(ctx, desc.value);
+ if (desc.flags & JS_PROP_GETSET) {
+ JS_FreeValue(ctx, desc.getter);
+ JS_FreeValue(ctx, desc.setter);
+ ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden");
+ goto done;
+ } else if (!(desc.flags & JS_PROP_WRITABLE) ||
+ p->class_id == JS_CLASS_MODULE_NS) {
+ read_only_prop:
+ ret = JS_ThrowTypeErrorReadOnly(ctx, flags, prop);
+ goto done;
}
+ ret = JS_DefineProperty(ctx, this_obj, prop, val,
+ JS_UNDEFINED, JS_UNDEFINED,
+ JS_PROP_HAS_VALUE);
+ } else {
+ generic_create_prop:
+ ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED,
+ flags |
+ JS_PROP_HAS_VALUE |
+ JS_PROP_HAS_ENUMERABLE |
+ JS_PROP_HAS_WRITABLE |
+ JS_PROP_HAS_CONFIGURABLE |
+ JS_PROP_C_W_E);
}
+
+done:
+ JS_FreeValue(ctx, val);
+ return ret;
+fail:
+ JS_FreeValue(ctx, val);
+ return -1;
+}
+
+static int JS_SetPropertyInternal(JSContext *ctx, JSValue obj, JSAtom prop,
+ JSValue val, int flags)
+{
+ return JS_SetPropertyInternal2(ctx, obj, prop, val, obj, flags);
+}
+
+int JS_SetProperty(JSContext *ctx, JSValue this_obj, JSAtom prop, JSValue val)
+{
+ return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW);
}
/* flags can be JS_PROP_THROW or JS_PROP_THROW_STRICT */
-static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
+static int JS_SetPropertyValue(JSContext *ctx, JSValue this_obj,
JSValue prop, JSValue val, int flags)
{
if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT &&
@@ -8795,7 +9036,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
break;
case JS_CLASS_UINT8C_ARRAY:
if (JS_ToUint8ClampFree(ctx, &v, val))
- return -1;
+ goto ta_cvt_fail;
/* Note: the conversion can detach the typed array, so the
array bound check must be done after */
if (unlikely(idx >= (uint32_t)p->u.array.count))
@@ -8805,7 +9046,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
case JS_CLASS_INT8_ARRAY:
case JS_CLASS_UINT8_ARRAY:
if (JS_ToInt32Free(ctx, &v, val))
- return -1;
+ goto ta_cvt_fail;
if (unlikely(idx >= (uint32_t)p->u.array.count))
goto ta_out_of_bound;
p->u.array.u.uint8_ptr[idx] = v;
@@ -8813,7 +9054,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
case JS_CLASS_INT16_ARRAY:
case JS_CLASS_UINT16_ARRAY:
if (JS_ToInt32Free(ctx, &v, val))
- return -1;
+ goto ta_cvt_fail;
if (unlikely(idx >= (uint32_t)p->u.array.count))
goto ta_out_of_bound;
p->u.array.u.uint16_ptr[idx] = v;
@@ -8821,7 +9062,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
case JS_CLASS_INT32_ARRAY:
case JS_CLASS_UINT32_ARRAY:
if (JS_ToInt32Free(ctx, &v, val))
- return -1;
+ goto ta_cvt_fail;
if (unlikely(idx >= (uint32_t)p->u.array.count))
goto ta_out_of_bound;
p->u.array.u.uint32_ptr[idx] = v;
@@ -8832,32 +9073,48 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
{
int64_t v;
if (JS_ToBigInt64Free(ctx, &v, val))
- return -1;
+ goto ta_cvt_fail;
if (unlikely(idx >= (uint32_t)p->u.array.count))
goto ta_out_of_bound;
p->u.array.u.uint64_ptr[idx] = v;
}
break;
+ case JS_CLASS_FLOAT16_ARRAY:
+ if (JS_ToFloat64Free(ctx, &d, val))
+ goto ta_cvt_fail;
+ if (unlikely(idx >= (uint32_t)p->u.array.count))
+ goto ta_out_of_bound;
+ p->u.array.u.fp16_ptr[idx] = tofp16(d);
+ break;
case JS_CLASS_FLOAT32_ARRAY:
if (JS_ToFloat64Free(ctx, &d, val))
- return -1;
+ goto ta_cvt_fail;
if (unlikely(idx >= (uint32_t)p->u.array.count))
goto ta_out_of_bound;
p->u.array.u.float_ptr[idx] = d;
break;
case JS_CLASS_FLOAT64_ARRAY:
- if (JS_ToFloat64Free(ctx, &d, val))
+ if (JS_ToFloat64Free(ctx, &d, val)) {
+ ta_cvt_fail:
+ if (flags & JS_PROP_REFLECT_DEFINE_PROPERTY) {
+ JS_FreeValue(ctx, JS_GetException(ctx));
+ return false;
+ }
return -1;
+ }
if (unlikely(idx >= (uint32_t)p->u.array.count)) {
ta_out_of_bound:
- return TRUE;
+ if (typed_array_is_oob(p))
+ if (flags & JS_PROP_DEFINE_PROPERTY)
+ return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");
+ return true; // per spec: no OOB exception
}
p->u.array.u.double_ptr[idx] = d;
break;
default:
goto slow_path;
}
- return TRUE;
+ return true;
} else {
JSAtom atom;
int ret;
@@ -8868,20 +9125,20 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
JS_FreeValue(ctx, val);
return -1;
}
- ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, flags);
+ ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, flags);
JS_FreeAtom(ctx, atom);
return ret;
}
}
-int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
+int JS_SetPropertyUint32(JSContext *ctx, JSValue this_obj,
uint32_t idx, JSValue val)
{
- return JS_SetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx), val,
+ return JS_SetPropertyValue(ctx, this_obj, js_uint32(idx), val,
JS_PROP_THROW);
}
-int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj,
+int JS_SetPropertyInt64(JSContext *ctx, JSValue this_obj,
int64_t idx, JSValue val)
{
JSAtom prop;
@@ -8889,7 +9146,7 @@ int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj,
if ((uint64_t)idx <= INT32_MAX) {
/* fast path for fast arrays */
- return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val,
+ return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), val,
JS_PROP_THROW);
}
prop = JS_NewAtomInt64(ctx, idx);
@@ -8902,13 +9159,14 @@ int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj,
return res;
}
-int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,
+/* `prop` may be pure ASCII or UTF-8 encoded */
+int JS_SetPropertyStr(JSContext *ctx, JSValue this_obj,
const char *prop, JSValue val)
{
JSAtom atom;
int ret;
atom = JS_NewAtom(ctx, prop);
- ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, JS_PROP_THROW);
+ ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, JS_PROP_THROW);
JS_FreeAtom(ctx, atom);
return ret;
}
@@ -8925,8 +9183,8 @@ static int get_prop_flags(int flags, int def_flags)
}
static int JS_CreateProperty(JSContext *ctx, JSObject *p,
- JSAtom prop, JSValueConst val,
- JSValueConst getter, JSValueConst setter,
+ JSAtom prop, JSValue val,
+ JSValue getter, JSValue setter,
int flags)
{
JSProperty *pr;
@@ -8949,7 +9207,7 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p,
if (prop_flags != JS_PROP_C_W_E)
goto convert_to_array;
return add_fast_array_element(ctx, p,
- JS_DupValue(ctx, val), flags);
+ js_dup(val), flags);
} else {
goto convert_to_array;
}
@@ -8974,11 +9232,10 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p,
/* XXX: should update the length after defining
the property */
len = idx + 1;
- set_value(ctx, &plen->u.value, JS_NewUint32(ctx, len));
+ set_value(ctx, &plen->u.value, js_uint32(len));
}
}
- } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
+ } else if (is_typed_array(p->class_id)) {
ret = JS_AtomIsNumericIndex(ctx, prop);
if (ret != 0) {
if (ret < 0)
@@ -9019,36 +9276,36 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p,
pr->u.getset.getter = NULL;
if ((flags & JS_PROP_HAS_GET) && JS_IsFunction(ctx, getter)) {
pr->u.getset.getter =
- JS_VALUE_GET_OBJ(JS_DupValue(ctx, getter));
+ JS_VALUE_GET_OBJ(js_dup(getter));
}
pr->u.getset.setter = NULL;
if ((flags & JS_PROP_HAS_SET) && JS_IsFunction(ctx, setter)) {
pr->u.getset.setter =
- JS_VALUE_GET_OBJ(JS_DupValue(ctx, setter));
+ JS_VALUE_GET_OBJ(js_dup(setter));
}
} else {
if (flags & JS_PROP_HAS_VALUE) {
- pr->u.value = JS_DupValue(ctx, val);
+ pr->u.value = js_dup(val);
} else {
pr->u.value = JS_UNDEFINED;
}
}
- return TRUE;
+ return true;
}
-/* return FALSE if not OK */
-static BOOL check_define_prop_flags(int prop_flags, int flags)
+/* return false if not OK */
+static bool check_define_prop_flags(int prop_flags, int flags)
{
- BOOL has_accessor, is_getset;
+ bool has_accessor, is_getset;
if (!(prop_flags & JS_PROP_CONFIGURABLE)) {
if ((flags & (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) ==
(JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) {
- return FALSE;
+ return false;
}
if ((flags & JS_PROP_HAS_ENUMERABLE) &&
(flags & JS_PROP_ENUMERABLE) != (prop_flags & JS_PROP_ENUMERABLE))
- return FALSE;
+ return false;
}
if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE |
JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {
@@ -9056,16 +9313,16 @@ static BOOL check_define_prop_flags(int prop_flags, int flags)
has_accessor = ((flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) != 0);
is_getset = ((prop_flags & JS_PROP_TMASK) == JS_PROP_GETSET);
if (has_accessor != is_getset)
- return FALSE;
+ return false;
if (!has_accessor && !is_getset && !(prop_flags & JS_PROP_WRITABLE)) {
/* not writable: cannot set the writable bit */
if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) ==
(JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE))
- return FALSE;
+ return false;
}
}
}
- return TRUE;
+ return true;
}
/* ensure that the shape can be safely modified */
@@ -9090,7 +9347,7 @@ static int js_shape_prepare_update(JSContext *ctx, JSObject *p,
*pprs = get_shape_prop(sh) + idx;
} else {
js_shape_hash_unlink(ctx->rt, sh);
- sh->is_hashed = FALSE;
+ sh->is_hashed = false;
}
}
return 0;
@@ -9112,14 +9369,14 @@ static int js_update_property_flags(JSContext *ctx, JSObject *p,
JS_PROP_HAS_GET, JS_PROP_HAS_SET, JS_PROP_HAS_VALUE,
JS_PROP_HAS_CONFIGURABLE, JS_PROP_HAS_WRITABLE, JS_PROP_HAS_ENUMERABLE,
JS_PROP_THROW, JS_PROP_NO_EXOTIC.
- If JS_PROP_THROW is set, return an exception instead of FALSE.
+ If JS_PROP_THROW is set, return an exception instead of false.
if JS_PROP_NO_EXOTIC is set, do not call the exotic
define_own_property callback.
- return -1 (exception), FALSE or TRUE.
+ return -1 (exception), false or true.
*/
-int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop, JSValueConst val,
- JSValueConst getter, JSValueConst setter, int flags)
+int JS_DefineProperty(JSContext *ctx, JSValue this_obj,
+ JSAtom prop, JSValue val,
+ JSValue getter, JSValue setter, int flags)
{
JSObject *p;
JSShapeProperty *prs;
@@ -9139,11 +9396,11 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
if ((prs->flags & JS_PROP_LENGTH) && (flags & JS_PROP_HAS_VALUE)) {
uint32_t array_length;
if (JS_ToArrayLengthFree(ctx, &array_length,
- JS_DupValue(ctx, val), FALSE)) {
+ js_dup(val), false)) {
return -1;
}
/* this code relies on the fact that Uint32 are never allocated */
- val = JS_NewUint32(ctx, array_length);
+ val = js_uint32(array_length);
/* prs may have been modified */
prs = find_own_property(&pr, p, prop);
assert(prs != NULL);
@@ -9207,14 +9464,14 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
if (pr->u.getset.getter)
JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));
if (new_getter)
- JS_DupValue(ctx, getter);
+ js_dup(getter);
pr->u.getset.getter = new_getter;
}
if (flags & JS_PROP_HAS_SET) {
if (pr->u.getset.setter)
JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));
if (new_setter)
- JS_DupValue(ctx, setter);
+ js_dup(setter);
pr->u.getset.setter = new_setter;
}
} else {
@@ -9236,7 +9493,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
if (!js_same_value(ctx, val, pr->u.value)) {
goto not_configurable;
} else {
- return TRUE;
+ return true;
}
}
}
@@ -9248,22 +9505,18 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
spaces. */
if (!js_same_value(ctx, val, *pr->u.var_ref->pvalue))
goto not_configurable;
- } else {
- /* update the reference */
- set_value(ctx, pr->u.var_ref->pvalue,
- JS_DupValue(ctx, val));
}
+ /* update the reference */
+ set_value(ctx, pr->u.var_ref->pvalue,
+ js_dup(val));
}
/* if writable is set to false, no longer a
reference (for mapped arguments) */
if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) {
JSValue val1;
- if (p->class_id == JS_CLASS_MODULE_NS) {
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "module namespace properties have writable = false");
- }
if (js_shape_prepare_update(ctx, p, &prs))
return -1;
- val1 = JS_DupValue(ctx, *pr->u.var_ref->pvalue);
+ val1 = js_dup(*pr->u.var_ref->pvalue);
free_var_ref(ctx->rt, pr->u.var_ref);
pr->u.value = val1;
prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE);
@@ -9272,10 +9525,10 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
if (flags & JS_PROP_HAS_VALUE) {
/* Note: no JS code is executable because
'val' is guaranted to be a Uint32 */
- res = set_array_length(ctx, p, JS_DupValue(ctx, val),
+ res = set_array_length(ctx, p, js_dup(val),
flags);
} else {
- res = TRUE;
+ res = true;
}
/* still need to reset the writable flag if
needed. The JS_PROP_LENGTH is kept because the
@@ -9292,7 +9545,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
} else {
if (flags & JS_PROP_HAS_VALUE) {
JS_FreeValue(ctx, pr->u.value);
- pr->u.value = JS_DupValue(ctx, val);
+ pr->u.value = js_dup(val);
}
if (flags & JS_PROP_HAS_WRITABLE) {
if (js_update_property_flags(ctx, p, &prs,
@@ -9311,7 +9564,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
if (js_update_property_flags(ctx, p, &prs,
(prs->flags & ~mask) | (flags & mask)))
return -1;
- return TRUE;
+ return true;
}
/* handle modification of fast array elements */
@@ -9333,13 +9586,12 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
goto redo_prop_update;
}
if (flags & JS_PROP_HAS_VALUE) {
- set_value(ctx, &p->u.array.u.values[idx], JS_DupValue(ctx, val));
+ set_value(ctx, &p->u.array.u.values[idx], js_dup(val));
}
- return TRUE;
+ return true;
}
}
- } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
+ } else if (is_typed_array(p->class_id)) {
JSValue num;
int ret;
@@ -9369,7 +9621,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
}
idx = __JS_AtomToUInt32(prop);
/* if the typed array is detached, p->u.array.count = 0 */
- if (idx >= p->u.array.count) {
+ if (idx >= typed_array_get_length(ctx, p)) {
typed_array_oob:
return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound index in typed array");
}
@@ -9379,9 +9631,9 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
return JS_ThrowTypeErrorOrFalse(ctx, flags, "invalid descriptor flags");
}
if (flags & JS_PROP_HAS_VALUE) {
- return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), JS_DupValue(ctx, val), flags);
+ return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), js_dup(val), flags);
}
- return TRUE;
+ return true;
typed_array_done: ;
}
}
@@ -9389,7 +9641,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
return JS_CreateProperty(ctx, p, prop, val, getter, setter, flags);
}
-static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj,
+static int JS_DefineAutoInitProperty(JSContext *ctx, JSValue this_obj,
JSAtom prop, JSAutoInitIDEnum id,
void *opaque, int flags)
{
@@ -9397,14 +9649,14 @@ static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj,
JSProperty *pr;
if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT)
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(this_obj);
if (find_own_property(&pr, p, prop)) {
/* property already exists */
abort();
- return FALSE;
+ return false;
}
/* Specialized CreateProperty */
@@ -9416,11 +9668,11 @@ static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj,
assert(id <= 3);
pr->u.init.realm_and_id |= id;
pr->u.init.opaque = opaque;
- return TRUE;
+ return true;
}
/* shortcut to add or redefine a new property value */
-int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj,
+int JS_DefinePropertyValue(JSContext *ctx, JSValue this_obj,
JSAtom prop, JSValue val, int flags)
{
int ret;
@@ -9430,7 +9682,7 @@ int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj,
return ret;
}
-int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj,
+int JS_DefinePropertyValueValue(JSContext *ctx, JSValue this_obj,
JSValue prop, JSValue val, int flags)
{
JSAtom atom;
@@ -9446,21 +9698,22 @@ int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj,
return ret;
}
-int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj,
+int JS_DefinePropertyValueUint32(JSContext *ctx, JSValue this_obj,
uint32_t idx, JSValue val, int flags)
{
- return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewUint32(ctx, idx),
+ return JS_DefinePropertyValueValue(ctx, this_obj, js_uint32(idx),
val, flags);
}
-int JS_DefinePropertyValueInt64(JSContext *ctx, JSValueConst this_obj,
+int JS_DefinePropertyValueInt64(JSContext *ctx, JSValue this_obj,
int64_t idx, JSValue val, int flags)
{
- return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx),
+ return JS_DefinePropertyValueValue(ctx, this_obj, js_int64(idx),
val, flags);
}
-int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,
+/* `prop` may be pure ASCII or UTF-8 encoded */
+int JS_DefinePropertyValueStr(JSContext *ctx, JSValue this_obj,
const char *prop, JSValue val, int flags)
{
JSAtom atom;
@@ -9472,7 +9725,7 @@ int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,
}
/* shortcut to add getter & setter */
-int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj,
+int JS_DefinePropertyGetSet(JSContext *ctx, JSValue this_obj,
JSAtom prop, JSValue getter, JSValue setter,
int flags)
{
@@ -9485,36 +9738,36 @@ int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj,
return ret;
}
-static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValueConst this_obj,
+static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValue this_obj,
int64_t idx, JSValue val, int flags)
{
- return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx),
+ return JS_DefinePropertyValueValue(ctx, this_obj, js_int64(idx),
val, flags | JS_PROP_CONFIGURABLE |
JS_PROP_ENUMERABLE | JS_PROP_WRITABLE);
}
-/* return TRUE if 'obj' has a non empty 'name' string */
-static BOOL js_object_has_name(JSContext *ctx, JSValueConst obj)
+/* return true if 'obj' has a non empty 'name' string */
+static bool js_object_has_name(JSContext *ctx, JSValue obj)
{
JSProperty *pr;
JSShapeProperty *prs;
- JSValueConst val;
+ JSValue val;
JSString *p;
prs = find_own_property(&pr, JS_VALUE_GET_OBJ(obj), JS_ATOM_name);
if (!prs)
- return FALSE;
+ return false;
if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL)
- return TRUE;
+ return true;
val = pr->u.value;
if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING)
- return TRUE;
+ return true;
p = JS_VALUE_GET_STRING(val);
return (p->len != 0);
}
-static int JS_DefineObjectName(JSContext *ctx, JSValueConst obj,
+static int JS_DefineObjectName(JSContext *ctx, JSValue obj,
JSAtom name, int flags)
{
if (name != JS_ATOM_NULL
@@ -9526,8 +9779,8 @@ static int JS_DefineObjectName(JSContext *ctx, JSValueConst obj,
return 0;
}
-static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj,
- JSValueConst str, int flags)
+static int JS_DefineObjectNameComputed(JSContext *ctx, JSValue obj,
+ JSValue str, int flags)
{
if (JS_IsObject(obj) &&
!js_object_has_name(ctx, obj)) {
@@ -9632,7 +9885,7 @@ static int JS_DefineGlobalVar(JSContext *ctx, JSAtom prop, int def_flags)
/* 'def_flags' is 0 or JS_PROP_CONFIGURABLE. */
/* XXX: could support exotic global object. */
static int JS_DefineGlobalFunction(JSContext *ctx, JSAtom prop,
- JSValueConst func, int def_flags)
+ JSValue func, int def_flags)
{
JSObject *p;
@@ -9653,7 +9906,7 @@ static int JS_DefineGlobalFunction(JSContext *ctx, JSAtom prop,
}
static JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop,
- BOOL throw_ref_error)
+ bool throw_ref_error)
{
JSObject *p;
JSShapeProperty *prs;
@@ -9666,7 +9919,7 @@ static JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop,
/* XXX: should handle JS_PROP_TMASK properties */
if (unlikely(JS_IsUninitialized(pr->u.value)))
return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);
- return JS_DupValue(ctx, pr->u.value);
+ return js_dup(pr->u.value);
}
if (ctx->scopeLookup) {
struct LookupResult result = ctx->scopeLookup(ctx, prop);
@@ -9698,14 +9951,14 @@ static int JS_GetGlobalVarRef(JSContext *ctx, JSAtom prop, JSValue *sp)
if (unlikely(!(prs->flags & JS_PROP_WRITABLE))) {
return JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, prop);
}
- sp[0] = JS_DupValue(ctx, ctx->global_var_obj);
+ sp[0] = js_dup(ctx->global_var_obj);
} else {
int ret;
ret = JS_HasProperty(ctx, ctx->global_obj, prop);
if (ret < 0)
return -1;
if (ret) {
- sp[0] = JS_DupValue(ctx, ctx->global_obj);
+ sp[0] = js_dup(ctx->global_obj);
} else {
sp[0] = JS_UNDEFINED;
}
@@ -9725,7 +9978,7 @@ static int JS_CheckGlobalVar(JSContext *ctx, JSAtom prop)
p = JS_VALUE_GET_OBJ(ctx->global_var_obj);
prs = find_own_property1(p, prop);
if (prs) {
- ret = TRUE;
+ ret = true;
} else {
ret = JS_HasProperty(ctx, ctx->global_obj, prop);
if (ret < 0)
@@ -9773,17 +10026,17 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,
struct LookupResult result = ctx->scopeLookup(ctx, prop);
if (result.useResult) {
JS_FreeValue(ctx, result.value);
- return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, result.scope, flags);
+ return JS_SetPropertyInternal2(ctx, ctx->global_obj, prop, val, result.scope, flags);
}
}
- return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, ctx->global_obj, flags);
+ return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags);
}
-/* return -1, FALSE or TRUE. return FALSE if not configurable or
+/* return -1, false or true. return false if not configurable or
invalid object. return -1 in case of exception.
flags can be 0, JS_PROP_THROW or JS_PROP_THROW_STRICT */
-int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags)
+int JS_DeleteProperty(JSContext *ctx, JSValue obj, JSAtom prop, int flags)
{
JSValue obj1;
JSObject *p;
@@ -9795,17 +10048,17 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags)
p = JS_VALUE_GET_OBJ(obj1);
res = delete_property(ctx, p, prop);
JS_FreeValue(ctx, obj1);
- if (res != FALSE)
+ if (res != false)
return res;
if ((flags & JS_PROP_THROW) ||
((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {
JS_ThrowTypeError(ctx, "could not delete property");
return -1;
}
- return FALSE;
+ return false;
}
-int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int flags)
+int JS_DeletePropertyInt64(JSContext *ctx, JSValue obj, int64_t idx, int flags)
{
JSAtom prop;
int res;
@@ -9822,15 +10075,15 @@ int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int fl
return res;
}
-BOOL JS_IsFunction(JSContext *ctx, JSValueConst val)
+bool JS_IsFunction(JSContext *ctx, JSValue val)
{
JSObject *p;
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(val);
switch(p->class_id) {
case JS_CLASS_BYTECODE_FUNCTION:
- return TRUE;
+ return true;
case JS_CLASS_PROXY:
return p->u.proxy_data->is_func;
default:
@@ -9838,65 +10091,80 @@ BOOL JS_IsFunction(JSContext *ctx, JSValueConst val)
}
}
-BOOL JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int magic)
+bool JS_IsCFunction(JSContext *ctx, JSValue val, JSCFunction *func, int magic)
{
JSObject *p;
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(val);
if (p->class_id == JS_CLASS_C_FUNCTION)
return (p->u.cfunc.c_function.generic == func && p->u.cfunc.magic == magic);
else
- return FALSE;
+ return false;
}
-BOOL JS_IsConstructor(JSContext *ctx, JSValueConst val)
+bool JS_IsConstructor(JSContext *ctx, JSValue val)
{
JSObject *p;
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(val);
return p->is_constructor;
}
-BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, BOOL val)
+bool JS_SetConstructorBit(JSContext *ctx, JSValue func_obj, bool val)
{
JSObject *p;
if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(func_obj);
p->is_constructor = val;
- return TRUE;
+ return true;
}
-JS_BOOL JS_IsArrayBuffer(JSValueConst v)
+bool JS_IsRegExp(JSValue val)
{
- if (!JS_IsObject(v))
- return FALSE;
- JSObject *p = JS_VALUE_GET_OBJ(v);
- return p->class_id == JS_CLASS_ARRAY_BUFFER || p->class_id == JS_CLASS_SHARED_ARRAY_BUFFER;
+ if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
+ return false;
+ return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_REGEXP;
+}
+
+bool JS_IsMap(JSValue val)
+{
+ if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
+ return false;
+ return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_MAP;
+}
+
+int JS_IsSimpleValue(JSContext* ctx, JSValue v)
+{
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
+ return 1;
+ p = JS_VALUE_GET_OBJ(v);
+ return p->class_id >= JS_CLASS_OBJECT && p->class_id <= JS_CLASS_BOOLEAN;
}
-BOOL JS_IsError(JSContext *ctx, JSValueConst val)
+bool JS_IsError(JSContext *ctx, JSValue val)
{
JSObject *p;
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(val);
return (p->class_id == JS_CLASS_ERROR);
}
/* used to avoid catching interrupt exceptions */
-BOOL JS_IsUncatchableError(JSContext *ctx, JSValueConst val)
+bool JS_IsUncatchableError(JSContext *ctx, JSValue val)
{
JSObject *p;
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(val);
return p->class_id == JS_CLASS_ERROR && p->is_uncatchable_error;
}
-void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag)
+static void js_set_uncatchable_error(JSContext *ctx, JSValue val, bool flag)
{
JSObject *p;
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
@@ -9906,22 +10174,48 @@ void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag)
p->is_uncatchable_error = flag;
}
+void JS_SetUncatchableError(JSContext *ctx, JSValue val)
+{
+ js_set_uncatchable_error(ctx, val, true);
+}
+
+void JS_ClearUncatchableError(JSContext *ctx, JSValue val)
+{
+ js_set_uncatchable_error(ctx, val, false);
+}
+
void JS_ResetUncatchableError(JSContext *ctx)
{
- JS_SetUncatchableError(ctx, ctx->rt->current_exception, FALSE);
+ js_set_uncatchable_error(ctx, ctx->rt->current_exception, false);
}
-void JS_SetOpaque(JSValue obj, void *opaque)
+int JS_SetOpaque(JSValue obj, void *opaque)
{
- JSObject *p;
+ JSObject *p;
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
p = JS_VALUE_GET_OBJ(obj);
- p->u.opaque = opaque;
+ // User code can't set the opaque of internal objects.
+ if (p->class_id >= JS_CLASS_INIT_COUNT) {
+ p->u.opaque = opaque;
+ return 0;
+ }
}
+
+ return -1;
+}
+
+/* |obj| must be a JSObject of an internal class. */
+static void JS_SetOpaqueInternal(JSValue obj, void *opaque)
+{
+ JSObject *p;
+ assert(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT);
+ p = JS_VALUE_GET_OBJ(obj);
+ assert(p->class_id < JS_CLASS_INIT_COUNT);
+ p->u.opaque = opaque;
}
/* return NULL if not an object of class class_id */
-void *JS_GetOpaque(JSValueConst obj, JSClassID class_id)
+void *JS_GetOpaque(JSValue obj, JSClassID class_id)
{
JSObject *p;
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
@@ -9932,7 +10226,7 @@ void *JS_GetOpaque(JSValueConst obj, JSClassID class_id)
return p->u.opaque;
}
-void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id)
+void *JS_GetOpaque2(JSContext *ctx, JSValue obj, JSClassID class_id)
{
void *p = JS_GetOpaque(obj, class_id);
if (unlikely(!p)) {
@@ -9941,10 +10235,22 @@ void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id)
return p;
}
+void *JS_GetAnyOpaque(JSValue obj, JSClassID *class_id)
+{
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {
+ *class_id = 0;
+ return NULL;
+ }
+ p = JS_VALUE_GET_OBJ(obj);
+ *class_id = p->class_id;
+ return p->u.opaque;
+}
+
static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)
{
int i;
- BOOL force_ordinary;
+ bool force_ordinary;
JSAtom method_name;
JSValue method, ret;
@@ -9974,7 +10280,7 @@ static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)
break;
}
arg = JS_AtomToString(ctx, atom);
- ret = JS_CallFree(ctx, method, val, 1, (JSValueConst *)&arg);
+ ret = JS_CallFree(ctx, method, val, 1, &arg);
JS_FreeValue(ctx, arg);
if (JS_IsException(ret))
goto exception;
@@ -10015,25 +10321,25 @@ exception:
return JS_EXCEPTION;
}
-static JSValue JS_ToPrimitive(JSContext *ctx, JSValueConst val, int hint)
+static JSValue JS_ToPrimitive(JSContext *ctx, JSValue val, int hint)
{
- return JS_ToPrimitiveFree(ctx, JS_DupValue(ctx, val), hint);
+ return JS_ToPrimitiveFree(ctx, js_dup(val), hint);
}
-void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj)
+void JS_SetIsHTMLDDA(JSContext *ctx, JSValue obj)
{
JSObject *p;
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
return;
p = JS_VALUE_GET_OBJ(obj);
- p->is_HTMLDDA = TRUE;
+ p->is_HTMLDDA = true;
}
-static inline BOOL JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj)
+static inline bool JS_IsHTMLDDA(JSContext *ctx, JSValue obj)
{
JSObject *p;
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
- return FALSE;
+ return false;
p = JS_VALUE_GET_OBJ(obj);
return p->is_HTMLDDA;
}
@@ -10052,36 +10358,22 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val)
return -1;
case JS_TAG_STRING:
{
- BOOL ret = JS_VALUE_GET_STRING(val)->len != 0;
+ bool ret = JS_VALUE_GET_STRING(val)->len != 0;
JS_FreeValue(ctx, val);
return ret;
}
case JS_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
-#endif
{
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- BOOL ret;
+ JSBigInt *p = JS_VALUE_GET_PTR(val);
+ bool ret;
ret = p->num.expn != BF_EXP_ZERO && p->num.expn != BF_EXP_NAN;
JS_FreeValue(ctx, val);
return ret;
}
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_DECIMAL:
- {
- JSBigDecimal *p = JS_VALUE_GET_PTR(val);
- BOOL ret;
- ret = p->num.expn != BF_EXP_ZERO && p->num.expn != BF_EXP_NAN;
- JS_FreeValue(ctx, val);
- return ret;
- }
-#endif
case JS_TAG_OBJECT:
{
JSObject *p = JS_VALUE_GET_OBJ(val);
- BOOL ret;
- ret = !p->is_HTMLDDA;
+ bool ret = !p->is_HTMLDDA;
JS_FreeValue(ctx, val);
return ret;
}
@@ -10092,16 +10384,17 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val)
return !isnan(d) && d != 0;
} else {
JS_FreeValue(ctx, val);
- return TRUE;
+ return true;
}
}
}
-int JS_ToBool(JSContext *ctx, JSValueConst val)
+int JS_ToBool(JSContext *ctx, JSValue val)
{
- return JS_ToBoolFree(ctx, JS_DupValue(ctx, val));
+ return JS_ToBoolFree(ctx, js_dup(val));
}
+/* pc points to pure ASCII or UTF-8, null terminated contents */
static int skip_spaces(const char *pc)
{
const uint8_t *p, *p_next, *p_start;
@@ -10109,19 +10402,19 @@ static int skip_spaces(const char *pc)
p = p_start = (const uint8_t *)pc;
for (;;) {
- c = *p;
- if (c < 128) {
+ c = *p++;
+ if (c < 0x80) {
if (!((c >= 0x09 && c <= 0x0d) || (c == 0x20)))
break;
- p++;
} else {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next);
+ c = utf8_decode(p - 1, &p_next);
+ /* no need to test for invalid UTF-8, 0xFFFD is not a space */
if (!lre_is_space(c))
break;
p = p_next;
}
}
- return p - p_start;
+ return p - 1 - p_start;
}
static inline int to_digit(int c)
@@ -10137,7 +10430,7 @@ static inline int to_digit(int c)
}
/* XXX: remove */
-static double js_strtod(const char *str, int radix, BOOL is_float)
+static double js_strtod(const char *str, int radix, bool is_float)
{
double d;
int c;
@@ -10163,10 +10456,7 @@ static double js_strtod(const char *str, int radix, BOOL is_float)
n_max = ((uint64_t)-1 - (radix - 1)) / radix;
/* XXX: could be more precise */
int_exp = 0;
- while (*p != '\0') {
- c = to_digit((uint8_t)*p);
- if (c >= radix)
- break;
+ while ((c = to_digit(*p)) < radix) {
if (n <= n_max) {
n = n * radix + c;
} else {
@@ -10189,33 +10479,9 @@ static double js_strtod(const char *str, int radix, BOOL is_float)
return d;
}
-#define ATOD_INT_ONLY (1 << 0)
-/* accept Oo and Ob prefixes in addition to 0x prefix if radix = 0 */
-#define ATOD_ACCEPT_BIN_OCT (1 << 2)
-/* accept O prefix as octal if radix == 0 and properly formed (Annex B) */
-#define ATOD_ACCEPT_LEGACY_OCTAL (1 << 4)
-/* accept _ between digits as a digit separator */
-#define ATOD_ACCEPT_UNDERSCORES (1 << 5)
-/* allow a suffix to override the type */
-#define ATOD_ACCEPT_SUFFIX (1 << 6)
-/* default type */
-#define ATOD_TYPE_MASK (3 << 7)
-#define ATOD_TYPE_FLOAT64 (0 << 7)
-#define ATOD_TYPE_BIG_INT (1 << 7)
-#ifdef CONFIG_BIGNUM
-#define ATOD_TYPE_BIG_FLOAT (2 << 7)
-#define ATOD_TYPE_BIG_DECIMAL (3 << 7)
-/* assume bigint mode: floats are parsed as integers if no decimal
- point nor exponent */
-#define ATOD_MODE_BIGINT (1 << 9)
-#endif
-/* accept -0x1 */
-#define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10)
-
-static JSValue js_string_to_bigint(JSContext *ctx, const char *buf,
- int radix, int flags, slimb_t *pexponent)
+static JSValue js_string_to_bigint(JSContext *ctx, const char *buf, int radix)
{
- bf_t a_s, *a = &a_s;
+ bf_t *a;
int ret;
JSValue val;
val = JS_NewBigInt(ctx);
@@ -10227,211 +10493,136 @@ static JSValue js_string_to_bigint(JSContext *ctx, const char *buf,
JS_FreeValue(ctx, val);
return JS_ThrowOutOfMemory(ctx);
}
-#ifdef CONFIG_BIGNUM
- val = JS_CompactBigInt1(ctx, val, (flags & ATOD_MODE_BIGINT) != 0);
-#else
- val = JS_CompactBigInt1(ctx, val, FALSE);
-#endif
- return val;
-}
-
-#ifdef CONFIG_BIGNUM
-static JSValue js_string_to_bigfloat(JSContext *ctx, const char *buf,
- int radix, int flags, slimb_t *pexponent)
-{
- bf_t *a;
- int ret;
- JSValue val;
-
- val = JS_NewBigFloat(ctx);
- if (JS_IsException(val))
- return val;
- a = JS_GetBigFloat(val);
- if (flags & ATOD_ACCEPT_SUFFIX) {
- /* return the exponent to get infinite precision */
- ret = bf_atof2(a, pexponent, buf, NULL, radix, BF_PREC_INF,
- BF_RNDZ | BF_ATOF_EXPONENT);
- } else {
- ret = bf_atof(a, buf, NULL, radix, ctx->fp_env.prec,
- ctx->fp_env.flags);
- }
- if (ret & BF_ST_MEM_ERROR) {
- JS_FreeValue(ctx, val);
- return JS_ThrowOutOfMemory(ctx);
- }
- return val;
-}
-
-static JSValue js_string_to_bigdecimal(JSContext *ctx, const char *buf,
- int radix, int flags, slimb_t *pexponent)
-{
- bfdec_t *a;
- int ret;
- JSValue val;
+ return JS_CompactBigInt1(ctx, val);
+}
+
+/* `js_atof(ctx, p, len, pp, radix, flags)`
+ Convert the string pointed to by `p` to a number value.
+ Return an exception in case of memory error.
+ Return `JS_NAN` if invalid syntax.
+ - `p` points to a null terminated UTF-8 encoded char array,
+ - `len` the length of the array,
+ - `pp` if not null receives a pointer to the next character,
+ - `radix` must be in range 2 to 36, else return `JS_NAN`.
+ - `flags` is a combination of the flags below.
+ There is a null byte at `p[len]`, but there might be embedded null
+ bytes between `p[0]` and `p[len]` which must produce `JS_NAN` if
+ the `ATOD_NO_TRAILING_CHARS` flag is present.
+ */
- val = JS_NewBigDecimal(ctx);
- if (JS_IsException(val))
- return val;
- a = JS_GetBigDecimal(val);
- ret = bfdec_atof(a, buf, NULL, BF_PREC_INF,
- BF_RNDZ | BF_ATOF_NO_NAN_INF);
- if (ret & BF_ST_MEM_ERROR) {
- JS_FreeValue(ctx, val);
- return JS_ThrowOutOfMemory(ctx);
- }
- return val;
-}
-#endif
+#define ATOD_TRIM_SPACES (1 << 0) /* trim white space */
+#define ATOD_ACCEPT_EMPTY (1 << 1) /* accept an empty string, value is 0 */
+#define ATOD_ACCEPT_FLOAT (1 << 2) /* parse decimal floating point syntax */
+#define ATOD_ACCEPT_INFINITY (1 << 3) /* parse Infinity as a float point number */
+#define ATOD_ACCEPT_BIN_OCT (1 << 4) /* accept 0o and 0b prefixes */
+#define ATOD_ACCEPT_HEX_PREFIX (1 << 5) /* accept 0x prefix for radix 16 */
+#define ATOD_ACCEPT_UNDERSCORES (1 << 6) /* accept _ between digits as a digit separator */
+#define ATOD_ACCEPT_SUFFIX (1 << 7) /* allow 'n' suffix to produce BigInt */
+#define ATOD_WANT_BIG_INT (1 << 8) /* return type must be BigInt */
+#define ATOD_DECIMAL_AFTER_SIGN (1 << 9) /* only accept decimal number after sign */
+#define ATOD_NO_TRAILING_CHARS (1 << 10) /* do not accept trailing characters */
+
+static JSValue js_atof(JSContext *ctx, const char *p, size_t len,
+ const char **pp, int radix, int flags)
+{
+ const char *p_start;
+ const char *end = p + len;
+ int sep;
+ bool is_float;
+ char buf1[64], *buf = buf1;
+ size_t i, j;
+ JSValue val = JS_NAN;
+ double d;
+ char sign;
-/* return an exception in case of memory error. Return JS_NAN if
- invalid syntax */
-#ifdef CONFIG_BIGNUM
-static JSValue js_atof2(JSContext *ctx, const char *str, const char **pp,
- int radix, int flags, slimb_t *pexponent)
-#else
-static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
- int radix, int flags)
-#endif
-{
- const char *p, *p_start;
- int sep, is_neg;
- BOOL is_float, has_legacy_octal;
- int atod_type = flags & ATOD_TYPE_MASK;
- char buf1[64], *buf;
- int i, j, len;
- BOOL buf_allocated = FALSE;
- JSValue val;
+ if (radix < 2 || radix > 36)
+ goto done;
/* optional separator between digits */
sep = (flags & ATOD_ACCEPT_UNDERSCORES) ? '_' : 256;
- has_legacy_octal = FALSE;
-
- p = str;
- p_start = p;
- is_neg = 0;
- if (p[0] == '+') {
- p++;
- p_start++;
- if (!(flags & ATOD_ACCEPT_PREFIX_AFTER_SIGN))
- goto no_radix_prefix;
- } else if (p[0] == '-') {
+ sign = 0;
+ if (flags & ATOD_TRIM_SPACES)
+ p += skip_spaces(p);
+ if (p == end && (flags & ATOD_ACCEPT_EMPTY)) {
+ if (pp) *pp = p;
+ if (flags & ATOD_WANT_BIG_INT)
+ return JS_NewBigInt64(ctx, 0);
+ else
+ return js_int32(0);
+ }
+ if (*p == '+' || *p == '-') {
+ sign = *p;
p++;
- p_start++;
- is_neg = 1;
- if (!(flags & ATOD_ACCEPT_PREFIX_AFTER_SIGN))
- goto no_radix_prefix;
+ if (flags & ATOD_DECIMAL_AFTER_SIGN)
+ flags &= ~(ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT);
}
if (p[0] == '0') {
if ((p[1] == 'x' || p[1] == 'X') &&
- (radix == 0 || radix == 16)) {
+ ((flags & ATOD_ACCEPT_HEX_PREFIX) || radix == 16)) {
p += 2;
radix = 16;
- } else if ((p[1] == 'o' || p[1] == 'O') &&
- radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) {
- p += 2;
- radix = 8;
- } else if ((p[1] == 'b' || p[1] == 'B') &&
- radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) {
- p += 2;
- radix = 2;
- } else if ((p[1] >= '0' && p[1] <= '9') &&
- radix == 0 && (flags & ATOD_ACCEPT_LEGACY_OCTAL)) {
- int i;
- has_legacy_octal = TRUE;
- sep = 256;
- for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++)
- continue;
- if (p[i] == '8' || p[i] == '9')
- goto no_prefix;
- p += 1;
- radix = 8;
- } else {
- goto no_prefix;
+ } else if (flags & ATOD_ACCEPT_BIN_OCT) {
+ if (p[1] == 'o' || p[1] == 'O') {
+ p += 2;
+ radix = 8;
+ } else if (p[1] == 'b' || p[1] == 'B') {
+ p += 2;
+ radix = 2;
+ }
}
- /* there must be a digit after the prefix */
- if (to_digit((uint8_t)*p) >= radix)
- goto fail;
- no_prefix: ;
} else {
- no_radix_prefix:
- if (!(flags & ATOD_INT_ONLY) &&
- (atod_type == ATOD_TYPE_FLOAT64
-#ifdef CONFIG_BIGNUM
- || atod_type == ATOD_TYPE_BIG_FLOAT
-#endif
- ) &&
- strstart(p, "Infinity", &p)) {
-#ifdef CONFIG_BIGNUM
- if (atod_type == ATOD_TYPE_BIG_FLOAT) {
- bf_t *a;
- val = JS_NewBigFloat(ctx);
- if (JS_IsException(val))
- goto done;
- a = JS_GetBigFloat(val);
- bf_set_inf(a, is_neg);
- } else
-#endif
- {
- double d = INFINITY;
- if (is_neg)
- d = -d;
- val = JS_NewFloat64(ctx, d);
- }
+ if (*p == 'I' && (flags & ATOD_ACCEPT_INFINITY) && js__strstart(p, "Infinity", &p)) {
+ d = INF;
+ if (sign == '-')
+ d = -d;
+ val = js_float64(d);
goto done;
}
}
- if (radix == 0)
- radix = 10;
- is_float = FALSE;
+ is_float = false;
p_start = p;
- while (to_digit((uint8_t)*p) < radix
- || (*p == sep && (radix != 10 ||
- p != p_start + 1 || p[-1] != '0') &&
- to_digit((uint8_t)p[1]) < radix)) {
+ while (to_digit(*p) < radix) {
p++;
+ if (*p == sep && to_digit(p[1]) < radix)
+ p++;
}
- if (!(flags & ATOD_INT_ONLY)) {
- if (*p == '.' && (p > p_start || to_digit((uint8_t)p[1]) < radix)) {
- is_float = TRUE;
+ if ((flags & ATOD_ACCEPT_FLOAT) && radix == 10) {
+ if (*p == '.' && (p > p_start || to_digit(p[1]) < radix)) {
+ is_float = true;
p++;
- if (*p == sep)
- goto fail;
- while (to_digit((uint8_t)*p) < radix ||
- (*p == sep && to_digit((uint8_t)p[1]) < radix))
+ while (to_digit(*p) < radix) {
p++;
+ if (*p == sep && to_digit(p[1]) < radix)
+ p++;
+ }
}
- if (p > p_start &&
- (((*p == 'e' || *p == 'E') && radix == 10) ||
- ((*p == 'p' || *p == 'P') && (radix == 2 || radix == 8 || radix == 16)))) {
- const char *p1 = p + 1;
- is_float = TRUE;
- if (*p1 == '+') {
- p1++;
- } else if (*p1 == '-') {
- p1++;
- }
- if (is_digit((uint8_t)*p1)) {
- p = p1 + 1;
- while (is_digit((uint8_t)*p) || (*p == sep && is_digit((uint8_t)p[1])))
+ if (p > p_start && (*p == 'e' || *p == 'E')) {
+ i = 1;
+ if (p[1] == '+' || p[1] == '-') {
+ i++;
+ }
+ if (is_digit(p[i])) {
+ is_float = true;
+ p += i + 1;
+ while (is_digit(*p) || (*p == sep && is_digit(p[1])))
p++;
}
}
}
if (p == p_start)
- goto fail;
+ goto done;
- buf = buf1;
- buf_allocated = FALSE;
len = p - p_start;
if (unlikely((len + 2) > sizeof(buf1))) {
buf = js_malloc_rt(ctx->rt, len + 2); /* no exception raised */
- if (!buf)
- goto mem_error;
- buf_allocated = TRUE;
+ if (!buf) {
+ if (pp) *pp = p;
+ return JS_ThrowOutOfMemory(ctx);
+ }
}
- /* remove the separators and the radix prefixes */
+ /* remove the separators and the radix prefix */
j = 0;
- if (is_neg)
+ if (sign == '-')
buf[j++] = '-';
for (i = 0; i < len; i++) {
if (p_start[i] != '_')
@@ -10442,96 +10633,33 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
if (flags & ATOD_ACCEPT_SUFFIX) {
if (*p == 'n') {
p++;
- atod_type = ATOD_TYPE_BIG_INT;
- } else
-#ifdef CONFIG_BIGNUM
- if (*p == 'l') {
- p++;
- atod_type = ATOD_TYPE_BIG_FLOAT;
- } else if (*p == 'm') {
- p++;
- atod_type = ATOD_TYPE_BIG_DECIMAL;
- } else if (flags & ATOD_MODE_BIGINT) {
- if (!is_float)
- atod_type = ATOD_TYPE_BIG_INT;
- if (has_legacy_octal)
- goto fail;
- } else
-#endif
- {
- if (is_float && radix != 10)
- goto fail;
+ flags |= ATOD_WANT_BIG_INT;
}
+ }
+
+ if (flags & ATOD_WANT_BIG_INT) {
+ if (!is_float)
+ val = js_string_to_bigint(ctx, buf, radix);
} else {
- if (atod_type == ATOD_TYPE_FLOAT64) {
-#ifdef CONFIG_BIGNUM
- if (flags & ATOD_MODE_BIGINT) {
- if (!is_float)
- atod_type = ATOD_TYPE_BIG_INT;
- if (has_legacy_octal)
- goto fail;
- } else
-#endif
- {
- if (is_float && radix != 10)
- goto fail;
- }
- }
+ d = js_strtod(buf, radix, is_float);
+ val = js_number(d); /* return int or float64 */
}
- switch(atod_type) {
- case ATOD_TYPE_FLOAT64:
- {
- double d;
- d = js_strtod(buf, radix, is_float);
- /* return int or float64 */
- val = JS_NewFloat64(ctx, d);
+ done:
+ if (flags & ATOD_NO_TRAILING_CHARS) {
+ if (flags & ATOD_TRIM_SPACES)
+ p += skip_spaces(p);
+ if (p != end) {
+ JS_FreeValue(ctx, val);
+ val = JS_NAN;
}
- break;
- case ATOD_TYPE_BIG_INT:
- if (has_legacy_octal || is_float)
- goto fail;
- val = ctx->rt->bigint_ops.from_string(ctx, buf, radix, flags, NULL);
- break;
-#ifdef CONFIG_BIGNUM
- case ATOD_TYPE_BIG_FLOAT:
- if (has_legacy_octal)
- goto fail;
- val = ctx->rt->bigfloat_ops.from_string(ctx, buf, radix, flags,
- pexponent);
- break;
- case ATOD_TYPE_BIG_DECIMAL:
- if (radix != 10)
- goto fail;
- val = ctx->rt->bigdecimal_ops.from_string(ctx, buf, radix, flags, NULL);
- break;
-#endif
- default:
- abort();
}
-
-done:
- if (buf_allocated)
+ if (buf != buf1)
js_free_rt(ctx->rt, buf);
- if (pp)
- *pp = p;
+ if (pp) *pp = p;
return val;
- fail:
- val = JS_NAN;
- goto done;
- mem_error:
- val = JS_ThrowOutOfMemory(ctx);
- goto done;
}
-#ifdef CONFIG_BIGNUM
-static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
- int radix, int flags)
-{
- return js_atof2(ctx, str, pp, radix, flags, NULL);
-}
-#endif
-
typedef enum JSToNumberHintEnum {
TON_FLAG_NUMBER,
TON_FLAG_NUMERIC,
@@ -10549,26 +10677,10 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val,
case JS_TAG_BIG_INT:
if (flag != TON_FLAG_NUMERIC) {
JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert bigint to number");
- }
- ret = val;
- break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_DECIMAL:
- if (flag != TON_FLAG_NUMERIC) {
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert bigdecimal to number");
+ return JS_ThrowTypeError(ctx, "cannot convert BigInt to number");
}
ret = val;
break;
- case JS_TAG_BIG_FLOAT:
- if (flag != TON_FLAG_NUMERIC) {
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert bigfloat to number");
- }
- ret = val;
- break;
-#endif
case JS_TAG_FLOAT64:
case JS_TAG_INT:
case JS_TAG_EXCEPTION:
@@ -10576,7 +10688,7 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val,
break;
case JS_TAG_BOOL:
case JS_TAG_NULL:
- ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val));
+ ret = js_int32(JS_VALUE_GET_INT(val));
break;
case JS_TAG_UNDEFINED:
ret = JS_NAN;
@@ -10589,28 +10701,18 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val,
case JS_TAG_STRING:
{
const char *str;
- const char *p;
size_t len;
+ int flags;
str = JS_ToCStringLen(ctx, &len, val);
JS_FreeValue(ctx, val);
if (!str)
return JS_EXCEPTION;
- p = str;
- p += skip_spaces(p);
- if ((p - str) == len) {
- ret = JS_NewInt32(ctx, 0);
- } else {
- int flags = ATOD_ACCEPT_BIN_OCT;
- ret = js_atof(ctx, p, &p, 0, flags);
- if (!JS_IsException(ret)) {
- p += skip_spaces(p);
- if ((p - str) != len) {
- JS_FreeValue(ctx, ret);
- ret = JS_NAN;
- }
- }
- }
+ flags = ATOD_TRIM_SPACES | ATOD_ACCEPT_EMPTY |
+ ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_INFINITY |
+ ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT |
+ ATOD_DECIMAL_AFTER_SIGN | ATOD_NO_TRAILING_CHARS;
+ ret = js_atof(ctx, str, len, NULL, 10, flags);
JS_FreeCString(ctx, str);
}
break;
@@ -10635,9 +10737,9 @@ static JSValue JS_ToNumericFree(JSContext *ctx, JSValue val)
return JS_ToNumberHintFree(ctx, val, TON_FLAG_NUMERIC);
}
-static JSValue JS_ToNumeric(JSContext *ctx, JSValueConst val)
+static JSValue JS_ToNumeric(JSContext *ctx, JSValue val)
{
- return JS_ToNumericFree(ctx, JS_DupValue(ctx, val));
+ return JS_ToNumericFree(ctx, js_dup(val));
}
static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres,
@@ -10648,7 +10750,7 @@ static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres,
val = JS_ToNumberFree(ctx, val);
if (JS_IsException(val)) {
- *pres = JS_FLOAT64_NAN;
+ *pres = NAN;
return -1;
}
tag = JS_VALUE_GET_NORM_TAG(val);
@@ -10660,11 +10762,8 @@ static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres,
d = JS_VALUE_GET_FLOAT64(val);
break;
case JS_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
-#endif
{
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
+ JSBigInt *p = JS_VALUE_GET_PTR(val);
/* XXX: there can be a double rounding issue with some
primitives (such as JS_ToUint8ClampFree()), but it is
not critical to fix it. */
@@ -10695,14 +10794,14 @@ static inline int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val)
}
}
-int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val)
+int JS_ToFloat64(JSContext *ctx, double *pres, JSValue val)
{
- return JS_ToFloat64Free(ctx, pres, JS_DupValue(ctx, val));
+ return JS_ToFloat64Free(ctx, pres, js_dup(val));
}
-static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val)
+JSValue JS_ToNumber(JSContext *ctx, JSValue val)
{
- return JS_ToNumberFree(ctx, JS_DupValue(ctx, val));
+ return JS_ToNumberFree(ctx, js_dup(val));
}
/* same as JS_ToNumber() but return 0 in case of NaN/Undefined */
@@ -10718,52 +10817,20 @@ static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
case JS_TAG_BOOL:
case JS_TAG_NULL:
case JS_TAG_UNDEFINED:
- ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val));
+ ret = js_int32(JS_VALUE_GET_INT(val));
break;
case JS_TAG_FLOAT64:
{
double d = JS_VALUE_GET_FLOAT64(val);
if (isnan(d)) {
- ret = JS_NewInt32(ctx, 0);
+ ret = js_int32(0);
} else {
/* convert -0 to +0 */
d = trunc(d) + 0.0;
- ret = JS_NewFloat64(ctx, d);
+ ret = js_number(d);
}
}
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- {
- bf_t a_s, *a, r_s, *r = &r_s;
- BOOL is_nan;
-
- a = JS_ToBigFloat(ctx, &a_s, val);
- if (!a) {
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
- }
- if (!bf_is_finite(a)) {
- is_nan = bf_is_nan(a);
- if (is_nan)
- ret = JS_NewInt32(ctx, 0);
- else
- ret = JS_DupValue(ctx, val);
- } else {
- ret = JS_NewBigInt(ctx);
- if (!JS_IsException(ret)) {
- r = JS_GetBigInt(ret);
- bf_set(r, a);
- bf_rint(r, BF_RNDZ);
- ret = JS_CompactBigInt(ctx, ret);
- }
- }
- if (a == &a_s)
- bf_delete(a);
- JS_FreeValue(ctx, val);
- }
- break;
-#endif
default:
val = JS_ToNumberFree(ctx, val);
if (JS_IsException(val))
@@ -10806,15 +10873,6 @@ static int JS_ToInt32SatFree(JSContext *ctx, int *pres, JSValue val)
}
}
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- bf_get_int32(&ret, &p->num, 0);
- JS_FreeValue(ctx, val);
- }
- break;
-#endif
default:
val = JS_ToNumberFree(ctx, val);
if (JS_IsException(val)) {
@@ -10827,15 +10885,15 @@ static int JS_ToInt32SatFree(JSContext *ctx, int *pres, JSValue val)
return 0;
}
-int JS_ToInt32Sat(JSContext *ctx, int *pres, JSValueConst val)
+int JS_ToInt32Sat(JSContext *ctx, int *pres, JSValue val)
{
- return JS_ToInt32SatFree(ctx, pres, JS_DupValue(ctx, val));
+ return JS_ToInt32SatFree(ctx, pres, js_dup(val));
}
-int JS_ToInt32Clamp(JSContext *ctx, int *pres, JSValueConst val,
+int JS_ToInt32Clamp(JSContext *ctx, int *pres, JSValue val,
int min, int max, int min_offset)
{
- int res = JS_ToInt32SatFree(ctx, pres, JS_DupValue(ctx, val));
+ int res = JS_ToInt32SatFree(ctx, pres, js_dup(val));
if (res == 0) {
if (*pres < min) {
*pres += min_offset;
@@ -10873,22 +10931,13 @@ static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val)
} else {
if (d < INT64_MIN)
*pres = INT64_MIN;
- else if (d >= 0x1p63) /* must use INT64_MAX + 1 because INT64_MAX cannot be exactly represented as a double */
+ else if (d >= 0x1p63)
*pres = INT64_MAX;
else
*pres = (int64_t)d;
}
}
return 0;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- bf_get_int64(pres, &p->num, 0);
- JS_FreeValue(ctx, val);
- }
- return 0;
-#endif
default:
val = JS_ToNumberFree(ctx, val);
if (JS_IsException(val)) {
@@ -10899,15 +10948,15 @@ static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val)
}
}
-int JS_ToInt64Sat(JSContext *ctx, int64_t *pres, JSValueConst val)
+int JS_ToInt64Sat(JSContext *ctx, int64_t *pres, JSValue val)
{
- return JS_ToInt64SatFree(ctx, pres, JS_DupValue(ctx, val));
+ return JS_ToInt64SatFree(ctx, pres, js_dup(val));
}
-int JS_ToInt64Clamp(JSContext *ctx, int64_t *pres, JSValueConst val,
+int JS_ToInt64Clamp(JSContext *ctx, int64_t *pres, JSValue val,
int64_t min, int64_t max, int64_t neg_offset)
{
- int res = JS_ToInt64SatFree(ctx, pres, JS_DupValue(ctx, val));
+ int res = JS_ToInt64SatFree(ctx, pres, js_dup(val));
if (res == 0) {
if (*pres < 0)
*pres += neg_offset;
@@ -10954,21 +11003,13 @@ static int JS_ToInt64Free(JSContext *ctx, int64_t *pres, JSValue val)
ret = v << ((e - 1023) - 52);
/* take the sign into account */
if (u.u64 >> 63)
- ret = -ret;
+ if (ret != INT64_MIN)
+ ret = -ret;
} else {
ret = 0; /* also handles NaN and +inf */
}
}
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- bf_get_int64(&ret, &p->num, BF_GET_INT_MOD);
- JS_FreeValue(ctx, val);
- }
- break;
-#endif
default:
val = JS_ToNumberFree(ctx, val);
if (JS_IsException(val)) {
@@ -10981,12 +11022,12 @@ static int JS_ToInt64Free(JSContext *ctx, int64_t *pres, JSValue val)
return 0;
}
-int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val)
+int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValue val)
{
- return JS_ToInt64Free(ctx, pres, JS_DupValue(ctx, val));
+ return JS_ToInt64Free(ctx, pres, js_dup(val));
}
-int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val)
+int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValue val)
{
if (JS_IsBigInt(ctx, val))
return JS_ToBigInt64(ctx, pres, val);
@@ -11029,21 +11070,13 @@ static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val)
ret = v >> 32;
/* take the sign into account */
if (u.u64 >> 63)
- ret = -ret;
+ if (ret != INT32_MIN)
+ ret = -ret;
} else {
ret = 0; /* also handles NaN and +inf */
}
}
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- bf_get_int32(&ret, &p->num, BF_GET_INT_MOD);
- JS_FreeValue(ctx, val);
- }
- break;
-#endif
default:
val = JS_ToNumberFree(ctx, val);
if (JS_IsException(val)) {
@@ -11056,9 +11089,9 @@ static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val)
return 0;
}
-int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val)
+int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValue val)
{
- return JS_ToInt32Free(ctx, pres, JS_DupValue(ctx, val));
+ return JS_ToInt32Free(ctx, pres, js_dup(val));
}
static inline int JS_ToUint32Free(JSContext *ctx, uint32_t *pres, JSValue val)
@@ -11079,9 +11112,6 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val)
case JS_TAG_NULL:
case JS_TAG_UNDEFINED:
res = JS_VALUE_GET_INT(val);
-#ifdef CONFIG_BIGNUM
- int_clamp:
-#endif
res = max_int(0, min_int(255, res));
break;
case JS_TAG_FLOAT64:
@@ -11099,20 +11129,6 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val)
}
}
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- bf_t r_s, *r = &r_s;
- bf_init(ctx->bf_ctx, r);
- bf_set(r, &p->num);
- bf_rint(r, BF_RNDN);
- bf_get_int32(&res, r, 0);
- bf_delete(r);
- JS_FreeValue(ctx, val);
- }
- goto int_clamp;
-#endif
default:
val = JS_ToNumberFree(ctx, val);
if (JS_IsException(val)) {
@@ -11126,7 +11142,7 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val)
}
static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
- JSValue val, BOOL is_array_ctor)
+ JSValue val, bool is_array_ctor)
{
uint32_t tag, len;
@@ -11144,13 +11160,10 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
}
break;
case JS_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
-#endif
{
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
+ JSBigInt *p = JS_VALUE_GET_PTR(val);
bf_t a;
- BOOL res;
+ bool res;
bf_get_int32((int32_t *)&len, &p->num, BF_GET_INT_MOD);
bf_init(ctx->bf_ctx, &a);
bf_set_ui(&a, len);
@@ -11178,7 +11191,7 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
if (JS_IsException(val))
return -1;
/* cannot recurse because val is a number */
- if (JS_ToArrayLengthFree(ctx, &len, val, TRUE))
+ if (JS_ToArrayLengthFree(ctx, &len, val, true))
return -1;
} else {
/* legacy behavior: must do the conversion twice and compare */
@@ -11190,7 +11203,7 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
if (JS_IsException(val))
return -1;
/* cannot recurse because val is a number */
- if (JS_ToArrayLengthFree(ctx, &len1, val, FALSE))
+ if (JS_ToArrayLengthFree(ctx, &len1, val, false))
return -1;
if (len1 != len) {
fail:
@@ -11207,13 +11220,13 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
#define MAX_SAFE_INTEGER (((int64_t)1 << 53) - 1)
-static BOOL is_safe_integer(double d)
+static bool is_safe_integer(double d)
{
return isfinite(d) && floor(d) == d &&
fabs(d) <= (double)MAX_SAFE_INTEGER;
}
-int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val)
+int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValue val)
{
int64_t v;
if (JS_ToInt64Sat(ctx, &v, val))
@@ -11238,17 +11251,17 @@ static __exception int JS_ToLengthFree(JSContext *ctx, int64_t *plen,
}
/* Note: can return an exception */
-static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val)
+static int JS_NumberIsInteger(JSContext *ctx, JSValue val)
{
double d;
if (!JS_IsNumber(val))
- return FALSE;
+ return false;
if (unlikely(JS_ToFloat64(ctx, &d, val)))
return -1;
return isfinite(d) && floor(d) == d;
}
-static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val)
+static bool JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValue val)
{
uint32_t tag;
@@ -11268,35 +11281,22 @@ static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val)
}
case JS_TAG_BIG_INT:
{
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
+ JSBigInt *p = JS_VALUE_GET_PTR(val);
/* Note: integer zeros are not necessarily positive */
return p->num.sign && !bf_is_zero(&p->num);
}
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- return p->num.sign;
- }
- break;
- case JS_TAG_BIG_DECIMAL:
- {
- JSBigDecimal *p = JS_VALUE_GET_PTR(val);
- return p->num.sign;
- }
- break;
-#endif
default:
- return FALSE;
+ return false;
}
}
-static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix)
+static JSValue js_bigint_to_string1(JSContext *ctx, JSValue val, int radix)
{
JSValue ret;
bf_t a_s, *a;
char *str;
int saved_sign;
+ size_t len;
a = JS_ToBigInt(ctx, &a_s, val);
if (!a)
@@ -11304,414 +11304,380 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix)
saved_sign = a->sign;
if (a->expn == BF_EXP_ZERO)
a->sign = 0;
- str = bf_ftoa(NULL, a, radix, 0, BF_RNDZ | BF_FTOA_FORMAT_FRAC |
+ str = bf_ftoa(&len, a, radix, 0, BF_RNDZ | BF_FTOA_FORMAT_FRAC |
BF_FTOA_JS_QUIRKS);
a->sign = saved_sign;
JS_FreeBigInt(ctx, a, &a_s);
if (!str)
return JS_ThrowOutOfMemory(ctx);
- ret = JS_NewString(ctx, str);
+ ret = js_new_string8_len(ctx, str, len);
bf_free(ctx->bf_ctx, str);
return ret;
}
-static JSValue js_bigint_to_string(JSContext *ctx, JSValueConst val)
+static JSValue js_bigint_to_string(JSContext *ctx, JSValue val)
{
return js_bigint_to_string1(ctx, val, 10);
}
-#ifdef CONFIG_BIGNUM
+/*---- floating point number to string conversions ----*/
-static JSValue js_ftoa(JSContext *ctx, JSValueConst val1, int radix,
- limb_t prec, bf_flags_t flags)
-{
- JSValue val, ret;
- bf_t a_s, *a;
- char *str;
- int saved_sign;
+/* JavaScript rounding is specified as round to nearest tie away
+ from zero (RNDNA), but in `printf` the "ties" case is not
+ specified (in most cases it is RNDN, round to nearest, tie to even),
+ so we must round manually. We generate 2 extra places and make
+ an extra call to snprintf if these are exactly '50'.
+ We set the current rounding mode to FE_DOWNWARD to check if the
+ last 2 places become '49'. If not, we must round up, which is
+ performed in place using the string digits.
- val = JS_ToNumeric(ctx, val1);
- if (JS_IsException(val))
- return val;
- a = JS_ToBigFloat(ctx, &a_s, val);
- if (!a) {
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
- }
- saved_sign = a->sign;
- if (a->expn == BF_EXP_ZERO)
- a->sign = 0;
- flags |= BF_FTOA_JS_QUIRKS;
- if ((flags & BF_FTOA_FORMAT_MASK) == BF_FTOA_FORMAT_FREE_MIN) {
- /* Note: for floating point numbers with a radix which is not
- a power of two, the current precision is used to compute
- the number of digits. */
- if ((radix & (radix - 1)) != 0) {
- bf_t r_s, *r = &r_s;
- int prec, flags1;
- /* must round first */
- if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) {
- prec = ctx->fp_env.prec;
- flags1 = ctx->fp_env.flags &
- (BF_FLAG_SUBNORMAL | (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT));
- } else {
- prec = 53;
- flags1 = bf_set_exp_bits(11) | BF_FLAG_SUBNORMAL;
- }
- bf_init(ctx->bf_ctx, r);
- bf_set(r, a);
- bf_round(r, prec, flags1 | BF_RNDN);
- str = bf_ftoa(NULL, r, radix, prec, flags1 | flags);
- bf_delete(r);
- } else {
- str = bf_ftoa(NULL, a, radix, BF_PREC_INF, flags);
- }
- } else {
- str = bf_ftoa(NULL, a, radix, prec, flags);
- }
- a->sign = saved_sign;
- if (a == &a_s)
- bf_delete(a);
- JS_FreeValue(ctx, val);
- if (!str)
- return JS_ThrowOutOfMemory(ctx);
- ret = JS_NewString(ctx, str);
- bf_free(ctx->bf_ctx, str);
- return ret;
-}
-
-static JSValue js_bigfloat_to_string(JSContext *ctx, JSValueConst val)
-{
- return js_ftoa(ctx, val, 10, 0, BF_RNDN | BF_FTOA_FORMAT_FREE_MIN);
-}
-
-static JSValue js_bigdecimal_to_string1(JSContext *ctx, JSValueConst val,
- limb_t prec, int flags)
-{
- JSValue ret;
- bfdec_t *a;
- char *str;
- int saved_sign;
+ Note that we cannot rely on snprintf for rounding up:
+ the code below fails on macOS for `0.5.toFixed(0)`: gives `0` expected `1`
+ fesetround(FE_UPWARD);
+ snprintf(dest, size, "%.*f", n_digits, d);
+ fesetround(FE_TONEAREST);
+ */
- a = JS_ToBigDecimal(ctx, val);
- if (!a)
- return JS_EXCEPTION;
- saved_sign = a->sign;
- if (a->expn == BF_EXP_ZERO)
- a->sign = 0;
- str = bfdec_ftoa(NULL, a, prec, flags | BF_FTOA_JS_QUIRKS);
- a->sign = saved_sign;
- if (!str)
- return JS_ThrowOutOfMemory(ctx);
- ret = JS_NewString(ctx, str);
- bf_free(ctx->bf_ctx, str);
- return ret;
-}
+/* `js_fcvt` minimum buffer length:
+ - up to 21 digits in integral part
+ - 1 potential decimal point
+ - up to 102 decimals
+ - 1 null terminator
+ */
+#define JS_FCVT_BUF_SIZE (21+1+102+1)
+
+/* `js_ecvt` minimum buffer length:
+ - 1 leading digit
+ - 1 potential decimal point
+ - up to 102 decimals
+ - 5 exponent characters (from 'e-324' to 'e+308')
+ - 1 null terminator
+ */
+#define JS_ECVT_BUF_SIZE (1+1+102+5+1)
-static JSValue js_bigdecimal_to_string(JSContext *ctx, JSValueConst val)
-{
- return js_bigdecimal_to_string1(ctx, val, 0,
- BF_RNDZ | BF_FTOA_FORMAT_FREE);
+/* `js_dtoa` minimum buffer length:
+ - 8 byte prefix
+ - either JS_FCVT_BUF_SIZE or JS_ECVT_BUF_SIZE
+ - JS_FCVT_BUF_SIZE is larger than JS_ECVT_BUF_SIZE
+ */
+#define JS_DTOA_BUF_SIZE (8+JS_FCVT_BUF_SIZE)
+
+/* `js_ecvt1`: compute the digits and decimal point spot for a double
+ - `d` is finite, positive or zero
+ - `n_digits` number of significant digits in range 1..103
+ - `buf` receives the printf result
+ - `buf` has a fixed format: n_digits with a decimal point at offset 1
+ and exponent 'e{+/-}xx[x]' at offset n_digits+1
+ Return n_digits
+ Store the position of the decimal point into `*decpt`
+ */
+static int js_ecvt1(double d, int n_digits,
+ char dest[minimum_length(JS_ECVT_BUF_SIZE)],
+ size_t size, int *decpt)
+{
+ /* d is positive, ensure decimal point is always present */
+ snprintf(dest, size, "%#.*e", n_digits - 1, d);
+ /* dest contents:
+ 0: first digit
+ 1: '.' decimal point (locale specific)
+ 2..n_digits: (n_digits-1) additional digits
+ n_digits+1: 'e' exponent mark
+ n_digits+2..: exponent sign, value and null terminator
+ */
+ /* extract the exponent (actually the position of the decimal point) */
+ *decpt = 1 + atoi(dest + n_digits + 2);
+ return n_digits;
}
-#endif /* CONFIG_BIGNUM */
-
-/* 2 <= base <= 36 */
-static char const digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
-
-static char *i64toa(char *buf_end, int64_t n, unsigned int base)
-{
- char *q = buf_end;
- int digit, is_neg;
-
- is_neg = 0;
- if (n < 0) {
- is_neg = 1;
- n = -n;
- }
- *--q = '\0';
- if (base == 10) {
- /* division by known base uses multiplication */
- do {
- digit = (uint64_t)n % 10;
- n = (uint64_t)n / 10;
- *--q = '0' + digit;
- } while (n != 0);
- } else {
- do {
- digit = (uint64_t)n % base;
- n = (uint64_t)n / base;
- *--q = digits[digit];
- } while (n != 0);
- }
- if (is_neg)
- *--q = '-';
- return q;
-}
-
-/* buf1 contains the printf result */
-static void js_ecvt1(double d, int n_digits, int *decpt, int *sign, char *buf,
- int rounding_mode, char *buf1, int buf1_size)
-{
- if (rounding_mode != FE_TONEAREST)
- fesetround(rounding_mode);
- snprintf(buf1, buf1_size, "%+.*e", n_digits - 1, d);
- if (rounding_mode != FE_TONEAREST)
- fesetround(FE_TONEAREST);
- *sign = (buf1[0] == '-');
- /* mantissa */
- buf[0] = buf1[1];
- if (n_digits > 1)
- memcpy(buf + 1, buf1 + 3, n_digits - 1);
- buf[n_digits] = '\0';
- /* exponent */
- *decpt = atoi(buf1 + n_digits + 2 + (n_digits > 1)) + 1;
-}
-
-/* maximum buffer size for js_dtoa */
-#define JS_DTOA_BUF_SIZE 128
-
-/* needed because ecvt usually limits the number of digits to
- 17. Return the number of digits. */
-static int js_ecvt(double d, int n_digits, int *decpt, int *sign, char *buf,
- BOOL is_fixed)
-{
- int rounding_mode;
- char buf_tmp[JS_DTOA_BUF_SIZE];
-
- if (!is_fixed) {
- unsigned int n_digits_min, n_digits_max;
- /* find the minimum amount of digits (XXX: inefficient but simple) */
- n_digits_min = 1;
- n_digits_max = 17;
- while (n_digits_min < n_digits_max) {
+/* `js_ecvt`: compute the digits and decimal point spot for a double
+ with proper javascript rounding. We cannot use `ecvt` for multiple
+ resasons: portability, because of the number of digits is typically
+ limited to 17, finally because the default rounding is inadequate.
+ `d` is finite and positive or zero.
+ `n_digits` number of significant digits in range 1..101
+ or 0 for automatic (only as many digits as necessary)
+ Return the number of digits produced in `dest`.
+ Store the position of the decimal point into `*decpt`
+ */
+static int js_ecvt(double d, int n_digits,
+ char dest[minimum_length(JS_ECVT_BUF_SIZE)],
+ size_t size, int *decpt)
+{
+ if (n_digits == 0) {
+ /* find the minimum number of digits (XXX: inefficient but simple) */
+ // TODO(chqrlie) use direct method from quickjs-printf
+ unsigned int n_digits_min = 1;
+ unsigned int n_digits_max = 17;
+ for (;;) {
n_digits = (n_digits_min + n_digits_max) / 2;
- js_ecvt1(d, n_digits, decpt, sign, buf, FE_TONEAREST,
- buf_tmp, sizeof(buf_tmp));
- if (safe_strtod(buf_tmp, NULL) == d) {
- /* no need to keep the trailing zeros */
- while (n_digits >= 2 && buf[n_digits - 1] == '0')
+ js_ecvt1(d, n_digits, dest, size, decpt);
+ if (n_digits_min == n_digits_max)
+ return n_digits;
+ /* dest contents:
+ 0: first digit
+ 1: '.' decimal point (locale specific)
+ 2..n_digits: (n_digits-1) additional digits
+ n_digits+1: 'e' exponent mark
+ n_digits+2..: exponent sign, value and null terminator
+ */
+ if (safe_strtod(dest, NULL) == d) {
+ unsigned int n0 = n_digits;
+ /* enough digits */
+ /* strip the trailing zeros */
+ while (dest[n_digits] == '0')
n_digits--;
+ if (n_digits == n_digits_min)
+ return n_digits;
+ /* done if trailing zeros and not denormal or huge */
+ if (n_digits < n0 && d > 3e-308 && d < 8e307)
+ return n_digits;
n_digits_max = n_digits;
} else {
+ /* need at least one more digit */
n_digits_min = n_digits + 1;
}
}
- n_digits = n_digits_max;
- rounding_mode = FE_TONEAREST;
} else {
- rounding_mode = FE_TONEAREST;
-#ifdef CONFIG_PRINTF_RNDN
- {
- char buf1[JS_DTOA_BUF_SIZE], buf2[JS_DTOA_BUF_SIZE];
- int decpt1, sign1, decpt2, sign2;
- /* The JS rounding is specified as round to nearest ties away
- from zero (RNDNA), but in printf the "ties" case is not
- specified (for example it is RNDN for glibc, RNDNA for
- Windows), so we must round manually. */
- js_ecvt1(d, n_digits + 1, &decpt1, &sign1, buf1, FE_TONEAREST,
- buf_tmp, sizeof(buf_tmp));
- /* XXX: could use 2 digits to reduce the average running time */
- if (buf1[n_digits] == '5') {
- js_ecvt1(d, n_digits + 1, &decpt1, &sign1, buf1, FE_DOWNWARD,
- buf_tmp, sizeof(buf_tmp));
- js_ecvt1(d, n_digits + 1, &decpt2, &sign2, buf2, FE_UPWARD,
- buf_tmp, sizeof(buf_tmp));
- if (memcmp(buf1, buf2, n_digits + 1) == 0 && decpt1 == decpt2) {
- /* exact result: round away from zero */
- if (sign1)
- rounding_mode = FE_DOWNWARD;
- else
- rounding_mode = FE_UPWARD;
+#if defined(FE_DOWNWARD) && defined(FE_TONEAREST)
+ int i;
+ /* generate 2 extra digits: 99% chances to avoid 2 calls */
+ js_ecvt1(d, n_digits + 2, dest, size, decpt);
+ if (dest[n_digits + 1] < '5')
+ return n_digits; /* truncate the 2 extra digits */
+ if (dest[n_digits + 1] == '5' && dest[n_digits + 2] == '0') {
+ /* close to half-way: try rounding toward 0 */
+ fesetround(FE_DOWNWARD);
+ js_ecvt1(d, n_digits + 2, dest, size, decpt);
+ fesetround(FE_TONEAREST);
+ if (dest[n_digits + 1] < '5')
+ return n_digits; /* truncate the 2 extra digits */
+ }
+ /* round up in the string */
+ for(i = n_digits;; i--) {
+ /* ignore the locale specific decimal point */
+ if (is_digit(dest[i])) {
+ if (dest[i]++ < '9')
+ break;
+ dest[i] = '0';
+ if (i == 0) {
+ dest[0] = '1';
+ (*decpt)++;
+ break;
}
}
}
-#endif /* CONFIG_PRINTF_RNDN */
+ return n_digits; /* truncate the 2 extra digits */
+#else
+ /* No disambiguation available, eg: __wasi__ targets */
+ return js_ecvt1(d, n_digits, dest, size, decpt);
+#endif
}
- js_ecvt1(d, n_digits, decpt, sign, buf, rounding_mode,
- buf_tmp, sizeof(buf_tmp));
- return n_digits;
-}
-
-static int js_fcvt1(char (*buf)[JS_DTOA_BUF_SIZE], double d, int n_digits,
- int rounding_mode)
-{
- int n;
- if (rounding_mode != FE_TONEAREST)
- fesetround(rounding_mode);
- n = snprintf(*buf, sizeof(*buf), "%.*f", n_digits, d);
- if (rounding_mode != FE_TONEAREST)
- fesetround(FE_TONEAREST);
- assert(n < sizeof(*buf));
- return n;
}
-static void js_fcvt(char (*buf)[JS_DTOA_BUF_SIZE], double d, int n_digits)
-{
- int rounding_mode;
- rounding_mode = FE_TONEAREST;
-#ifdef CONFIG_PRINTF_RNDN
- {
- int n1, n2;
- char buf1[JS_DTOA_BUF_SIZE];
- char buf2[JS_DTOA_BUF_SIZE];
-
- /* The JS rounding is specified as round to nearest ties away from
- zero (RNDNA), but in printf the "ties" case is not specified
- (for example it is RNDN for glibc, RNDNA for Windows), so we
- must round manually. */
- n1 = js_fcvt1(&buf1, d, n_digits + 1, FE_TONEAREST);
- rounding_mode = FE_TONEAREST;
- /* XXX: could use 2 digits to reduce the average running time */
- if (buf1[n1 - 1] == '5') {
- n1 = js_fcvt1(&buf1, d, n_digits + 1, FE_DOWNWARD);
- n2 = js_fcvt1(&buf2, d, n_digits + 1, FE_UPWARD);
- if (n1 == n2 && memcmp(buf1, buf2, n1) == 0) {
- /* exact result: round away from zero */
- if (buf1[0] == '-')
- rounding_mode = FE_DOWNWARD;
- else
- rounding_mode = FE_UPWARD;
+/* `js_fcvt`: convert a floating point value to %f format using RNDNA
+ `d` is finite and positive or zero.
+ `n_digits` number of decimal places in range 0..100
+ Return the number of characters produced in `dest`.
+ */
+static size_t js_fcvt(double d, int n_digits,
+ char dest[minimum_length(JS_FCVT_BUF_SIZE)], size_t size)
+{
+#if defined(FE_DOWNWARD) && defined(FE_TONEAREST)
+ int i, n1;
+ /* generate 2 extra digits: 99% chances to avoid 2 calls */
+ n1 = snprintf(dest, size, "%.*f", n_digits + 2, d) - 2;
+ if (dest[n1] >= '5') {
+ if (dest[n1] == '5' && dest[n1 + 1] == '0') {
+ /* close to half-way: try rounding toward 0 */
+ fesetround(FE_DOWNWARD);
+ n1 = snprintf(dest, size, "%.*f", n_digits + 2, d) - 2;
+ fesetround(FE_TONEAREST);
+ }
+ if (dest[n1] >= '5') { /* number should be rounded up */
+ /* d is either exactly half way or greater: round the string manually */
+ for (i = n1 - 1;; i--) {
+ /* ignore the locale specific decimal point */
+ if (is_digit(dest[i])) {
+ if (dest[i]++ < '9')
+ break;
+ dest[i] = '0';
+ if (i == 0) {
+ dest[0] = '1';
+ dest[n1] = '0';
+ dest[n1 - n_digits - 1] = '0';
+ dest[n1 - n_digits] = '.';
+ n1++;
+ break;
+ }
+ }
}
}
}
-#endif /* CONFIG_PRINTF_RNDN */
- js_fcvt1(buf, d, n_digits, rounding_mode);
+ /* truncate the extra 2 digits and the decimal point if !n_digits */
+ n1 -= !n_digits;
+ //dest[n1] = '\0'; // optional
+ return n1;
+#else
+ /* No disambiguation available, eg: __wasi__ targets */
+ return snprintf(dest, size, "%.*f", n_digits, d);
+#endif
}
-/* radix != 10 is only supported with flags = JS_DTOA_VAR_FORMAT */
-/* use as many digits as necessary */
-#define JS_DTOA_VAR_FORMAT (0 << 0)
-/* use n_digits significant digits (1 <= n_digits <= 101) */
-#define JS_DTOA_FIXED_FORMAT (1 << 0)
-/* force fractional format: [-]dd.dd with n_digits fractional digits */
-#define JS_DTOA_FRAC_FORMAT (2 << 0)
-/* force exponential notation either in fixed or variable format */
-#define JS_DTOA_FORCE_EXP (1 << 2)
-
-/* XXX: slow and maybe not fully correct. Use libbf when it is fast enough.
- XXX: radix != 10 is only supported for small integers
-*/
-static void js_dtoa1(char (*buf)[JS_DTOA_BUF_SIZE], double d,
- int radix, int n_digits, int flags)
+static JSValue js_dtoa_infinite(JSContext *ctx, double d)
+{
+ // TODO(chqrlie) use atoms for NaN and Infinite?
+ if (isnan(d))
+ return js_new_string8(ctx, "NaN");
+ if (d < 0)
+ return js_new_string8(ctx, "-Infinity");
+ else
+ return js_new_string8(ctx, "Infinity");
+}
+
+#define JS_DTOA_TOSTRING 0 /* use as many digits as necessary */
+#define JS_DTOA_EXPONENTIAL 1 /* use exponential notation either fixed or variable digits */
+#define JS_DTOA_FIXED 2 /* force fixed number of fractional digits */
+#define JS_DTOA_PRECISION 3 /* use n_digits significant digits (1 <= n_digits <= 101) */
+
+/* `js_dtoa`: convert a floating point number to a string
+ - `mode`: one of the 4 supported formats
+ - `n_digits`: digit number according to mode
+ - TOSTRING: 0 only. As many digits as necessary
+ - EXPONENTIAL: 0 as many decimals as necessary
+ - 1..101 number of significant digits
+ - FIXED: 0..100 number of decimal places
+ - PRECISION: 1..101 number of significant digits
+ */
+// XXX: should use libbf or quickjs-printf.
+static JSValue js_dtoa(JSContext *ctx, double d, int n_digits, int mode)
{
- char *q;
+ char buf[JS_DTOA_BUF_SIZE];
+ size_t len;
+ char *start;
+ int sign, decpt, exp, i, k, n, n_max;
- if (!isfinite(d)) {
- if (isnan(d)) {
- pstrcpy(*buf, sizeof(*buf), "NaN");
- } else if (d < 0) {
- pstrcpy(*buf, sizeof(*buf), "-Infinity");
- } else {
- pstrcpy(*buf, sizeof(*buf), "Infinity");
- }
- } else if (flags == JS_DTOA_VAR_FORMAT) {
- int64_t i64;
- char buf1[70], *ptr;
- if (d > (double)MAX_SAFE_INTEGER || d < (double)-MAX_SAFE_INTEGER)
- goto generic_conv;
- i64 = (int64_t)d;
- if (d != i64)
- goto generic_conv;
- /* fast path for integers */
- ptr = i64toa(buf1 + sizeof(buf1), i64, radix);
- pstrcpy(*buf, sizeof(*buf), ptr);
- } else {
- if (d == 0.0)
- d = 0.0; /* convert -0 to 0 */
- if (flags == JS_DTOA_FRAC_FORMAT) {
- js_fcvt(buf, d, n_digits);
- } else {
- char buf1[JS_DTOA_BUF_SIZE];
- int sign, decpt, k, n, i, p, n_max;
- BOOL is_fixed;
- generic_conv:
- is_fixed = ((flags & 3) == JS_DTOA_FIXED_FORMAT);
- if (is_fixed) {
- n_max = n_digits;
- } else {
- n_max = 21;
- }
- /* the number has k digits (k >= 1) */
- k = js_ecvt(d, n_digits, &decpt, &sign, buf1, is_fixed);
- n = decpt; /* d=10^(n-k)*(buf1) i.e. d= < x.yyyy 10^(n-1) */
- q = *buf;
- if (sign)
- *q++ = '-';
- if (flags & JS_DTOA_FORCE_EXP)
- goto force_exp;
- if (n >= 1 && n <= n_max) {
- if (k <= n) {
- memcpy(q, buf1, k);
- q += k;
- for(i = 0; i < (n - k); i++)
- *q++ = '0';
- *q = '\0';
- } else {
- /* k > n */
- memcpy(q, buf1, n);
- q += n;
- *q++ = '.';
- for(i = 0; i < (k - n); i++)
- *q++ = buf1[n + i];
- *q = '\0';
- }
- } else if (n >= -5 && n <= 0) {
- *q++ = '0';
- *q++ = '.';
- for(i = 0; i < -n; i++)
- *q++ = '0';
- memcpy(q, buf1, k);
- q += k;
- *q = '\0';
+ if (!isfinite(d))
+ return js_dtoa_infinite(ctx, d);
+
+ sign = (d < 0);
+ start = buf + 8;
+ d = fabs(d); /* also converts -0 to 0 */
+
+ if (mode != JS_DTOA_EXPONENTIAL && n_digits == 0) {
+ /* fast path for exact integers in variable format:
+ clip to MAX_SAFE_INTEGER because to ensure insignificant
+ digits are generated as 0.
+ used for JS_DTOA_TOSTRING and JS_DTOA_FIXED without decimals.
+ */
+ if (d <= (double)MAX_SAFE_INTEGER) {
+ uint64_t u64 = (uint64_t)d;
+ if (d == u64) {
+ len = u64toa(start, u64);
+ goto done;
+ }
+ }
+ }
+ if (mode == JS_DTOA_FIXED) {
+ len = js_fcvt(d, n_digits, start, sizeof(buf) - 8);
+ // TODO(chqrlie) patch the locale specific decimal point
+ goto done;
+ }
+
+ n_max = (n_digits > 0) ? n_digits : 21;
+ /* the number has k digits (1 <= k <= n_max) */
+ k = js_ecvt(d, n_digits, start, sizeof(buf) - 8, &decpt);
+ /* buffer contents:
+ 0: first digit
+ 1: '.' decimal point
+ 2..k: (k-1) additional digits
+ */
+ n = decpt; /* d=10^(n-k)*(buf1) i.e. d= < x.yyyy 10^(n-1) */
+ if (mode != JS_DTOA_EXPONENTIAL) {
+ /* mode is JS_DTOA_PRECISION or JS_DTOA_TOSTRING */
+ if (n >= 1 && n <= n_max) {
+ /* between 1 and n_max digits before the decimal point */
+ if (k <= n) {
+ /* all digits before the point, append zeros */
+ start[1] = start[0];
+ start++;
+ for(i = k; i < n; i++)
+ start[i] = '0';
+ len = n;
} else {
- force_exp:
- /* exponential notation */
- *q++ = buf1[0];
- if (k > 1) {
- *q++ = '.';
- for(i = 1; i < k; i++)
- *q++ = buf1[i];
- }
- *q++ = 'e';
- p = n - 1;
- if (p >= 0)
- *q++ = '+';
- snprintf(q, *buf + sizeof(*buf) - q, "%d", p);
+ /* k > n: move digits before the point */
+ for(i = 1; i < n; i++)
+ start[i] = start[i + 1];
+ start[i] = '.';
+ len = 1 + k;
}
+ goto done;
+ }
+ if (n >= -5 && n <= 0) {
+ /* insert -n leading 0 decimals and a '0.' prefix */
+ n = -n;
+ start[1] = start[0];
+ start -= n + 1;
+ start[0] = '0';
+ start[1] = '.';
+ for(i = 0; i < n; i++)
+ start[2 + i] = '0';
+ len = 2 + k + n;
+ goto done;
}
}
-}
+ /* exponential notation */
+ exp = n - 1;
+ /* count the digits and the decimal point if at least one decimal */
+ len = k + (k > 1);
+ start[1] = '.'; /* patch the locale specific decimal point */
+ start[len] = 'e';
+ start[len + 1] = '+';
+ if (exp < 0) {
+ start[len + 1] = '-';
+ exp = -exp;
+ }
+ len += 2 + 1 + (exp > 9) + (exp > 99);
+ for (i = len - 1; exp > 9;) {
+ int quo = exp / 10;
+ start[i--] = (char)('0' + exp % 10);
+ exp = quo;
+ }
+ start[i] = (char)('0' + exp);
-static JSValue js_dtoa(JSContext *ctx,
- double d, int radix, int n_digits, int flags)
-{
- char buf[JS_DTOA_BUF_SIZE];
- js_dtoa1(&buf, d, radix, n_digits, flags);
- return JS_NewString(ctx, buf);
+ done:
+ start[-1] = '-'; /* prepend the sign if negative */
+ return js_new_string8_len(ctx, start - sign, len + sign);
}
+/* `js_dtoa_radix`: convert a floating point number using a specific base
+ - `d` must be finite
+ - `radix` must be in range 2..36
+ */
static JSValue js_dtoa_radix(JSContext *ctx, double d, int radix)
{
- char buf[2200], *ptr, *ptr2;
- /* d is finite */
- int sign = d < 0;
- int digit;
+ char buf[2200], *ptr, *ptr2, *ptr3;
+ int sign, digit;
double frac, d0;
- int64_t n0 = 0;
+ int64_t n0;
+
+ if (!isfinite(d))
+ return js_dtoa_infinite(ctx, d);
+
+ sign = (d < 0);
d = fabs(d);
d0 = trunc(d);
+ n0 = 0;
frac = d - d0;
- ptr = buf + 1100;
- *ptr = '\0';
+ ptr2 = buf + 1100; /* ptr2 points to the end of the string */
+ ptr = ptr2; /* ptr points to the beginning of the string */
if (d0 <= MAX_SAFE_INTEGER) {
int64_t n = n0 = (int64_t)d0;
while (n >= radix) {
digit = n % radix;
n = n / radix;
- *--ptr = digits[digit];
+ *--ptr = digits36[digit];
}
- *--ptr = digits[(int)n];
+ *--ptr = digits36[(size_t)n];
} else {
/* no decimals */
while (d0 >= radix) {
@@ -11719,66 +11685,77 @@ static JSValue js_dtoa_radix(JSContext *ctx, double d, int radix)
d0 = trunc(d0 / radix);
if (d0 >= MAX_SAFE_INTEGER)
digit = 0;
- *--ptr = digits[digit];
+ *--ptr = digits36[digit];
}
- *--ptr = digits[(int)d0];
+ *--ptr = digits36[(size_t)d0];
goto done;
}
if (frac != 0) {
double log2_radix = log2(radix);
double prec = 1023 + 51; // handle subnormals
- ptr2 = buf + 1100;
*ptr2++ = '.';
while (frac != 0 && n0 <= MAX_SAFE_INTEGER/2 && prec > 0) {
frac *= radix;
digit = trunc(frac);
frac -= digit;
- *ptr2++ = digits[digit];
+ *ptr2++ = digits36[digit];
n0 = n0 * radix + digit;
prec -= log2_radix;
}
- *ptr2 = '\0';
if (frac * radix >= radix / 2) {
- char nine = digits[radix - 1];
- // round to closest
- while (ptr2[-1] == nine)
- *--ptr2 = '\0';
+ /* round up the string representation manually */
+ char nine = digits36[radix - 1];
+ while (ptr2[-1] == nine) {
+ /* strip trailing '9' or equivalent digits */
+ ptr2--;
+ }
if (ptr2[-1] == '.') {
- *--ptr2 = '\0';
- while (ptr2[-1] == nine)
- *--ptr2 = '0';
+ /* strip the 'decimal' point */
+ ptr2--;
+ /* increment the integral part */
+ for (ptr3 = ptr2;;) {
+ if (ptr3[-1] != nine) {
+ ptr3[-1] = (ptr3[-1] == '9') ? 'a' : ptr3[-1] + 1;
+ break;
+ }
+ *--ptr3 = '0';
+ if (ptr3 <= ptr) {
+ /* prepend a '1' if number was all nines */
+ *--ptr = '1';
+ break;
+ }
+ }
+ } else {
+ /* increment the last fractional digit */
+ ptr2[-1] = (ptr2[-1] == '9') ? 'a' : ptr2[-1] + 1;
}
- if (ptr2 - 1 == ptr)
- *--ptr = '1';
- else
- ptr2[-1] += 1;
} else {
+ /* strip trailing fractional zeros */
while (ptr2[-1] == '0')
- *--ptr2 = '\0';
- if (ptr2[-1] == '.')
- *--ptr2 = '\0';
+ ptr2--;
+ /* strip the 'decimal' point if last */
+ ptr2 -= (ptr2[-1] == '.');
}
}
done:
ptr[-1] = '-';
ptr -= sign;
- return JS_NewString(ctx, ptr);
+ return js_new_string8_len(ctx, ptr, ptr2 - ptr);
}
-JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToPropertyKey)
+JSValue JS_ToStringInternal(JSContext *ctx, JSValue val, bool is_ToPropertyKey)
{
uint32_t tag;
- const char *str;
char buf[32];
+ size_t len;
tag = JS_VALUE_GET_NORM_TAG(val);
switch(tag) {
case JS_TAG_STRING:
- return JS_DupValue(ctx, val);
+ return js_dup(val);
case JS_TAG_INT:
- snprintf(buf, sizeof(buf), "%d", JS_VALUE_GET_INT(val));
- str = buf;
- goto new_string;
+ len = i32toa(buf, JS_VALUE_GET_INT(val));
+ return js_new_string8_len(ctx, buf, len);
case JS_TAG_BOOL:
return JS_AtomToString(ctx, JS_VALUE_GET_BOOL(val) ?
JS_ATOM_true : JS_ATOM_false);
@@ -11800,35 +11777,27 @@ JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToProperty
}
break;
case JS_TAG_FUNCTION_BYTECODE:
- str = "[function bytecode]";
- goto new_string;
+ return js_new_string8(ctx, "[function bytecode]");
case JS_TAG_SYMBOL:
if (is_ToPropertyKey) {
- return JS_DupValue(ctx, val);
+ return js_dup(val);
} else {
return JS_ThrowTypeError(ctx, "cannot convert symbol to string");
}
case JS_TAG_FLOAT64:
- return js_dtoa(ctx, JS_VALUE_GET_FLOAT64(val), 10, 0,
- JS_DTOA_VAR_FORMAT);
+ return js_dtoa(ctx, JS_VALUE_GET_FLOAT64(val), 0, JS_DTOA_TOSTRING);
case JS_TAG_BIG_INT:
- return ctx->rt->bigint_ops.to_string(ctx, val);
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- return ctx->rt->bigfloat_ops.to_string(ctx, val);
- case JS_TAG_BIG_DECIMAL:
- return ctx->rt->bigdecimal_ops.to_string(ctx, val);
-#endif
+ return js_bigint_to_string(ctx, val);
+ case JS_TAG_UNINITIALIZED:
+ return js_new_string8(ctx, "[uninitialized]");
default:
- str = "[unsupported type]";
- new_string:
- return JS_NewString(ctx, str);
+ return js_new_string8(ctx, "[unsupported type]");
}
}
-JSValue JS_ToString(JSContext *ctx, JSValueConst val)
+JSValue JS_ToString(JSContext *ctx, JSValue val)
{
- return JS_ToStringInternal(ctx, val, FALSE);
+ return JS_ToStringInternal(ctx, val, false);
}
static JSValue JS_ToStringFree(JSContext *ctx, JSValue val)
@@ -11846,12 +11815,12 @@ static JSValue JS_ToLocaleStringFree(JSContext *ctx, JSValue val)
return JS_InvokeFree(ctx, val, JS_ATOM_toLocaleString, 0, NULL);
}
-JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val)
+JSValue JS_ToPropertyKey(JSContext *ctx, JSValue val)
{
- return JS_ToStringInternal(ctx, val, TRUE);
+ return JS_ToStringInternal(ctx, val, true);
}
-static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val)
+static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValue val)
{
uint32_t tag = JS_VALUE_GET_TAG(val);
if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED)
@@ -11859,7 +11828,7 @@ static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val)
return JS_ToString(ctx, val);
}
-static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
+static JSValue JS_ToQuotedString(JSContext *ctx, JSValue val1)
{
JSValue val;
JSString *p;
@@ -11907,7 +11876,7 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
default:
if (c < 32 || is_surrogate(c)) {
snprintf(buf, sizeof(buf), "\\u%04x", c);
- if (string_buffer_puts8(b, buf))
+ if (string_buffer_write8(b, (uint8_t*)buf, 6))
goto fail;
} else {
if (string_buffer_putc(b, c))
@@ -11940,7 +11909,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
JSShape *sh;
JSShapeProperty *prs;
JSProperty *pr;
- BOOL is_first = TRUE;
+ bool is_first = true;
/* XXX: should encode atoms with special characters */
sh = p->shape; /* the shape can be NULL while freeing an object */
@@ -11965,7 +11934,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
switch (p->class_id) {
case JS_CLASS_ARRAY:
case JS_CLASS_ARGUMENTS:
- JS_DumpValueShort(rt, p->u.array.u.values[i]);
+ JS_DumpValue(rt, p->u.array.u.values[i]);
break;
case JS_CLASS_UINT8C_ARRAY:
case JS_CLASS_INT8_ARRAY:
@@ -11976,6 +11945,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
case JS_CLASS_UINT32_ARRAY:
case JS_CLASS_BIG_INT64_ARRAY:
case JS_CLASS_BIG_UINT64_ARRAY:
+ case JS_CLASS_FLOAT16_ARRAY:
case JS_CLASS_FLOAT32_ARRAY:
case JS_CLASS_FLOAT64_ARRAY:
{
@@ -12010,9 +11980,9 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
js_autoinit_get_id(pr),
(void *)pr->u.init.opaque);
} else {
- JS_DumpValueShort(rt, pr->u.value);
+ JS_DumpValue(rt, pr->u.value);
}
- is_first = FALSE;
+ is_first = false;
}
}
printf(" }");
@@ -12026,11 +11996,11 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
printf(" Closure:");
for(i = 0; i < b->closure_var_count; i++) {
printf(" ");
- JS_DumpValueShort(rt, var_refs[i]->value);
+ JS_DumpValue(rt, var_refs[i]->value);
}
if (p->u.func.home_object) {
printf(" HomeObject: ");
- JS_DumpValueShort(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object));
+ JS_DumpValue(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object));
}
}
}
@@ -12069,8 +12039,7 @@ static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
}
}
-static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
- JSValueConst val)
+static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValue val)
{
uint32_t tag = JS_VALUE_GET_NORM_TAG(val);
const char *str;
@@ -12104,7 +12073,7 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
break;
case JS_TAG_BIG_INT:
{
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
+ JSBigInt *p = JS_VALUE_GET_PTR(val);
char *str;
str = bf_ftoa(NULL, &p->num, 10, 0,
BF_RNDZ | BF_FTOA_FORMAT_FRAC);
@@ -12112,28 +12081,6 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
bf_realloc(&rt->bf_ctx, str, 0);
}
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- char *str;
- str = bf_ftoa(NULL, &p->num, 16, BF_PREC_INF,
- BF_RNDZ | BF_FTOA_FORMAT_FREE | BF_FTOA_ADD_PREFIX);
- printf("%sl", str);
- bf_free(&rt->bf_ctx, str);
- }
- break;
- case JS_TAG_BIG_DECIMAL:
- {
- JSBigDecimal *p = JS_VALUE_GET_PTR(val);
- char *str;
- str = bfdec_ftoa(NULL, &p->num, BF_PREC_INF,
- BF_RNDZ | BF_FTOA_FORMAT_FREE);
- printf("%sm", str);
- bf_free(&rt->bf_ctx, str);
- }
- break;
-#endif
case JS_TAG_STRING:
{
JSString *p;
@@ -12145,7 +12092,11 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
{
JSFunctionBytecode *b = JS_VALUE_GET_PTR(val);
char buf[ATOM_GET_STR_BUF_SIZE];
- printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));
+ if (b->func_name) {
+ printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));
+ } else {
+ printf("[bytecode (anonymous)]");
+ }
}
break;
case JS_TAG_OBJECT:
@@ -12174,46 +12125,32 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
}
}
-static __maybe_unused void JS_DumpValue(JSContext *ctx,
- JSValueConst val)
-{
- JS_DumpValueShort(ctx->rt, val);
-}
-
-static __maybe_unused void JS_PrintValue(JSContext *ctx,
- const char *str,
- JSValueConst val)
+/* return -1 if exception (proxy case) or true/false */
+int JS_IsArray(JSContext *ctx, JSValue val)
{
- printf("%s=", str);
- JS_DumpValueShort(ctx->rt, val);
- printf("\n");
-}
-
-/* return -1 if exception (proxy case) or TRUE/FALSE */
-// TODO: should take flags to make proxy resolution and exceptions optional
-int JS_IsArray(JSContext *ctx, JSValueConst val)
-{
- if (js_resolve_proxy(ctx, &val, TRUE))
- return -1;
+ JSObject *p;
if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) {
- JSObject *p = JS_VALUE_GET_OBJ(val);
- return p->class_id == JS_CLASS_ARRAY;
+ p = JS_VALUE_GET_OBJ(val);
+ if (unlikely(p->class_id == JS_CLASS_PROXY))
+ return js_proxy_isArray(ctx, val);
+ else
+ return p->class_id == JS_CLASS_ARRAY;
} else {
- return FALSE;
+ return false;
}
}
-static double js_pow(double a, double b)
+static double js_math_pow(double a, double b)
{
if (unlikely(!isfinite(b)) && fabs(a) == 1) {
/* not compatible with IEEE 754 */
- return JS_FLOAT64_NAN;
+ return NAN;
} else {
return pow(a, b);
}
}
-JSValue JS_NewBigInt64_1(JSContext *ctx, int64_t v)
+JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)
{
JSValue val;
bf_t *a;
@@ -12228,39 +12165,69 @@ JSValue JS_NewBigInt64_1(JSContext *ctx, int64_t v)
return val;
}
-JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)
+JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)
{
- if (is_math_mode(ctx) &&
- v >= -MAX_SAFE_INTEGER && v <= MAX_SAFE_INTEGER) {
- return JS_NewInt64(ctx, v);
- } else {
- return JS_NewBigInt64_1(ctx, v);
+ JSValue val;
+ bf_t *a;
+ val = JS_NewBigInt(ctx);
+ if (JS_IsException(val))
+ return val;
+ a = JS_GetBigInt(val);
+ if (bf_set_ui(a, v)) {
+ JS_FreeValue(ctx, val);
+ return JS_ThrowOutOfMemory(ctx);
}
+
+ return val;
}
-JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)
+/* if the returned bigint is allocated it is equal to
+ 'buf'. Otherwise it is a pointer to the bigint in 'val'. Return
+ NULL in case of error. */
+// TODO(bnoordhuis) Merge with JS_ToBigInt()
+static bf_t *JS_ToBigInt1(JSContext *ctx, bf_t *buf, JSValue val)
{
- JSValue val;
- if (is_math_mode(ctx) && v <= MAX_SAFE_INTEGER) {
- val = JS_NewInt64(ctx, v);
- } else {
- bf_t *a;
- val = JS_NewBigInt(ctx);
- if (JS_IsException(val))
- return val;
- a = JS_GetBigInt(val);
- if (bf_set_ui(a, v)) {
- JS_FreeValue(ctx, val);
- return JS_ThrowOutOfMemory(ctx);
+ uint32_t tag;
+ bf_t *r;
+ JSBigInt *p;
+
+ tag = JS_VALUE_GET_NORM_TAG(val);
+ switch(tag) {
+ case JS_TAG_INT:
+ case JS_TAG_BOOL:
+ case JS_TAG_NULL:
+ r = buf;
+ bf_init(ctx->bf_ctx, r);
+ if (bf_set_si(r, JS_VALUE_GET_INT(val)))
+ goto fail;
+ break;
+ case JS_TAG_FLOAT64:
+ r = buf;
+ bf_init(ctx->bf_ctx, r);
+ if (bf_set_float64(r, JS_VALUE_GET_FLOAT64(val))) {
+ fail:
+ bf_delete(r);
+ return NULL;
}
+ break;
+ case JS_TAG_BIG_INT:
+ p = JS_VALUE_GET_PTR(val);
+ r = &p->num;
+ break;
+ case JS_TAG_UNDEFINED:
+ default:
+ r = buf;
+ bf_init(ctx->bf_ctx, r);
+ bf_set_nan(r);
+ break;
}
- return val;
+ return r;
}
/* return NaN if bad bigint literal */
static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val)
{
- const char *str, *p;
+ const char *str;
size_t len;
int flags;
@@ -12268,25 +12235,11 @@ static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val)
JS_FreeValue(ctx, val);
if (!str)
return JS_EXCEPTION;
- p = str;
- p += skip_spaces(p);
- if ((p - str) == len) {
- val = JS_NewBigInt64(ctx, 0);
- } else {
- flags = ATOD_INT_ONLY | ATOD_ACCEPT_BIN_OCT | ATOD_TYPE_BIG_INT;
-#ifdef CONFIG_BIGNUM
- if (is_math_mode(ctx))
- flags |= ATOD_MODE_BIGINT;
-#endif
- val = js_atof(ctx, p, &p, 0, flags);
- p += skip_spaces(p);
- if (!JS_IsException(val)) {
- if ((p - str) != len) {
- JS_FreeValue(ctx, val);
- val = JS_NAN;
- }
- }
- }
+ flags = ATOD_WANT_BIG_INT |
+ ATOD_TRIM_SPACES | ATOD_ACCEPT_EMPTY |
+ ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT |
+ ATOD_DECIMAL_AFTER_SIGN | ATOD_NO_TRAILING_CHARS;
+ val = js_atof(ctx, str, len, NULL, 10, flags);
JS_FreeCString(ctx, str);
return val;
}
@@ -12295,17 +12248,17 @@ static JSValue JS_StringToBigIntErr(JSContext *ctx, JSValue val)
{
val = JS_StringToBigInt(ctx, val);
if (JS_VALUE_IS_NAN(val))
- return JS_ThrowSyntaxError(ctx, "invalid bigint literal");
+ return JS_ThrowSyntaxError(ctx, "invalid BigInt literal");
return val;
}
-/* if the returned bigfloat is allocated it is equal to
- 'buf'. Otherwise it is a pointer to the bigfloat in 'val'. */
+/* if the returned bigint is allocated it is equal to
+ 'buf'. Otherwise it is a pointer to the bigint in 'val'. */
static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val)
{
uint32_t tag;
bf_t *r;
- JSBigFloat *p;
+ JSBigInt *p;
redo:
tag = JS_VALUE_GET_NORM_TAG(val);
@@ -12313,45 +12266,17 @@ static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val)
case JS_TAG_INT:
case JS_TAG_NULL:
case JS_TAG_UNDEFINED:
- if (!is_math_mode(ctx))
- goto fail;
- /* fall tru */
+ case JS_TAG_FLOAT64:
+ goto fail;
case JS_TAG_BOOL:
r = buf;
bf_init(ctx->bf_ctx, r);
bf_set_si(r, JS_VALUE_GET_INT(val));
break;
- case JS_TAG_FLOAT64:
- {
- double d = JS_VALUE_GET_FLOAT64(val);
- if (!is_math_mode(ctx))
- goto fail;
- if (!isfinite(d))
- goto fail;
- r = buf;
- bf_init(ctx->bf_ctx, r);
- d = trunc(d);
- bf_set_float64(r, d);
- }
- break;
case JS_TAG_BIG_INT:
p = JS_VALUE_GET_PTR(val);
r = &p->num;
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- if (!is_math_mode(ctx))
- goto fail;
- p = JS_VALUE_GET_PTR(val);
- if (!bf_is_finite(&p->num))
- goto fail;
- r = buf;
- bf_init(ctx->bf_ctx, r);
- bf_set(r, &p->num);
- bf_rint(r, BF_RNDZ);
- JS_FreeValue(ctx, val);
- break;
-#endif
case JS_TAG_STRING:
val = JS_StringToBigIntErr(ctx, val);
if (JS_IsException(val))
@@ -12365,15 +12290,15 @@ static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val)
default:
fail:
JS_FreeValue(ctx, val);
- JS_ThrowTypeError(ctx, "cannot convert to bigint");
+ JS_ThrowTypeError(ctx, "cannot convert to BigInt");
return NULL;
}
return r;
}
-static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val)
+static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValue val)
{
- return JS_ToBigIntFree(ctx, buf, JS_DupValue(ctx, val));
+ return JS_ToBigIntFree(ctx, buf, js_dup(val));
}
static __maybe_unused JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val)
@@ -12410,8 +12335,7 @@ static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf)
if (a == buf) {
bf_delete(a);
} else {
- JSBigFloat *p = (JSBigFloat *)((uint8_t *)a -
- offsetof(JSBigFloat, num));
+ JSBigInt *p = (JSBigInt *)((uint8_t *)a - offsetof(JSBigInt, num));
JS_FreeValue(ctx, JS_MKPTR(JS_TAG_BIG_INT, p));
}
}
@@ -12431,25 +12355,19 @@ static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val)
return 0;
}
-int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)
+int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValue val)
{
- return JS_ToBigInt64Free(ctx, pres, JS_DupValue(ctx, val));
+ return JS_ToBigInt64Free(ctx, pres, js_dup(val));
}
-static JSBigFloat *js_new_bf(JSContext *ctx)
+int JS_ToBigUint64(JSContext *ctx, uint64_t *pres, JSValue val)
{
- JSBigFloat *p;
- p = js_malloc(ctx, sizeof(*p));
- if (!p)
- return NULL;
- p->header.ref_count = 1;
- bf_init(ctx->bf_ctx, &p->num);
- return p;
+ return JS_ToBigInt64Free(ctx, (int64_t *)pres, js_dup(val));
}
static JSValue JS_NewBigInt(JSContext *ctx)
{
- JSBigFloat *p;
+ JSBigInt *p;
p = js_malloc(ctx, sizeof(*p));
if (!p)
return JS_EXCEPTION;
@@ -12458,34 +12376,24 @@ static JSValue JS_NewBigInt(JSContext *ctx)
return JS_MKPTR(JS_TAG_BIG_INT, p);
}
-static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,
- BOOL convert_to_safe_integer)
+static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val)
{
- int64_t v;
- bf_t *a;
-
if (JS_VALUE_GET_TAG(val) != JS_TAG_BIG_INT)
return val; /* fail safe */
- a = JS_GetBigInt(val);
- if (convert_to_safe_integer && bf_get_int64(&v, a, 0) == 0 &&
- v >= -MAX_SAFE_INTEGER && v <= MAX_SAFE_INTEGER) {
- JS_FreeValue(ctx, val);
- return JS_NewInt64(ctx, v);
- } else if (a->expn == BF_EXP_ZERO && a->sign) {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- assert(p->header.ref_count == 1);
+ bf_t *a = JS_GetBigInt(val);
+ if (a->expn == BF_EXP_ZERO && a->sign) {
+ assert(((JSBigInt*)JS_VALUE_GET_PTR(val))->header.ref_count == 1);
a->sign = 0;
}
return val;
}
-/* Convert the big int to a safe integer if in math mode. normalize
- the zero representation. Could also be used to convert the bigint
+/* Nnormalize the zero representation. Could also be used to convert the bigint
to a short bigint value. The reference count of the value must be
1. Cannot fail */
static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val)
{
- return JS_CompactBigInt1(ctx, val, is_math_mode(ctx));
+ return JS_CompactBigInt1(ctx, val);
}
static JSValue throw_bf_exception(JSContext *ctx, int status)
@@ -12503,526 +12411,6 @@ static JSValue throw_bf_exception(JSContext *ctx, int status)
return JS_ThrowRangeError(ctx, "%s", str);
}
-/* if the returned bigfloat is allocated it is equal to
- 'buf'. Otherwise it is a pointer to the bigfloat in 'val'. Return
- NULL in case of error. */
-static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val)
-{
- uint32_t tag;
- bf_t *r;
- JSBigFloat *p;
-
- tag = JS_VALUE_GET_NORM_TAG(val);
- switch(tag) {
- case JS_TAG_INT:
- case JS_TAG_BOOL:
- case JS_TAG_NULL:
- r = buf;
- bf_init(ctx->bf_ctx, r);
- if (bf_set_si(r, JS_VALUE_GET_INT(val)))
- goto fail;
- break;
- case JS_TAG_FLOAT64:
- r = buf;
- bf_init(ctx->bf_ctx, r);
- if (bf_set_float64(r, JS_VALUE_GET_FLOAT64(val))) {
- fail:
- bf_delete(r);
- return NULL;
- }
- break;
- case JS_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
-#endif
- p = JS_VALUE_GET_PTR(val);
- r = &p->num;
- break;
- case JS_TAG_UNDEFINED:
- default:
- r = buf;
- bf_init(ctx->bf_ctx, r);
- bf_set_nan(r);
- break;
- }
- return r;
-}
-
-#ifdef CONFIG_BIGNUM
-/* return NULL if invalid type */
-static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val)
-{
- uint32_t tag;
- JSBigDecimal *p;
- bfdec_t *r;
-
- tag = JS_VALUE_GET_NORM_TAG(val);
- switch(tag) {
- case JS_TAG_BIG_DECIMAL:
- p = JS_VALUE_GET_PTR(val);
- r = &p->num;
- break;
- default:
- JS_ThrowTypeError(ctx, "bigdecimal expected");
- r = NULL;
- break;
- }
- return r;
-}
-
-static JSValue JS_NewBigFloat(JSContext *ctx)
-{
- JSBigFloat *p;
- p = js_malloc(ctx, sizeof(*p));
- if (!p)
- return JS_EXCEPTION;
- p->header.ref_count = 1;
- bf_init(ctx->bf_ctx, &p->num);
- return JS_MKPTR(JS_TAG_BIG_FLOAT, p);
-}
-
-static JSValue JS_NewBigDecimal(JSContext *ctx)
-{
- JSBigDecimal *p;
- p = js_malloc(ctx, sizeof(*p));
- if (!p)
- return JS_EXCEPTION;
- p->header.ref_count = 1;
- bfdec_init(ctx->bf_ctx, &p->num);
- return JS_MKPTR(JS_TAG_BIG_DECIMAL, p);
-}
-
-/* must be kept in sync with JSOverloadableOperatorEnum */
-/* XXX: use atoms ? */
-static const char js_overloadable_operator_names[JS_OVOP_COUNT][4] = {
- "+",
- "-",
- "*",
- "/",
- "%",
- "**",
- "|",
- "&",
- "^",
- "<<",
- ">>",
- ">>>",
- "==",
- "<",
- "pos",
- "neg",
- "++",
- "--",
- "~",
-};
-
-static int get_ovop_from_opcode(OPCodeEnum op)
-{
- switch(op) {
- case OP_add:
- return JS_OVOP_ADD;
- case OP_sub:
- return JS_OVOP_SUB;
- case OP_mul:
- return JS_OVOP_MUL;
- case OP_div:
- return JS_OVOP_DIV;
- case OP_mod:
- case OP_math_mod:
- return JS_OVOP_MOD;
- case OP_pow:
- return JS_OVOP_POW;
- case OP_or:
- return JS_OVOP_OR;
- case OP_and:
- return JS_OVOP_AND;
- case OP_xor:
- return JS_OVOP_XOR;
- case OP_shl:
- return JS_OVOP_SHL;
- case OP_sar:
- return JS_OVOP_SAR;
- case OP_shr:
- return JS_OVOP_SHR;
- case OP_eq:
- case OP_neq:
- return JS_OVOP_EQ;
- case OP_lt:
- case OP_lte:
- case OP_gt:
- case OP_gte:
- return JS_OVOP_LESS;
- case OP_plus:
- return JS_OVOP_POS;
- case OP_neg:
- return JS_OVOP_NEG;
- case OP_inc:
- return JS_OVOP_INC;
- case OP_dec:
- return JS_OVOP_DEC;
- default:
- abort();
- }
-}
-
-/* return NULL if not present */
-static JSObject *find_binary_op(JSBinaryOperatorDef *def,
- uint32_t operator_index,
- JSOverloadableOperatorEnum op)
-{
- JSBinaryOperatorDefEntry *ent;
- int i;
- for(i = 0; i < def->count; i++) {
- ent = &def->tab[i];
- if (ent->operator_index == operator_index)
- return ent->ops[op];
- }
- return NULL;
-}
-
-/* return -1 if exception, 0 if no operator overloading, 1 if
- overloaded operator called */
-static __exception int js_call_binary_op_fallback(JSContext *ctx,
- JSValue *pret,
- JSValueConst op1,
- JSValueConst op2,
- OPCodeEnum op,
- BOOL is_numeric,
- int hint)
-{
- JSValue opset1_obj, opset2_obj, method, ret, new_op1, new_op2;
- JSOperatorSetData *opset1, *opset2;
- JSOverloadableOperatorEnum ovop;
- JSObject *p;
- JSValueConst args[2];
-
- if (!ctx->allow_operator_overloading)
- return 0;
-
- opset2_obj = JS_UNDEFINED;
- opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet);
- if (JS_IsException(opset1_obj))
- goto exception;
- if (JS_IsUndefined(opset1_obj))
- return 0;
- opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET);
- if (!opset1)
- goto exception;
-
- opset2_obj = JS_GetProperty(ctx, op2, JS_ATOM_Symbol_operatorSet);
- if (JS_IsException(opset2_obj))
- goto exception;
- if (JS_IsUndefined(opset2_obj)) {
- JS_FreeValue(ctx, opset1_obj);
- return 0;
- }
- opset2 = JS_GetOpaque2(ctx, opset2_obj, JS_CLASS_OPERATOR_SET);
- if (!opset2)
- goto exception;
-
- if (opset1->is_primitive && opset2->is_primitive) {
- JS_FreeValue(ctx, opset1_obj);
- JS_FreeValue(ctx, opset2_obj);
- return 0;
- }
-
- ovop = get_ovop_from_opcode(op);
-
- if (opset1->operator_counter == opset2->operator_counter) {
- p = opset1->self_ops[ovop];
- } else if (opset1->operator_counter > opset2->operator_counter) {
- p = find_binary_op(&opset1->left, opset2->operator_counter, ovop);
- } else {
- p = find_binary_op(&opset2->right, opset1->operator_counter, ovop);
- }
- if (!p) {
- JS_ThrowTypeError(ctx, "operator %s: no function defined",
- js_overloadable_operator_names[ovop]);
- goto exception;
- }
-
- if (opset1->is_primitive) {
- if (is_numeric) {
- new_op1 = JS_ToNumeric(ctx, op1);
- } else {
- new_op1 = JS_ToPrimitive(ctx, op1, hint);
- }
- if (JS_IsException(new_op1))
- goto exception;
- } else {
- new_op1 = JS_DupValue(ctx, op1);
- }
-
- if (opset2->is_primitive) {
- if (is_numeric) {
- new_op2 = JS_ToNumeric(ctx, op2);
- } else {
- new_op2 = JS_ToPrimitive(ctx, op2, hint);
- }
- if (JS_IsException(new_op2)) {
- JS_FreeValue(ctx, new_op1);
- goto exception;
- }
- } else {
- new_op2 = JS_DupValue(ctx, op2);
- }
-
- /* XXX: could apply JS_ToPrimitive() if primitive type so that the
- operator function does not get a value object */
-
- method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
- if (ovop == JS_OVOP_LESS && (op == OP_lte || op == OP_gt)) {
- args[0] = new_op2;
- args[1] = new_op1;
- } else {
- args[0] = new_op1;
- args[1] = new_op2;
- }
- ret = JS_CallFree(ctx, method, JS_UNDEFINED, 2, args);
- JS_FreeValue(ctx, new_op1);
- JS_FreeValue(ctx, new_op2);
- if (JS_IsException(ret))
- goto exception;
- if (ovop == JS_OVOP_EQ) {
- BOOL res = JS_ToBoolFree(ctx, ret);
- if (op == OP_neq)
- res ^= 1;
- ret = JS_NewBool(ctx, res);
- } else if (ovop == JS_OVOP_LESS) {
- if (JS_IsUndefined(ret)) {
- ret = JS_FALSE;
- } else {
- BOOL res = JS_ToBoolFree(ctx, ret);
- if (op == OP_lte || op == OP_gte)
- res ^= 1;
- ret = JS_NewBool(ctx, res);
- }
- }
- JS_FreeValue(ctx, opset1_obj);
- JS_FreeValue(ctx, opset2_obj);
- *pret = ret;
- return 1;
- exception:
- JS_FreeValue(ctx, opset1_obj);
- JS_FreeValue(ctx, opset2_obj);
- *pret = JS_UNDEFINED;
- return -1;
-}
-
-/* try to call the operation on the operatorSet field of 'obj'. Only
- used for "/" and "**" on the BigInt prototype in math mode */
-static __exception int js_call_binary_op_simple(JSContext *ctx,
- JSValue *pret,
- JSValueConst obj,
- JSValueConst op1,
- JSValueConst op2,
- OPCodeEnum op)
-{
- JSValue opset1_obj, method, ret, new_op1, new_op2;
- JSOperatorSetData *opset1;
- JSOverloadableOperatorEnum ovop;
- JSObject *p;
- JSValueConst args[2];
-
- opset1_obj = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_operatorSet);
- if (JS_IsException(opset1_obj))
- goto exception;
- if (JS_IsUndefined(opset1_obj))
- return 0;
- opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET);
- if (!opset1)
- goto exception;
- ovop = get_ovop_from_opcode(op);
-
- p = opset1->self_ops[ovop];
- if (!p) {
- JS_FreeValue(ctx, opset1_obj);
- return 0;
- }
-
- new_op1 = JS_ToNumeric(ctx, op1);
- if (JS_IsException(new_op1))
- goto exception;
- new_op2 = JS_ToNumeric(ctx, op2);
- if (JS_IsException(new_op2)) {
- JS_FreeValue(ctx, new_op1);
- goto exception;
- }
-
- method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
- args[0] = new_op1;
- args[1] = new_op2;
- ret = JS_CallFree(ctx, method, JS_UNDEFINED, 2, args);
- JS_FreeValue(ctx, new_op1);
- JS_FreeValue(ctx, new_op2);
- if (JS_IsException(ret))
- goto exception;
- JS_FreeValue(ctx, opset1_obj);
- *pret = ret;
- return 1;
- exception:
- JS_FreeValue(ctx, opset1_obj);
- *pret = JS_UNDEFINED;
- return -1;
-}
-
-/* return -1 if exception, 0 if no operator overloading, 1 if
- overloaded operator called */
-static __exception int js_call_unary_op_fallback(JSContext *ctx,
- JSValue *pret,
- JSValueConst op1,
- OPCodeEnum op)
-{
- JSValue opset1_obj, method, ret;
- JSOperatorSetData *opset1;
- JSOverloadableOperatorEnum ovop;
- JSObject *p;
-
- if (!ctx->allow_operator_overloading)
- return 0;
-
- opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet);
- if (JS_IsException(opset1_obj))
- goto exception;
- if (JS_IsUndefined(opset1_obj))
- return 0;
- opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET);
- if (!opset1)
- goto exception;
- if (opset1->is_primitive) {
- JS_FreeValue(ctx, opset1_obj);
- return 0;
- }
-
- ovop = get_ovop_from_opcode(op);
-
- p = opset1->self_ops[ovop];
- if (!p) {
- JS_ThrowTypeError(ctx, "no overloaded operator %s",
- js_overloadable_operator_names[ovop]);
- goto exception;
- }
- method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
- ret = JS_CallFree(ctx, method, JS_UNDEFINED, 1, &op1);
- if (JS_IsException(ret))
- goto exception;
- JS_FreeValue(ctx, opset1_obj);
- *pret = ret;
- return 1;
- exception:
- JS_FreeValue(ctx, opset1_obj);
- *pret = JS_UNDEFINED;
- return -1;
-}
-
-static int js_unary_arith_bigfloat(JSContext *ctx,
- JSValue *pres, OPCodeEnum op, JSValue op1)
-{
- bf_t a_s, *r, *a;
- int ret, v;
- JSValue res;
-
- if (op == OP_plus && !is_math_mode(ctx)) {
- JS_ThrowTypeError(ctx, "bigfloat argument with unary +");
- JS_FreeValue(ctx, op1);
- return -1;
- }
-
- res = JS_NewBigFloat(ctx);
- if (JS_IsException(res)) {
- JS_FreeValue(ctx, op1);
- return -1;
- }
- r = JS_GetBigFloat(res);
- a = JS_ToBigFloat(ctx, &a_s, op1);
- if (!a) {
- JS_FreeValue(ctx, res);
- JS_FreeValue(ctx, op1);
- return -1;
- }
- ret = 0;
- switch(op) {
- case OP_inc:
- case OP_dec:
- v = 2 * (op - OP_dec) - 1;
- ret = bf_add_si(r, a, v, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_plus:
- ret = bf_set(r, a);
- break;
- case OP_neg:
- ret = bf_set(r, a);
- bf_neg(r);
- break;
- default:
- abort();
- }
- if (a == &a_s)
- bf_delete(a);
- JS_FreeValue(ctx, op1);
- if (unlikely(ret & BF_ST_MEM_ERROR)) {
- JS_FreeValue(ctx, res);
- throw_bf_exception(ctx, ret);
- return -1;
- }
- *pres = res;
- return 0;
-}
-
-static int js_unary_arith_bigdecimal(JSContext *ctx,
- JSValue *pres, OPCodeEnum op, JSValue op1)
-{
- bfdec_t *r, *a;
- int ret, v;
- JSValue res;
-
- if (op == OP_plus && !is_math_mode(ctx)) {
- JS_ThrowTypeError(ctx, "bigdecimal argument with unary +");
- JS_FreeValue(ctx, op1);
- return -1;
- }
-
- res = JS_NewBigDecimal(ctx);
- if (JS_IsException(res)) {
- JS_FreeValue(ctx, op1);
- return -1;
- }
- r = JS_GetBigDecimal(res);
- a = JS_ToBigDecimal(ctx, op1);
- if (!a) {
- JS_FreeValue(ctx, res);
- JS_FreeValue(ctx, op1);
- return -1;
- }
- ret = 0;
- switch(op) {
- case OP_inc:
- case OP_dec:
- v = 2 * (op - OP_dec) - 1;
- ret = bfdec_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);
- break;
- case OP_plus:
- ret = bfdec_set(r, a);
- break;
- case OP_neg:
- ret = bfdec_set(r, a);
- bfdec_neg(r);
- break;
- default:
- abort();
- }
- JS_FreeValue(ctx, op1);
- if (unlikely(ret)) {
- JS_FreeValue(ctx, res);
- throw_bf_exception(ctx, ret);
- return -1;
- }
- *pres = res;
- return 0;
-}
-
-#endif /* CONFIG_BIGNUM */
-
static int js_unary_arith_bigint(JSContext *ctx,
JSValue *pres, OPCodeEnum op, JSValue op1)
{
@@ -13030,8 +12418,8 @@ static int js_unary_arith_bigint(JSContext *ctx,
int ret, v;
JSValue res;
- if (op == OP_plus && !is_math_mode(ctx)) {
- JS_ThrowTypeError(ctx, "bigint argument with unary +");
+ if (op == OP_plus) {
+ JS_ThrowTypeError(ctx, "BigInt argument with unary +");
JS_FreeValue(ctx, op1);
return -1;
}
@@ -13041,12 +12429,7 @@ static int js_unary_arith_bigint(JSContext *ctx,
return -1;
}
r = JS_GetBigInt(res);
- a = JS_ToBigInt(ctx, &a_s, op1);
- if (!a) {
- JS_FreeValue(ctx, res);
- JS_FreeValue(ctx, op1);
- return -1;
- }
+ a = JS_ToBigIntFree(ctx, &a_s, op1); // infallible, always a bigint
ret = 0;
switch(op) {
case OP_inc:
@@ -13069,7 +12452,6 @@ static int js_unary_arith_bigint(JSContext *ctx,
abort();
}
JS_FreeBigInt(ctx, a, &a_s);
- JS_FreeValue(ctx, op1);
if (unlikely(ret)) {
JS_FreeValue(ctx, res);
throw_bf_exception(ctx, ret);
@@ -13092,19 +12474,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
/* fast path for float64 */
if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)))
goto handle_float64;
-#ifdef CONFIG_BIGNUM
- if (JS_IsObject(op1)) {
- JSValue val;
- int ret = js_call_unary_op_fallback(ctx, &val, op1, op);
- if (ret < 0)
- return -1;
- if (ret) {
- JS_FreeValue(ctx, op1);
- sp[-1] = val;
- return 0;
- }
- }
-#endif
+
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1))
goto exception;
@@ -13124,7 +12494,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
break;
case OP_neg:
if (v64 == 0) {
- sp[-1] = JS_NewFloat64(ctx, -0.0);
+ sp[-1] = js_float64(-0.0);
return 0;
} else {
v64 = -v64;
@@ -13133,31 +12503,17 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
default:
abort();
}
- sp[-1] = JS_NewInt64(ctx, v64);
+ sp[-1] = js_int64(v64);
}
break;
case JS_TAG_BIG_INT:
- handle_bigint:
- if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, op, op1))
- goto exception;
- break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- if (ctx->rt->bigfloat_ops.unary_arith(ctx, sp - 1, op, op1))
- goto exception;
- break;
- case JS_TAG_BIG_DECIMAL:
- if (ctx->rt->bigdecimal_ops.unary_arith(ctx, sp - 1, op, op1))
+ if (js_unary_arith_bigint(ctx, sp - 1, op, op1))
goto exception;
break;
-#endif
default:
handle_float64:
{
- double d;
- if (is_math_mode(ctx))
- goto handle_bigint;
- d = JS_VALUE_GET_FLOAT64(op1);
+ double d = JS_VALUE_GET_FLOAT64(op1);
switch(op) {
case OP_inc:
case OP_dec:
@@ -13172,7 +12528,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
default:
abort();
}
- sp[-1] = JS_NewFloat64(ctx, d);
+ sp[-1] = js_float64(d);
}
break;
}
@@ -13195,7 +12551,7 @@ static __exception int js_post_inc_slow(JSContext *ctx,
return -1;
}
sp[-1] = op1;
- sp[0] = JS_DupValue(ctx, op1);
+ sp[0] = js_dup(op1);
return js_unary_arith_slow(ctx, sp + 1, op - OP_post_dec + OP_dec);
}
@@ -13203,31 +12559,17 @@ static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
{
JSValue op1;
- op1 = sp[-1];
-#ifdef CONFIG_BIGNUM
- if (JS_IsObject(op1)) {
- JSValue val;
- int ret = js_call_unary_op_fallback(ctx, &val, op1, OP_not);
- if (ret < 0)
- return -1;
- if (ret) {
- JS_FreeValue(ctx, op1);
- sp[-1] = val;
- return 0;
- }
- }
-#endif
- op1 = JS_ToNumericFree(ctx, op1);
+ op1 = JS_ToNumericFree(ctx, sp[-1]);
if (JS_IsException(op1))
goto exception;
- if (is_math_mode(ctx) || JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT) {
- if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, OP_not, op1))
+ if (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT) {
+ if (js_unary_arith_bigint(ctx, sp - 1, OP_not, op1))
goto exception;
} else {
int32_t v1;
if (unlikely(JS_ToInt32Free(ctx, &v1, op1)))
goto exception;
- sp[-1] = JS_NewInt32(ctx, ~v1);
+ sp[-1] = js_int32(~v1);
}
return 0;
exception:
@@ -13242,16 +12584,21 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
int ret;
JSValue res;
- res = JS_NewBigInt(ctx);
- if (JS_IsException(res))
- goto fail;
- a = JS_ToBigInt(ctx, &a_s, op1);
- if (!a)
- goto fail;
- b = JS_ToBigInt(ctx, &b_s, op2);
+ a = JS_ToBigIntFree(ctx, &a_s, op1);
+ if (!a) {
+ JS_FreeValue(ctx, op2);
+ return -1;
+ }
+ b = JS_ToBigIntFree(ctx, &b_s, op2);
if (!b) {
JS_FreeBigInt(ctx, a, &a_s);
- goto fail;
+ return -1;
+ }
+ res = JS_NewBigInt(ctx);
+ if (JS_IsException(res)) {
+ JS_FreeBigInt(ctx, a, &a_s);
+ JS_FreeBigInt(ctx, b, &b_s);
+ return -1;
}
r = JS_GetBigInt(res);
ret = 0;
@@ -13266,78 +12613,20 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
ret = bf_mul(r, a, b, BF_PREC_INF, BF_RNDZ);
break;
case OP_div:
- if (!is_math_mode(ctx)) {
+ {
bf_t rem_s, *rem = &rem_s;
bf_init(ctx->bf_ctx, rem);
- ret = bf_divrem(r, rem, a, b, BF_PREC_INF, BF_RNDZ,
- BF_RNDZ);
+ ret = bf_divrem(r, rem, a, b, BF_PREC_INF, BF_RNDZ, BF_RNDZ);
bf_delete(rem);
- } else {
- goto math_mode_div_pow;
}
break;
-#ifdef CONFIG_BIGNUM
- case OP_math_mod:
- /* Euclidian remainder */
- ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
- BF_DIVREM_EUCLIDIAN) & BF_ST_INVALID_OP;
- break;
-#endif
case OP_mod:
ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
BF_RNDZ) & BF_ST_INVALID_OP;
break;
case OP_pow:
if (b->sign) {
- if (!is_math_mode(ctx)) {
- ret = BF_ST_INVALID_OP;
- } else {
- math_mode_div_pow:
-#ifdef CONFIG_BIGNUM
- JS_FreeValue(ctx, res);
- ret = js_call_binary_op_simple(ctx, &res, ctx->class_proto[JS_CLASS_BIG_INT], op1, op2, op);
- if (ret != 0) {
- JS_FreeBigInt(ctx, a, &a_s);
- JS_FreeBigInt(ctx, b, &b_s);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (ret < 0) {
- return -1;
- } else {
- *pres = res;
- return 0;
- }
- }
- /* if no BigInt power operator defined, return a
- bigfloat */
- res = JS_NewBigFloat(ctx);
- if (JS_IsException(res)) {
- JS_FreeBigInt(ctx, a, &a_s);
- JS_FreeBigInt(ctx, b, &b_s);
- goto fail;
- }
- r = JS_GetBigFloat(res);
- if (op == OP_div) {
- ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags) & BF_ST_MEM_ERROR;
- } else {
- ret = bf_pow(r, a, b, ctx->fp_env.prec,
- ctx->fp_env.flags | BF_POW_JS_QUIRKS) & BF_ST_MEM_ERROR;
- }
- JS_FreeBigInt(ctx, a, &a_s);
- JS_FreeBigInt(ctx, b, &b_s);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (unlikely(ret)) {
- JS_FreeValue(ctx, res);
- throw_bf_exception(ctx, ret);
- return -1;
- }
- *pres = res;
- return 0;
-#else
- abort();
-#endif
- }
+ ret = BF_ST_INVALID_OP;
} else {
ret = bf_pow(r, a, b, BF_PREC_INF, BF_RNDZ | BF_POW_JS_QUIRKS);
}
@@ -13380,8 +12669,6 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
}
JS_FreeBigInt(ctx, a, &a_s);
JS_FreeBigInt(ctx, b, &b_s);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
if (unlikely(ret)) {
JS_FreeValue(ctx, res);
throw_bf_exception(ctx, ret);
@@ -13389,174 +12676,8 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
}
*pres = JS_CompactBigInt(ctx, res);
return 0;
- fail:
- JS_FreeValue(ctx, res);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- return -1;
-}
-
-#ifdef CONFIG_BIGNUM
-static int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op,
- JSValue *pres, JSValue op1, JSValue op2)
-{
- bf_t a_s, b_s, *r, *a, *b;
- int ret;
- JSValue res;
-
- res = JS_NewBigFloat(ctx);
- if (JS_IsException(res))
- goto fail;
- r = JS_GetBigFloat(res);
- a = JS_ToBigFloat(ctx, &a_s, op1);
- if (!a) {
- JS_FreeValue(ctx, res);
- goto fail;
- }
- b = JS_ToBigFloat(ctx, &b_s, op2);
- if (!b) {
- if (a == &a_s)
- bf_delete(a);
- JS_FreeValue(ctx, res);
- goto fail;
- }
- bf_init(ctx->bf_ctx, r);
- switch(op) {
- case OP_add:
- ret = bf_add(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_sub:
- ret = bf_sub(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_mul:
- ret = bf_mul(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_div:
- ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_math_mod:
- /* Euclidian remainder */
- ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
- BF_DIVREM_EUCLIDIAN);
- break;
- case OP_mod:
- ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
- BF_RNDZ);
- break;
- case OP_pow:
- ret = bf_pow(r, a, b, ctx->fp_env.prec,
- ctx->fp_env.flags | BF_POW_JS_QUIRKS);
- break;
- default:
- abort();
- }
- if (a == &a_s)
- bf_delete(a);
- if (b == &b_s)
- bf_delete(b);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (unlikely(ret & BF_ST_MEM_ERROR)) {
- JS_FreeValue(ctx, res);
- throw_bf_exception(ctx, ret);
- return -1;
- }
- *pres = res;
- return 0;
- fail:
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- return -1;
}
-/* b must be a positive integer */
-static int js_bfdec_pow(bfdec_t *r, const bfdec_t *a, const bfdec_t *b)
-{
- bfdec_t b1;
- int32_t b2;
- int ret;
-
- bfdec_init(b->ctx, &b1);
- ret = bfdec_set(&b1, b);
- if (ret) {
- bfdec_delete(&b1);
- return ret;
- }
- ret = bfdec_rint(&b1, BF_RNDZ);
- if (ret) {
- bfdec_delete(&b1);
- return BF_ST_INVALID_OP; /* must be an integer */
- }
- ret = bfdec_get_int32(&b2, &b1);
- bfdec_delete(&b1);
- if (ret)
- return ret; /* overflow */
- if (b2 < 0)
- return BF_ST_INVALID_OP; /* must be positive */
- return bfdec_pow_ui(r, a, b2);
-}
-
-static int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op,
- JSValue *pres, JSValue op1, JSValue op2)
-{
- bfdec_t *r, *a, *b;
- int ret;
- JSValue res;
-
- res = JS_NewBigDecimal(ctx);
- if (JS_IsException(res))
- goto fail;
- r = JS_GetBigDecimal(res);
-
- a = JS_ToBigDecimal(ctx, op1);
- if (!a)
- goto fail;
- b = JS_ToBigDecimal(ctx, op2);
- if (!b)
- goto fail;
- switch(op) {
- case OP_add:
- ret = bfdec_add(r, a, b, BF_PREC_INF, BF_RNDZ);
- break;
- case OP_sub:
- ret = bfdec_sub(r, a, b, BF_PREC_INF, BF_RNDZ);
- break;
- case OP_mul:
- ret = bfdec_mul(r, a, b, BF_PREC_INF, BF_RNDZ);
- break;
- case OP_div:
- ret = bfdec_div(r, a, b, BF_PREC_INF, BF_RNDZ);
- break;
- case OP_math_mod:
- /* Euclidian remainder */
- ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_DIVREM_EUCLIDIAN);
- break;
- case OP_mod:
- ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_RNDZ);
- break;
- case OP_pow:
- ret = js_bfdec_pow(r, a, b);
- break;
- default:
- abort();
- }
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (unlikely(ret)) {
- JS_FreeValue(ctx, res);
- throw_bf_exception(ctx, ret);
- return -1;
- }
- *pres = res;
- return 0;
- fail:
- JS_FreeValue(ctx, res);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- return -1;
-}
-#endif /* CONFIG_BIGNUM */
-
static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
OPCodeEnum op)
{
@@ -13575,27 +12696,6 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
goto handle_float64;
}
-#ifdef CONFIG_BIGNUM
- /* try to call an overloaded operator */
- if ((tag1 == JS_TAG_OBJECT &&
- (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||
- (tag2 == JS_TAG_OBJECT &&
- (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {
- JSValue res;
- int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);
- if (ret != 0) {
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (ret < 0) {
- goto exception;
- } else {
- sp[-2] = res;
- return 0;
- }
- }
- }
-#endif
-
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -13620,67 +12720,31 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
break;
case OP_mul:
v = (int64_t)v1 * (int64_t)v2;
- if (is_math_mode(ctx) &&
- (v < -MAX_SAFE_INTEGER || v > MAX_SAFE_INTEGER))
- goto handle_bigint;
if (v == 0 && (v1 | v2) < 0) {
- sp[-2] = JS_NewFloat64(ctx, -0.0);
+ sp[-2] = js_float64(-0.0);
return 0;
}
break;
case OP_div:
- if (is_math_mode(ctx))
- goto handle_bigint;
- sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2);
+ sp[-2] = js_float64((double)v1 / (double)v2);
return 0;
-#ifdef CONFIG_BIGNUM
- case OP_math_mod:
- if (unlikely(v2 == 0)) {
- throw_bf_exception(ctx, BF_ST_DIVIDE_ZERO);
- goto exception;
- }
- v = (int64_t)v1 % (int64_t)v2;
- if (v < 0) {
- if (v2 < 0)
- v -= v2;
- else
- v += v2;
- }
- break;
-#endif
case OP_mod:
if (v1 < 0 || v2 <= 0) {
- sp[-2] = JS_NewFloat64(ctx, fmod(v1, v2));
+ sp[-2] = js_number(fmod(v1, v2));
return 0;
} else {
v = (int64_t)v1 % (int64_t)v2;
}
break;
case OP_pow:
- if (!is_math_mode(ctx)) {
- sp[-2] = JS_NewFloat64(ctx, js_pow(v1, v2));
- return 0;
- } else {
- goto handle_bigint;
- }
- break;
+ sp[-2] = js_number(js_math_pow(v1, v2));
+ return 0;
default:
abort();
}
- sp[-2] = JS_NewInt64(ctx, v);
- } else
-#ifdef CONFIG_BIGNUM
- if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
- if (ctx->rt->bigdecimal_ops.binary_arith(ctx, op, sp - 2, op1, op2))
- goto exception;
- } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
- if (ctx->rt->bigfloat_ops.binary_arith(ctx, op, sp - 2, op1, op2))
- goto exception;
- } else
-#endif
- if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
- handle_bigint:
- if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))
+ sp[-2] = js_int64(v);
+ } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
+ if (js_binary_arith_bigint(ctx, op, sp - 2, op1, op2))
goto exception;
} else {
double dr;
@@ -13692,8 +12756,6 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
if (JS_ToFloat64Free(ctx, &d2, op2))
goto exception;
handle_float64:
- if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))
- goto handle_bigint;
switch(op) {
case OP_sub:
dr = d1 - d2;
@@ -13707,22 +12769,13 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
case OP_mod:
dr = fmod(d1, d2);
break;
-#ifdef CONFIG_BIGNUM
- case OP_math_mod:
- d2 = fabs(d2);
- dr = fmod(d1, d2);
- /* XXX: loss of accuracy if dr < 0 */
- if (dr < 0)
- dr += d2;
- break;
-#endif
case OP_pow:
- dr = js_pow(d1, d2);
+ dr = js_math_pow(d1, d2);
break;
default:
abort();
}
- sp[-2] = JS_NewFloat64(ctx, dr);
+ sp[-2] = js_float64(dr);
}
return 0;
exception:
@@ -13746,34 +12799,11 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
double d1, d2;
d1 = JS_VALUE_GET_FLOAT64(op1);
d2 = JS_VALUE_GET_FLOAT64(op2);
- sp[-2] = JS_NewFloat64(ctx, d1 + d2);
+ sp[-2] = js_float64(d1 + d2);
return 0;
}
if (tag1 == JS_TAG_OBJECT || tag2 == JS_TAG_OBJECT) {
-#ifdef CONFIG_BIGNUM
- /* try to call an overloaded operator */
- if ((tag1 == JS_TAG_OBJECT &&
- (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED &&
- tag2 != JS_TAG_STRING)) ||
- (tag2 == JS_TAG_OBJECT &&
- (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED &&
- tag1 != JS_TAG_STRING))) {
- JSValue res;
- int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, OP_add,
- FALSE, HINT_NONE);
- if (ret != 0) {
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (ret < 0) {
- goto exception;
- } else {
- sp[-2] = res;
- return 0;
- }
- }
- }
-#endif
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -13815,20 +12845,9 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
v1 = JS_VALUE_GET_INT(op1);
v2 = JS_VALUE_GET_INT(op2);
v = (int64_t)v1 + (int64_t)v2;
- sp[-2] = JS_NewInt64(ctx, v);
- } else
-#ifdef CONFIG_BIGNUM
- if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
- if (ctx->rt->bigdecimal_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
- goto exception;
- } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
- if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
- goto exception;
- } else
-#endif
- if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
- handle_bigint:
- if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
+ sp[-2] = js_int64(v);
+ } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
+ if (js_binary_arith_bigint(ctx, OP_add, sp - 2, op1, op2))
goto exception;
} else {
double d1, d2;
@@ -13839,9 +12858,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
}
if (JS_ToFloat64Free(ctx, &d2, op2))
goto exception;
- if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))
- goto handle_bigint;
- sp[-2] = JS_NewFloat64(ctx, d1 + d2);
+ sp[-2] = js_float64(d1 + d2);
}
return 0;
exception:
@@ -13863,27 +12880,6 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
tag1 = JS_VALUE_GET_NORM_TAG(op1);
tag2 = JS_VALUE_GET_NORM_TAG(op2);
-#ifdef CONFIG_BIGNUM
- /* try to call an overloaded operator */
- if ((tag1 == JS_TAG_OBJECT &&
- (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||
- (tag2 == JS_TAG_OBJECT &&
- (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {
- JSValue res;
- int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);
- if (ret != 0) {
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (ret < 0) {
- goto exception;
- } else {
- sp[-2] = res;
- return 0;
- }
- }
- }
-#endif
-
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -13895,21 +12891,16 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
goto exception;
}
- if (is_math_mode(ctx))
- goto bigint_op;
-
tag1 = JS_VALUE_GET_TAG(op1);
tag2 = JS_VALUE_GET_TAG(op2);
if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
if (tag1 != tag2) {
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
- JS_ThrowTypeError(ctx, "both operands must be bigint");
+ JS_ThrowTypeError(ctx, "both operands must be BigInt");
+ goto exception;
+ } else if (js_binary_arith_bigint(ctx, op, sp - 2, op1, op2)) {
goto exception;
- } else {
- bigint_op:
- if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))
- goto exception;
}
} else {
if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) {
@@ -13937,7 +12928,7 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
default:
abort();
}
- sp[-2] = JS_NewInt32(ctx, r);
+ sp[-2] = js_int32(r);
}
return 0;
exception:
@@ -13946,19 +12937,18 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
return -1;
}
-/* Note: also used for bigint */
-static int js_compare_bigfloat(JSContext *ctx, OPCodeEnum op,
- JSValue op1, JSValue op2)
+static int js_compare_bigint(JSContext *ctx, OPCodeEnum op,
+ JSValue op1, JSValue op2)
{
bf_t a_s, b_s, *a, *b;
int res;
- a = JS_ToBigFloat(ctx, &a_s, op1);
+ a = JS_ToBigInt1(ctx, &a_s, op1);
if (!a) {
JS_FreeValue(ctx, op2);
return -1;
}
- b = JS_ToBigFloat(ctx, &b_s, op2);
+ b = JS_ToBigInt1(ctx, &b_s, op2);
if (!b) {
if (a == &a_s)
bf_delete(a);
@@ -13993,54 +12983,6 @@ static int js_compare_bigfloat(JSContext *ctx, OPCodeEnum op,
return res;
}
-#ifdef CONFIG_BIGNUM
-static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op,
- JSValue op1, JSValue op2)
-{
- bfdec_t *a, *b;
- int res;
-
- /* Note: binary floats are converted to bigdecimal with
- toString(). It is not mathematically correct but is consistent
- with the BigDecimal() constructor behavior */
- op1 = JS_ToBigDecimalFree(ctx, op1, TRUE);
- if (JS_IsException(op1)) {
- JS_FreeValue(ctx, op2);
- return -1;
- }
- op2 = JS_ToBigDecimalFree(ctx, op2, TRUE);
- if (JS_IsException(op2)) {
- JS_FreeValue(ctx, op1);
- return -1;
- }
- a = JS_ToBigDecimal(ctx, op1); /* cannot fail */
- b = JS_ToBigDecimal(ctx, op2); /* cannot fail */
-
- switch(op) {
- case OP_lt:
- res = bfdec_cmp_lt(a, b); /* if NaN return false */
- break;
- case OP_lte:
- res = bfdec_cmp_le(a, b); /* if NaN return false */
- break;
- case OP_gt:
- res = bfdec_cmp_lt(b, a); /* if NaN return false */
- break;
- case OP_gte:
- res = bfdec_cmp_le(b, a); /* if NaN return false */
- break;
- case OP_eq:
- res = bfdec_cmp_eq(a, b); /* if NaN return false */
- break;
- default:
- abort();
- }
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- return res;
-}
-#endif /* !CONFIG_BIGNUM */
-
static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
OPCodeEnum op)
{
@@ -14052,27 +12994,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
op2 = sp[-1];
tag1 = JS_VALUE_GET_NORM_TAG(op1);
tag2 = JS_VALUE_GET_NORM_TAG(op2);
-#ifdef CONFIG_BIGNUM
- /* try to call an overloaded operator */
- if ((tag1 == JS_TAG_OBJECT &&
- (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||
- (tag2 == JS_TAG_OBJECT &&
- (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {
- JSValue ret;
- res = js_call_binary_op_fallback(ctx, &ret, op1, op2, op,
- FALSE, HINT_NUMBER);
- if (res != 0) {
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (res < 0) {
- goto exception;
- } else {
- sp[-2] = ret;
- return 0;
- }
- }
- }
-#endif
+
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -14090,7 +13012,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
JSString *p1, *p2;
p1 = JS_VALUE_GET_STRING(op1);
p2 = JS_VALUE_GET_STRING(op2);
- res = js_string_compare(ctx, p1, p2);
+ res = js_string_compare(p1, p2);
switch(op) {
case OP_lt:
res = (res < 0);
@@ -14114,8 +13036,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
goto float64_compare;
} else {
if (((tag1 == JS_TAG_BIG_INT && tag2 == JS_TAG_STRING) ||
- (tag2 == JS_TAG_BIG_INT && tag1 == JS_TAG_STRING)) &&
- !is_math_mode(ctx)) {
+ (tag2 == JS_TAG_BIG_INT && tag1 == JS_TAG_STRING))) {
if (tag1 == JS_TAG_STRING) {
op1 = JS_StringToBigInt(ctx, op1);
if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)
@@ -14127,7 +13048,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
invalid_bigint_string:
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
- res = FALSE;
+ res = false;
goto done;
}
}
@@ -14147,19 +13068,8 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
tag1 = JS_VALUE_GET_NORM_TAG(op1);
tag2 = JS_VALUE_GET_NORM_TAG(op2);
-#ifdef CONFIG_BIGNUM
- if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
- res = ctx->rt->bigdecimal_ops.compare(ctx, op, op1, op2);
- if (res < 0)
- goto exception;
- } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
- res = ctx->rt->bigfloat_ops.compare(ctx, op, op1, op2);
- if (res < 0)
- goto exception;
- } else
-#endif
if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
- res = ctx->rt->bigint_ops.compare(ctx, op, op1, op2);
+ res = js_compare_bigint(ctx, op, op1, op2);
if (res < 0)
goto exception;
} else {
@@ -14195,7 +13105,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
}
}
done:
- sp[-2] = JS_NewBool(ctx, res);
+ sp[-2] = js_bool(res);
return 0;
exception:
sp[-2] = JS_UNDEFINED;
@@ -14203,23 +13113,16 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
return -1;
}
-static BOOL tag_is_number(uint32_t tag)
+static bool tag_is_number(uint32_t tag)
{
return (tag == JS_TAG_INT || tag == JS_TAG_BIG_INT ||
- tag == JS_TAG_FLOAT64
-#ifdef CONFIG_BIGNUM
- || tag == JS_TAG_BIG_FLOAT || tag == JS_TAG_BIG_DECIMAL
-#endif
- );
+ tag == JS_TAG_FLOAT64);
}
static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
- BOOL is_neq)
+ bool is_neq)
{
JSValue op1, op2;
-#ifdef CONFIG_BIGNUM
- JSValue ret;
-#endif
int res;
uint32_t tag1, tag2;
@@ -14247,51 +13150,20 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
d2 = JS_VALUE_GET_INT(op2);
}
res = (d1 == d2);
- } else
-#ifdef CONFIG_BIGNUM
- if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
- res = ctx->rt->bigdecimal_ops.compare(ctx, OP_eq, op1, op2);
- if (res < 0)
- goto exception;
- } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
- res = ctx->rt->bigfloat_ops.compare(ctx, OP_eq, op1, op2);
- if (res < 0)
- goto exception;
- } else
-#endif
- {
- res = ctx->rt->bigint_ops.compare(ctx, OP_eq, op1, op2);
+ } else {
+ res = js_compare_bigint(ctx, OP_eq, op1, op2);
if (res < 0)
goto exception;
}
} else if (tag1 == tag2) {
-#ifdef CONFIG_BIGNUM
- if (tag1 == JS_TAG_OBJECT) {
- /* try the fallback operator */
- res = js_call_binary_op_fallback(ctx, &ret, op1, op2,
- is_neq ? OP_neq : OP_eq,
- FALSE, HINT_NONE);
- if (res != 0) {
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (res < 0) {
- goto exception;
- } else {
- sp[-2] = ret;
- return 0;
- }
- }
- }
-#endif
res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
} else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||
(tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {
- res = TRUE;
+ res = true;
} else if ((tag1 == JS_TAG_STRING && tag_is_number(tag2)) ||
(tag2 == JS_TAG_STRING && tag_is_number(tag1))) {
- if ((tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) &&
- !is_math_mode(ctx)) {
+ if ((tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT)) {
if (tag1 == JS_TAG_STRING) {
op1 = JS_StringToBigInt(ctx, op1);
if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)
@@ -14303,7 +13175,7 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
invalid_bigint_string:
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
- res = FALSE;
+ res = false;
goto done;
}
}
@@ -14319,33 +13191,17 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
goto exception;
}
}
- res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
+ res = js_strict_eq(ctx, op1, op2);
} else if (tag1 == JS_TAG_BOOL) {
- op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));
+ op1 = js_int32(JS_VALUE_GET_INT(op1));
goto redo;
} else if (tag2 == JS_TAG_BOOL) {
- op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2));
+ op2 = js_int32(JS_VALUE_GET_INT(op2));
goto redo;
} else if ((tag1 == JS_TAG_OBJECT &&
(tag_is_number(tag2) || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) ||
(tag2 == JS_TAG_OBJECT &&
(tag_is_number(tag1) || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL))) {
-#ifdef CONFIG_BIGNUM
- /* try the fallback operator */
- res = js_call_binary_op_fallback(ctx, &ret, op1, op2,
- is_neq ? OP_neq : OP_eq,
- FALSE, HINT_NONE);
- if (res != 0) {
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (res < 0) {
- goto exception;
- } else {
- sp[-2] = ret;
- return 0;
- }
- }
-#endif
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -14363,15 +13219,15 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
(tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||
(JS_IsHTMLDDA(ctx, op2) &&
(tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {
- res = TRUE;
+ res = true;
} else {
- res = FALSE;
+ res = false;
}
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
}
done:
- sp[-2] = JS_NewBool(ctx, res ^ is_neq);
+ sp[-2] = js_bool(res ^ is_neq);
return 0;
exception:
sp[-2] = JS_UNDEFINED;
@@ -14396,11 +13252,10 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)
JS_FreeValue(ctx, op1);
goto exception;
}
- /* XXX: could forbid >>> in bignum mode */
- if (!is_math_mode(ctx) &&
- (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT ||
+
+ if ((JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT ||
JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_INT)) {
- JS_ThrowTypeError(ctx, "bigint operands are forbidden for >>>");
+ JS_ThrowTypeError(ctx, "BigInt operands are forbidden for >>>");
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
goto exception;
@@ -14409,7 +13264,7 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)
JS_ToUint32Free(ctx, &v1, op1);
JS_ToUint32Free(ctx, &v2, op2);
r = v1 >> (v2 & 0x1f);
- sp[-2] = JS_NewUint32(ctx, r);
+ sp[-2] = js_uint32(r);
return 0;
exception:
sp[-2] = JS_UNDEFINED;
@@ -14417,72 +13272,11 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)
return -1;
}
-#ifdef CONFIG_BIGNUM
-static JSValue js_mul_pow10_to_float64(JSContext *ctx, const bf_t *a,
- int64_t exponent)
-{
- bf_t r_s, *r = &r_s;
- double d;
- int ret;
-
- /* always convert to Float64 */
- bf_init(ctx->bf_ctx, r);
- ret = bf_mul_pow_radix(r, a, 10, exponent,
- 53, bf_set_exp_bits(11) | BF_RNDN |
- BF_FLAG_SUBNORMAL);
- bf_get_float64(r, &d, BF_RNDN);
- bf_delete(r);
- if (ret & BF_ST_MEM_ERROR)
- return JS_ThrowOutOfMemory(ctx);
- else
- return JS_NewFloat64(ctx, d);
-}
-
-static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp)
-{
- bf_t a_s, *a, *r;
- JSValue op1, op2, res;
- int64_t e;
- int ret;
-
- res = JS_NewBigFloat(ctx);
- if (JS_IsException(res))
- return -1;
- r = JS_GetBigFloat(res);
- op1 = sp[-2];
- op2 = sp[-1];
- a = JS_ToBigFloat(ctx, &a_s, op1);
- if (!a) {
- JS_FreeValue(ctx, res);
- return -1;
- }
- if (JS_IsBigInt(ctx, op2)) {
- ret = JS_ToBigInt64(ctx, &e, op2);
- } else {
- ret = JS_ToInt64(ctx, &e, op2);
- }
- if (ret) {
- if (a == &a_s)
- bf_delete(a);
- JS_FreeValue(ctx, res);
- return -1;
- }
-
- bf_mul_pow_radix(r, a, 10, e, ctx->fp_env.prec, ctx->fp_env.flags);
- if (a == &a_s)
- bf_delete(a);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- sp[-2] = res;
- return 0;
-}
-#endif
-
-/* XXX: Should take JSValueConst arguments */
-static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
+/* XXX: Should take JSValue arguments */
+static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
JSStrictEqModeEnum eq_mode)
{
- BOOL res;
+ bool res;
int tag1, tag2;
double d1, d2;
@@ -14491,7 +13285,7 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
switch(tag1) {
case JS_TAG_BOOL:
if (tag1 != tag2) {
- res = FALSE;
+ res = false;
} else {
res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2);
goto done_no_free;
@@ -14505,11 +13299,11 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
{
JSString *p1, *p2;
if (tag1 != tag2) {
- res = FALSE;
+ res = false;
} else {
p1 = JS_VALUE_GET_STRING(op1);
p2 = JS_VALUE_GET_STRING(op2);
- res = (js_string_compare(ctx, p1, p2) == 0);
+ res = js_string_eq(p1, p2);
}
}
break;
@@ -14517,7 +13311,7 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
{
JSAtomStruct *p1, *p2;
if (tag1 != tag2) {
- res = FALSE;
+ res = false;
} else {
p1 = JS_VALUE_GET_PTR(op1);
p2 = JS_VALUE_GET_PTR(op2);
@@ -14527,7 +13321,7 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
break;
case JS_TAG_OBJECT:
if (tag1 != tag2)
- res = FALSE;
+ res = false;
else
res = JS_VALUE_GET_OBJ(op1) == JS_VALUE_GET_OBJ(op2);
break;
@@ -14540,7 +13334,7 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
d2 = JS_VALUE_GET_FLOAT64(op2);
goto number_test;
} else {
- res = FALSE;
+ res = false;
}
break;
case JS_TAG_FLOAT64:
@@ -14550,7 +13344,7 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
} else if (tag2 == JS_TAG_INT) {
d2 = JS_VALUE_GET_INT(op2);
} else {
- res = FALSE;
+ res = false;
break;
}
number_test:
@@ -14574,11 +13368,11 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
{
bf_t a_s, *a, b_s, *b;
if (tag1 != tag2) {
- res = FALSE;
+ res = false;
break;
}
- a = JS_ToBigFloat(ctx, &a_s, op1); /* cannot fail */
- b = JS_ToBigFloat(ctx, &b_s, op2); /* cannot fail */
+ a = JS_ToBigInt1(ctx, &a_s, op1);
+ b = JS_ToBigInt1(ctx, &b_s, op2);
res = bf_cmp_eq(a, b);
if (a == &a_s)
bf_delete(a);
@@ -14586,49 +13380,8 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
bf_delete(b);
}
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- {
- JSBigFloat *p1, *p2;
- const bf_t *a, *b;
- if (tag1 != tag2) {
- res = FALSE;
- break;
- }
- p1 = JS_VALUE_GET_PTR(op1);
- p2 = JS_VALUE_GET_PTR(op2);
- a = &p1->num;
- b = &p2->num;
- if (unlikely(eq_mode >= JS_EQ_SAME_VALUE)) {
- if (eq_mode == JS_EQ_SAME_VALUE_ZERO &&
- a->expn == BF_EXP_ZERO && b->expn == BF_EXP_ZERO) {
- res = TRUE;
- } else {
- res = (bf_cmp_full(a, b) == 0);
- }
- } else {
- res = bf_cmp_eq(a, b);
- }
- }
- break;
- case JS_TAG_BIG_DECIMAL:
- {
- JSBigDecimal *p1, *p2;
- const bfdec_t *a, *b;
- if (tag1 != tag2) {
- res = FALSE;
- break;
- }
- p1 = JS_VALUE_GET_PTR(op1);
- p2 = JS_VALUE_GET_PTR(op2);
- a = &p1->num;
- b = &p2->num;
- res = bfdec_cmp_eq(a, b);
- }
- break;
-#endif
default:
- res = FALSE;
+ res = false;
break;
}
JS_FreeValue(ctx, op1);
@@ -14637,48 +13390,27 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
return res;
}
-static BOOL js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2)
-{
- return js_strict_eq2(ctx,
- JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),
- JS_EQ_STRICT);
-}
-
-BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2)
+static bool js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2)
{
- return js_strict_eq(ctx, op1, op2);
+ return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
}
-static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2)
+static bool js_same_value(JSContext *ctx, JSValue op1, JSValue op2)
{
- return js_strict_eq2(ctx,
- JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),
- JS_EQ_SAME_VALUE);
+ return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_SAME_VALUE);
}
-BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2)
+static bool js_same_value_zero(JSContext *ctx, JSValue op1, JSValue op2)
{
- return js_same_value(ctx, op1, op2);
-}
-
-static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2)
-{
- return js_strict_eq2(ctx,
- JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),
- JS_EQ_SAME_VALUE_ZERO);
-}
-
-BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2)
-{
- return js_same_value_zero(ctx, op1, op2);
+ return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_SAME_VALUE_ZERO);
}
static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp,
- BOOL is_neq)
+ bool is_neq)
{
- BOOL res;
- res = js_strict_eq2(ctx, sp[-2], sp[-1], JS_EQ_STRICT);
- sp[-2] = JS_NewBool(ctx, res ^ is_neq);
+ bool res;
+ res = js_strict_eq(ctx, sp[-2], sp[-1]);
+ sp[-2] = js_bool(res ^ is_neq);
return 0;
}
@@ -14704,7 +13436,7 @@ static __exception int js_operator_in(JSContext *ctx, JSValue *sp)
return -1;
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
- sp[-2] = JS_NewBool(ctx, ret);
+ sp[-2] = js_bool(ret);
return 0;
}
@@ -14712,10 +13444,8 @@ static __exception int js_operator_private_in(JSContext *ctx, JSValue *sp)
{
JSValue op1, op2;
int ret;
-
op1 = sp[-2]; /* object */
op2 = sp[-1]; /* field name or method function */
-
if (JS_VALUE_GET_TAG(op1) != JS_TAG_OBJECT) {
JS_ThrowTypeError(ctx, "invalid 'in' operand");
return -1;
@@ -14745,7 +13475,7 @@ static __exception int js_operator_private_in(JSContext *ctx, JSValue *sp)
return 0;
}
-static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,
+static __exception int js_has_unscopable(JSContext *ctx, JSValue obj,
JSAtom atom)
{
JSValue arr, val;
@@ -14766,7 +13496,7 @@ static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,
static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp)
{
JSValue op1, op2;
- BOOL ret;
+ int ret;
op1 = sp[-2];
op2 = sp[-1];
@@ -14775,11 +13505,11 @@ static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp)
return ret;
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
- sp[-2] = JS_NewBool(ctx, ret);
+ sp[-2] = js_bool(ret);
return 0;
}
-static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)
+static __exception int js_operator_typeof(JSContext *ctx, JSValue op1)
{
JSAtom atom;
uint32_t tag;
@@ -14789,14 +13519,6 @@ static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)
case JS_TAG_BIG_INT:
atom = JS_ATOM_bigint;
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- atom = JS_ATOM_bigfloat;
- break;
- case JS_TAG_BIG_DECIMAL:
- atom = JS_ATOM_bigdecimal;
- break;
-#endif
case JS_TAG_INT:
case JS_TAG_FLOAT64:
atom = JS_ATOM_number;
@@ -14853,12 +13575,12 @@ static __exception int js_operator_delete(JSContext *ctx, JSValue *sp)
return -1;
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
- sp[-2] = JS_NewBool(ctx, ret);
+ sp[-2] = js_bool(ret);
return 0;
}
-static JSValue js_throw_type_error(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_throw_type_error(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return JS_ThrowTypeError(ctx, "invalid property access");
}
@@ -14866,40 +13588,42 @@ static JSValue js_throw_type_error(JSContext *ctx, JSValueConst this_val,
/* XXX: not 100% compatible, but mozilla seems to use a similar
implementation to ensure that caller in non strict mode does not
throw (ES5 compatibility) */
-static JSValue js_function_proto_caller(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_function_proto_caller(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val);
- if (!b || (b->js_mode & JS_MODE_STRICT) || !b->has_prototype) {
+ if (!b || b->is_strict_mode || !b->has_prototype) {
return js_throw_type_error(ctx, this_val, 0, NULL);
}
return JS_UNDEFINED;
}
static JSValue js_function_proto_fileName(JSContext *ctx,
- JSValueConst this_val)
+ JSValue this_val)
{
JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val);
- if (b && b->has_debug) {
- return JS_AtomToString(ctx, b->debug.filename);
+ if (b) {
+ return JS_AtomToString(ctx, b->filename);
}
return JS_UNDEFINED;
}
-static JSValue js_function_proto_lineNumber(JSContext *ctx,
- JSValueConst this_val)
+static JSValue js_function_proto_int32(JSContext *ctx,
+ JSValue this_val,
+ int magic)
{
JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val);
- if (b && b->has_debug) {
- return JS_NewInt32(ctx, b->debug.line_num);
+ if (b) {
+ int *field = (int *) ((char *)b + magic);
+ return js_int32(*field);
}
return JS_UNDEFINED;
}
static int js_arguments_define_own_property(JSContext *ctx,
- JSValueConst this_obj,
- JSAtom prop, JSValueConst val,
- JSValueConst getter, JSValueConst setter, int flags)
+ JSValue this_obj,
+ JSAtom prop, JSValue val,
+ JSValue getter, JSValue setter, int flags)
{
JSObject *p;
uint32_t idx;
@@ -14919,7 +13643,7 @@ static const JSClassExoticMethods js_arguments_exotic_methods = {
.define_own_property = js_arguments_define_own_property,
};
-static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv)
+static JSValue js_build_arguments(JSContext *ctx, int argc, JSValue *argv)
{
JSValue val, *tab;
JSProperty *pr;
@@ -14935,7 +13659,11 @@ static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv)
/* add the length field (cannot fail) */
pr = add_property(ctx, p, JS_ATOM_length,
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- pr->u.value = JS_NewInt32(ctx, argc);
+ if (!pr) {
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
+ pr->u.value = js_int32(argc);
/* initialize the fast array part */
tab = NULL;
@@ -14946,14 +13674,14 @@ static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv)
return JS_EXCEPTION;
}
for(i = 0; i < argc; i++) {
- tab[i] = JS_DupValue(ctx, argv[i]);
+ tab[i] = js_dup(argv[i]);
}
}
p->u.array.u.values = tab;
p->u.array.count = argc;
JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator,
- JS_DupValue(ctx, ctx->array_proto_values),
+ js_dup(ctx->array_proto_values),
JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
/* add callee property to throw a TypeError in strict mode */
JS_DefineProperty(ctx, val, JS_ATOM_callee, JS_UNDEFINED,
@@ -14967,7 +13695,7 @@ static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv)
/* legacy arguments object: add references to the function arguments */
static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,
- JSValueConst *argv,
+ JSValue *argv,
JSStackFrame *sf, int arg_count)
{
JSValue val;
@@ -14984,11 +13712,13 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,
/* add the length field (cannot fail) */
pr = add_property(ctx, p, JS_ATOM_length,
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- pr->u.value = JS_NewInt32(ctx, argc);
+ if (!pr)
+ goto fail;
+ pr->u.value = js_int32(argc);
for(i = 0; i < arg_count; i++) {
JSVarRef *var_ref;
- var_ref = get_var_ref(ctx, sf, i, TRUE);
+ var_ref = get_var_ref(ctx, sf, i, true);
if (!var_ref)
goto fail;
pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);
@@ -15003,17 +13733,17 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,
be normal properties */
for(i = arg_count; i < argc; i++) {
if (JS_DefinePropertyValueUint32(ctx, val, i,
- JS_DupValue(ctx, argv[i]),
+ js_dup(argv[i]),
JS_PROP_C_W_E) < 0)
goto fail;
}
JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator,
- JS_DupValue(ctx, ctx->array_proto_values),
+ js_dup(ctx->array_proto_values),
JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
/* callee returns this function in non strict mode */
JS_DefinePropertyValue(ctx, val, JS_ATOM_callee,
- JS_DupValue(ctx, ctx->rt->current_stack_frame->cur_func),
+ js_dup(ctx->rt->current_stack_frame->cur_func),
JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
return val;
fail:
@@ -15021,32 +13751,12 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,
return JS_EXCEPTION;
}
-static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst *argv)
-{
- JSValue val;
- int i, ret;
-
- val = JS_NewArray(ctx);
- if (JS_IsException(val))
- return val;
- for (i = first; i < argc; i++) {
- ret = JS_DefinePropertyValueUint32(ctx, val, i - first,
- JS_DupValue(ctx, argv[i]),
- JS_PROP_C_W_E);
- if (ret < 0) {
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
- }
- }
- return val;
-}
-
static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
{
- JSObject *p, *p1;
+ JSObject *p;
JSPropertyEnum *tab_atom;
int i;
- JSValue enum_obj;
+ JSValue enum_obj, obj1;
JSForInIterator *it;
uint32_t tag, tab_atom_count;
@@ -15066,19 +13776,43 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
- it->is_array = FALSE;
+ it->is_array = false;
it->obj = obj;
it->idx = 0;
- it->tab_atom = NULL;
- it->atom_count = 0;
- it->in_prototype_chain = FALSE;
- p1 = JS_VALUE_GET_OBJ(enum_obj);
- p1->u.for_in_iterator = it;
+ p = JS_VALUE_GET_OBJ(enum_obj);
+ p->u.for_in_iterator = it;
if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED)
return enum_obj;
+ /* fast path: assume no enumerable properties in the prototype chain */
+ obj1 = js_dup(obj);
+ for(;;) {
+ obj1 = JS_GetPrototypeFree(ctx, obj1);
+ if (JS_IsNull(obj1))
+ break;
+ if (JS_IsException(obj1))
+ goto fail;
+ if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
+ JS_VALUE_GET_OBJ(obj1),
+ JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) {
+ JS_FreeValue(ctx, obj1);
+ goto fail;
+ }
+ js_free_prop_enum(ctx, tab_atom, tab_atom_count);
+ if (tab_atom_count != 0) {
+ JS_FreeValue(ctx, obj1);
+ goto slow_path;
+ }
+ /* must check for timeout to avoid infinite loop */
+ if (js_poll_interrupts(ctx)) {
+ JS_FreeValue(ctx, obj1);
+ goto fail;
+ }
+ }
+
p = JS_VALUE_GET_OBJ(obj);
+
if (p->fast_array) {
JSShape *sh;
JSShapeProperty *prs;
@@ -15089,102 +13823,71 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
goto normal_case;
}
/* for fast arrays, we only store the number of elements */
- it->is_array = TRUE;
- it->atom_count = p->u.array.count;
+ it->is_array = true;
+ it->array_length = p->u.array.count;
} else {
normal_case:
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,
- JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
- JS_FreeValue(ctx, enum_obj);
- return JS_EXCEPTION;
+ JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY))
+ goto fail;
+ for(i = 0; i < tab_atom_count; i++) {
+ JS_SetPropertyInternal(ctx, enum_obj, tab_atom[i].atom, JS_NULL, 0);
}
- it->tab_atom = tab_atom;
- it->atom_count = tab_atom_count;
+ js_free_prop_enum(ctx, tab_atom, tab_atom_count);
}
return enum_obj;
-}
-/* obj -> enum_obj */
-static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)
-{
- sp[-1] = build_for_in_iterator(ctx, sp[-1]);
- if (JS_IsException(sp[-1]))
- return -1;
- return 0;
-}
-
-/* return -1 if exception, 0 if slow case, 1 if the enumeration is finished */
-static __exception int js_for_in_prepare_prototype_chain_enum(JSContext *ctx,
- JSValueConst enum_obj)
-{
- JSObject *p;
- JSForInIterator *it;
- JSPropertyEnum *tab_atom;
- uint32_t tab_atom_count, i;
- JSValue obj1;
-
- p = JS_VALUE_GET_OBJ(enum_obj);
- it = p->u.for_in_iterator;
-
- /* check if there are enumerable properties in the prototype chain (fast path) */
- obj1 = JS_DupValue(ctx, it->obj);
+ slow_path:
+ /* non enumerable properties hide the enumerables ones in the
+ prototype chain */
+ obj1 = js_dup(obj);
for(;;) {
- obj1 = JS_GetPrototypeFree(ctx, obj1);
- if (JS_IsNull(obj1))
- break;
- if (JS_IsException(obj1))
- goto fail;
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
JS_VALUE_GET_OBJ(obj1),
- JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) {
+ JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
JS_FreeValue(ctx, obj1);
goto fail;
}
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
- if (tab_atom_count != 0) {
- JS_FreeValue(ctx, obj1);
- goto slow_path;
+ for(i = 0; i < tab_atom_count; i++) {
+ JS_DefinePropertyValue(ctx, enum_obj, tab_atom[i].atom, JS_NULL,
+ (tab_atom[i].is_enumerable ?
+ JS_PROP_ENUMERABLE : 0));
}
+ js_free_prop_enum(ctx, tab_atom, tab_atom_count);
+ obj1 = JS_GetPrototypeFree(ctx, obj1);
+ if (JS_IsNull(obj1))
+ break;
+ if (JS_IsException(obj1))
+ goto fail;
/* must check for timeout to avoid infinite loop */
if (js_poll_interrupts(ctx)) {
JS_FreeValue(ctx, obj1);
goto fail;
}
}
- JS_FreeValue(ctx, obj1);
- return 1;
+ return enum_obj;
- slow_path:
- /* add the visited properties, even if they are not enumerable */
- if (it->is_array) {
- if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
- JS_VALUE_GET_OBJ(it->obj),
- JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
- goto fail;
- }
- it->is_array = FALSE;
- it->tab_atom = tab_atom;
- it->atom_count = tab_atom_count;
- }
+ fail:
+ JS_FreeValue(ctx, enum_obj);
+ return JS_EXCEPTION;
+}
- for(i = 0; i < it->atom_count; i++) {
- if (JS_DefinePropertyValue(ctx, enum_obj, it->tab_atom[i].atom, JS_NULL, JS_PROP_ENUMERABLE) < 0)
- goto fail;
- }
+/* obj -> enum_obj */
+static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)
+{
+ sp[-1] = build_for_in_iterator(ctx, sp[-1]);
+ if (JS_IsException(sp[-1]))
+ return -1;
return 0;
- fail:
- return -1;
}
/* enum_obj -> enum_obj value done */
static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
{
- JSValueConst enum_obj;
+ JSValue enum_obj;
JSObject *p;
JSAtom prop;
JSForInIterator *it;
- JSPropertyEnum *tab_atom;
- uint32_t tab_atom_count;
int ret;
enum_obj = sp[-1];
@@ -15197,68 +13900,34 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
it = p->u.for_in_iterator;
for(;;) {
- if (it->idx >= it->atom_count) {
- if (JS_IsNull(it->obj) || JS_IsUndefined(it->obj))
- goto done; /* not an object */
- /* no more property in the current object: look in the prototype */
- if (!it->in_prototype_chain) {
- ret = js_for_in_prepare_prototype_chain_enum(ctx, enum_obj);
- if (ret < 0)
- return -1;
- if (ret)
- goto done;
- it->in_prototype_chain = TRUE;
- }
- it->obj = JS_GetPrototypeFree(ctx, it->obj);
- if (JS_IsException(it->obj))
- return -1;
- if (JS_IsNull(it->obj))
- goto done; /* no more prototype */
-
- /* must check for timeout to avoid infinite loop */
- if (js_poll_interrupts(ctx))
- return -1;
-
- if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
- JS_VALUE_GET_OBJ(it->obj),
- JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
- return -1;
- }
- js_free_prop_enum(ctx, it->tab_atom, it->atom_count);
- it->tab_atom = tab_atom;
- it->atom_count = tab_atom_count;
- it->idx = 0;
+ if (it->is_array) {
+ if (it->idx >= it->array_length)
+ goto done;
+ prop = __JS_AtomFromUInt32(it->idx);
+ it->idx++;
} else {
- if (it->is_array) {
- prop = __JS_AtomFromUInt32(it->idx);
- it->idx++;
- } else {
- BOOL is_enumerable;
- prop = it->tab_atom[it->idx].atom;
- is_enumerable = it->tab_atom[it->idx].is_enumerable;
- it->idx++;
- if (it->in_prototype_chain) {
- /* slow case: we are in the prototype chain */
- ret = JS_GetOwnPropertyInternal(ctx, NULL, JS_VALUE_GET_OBJ(enum_obj), prop);
- if (ret < 0)
- return ret;
- if (ret)
- continue; /* already visited */
- /* add to the visited property list */
- if (JS_DefinePropertyValue(ctx, enum_obj, prop, JS_NULL,
- JS_PROP_ENUMERABLE) < 0)
- return -1;
- }
- if (!is_enumerable)
- continue;
- }
- /* check if the property was deleted */
- ret = JS_GetOwnPropertyInternal(ctx, NULL, JS_VALUE_GET_OBJ(it->obj), prop);
- if (ret < 0)
- return ret;
- if (ret)
+ JSShape *sh = p->shape;
+ JSShapeProperty *prs;
+ if (it->idx >= sh->prop_count)
+ goto done;
+ prs = get_shape_prop(sh) + it->idx;
+ prop = prs->atom;
+ it->idx++;
+ if (prop == JS_ATOM_NULL || !(prs->flags & JS_PROP_ENUMERABLE))
+ continue;
+ }
+ // check if the property was deleted unless we're dealing with a proxy
+ JSValue obj = it->obj;
+ if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
+ JSObject *p = JS_VALUE_GET_OBJ(obj);
+ if (p->class_id == JS_CLASS_PROXY)
break;
}
+ ret = JS_HasProperty(ctx, obj, prop);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ break;
}
/* return the property */
sp[0] = JS_AtomToValue(ctx, prop);
@@ -15271,8 +13940,8 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
return 0;
}
-static JSValue JS_GetIterator2(JSContext *ctx, JSValueConst obj,
- JSValueConst method)
+static JSValue JS_GetIterator2(JSContext *ctx, JSValue obj,
+ JSValue method)
{
JSValue enum_obj;
@@ -15286,7 +13955,7 @@ static JSValue JS_GetIterator2(JSContext *ctx, JSValueConst obj,
return enum_obj;
}
-static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, BOOL is_async)
+static JSValue JS_GetIterator(JSContext *ctx, JSValue obj, bool is_async)
{
JSValue method, ret, sync_iter;
@@ -15321,9 +13990,9 @@ static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, BOOL is_async)
}
/* return *pdone = 2 if the iterator object is not parsed */
-static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj,
- JSValueConst method,
- int argc, JSValueConst *argv, int *pdone)
+static JSValue JS_IteratorNext2(JSContext *ctx, JSValue enum_obj,
+ JSValue method,
+ int argc, JSValue *argv, int *pdone)
{
JSValue obj;
@@ -15334,7 +14003,7 @@ static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj,
if (p->class_id == JS_CLASS_C_FUNCTION &&
p->u.cfunc.cproto == JS_CFUNC_iterator_next) {
JSCFunctionType func;
- JSValueConst args[1];
+ JSValue args[1];
/* in case the function expects one argument */
if (argc == 0) {
@@ -15357,13 +14026,13 @@ static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj,
*pdone = 2;
return obj;
fail:
- *pdone = FALSE;
+ *pdone = false;
return JS_EXCEPTION;
}
-static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj,
- JSValueConst method,
- int argc, JSValueConst *argv, BOOL *pdone)
+static JSValue JS_IteratorNext(JSContext *ctx, JSValue enum_obj,
+ JSValue method,
+ int argc, JSValue *argv, int *pdone)
{
JSValue obj, value, done_val;
int done;
@@ -15388,20 +14057,20 @@ static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj,
}
fail:
JS_FreeValue(ctx, obj);
- *pdone = FALSE;
+ *pdone = false;
return JS_EXCEPTION;
}
/* return < 0 in case of exception */
-static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj,
- BOOL is_exception_pending)
+static int JS_IteratorClose(JSContext *ctx, JSValue enum_obj,
+ bool is_exception_pending)
{
JSValue method, ret, ex_obj;
int res;
if (is_exception_pending) {
ex_obj = ctx->rt->current_exception;
- ctx->rt->current_exception = JS_NULL;
+ ctx->rt->current_exception = JS_UNINITIALIZED;
res = -1;
} else {
ex_obj = JS_UNDEFINED;
@@ -15434,7 +14103,7 @@ static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj,
/* obj -> enum_rec (3 slots) */
static __exception int js_for_of_start(JSContext *ctx, JSValue *sp,
- BOOL is_async)
+ bool is_async)
{
JSValue op1, obj, method;
op1 = sp[-1];
@@ -15477,15 +14146,15 @@ static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
}
}
sp[0] = value;
- sp[1] = JS_NewBool(ctx, done);
+ sp[1] = js_bool(done);
return 0;
}
-static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj,
- BOOL *pdone)
+static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValue obj,
+ int *pdone)
{
JSValue done_val, value;
- BOOL done;
+ int done;
done_val = JS_GetProperty(ctx, obj, JS_ATOM_done);
if (JS_IsException(done_val))
goto fail;
@@ -15496,14 +14165,14 @@ static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj,
*pdone = done;
return value;
fail:
- *pdone = FALSE;
+ *pdone = false;
return JS_EXCEPTION;
}
static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)
{
JSValue obj, value;
- BOOL done;
+ int done;
obj = sp[-1];
if (!JS_IsObject(obj)) {
JS_ThrowTypeError(ctx, "iterator must return an object");
@@ -15514,13 +14183,13 @@ static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)
return -1;
JS_FreeValue(ctx, obj);
sp[-1] = value;
- sp[0] = JS_NewBool(ctx, done);
+ sp[0] = js_bool(done);
return 0;
}
static JSValue js_create_iterator_result(JSContext *ctx,
JSValue val,
- BOOL done)
+ bool done)
{
JSValue obj;
obj = JS_NewObject(ctx);
@@ -15533,7 +14202,7 @@ static JSValue js_create_iterator_result(JSContext *ctx,
goto fail;
}
if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_done,
- JS_NewBool(ctx, done), JS_PROP_C_W_E) < 0) {
+ js_bool(done), JS_PROP_C_W_E) < 0) {
fail:
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
@@ -15541,27 +14210,27 @@ static JSValue js_create_iterator_result(JSContext *ctx,
return obj;
}
-static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
- BOOL *pdone, int magic);
+static JSValue js_array_iterator_next(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
+ int *pdone, int magic);
-static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic);
+static JSValue js_create_array_iterator(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic);
-static BOOL js_is_fast_array(JSContext *ctx, JSValueConst obj)
+static bool js_is_fast_array(JSContext *ctx, JSValue obj)
{
/* Try and handle fast arrays explicitly */
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(obj);
if (p->class_id == JS_CLASS_ARRAY && p->fast_array) {
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
/* Access an Array's internal JSValue array if available */
-static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
+static bool js_get_fast_array(JSContext *ctx, JSValue obj,
JSValue **arrpp, uint32_t *countp)
{
/* Try and handle fast arrays explicitly */
@@ -15570,10 +14239,10 @@ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
if (p->class_id == JS_CLASS_ARRAY && p->fast_array) {
*countp = p->u.array.count;
*arrpp = p->u.array.u.values;
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
@@ -15599,12 +14268,14 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
iterator = JS_GetProperty(ctx, sp[-1], JS_ATOM_Symbol_iterator);
if (JS_IsException(iterator))
return -1;
+ /* Used to squelch a -Wcast-function-type warning. */
+ JSCFunctionType ft = { .generic_magic = js_create_array_iterator };
is_array_iterator = JS_IsCFunction(ctx, iterator,
- (JSCFunction *)js_create_array_iterator,
+ ft.generic,
JS_ITERATOR_KIND_VALUE);
JS_FreeValue(ctx, iterator);
- enumobj = JS_GetIterator(ctx, sp[-1], FALSE);
+ enumobj = JS_GetIterator(ctx, sp[-1], false);
if (JS_IsException(enumobj))
return -1;
method = JS_GetProperty(ctx, enumobj, JS_ATOM_next);
@@ -15612,9 +14283,11 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
JS_FreeValue(ctx, enumobj);
return -1;
}
+ /* Used to squelch a -Wcast-function-type warning. */
+ JSCFunctionType ft2 = { .iterator_next = js_array_iterator_next };
if (is_array_iterator
- && JS_IsCFunction(ctx, method, (JSCFunction *)js_array_iterator_next, 0)
- && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) {
+ && JS_IsCFunction(ctx, method, ft2.generic, 0)
+ && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) {
uint32_t len;
if (js_get_length32(ctx, &len, sp[-1]))
goto exception;
@@ -15625,13 +14298,13 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
/* Handle fast arrays explicitly */
for (i = 0; i < count32; i++) {
if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++,
- JS_DupValue(ctx, arrp[i]), JS_PROP_C_W_E) < 0)
+ js_dup(arrp[i]), JS_PROP_C_W_E) < 0)
goto exception;
}
} else {
general_case:
for (;;) {
- BOOL done;
+ int done;
value = JS_IteratorNext(ctx, enumobj, method, 0, NULL, &done);
if (JS_IsException(value))
goto exception;
@@ -15644,23 +14317,23 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
}
}
/* Note: could raise an error if too many elements */
- sp[-2] = JS_NewInt32(ctx, pos);
+ sp[-2] = js_int32(pos);
JS_FreeValue(ctx, enumobj);
JS_FreeValue(ctx, method);
return 0;
exception:
- JS_IteratorClose(ctx, enumobj, TRUE);
+ JS_IteratorClose(ctx, enumobj, true);
JS_FreeValue(ctx, enumobj);
JS_FreeValue(ctx, method);
return -1;
}
static __exception int JS_CopyDataProperties(JSContext *ctx,
- JSValueConst target,
- JSValueConst source,
- JSValueConst excluded,
- BOOL setprop)
+ JSValue target,
+ JSValue source,
+ JSValue excluded,
+ bool setprop)
{
JSPropertyEnum *tab_atom;
JSValue val;
@@ -15669,7 +14342,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx,
JSObject *pexcl = NULL;
int ret, gpn_flags;
JSPropertyDescriptor desc;
- BOOL is_enumerable;
+ bool is_enumerable;
if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT)
return 0;
@@ -15732,19 +14405,19 @@ static __exception int JS_CopyDataProperties(JSContext *ctx,
}
/* only valid inside C functions */
-static JSValueConst JS_GetActiveFunction(JSContext *ctx)
+static JSValue JS_GetActiveFunction(JSContext *ctx)
{
return ctx->rt->current_stack_frame->cur_func;
}
static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf,
- int var_idx, BOOL is_arg)
+ int var_idx, bool is_arg)
{
JSVarRef *var_ref;
struct list_head *el;
list_for_each(el, &sf->var_ref_list) {
- var_ref = list_entry(el, JSVarRef, var_ref_link);
+ var_ref = list_entry(el, JSVarRef, header.link);
if (var_ref->var_idx == var_idx && var_ref->is_arg == is_arg) {
var_ref->header.ref_count++;
return var_ref;
@@ -15755,29 +14428,15 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf,
if (!var_ref)
return NULL;
var_ref->header.ref_count = 1;
- add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);
- var_ref->is_detached = FALSE;
+ var_ref->is_detached = false;
var_ref->is_arg = is_arg;
var_ref->var_idx = var_idx;
- list_add_tail(&var_ref->var_ref_link, &sf->var_ref_list);
- if (sf->js_mode & JS_MODE_ASYNC) {
- /* The stack frame is detached and may be destroyed at any
- time so its reference count must be increased. Calling
- close_var_refs() when destroying the stack frame is not
- possible because it would change the graph between the GC
- objects. Another solution could be to temporarily detach
- the JSVarRef of async functions during the GC. It would
- have the advantage of allowing the release of unused stack
- frames in a cycle. */
- var_ref->async_func = container_of(sf, JSAsyncFunctionState, frame);
- var_ref->async_func->header.ref_count++;
- } else {
- var_ref->async_func = NULL;
- }
+ list_add_tail(&var_ref->header.link, &sf->var_ref_list);
if (is_arg)
var_ref->pvalue = &sf->arg_buf[var_idx];
else
var_ref->pvalue = &sf->var_buf[var_idx];
+ var_ref->value = JS_UNDEFINED;
return var_ref;
}
@@ -15833,7 +14492,7 @@ static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom
set_cycle_flag(ctx, obj);
set_cycle_flag(ctx, this_val);
ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_constructor,
- JS_DupValue(ctx, this_val),
+ js_dup(this_val),
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
if (ret < 0) {
JS_FreeValue(ctx, obj);
@@ -15892,7 +14551,7 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc,
/* add the 'prototype' property: delay instantiation to avoid
creating cycles for every javascript function. The prototype
object is created on the fly when first accessed */
- JS_SetConstructorBit(ctx, func_obj, TRUE);
+ JS_SetConstructorBit(ctx, func_obj, true);
JS_DefineAutoInitProperty(ctx, func_obj, JS_ATOM_prototype,
JS_AUTOINIT_ID_PROTOTYPE, NULL,
JS_PROP_WRITABLE);
@@ -15909,7 +14568,7 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc,
static int js_op_define_class(JSContext *ctx, JSValue *sp,
JSAtom class_name, int class_flags,
JSVarRef **cur_var_refs,
- JSStackFrame *sf, BOOL is_computed_name)
+ JSStackFrame *sf, bool is_computed_name)
{
JSValue bfunc, parent_class, proto = JS_UNDEFINED;
JSValue ctor = JS_UNDEFINED, parent_proto = JS_UNDEFINED;
@@ -15921,7 +14580,7 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp,
if (class_flags & JS_DEFINE_CLASS_HAS_HERITAGE) {
if (JS_IsNull(parent_class)) {
parent_proto = JS_NULL;
- parent_class = JS_DupValue(ctx, ctx->function_proto);
+ parent_class = js_dup(ctx->function_proto);
} else {
if (!JS_IsConstructor(ctx, parent_class)) {
JS_ThrowTypeError(ctx, "parent class must be constructor");
@@ -15937,8 +14596,8 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp,
}
} else {
/* parent_class is JS_UNDEFINED in this case */
- parent_proto = JS_DupValue(ctx, ctx->class_proto[JS_CLASS_OBJECT]);
- parent_class = JS_DupValue(ctx, ctx->function_proto);
+ parent_proto = js_dup(ctx->class_proto[JS_CLASS_OBJECT]);
+ parent_class = js_dup(ctx->function_proto);
}
proto = JS_NewObjectProto(ctx, parent_proto);
if (JS_IsException(proto))
@@ -15955,10 +14614,10 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp,
if (JS_IsException(ctor))
goto fail;
js_method_set_home_object(ctx, ctor, proto);
- JS_SetConstructorBit(ctx, ctor, TRUE);
+ JS_SetConstructorBit(ctx, ctor, true);
JS_DefinePropertyValue(ctx, ctor, JS_ATOM_length,
- JS_NewInt32(ctx, b->defined_arg_count),
+ js_int32(b->defined_arg_count),
JS_PROP_CONFIGURABLE);
if (is_computed_name) {
@@ -15973,13 +14632,13 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp,
/* the constructor property must be first. It can be overriden by
computed property names */
if (JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor,
- JS_DupValue(ctx, ctor),
+ js_dup(ctor),
JS_PROP_CONFIGURABLE |
JS_PROP_WRITABLE | JS_PROP_THROW) < 0)
goto fail;
/* set the prototype property */
if (JS_DefinePropertyValue(ctx, ctor, JS_ATOM_prototype,
- JS_DupValue(ctx, proto), JS_PROP_THROW) < 0)
+ js_dup(proto), JS_PROP_THROW) < 0)
goto fail;
set_cycle_flag(ctx, ctor);
set_cycle_flag(ctx, proto);
@@ -16008,37 +14667,33 @@ static void close_var_refs(JSRuntime *rt, JSStackFrame *sf)
int var_idx;
list_for_each_safe(el, el1, &sf->var_ref_list) {
- var_ref = list_entry(el, JSVarRef, var_ref_link);
- /* no need to unlink var_ref->var_ref_link as the list is never used afterwards */
- if (var_ref->async_func)
- async_func_free(rt, var_ref->async_func);
+ var_ref = list_entry(el, JSVarRef, header.link);
var_idx = var_ref->var_idx;
if (var_ref->is_arg)
- var_ref->value = JS_DupValueRT(rt, sf->arg_buf[var_idx]);
+ var_ref->value = js_dup(sf->arg_buf[var_idx]);
else
- var_ref->value = JS_DupValueRT(rt, sf->var_buf[var_idx]);
+ var_ref->value = js_dup(sf->var_buf[var_idx]);
var_ref->pvalue = &var_ref->value;
/* the reference is no longer to a local variable */
- var_ref->is_detached = TRUE;
+ var_ref->is_detached = true;
+ add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);
}
}
-static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int idx, int is_arg)
+static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int var_idx)
{
struct list_head *el, *el1;
JSVarRef *var_ref;
- int var_idx = idx;
list_for_each_safe(el, el1, &sf->var_ref_list) {
- var_ref = list_entry(el, JSVarRef, var_ref_link);
- if (var_idx == var_ref->var_idx && var_ref->is_arg == is_arg) {
- list_del(&var_ref->var_ref_link);
- if (var_ref->async_func)
- async_func_free(ctx->rt, var_ref->async_func);
- var_ref->value = JS_DupValue(ctx, sf->var_buf[var_idx]);
+ var_ref = list_entry(el, JSVarRef, header.link);
+ if (var_idx == var_ref->var_idx && !var_ref->is_arg) {
+ var_ref->value = js_dup(sf->var_buf[var_idx]);
var_ref->pvalue = &var_ref->value;
+ list_del(&var_ref->header.link);
/* the reference is no longer to a local variable */
- var_ref->is_detached = TRUE;
+ var_ref->is_detached = true;
+ add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);
}
}
}
@@ -16046,16 +14701,16 @@ static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int idx, int is_
#define JS_CALL_FLAG_COPY_ARGV (1 << 1)
#define JS_CALL_FLAG_GENERATOR (1 << 2)
-static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_obj,
- int argc, JSValueConst *argv, int flags)
+static JSValue js_call_c_function(JSContext *ctx, JSValue func_obj,
+ JSValue this_obj,
+ int argc, JSValue *argv, int flags)
{
JSRuntime *rt = ctx->rt;
JSCFunctionType func;
JSObject *p;
JSStackFrame sf_s, *sf = &sf_s, *prev_sf;
JSValue ret_val;
- JSValueConst *arg_buf;
+ JSValue *arg_buf;
int arg_count, i;
JSCFunctionEnum cproto;
@@ -16072,16 +14727,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
rt->current_stack_frame = sf;
ctx = p->u.cfunc.realm; /* change the current realm */
-#ifdef CONFIG_BIGNUM
- /* we only propagate the bignum mode as some runtime functions
- test it */
- if (prev_sf)
- sf->js_mode = prev_sf->js_mode & JS_MODE_MATH;
- else
- sf->js_mode = 0;
-#else
- sf->js_mode = 0;
-#endif
+ sf->is_strict_mode = false;
sf->cur_func = func_obj;
sf->arg_count = argc;
arg_buf = argv;
@@ -16095,7 +14741,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
arg_buf[i] = JS_UNDEFINED;
sf->arg_count = arg_count;
}
- sf->arg_buf = (JSValue*)arg_buf;
+ sf->arg_buf = arg_buf;
func = p->u.cfunc.c_function;
switch(cproto) {
@@ -16149,7 +14795,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
ret_val = JS_EXCEPTION;
break;
}
- ret_val = JS_NewFloat64(ctx, func.f_f(d1));
+ ret_val = js_number(func.f_f(d1));
}
break;
case JS_CFUNC_f_f_f:
@@ -16164,7 +14810,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
ret_val = JS_EXCEPTION;
break;
}
- ret_val = JS_NewFloat64(ctx, func.f_f_f(d1, d2));
+ ret_val = js_number(func.f_f_f(d1, d2));
}
break;
case JS_CFUNC_iterator_next:
@@ -16185,13 +14831,13 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
return ret_val;
}
-static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_obj,
- int argc, JSValueConst *argv, int flags)
+static JSValue js_call_bound_function(JSContext *ctx, JSValue func_obj,
+ JSValue this_obj,
+ int argc, JSValue *argv, int flags)
{
JSObject *p;
JSBoundFunction *bf;
- JSValueConst *arg_buf, new_target;
+ JSValue *arg_buf, new_target;
int arg_count, i;
p = JS_VALUE_GET_OBJ(func_obj);
@@ -16229,14 +14875,31 @@ typedef enum {
OP_SPECIAL_OBJECT_IMPORT_META,
} OPSpecialObjectEnum;
-#define FUNC_RET_AWAIT 0
-#define FUNC_RET_YIELD 1
-#define FUNC_RET_YIELD_STAR 2
-#define FUNC_RET_INITIAL_YIELD 3
+#define FUNC_RET_AWAIT 0
+#define FUNC_RET_YIELD 1
+#define FUNC_RET_YIELD_STAR 2
+
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_*
+static void dump_single_byte_code(JSContext *ctx, const uint8_t *pc,
+ JSFunctionBytecode *b, int start_pos);
+static void print_func_name(JSFunctionBytecode *b);
+#endif
+
+static bool needs_backtrace(JSValue exc)
+{
+ JSObject *p;
+
+ if (JS_VALUE_GET_TAG(exc) != JS_TAG_OBJECT)
+ return false;
+ p = JS_VALUE_GET_OBJ(exc);
+ if (p->class_id != JS_CLASS_ERROR)
+ return false;
+ return !find_own_property1(p, JS_ATOM_stack);
+}
/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */
-static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- JSValueConst this_obj, JSValueConst new_target,
+static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj,
+ JSValue this_obj, JSValue new_target,
int argc, JSValue *argv, int flags)
{
JSRuntime *rt = caller_ctx->rt;
@@ -16244,29 +14907,32 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JSObject *p;
JSFunctionBytecode *b;
JSStackFrame sf_s, *sf = &sf_s;
- const uint8_t *pc;
+ uint8_t *pc;
int opcode, arg_allocated_size, i;
JSValue *local_buf, *stack_buf, *var_buf, *arg_buf, *sp, ret_val, *pval;
JSVarRef **var_refs;
size_t alloca_size;
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_STEP
+#define DUMP_BYTECODE_OR_DONT(pc) \
+ if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_STEP)) dump_single_byte_code(ctx, pc, b, 0);
+#else
+#define DUMP_BYTECODE_OR_DONT(pc)
+#endif
+
#if !DIRECT_DISPATCH
-#define SWITCH(pc) switch (opcode = *pc++)
+#define SWITCH(pc) DUMP_BYTECODE_OR_DONT(pc) switch (opcode = *pc++)
#define CASE(op) case op
#define DEFAULT default
#define BREAK break
#else
- static const void * const dispatch_table[256] = {
+ __extension__ static const void * const dispatch_table[256] = {
#define DEF(id, size, n_pop, n_push, f) && case_OP_ ## id,
-#if SHORT_OPCODES
#define def(id, size, n_pop, n_push, f)
-#else
-#define def(id, size, n_pop, n_push, f) && case_default,
-#endif
#include "quickjs-opcode.h"
[ OP_COUNT ... 255 ] = &&case_default
};
-#define SWITCH(pc) goto *dispatch_table[opcode = *pc++];
+#define SWITCH(pc) DUMP_BYTECODE_OR_DONT(pc) __extension__ ({ goto *dispatch_table[opcode = *pc++]; });
#define CASE(op) case_ ## op
#define DEFAULT case_default
#define BREAK SWITCH(pc)
@@ -16306,10 +14972,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
call_func = rt->class_array[p->class_id].call;
if (!call_func) {
not_a_function:
- return JS_ThrowTypeError(caller_ctx, "not a function");
+ return JS_ThrowTypeErrorNotAFunction(caller_ctx);
}
return call_func(caller_ctx, func_obj, this_obj, argc,
- (JSValueConst *)argv, flags);
+ argv, flags);
}
b = p->u.func.function_bytecode;
@@ -16324,7 +14990,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
if (js_check_stack_overflow(rt, alloca_size))
return JS_ThrowStackOverflow(caller_ctx);
- sf->js_mode = b->js_mode;
+ sf->is_strict_mode = b->is_strict_mode;
arg_buf = argv;
sf->arg_count = argc;
sf->cur_func = func_obj;
@@ -16351,6 +15017,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
stack_buf = var_buf + b->var_count;
sp = stack_buf;
pc = b->byte_code_buf;
+ /* sf->cur_pc must we set to pc before any recursive calls to JS_CallInternal. */
+ sf->cur_pc = NULL;
sf->prev_frame = rt->current_stack_frame;
rt->current_stack_frame = sf;
ctx = b->realm; /* set the current realm */
@@ -16358,6 +15026,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
if (ctx->handleFunctionEntered)
ctx->handleFunctionEntered(ctx, this_obj);
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_STEP
+ if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_STEP))
+ print_func_name(b);
+#endif
+
restart:
for(;;) {
int call_argc;
@@ -16365,14 +15038,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
SWITCH(pc) {
CASE(OP_push_i32):
- *sp++ = JS_NewInt32(ctx, get_u32(pc));
+ *sp++ = js_int32(get_u32(pc));
pc += 4;
BREAK;
CASE(OP_push_const):
- *sp++ = JS_DupValue(ctx, b->cpool[get_u32(pc)]);
+ *sp++ = js_dup(b->cpool[get_u32(pc)]);
pc += 4;
BREAK;
-#if SHORT_OPCODES
CASE(OP_push_minus1):
CASE(OP_push_0):
CASE(OP_push_1):
@@ -16382,21 +15054,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_push_5):
CASE(OP_push_6):
CASE(OP_push_7):
- *sp++ = JS_NewInt32(ctx, opcode - OP_push_0);
+ *sp++ = js_int32(opcode - OP_push_0);
BREAK;
CASE(OP_push_i8):
- *sp++ = JS_NewInt32(ctx, get_i8(pc));
+ *sp++ = js_int32(get_i8(pc));
pc += 1;
BREAK;
CASE(OP_push_i16):
- *sp++ = JS_NewInt32(ctx, get_i16(pc));
+ *sp++ = js_int32(get_i16(pc));
pc += 2;
BREAK;
CASE(OP_push_const8):
- *sp++ = JS_DupValue(ctx, b->cpool[*pc++]);
+ *sp++ = js_dup(b->cpool[*pc++]);
BREAK;
CASE(OP_fclosure8):
- *sp++ = js_closure(ctx, JS_DupValue(ctx, b->cpool[*pc++]), var_refs, sf);
+ *sp++ = js_closure(ctx, js_dup(b->cpool[*pc++]), var_refs, sf);
if (unlikely(JS_IsException(sp[-1])))
goto exception;
BREAK;
@@ -16407,6 +15079,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue val;
+ sf->cur_pc = pc;
val = JS_GetProperty(ctx, sp[-1], JS_ATOM_length);
if (unlikely(JS_IsException(val)))
goto exception;
@@ -16414,7 +15087,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp[-1] = val;
}
BREAK;
-#endif
CASE(OP_push_atom_value):
*sp++ = JS_AtomToValue(ctx, get_u32(pc));
pc += 4;
@@ -16429,12 +15101,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
/* OP_push_this is only called at the start of a function */
{
JSValue val;
- if (!(b->js_mode & JS_MODE_STRICT)) {
+ if (!b->is_strict_mode) {
uint32_t tag = JS_VALUE_GET_TAG(this_obj);
if (likely(tag == JS_TAG_OBJECT))
goto normal_this;
if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED) {
- val = JS_DupValue(ctx, ctx->global_obj);
+ val = js_dup(ctx->global_obj);
} else {
val = JS_ToObject(ctx, this_obj);
if (JS_IsException(val))
@@ -16442,7 +15114,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
}
} else {
normal_this:
- val = JS_DupValue(ctx, this_obj);
+ val = js_dup(this_obj);
}
*sp++ = val;
}
@@ -16463,21 +15135,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int arg = *pc++;
switch(arg) {
case OP_SPECIAL_OBJECT_ARGUMENTS:
- *sp++ = js_build_arguments(ctx, argc, (JSValueConst *)argv);
+ *sp++ = js_build_arguments(ctx, argc, argv);
if (unlikely(JS_IsException(sp[-1])))
goto exception;
break;
case OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS:
- *sp++ = js_build_mapped_arguments(ctx, argc, (JSValueConst *)argv,
+ *sp++ = js_build_mapped_arguments(ctx, argc, argv,
sf, min_int(argc, b->arg_count));
if (unlikely(JS_IsException(sp[-1])))
goto exception;
break;
case OP_SPECIAL_OBJECT_THIS_FUNC:
- *sp++ = JS_DupValue(ctx, sf->cur_func);
+ *sp++ = js_dup(sf->cur_func);
break;
case OP_SPECIAL_OBJECT_NEW_TARGET:
- *sp++ = JS_DupValue(ctx, new_target);
+ *sp++ = js_dup(new_target);
break;
case OP_SPECIAL_OBJECT_HOME_OBJECT:
{
@@ -16486,7 +15158,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
if (unlikely(!p1))
*sp++ = JS_UNDEFINED;
else
- *sp++ = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));
+ *sp++ = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1));
}
break;
case OP_SPECIAL_OBJECT_VAR_OBJECT:
@@ -16506,9 +15178,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_rest):
{
- int first = get_u16(pc);
+ int i, n, first = get_u16(pc);
pc += 2;
- *sp++ = js_build_rest(ctx, first, argc, (JSValueConst *)argv);
+ i = min_int(first, argc);
+ n = argc - i;
+ *sp++ = js_create_array(ctx, n, &argv[i]);
if (unlikely(JS_IsException(sp[-1])))
goto exception;
}
@@ -16530,36 +15204,36 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp--;
BREAK;
CASE(OP_dup):
- sp[0] = JS_DupValue(ctx, sp[-1]);
+ sp[0] = js_dup(sp[-1]);
sp++;
BREAK;
CASE(OP_dup2): /* a b -> a b a b */
- sp[0] = JS_DupValue(ctx, sp[-2]);
- sp[1] = JS_DupValue(ctx, sp[-1]);
+ sp[0] = js_dup(sp[-2]);
+ sp[1] = js_dup(sp[-1]);
sp += 2;
BREAK;
CASE(OP_dup3): /* a b c -> a b c a b c */
- sp[0] = JS_DupValue(ctx, sp[-3]);
- sp[1] = JS_DupValue(ctx, sp[-2]);
- sp[2] = JS_DupValue(ctx, sp[-1]);
+ sp[0] = js_dup(sp[-3]);
+ sp[1] = js_dup(sp[-2]);
+ sp[2] = js_dup(sp[-1]);
sp += 3;
BREAK;
CASE(OP_dup1): /* a b -> a a b */
sp[0] = sp[-1];
- sp[-1] = JS_DupValue(ctx, sp[-2]);
+ sp[-1] = js_dup(sp[-2]);
sp++;
BREAK;
CASE(OP_insert2): /* obj a -> a obj a (dup_x1) */
sp[0] = sp[-1];
sp[-1] = sp[-2];
- sp[-2] = JS_DupValue(ctx, sp[0]);
+ sp[-2] = js_dup(sp[0]);
sp++;
BREAK;
CASE(OP_insert3): /* obj prop a -> a obj prop a (dup_x2) */
sp[0] = sp[-1];
sp[-1] = sp[-2];
sp[-2] = sp[-3];
- sp[-3] = JS_DupValue(ctx, sp[0]);
+ sp[-3] = js_dup(sp[0]);
sp++;
BREAK;
CASE(OP_insert4): /* this obj prop a -> a this obj prop a */
@@ -16567,7 +15241,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp[-1] = sp[-2];
sp[-2] = sp[-3];
sp[-3] = sp[-4];
- sp[-4] = JS_DupValue(ctx, sp[0]);
+ sp[-4] = js_dup(sp[0]);
sp++;
BREAK;
CASE(OP_perm3): /* obj a b -> a obj b (213) */
@@ -16658,21 +15332,19 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_fclosure):
{
- JSValue bfunc = JS_DupValue(ctx, b->cpool[get_u32(pc)]);
+ JSValue bfunc = js_dup(b->cpool[get_u32(pc)]);
pc += 4;
*sp++ = js_closure(ctx, bfunc, var_refs, sf);
if (unlikely(JS_IsException(sp[-1])))
goto exception;
}
BREAK;
-#if SHORT_OPCODES
CASE(OP_call0):
CASE(OP_call1):
CASE(OP_call2):
CASE(OP_call3):
call_argc = opcode - OP_call0;
goto has_call_argc;
-#endif
CASE(OP_call):
CASE(OP_tail_call):
{
@@ -16732,23 +15404,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_array_from):
{
- int i, ret;
-
call_argc = get_u16(pc);
pc += 2;
- ret_val = JS_NewArray(ctx);
+ call_argv = sp - call_argc;
+ ret_val = JS_NewArrayFrom(ctx, call_argc, call_argv);
if (unlikely(JS_IsException(ret_val)))
goto exception;
- call_argv = sp - call_argc;
- for(i = 0; i < call_argc; i++) {
- ret = JS_DefinePropertyValue(ctx, ret_val, __JS_AtomFromUInt32(i), call_argv[i],
- JS_PROP_C_W_E | JS_PROP_THROW);
- call_argv[i] = JS_UNDEFINED;
- if (ret < 0) {
- JS_FreeValue(ctx, ret_val);
- goto exception;
- }
- }
sp -= call_argc;
*sp++ = ret_val;
}
@@ -16759,8 +15420,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int magic;
magic = get_u16(pc);
pc += 2;
+ sf->cur_pc = pc;
- ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic);
+ ret_val = js_function_apply(ctx, sp[-3], 2, &sp[-2], magic);
if (unlikely(JS_IsException(ret_val)))
goto exception;
JS_FreeValue(ctx, sp[-3]);
@@ -16778,7 +15440,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
goto done;
CASE(OP_check_ctor_return):
- /* return TRUE if 'this' should be returned */
+ /* return true if 'this' should be returned */
if (!JS_IsObject(sp[-1])) {
if (!JS_IsUndefined(sp[-1])) {
JS_ThrowTypeError(caller_ctx, "derived class constructor must return an object or undefined");
@@ -16792,10 +15454,27 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_check_ctor):
if (JS_IsUndefined(new_target)) {
+ non_ctor_call:
JS_ThrowTypeError(ctx, "class constructors must be invoked with 'new'");
goto exception;
}
BREAK;
+ CASE(OP_init_ctor):
+ {
+ JSValue super, ret;
+ sf->cur_pc = pc;
+ if (JS_IsUndefined(new_target))
+ goto non_ctor_call;
+ super = JS_GetPrototype(ctx, func_obj);
+ if (JS_IsException(super))
+ goto exception;
+ ret = JS_CallConstructor2(ctx, super, new_target, argc, argv);
+ JS_FreeValue(ctx, super);
+ if (JS_IsException(ret))
+ goto exception;
+ *sp++ = ret;
+ }
+ BREAK;
CASE(OP_check_brand):
{
int ret = JS_CheckBrand(ctx, sp[-2], sp[-1]);
@@ -16852,7 +15531,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_eval):
{
- JSValueConst obj;
+ JSValue obj;
int scope_idx;
call_argc = get_u16(pc);
scope_idx = get_u16(pc + 2) - 1;
@@ -16884,10 +15563,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int scope_idx;
uint32_t len;
JSValue *tab;
- JSValueConst obj;
+ JSValue obj;
scope_idx = get_u16(pc) - 1;
pc += 2;
+ sf->cur_pc = pc;
tab = build_arg_list(ctx, &len, sp[-1]);
if (!tab)
goto exception;
@@ -16900,7 +15580,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JS_EVAL_TYPE_DIRECT, scope_idx);
} else {
ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len,
- (JSValueConst *)tab);
+ tab);
}
free_arg_list(ctx, tab, len);
if (unlikely(JS_IsException(ret_val)))
@@ -16934,6 +15614,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_import):
{
JSValue val;
+ sf->cur_pc = pc;
val = js_dynamic_import(ctx, sp[-1]);
if (JS_IsException(val))
goto exception;
@@ -16952,7 +15633,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
ret = JS_CheckGlobalVar(ctx, atom);
if (ret < 0)
goto exception;
- *sp++ = JS_NewBool(ctx, ret);
+ *sp++ = js_bool(ret);
}
BREAK;
@@ -16963,6 +15644,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JSAtom atom;
atom = get_u32(pc);
pc += 4;
+ sf->cur_pc = pc;
val = JS_GetGlobalVar(ctx, atom, opcode - OP_get_var_undef);
if (unlikely(JS_IsException(val)))
@@ -16978,6 +15660,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JSAtom atom;
atom = get_u32(pc);
pc += 4;
+ sf->cur_pc = pc;
ret = JS_SetGlobalVar(ctx, atom, sp[-1], opcode - OP_put_var);
sp--;
@@ -16992,6 +15675,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JSAtom atom;
atom = get_u32(pc);
pc += 4;
+ sf->cur_pc = pc;
/* sp[-2] is JS_TRUE or JS_FALSE */
if (unlikely(!JS_VALUE_GET_INT(sp[-2]))) {
@@ -17046,7 +15730,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int idx;
idx = get_u16(pc);
pc += 2;
- sp[0] = JS_DupValue(ctx, var_buf[idx]);
+ sp[0] = js_dup(var_buf[idx]);
sp++;
}
BREAK;
@@ -17064,7 +15748,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int idx;
idx = get_u16(pc);
pc += 2;
- set_value(ctx, &var_buf[idx], JS_DupValue(ctx, sp[-1]));
+ set_value(ctx, &var_buf[idx], js_dup(sp[-1]));
}
BREAK;
CASE(OP_get_arg):
@@ -17072,7 +15756,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int idx;
idx = get_u16(pc);
pc += 2;
- sp[0] = JS_DupValue(ctx, arg_buf[idx]);
+ sp[0] = js_dup(arg_buf[idx]);
sp++;
}
BREAK;
@@ -17090,52 +15774,58 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int idx;
idx = get_u16(pc);
pc += 2;
- set_value(ctx, &arg_buf[idx], JS_DupValue(ctx, sp[-1]));
+ set_value(ctx, &arg_buf[idx], js_dup(sp[-1]));
}
BREAK;
-#if SHORT_OPCODES
- CASE(OP_get_loc8): *sp++ = JS_DupValue(ctx, var_buf[*pc++]); BREAK;
+ CASE(OP_get_loc8): *sp++ = js_dup(var_buf[*pc++]); BREAK;
CASE(OP_put_loc8): set_value(ctx, &var_buf[*pc++], *--sp); BREAK;
- CASE(OP_set_loc8): set_value(ctx, &var_buf[*pc++], JS_DupValue(ctx, sp[-1])); BREAK;
+ CASE(OP_set_loc8): set_value(ctx, &var_buf[*pc++], js_dup(sp[-1])); BREAK;
+
+ // Observation: get_loc0 and get_loc1 are individually very
+ // frequent opcodes _and_ they are very often paired together,
+ // making them ideal candidates for opcode fusion.
+ CASE(OP_get_loc0_loc1):
+ *sp++ = js_dup(var_buf[0]);
+ *sp++ = js_dup(var_buf[1]);
+ BREAK;
- CASE(OP_get_loc0): *sp++ = JS_DupValue(ctx, var_buf[0]); BREAK;
- CASE(OP_get_loc1): *sp++ = JS_DupValue(ctx, var_buf[1]); BREAK;
- CASE(OP_get_loc2): *sp++ = JS_DupValue(ctx, var_buf[2]); BREAK;
- CASE(OP_get_loc3): *sp++ = JS_DupValue(ctx, var_buf[3]); BREAK;
+ CASE(OP_get_loc0): *sp++ = js_dup(var_buf[0]); BREAK;
+ CASE(OP_get_loc1): *sp++ = js_dup(var_buf[1]); BREAK;
+ CASE(OP_get_loc2): *sp++ = js_dup(var_buf[2]); BREAK;
+ CASE(OP_get_loc3): *sp++ = js_dup(var_buf[3]); BREAK;
CASE(OP_put_loc0): set_value(ctx, &var_buf[0], *--sp); BREAK;
CASE(OP_put_loc1): set_value(ctx, &var_buf[1], *--sp); BREAK;
CASE(OP_put_loc2): set_value(ctx, &var_buf[2], *--sp); BREAK;
CASE(OP_put_loc3): set_value(ctx, &var_buf[3], *--sp); BREAK;
- CASE(OP_set_loc0): set_value(ctx, &var_buf[0], JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_set_loc1): set_value(ctx, &var_buf[1], JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_set_loc2): set_value(ctx, &var_buf[2], JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_set_loc3): set_value(ctx, &var_buf[3], JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_get_arg0): *sp++ = JS_DupValue(ctx, arg_buf[0]); BREAK;
- CASE(OP_get_arg1): *sp++ = JS_DupValue(ctx, arg_buf[1]); BREAK;
- CASE(OP_get_arg2): *sp++ = JS_DupValue(ctx, arg_buf[2]); BREAK;
- CASE(OP_get_arg3): *sp++ = JS_DupValue(ctx, arg_buf[3]); BREAK;
+ CASE(OP_set_loc0): set_value(ctx, &var_buf[0], js_dup(sp[-1])); BREAK;
+ CASE(OP_set_loc1): set_value(ctx, &var_buf[1], js_dup(sp[-1])); BREAK;
+ CASE(OP_set_loc2): set_value(ctx, &var_buf[2], js_dup(sp[-1])); BREAK;
+ CASE(OP_set_loc3): set_value(ctx, &var_buf[3], js_dup(sp[-1])); BREAK;
+ CASE(OP_get_arg0): *sp++ = js_dup(arg_buf[0]); BREAK;
+ CASE(OP_get_arg1): *sp++ = js_dup(arg_buf[1]); BREAK;
+ CASE(OP_get_arg2): *sp++ = js_dup(arg_buf[2]); BREAK;
+ CASE(OP_get_arg3): *sp++ = js_dup(arg_buf[3]); BREAK;
CASE(OP_put_arg0): set_value(ctx, &arg_buf[0], *--sp); BREAK;
CASE(OP_put_arg1): set_value(ctx, &arg_buf[1], *--sp); BREAK;
CASE(OP_put_arg2): set_value(ctx, &arg_buf[2], *--sp); BREAK;
CASE(OP_put_arg3): set_value(ctx, &arg_buf[3], *--sp); BREAK;
- CASE(OP_set_arg0): set_value(ctx, &arg_buf[0], JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_set_arg1): set_value(ctx, &arg_buf[1], JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_set_arg2): set_value(ctx, &arg_buf[2], JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_set_arg3): set_value(ctx, &arg_buf[3], JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_get_var_ref0): *sp++ = JS_DupValue(ctx, *var_refs[0]->pvalue); BREAK;
- CASE(OP_get_var_ref1): *sp++ = JS_DupValue(ctx, *var_refs[1]->pvalue); BREAK;
- CASE(OP_get_var_ref2): *sp++ = JS_DupValue(ctx, *var_refs[2]->pvalue); BREAK;
- CASE(OP_get_var_ref3): *sp++ = JS_DupValue(ctx, *var_refs[3]->pvalue); BREAK;
+ CASE(OP_set_arg0): set_value(ctx, &arg_buf[0], js_dup(sp[-1])); BREAK;
+ CASE(OP_set_arg1): set_value(ctx, &arg_buf[1], js_dup(sp[-1])); BREAK;
+ CASE(OP_set_arg2): set_value(ctx, &arg_buf[2], js_dup(sp[-1])); BREAK;
+ CASE(OP_set_arg3): set_value(ctx, &arg_buf[3], js_dup(sp[-1])); BREAK;
+ CASE(OP_get_var_ref0): *sp++ = js_dup(*var_refs[0]->pvalue); BREAK;
+ CASE(OP_get_var_ref1): *sp++ = js_dup(*var_refs[1]->pvalue); BREAK;
+ CASE(OP_get_var_ref2): *sp++ = js_dup(*var_refs[2]->pvalue); BREAK;
+ CASE(OP_get_var_ref3): *sp++ = js_dup(*var_refs[3]->pvalue); BREAK;
CASE(OP_put_var_ref0): set_value(ctx, var_refs[0]->pvalue, *--sp); BREAK;
CASE(OP_put_var_ref1): set_value(ctx, var_refs[1]->pvalue, *--sp); BREAK;
CASE(OP_put_var_ref2): set_value(ctx, var_refs[2]->pvalue, *--sp); BREAK;
CASE(OP_put_var_ref3): set_value(ctx, var_refs[3]->pvalue, *--sp); BREAK;
- CASE(OP_set_var_ref0): set_value(ctx, var_refs[0]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_set_var_ref1): set_value(ctx, var_refs[1]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_set_var_ref2): set_value(ctx, var_refs[2]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;
- CASE(OP_set_var_ref3): set_value(ctx, var_refs[3]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;
-#endif
+ CASE(OP_set_var_ref0): set_value(ctx, var_refs[0]->pvalue, js_dup(sp[-1])); BREAK;
+ CASE(OP_set_var_ref1): set_value(ctx, var_refs[1]->pvalue, js_dup(sp[-1])); BREAK;
+ CASE(OP_set_var_ref2): set_value(ctx, var_refs[2]->pvalue, js_dup(sp[-1])); BREAK;
+ CASE(OP_set_var_ref3): set_value(ctx, var_refs[3]->pvalue, js_dup(sp[-1])); BREAK;
CASE(OP_get_var_ref):
{
@@ -17144,7 +15834,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
idx = get_u16(pc);
pc += 2;
val = *var_refs[idx]->pvalue;
- sp[0] = JS_DupValue(ctx, val);
+ sp[0] = js_dup(val);
sp++;
}
BREAK;
@@ -17162,7 +15852,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int idx;
idx = get_u16(pc);
pc += 2;
- set_value(ctx, var_refs[idx]->pvalue, JS_DupValue(ctx, sp[-1]));
+ set_value(ctx, var_refs[idx]->pvalue, js_dup(sp[-1]));
}
BREAK;
CASE(OP_get_var_ref_check):
@@ -17173,10 +15863,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
pc += 2;
val = *var_refs[idx]->pvalue;
if (unlikely(JS_IsUninitialized(val))) {
- JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE);
+ JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, true);
goto exception;
}
- sp[0] = JS_DupValue(ctx, val);
+ sp[0] = js_dup(val);
sp++;
}
BREAK;
@@ -17186,7 +15876,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
idx = get_u16(pc);
pc += 2;
if (unlikely(JS_IsUninitialized(*var_refs[idx]->pvalue))) {
- JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE);
+ JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, true);
goto exception;
}
set_value(ctx, var_refs[idx]->pvalue, sp[-1]);
@@ -17199,7 +15889,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
idx = get_u16(pc);
pc += 2;
if (unlikely(!JS_IsUninitialized(*var_refs[idx]->pvalue))) {
- JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE);
+ JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, true);
goto exception;
}
set_value(ctx, var_refs[idx]->pvalue, sp[-1]);
@@ -17220,23 +15910,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
idx = get_u16(pc);
pc += 2;
if (unlikely(JS_IsUninitialized(var_buf[idx]))) {
- JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, FALSE);
+ JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx,
+ false);
goto exception;
}
- sp[0] = JS_DupValue(ctx, var_buf[idx]);
- sp++;
- }
- BREAK;
- CASE(OP_get_loc_checkthis):
- {
- int idx;
- idx = get_u16(pc);
- pc += 2;
- if (unlikely(JS_IsUninitialized(var_buf[idx]))) {
- JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx, FALSE);
- goto exception;
- }
- sp[0] = JS_DupValue(ctx, var_buf[idx]);
+ sp[0] = js_dup(var_buf[idx]);
sp++;
}
BREAK;
@@ -17246,7 +15924,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
idx = get_u16(pc);
pc += 2;
if (unlikely(JS_IsUninitialized(var_buf[idx]))) {
- JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, FALSE);
+ JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx,
+ false);
goto exception;
}
set_value(ctx, &var_buf[idx], sp[-1]);
@@ -17259,7 +15938,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
idx = get_u16(pc);
pc += 2;
if (unlikely(!JS_IsUninitialized(var_buf[idx]))) {
- JS_ThrowReferenceError(ctx, "'this' can be initialized only once");
+ JS_ThrowReferenceError(caller_ctx,
+ "'this' can be initialized only once");
goto exception;
}
set_value(ctx, &var_buf[idx], sp[-1]);
@@ -17271,7 +15951,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int idx;
idx = get_u16(pc);
pc += 2;
- close_lexical_var(ctx, sf, idx, FALSE);
+ close_lexical_var(ctx, sf, idx);
}
BREAK;
@@ -17324,7 +16004,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
if (unlikely(js_poll_interrupts(ctx)))
goto exception;
BREAK;
-#if SHORT_OPCODES
CASE(OP_goto16):
pc += (int16_t)get_u16(pc);
if (unlikely(js_poll_interrupts(ctx)))
@@ -17335,7 +16014,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
if (unlikely(js_poll_interrupts(ctx)))
goto exception;
BREAK;
-#endif
CASE(OP_if_true):
{
int res;
@@ -17363,7 +16041,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
op1 = sp[-1];
pc += 4;
- /* quick and dirty test for JS_TAG_INT, JS_TAG_BOOL, JS_TAG_NULL and JS_TAG_UNDEFINED */
if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {
res = JS_VALUE_GET_INT(op1);
} else {
@@ -17377,7 +16054,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
goto exception;
}
BREAK;
-#if SHORT_OPCODES
CASE(OP_if_true8):
{
int res;
@@ -17418,7 +16094,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
goto exception;
}
BREAK;
-#endif
CASE(OP_catch):
{
int32_t diff;
@@ -17433,7 +16108,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int32_t diff;
diff = get_u32(pc);
/* XXX: should have a different tag to avoid security flaw */
- sp[0] = JS_NewInt32(ctx, pc + 4 - b->byte_code_buf);
+ sp[0] = js_int32(pc + 4 - b->byte_code_buf);
sp++;
pc += diff;
}
@@ -17457,16 +16132,19 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_for_in_start):
+ sf->cur_pc = pc;
if (js_for_in_start(ctx, sp))
goto exception;
BREAK;
CASE(OP_for_in_next):
+ sf->cur_pc = pc;
if (js_for_in_next(ctx, sp))
goto exception;
sp += 2;
BREAK;
CASE(OP_for_of_start):
- if (js_for_of_start(ctx, sp, FALSE))
+ sf->cur_pc = pc;
+ if (js_for_of_start(ctx, sp, false))
goto exception;
sp += 1;
*sp++ = JS_NewCatchOffset(ctx, 0);
@@ -17475,18 +16153,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
int offset = -3 - pc[0];
pc += 1;
+ sf->cur_pc = pc;
if (js_for_of_next(ctx, sp, offset))
goto exception;
sp += 2;
}
BREAK;
CASE(OP_for_await_of_start):
- if (js_for_of_start(ctx, sp, TRUE))
+ sf->cur_pc = pc;
+ if (js_for_of_start(ctx, sp, true))
goto exception;
sp += 1;
*sp++ = JS_NewCatchOffset(ctx, 0);
BREAK;
CASE(OP_iterator_get_value_done):
+ sf->cur_pc = pc;
if (js_iterator_get_value_done(ctx, sp))
goto exception;
sp += 1;
@@ -17504,7 +16185,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JS_FreeValue(ctx, sp[-1]); /* drop the next method */
sp--;
if (!JS_IsUndefined(sp[-1])) {
- if (JS_IteratorClose(ctx, sp[-1], FALSE))
+ sf->cur_pc = pc;
+ if (JS_IteratorClose(ctx, sp[-1], false))
goto exception;
JS_FreeValue(ctx, sp[-1]);
}
@@ -17532,8 +16214,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
/* stack: iter_obj next catch_offset val */
{
JSValue ret;
- ret = JS_Call(ctx, sp[-3], sp[-4],
- 1, (JSValueConst *)(sp - 1));
+ sf->cur_pc = pc;
+ ret = JS_Call(ctx, sp[-3], sp[-4], 1, (sp - 1));
if (JS_IsException(ret))
goto exception;
JS_FreeValue(ctx, sp[-1]);
@@ -17545,15 +16227,16 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
/* stack: iter_obj next catch_offset val */
{
JSValue method, ret;
- BOOL ret_flag;
+ bool ret_flag;
int flags;
flags = *pc++;
+ sf->cur_pc = pc;
method = JS_GetProperty(ctx, sp[-4], (flags & 1) ?
JS_ATOM_throw : JS_ATOM_return);
if (JS_IsException(method))
goto exception;
if (JS_IsUndefined(method) || JS_IsNull(method)) {
- ret_flag = TRUE;
+ ret_flag = true;
} else {
if (flags & 2) {
/* no argument */
@@ -17561,15 +16244,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
0, NULL);
} else {
ret = JS_CallFree(ctx, method, sp[-4],
- 1, (JSValueConst *)(sp - 1));
+ 1, (sp - 1));
}
if (JS_IsException(ret))
goto exception;
JS_FreeValue(ctx, sp[-1]);
sp[-1] = ret;
- ret_flag = FALSE;
+ ret_flag = false;
}
- sp[0] = JS_NewBool(ctx, ret_flag);
+ sp[0] = js_bool(ret_flag);
sp += 1;
}
BREAK;
@@ -17585,7 +16268,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
} else {
res = JS_ToBoolFree(ctx, op1);
}
- sp[-1] = JS_NewBool(ctx, !res);
+ sp[-1] = js_bool(!res);
}
BREAK;
@@ -17595,8 +16278,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JSAtom atom;
atom = get_u32(pc);
pc += 4;
-
- val = JS_GetProperty(ctx, sp[-1], atom);
+ sf->cur_pc = pc;
+ val = JS_GetPropertyInternal(ctx, sp[-1], atom, sp[-1], false);
if (unlikely(JS_IsException(val)))
goto exception;
JS_FreeValue(ctx, sp[-1]);
@@ -17610,13 +16293,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JSAtom atom;
atom = get_u32(pc);
pc += 4;
-
- val = JS_GetProperty(ctx, sp[-1], atom);
+ sf->cur_pc = pc;
+ val = JS_GetPropertyInternal(ctx, sp[-1], atom, sp[-1], false);
if (unlikely(JS_IsException(val)))
goto exception;
*sp++ = val;
- }
- BREAK;
+ }
+ BREAK;
CASE(OP_put_field):
{
@@ -17624,9 +16307,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JSAtom atom;
atom = get_u32(pc);
pc += 4;
-
- ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1], sp[-2],
- JS_PROP_THROW_STRICT);
+ sf->cur_pc = pc;
+ ret = JS_SetPropertyInternal2(ctx,
+ sp[-2], atom,
+ sp[-1], sp[-2],
+ JS_PROP_THROW_STRICT);
JS_FreeValue(ctx, sp[-2]);
sp -= 2;
if (unlikely(ret < 0))
@@ -17651,7 +16336,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_get_private_field):
{
JSValue val;
-
+ sf->cur_pc = pc;
val = JS_GetPrivateField(ctx, sp[-2], sp[-1]);
JS_FreeValue(ctx, sp[-1]);
JS_FreeValue(ctx, sp[-2]);
@@ -17665,6 +16350,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_put_private_field):
{
int ret;
+ sf->cur_pc = pc;
ret = JS_SetPrivateField(ctx, sp[-3], sp[-1], sp[-2]);
JS_FreeValue(ctx, sp[-3]);
JS_FreeValue(ctx, sp[-1]);
@@ -17725,7 +16411,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JSValue proto;
proto = sp[-1];
if (JS_IsObject(proto) || JS_IsNull(proto)) {
- if (JS_SetPrototypeInternal(ctx, sp[-2], proto, TRUE) < 0)
+ if (JS_SetPrototypeInternal(ctx, sp[-2], proto, true) < 0)
goto exception;
}
JS_FreeValue(ctx, proto);
@@ -17739,10 +16425,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_define_method_computed):
{
JSValue getter, setter, value;
- JSValueConst obj;
+ JSValue obj;
JSAtom atom;
int flags, ret, op_flags;
- BOOL is_computed;
+ bool is_computed;
#define OP_DEFINE_METHOD_METHOD 0
#define OP_DEFINE_METHOD_GETTER 1
#define OP_DEFINE_METHOD_SETTER 2
@@ -17815,6 +16501,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue val;
+ sf->cur_pc = pc;
val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);
JS_FreeValue(ctx, sp[-2]);
sp[-2] = val;
@@ -17828,6 +16515,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue val;
+ sf->cur_pc = pc;
val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);
sp[-1] = val;
if (unlikely(JS_IsException(val)))
@@ -17838,6 +16526,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_get_ref_value):
{
JSValue val;
+ sf->cur_pc = pc;
if (unlikely(JS_IsUndefined(sp[-2]))) {
JSAtom atom = JS_ValueToAtom(ctx, sp[-1]);
if (atom != JS_ATOM_NULL) {
@@ -17847,7 +16536,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
goto exception;
}
val = JS_GetPropertyValue(ctx, sp[-2],
- JS_DupValue(ctx, sp[-1]));
+ js_dup(sp[-1]));
if (unlikely(JS_IsException(val)))
goto exception;
sp[0] = val;
@@ -17859,10 +16548,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue val;
JSAtom atom;
+ sf->cur_pc = pc;
atom = JS_ValueToAtom(ctx, sp[-1]);
if (unlikely(atom == JS_ATOM_NULL))
goto exception;
- val = JS_GetPropertyInternal(ctx, sp[-2], atom, sp[-3], FALSE);
+ val = JS_GetPropertyInternal(ctx, sp[-2], atom, sp[-3], false);
JS_FreeAtom(ctx, atom);
if (unlikely(JS_IsException(val)))
goto exception;
@@ -17877,7 +16567,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_put_array_el):
{
int ret;
-
+ sf->cur_pc = pc;
ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT);
JS_FreeValue(ctx, sp[-3]);
sp -= 3;
@@ -17889,6 +16579,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_put_ref_value):
{
int ret, flags;
+ sf->cur_pc = pc;
flags = JS_PROP_THROW_STRICT;
if (unlikely(JS_IsUndefined(sp[-3]))) {
if (is_strict_mode(ctx)) {
@@ -17899,7 +16590,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
}
goto exception;
} else {
- sp[-3] = JS_DupValue(ctx, ctx->global_obj);
+ sp[-3] = js_dup(ctx->global_obj);
}
} else {
if (is_strict_mode(ctx))
@@ -17917,6 +16608,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
int ret;
JSAtom atom;
+ sf->cur_pc = pc;
if (JS_VALUE_GET_TAG(sp[-3]) != JS_TAG_OBJECT) {
JS_ThrowTypeErrorNotAnObject(ctx);
goto exception;
@@ -17924,8 +16616,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
atom = JS_ValueToAtom(ctx, sp[-2]);
if (unlikely(atom == JS_ATOM_NULL))
goto exception;
- ret = JS_SetPropertyInternal(ctx, sp[-3], atom, sp[-1], sp[-4],
- JS_PROP_THROW_STRICT);
+ ret = JS_SetPropertyInternal2(ctx,
+ sp[-3], atom,
+ sp[-1], sp[-4],
+ JS_PROP_THROW_STRICT);
JS_FreeAtom(ctx, atom);
JS_FreeValue(ctx, sp[-4]);
JS_FreeValue(ctx, sp[-3]);
@@ -17939,7 +16633,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_define_array_el):
{
int ret;
- ret = JS_DefinePropertyValueValue(ctx, sp[-3], JS_DupValue(ctx, sp[-2]), sp[-1],
+ ret = JS_DefinePropertyValueValue(ctx, sp[-3], js_dup(sp[-2]), sp[-1],
JS_PROP_C_W_E | JS_PROP_THROW);
sp -= 1;
if (unlikely(ret < 0))
@@ -17949,6 +16643,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_append): /* array pos enumobj -- array pos */
{
+ sf->cur_pc = pc;
if (js_append_enumerate(ctx, sp))
goto exception;
JS_FreeValue(ctx, *--sp);
@@ -17964,6 +16659,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int mask;
mask = *pc++;
+ sf->cur_pc = pc;
if (JS_CopyDataProperties(ctx, sp[-1 - (mask & 3)],
sp[-1 - ((mask >> 2) & 7)],
sp[-1 - ((mask >> 5) & 7)], 0))
@@ -17981,19 +16677,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
r = (int64_t)JS_VALUE_GET_INT(op1) + JS_VALUE_GET_INT(op2);
if (unlikely((int)r != r))
goto add_slow;
- sp[-2] = JS_NewInt32(ctx, r);
+ sp[-2] = js_int32(r);
sp--;
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
- sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) +
- JS_VALUE_GET_FLOAT64(op2));
+ sp[-2] = js_float64(JS_VALUE_GET_FLOAT64(op1) +
+ JS_VALUE_GET_FLOAT64(op2));
sp--;
- } else if (JS_IsString(op1) && JS_IsString(op2)) {
- sp[-2] = JS_ConcatString(ctx, op1, op2);
- sp--;
- if (JS_IsException(sp[-1]))
- goto exception;
} else {
add_slow:
+ sf->cur_pc = pc;
if (js_add_slow(ctx, sp))
goto exception;
sp--;
@@ -18002,45 +16694,40 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_add_loc):
{
- JSValue op2;
JSValue *pv;
int idx;
idx = *pc;
pc += 1;
- op2 = sp[-1];
pv = &var_buf[idx];
- if (likely(JS_VALUE_IS_BOTH_INT(*pv, op2))) {
+ if (likely(JS_VALUE_IS_BOTH_INT(*pv, sp[-1]))) {
int64_t r;
- r = (int64_t)JS_VALUE_GET_INT(*pv) + JS_VALUE_GET_INT(op2);
+ r = (int64_t)JS_VALUE_GET_INT(*pv) +
+ JS_VALUE_GET_INT(sp[-1]);
if (unlikely((int)r != r))
goto add_loc_slow;
- *pv = JS_NewInt32(ctx, r);
- sp--;
- } else if (JS_VALUE_IS_BOTH_FLOAT(*pv, op2)) {
- *pv = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(*pv) +
- JS_VALUE_GET_FLOAT64(op2));
+ *pv = js_int32(r);
sp--;
} else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) {
+ JSValue op1;
+ op1 = sp[-1];
sp--;
- op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
- if (JS_IsException(op2))
+ sf->cur_pc = pc;
+ op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
+ if (JS_IsException(op1))
goto exception;
- if (JS_ConcatStringInPlace(ctx, JS_VALUE_GET_STRING(*pv), op2)) {
- JS_FreeValue(ctx, op2);
- } else {
- op2 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op2);
- if (JS_IsException(op2))
- goto exception;
- set_value(ctx, pv, op2);
- }
+ op1 = JS_ConcatString(ctx, js_dup(*pv), op1);
+ if (JS_IsException(op1))
+ goto exception;
+ set_value(ctx, pv, op1);
} else {
JSValue ops[2];
add_loc_slow:
/* In case of exception, js_add_slow frees ops[0]
and ops[1], so we must duplicate *pv */
- ops[0] = JS_DupValue(ctx, *pv);
- ops[1] = op2;
+ sf->cur_pc = pc;
+ ops[0] = js_dup(*pv);
+ ops[1] = sp[-1];
sp--;
if (js_add_slow(ctx, ops + 2))
goto exception;
@@ -18058,11 +16745,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
r = (int64_t)JS_VALUE_GET_INT(op1) - JS_VALUE_GET_INT(op2);
if (unlikely((int)r != r))
goto binary_arith_slow;
- sp[-2] = JS_NewInt32(ctx, r);
+ sp[-2] = js_int32(r);
sp--;
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
- sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) -
- JS_VALUE_GET_FLOAT64(op2));
+ sp[-2] = js_float64(JS_VALUE_GET_FLOAT64(op1) -
+ JS_VALUE_GET_FLOAT64(op2));
sp--;
} else {
goto binary_arith_slow;
@@ -18082,11 +16769,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
v2 = JS_VALUE_GET_INT(op2);
r = (int64_t)v1 * v2;
if (unlikely((int)r != r)) {
-#ifdef CONFIG_BIGNUM
- if (unlikely(sf->js_mode & JS_MODE_MATH) &&
- (r < -MAX_SAFE_INTEGER || r > MAX_SAFE_INTEGER))
- goto binary_arith_slow;
-#endif
d = (double)r;
goto mul_fp_res;
}
@@ -18095,16 +16777,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
d = -0.0;
goto mul_fp_res;
}
- sp[-2] = JS_NewInt32(ctx, r);
+ sp[-2] = js_int32(r);
sp--;
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
-#ifdef CONFIG_BIGNUM
- if (unlikely(sf->js_mode & JS_MODE_MATH))
- goto binary_arith_slow;
-#endif
d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2);
mul_fp_res:
- sp[-2] = __JS_NewFloat64(ctx, d);
+ sp[-2] = js_float64(d);
sp--;
} else {
goto binary_arith_slow;
@@ -18118,11 +16796,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
op2 = sp[-1];
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
int v1, v2;
- if (unlikely(sf->js_mode & JS_MODE_MATH))
- goto binary_arith_slow;
v1 = JS_VALUE_GET_INT(op1);
v2 = JS_VALUE_GET_INT(op2);
- sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2);
+ sp[-2] = js_number((double)v1 / (double)v2);
sp--;
} else {
goto binary_arith_slow;
@@ -18130,9 +16806,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
}
BREAK;
CASE(OP_mod):
-#ifdef CONFIG_BIGNUM
- CASE(OP_math_mod):
-#endif
{
JSValue op1, op2;
op1 = sp[-2];
@@ -18146,7 +16819,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
if (unlikely(v1 < 0 || v2 <= 0))
goto binary_arith_slow;
r = v1 % v2;
- sp[-2] = JS_NewInt32(ctx, r);
+ sp[-2] = js_int32(r);
sp--;
} else {
goto binary_arith_slow;
@@ -18155,6 +16828,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_pow):
binary_arith_slow:
+ sf->cur_pc = pc;
if (js_binary_arith_slow(ctx, sp, opcode))
goto exception;
sp--;
@@ -18168,6 +16842,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
tag = JS_VALUE_GET_TAG(op1);
if (tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag)) {
} else {
+ sf->cur_pc = pc;
if (js_unary_arith_slow(ctx, sp, opcode))
goto exception;
}
@@ -18192,12 +16867,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
d = -(double)val;
goto neg_fp_res;
}
- sp[-1] = JS_NewInt32(ctx, -val);
+ sp[-1] = js_int32(-val);
} else if (JS_TAG_IS_FLOAT64(tag)) {
d = -JS_VALUE_GET_FLOAT64(op1);
neg_fp_res:
- sp[-1] = __JS_NewFloat64(ctx, d);
+ sp[-1] = js_float64(d);
} else {
+ sf->cur_pc = pc;
if (js_unary_arith_slow(ctx, sp, opcode))
goto exception;
}
@@ -18212,9 +16888,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
val = JS_VALUE_GET_INT(op1);
if (unlikely(val == INT32_MAX))
goto inc_slow;
- sp[-1] = JS_NewInt32(ctx, val + 1);
+ sp[-1] = js_int32(val + 1);
} else {
inc_slow:
+ sf->cur_pc = pc;
if (js_unary_arith_slow(ctx, sp, opcode))
goto exception;
}
@@ -18229,9 +16906,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
val = JS_VALUE_GET_INT(op1);
if (unlikely(val == INT32_MIN))
goto dec_slow;
- sp[-1] = JS_NewInt32(ctx, val - 1);
+ sp[-1] = js_int32(val - 1);
} else {
dec_slow:
+ sf->cur_pc = pc;
if (js_unary_arith_slow(ctx, sp, opcode))
goto exception;
}
@@ -18239,6 +16917,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_post_inc):
CASE(OP_post_dec):
+ sf->cur_pc = pc;
if (js_post_inc_slow(ctx, sp, opcode))
goto exception;
sp++;
@@ -18256,12 +16935,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
val = JS_VALUE_GET_INT(op1);
if (unlikely(val == INT32_MAX))
goto inc_loc_slow;
- var_buf[idx] = JS_NewInt32(ctx, val + 1);
+ var_buf[idx] = js_int32(val + 1);
} else {
inc_loc_slow:
+ sf->cur_pc = pc;
/* must duplicate otherwise the variable value may
be destroyed before JS code accesses it */
- op1 = JS_DupValue(ctx, op1);
+ op1 = js_dup(op1);
if (js_unary_arith_slow(ctx, &op1 + 1, OP_inc))
goto exception;
set_value(ctx, &var_buf[idx], op1);
@@ -18281,12 +16961,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
val = JS_VALUE_GET_INT(op1);
if (unlikely(val == INT32_MIN))
goto dec_loc_slow;
- var_buf[idx] = JS_NewInt32(ctx, val - 1);
+ var_buf[idx] = js_int32(val - 1);
} else {
dec_loc_slow:
+ sf->cur_pc = pc;
/* must duplicate otherwise the variable value may
be destroyed before JS code accesses it */
- op1 = JS_DupValue(ctx, op1);
+ op1 = js_dup(op1);
if (js_unary_arith_slow(ctx, &op1 + 1, OP_dec))
goto exception;
set_value(ctx, &var_buf[idx], op1);
@@ -18298,8 +16979,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JSValue op1;
op1 = sp[-1];
if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {
- sp[-1] = JS_NewInt32(ctx, ~JS_VALUE_GET_INT(op1));
+ sp[-1] = js_int32(~JS_VALUE_GET_INT(op1));
} else {
+ sf->cur_pc = pc;
if (js_not_slow(ctx, sp))
goto exception;
}
@@ -18314,29 +16996,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
uint32_t v1, v2;
v1 = JS_VALUE_GET_INT(op1);
- v2 = JS_VALUE_GET_INT(op2);
-#ifdef CONFIG_BIGNUM
- {
- int64_t r;
- if (unlikely(sf->js_mode & JS_MODE_MATH)) {
- if (v2 > 0x1f)
- goto shl_slow;
- r = (int64_t)v1 << v2;
- if ((int)r != r)
- goto shl_slow;
- } else {
- v2 &= 0x1f;
- }
- }
-#else
- v2 &= 0x1f;
-#endif
- sp[-2] = JS_NewInt32(ctx, v1 << v2);
+ v2 = JS_VALUE_GET_INT(op2) & 0x1f;
+ sp[-2] = js_int32(v1 << v2);
sp--;
} else {
-#ifdef CONFIG_BIGNUM
- shl_slow:
-#endif
+ sf->cur_pc = pc;
if (js_binary_logic_slow(ctx, sp, opcode))
goto exception;
sp--;
@@ -18351,13 +17015,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
uint32_t v2;
v2 = JS_VALUE_GET_INT(op2);
- /* v1 >>> v2 retains its JS semantics if CONFIG_BIGNUM */
v2 &= 0x1f;
- sp[-2] = JS_NewUint32(ctx,
- (uint32_t)JS_VALUE_GET_INT(op1) >>
- v2);
+ sp[-2] = js_uint32((uint32_t)JS_VALUE_GET_INT(op1) >> v2);
sp--;
} else {
+ sf->cur_pc = pc;
if (js_shr_slow(ctx, sp))
goto exception;
sp--;
@@ -18372,23 +17034,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
uint32_t v2;
v2 = JS_VALUE_GET_INT(op2);
-#ifdef CONFIG_BIGNUM
if (unlikely(v2 > 0x1f)) {
- if (unlikely(sf->js_mode & JS_MODE_MATH))
- goto sar_slow;
- else
- v2 &= 0x1f;
+ v2 &= 0x1f;
}
-#else
- v2 &= 0x1f;
-#endif
- sp[-2] = JS_NewInt32(ctx,
- (int)JS_VALUE_GET_INT(op1) >> v2);
+ sp[-2] = js_int32((int)JS_VALUE_GET_INT(op1) >> v2);
sp--;
} else {
-#ifdef CONFIG_BIGNUM
- sar_slow:
-#endif
+ sf->cur_pc = pc;
if (js_binary_logic_slow(ctx, sp, opcode))
goto exception;
sp--;
@@ -18401,11 +17053,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
op1 = sp[-2];
op2 = sp[-1];
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
- sp[-2] = JS_NewInt32(ctx,
- JS_VALUE_GET_INT(op1) &
- JS_VALUE_GET_INT(op2));
+ sp[-2] = js_int32(JS_VALUE_GET_INT(op1) & JS_VALUE_GET_INT(op2));
sp--;
} else {
+ sf->cur_pc = pc;
if (js_binary_logic_slow(ctx, sp, opcode))
goto exception;
sp--;
@@ -18418,11 +17069,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
op1 = sp[-2];
op2 = sp[-1];
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
- sp[-2] = JS_NewInt32(ctx,
- JS_VALUE_GET_INT(op1) |
- JS_VALUE_GET_INT(op2));
+ sp[-2] = js_int32(JS_VALUE_GET_INT(op1) | JS_VALUE_GET_INT(op2));
sp--;
} else {
+ sf->cur_pc = pc;
if (js_binary_logic_slow(ctx, sp, opcode))
goto exception;
sp--;
@@ -18435,11 +17085,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
op1 = sp[-2];
op2 = sp[-1];
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
- sp[-2] = JS_NewInt32(ctx,
- JS_VALUE_GET_INT(op1) ^
- JS_VALUE_GET_INT(op2));
+ sp[-2] = js_int32(JS_VALUE_GET_INT(op1) ^ JS_VALUE_GET_INT(op2));
sp--;
} else {
+ sf->cur_pc = pc;
if (js_binary_logic_slow(ctx, sp, opcode))
goto exception;
sp--;
@@ -18455,9 +17104,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
op1 = sp[-2]; \
op2 = sp[-1]; \
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { \
- sp[-2] = JS_NewBool(ctx, JS_VALUE_GET_INT(op1) binary_op JS_VALUE_GET_INT(op2)); \
+ sp[-2] = js_bool(JS_VALUE_GET_INT(op1) binary_op JS_VALUE_GET_INT(op2)); \
sp--; \
} else { \
+ sf->cur_pc = pc; \
if (slow_call) \
goto exception; \
sp--; \
@@ -18474,14 +17124,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
OP_CMP(OP_strict_eq, ==, js_strict_eq_slow(ctx, sp, 0));
OP_CMP(OP_strict_neq, !=, js_strict_eq_slow(ctx, sp, 1));
-#ifdef CONFIG_BIGNUM
- CASE(OP_mul_pow10):
- if (rt->bigfloat_ops.mul_pow10(ctx, sp))
- goto exception;
- sp--;
- BREAK;
-#endif
CASE(OP_in):
+ sf->cur_pc = pc;
if (js_operator_in(ctx, sp))
goto exception;
sp--;
@@ -18492,6 +17136,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp--;
BREAK;
CASE(OP_instanceof):
+ sf->cur_pc = pc;
if (js_operator_instanceof(ctx, sp))
goto exception;
sp--;
@@ -18508,6 +17153,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
}
BREAK;
CASE(OP_delete):
+ sf->cur_pc = pc;
if (js_operator_delete(ctx, sp))
goto exception;
sp--;
@@ -18520,15 +17166,17 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
atom = get_u32(pc);
pc += 4;
+ sf->cur_pc = pc;
ret = JS_DeleteProperty(ctx, ctx->global_obj, atom, 0);
if (unlikely(ret < 0))
goto exception;
- *sp++ = JS_NewBool(ctx, ret);
+ *sp++ = js_bool(ret);
}
BREAK;
CASE(OP_to_object):
if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_OBJECT) {
+ sf->cur_pc = pc;
ret_val = JS_ToObject(ctx, sp[-1]);
if (JS_IsException(ret_val))
goto exception;
@@ -18544,6 +17192,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
case JS_TAG_SYMBOL:
break;
default:
+ sf->cur_pc = pc;
ret_val = JS_ToPropertyKey(ctx, sp[-1]);
if (JS_IsException(ret_val))
goto exception;
@@ -18565,6 +17214,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
case JS_TAG_SYMBOL:
break;
default:
+ sf->cur_pc = pc;
ret_val = JS_ToPropertyKey(ctx, sp[-1]);
if (JS_IsException(ret_val))
goto exception;
@@ -18573,17 +17223,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
break;
}
BREAK;
-#if 0
- CASE(OP_to_string):
- if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_STRING) {
- ret_val = JS_ToString(ctx, sp[-1]);
- if (JS_IsException(ret_val))
- goto exception;
- JS_FreeValue(ctx, sp[-1]);
- sp[-1] = ret_val;
- }
- BREAK;
-#endif
CASE(OP_with_get_var):
CASE(OP_with_put_var):
CASE(OP_with_delete_var):
@@ -18599,6 +17238,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
diff = get_u32(pc + 4);
is_with = pc[8];
pc += 9;
+ sf->cur_pc = pc;
obj = sp[-1];
ret = JS_HasProperty(ctx, obj, atom);
@@ -18621,7 +17261,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
break;
case OP_with_put_var:
/* XXX: check if strict mode */
- ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2], obj,
+ ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2],
JS_PROP_THROW_STRICT);
JS_FreeValue(ctx, sp[-1]);
sp -= 2;
@@ -18633,7 +17273,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
if (unlikely(ret < 0))
goto exception;
JS_FreeValue(ctx, sp[-1]);
- sp[-1] = JS_NewBool(ctx, ret);
+ sp[-1] = js_bool(ret);
break;
case OP_with_make_ref:
/* produce a pair object/propname on the stack */
@@ -18667,20 +17307,18 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_await):
- ret_val = JS_NewInt32(ctx, FUNC_RET_AWAIT);
+ ret_val = js_int32(FUNC_RET_AWAIT);
goto done_generator;
CASE(OP_yield):
- ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD);
+ ret_val = js_int32(FUNC_RET_YIELD);
goto done_generator;
CASE(OP_yield_star):
CASE(OP_async_yield_star):
- ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD_STAR);
+ ret_val = js_int32(FUNC_RET_YIELD_STAR);
goto done_generator;
CASE(OP_return_async):
- ret_val = JS_UNDEFINED;
- goto done_generator;
CASE(OP_initial_yield):
- ret_val = JS_NewInt32(ctx, FUNC_RET_INITIAL_YIELD);
+ ret_val = JS_UNDEFINED;
goto done_generator;
CASE(OP_nop):
@@ -18692,7 +17330,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
} else {
goto free_and_set_false;
}
-#if SHORT_OPCODES
CASE(OP_is_undefined):
if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_UNDEFINED) {
goto set_true;
@@ -18721,7 +17358,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
}
free_and_set_true:
JS_FreeValue(ctx, sp[-1]);
-#endif
set_true:
sp[-1] = JS_TRUE;
BREAK;
@@ -18737,19 +17373,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
}
}
exception:
- if (JS_IsString(rt->current_exception)) {
- JSValue error_obj = JS_NewError(ctx);
- JSAtom msgProp = JS_NewAtom(ctx, "message");
- JS_DefinePropertyValue(ctx, error_obj, msgProp, rt->current_exception, 0);
- rt->current_exception = error_obj;
- JS_FreeAtom(ctx, msgProp);
- }
- if (is_backtrace_needed(ctx, rt->current_exception)) {
- /* add the backtrace information now (it is not done
- before if the exception happens in a bytecode
- operation */
+ if (needs_backtrace(rt->current_exception)
+ || JS_IsUndefined(ctx->error_back_trace)) {
sf->cur_pc = pc;
- build_backtrace(ctx, rt->current_exception, NULL, 0, 0);
+ build_backtrace(ctx, rt->current_exception, JS_UNDEFINED,
+ NULL, 0, 0, 0);
}
if (!JS_IsUncatchableError(ctx, rt->current_exception)) {
while (sp > stack_buf) {
@@ -18761,10 +17389,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
/* enumerator: close it with a throw */
JS_FreeValue(ctx, sp[-1]); /* drop the next method */
sp--;
- JS_IteratorClose(ctx, sp[-1], TRUE);
+ JS_IteratorClose(ctx, sp[-1], true);
} else {
*sp++ = rt->current_exception;
- rt->current_exception = JS_NULL;
+ rt->current_exception = JS_UNINITIALIZED;
+ JS_FreeValueRT(rt, ctx->error_back_trace);
+ ctx->error_back_trace = JS_UNDEFINED;
pc = b->byte_code_buf + pos;
goto restart;
}
@@ -18796,25 +17426,25 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
return ret_val;
}
-JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
+JSValue JS_Call(JSContext *ctx, JSValue func_obj, JSValue this_obj,
+ int argc, JSValue *argv)
{
return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
- argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
+ argc, argv, JS_CALL_FLAG_COPY_ARGV);
}
-static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
+static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValue this_obj,
+ int argc, JSValue *argv)
{
JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
- argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
+ argc, argv, JS_CALL_FLAG_COPY_ARGV);
JS_FreeValue(ctx, func_obj);
return res;
}
/* warning: the refcount of the context is not incremented. Return
NULL in case of exception (case of revoked proxy only) */
-static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj)
+static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValue func_obj)
{
JSObject *p;
JSContext *realm;
@@ -18862,14 +17492,14 @@ static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj)
return realm;
}
-static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor,
+static JSValue js_create_from_ctor(JSContext *ctx, JSValue ctor,
int class_id)
{
JSValue proto, obj;
JSContext *realm;
if (JS_IsUndefined(ctor)) {
- proto = JS_DupValue(ctx, ctx->class_proto[class_id]);
+ proto = js_dup(ctx->class_proto[class_id]);
} else {
proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype);
if (JS_IsException(proto))
@@ -18879,7 +17509,7 @@ static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor,
realm = JS_GetFunctionRealm(ctx, ctor);
if (!realm)
return JS_EXCEPTION;
- proto = JS_DupValue(ctx, realm->class_proto[class_id]);
+ proto = js_dup(realm->class_proto[class_id]);
}
}
obj = JS_NewObjectProtoClass(ctx, proto, class_id);
@@ -18889,8 +17519,8 @@ static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor,
/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */
static JSValue JS_CallConstructorInternal(JSContext *ctx,
- JSValueConst func_obj,
- JSValueConst new_target,
+ JSValue func_obj,
+ JSValue new_target,
int argc, JSValue *argv, int flags)
{
JSObject *p;
@@ -18909,10 +17539,10 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx,
call_func = ctx->rt->class_array[p->class_id].call;
if (!call_func) {
not_a_function:
- return JS_ThrowTypeError(ctx, "not a function");
+ return JS_ThrowTypeErrorNotAFunction(ctx);
}
return call_func(ctx, func_obj, new_target, argc,
- (JSValueConst *)argv, flags);
+ argv, flags);
}
b = p->u.func.function_bytecode;
@@ -18936,25 +17566,25 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx,
}
}
-JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,
- JSValueConst new_target,
- int argc, JSValueConst *argv)
+JSValue JS_CallConstructor2(JSContext *ctx, JSValue func_obj,
+ JSValue new_target,
+ int argc, JSValue *argv)
{
return JS_CallConstructorInternal(ctx, func_obj, new_target,
- argc, (JSValue *)argv,
+ argc, argv,
JS_CALL_FLAG_COPY_ARGV);
}
-JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,
- int argc, JSValueConst *argv)
+JSValue JS_CallConstructor(JSContext *ctx, JSValue func_obj,
+ int argc, JSValue *argv)
{
return JS_CallConstructorInternal(ctx, func_obj, func_obj,
- argc, (JSValue *)argv,
+ argc, argv,
JS_CALL_FLAG_COPY_ARGV);
}
-JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom,
- int argc, JSValueConst *argv)
+JSValue JS_Invoke(JSContext *ctx, JSValue this_val, JSAtom atom,
+ int argc, JSValue *argv)
{
JSValue func_obj;
func_obj = JS_GetProperty(ctx, this_val, atom);
@@ -18964,7 +17594,7 @@ JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom,
}
static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
- int argc, JSValueConst *argv)
+ int argc, JSValue *argv)
{
JSValue res = JS_Invoke(ctx, this_val, atom, argc, argv);
JS_FreeValue(ctx, this_val);
@@ -18972,57 +17602,69 @@ static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
}
/* JSAsyncFunctionState (used by generator and async functions) */
-static JSAsyncFunctionState *async_func_init(JSContext *ctx,
- JSValueConst func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
+static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,
+ JSValue func_obj, JSValue this_obj,
+ int argc, JSValue *argv)
{
- JSAsyncFunctionState *s;
JSObject *p;
JSFunctionBytecode *b;
JSStackFrame *sf;
int local_count, i, arg_buf_len, n;
- s = js_mallocz(ctx, sizeof(*s));
- if (!s)
- return NULL;
- s->header.ref_count = 1;
- add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
-
sf = &s->frame;
init_list_head(&sf->var_ref_list);
p = JS_VALUE_GET_OBJ(func_obj);
b = p->u.func.function_bytecode;
- sf->js_mode = b->js_mode | JS_MODE_ASYNC;
+ sf->is_strict_mode = b->is_strict_mode;
sf->cur_pc = b->byte_code_buf;
arg_buf_len = max_int(b->arg_count, argc);
local_count = arg_buf_len + b->var_count + b->stack_size;
sf->arg_buf = js_malloc(ctx, sizeof(JSValue) * max_int(local_count, 1));
- if (!sf->arg_buf) {
- js_free(ctx, s);
- return NULL;
- }
- sf->cur_func = JS_DupValue(ctx, func_obj);
- s->this_val = JS_DupValue(ctx, this_obj);
+ if (!sf->arg_buf)
+ return -1;
+ sf->cur_func = js_dup(func_obj);
+ s->this_val = js_dup(this_obj);
s->argc = argc;
sf->arg_count = arg_buf_len;
sf->var_buf = sf->arg_buf + arg_buf_len;
sf->cur_sp = sf->var_buf + b->var_count;
for(i = 0; i < argc; i++)
- sf->arg_buf[i] = JS_DupValue(ctx, argv[i]);
+ sf->arg_buf[i] = js_dup(argv[i]);
n = arg_buf_len + b->var_count;
for(i = argc; i < n; i++)
sf->arg_buf[i] = JS_UNDEFINED;
- s->resolving_funcs[0] = JS_UNDEFINED;
- s->resolving_funcs[1] = JS_UNDEFINED;
- s->is_completed = FALSE;
- return s;
+ return 0;
}
-static void async_func_free_frame(JSRuntime *rt, JSAsyncFunctionState *s)
+static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s,
+ JS_MarkFunc *mark_func)
{
- JSStackFrame *sf = &s->frame;
+ JSStackFrame *sf;
JSValue *sp;
+ sf = &s->frame;
+ JS_MarkValue(rt, sf->cur_func, mark_func);
+ JS_MarkValue(rt, s->this_val, mark_func);
+ if (sf->cur_sp) {
+ /* if the function is running, cur_sp is not known so we
+ cannot mark the stack. Marking the variables is not needed
+ because a running function cannot be part of a removable
+ cycle */
+ for(sp = sf->arg_buf; sp < sf->cur_sp; sp++)
+ JS_MarkValue(rt, *sp, mark_func);
+ }
+}
+
+static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
+{
+ JSStackFrame *sf;
+ JSValue *sp;
+
+ sf = &s->frame;
+
+ /* close the closure variables. */
+ close_var_refs(rt, sf);
+
if (sf->arg_buf) {
/* cannot free the function if it is running */
assert(sf->cur_sp != NULL);
@@ -19030,7 +17672,6 @@ static void async_func_free_frame(JSRuntime *rt, JSAsyncFunctionState *s)
JS_FreeValueRT(rt, *sp);
}
js_free_rt(rt, sf->arg_buf);
- sf->arg_buf = NULL;
}
JS_FreeValueRT(rt, sf->cur_func);
JS_FreeValueRT(rt, s->this_val);
@@ -19038,66 +17679,17 @@ static void async_func_free_frame(JSRuntime *rt, JSAsyncFunctionState *s)
static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s)
{
- JSRuntime *rt = ctx->rt;
- JSStackFrame *sf = &s->frame;
- JSValue func_obj, ret;
-
- assert(!s->is_completed);
- if (js_check_stack_overflow(ctx->rt, 0)) {
- ret = JS_ThrowStackOverflow(ctx);
- } else {
- /* the tag does not matter provided it is not an object */
- func_obj = JS_MKPTR(JS_TAG_INT, s);
- ret = JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED,
- s->argc, sf->arg_buf, JS_CALL_FLAG_GENERATOR);
- }
- if (JS_IsException(ret) || JS_IsUndefined(ret)) {
- if (JS_IsUndefined(ret)) {
- ret = sf->cur_sp[-1];
- sf->cur_sp[-1] = JS_UNDEFINED;
- }
- /* end of execution */
- s->is_completed = TRUE;
-
- /* close the closure variables. */
- close_var_refs(rt, sf);
-
- async_func_free_frame(rt, s);
- }
- return ret;
-}
-
-static void __async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
-{
- /* cannot close the closure variables here because it would
- potentially modify the object graph */
- if (!s->is_completed) {
- async_func_free_frame(rt, s);
- }
+ JSValue func_obj;
- JS_FreeValueRT(rt, s->resolving_funcs[0]);
- JS_FreeValueRT(rt, s->resolving_funcs[1]);
+ if (js_check_stack_overflow(ctx->rt, 0))
+ return JS_ThrowStackOverflow(ctx);
- remove_gc_object(&s->header);
- if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && s->header.ref_count != 0) {
- list_add_tail(&s->header.link, &rt->gc_zero_ref_count_list);
- } else {
- js_free_rt(rt, s);
- }
+ /* the tag does not matter provided it is not an object */
+ func_obj = JS_MKPTR(JS_TAG_INT, s);
+ return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED,
+ s->argc, s->frame.arg_buf, JS_CALL_FLAG_GENERATOR);
}
-static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
-{
- if (--s->header.ref_count == 0) {
- if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) {
- list_del(&s->header.link);
- list_add(&s->header.link, &rt->gc_zero_ref_count_list);
- if (rt->gc_phase == JS_GC_PHASE_NONE) {
- free_zero_refcount(rt);
- }
- }
- }
-}
/* Generators */
@@ -19111,17 +17703,14 @@ typedef enum JSGeneratorStateEnum {
typedef struct JSGeneratorData {
JSGeneratorStateEnum state;
- JSAsyncFunctionState *func_state;
+ JSAsyncFunctionState func_state;
} JSGeneratorData;
static void free_generator_stack_rt(JSRuntime *rt, JSGeneratorData *s)
{
if (s->state == JS_GENERATOR_STATE_COMPLETED)
return;
- if (s->func_state) {
- async_func_free(rt, s->func_state);
- s->func_state = NULL;
- }
+ async_func_free(rt, &s->func_state);
s->state = JS_GENERATOR_STATE_COMPLETED;
}
@@ -19140,15 +17729,15 @@ static void free_generator_stack(JSContext *ctx, JSGeneratorData *s)
free_generator_stack_rt(ctx->rt, s);
}
-static void js_generator_mark(JSRuntime *rt, JSValueConst val,
+static void js_generator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
JSGeneratorData *s = p->u.generator_data;
- if (!s || !s->func_state)
+ if (!s || s->state == JS_GENERATOR_STATE_COMPLETED)
return;
- mark_func(rt, &s->func_state->header);
+ async_func_mark(rt, &s->func_state, mark_func);
}
/* XXX: use enum */
@@ -19156,21 +17745,21 @@ static void js_generator_mark(JSRuntime *rt, JSValueConst val,
#define GEN_MAGIC_RETURN 1
#define GEN_MAGIC_THROW 2
-static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
- BOOL *pdone, int magic)
+static JSValue js_generator_next(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
+ int *pdone, int magic)
{
JSGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_GENERATOR);
JSStackFrame *sf;
JSValue ret, func_ret;
- *pdone = TRUE;
+ *pdone = true;
if (!s)
return JS_ThrowTypeError(ctx, "not a generator");
+ sf = &s->func_state.frame;
switch(s->state) {
default:
case JS_GENERATOR_STATE_SUSPENDED_START:
- sf = &s->func_state->frame;
if (magic == GEN_MAGIC_NEXT) {
goto exec_no_arg;
} else {
@@ -19180,29 +17769,28 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
break;
case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR:
case JS_GENERATOR_STATE_SUSPENDED_YIELD:
- sf = &s->func_state->frame;
/* cur_sp[-1] was set to JS_UNDEFINED in the previous call */
- ret = JS_DupValue(ctx, argv[0]);
+ ret = js_dup(argv[0]);
if (magic == GEN_MAGIC_THROW &&
s->state == JS_GENERATOR_STATE_SUSPENDED_YIELD) {
JS_Throw(ctx, ret);
- s->func_state->throw_flag = TRUE;
+ s->func_state.throw_flag = true;
} else {
sf->cur_sp[-1] = ret;
- sf->cur_sp[0] = JS_NewInt32(ctx, magic);
+ sf->cur_sp[0] = js_int32(magic);
sf->cur_sp++;
exec_no_arg:
- s->func_state->throw_flag = FALSE;
+ s->func_state.throw_flag = false;
}
s->state = JS_GENERATOR_STATE_EXECUTING;
- func_ret = async_func_resume(ctx, s->func_state);
+ func_ret = async_func_resume(ctx, &s->func_state);
s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD;
- if (s->func_state->is_completed) {
- /* finalize the execution in case of exception or normal return */
+ if (JS_IsException(func_ret)) {
+ /* finalize the execution in case of exception */
free_generator_stack(ctx, s);
return func_ret;
- } else {
- assert(JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT);
+ }
+ if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {
/* get the returned yield value at the top of the stack */
ret = sf->cur_sp[-1];
sf->cur_sp[-1] = JS_UNDEFINED;
@@ -19211,8 +17799,14 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
/* return (value, done) object */
*pdone = 2;
} else {
- *pdone = FALSE;
+ *pdone = false;
}
+ } else {
+ /* end of iterator */
+ ret = sf->cur_sp[-1];
+ sf->cur_sp[-1] = JS_UNDEFINED;
+ JS_FreeValue(ctx, func_ret);
+ free_generator_stack(ctx, s);
}
break;
case JS_GENERATOR_STATE_COMPLETED:
@@ -19224,10 +17818,10 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
ret = JS_UNDEFINED;
break;
case GEN_MAGIC_RETURN:
- ret = JS_DupValue(ctx, argv[0]);
+ ret = js_dup(argv[0]);
break;
case GEN_MAGIC_THROW:
- ret = JS_Throw(ctx, JS_DupValue(ctx, argv[0]));
+ ret = JS_Throw(ctx, js_dup(argv[0]));
break;
}
break;
@@ -19238,9 +17832,9 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
return ret;
}
-static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_obj,
- int argc, JSValueConst *argv,
+static JSValue js_generator_function_call(JSContext *ctx, JSValue func_obj,
+ JSValue this_obj,
+ int argc, JSValue *argv,
int flags)
{
JSValue obj, func_ret;
@@ -19250,14 +17844,13 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
if (!s)
return JS_EXCEPTION;
s->state = JS_GENERATOR_STATE_SUSPENDED_START;
- s->func_state = async_func_init(ctx, func_obj, this_obj, argc, argv);
- if (!s->func_state) {
+ if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {
s->state = JS_GENERATOR_STATE_COMPLETED;
goto fail;
}
/* execute the function up to 'OP_initial_yield' */
- func_ret = async_func_resume(ctx, s->func_state);
+ func_ret = async_func_resume(ctx, &s->func_state);
if (JS_IsException(func_ret))
goto fail;
JS_FreeValue(ctx, func_ret);
@@ -19265,7 +17858,7 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
obj = js_create_from_ctor(ctx, func_obj, JS_CLASS_GENERATOR);
if (JS_IsException(obj))
goto fail;
- JS_SetOpaque(obj, s);
+ JS_SetOpaqueInternal(obj, s);
return obj;
fail:
free_generator_stack_rt(ctx->rt, s);
@@ -19275,27 +17868,51 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
/* AsyncFunction */
+static void js_async_function_terminate(JSRuntime *rt, JSAsyncFunctionData *s)
+{
+ if (s->is_active) {
+ async_func_free(rt, &s->func_state);
+ s->is_active = false;
+ }
+}
+
+static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s)
+{
+ js_async_function_terminate(rt, s);
+ JS_FreeValueRT(rt, s->resolving_funcs[0]);
+ JS_FreeValueRT(rt, s->resolving_funcs[1]);
+ remove_gc_object(&s->header);
+ js_free_rt(rt, s);
+}
+
+static void js_async_function_free(JSRuntime *rt, JSAsyncFunctionData *s)
+{
+ if (--s->header.ref_count == 0) {
+ js_async_function_free0(rt, s);
+ }
+}
+
static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
- JSAsyncFunctionState *s = p->u.async_function_data;
+ JSAsyncFunctionData *s = p->u.async_function_data;
if (s) {
- async_func_free(rt, s);
+ js_async_function_free(rt, s);
}
}
-static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,
+static void js_async_function_resolve_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
- JSAsyncFunctionState *s = p->u.async_function_data;
+ JSAsyncFunctionData *s = p->u.async_function_data;
if (s) {
mark_func(rt, &s->header);
}
}
static int js_async_function_resolve_create(JSContext *ctx,
- JSAsyncFunctionState *s,
+ JSAsyncFunctionData *s,
JSValue *resolving_funcs)
{
int i;
@@ -19317,107 +17934,133 @@ static int js_async_function_resolve_create(JSContext *ctx,
return 0;
}
-static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionState *s)
+static bool js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
{
+ bool is_success = true;
JSValue func_ret, ret2;
- func_ret = async_func_resume(ctx, s);
- if (s->is_completed) {
- if (JS_IsException(func_ret)) {
- JSValue error;
- fail:
- error = JS_GetException(ctx);
- ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,
- 1, (JSValueConst *)&error);
- JS_FreeValue(ctx, error);
- JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
+ func_ret = async_func_resume(ctx, &s->func_state);
+ if (JS_IsException(func_ret)) {
+ fail:
+ if (unlikely(JS_IsUncatchableError(ctx, ctx->rt->current_exception))) {
+ is_success = false;
} else {
- /* normal return */
- ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,
- 1, (JSValueConst *)&func_ret);
- JS_FreeValue(ctx, func_ret);
- JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
+ JSValue error = JS_GetException(ctx);
+ ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED, 1, &error);
+ JS_FreeValue(ctx, error);
+ resolved:
+ if (unlikely(JS_IsException(ret2))) {
+ if (JS_IsUncatchableError(ctx, ctx->rt->current_exception)) {
+ is_success = false;
+ } else {
+ abort(); /* BUG */
+ }
+ }
+ JS_FreeValue(ctx, ret2);
}
+ js_async_function_terminate(ctx->rt, s);
} else {
- JSValue value, promise, resolving_funcs[2], resolving_funcs1[2];
- int i, res;
+ JSValue value;
+ value = s->func_state.frame.cur_sp[-1];
+ s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
+ if (JS_IsUndefined(func_ret)) {
+ /* function returned */
+ ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,
+ 1, &value);
+ JS_FreeValue(ctx, value);
+ goto resolved;
+ } else {
+ JSValue promise, resolving_funcs[2], resolving_funcs1[2];
+ int i, res;
- value = s->frame.cur_sp[-1];
- s->frame.cur_sp[-1] = JS_UNDEFINED;
+ /* await */
+ JS_FreeValue(ctx, func_ret); /* not used */
+ promise = js_promise_resolve(ctx, ctx->promise_ctor,
+ 1, &value, 0);
+ JS_FreeValue(ctx, value);
+ if (JS_IsException(promise))
+ goto fail;
+ if (js_async_function_resolve_create(ctx, s, resolving_funcs)) {
+ JS_FreeValue(ctx, promise);
+ goto fail;
+ }
- /* await */
- JS_FreeValue(ctx, func_ret); /* not used */
- promise = js_promise_resolve(ctx, ctx->promise_ctor,
- 1, (JSValueConst *)&value, 0);
- JS_FreeValue(ctx, value);
- if (JS_IsException(promise))
- goto fail;
- if (js_async_function_resolve_create(ctx, s, resolving_funcs)) {
+ /* Note: no need to create 'thrownawayCapability' as in
+ the spec */
+ for(i = 0; i < 2; i++)
+ resolving_funcs1[i] = JS_UNDEFINED;
+ res = perform_promise_then(ctx, promise,
+ resolving_funcs,
+ resolving_funcs1);
JS_FreeValue(ctx, promise);
- goto fail;
+ for(i = 0; i < 2; i++)
+ JS_FreeValue(ctx, resolving_funcs[i]);
+ if (res)
+ goto fail;
}
-
- /* Note: no need to create 'thrownawayCapability' as in
- the spec */
- for(i = 0; i < 2; i++)
- resolving_funcs1[i] = JS_UNDEFINED;
- res = perform_promise_then(ctx, promise,
- (JSValueConst *)resolving_funcs,
- (JSValueConst *)resolving_funcs1);
- JS_FreeValue(ctx, promise);
- for(i = 0; i < 2; i++)
- JS_FreeValue(ctx, resolving_funcs[i]);
- if (res)
- goto fail;
}
+ return is_success;
}
static JSValue js_async_function_resolve_call(JSContext *ctx,
- JSValueConst func_obj,
- JSValueConst this_obj,
- int argc, JSValueConst *argv,
+ JSValue func_obj,
+ JSValue this_obj,
+ int argc, JSValue *argv,
int flags)
{
JSObject *p = JS_VALUE_GET_OBJ(func_obj);
- JSAsyncFunctionState *s = p->u.async_function_data;
- BOOL is_reject = p->class_id - JS_CLASS_ASYNC_FUNCTION_RESOLVE;
- JSValueConst arg;
+ JSAsyncFunctionData *s = p->u.async_function_data;
+ bool is_reject = p->class_id - JS_CLASS_ASYNC_FUNCTION_RESOLVE;
+ JSValue arg;
if (argc > 0)
arg = argv[0];
else
arg = JS_UNDEFINED;
- s->throw_flag = is_reject;
+ s->func_state.throw_flag = is_reject;
if (is_reject) {
- JS_Throw(ctx, JS_DupValue(ctx, arg));
+ JS_Throw(ctx, js_dup(arg));
} else {
/* return value of await */
- s->frame.cur_sp[-1] = JS_DupValue(ctx, arg);
+ s->func_state.frame.cur_sp[-1] = js_dup(arg);
}
- js_async_function_resume(ctx, s);
+ if (!js_async_function_resume(ctx, s))
+ return JS_EXCEPTION;
return JS_UNDEFINED;
}
-static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_obj,
- int argc, JSValueConst *argv, int flags)
+static JSValue js_async_function_call(JSContext *ctx, JSValue func_obj,
+ JSValue this_obj,
+ int argc, JSValue *argv, int flags)
{
JSValue promise;
- JSAsyncFunctionState *s;
+ JSAsyncFunctionData *s;
- s = async_func_init(ctx, func_obj, this_obj, argc, argv);
+ s = js_mallocz(ctx, sizeof(*s));
if (!s)
return JS_EXCEPTION;
+ s->header.ref_count = 1;
+ add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
+ s->is_active = false;
+ s->resolving_funcs[0] = JS_UNDEFINED;
+ s->resolving_funcs[1] = JS_UNDEFINED;
promise = JS_NewPromiseCapability(ctx, s->resolving_funcs);
- if (JS_IsException(promise)) {
- async_func_free(ctx->rt, s);
+ if (JS_IsException(promise))
+ goto fail;
+
+ if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {
+ fail:
+ JS_FreeValue(ctx, promise);
+ js_async_function_free(ctx->rt, s);
return JS_EXCEPTION;
}
+ s->is_active = true;
- js_async_function_resume(ctx, s);
+ if (!js_async_function_resume(ctx, s))
+ goto fail;
- async_func_free(ctx->rt, s);
+ js_async_function_free(ctx->rt, s);
return promise;
}
@@ -19446,8 +18089,7 @@ typedef struct JSAsyncGeneratorRequest {
typedef struct JSAsyncGeneratorData {
JSObject *generator; /* back pointer to the object (const) */
JSAsyncGeneratorStateEnum state;
- /* func_state is NULL is state AWAITING_RETURN and COMPLETED */
- JSAsyncFunctionState *func_state;
+ JSAsyncFunctionState func_state;
struct list_head queue; /* list of JSAsyncGeneratorRequest.link */
} JSAsyncGeneratorData;
@@ -19465,8 +18107,10 @@ static void js_async_generator_free(JSRuntime *rt,
JS_FreeValueRT(rt, req->resolving_funcs[1]);
js_free_rt(rt, req);
}
- if (s->func_state)
- async_func_free(rt, s->func_state);
+ if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&
+ s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {
+ async_func_free(rt, &s->func_state);
+ }
js_free_rt(rt, s);
}
@@ -19479,7 +18123,7 @@ static void js_async_generator_finalizer(JSRuntime *rt, JSValue obj)
}
}
-static void js_async_generator_mark(JSRuntime *rt, JSValueConst val,
+static void js_async_generator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSAsyncGeneratorData *s = JS_GetOpaque(val, JS_CLASS_ASYNC_GENERATOR);
@@ -19493,21 +18137,22 @@ static void js_async_generator_mark(JSRuntime *rt, JSValueConst val,
JS_MarkValue(rt, req->resolving_funcs[0], mark_func);
JS_MarkValue(rt, req->resolving_funcs[1], mark_func);
}
- if (s->func_state) {
- mark_func(rt, &s->func_state->header);
+ if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&
+ s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {
+ async_func_mark(rt, &s->func_state, mark_func);
}
}
}
static JSValue js_async_generator_resolve_function(JSContext *ctx,
- JSValueConst this_obj,
- int argc, JSValueConst *argv,
+ JSValue this_obj,
+ int argc, JSValue *argv,
int magic, JSValue *func_data);
static int js_async_generator_resolve_function_create(JSContext *ctx,
- JSValueConst generator,
+ JSValue generator,
JSValue *resolving_funcs,
- BOOL is_resume_next)
+ bool is_resume_next)
{
int i;
JSValue func;
@@ -19527,7 +18172,7 @@ static int js_async_generator_resolve_function_create(JSContext *ctx,
static int js_async_generator_await(JSContext *ctx,
JSAsyncGeneratorData *s,
- JSValueConst value)
+ JSValue value)
{
JSValue promise, resolving_funcs[2], resolving_funcs1[2];
int i, res;
@@ -19538,7 +18183,7 @@ static int js_async_generator_await(JSContext *ctx,
goto fail;
if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator),
- resolving_funcs, FALSE)) {
+ resolving_funcs, false)) {
JS_FreeValue(ctx, promise);
goto fail;
}
@@ -19548,8 +18193,8 @@ static int js_async_generator_await(JSContext *ctx,
for(i = 0; i < 2; i++)
resolving_funcs1[i] = JS_UNDEFINED;
res = perform_promise_then(ctx, promise,
- (JSValueConst *)resolving_funcs,
- (JSValueConst *)resolving_funcs1);
+ resolving_funcs,
+ resolving_funcs1);
JS_FreeValue(ctx, promise);
for(i = 0; i < 2; i++)
JS_FreeValue(ctx, resolving_funcs[i]);
@@ -19562,7 +18207,7 @@ static int js_async_generator_await(JSContext *ctx,
static void js_async_generator_resolve_or_reject(JSContext *ctx,
JSAsyncGeneratorData *s,
- JSValueConst result,
+ JSValue result,
int is_reject)
{
JSAsyncGeneratorRequest *next;
@@ -19582,11 +18227,11 @@ static void js_async_generator_resolve_or_reject(JSContext *ctx,
static void js_async_generator_resolve(JSContext *ctx,
JSAsyncGeneratorData *s,
- JSValueConst value,
- BOOL done)
+ JSValue value,
+ bool done)
{
JSValue result;
- result = js_create_iterator_result(ctx, JS_DupValue(ctx, value), done);
+ result = js_create_iterator_result(ctx, js_dup(value), done);
/* XXX: better exception handling ? */
js_async_generator_resolve_or_reject(ctx, s, result, 0);
JS_FreeValue(ctx, result);
@@ -19594,7 +18239,7 @@ static void js_async_generator_resolve(JSContext *ctx,
static void js_async_generator_reject(JSContext *ctx,
JSAsyncGeneratorData *s,
- JSValueConst exception)
+ JSValue exception)
{
js_async_generator_resolve_or_reject(ctx, s, exception, 1);
}
@@ -19604,14 +18249,13 @@ static void js_async_generator_complete(JSContext *ctx,
{
if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED) {
s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;
- async_func_free(ctx->rt, s->func_state);
- s->func_state = NULL;
+ async_func_free(ctx->rt, &s->func_state);
}
}
static int js_async_generator_completed_return(JSContext *ctx,
JSAsyncGeneratorData *s,
- JSValueConst value)
+ JSValue value)
{
JSValue promise, resolving_funcs[2], resolving_funcs1[2];
int res;
@@ -19623,7 +18267,7 @@ static int js_async_generator_completed_return(JSContext *ctx,
// exception should be delivered to the catch handler.
if (JS_IsException(promise)) {
JSValue err = JS_GetException(ctx);
- promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, (JSValueConst *)&err,
+ promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, &err,
/*is_reject*/1);
JS_FreeValue(ctx, err);
if (JS_IsException(promise))
@@ -19632,15 +18276,15 @@ static int js_async_generator_completed_return(JSContext *ctx,
if (js_async_generator_resolve_function_create(ctx,
JS_MKPTR(JS_TAG_OBJECT, s->generator),
resolving_funcs1,
- TRUE)) {
+ true)) {
JS_FreeValue(ctx, promise);
return -1;
}
resolving_funcs[0] = JS_UNDEFINED;
resolving_funcs[1] = JS_UNDEFINED;
res = perform_promise_then(ctx, promise,
- (JSValueConst *)resolving_funcs1,
- (JSValueConst *)resolving_funcs);
+ resolving_funcs1,
+ resolving_funcs);
JS_FreeValue(ctx, resolving_funcs1[0]);
JS_FreeValue(ctx, resolving_funcs1[1]);
JS_FreeValue(ctx, promise);
@@ -19672,7 +18316,7 @@ static void js_async_generator_resume_next(JSContext *ctx,
break;
case JS_ASYNC_GENERATOR_STATE_COMPLETED:
if (next->completion_type == GEN_MAGIC_NEXT) {
- js_async_generator_resolve(ctx, s, JS_UNDEFINED, TRUE);
+ js_async_generator_resolve(ctx, s, JS_UNDEFINED, true);
} else if (next->completion_type == GEN_MAGIC_RETURN) {
s->state = JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN;
js_async_generator_completed_return(ctx, s, next->result);
@@ -19682,42 +18326,34 @@ static void js_async_generator_resume_next(JSContext *ctx,
goto done;
case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD:
case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR:
- value = JS_DupValue(ctx, next->result);
+ value = js_dup(next->result);
if (next->completion_type == GEN_MAGIC_THROW &&
s->state == JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD) {
JS_Throw(ctx, value);
- s->func_state->throw_flag = TRUE;
+ s->func_state.throw_flag = true;
} else {
/* 'yield' returns a value. 'yield *' also returns a value
in case the 'throw' method is called */
- s->func_state->frame.cur_sp[-1] = value;
- s->func_state->frame.cur_sp[0] =
- JS_NewInt32(ctx, next->completion_type);
- s->func_state->frame.cur_sp++;
+ s->func_state.frame.cur_sp[-1] = value;
+ s->func_state.frame.cur_sp[0] =
+ js_int32(next->completion_type);
+ s->func_state.frame.cur_sp++;
exec_no_arg:
- s->func_state->throw_flag = FALSE;
+ s->func_state.throw_flag = false;
}
s->state = JS_ASYNC_GENERATOR_STATE_EXECUTING;
resume_exec:
- func_ret = async_func_resume(ctx, s->func_state);
- if (s->func_state->is_completed) {
- if (JS_IsException(func_ret)) {
- value = JS_GetException(ctx);
- js_async_generator_complete(ctx, s);
- js_async_generator_reject(ctx, s, value);
- JS_FreeValue(ctx, value);
- } else {
- /* end of function */
- js_async_generator_complete(ctx, s);
- js_async_generator_resolve(ctx, s, func_ret, TRUE);
- JS_FreeValue(ctx, func_ret);
- }
- } else {
+ func_ret = async_func_resume(ctx, &s->func_state);
+ if (JS_IsException(func_ret)) {
+ value = JS_GetException(ctx);
+ js_async_generator_complete(ctx, s);
+ js_async_generator_reject(ctx, s, value);
+ JS_FreeValue(ctx, value);
+ } else if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {
int func_ret_code, ret;
- assert(JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT);
+ value = s->func_state.frame.cur_sp[-1];
+ s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
func_ret_code = JS_VALUE_GET_INT(func_ret);
- value = s->func_state->frame.cur_sp[-1];
- s->func_state->frame.cur_sp[-1] = JS_UNDEFINED;
switch(func_ret_code) {
case FUNC_RET_YIELD:
case FUNC_RET_YIELD_STAR:
@@ -19725,7 +18361,7 @@ static void js_async_generator_resume_next(JSContext *ctx,
s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR;
else
s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD;
- js_async_generator_resolve(ctx, s, value, FALSE);
+ js_async_generator_resolve(ctx, s, value, false);
JS_FreeValue(ctx, value);
break;
case FUNC_RET_AWAIT:
@@ -19733,13 +18369,21 @@ static void js_async_generator_resume_next(JSContext *ctx,
JS_FreeValue(ctx, value);
if (ret < 0) {
/* exception: throw it */
- s->func_state->throw_flag = TRUE;
+ s->func_state.throw_flag = true;
goto resume_exec;
}
goto done;
default:
abort();
}
+ } else {
+ assert(JS_IsUndefined(func_ret));
+ /* end of function */
+ value = s->func_state.frame.cur_sp[-1];
+ s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
+ js_async_generator_complete(ctx, s);
+ js_async_generator_resolve(ctx, s, value, true);
+ JS_FreeValue(ctx, value);
}
break;
default:
@@ -19750,13 +18394,13 @@ static void js_async_generator_resume_next(JSContext *ctx,
}
static JSValue js_async_generator_resolve_function(JSContext *ctx,
- JSValueConst this_obj,
- int argc, JSValueConst *argv,
+ JSValue this_obj,
+ int argc, JSValue *argv,
int magic, JSValue *func_data)
{
- BOOL is_reject = magic & 1;
+ bool is_reject = magic & 1;
JSAsyncGeneratorData *s = JS_GetOpaque(func_data[0], JS_CLASS_ASYNC_GENERATOR);
- JSValueConst arg = argv[0];
+ JSValue arg = argv[0];
/* XXX: what if s == NULL */
@@ -19768,17 +18412,17 @@ static JSValue js_async_generator_resolve_function(JSContext *ctx,
if (is_reject) {
js_async_generator_reject(ctx, s, arg);
} else {
- js_async_generator_resolve(ctx, s, arg, TRUE);
+ js_async_generator_resolve(ctx, s, arg, true);
}
} else {
/* restart function execution after await() */
assert(s->state == JS_ASYNC_GENERATOR_STATE_EXECUTING);
- s->func_state->throw_flag = is_reject;
+ s->func_state.throw_flag = is_reject;
if (is_reject) {
- JS_Throw(ctx, JS_DupValue(ctx, arg));
+ JS_Throw(ctx, js_dup(arg));
} else {
/* return value of await */
- s->func_state->frame.cur_sp[-1] = JS_DupValue(ctx, arg);
+ s->func_state.frame.cur_sp[-1] = js_dup(arg);
}
js_async_generator_resume_next(ctx, s);
}
@@ -19786,8 +18430,8 @@ static JSValue js_async_generator_resolve_function(JSContext *ctx,
}
/* magic = GEN_MAGIC_x */
-static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
+static JSValue js_async_generator_next(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
int magic)
{
JSAsyncGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_ASYNC_GENERATOR);
@@ -19802,7 +18446,7 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val,
JS_ThrowTypeError(ctx, "not an AsyncGenerator object");
err = JS_GetException(ctx);
res2 = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
- 1, (JSValueConst *)&err);
+ 1, &err);
JS_FreeValue(ctx, err);
JS_FreeValue(ctx, res2);
JS_FreeValue(ctx, resolving_funcs[0]);
@@ -19813,8 +18457,8 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val,
if (!req)
goto fail;
req->completion_type = magic;
- req->result = JS_DupValue(ctx, argv[0]);
- req->promise = JS_DupValue(ctx, promise);
+ req->result = js_dup(argv[0]);
+ req->promise = js_dup(promise);
req->resolving_funcs[0] = resolving_funcs[0];
req->resolving_funcs[1] = resolving_funcs[1];
list_add_tail(&req->link, &s->queue);
@@ -19829,9 +18473,9 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_obj,
- int argc, JSValueConst *argv,
+static JSValue js_async_generator_function_call(JSContext *ctx, JSValue func_obj,
+ JSValue this_obj,
+ int argc, JSValue *argv,
int flags)
{
JSValue obj, func_ret;
@@ -19842,12 +18486,14 @@ static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst fun
return JS_EXCEPTION;
s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_START;
init_list_head(&s->queue);
- s->func_state = async_func_init(ctx, func_obj, this_obj, argc, argv);
- if (!s->func_state)
+ if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {
+ s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;
goto fail;
+ }
+
/* execute the function up to 'OP_initial_yield' (no yield nor
await are possible) */
- func_ret = async_func_resume(ctx, s->func_state);
+ func_ret = async_func_resume(ctx, &s->func_state);
if (JS_IsException(func_ret))
goto fail;
JS_FreeValue(ctx, func_ret);
@@ -19856,7 +18502,7 @@ static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst fun
if (JS_IsException(obj))
goto fail;
s->generator = JS_VALUE_GET_OBJ(obj);
- JS_SetOpaque(obj, s);
+ JS_SetOpaqueInternal(obj, s);
return obj;
fail:
js_async_generator_free(ctx->rt, s);
@@ -19883,9 +18529,6 @@ enum {
TOK_AND_ASSIGN,
TOK_XOR_ASSIGN,
TOK_OR_ASSIGN,
-#ifdef CONFIG_BIGNUM
- TOK_MATH_POW_ASSIGN,
-#endif
TOK_POW_ASSIGN,
TOK_LAND_ASSIGN,
TOK_LOR_ASSIGN,
@@ -19905,9 +18548,6 @@ enum {
TOK_STRICT_NEQ,
TOK_LAND,
TOK_LOR,
-#ifdef CONFIG_BIGNUM
- TOK_MATH_POW,
-#endif
TOK_POW,
TOK_ARROW,
TOK_ELLIPSIS,
@@ -19986,7 +18626,8 @@ typedef struct BlockEnv {
int drop_count; /* number of stack elements to drop */
int label_finally; /* -1 if none */
int scope_level;
- int has_iterator;
+ uint8_t has_iterator : 1;
+ uint8_t is_regular_stmt : 1; // i.e. not a loop statement
} BlockEnv;
typedef struct JSGlobalVar {
@@ -20020,10 +18661,11 @@ typedef struct LabelSlot {
RelocEntry *first_reloc;
} LabelSlot;
-typedef struct LineNumberSlot {
+typedef struct SourceLocSlot {
uint32_t pc;
int line_num;
-} LineNumberSlot;
+ int col_num;
+} SourceLocSlot;
typedef enum JSParseFunctionEnum {
JS_PARSE_FUNC_STATEMENT,
@@ -20053,35 +18695,36 @@ typedef struct JSFunctionDef {
struct list_head child_list; /* list of JSFunctionDef.link */
struct list_head link;
- BOOL is_eval; /* TRUE if eval code */
- int eval_type; /* only valid if is_eval = TRUE */
- BOOL is_global_var; /* TRUE if variables are not defined locally:
+ bool is_eval; /* true if eval code */
+ int eval_type; /* only valid if is_eval = true */
+ bool is_global_var; /* true if variables are not defined locally:
eval global, eval module or non strict eval */
- BOOL is_func_expr; /* TRUE if function expression */
- BOOL has_home_object; /* TRUE if the home object is available */
- BOOL has_prototype; /* true if a prototype field is necessary */
- BOOL has_simple_parameter_list;
- BOOL has_parameter_expressions; /* if true, an argument scope is created */
- BOOL has_use_strict; /* to reject directive in special cases */
- BOOL has_eval_call; /* true if the function contains a call to eval() */
- BOOL has_arguments_binding; /* true if the 'arguments' binding is
+ bool is_func_expr; /* true if function expression */
+ bool has_home_object; /* true if the home object is available */
+ bool has_prototype; /* true if a prototype field is necessary */
+ bool has_simple_parameter_list;
+ bool has_parameter_expressions; /* if true, an argument scope is created */
+ bool has_use_strict; /* to reject directive in special cases */
+ bool has_eval_call; /* true if the function contains a call to eval() */
+ bool has_arguments_binding; /* true if the 'arguments' binding is
available in the function */
- BOOL has_this_binding; /* true if the 'this' and new.target binding are
+ bool has_this_binding; /* true if the 'this' and new.target binding are
available in the function */
- BOOL new_target_allowed; /* true if the 'new.target' does not
+ bool new_target_allowed; /* true if the 'new.target' does not
throw a syntax error */
- BOOL super_call_allowed; /* true if super() is allowed */
- BOOL super_allowed; /* true if super. or super[] is allowed */
- BOOL arguments_allowed; /* true if the 'arguments' identifier is allowed */
- BOOL is_derived_class_constructor;
- BOOL in_function_body;
- BOOL backtrace_barrier;
+ bool super_call_allowed; /* true if super() is allowed */
+ bool super_allowed; /* true if super. or super[] is allowed */
+ bool arguments_allowed; /* true if the 'arguments' identifier is allowed */
+ bool is_derived_class_constructor;
+ bool in_function_body;
+ bool backtrace_barrier;
JSFunctionKindEnum func_kind : 8;
- JSParseFunctionEnum func_type : 8;
- uint8_t js_mode; /* bitmap of JS_MODE_x */
+ JSParseFunctionEnum func_type : 7;
+ uint8_t is_strict_mode : 1;
JSAtom func_name; /* JS_ATOM_NULL if no name */
JSVarDef *vars;
+ uint32_t *vars_htab; // indexes into vars[]
int var_size; /* allocated size for vars[] */
int var_count;
JSVarDef *args;
@@ -20100,7 +18743,7 @@ typedef struct JSFunctionDef {
int new_target_var_idx; /* variable containg the 'new.target' value, -1 if none */
int this_active_func_var_idx; /* variable containg the 'this.active_func' value, -1 if none */
int home_object_var_idx;
- BOOL need_home_object;
+ bool need_home_object;
int scope_level; /* index into fd->scopes if the current lexical scope */
int scope_first; /* index into vd->vars of first lexically scoped variable */
@@ -20116,8 +18759,7 @@ typedef struct JSFunctionDef {
DynBuf byte_code;
int last_opcode_pos; /* -1 if no last opcode */
- int last_opcode_line_num;
- BOOL use_short_opcodes; /* true if short opcodes are used in byte_code */
+ bool use_short_opcodes; /* true if short opcodes are used in byte_code */
LabelSlot *label_slots;
int label_size; /* allocated size for label_slots[] */
@@ -20138,27 +18780,30 @@ typedef struct JSFunctionDef {
int jump_size;
int jump_count;
- LineNumberSlot *line_number_slots;
- int line_number_size;
- int line_number_count;
+ SourceLocSlot *source_loc_slots;
+ int source_loc_size;
+ int source_loc_count;
int line_number_last;
int line_number_last_pc;
+ int col_number_last;
/* pc2line table */
JSAtom filename;
int line_num;
+ int col_num;
DynBuf pc2line;
char *source; /* raw source, utf-8 encoded */
int source_len;
JSModuleDef *module; /* != NULL when parsing a module */
- BOOL has_await; /* TRUE if await is used (used in module eval) */
+ bool has_await; /* true if await is used (used in module eval) */
} JSFunctionDef;
typedef struct JSToken {
int val;
int line_num; /* line number of token start */
+ int col_num; /* column number of token start */
const uint8_t *ptr;
union {
struct {
@@ -20167,14 +18812,11 @@ typedef struct JSToken {
} str;
struct {
JSValue val;
-#ifdef CONFIG_BIGNUM
- slimb_t exponent; /* may be != 0 only if val is a float */
-#endif
} num;
struct {
JSAtom atom;
- BOOL has_escape;
- BOOL is_reserved;
+ bool has_escape;
+ bool is_reserved;
} ident;
struct {
JSValue body;
@@ -20186,23 +18828,27 @@ typedef struct JSToken {
typedef struct JSParseState {
JSContext *ctx;
int last_line_num; /* line number of last token */
+ int last_col_num; /* column number of last token */
int line_num; /* line number of current offset */
+ int col_num; /* column number of current offset */
const char *filename;
JSToken token;
- BOOL got_lf; /* true if got line feed before the current token */
+ bool got_lf; /* true if got line feed before the current token */
const uint8_t *last_ptr;
+ const uint8_t *buf_start;
const uint8_t *buf_ptr;
const uint8_t *buf_end;
+ const uint8_t *eol; // most recently seen end-of-line character
+ const uint8_t *mark; // first token character, invariant: eol < mark
/* current function code */
JSFunctionDef *cur_func;
- BOOL is_module; /* parsing a module */
- BOOL allow_html_comments;
- BOOL ext_json; /* true if accepting JSON superset */
+ bool is_module; /* parsing a module */
+ bool allow_html_comments;
} JSParseState;
typedef struct JSOpCode {
-#ifdef DUMP_BYTECODE
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_*
const char *name;
#endif
uint8_t size; /* in bytes */
@@ -20215,7 +18861,7 @@ typedef struct JSOpCode {
static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = {
#define FMT(f)
-#ifdef DUMP_BYTECODE
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_*
#define DEF(id, size, n_pop, n_push, f) { #id, size, n_pop, n_push, OP_FMT_ ## f },
#else
#define DEF(id, size, n_pop, n_push, f) { size, n_pop, n_push, OP_FMT_ ## f },
@@ -20225,7 +18871,6 @@ static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = {
#undef FMT
};
-#if SHORT_OPCODES
/* After the final compilation pass, short opcodes are used. Their
opcodes overlap with the temporary opcodes which cannot appear in
the final bytecode. Their description is after the temporary
@@ -20233,9 +18878,6 @@ static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = {
#define short_opcode_info(op) \
opcode_info[(op) >= OP_TEMP_START ? \
(op) + (OP_TEMP_END - OP_TEMP_START) : (op)]
-#else
-#define short_opcode_info(op) opcode_info[op]
-#endif
static __exception int next_token(JSParseState *s);
@@ -20266,9 +18908,10 @@ static void free_token(JSParseState *s, JSToken *token)
}
}
-static void __maybe_unused dump_token(JSParseState *s,
+static void __attribute((unused)) dump_token(JSParseState *s,
const JSToken *token)
{
+ printf("%d:%d ", token->line_num, token->col_num);
switch(token->val) {
case TOK_NUMBER:
{
@@ -20327,30 +18970,52 @@ static void __maybe_unused dump_token(JSParseState *s,
}
}
-int FORMAT_ATTR(2, 3) js_parse_error(JSParseState *s, const char *fmt, ...)
+int JS_PRINTF_FORMAT_ATTR(2, 3) js_parse_error(JSParseState *s, JS_PRINTF_FORMAT const char *fmt, ...)
{
JSContext *ctx = s->ctx;
va_list ap;
int backtrace_flags;
va_start(ap, fmt);
- JS_ThrowError2(ctx, JS_SYNTAX_ERROR, fmt, ap, FALSE);
+ JS_ThrowError2(ctx, JS_SYNTAX_ERROR, false, fmt, ap);
va_end(ap);
backtrace_flags = 0;
if (s->cur_func && s->cur_func->backtrace_barrier)
backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL;
- build_backtrace(ctx, ctx->rt->current_exception, s->filename, s->line_num,
- backtrace_flags);
+ build_backtrace(ctx, ctx->rt->current_exception, JS_UNDEFINED, s->filename,
+ s->line_num, s->col_num, backtrace_flags);
return -1;
}
static int js_parse_expect(JSParseState *s, int tok)
{
- if (s->token.val != tok) {
- /* XXX: dump token correctly in all cases */
- return js_parse_error(s, "expecting '%c'", tok);
+ char buf[ATOM_GET_STR_BUF_SIZE];
+
+ if (s->token.val == tok)
+ return next_token(s);
+
+ switch(s->token.val) {
+ case TOK_EOF:
+ return js_parse_error(s, "Unexpected end of input");
+ case TOK_NUMBER:
+ return js_parse_error(s, "Unexpected number");
+ case TOK_STRING:
+ return js_parse_error(s, "Unexpected string");
+ case TOK_TEMPLATE:
+ return js_parse_error(s, "Unexpected string template");
+ case TOK_REGEXP:
+ return js_parse_error(s, "Unexpected regexp");
+ case TOK_IDENT:
+ return js_parse_error(s, "Unexpected identifier '%s'",
+ JS_AtomGetStr(s->ctx, buf, sizeof(buf),
+ s->token.u.ident.atom));
+ case TOK_ERROR:
+ return js_parse_error(s, "Invalid or unexpected token");
+ default:
+ return js_parse_error(s, "Unexpected token '%.*s'",
+ (int)(s->buf_ptr - s->token.ptr),
+ (const char *)s->token.ptr);
}
- return next_token(s);
}
static int js_parse_expect_semi(JSParseState *s)
@@ -20373,8 +19038,10 @@ static int js_parse_error_reserved_identifier(JSParseState *s)
s->token.u.ident.atom));
}
-static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
+static __exception int js_parse_template_part(JSParseState *s,
+ const uint8_t *p)
{
+ const uint8_t *p_next;
uint32_t c;
StringBuffer b_s, *b = &b_s;
@@ -20409,10 +19076,11 @@ static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
}
if (c == '\n') {
s->line_num++;
+ s->eol = &p[-1];
+ s->mark = p;
} else if (c >= 0x80) {
- const uint8_t *p_next;
- c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);
- if (c > 0x10FFFF) {
+ c = utf8_decode(p - 1, &p_next);
+ if (p_next == p) {
js_parse_error(s, "invalid UTF-8 sequence");
goto fail;
}
@@ -20435,9 +19103,10 @@ static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
}
static __exception int js_parse_string(JSParseState *s, int sep,
- BOOL do_throw, const uint8_t *p,
+ bool do_throw, const uint8_t *p,
JSToken *token, const uint8_t **pp)
{
+ const uint8_t *p_next;
int ret;
uint32_t c;
StringBuffer b_s, *b = &b_s;
@@ -20450,11 +19119,6 @@ static __exception int js_parse_string(JSParseState *s, int sep,
goto invalid_char;
c = *p;
if (c < 0x20) {
- if (!s->cur_func) {
- if (do_throw)
- js_parse_error(s, "invalid character in a JSON string");
- goto fail;
- }
if (sep == '`') {
if (c == '\r') {
if (p[1] == '\n')
@@ -20475,12 +19139,15 @@ static __exception int js_parse_string(JSParseState *s, int sep,
}
if (c == '\\') {
c = *p;
- /* XXX: need a specific JSON case to avoid
- accepting invalid escapes */
switch(c) {
case '\0':
- if (p >= s->buf_end)
- goto invalid_char;
+ if (p >= s->buf_end) {
+ if (sep != '`')
+ goto invalid_char;
+ if (do_throw)
+ js_parse_error(s, "Unexpected end of input");
+ goto fail;
+ }
p++;
break;
case '\'':
@@ -20496,33 +19163,29 @@ static __exception int js_parse_string(JSParseState *s, int sep,
case '\n':
/* ignore escaped newline sequence */
p++;
- if (sep != '`')
+ if (sep != '`') {
s->line_num++;
+ s->eol = &p[-1];
+ s->mark = p;
+ }
continue;
default:
- if (c >= '0' && c <= '9') {
- if (!s->cur_func)
- goto invalid_escape; /* JSON case */
- if (!(s->cur_func->js_mode & JS_MODE_STRICT) && sep != '`')
- goto parse_escape;
- if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) {
- p++;
- c = '\0';
- } else {
- if (c >= '8' || sep == '`') {
- /* Note: according to ES2021, \8 and \9 are not
- accepted in strict mode or in templates. */
- goto invalid_escape;
- } else {
- if (do_throw)
- js_parse_error(s, "octal escape sequences are not allowed in strict mode");
- }
- goto fail;
+ if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) {
+ /* accept isolated \0 */
+ p++;
+ c = '\0';
+ } else
+ if ((c >= '0' && c <= '9')
+ && (s->cur_func->is_strict_mode || sep == '`')) {
+ if (do_throw) {
+ js_parse_error(s, "%s are not allowed in %s",
+ (c >= '8') ? "\\8 and \\9" : "Octal escape sequences",
+ (sep == '`') ? "template strings" : "strict mode");
}
+ goto fail;
} else if (c >= 0x80) {
- const uint8_t *p_next;
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next);
- if (c > 0x10FFFF) {
+ c = utf8_decode(p, &p_next);
+ if (p_next == p + 1) {
goto invalid_utf8;
}
p = p_next;
@@ -20530,12 +19193,12 @@ static __exception int js_parse_string(JSParseState *s, int sep,
if (c == CP_LS || c == CP_PS)
continue;
} else {
- parse_escape:
- ret = lre_parse_escape(&p, TRUE);
+ ret = lre_parse_escape(&p, true);
if (ret == -1) {
- invalid_escape:
- if (do_throw)
- js_parse_error(s, "malformed escape sequence in string literal");
+ if (do_throw) {
+ js_parse_error(s, "Invalid %s escape sequence",
+ c == 'u' ? "Unicode" : "hexadecimal");
+ }
goto fail;
} else if (ret < 0) {
/* ignore the '\' (could output a warning) */
@@ -20547,9 +19210,8 @@ static __exception int js_parse_string(JSParseState *s, int sep,
break;
}
} else if (c >= 0x80) {
- const uint8_t *p_next;
- c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);
- if (c > 0x10FFFF)
+ c = utf8_decode(p - 1, &p_next);
+ if (p_next == p)
goto invalid_utf8;
p = p_next;
}
@@ -20574,22 +19236,22 @@ static __exception int js_parse_string(JSParseState *s, int sep,
return -1;
}
-static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) {
+static inline bool token_is_pseudo_keyword(JSParseState *s, JSAtom atom) {
return s->token.val == TOK_IDENT && s->token.u.ident.atom == atom &&
!s->token.u.ident.has_escape;
}
static __exception int js_parse_regexp(JSParseState *s)
{
- const uint8_t *p;
- BOOL in_class;
+ const uint8_t *p, *p_next;
+ bool in_class;
StringBuffer b_s, *b = &b_s;
StringBuffer b2_s, *b2 = &b2_s;
uint32_t c;
p = s->buf_ptr;
p++;
- in_class = FALSE;
+ in_class = false;
if (string_buffer_init(s->ctx, b, 32))
return -1;
if (string_buffer_init(s->ctx, b2, 1))
@@ -20607,10 +19269,10 @@ static __exception int js_parse_regexp(JSParseState *s)
if (!in_class)
break;
} else if (c == '[') {
- in_class = TRUE;
+ in_class = true;
} else if (c == ']') {
/* XXX: incorrect as the first character in a class */
- in_class = FALSE;
+ in_class = false;
} else if (c == '\\') {
if (string_buffer_putc8(b, c))
goto fail;
@@ -20620,9 +19282,8 @@ static __exception int js_parse_regexp(JSParseState *s)
else if (c == '\0' && p >= s->buf_end)
goto eof_error;
else if (c >= 0x80) {
- const uint8_t *p_next;
- c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);
- if (c > 0x10FFFF) {
+ c = utf8_decode(p - 1, &p_next);
+ if (p_next == p) {
goto invalid_utf8;
}
p = p_next;
@@ -20630,9 +19291,8 @@ static __exception int js_parse_regexp(JSParseState *s)
goto eol_error;
}
} else if (c >= 0x80) {
- const uint8_t *p_next;
- c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);
- if (c > 0x10FFFF) {
+ c = utf8_decode(p - 1, &p_next);
+ if (p_next == p) {
invalid_utf8:
js_parse_error(s, "invalid UTF-8 sequence");
goto fail;
@@ -20651,14 +19311,8 @@ static __exception int js_parse_regexp(JSParseState *s)
/* flags */
for(;;) {
- const uint8_t *p_next = p;
- c = *p_next++;
- if (c >= 0x80) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next);
- if (c > 0x10FFFF) {
- goto invalid_utf8;
- }
- }
+ c = utf8_decode(p, &p_next);
+ /* no need to test for invalid UTF-8, 0xFFFD is not ident_next */
if (!lre_js_is_ident_next(c))
break;
if (string_buffer_putc(b2, c))
@@ -20678,7 +19332,7 @@ static __exception int js_parse_regexp(JSParseState *s)
}
static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
- const char *static_buf)
+ char *static_buf)
{
char *buf, *new_buf;
size_t size, new_size;
@@ -20709,7 +19363,7 @@ static void update_token_ident(JSParseState *s)
{
if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||
(s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&
- (s->cur_func->js_mode & JS_MODE_STRICT)) ||
+ s->cur_func->is_strict_mode) ||
(s->token.u.ident.atom == JS_ATOM_yield &&
((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||
(s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
@@ -20724,7 +19378,7 @@ static void update_token_ident(JSParseState *s)
((s->cur_func->parent->func_kind & JS_FUNC_ASYNC) ||
s->cur_func->parent->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))))) {
if (s->token.u.ident.has_escape) {
- s->token.u.ident.is_reserved = TRUE;
+ s->token.u.ident.is_reserved = true;
s->token.val = TOK_IDENT;
} else {
/* The keywords atoms are pre allocated */
@@ -20741,19 +19395,19 @@ static void reparse_ident_token(JSParseState *s)
(s->token.val >= TOK_FIRST_KEYWORD &&
s->token.val <= TOK_LAST_KEYWORD)) {
s->token.val = TOK_IDENT;
- s->token.u.ident.is_reserved = FALSE;
+ s->token.u.ident.is_reserved = false;
update_token_ident(s);
}
}
/* 'c' is the first character. Return JS_ATOM_NULL in case of error */
static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
- BOOL *pident_has_escape, int c, BOOL is_private)
+ bool *pident_has_escape, int c, bool is_private)
{
- const uint8_t *p, *p1;
+ const uint8_t *p, *p_next;
char ident_buf[128], *buf;
size_t ident_size, ident_pos;
- JSAtom atom;
+ JSAtom atom = JS_ATOM_NULL;
p = *pp;
buf = ident_buf;
@@ -20762,30 +19416,29 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
if (is_private)
buf[ident_pos++] = '#';
for(;;) {
- p1 = p;
-
- if (c < 128) {
+ if (c < 0x80) {
buf[ident_pos++] = c;
} else {
- ident_pos += unicode_to_utf8((uint8_t*)buf + ident_pos, c);
+ ident_pos += utf8_encode((uint8_t*)buf + ident_pos, c);
}
- c = *p1++;
- if (c == '\\' && *p1 == 'u') {
- c = lre_parse_escape(&p1, TRUE);
- *pident_has_escape = TRUE;
- } else if (c >= 128) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);
+ c = *p;
+ p_next = p + 1;
+ if (c == '\\' && *p_next == 'u') {
+ c = lre_parse_escape(&p_next, true);
+ *pident_has_escape = true;
+ } else if (c >= 0x80) {
+ c = utf8_decode(p, &p_next);
+ /* no need to test for invalid UTF-8, 0xFFFD is not ident_next */
}
if (!lre_js_is_ident_next(c))
break;
- p = p1;
+ p = p_next;
if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) {
- if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) {
- atom = JS_ATOM_NULL;
+ if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf))
goto done;
- }
}
}
+ /* buf is pure ASCII or UTF-8 encoded */
atom = JS_NewAtomLen(s->ctx, buf, ident_pos);
done:
if (unlikely(buf != ident_buf))
@@ -20797,22 +19450,26 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
static __exception int next_token(JSParseState *s)
{
- const uint8_t *p;
+ const uint8_t *p, *p_next;
int c;
- BOOL ident_has_escape;
+ bool ident_has_escape;
JSAtom atom;
+ int flags, radix;
- if (js_check_stack_overflow(s->ctx->rt, 0)) {
- return js_parse_error(s, "stack overflow");
+ if (js_check_stack_overflow(s->ctx->rt, 1000)) {
+ JS_ThrowStackOverflow(s->ctx);
+ return -1;
}
free_token(s, &s->token);
p = s->last_ptr = s->buf_ptr;
- s->got_lf = FALSE;
+ s->got_lf = false;
s->last_line_num = s->token.line_num;
+ s->last_col_num = s->token.col_num;
redo:
s->token.line_num = s->line_num;
+ s->token.col_num = s->col_num;
s->token.ptr = p;
c = *p;
switch(c) {
@@ -20830,7 +19487,7 @@ static __exception int next_token(JSParseState *s)
break;
case '\'':
case '\"':
- if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))
+ if (js_parse_string(s, c, true, p + 1, &s->token, &p))
goto fail;
break;
case '\r': /* accept DOS and MAC newline sequences */
@@ -20841,14 +19498,16 @@ static __exception int next_token(JSParseState *s)
case '\n':
p++;
line_terminator:
- s->got_lf = TRUE;
+ s->eol = &p[-1];
+ s->mark = p;
+ s->got_lf = true;
s->line_num++;
goto redo;
case '\f':
case '\v':
case ' ':
case '\t':
- p++;
+ s->mark = ++p;
goto redo;
case '/':
if (p[1] == '*') {
@@ -20865,22 +19524,23 @@ static __exception int next_token(JSParseState *s)
}
if (*p == '\n') {
s->line_num++;
- s->got_lf = TRUE; /* considered as LF for ASI */
- p++;
+ s->got_lf = true; /* considered as LF for ASI */
+ s->eol = p++;
+ s->mark = p;
} else if (*p == '\r') {
- s->got_lf = TRUE; /* considered as LF for ASI */
+ s->got_lf = true; /* considered as LF for ASI */
p++;
} else if (*p >= 0x80) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
+ c = utf8_decode(p, &p);
+ /* ignore invalid UTF-8 in comments */
if (c == CP_LS || c == CP_PS) {
- s->got_lf = TRUE; /* considered as LF for ASI */
- } else if (c == -1) {
- p++; /* skip invalid UTF-8 */
+ s->got_lf = true; /* considered as LF for ASI */
}
} else {
p++;
}
}
+ s->mark = p;
goto redo;
} else if (p[1] == '/') {
/* line comment */
@@ -20892,17 +19552,17 @@ static __exception int next_token(JSParseState *s)
if (*p == '\r' || *p == '\n')
break;
if (*p >= 0x80) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
+ c = utf8_decode(p, &p);
+ /* ignore invalid UTF-8 in comments */
/* LS or PS are considered as line terminator */
if (c == CP_LS || c == CP_PS) {
break;
- } else if (c == -1) {
- p++; /* skip invalid UTF-8 */
}
} else {
p++;
}
}
+ s->mark = p;
goto redo;
} else if (p[1] == '=') {
p += 2;
@@ -20915,11 +19575,11 @@ static __exception int next_token(JSParseState *s)
case '\\':
if (p[1] == 'u') {
const uint8_t *p1 = p + 1;
- int c1 = lre_parse_escape(&p1, TRUE);
+ int c1 = lre_parse_escape(&p1, true);
if (c1 >= 0 && lre_js_is_ident_first(c1)) {
c = c1;
p = p1;
- ident_has_escape = TRUE;
+ ident_has_escape = true;
goto has_ident;
} else {
/* XXX: syntax error? */
@@ -20943,37 +19603,39 @@ static __exception int next_token(JSParseState *s)
case '_':
case '$':
/* identifier */
+ s->mark = p;
p++;
- ident_has_escape = FALSE;
+ ident_has_escape = false;
has_ident:
- atom = parse_ident(s, &p, &ident_has_escape, c, FALSE);
+ atom = parse_ident(s, &p, &ident_has_escape, c, false);
if (atom == JS_ATOM_NULL)
goto fail;
s->token.u.ident.atom = atom;
s->token.u.ident.has_escape = ident_has_escape;
- s->token.u.ident.is_reserved = FALSE;
+ s->token.u.ident.is_reserved = false;
s->token.val = TOK_IDENT;
update_token_ident(s);
break;
case '#':
/* private name */
{
- const uint8_t *p1;
p++;
- p1 = p;
- c = *p1++;
- if (c == '\\' && *p1 == 'u') {
- c = lre_parse_escape(&p1, TRUE);
- } else if (c >= 128) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);
+ c = *p;
+ p_next = p + 1;
+ if (c == '\\' && *p_next == 'u') {
+ c = lre_parse_escape(&p_next, true);
+ } else if (c >= 0x80) {
+ c = utf8_decode(p, &p_next);
+ if (p_next == p + 1)
+ goto invalid_utf8;
}
if (!lre_js_is_ident_first(c)) {
js_parse_error(s, "invalid first character of private name");
goto fail;
}
- p = p1;
- ident_has_escape = FALSE; /* not used */
- atom = parse_ident(s, &p, &ident_has_escape, c, TRUE);
+ p = p_next;
+ ident_has_escape = false; /* not used */
+ atom = parse_ident(s, &p, &ident_has_escape, c, true);
if (atom == JS_ATOM_NULL)
goto fail;
s->token.u.ident.atom = atom;
@@ -20987,51 +19649,56 @@ static __exception int next_token(JSParseState *s)
break;
}
if (p[1] >= '0' && p[1] <= '9') {
+ flags = ATOD_ACCEPT_UNDERSCORES | ATOD_ACCEPT_FLOAT;
+ radix = 10;
goto parse_number;
- } else {
- goto def_token;
}
- break;
+ goto def_token;
case '0':
- /* in strict mode, octal literals are not accepted */
- if (is_digit(p[1]) && (s->cur_func->js_mode & JS_MODE_STRICT)) {
- js_parse_error(s, "octal literals are deprecated in strict mode");
+ if (is_digit(p[1])) { /* handle legacy octal */
+ if (s->cur_func->is_strict_mode) {
+ js_parse_error(s, "Octal literals are not allowed in strict mode");
+ goto fail;
+ }
+ /* Legacy octal: no separators, no suffix, no floats,
+ base 8 unless non octal digits are detected */
+ flags = 0;
+ radix = 8;
+ while (is_digit(*p)) {
+ if (*p >= '8' && *p <= '9')
+ radix = 10;
+ p++;
+ }
+ p = s->token.ptr;
+ goto parse_number;
+ }
+ if (p[1] == '_') {
+ js_parse_error(s, "Numeric separator can not be used after leading 0");
goto fail;
}
+ flags = ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT |
+ ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_UNDERSCORES | ATOD_ACCEPT_SUFFIX;
+ radix = 10;
goto parse_number;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8':
case '9':
/* number */
- parse_number:
{
JSValue ret;
- const uint8_t *p1;
- int flags, radix;
- flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL |
- ATOD_ACCEPT_UNDERSCORES;
- flags |= ATOD_ACCEPT_SUFFIX;
-#ifdef CONFIG_BIGNUM
- if (s->cur_func->js_mode & JS_MODE_MATH) {
- flags |= ATOD_MODE_BIGINT;
- if (s->cur_func->js_mode & JS_MODE_MATH)
- flags |= ATOD_TYPE_BIG_FLOAT;
- }
-#endif
- radix = 0;
-#ifdef CONFIG_BIGNUM
- s->token.u.num.exponent = 0;
- ret = js_atof2(s->ctx, (const char *)p, (const char **)&p, radix,
- flags, &s->token.u.num.exponent);
-#else
- ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix,
- flags);
-#endif
+ const char *p1;
+
+ flags = ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_UNDERSCORES | ATOD_ACCEPT_SUFFIX;
+ radix = 10;
+ parse_number:
+ p1 = (const char *)p;
+ ret = js_atof(s->ctx, p1, s->buf_end - p, &p1, radix, flags);
+ p = (const uint8_t *)p1;
if (JS_IsException(ret))
goto fail;
/* reject `10instanceof Number` */
if (JS_VALUE_IS_NAN(ret) ||
- lre_js_is_ident_next(unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1))) {
+ lre_js_is_ident_next(utf8_decode(p, &p_next))) {
JS_FreeValue(s->ctx, ret);
js_parse_error(s, "invalid number literal");
goto fail;
@@ -21080,8 +19747,8 @@ static __exception int next_token(JSParseState *s)
p += 2;
s->token.val = TOK_MINUS_ASSIGN;
} else if (p[1] == '-') {
- if (s->allow_html_comments &&
- p[2] == '>' && s->last_line_num != s->line_num) {
+ if (s->allow_html_comments && p[2] == '>' &&
+ (s->got_lf || s->last_ptr == s->buf_start)) {
/* Annex B: `-->` at beginning of line is an html comment end.
It extends to the end of the line.
*/
@@ -21182,33 +19849,6 @@ static __exception int next_token(JSParseState *s)
goto def_token;
}
break;
-#ifdef CONFIG_BIGNUM
- /* in math mode, '^' is the power operator. '^^' is always the
- xor operator and '**' is always the power operator */
- case '^':
- if (p[1] == '=') {
- p += 2;
- if (s->cur_func->js_mode & JS_MODE_MATH)
- s->token.val = TOK_MATH_POW_ASSIGN;
- else
- s->token.val = TOK_XOR_ASSIGN;
- } else if (p[1] == '^') {
- if (p[2] == '=') {
- p += 3;
- s->token.val = TOK_XOR_ASSIGN;
- } else {
- p += 2;
- s->token.val = '^';
- }
- } else {
- p++;
- if (s->cur_func->js_mode & JS_MODE_MATH)
- s->token.val = TOK_MATH_POW;
- else
- s->token.val = '^';
- }
- break;
-#else
case '^':
if (p[1] == '=') {
p += 2;
@@ -21217,7 +19857,6 @@ static __exception int next_token(JSParseState *s)
goto def_token;
}
break;
-#endif
case '|':
if (p[1] == '=') {
p += 2;
@@ -21251,9 +19890,11 @@ static __exception int next_token(JSParseState *s)
}
break;
default:
- if (c >= 128) {
- /* unicode value */
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
+ if (c >= 0x80) { /* non-ASCII code-point */
+ c = utf8_decode(p, &p_next);
+ if (p_next == p + 1)
+ goto invalid_utf8;
+ p = p_next;
switch(c) {
case CP_PS:
case CP_LS:
@@ -21262,9 +19903,10 @@ static __exception int next_token(JSParseState *s)
goto line_terminator;
default:
if (lre_is_space(c)) {
+ s->mark = p;
goto redo;
} else if (lre_js_is_ident_first(c)) {
- ident_has_escape = FALSE;
+ ident_has_escape = false;
goto has_ident;
} else {
js_parse_error(s, "unexpected character");
@@ -21277,16 +19919,150 @@ static __exception int next_token(JSParseState *s)
p++;
break;
}
+ s->token.col_num = max_int(1, s->mark - s->eol);
s->buf_ptr = p;
// dump_token(s, &s->token);
return 0;
+ invalid_utf8:
+ js_parse_error(s, "invalid UTF-8 sequence");
fail:
s->token.val = TOK_ERROR;
return -1;
}
+static int json_parse_error(JSParseState *s, const uint8_t *curp, const char *msg)
+{
+ const uint8_t *p, *line_start;
+ int position = curp - s->buf_start;
+ int line = 1;
+ for (line_start = p = s->buf_start; p < curp; p++) {
+ /* column count does not account for TABs nor wide characters */
+ if (*p == '\r' || *p == '\n') {
+ p += 1 + (p[0] == '\r' && p[1] == '\n');
+ line++;
+ line_start = p;
+ }
+ }
+ return js_parse_error(s, "%s in JSON at position %d (line %d column %d)",
+ msg, position, line, (int)(p - line_start) + 1);
+}
+
+static int json_parse_string(JSParseState *s, const uint8_t **pp)
+{
+ const uint8_t *p, *p_next;
+ int i;
+ uint32_t c;
+ StringBuffer b_s, *b = &b_s;
+
+ if (string_buffer_init(s->ctx, b, 32))
+ goto fail;
+
+ p = *pp;
+ for(;;) {
+ if (p >= s->buf_end) {
+ goto end_of_input;
+ }
+ c = *p++;
+ if (c == '"')
+ break;
+ if (c < 0x20) {
+ json_parse_error(s, p - 1, "Bad control character in string literal");
+ goto fail;
+ }
+ if (c == '\\') {
+ c = *p++;
+ switch(c) {
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case '\"': break;
+ case '\\': break;
+ case '/': break; /* for v8 compatibility */
+ case 'u':
+ c = 0;
+ for(i = 0; i < 4; i++) {
+ int h = from_hex(*p++);
+ if (h < 0) {
+ json_parse_error(s, p - 1, "Bad Unicode escape");
+ goto fail;
+ }
+ c = (c << 4) | h;
+ }
+ break;
+ default:
+ if (p > s->buf_end)
+ goto end_of_input;
+ json_parse_error(s, p - 1, "Bad escaped character");
+ goto fail;
+ }
+ } else
+ if (c >= 0x80) {
+ c = utf8_decode(p - 1, &p_next);
+ if (p_next == p) {
+ json_parse_error(s, p - 1, "Bad UTF-8 sequence");
+ goto fail;
+ }
+ p = p_next;
+ }
+ if (string_buffer_putc(b, c))
+ goto fail;
+ }
+ s->token.val = TOK_STRING;
+ s->token.u.str.sep = '"';
+ s->token.u.str.str = string_buffer_end(b);
+ *pp = p;
+ return 0;
+
+ end_of_input:
+ js_parse_error(s, "Unexpected end of JSON input");
+ fail:
+ string_buffer_free(b);
+ return -1;
+}
+
+static int json_parse_number(JSParseState *s, const uint8_t **pp)
+{
+ const uint8_t *p = *pp;
+ const uint8_t *p_start = p;
+
+ if (*p == '+' || *p == '-')
+ p++;
+
+ if (!is_digit(*p))
+ return js_parse_error(s, "Unexpected token '%c'", *p_start);
+
+ if (p[0] == '0' && is_digit(p[1]))
+ return json_parse_error(s, p, "Unexpected number");
+
+ while (is_digit(*p))
+ p++;
+
+ if (*p == '.') {
+ p++;
+ if (!is_digit(*p))
+ return json_parse_error(s, p, "Unterminated fractional number");
+ while (is_digit(*p))
+ p++;
+ }
+ if (*p == 'e' || *p == 'E') {
+ p++;
+ if (*p == '+' || *p == '-')
+ p++;
+ if (!is_digit(*p))
+ return json_parse_error(s, p, "Exponent part is missing a number");
+ while (is_digit(*p))
+ p++;
+ }
+ s->token.val = TOK_NUMBER;
+ s->token.u.num.val = js_float64(safe_strtod((const char *)p_start, NULL));
+ *pp = p;
+ return 0;
+}
+
/* 'c' is the first character. Return JS_ATOM_NULL in case of error */
static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
{
@@ -21302,7 +20078,8 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
for(;;) {
buf[ident_pos++] = c;
c = *p;
- if (c >= 128 || !lre_is_id_continue_byte(c))
+ if (c >= 128 ||
+ !((lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1))
break;
p++;
if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) {
@@ -21312,6 +20089,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
}
}
}
+ /* buf contains pure ASCII */
atom = JS_NewAtomLen(s->ctx, buf, ident_pos);
done:
if (unlikely(buf != ident_buf))
@@ -21322,20 +20100,23 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
static __exception int json_next_token(JSParseState *s)
{
- const uint8_t *p;
+ const uint8_t *p, *p_next;
int c;
JSAtom atom;
- if (js_check_stack_overflow(s->ctx->rt, 0)) {
- return js_parse_error(s, "stack overflow");
+ if (js_check_stack_overflow(s->ctx->rt, 1000)) {
+ JS_ThrowStackOverflow(s->ctx);
+ return -1;
}
free_token(s, &s->token);
p = s->last_ptr = s->buf_ptr;
s->last_line_num = s->token.line_num;
+ s->last_col_num = s->token.col_num;
redo:
s->token.line_num = s->line_num;
+ s->token.col_num = s->col_num;
s->token.ptr = p;
c = *p;
switch(c) {
@@ -21347,13 +20128,11 @@ static __exception int json_next_token(JSParseState *s)
}
break;
case '\'':
- if (!s->ext_json) {
- /* JSON does not accept single quoted strings */
- goto def_token;
- }
- /* fall through */
+ /* JSON does not accept single quoted strings */
+ goto def_token;
case '\"':
- if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))
+ p++;
+ if (json_parse_string(s, &p))
goto fail;
break;
case '\r': /* accept DOS and MAC newline sequences */
@@ -21362,77 +20141,22 @@ static __exception int json_next_token(JSParseState *s)
}
/* fall thru */
case '\n':
- p++;
s->line_num++;
+ s->eol = p++;
+ s->mark = p;
goto redo;
case '\f':
case '\v':
- if (!s->ext_json) {
- /* JSONWhitespace does not match <VT>, nor <FF> */
- goto def_token;
- }
- /* fall through */
+ /* JSONWhitespace does not match <VT>, nor <FF> */
+ goto def_token;
case ' ':
case '\t':
p++;
+ s->mark = p;
goto redo;
case '/':
- if (!s->ext_json) {
- /* JSON does not accept comments */
- goto def_token;
- }
- if (p[1] == '*') {
- /* comment */
- p += 2;
- for(;;) {
- if (*p == '\0' && p >= s->buf_end) {
- js_parse_error(s, "unexpected end of comment");
- goto fail;
- }
- if (p[0] == '*' && p[1] == '/') {
- p += 2;
- break;
- }
- if (*p == '\n') {
- s->line_num++;
- p++;
- } else if (*p == '\r') {
- p++;
- } else if (*p >= 0x80) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
- if (c == -1) {
- p++; /* skip invalid UTF-8 */
- }
- } else {
- p++;
- }
- }
- goto redo;
- } else if (p[1] == '/') {
- /* line comment */
- p += 2;
- for(;;) {
- if (*p == '\0' && p >= s->buf_end)
- break;
- if (*p == '\r' || *p == '\n')
- break;
- if (*p >= 0x80) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
- /* LS or PS are considered as line terminator */
- if (c == CP_LS || c == CP_PS) {
- break;
- } else if (c == -1) {
- p++; /* skip invalid UTF-8 */
- }
- } else {
- p++;
- }
- }
- goto redo;
- } else {
- goto def_token;
- }
- break;
+ /* JSON does not accept comments */
+ goto def_token;
case 'a': case 'b': case 'c': case 'd':
case 'e': case 'f': case 'g': case 'h':
case 'i': case 'j': case 'k': case 'l':
@@ -21455,48 +20179,41 @@ static __exception int json_next_token(JSParseState *s)
if (atom == JS_ATOM_NULL)
goto fail;
s->token.u.ident.atom = atom;
- s->token.u.ident.has_escape = FALSE;
- s->token.u.ident.is_reserved = FALSE;
+ s->token.u.ident.has_escape = false;
+ s->token.u.ident.is_reserved = false;
s->token.val = TOK_IDENT;
break;
- case '+':
- if (!s->ext_json || !is_digit(p[1]))
- goto def_token;
+ case '-':
+ if (!is_digit(p[1])) {
+ json_parse_error(s, p, "No number after minus sign");
+ goto fail;
+ }
goto parse_number;
case '0':
- if (is_digit(p[1]))
- goto def_token;
- goto parse_number;
- case '-':
- if (!is_digit(p[1]))
- goto def_token;
+ if (is_digit(p[1])) {
+ json_parse_error(s, p, "Unexpected number");
+ goto fail;
+ }
goto parse_number;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8':
case '9':
/* number */
parse_number:
- {
- JSValue ret;
- int flags, radix;
- if (!s->ext_json) {
- flags = 0;
- radix = 10;
- } else {
- flags = ATOD_ACCEPT_BIN_OCT;
- radix = 0;
- }
- ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix,
- flags);
- if (JS_IsException(ret))
- goto fail;
- s->token.val = TOK_NUMBER;
- s->token.u.num.val = ret;
- }
+ if (json_parse_number(s, &p))
+ goto fail;
break;
default:
- if (c >= 128) {
- js_parse_error(s, "unexpected character");
+ if (c >= 0x80) {
+ c = utf8_decode(p, &p_next);
+ if (p_next == p + 1) {
+ js_parse_error(s, "Unexpected token '\\x%02x' in JSON", *p);
+ } else {
+ if (c > 0xFFFF) {
+ c = get_hi_surrogate(c);
+ }
+ js_parse_error(s, "Unexpected token '\\u%04x' in JSON", c);
+ }
goto fail;
}
def_token:
@@ -21504,6 +20221,7 @@ static __exception int json_next_token(JSParseState *s)
p++;
break;
}
+ s->token.col_num = s->mark - s->eol;
s->buf_ptr = p;
// dump_token(s, &s->token);
@@ -21514,30 +20232,10 @@ static __exception int json_next_token(JSParseState *s)
return -1;
}
-static int match_identifier(const uint8_t *p, const char *s) {
- uint32_t c;
- while (*s) {
- if ((uint8_t)*s++ != *p++)
- return 0;
- }
- c = *p;
- if (c >= 128)
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
- return !lre_js_is_ident_next(c);
-}
-
-/* simple_next_token() is used to check for the next token in simple cases.
- It is only used for ':' and '=>', 'let' or 'function' look-ahead.
- (*pp) is only set if TOK_IMPORT is returned for JS_DetectModule()
- Whitespace and comments are skipped correctly.
- Then the next token is analyzed, only for specific words.
- Return values:
- - '\n' if !no_line_terminator
- - TOK_ARROW, TOK_IN, TOK_IMPORT, TOK_OF, TOK_EXPORT, TOK_FUNCTION
- - TOK_IDENT is returned for other identifiers and keywords
- - otherwise the next character or unicode codepoint is returned.
- */
-static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator)
+/* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is
+ only set if TOK_IMPORT is returned */
+/* XXX: handle all unicode cases */
+static int simple_next_token(const uint8_t **pp, bool no_line_terminator)
{
const uint8_t *p;
uint32_t c;
@@ -21580,49 +20278,43 @@ static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator)
if (*p == '>')
return TOK_ARROW;
break;
- case 'i':
- if (match_identifier(p, "n"))
- return TOK_IN;
- if (match_identifier(p, "mport")) {
- *pp = p + 5;
- return TOK_IMPORT;
- }
- return TOK_IDENT;
- case 'o':
- if (match_identifier(p, "f"))
- return TOK_OF;
- return TOK_IDENT;
- case 'e':
- if (match_identifier(p, "xport"))
- return TOK_EXPORT;
- return TOK_IDENT;
- case 'f':
- if (match_identifier(p, "unction"))
- return TOK_FUNCTION;
- return TOK_IDENT;
- case '\\':
- if (*p == 'u') {
- if (lre_js_is_ident_first(lre_parse_escape(&p, TRUE)))
- return TOK_IDENT;
- }
- break;
default:
- if (c >= 128) {
- c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p);
- if (no_line_terminator && (c == CP_PS || c == CP_LS))
- return '\n';
- }
- if (lre_is_space(c))
- continue;
- if (lre_js_is_ident_first(c))
+ if (lre_js_is_ident_first(c)) {
+ if (c == 'i') {
+ if (p[0] == 'n' && !lre_js_is_ident_next(p[1])) {
+ return TOK_IN;
+ }
+ if (p[0] == 'm' && p[1] == 'p' && p[2] == 'o' &&
+ p[3] == 'r' && p[4] == 't' &&
+ !lre_js_is_ident_next(p[5])) {
+ *pp = p + 5;
+ return TOK_IMPORT;
+ }
+ } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) {
+ return TOK_OF;
+ } else if (c == 'e' &&
+ p[0] == 'x' && p[1] == 'p' && p[2] == 'o' &&
+ p[3] == 'r' && p[4] == 't' &&
+ !lre_js_is_ident_next(p[5])) {
+ *pp = p + 5;
+ return TOK_EXPORT;
+ } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' &&
+ p[2] == 'c' && p[3] == 't' && p[4] == 'i' &&
+ p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) {
+ return TOK_FUNCTION;
+ } else if (c == 'a' && p[0] == 'w' && p[1] == 'a' &&
+ p[2] == 'i' && p[3] == 't' && !lre_js_is_ident_next(p[4])) {
+ return TOK_AWAIT;
+ }
return TOK_IDENT;
+ }
break;
}
return c;
}
}
-static int peek_token(JSParseState *s, BOOL no_line_terminator)
+static int peek_token(JSParseState *s, bool no_line_terminator)
{
const uint8_t *p = s->buf_ptr;
return simple_next_token(&p, no_line_terminator);
@@ -21639,12 +20331,10 @@ static void skip_shebang(const uint8_t **pp, const uint8_t *buf_end)
if (*p == '\n' || *p == '\r') {
break;
} else if (*p >= 0x80) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
- if (c == CP_LS || c == CP_PS) {
+ c = utf8_decode(p, &p);
+ /* purposely ignore UTF-8 encoding errors in this comment line */
+ if (c == CP_LS || c == CP_PS)
break;
- } else if (c == -1) {
- p++; /* skip invalid UTF-8 */
- }
} else {
p++;
}
@@ -21653,29 +20343,6 @@ static void skip_shebang(const uint8_t **pp, const uint8_t *buf_end)
}
}
-/* return true if 'input' contains the source of a module
- (heuristic). 'input' must be a zero terminated.
-
- Heuristic: skip comments and expect 'import' keyword not followed
- by '(' or '.' or export keyword.
-*/
-BOOL JS_DetectModule(const char *input, size_t input_len)
-{
- const uint8_t *p = (const uint8_t *)input;
- int tok;
-
- skip_shebang(&p, p + input_len);
- switch(simple_next_token(&p, FALSE)) {
- case TOK_IMPORT:
- tok = simple_next_token(&p, FALSE);
- return (tok != '.' && tok != '(');
- case TOK_EXPORT:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
static inline int get_prev_opcode(JSFunctionDef *fd) {
if (fd->last_opcode_pos < 0)
return OP_invalid;
@@ -21683,7 +20350,7 @@ static inline int get_prev_opcode(JSFunctionDef *fd) {
return fd->byte_code.buf[fd->last_opcode_pos];
}
-static BOOL js_is_live_code(JSParseState *s) {
+static bool js_is_live_code(JSParseState *s) {
switch (get_prev_opcode(s->cur_func)) {
case OP_tail_call:
case OP_tail_call_method:
@@ -21693,14 +20360,12 @@ static BOOL js_is_live_code(JSParseState *s) {
case OP_throw:
case OP_throw_error:
case OP_goto:
-#if SHORT_OPCODES
case OP_goto8:
case OP_goto16:
-#endif
case OP_ret:
- return FALSE;
+ return false;
default:
- return TRUE;
+ return true;
}
}
@@ -21719,19 +20384,21 @@ static void emit_u32(JSParseState *s, uint32_t val)
dbuf_put_u32(&s->cur_func->byte_code, val);
}
+static void emit_source_loc(JSParseState *s)
+{
+ JSFunctionDef *fd = s->cur_func;
+ DynBuf *bc = &fd->byte_code;
+
+ dbuf_putc(bc, OP_source_loc);
+ dbuf_put_u32(bc, s->token.line_num);
+ dbuf_put_u32(bc, s->token.col_num);
+}
+
static void emit_op(JSParseState *s, uint8_t val)
{
JSFunctionDef *fd = s->cur_func;
DynBuf *bc = &fd->byte_code;
- /* Use the line number of the last token used, not the next token,
- nor the current offset in the source file.
- */
- if (unlikely(fd->last_opcode_line_num != s->last_line_num)) {
- dbuf_putc(bc, OP_line_num);
- dbuf_put_u32(bc, s->last_line_num);
- fd->last_opcode_line_num = s->last_line_num;
- }
fd->last_opcode_pos = bc->size;
dbuf_putc(bc, val);
}
@@ -21824,8 +20491,8 @@ static int cpool_add(JSParseState *s, JSValue val)
return fd->cpool_count - 1;
}
-static __exception int emit_push_const(JSParseState *s, JSValueConst val,
- BOOL as_atom)
+static __exception int emit_push_const(JSParseState *s, JSValue val,
+ bool as_atom)
{
int idx;
@@ -21849,6 +20516,86 @@ static __exception int emit_push_const(JSParseState *s, JSValueConst val,
return 0;
}
+// perl hash; variation of k&r hash with a different magic multiplier
+// and a final shuffle to improve distribution of the low-order bits
+static uint32_t hash_bytes(uint32_t h, const void *b, size_t n)
+{
+ const char *p;
+
+ for (p = b; p < (char *)b + n; p++)
+ h = 33*h + *p;
+ h += h >> 5;
+ return h;
+}
+
+static uint32_t hash_atom(JSAtom atom)
+{
+ return hash_bytes(0, &atom, sizeof(atom));
+}
+
+// caveat emptor: the table size must be a power of two in order for
+// masking to work, and the load factor constant must be an odd number (5)
+//
+// f(n)=n+n/t is used to estimate the load factor but changing t to an
+// even number introduces gaps in the output of f, sometimes "jumping"
+// over the next power of two; it's at powers of two when the hash table
+// must be resized
+static int update_var_htab(JSContext *ctx, JSFunctionDef *fd)
+{
+ uint32_t i, j, k, m, *p;
+
+ if (fd->var_count < 27) // 27 + 27/5 == 32
+ return 0;
+ k = fd->var_count - 1;
+ m = fd->var_count + fd->var_count/5;
+ if (m & (m - 1)) // unless power of two
+ goto insert;
+ m *= 2;
+ p = js_realloc(ctx, fd->vars_htab, m * sizeof(*fd->vars_htab));
+ if (!p)
+ return -1;
+ for (i = 0; i < m; i++)
+ p[i] = UINT32_MAX;
+ fd->vars_htab = p;
+ k = 0;
+ m--;
+insert:
+ m = UINT32_MAX >> clz32(m);
+ do {
+ i = hash_atom(fd->vars[k].var_name);
+ j = 1;
+ for (;;) {
+ p = &fd->vars_htab[i & m];
+ if (*p == UINT32_MAX)
+ break;
+ i += j;
+ j += 1; // quadratic probing
+ }
+ *p = k++;
+ } while (k < (uint32_t)fd->var_count);
+ return 0;
+}
+
+static int find_var_htab(JSFunctionDef *fd, JSAtom var_name)
+{
+ uint32_t i, j, m, *p;
+
+ i = hash_atom(var_name);
+ j = 1;
+ m = fd->var_count + fd->var_count/5;
+ m = UINT32_MAX >> clz32(m);
+ for (;;) {
+ p = &fd->vars_htab[i & m];
+ if (*p == UINT32_MAX)
+ return -1;
+ if (fd->vars[*p].var_name == var_name)
+ return *p;
+ i += j;
+ j += 1; // quadratic probing
+ }
+ return -1; // pacify compiler
+}
+
/* return the variable index or -1 if not found,
add ARGUMENT_VAR_OFFSET for argument variables */
static int find_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
@@ -21863,11 +20610,24 @@ static int find_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
static int find_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
{
+ JSVarDef *vd;
int i;
- for(i = fd->var_count; i-- > 0;) {
- if (fd->vars[i].var_name == name && fd->vars[i].scope_level == 0)
+
+ if (fd->vars_htab) {
+ i = find_var_htab(fd, name);
+ if (i == -1)
+ goto not_found;
+ vd = &fd->vars[i];
+ if (fd->vars[i].scope_level == 0)
return i;
}
+ for(i = fd->var_count; i-- > 0;) {
+ vd = &fd->vars[i];
+ if (vd->var_name == name)
+ if (vd->scope_level == 0)
+ return i;
+ }
+not_found:
return find_arg(ctx, fd, name);
}
@@ -21888,15 +20648,15 @@ static int find_var_in_scope(JSContext *ctx, JSFunctionDef *fd,
/* return true if scope == parent_scope or if scope is a child of
parent_scope */
-static BOOL is_child_scope(JSContext *ctx, JSFunctionDef *fd,
+static bool is_child_scope(JSContext *ctx, JSFunctionDef *fd,
int scope, int parent_scope)
{
while (scope >= 0) {
if (scope == parent_scope)
- return TRUE;
+ return true;
scope = fd->scopes[scope].parent;
}
- return FALSE;
+ return false;
}
/* find a 'var' declaration in the same scope or a child scope */
@@ -21938,7 +20698,7 @@ static JSGlobalVar *find_lexical_global_var(JSFunctionDef *fd, JSAtom name)
}
static int find_lexical_decl(JSContext *ctx, JSFunctionDef *fd, JSAtom name,
- int scope_idx, BOOL check_catch_var)
+ int scope_idx, bool check_catch_var)
{
while (scope_idx >= 0) {
JSVarDef *vd = &fd->vars[scope_idx];
@@ -22030,7 +20790,9 @@ static int add_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
/* the local variable indexes are currently stored on 16 bits */
if (fd->var_count >= JS_MAX_LOCAL_VARS) {
- JS_ThrowInternalError(ctx, "too many local variables");
+ // XXX: add_var() should take JSParseState *s and use js_parse_error
+ JS_ThrowSyntaxError(ctx, "too many variables declared (only %d allowed)",
+ JS_MAX_LOCAL_VARS - 1);
return -1;
}
if (js_resize_array(ctx, (void **)&fd->vars, sizeof(fd->vars[0]),
@@ -22040,6 +20802,8 @@ static int add_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
memset(vd, 0, sizeof(*vd));
vd->var_name = JS_DupAtom(ctx, name);
vd->func_pool_idx = -1;
+ if (update_var_htab(ctx, fd))
+ return -1;
return fd->var_count - 1;
}
@@ -22064,8 +20828,8 @@ static int add_func_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
if (idx < 0 && (idx = add_var(ctx, fd, name)) >= 0) {
fd->func_var_idx = idx;
fd->vars[idx].var_kind = JS_VAR_FUNCTION_NAME;
- if (fd->js_mode & JS_MODE_STRICT)
- fd->vars[idx].is_const = TRUE;
+ if (fd->is_strict_mode)
+ fd->vars[idx].is_const = true;
}
return idx;
}
@@ -22096,7 +20860,7 @@ static int add_arguments_arg(JSContext *ctx, JSFunctionDef *fd)
fd->vars[idx].scope_next = fd->scopes[ARG_SCOPE_INDEX].first;
fd->scopes[ARG_SCOPE_INDEX].first = idx;
fd->vars[idx].scope_level = ARG_SCOPE_INDEX;
- fd->vars[idx].is_lexical = TRUE;
+ fd->vars[idx].is_lexical = true;
fd->arguments_arg_idx = idx;
}
@@ -22110,7 +20874,9 @@ static int add_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
/* the local variable indexes are currently stored on 16 bits */
if (fd->arg_count >= JS_MAX_LOCAL_VARS) {
- JS_ThrowInternalError(ctx, "too many arguments");
+ // XXX: add_arg() should take JSParseState *s and use js_parse_error
+ JS_ThrowSyntaxError(ctx, "too many parameters in function definition (only %d allowed)",
+ JS_MAX_LOCAL_VARS - 1);
return -1;
}
if (js_resize_array(ctx, (void **)&fd->args, sizeof(fd->args[0]),
@@ -22135,9 +20901,9 @@ static JSGlobalVar *add_global_var(JSContext *ctx, JSFunctionDef *s,
return NULL;
hf = &s->global_vars[s->global_var_count++];
hf->cpool_idx = -1;
- hf->force_init = FALSE;
- hf->is_lexical = FALSE;
- hf->is_const = FALSE;
+ hf->force_init = false;
+ hf->is_lexical = false;
+ hf->is_const = false;
hf->scope_level = s->scope_level;
hf->var_name = JS_DupAtom(ctx, name);
return hf;
@@ -22169,13 +20935,13 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
case JS_VAR_DEF_CONST:
case JS_VAR_DEF_FUNCTION_DECL:
case JS_VAR_DEF_NEW_FUNCTION_DECL:
- idx = find_lexical_decl(ctx, fd, name, fd->scope_first, TRUE);
+ idx = find_lexical_decl(ctx, fd, name, fd->scope_first, true);
if (idx >= 0) {
if (idx < GLOBAL_VAR_OFFSET) {
if (fd->vars[idx].scope_level == fd->scope_level) {
/* same scope: in non strict mode, functions
can be redefined (annex B.3.3.4). */
- if (!(!(fd->js_mode & JS_MODE_STRICT) &&
+ if (!(!fd->is_strict_mode &&
var_def_type == JS_VAR_DEF_FUNCTION_DECL &&
fd->vars[idx].var_kind == JS_VAR_FUNCTION_DECL)) {
goto redef_lex_error;
@@ -22220,7 +20986,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
hf = add_global_var(s->ctx, fd, name);
if (!hf)
return -1;
- hf->is_lexical = TRUE;
+ hf->is_lexical = true;
hf->is_const = (var_def_type == JS_VAR_DEF_CONST);
idx = GLOBAL_VAR_OFFSET;
} else {
@@ -22246,7 +21012,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
case JS_VAR_DEF_VAR:
if (find_lexical_decl(ctx, fd, name, fd->scope_first,
- FALSE) >= 0) {
+ false) >= 0) {
invalid_lexical_redefinition:
/* error to redefine a var that inside a lexical scope */
return js_parse_error(s, "invalid redefinition of lexical identifier");
@@ -22283,7 +21049,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
/* add a private field variable in the current scope */
static int add_private_class_field(JSParseState *s, JSFunctionDef *fd,
- JSAtom name, JSVarKindEnum var_kind, BOOL is_static)
+ JSAtom name, JSVarKindEnum var_kind, bool is_static)
{
JSContext *ctx = s->ctx;
JSVarDef *vd;
@@ -22304,7 +21070,7 @@ static __exception int js_parse_function_decl(JSParseState *s,
JSParseFunctionEnum func_type,
JSFunctionKindEnum func_kind,
JSAtom func_name, const uint8_t *ptr,
- int start_line);
+ int start_line, int start_col);
static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s);
static __exception int js_parse_function_decl2(JSParseState *s,
JSParseFunctionEnum func_type,
@@ -22312,6 +21078,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
JSAtom func_name,
const uint8_t *ptr,
int function_line_num,
+ int function_col_num,
JSParseExportEnum export_flag,
JSFunctionDef **pfd);
static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags);
@@ -22327,7 +21094,7 @@ static JSExportEntry *add_export_entry(JSParseState *s, JSModuleDef *m,
JSExportTypeEnum export_type);
/* Note: all the fields are already sealed except length */
-static int seal_template_obj(JSContext *ctx, JSValueConst obj)
+static int seal_template_obj(JSContext *ctx, JSValue obj)
{
JSObject *p;
JSShapeProperty *prs;
@@ -22339,7 +21106,7 @@ static int seal_template_obj(JSContext *ctx, JSValueConst obj)
prs->flags & ~(JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)))
return -1;
}
- p->extensible = FALSE;
+ p->extensible = false;
return 0;
}
@@ -22378,14 +21145,14 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc)
cooked = s->token;
if (call) {
if (JS_DefinePropertyValueUint32(ctx, raw_array, depth,
- JS_DupValue(ctx, s->token.u.str.str),
+ js_dup(s->token.u.str.str),
JS_PROP_ENUMERABLE | JS_PROP_THROW) < 0) {
return -1;
}
/* re-parse the string with escape sequences but do not throw a
syntax error if it contains invalid sequences
*/
- if (js_parse_string(s, '`', FALSE, p, &cooked, &p)) {
+ if (js_parse_string(s, '`', false, p, &cooked, &p)) {
cooked.u.str.str = JS_UNDEFINED;
}
if (JS_DefinePropertyValueUint32(ctx, template_object, depth,
@@ -22400,7 +21167,7 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc)
*/
JS_FreeValue(ctx, s->token.u.str.str);
s->token.u.str.str = JS_UNDEFINED;
- if (js_parse_string(s, '`', TRUE, p, &cooked, &p))
+ if (js_parse_string(s, '`', true, p, &cooked, &p))
return -1;
str = JS_VALUE_GET_STRING(cooked.u.str.str);
if (str->len != 0 || depth == 0) {
@@ -22433,8 +21200,9 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc)
free_token(s, &s->token);
/* Resume TOK_TEMPLATE parsing (s->token.line_num and
* s->token.ptr are OK) */
- s->got_lf = FALSE;
+ s->got_lf = false;
s->last_line_num = s->token.line_num;
+ s->last_col_num = s->token.col_num;
if (js_parse_template_part(s, s->buf_ptr))
return -1;
}
@@ -22465,7 +21233,7 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc)
#define PROP_TYPE_PRIVATE (1 << 4)
-static BOOL token_is_ident(int tok)
+static bool token_is_ident(int tok)
{
/* Accept keywords and reserved words as property names */
return (tok == TOK_IDENT ||
@@ -22476,11 +21244,11 @@ static BOOL token_is_ident(int tok)
/* if the property is an expression, name = JS_ATOM_NULL */
static int __exception js_parse_property_name(JSParseState *s,
JSAtom *pname,
- BOOL allow_method, BOOL allow_var,
- BOOL allow_private)
+ bool allow_method, bool allow_var,
+ bool allow_private)
{
int is_private = 0;
- BOOL is_non_reserved_ident;
+ bool is_non_reserved_ident;
JSAtom name;
int prop_type;
@@ -22494,8 +21262,8 @@ static int __exception js_parse_property_name(JSParseState *s,
goto fail1;
if (s->token.val == ':' || s->token.val == ',' ||
s->token.val == '}' || s->token.val == '(' ||
- s->token.val == '=') {
- is_non_reserved_ident = TRUE;
+ s->token.val == '=' || s->token.val == ';') {
+ is_non_reserved_ident = true;
goto ident_found;
}
prop_type = PROP_TYPE_GET + (name == JS_ATOM_set);
@@ -22505,14 +21273,14 @@ static int __exception js_parse_property_name(JSParseState *s,
goto fail;
prop_type = PROP_TYPE_STAR;
} else if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
- peek_token(s, TRUE) != '\n') {
+ peek_token(s, true) != '\n') {
name = JS_DupAtom(s->ctx, s->token.u.ident.atom);
if (next_token(s))
goto fail1;
if (s->token.val == ':' || s->token.val == ',' ||
s->token.val == '}' || s->token.val == '(' ||
- s->token.val == '=') {
- is_non_reserved_ident = TRUE;
+ s->token.val == '=' || s->token.val == ';') {
+ is_non_reserved_ident = true;
goto ident_found;
}
JS_FreeAtom(s->ctx, name);
@@ -22551,21 +21319,7 @@ static int __exception js_parse_property_name(JSParseState *s,
} else if (s->token.val == TOK_NUMBER) {
JSValue val;
val = s->token.u.num.val;
-#ifdef CONFIG_BIGNUM
- if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- val = s->ctx->rt->bigfloat_ops.
- mul_pow10_to_float64(s->ctx, &p->num,
- s->token.u.num.exponent);
- if (JS_IsException(val))
- goto fail;
- name = JS_ValueToAtom(s->ctx, val);
- JS_FreeValue(s->ctx, val);
- } else
-#endif
- {
- name = JS_ValueToAtom(s->ctx, val);
- }
+ name = JS_ValueToAtom(s->ctx, val);
if (name == JS_ATOM_NULL)
goto fail;
if (next_token(s))
@@ -22604,16 +21358,24 @@ static int __exception js_parse_property_name(JSParseState *s,
typedef struct JSParsePos {
int last_line_num;
+ int last_col_num;
int line_num;
- BOOL got_lf;
+ int col_num;
+ bool got_lf;
const uint8_t *ptr;
+ const uint8_t *eol;
+ const uint8_t *mark;
} JSParsePos;
static int js_parse_get_pos(JSParseState *s, JSParsePos *sp)
{
sp->last_line_num = s->last_line_num;
+ sp->last_col_num = s->last_col_num;
sp->line_num = s->token.line_num;
+ sp->col_num = s->token.col_num;
sp->ptr = s->token.ptr;
+ sp->eol = s->eol;
+ sp->mark = s->mark;
sp->got_lf = s->got_lf;
return 0;
}
@@ -22621,14 +21383,18 @@ static int js_parse_get_pos(JSParseState *s, JSParsePos *sp)
static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)
{
s->token.line_num = sp->last_line_num;
+ s->token.col_num = sp->last_col_num;
s->line_num = sp->line_num;
+ s->col_num = sp->col_num;
s->buf_ptr = sp->ptr;
+ s->eol = sp->eol;
+ s->mark = sp->mark;
s->got_lf = sp->got_lf;
return next_token(s);
}
-/* return TRUE if a regexp literal is allowed after this token */
-static BOOL is_regexp_allowed(int tok)
+/* return true if a regexp literal is allowed after this token */
+static bool is_regexp_allowed(int tok)
{
switch (tok) {
case TOK_NUMBER:
@@ -22644,9 +21410,9 @@ static BOOL is_regexp_allowed(int tok)
case ']':
case '}': /* XXX: regexp may occur after */
case TOK_IDENT:
- return FALSE;
+ return false;
default:
- return TRUE;
+ return true;
}
}
@@ -22657,14 +21423,13 @@ static BOOL is_regexp_allowed(int tok)
/* XXX: improve speed with early bailout */
/* XXX: no longer works if regexps are present. Could use previous
regexp parsing heuristics to handle most cases */
-static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_terminator)
+static int js_parse_skip_parens_token(JSParseState *s, int *pbits, bool no_line_terminator)
{
char state[256];
size_t level = 0;
JSParsePos pos;
int last_tok, tok = TOK_EOF;
- int tok_len, bits = 0;
- char c;
+ int c, tok_len, bits = 0;
/* protect from underflow */
state[level++] = 0;
@@ -22695,8 +21460,9 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_
free_token(s, &s->token);
/* Resume TOK_TEMPLATE parsing (s->token.line_num and
* s->token.ptr are OK) */
- s->got_lf = FALSE;
+ s->got_lf = false;
s->last_line_num = s->token.line_num;
+ s->last_col_num = s->token.col_num;
if (js_parse_template_part(s, s->buf_ptr))
goto done;
goto handle_template;
@@ -22828,18 +21594,19 @@ static __exception int js_parse_object_literal(JSParseState *s)
{
JSAtom name = JS_ATOM_NULL;
const uint8_t *start_ptr;
- int start_line, prop_type;
- BOOL has_proto;
+ int start_line, start_col, prop_type;
+ bool has_proto;
if (next_token(s))
goto fail;
/* XXX: add an initial length that will be patched back */
emit_op(s, OP_object);
- has_proto = FALSE;
+ has_proto = false;
while (s->token.val != '}') {
/* specific case for getter/setter */
start_ptr = s->token.ptr;
start_line = s->token.line_num;
+ start_col = s->token.col_num;
if (s->token.val == TOK_ELLIPSIS) {
if (next_token(s))
@@ -22854,7 +21621,7 @@ static __exception int js_parse_object_literal(JSParseState *s)
goto next;
}
- prop_type = js_parse_property_name(s, &name, TRUE, TRUE, FALSE);
+ prop_type = js_parse_property_name(s, &name, true, true, false);
if (prop_type < 0)
goto fail;
@@ -22866,7 +21633,7 @@ static __exception int js_parse_object_literal(JSParseState *s)
emit_op(s, OP_define_field);
emit_atom(s, name);
} else if (s->token.val == '(') {
- BOOL is_getset = (prop_type == PROP_TYPE_GET ||
+ bool is_getset = (prop_type == PROP_TYPE_GET ||
prop_type == PROP_TYPE_SET);
JSParseFunctionEnum func_type;
JSFunctionKindEnum func_kind;
@@ -22885,7 +21652,7 @@ static __exception int js_parse_object_literal(JSParseState *s)
func_kind = JS_FUNC_ASYNC_GENERATOR;
}
if (js_parse_function_decl(s, func_type, func_kind, JS_ATOM_NULL,
- start_ptr, start_line))
+ start_ptr, start_line, start_col))
goto fail;
if (name == JS_ATOM_NULL) {
emit_op(s, OP_define_method_computed);
@@ -22915,7 +21682,7 @@ static __exception int js_parse_object_literal(JSParseState *s)
goto fail;
}
emit_op(s, OP_set_proto);
- has_proto = TRUE;
+ has_proto = true;
} else {
set_object_name(s, name);
emit_op(s, OP_define_field);
@@ -22954,41 +21721,6 @@ static __exception int js_parse_left_hand_side_expr(JSParseState *s)
return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
}
-/* XXX: could generate specific bytecode */
-static __exception int js_parse_class_default_ctor(JSParseState *s,
- BOOL has_super,
- JSFunctionDef **pfd)
-{
- JSParsePos pos;
- const char *str;
- int ret, line_num;
- JSParseFunctionEnum func_type;
- const uint8_t *saved_buf_end;
-
- js_parse_get_pos(s, &pos);
- if (has_super) {
- /* spec change: no argument evaluation */
- str = "(){super(...arguments);}";
- func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR;
- } else {
- str = "(){}";
- func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;
- }
- line_num = s->token.line_num;
- saved_buf_end = s->buf_end;
- s->buf_ptr = (uint8_t *)str;
- s->buf_end = (uint8_t *)(str + strlen(str));
- ret = next_token(s);
- if (!ret) {
- ret = js_parse_function_decl2(s, func_type, JS_FUNC_NORMAL,
- JS_ATOM_NULL, (uint8_t *)str,
- line_num, JS_PARSE_EXPORT_NONE, pfd);
- }
- s->buf_end = saved_buf_end;
- ret |= js_parse_seek_token(s, &pos);
- return ret;
-}
-
/* find field in the current scope */
static int find_private_class_field(JSContext *ctx, JSFunctionDef *fd,
JSAtom name, int scope_level)
@@ -23042,9 +21774,9 @@ static JSAtom get_private_setter_name(JSContext *ctx, JSAtom name)
typedef struct {
JSFunctionDef *fields_init_fd;
int computed_fields_count;
- BOOL need_brand;
+ bool need_brand;
int brand_push_pos;
- BOOL is_static;
+ bool is_static;
} ClassFieldsDef;
static __exception int emit_class_init_start(JSParseState *s,
@@ -23097,8 +21829,74 @@ static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf)
emit_op(s, OP_set_home_object);
}
+static void emit_return(JSParseState *s, bool hasval);
+
+static JSFunctionDef *js_new_function_def(JSContext *ctx,
+ JSFunctionDef *parent,
+ bool is_eval,
+ bool is_func_expr,
+ const char *filename,
+ int line_num,
+ int col_num);
+
+static __exception int js_parse_class_default_ctor(JSParseState *s,
+ bool has_super,
+ JSFunctionDef **pfd)
+{
+ JSParseFunctionEnum func_type;
+ JSFunctionDef *fd = s->cur_func;
+
+ fd = js_new_function_def(s->ctx, fd, false, false, s->filename,
+ s->token.line_num, s->token.col_num);
+ if (!fd)
+ return -1;
+
+ s->cur_func = fd;
+ fd->has_home_object = true;
+ fd->super_allowed = true;
+ fd->has_prototype = false;
+ fd->has_this_binding = true;
+ fd->new_target_allowed = true;
+
+ push_scope(s); /* enter body scope */
+ fd->body_scope = fd->scope_level;
+ if (has_super) {
+ fd->is_derived_class_constructor = true;
+ fd->super_call_allowed = true;
+ fd->arguments_allowed = true;
+ fd->has_arguments_binding = true;
+ func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR;
+ emit_op(s, OP_init_ctor);
+ // TODO(bnoordhuis) roll into OP_init_ctor
+ emit_op(s, OP_scope_put_var_init);
+ emit_atom(s, JS_ATOM_this);
+ emit_u16(s, 0);
+ emit_class_field_init(s);
+ } else {
+ func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;
+ /* error if not invoked as a constructor */
+ emit_op(s, OP_check_ctor);
+ emit_class_field_init(s);
+ }
+
+ fd->func_kind = JS_FUNC_NORMAL;
+ fd->func_type = func_type;
+ emit_return(s, false);
+
+ s->cur_func = fd->parent;
+ if (pfd)
+ *pfd = fd;
+
+ int idx;
+ /* the real object will be set at the end of the compilation */
+ idx = cpool_add(s, JS_NULL);
+ fd->parent_cpool_idx = idx;
+
+ return 0;
+}
+
-static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
+static __exception int js_parse_class(JSParseState *s, bool is_class_expr,
JSParseExportEnum export_flag)
{
JSContext *ctx = s->ctx;
@@ -23106,16 +21904,16 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
JSAtom name = JS_ATOM_NULL, class_name = JS_ATOM_NULL, class_name1;
JSAtom class_var_name = JS_ATOM_NULL;
JSFunctionDef *method_fd, *ctor_fd;
- int saved_js_mode, class_name_var_idx, prop_type, ctor_cpool_offset;
+ int class_name_var_idx, prop_type, ctor_cpool_offset;
int class_flags = 0, i, define_class_offset;
- BOOL is_static, is_private;
+ bool is_static, is_private, is_strict_mode;
const uint8_t *class_start_ptr = s->token.ptr;
const uint8_t *start_ptr;
ClassFieldsDef class_fields[2];
/* classes are parsed and executed in strict mode */
- saved_js_mode = fd->js_mode;
- fd->js_mode |= JS_MODE_STRICT;
+ is_strict_mode = fd->is_strict_mode;
+ fd->is_strict_mode = true;
if (next_token(s))
goto fail;
if (s->token.val == TOK_IDENT) {
@@ -23185,7 +21983,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
ClassFieldsDef *cf = &class_fields[i];
cf->fields_init_fd = NULL;
cf->computed_fields_count = 0;
- cf->need_brand = FALSE;
+ cf->need_brand = false;
cf->is_static = i;
}
@@ -23196,11 +21994,11 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto fail;
continue;
}
- is_static = FALSE;
+ is_static = false;
if (s->token.val == TOK_STATIC) {
- int next = peek_token(s, TRUE);
+ int next = peek_token(s, true);
if (!(next == ';' || next == '}' || next == '(' || next == '='))
- is_static = TRUE;
+ is_static = true;
}
prop_type = -1;
if (is_static) {
@@ -23208,19 +22006,17 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto fail;
if (s->token.val == '{') {
ClassFieldsDef *cf = &class_fields[is_static];
- JSFunctionDef *init;
- if (!cf->fields_init_fd) {
+ if (!cf->fields_init_fd)
if (emit_class_init_start(s, cf))
goto fail;
- }
s->cur_func = cf->fields_init_fd;
- /* XXX: could try to avoid creating a new function and
- reuse 'fields_init_fd' with a specific 'var'
- scope */
// stack is now: <empty>
+ JSFunctionDef *init;
if (js_parse_function_decl2(s, JS_PARSE_FUNC_CLASS_STATIC_INIT,
JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num,
+ s->token.ptr,
+ s->token.line_num,
+ s->token.col_num,
JS_PARSE_EXPORT_NONE, &init) < 0) {
goto fail;
}
@@ -23230,6 +22026,13 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
emit_atom(s, JS_ATOM_this);
emit_u16(s, 0);
// stack is now: fclosure this
+ if (class_name != JS_ATOM_NULL) {
+ // TODO(bnoordhuis) pass as argument to init method?
+ emit_op(s, OP_dup);
+ emit_op(s, OP_scope_put_var_init);
+ emit_atom(s, class_name);
+ emit_u16(s, s->cur_func->scope_level);
+ }
emit_op(s, OP_swap);
// stack is now: this fclosure
emit_op(s, OP_call_method);
@@ -23243,7 +22046,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
}
/* allow "static" field name */
if (s->token.val == ';' || s->token.val == '=') {
- is_static = FALSE;
+ is_static = false;
name = JS_DupAtom(ctx, JS_ATOM_static);
prop_type = PROP_TYPE_IDENT;
}
@@ -23252,7 +22055,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
emit_op(s, OP_swap);
start_ptr = s->token.ptr;
if (prop_type < 0) {
- prop_type = js_parse_property_name(s, &name, TRUE, FALSE, TRUE);
+ prop_type = js_parse_property_name(s, &name, true, false, true);
if (prop_type < 0)
goto fail;
}
@@ -23267,7 +22070,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto fail;
}
if (prop_type == PROP_TYPE_GET || prop_type == PROP_TYPE_SET) {
- BOOL is_set = prop_type - PROP_TYPE_GET;
+ bool is_set = prop_type - PROP_TYPE_GET;
JSFunctionDef *method_fd;
if (is_private) {
@@ -23290,16 +22093,18 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
JS_VAR_PRIVATE_GETTER + is_set, is_static) < 0)
goto fail;
}
- class_fields[is_static].need_brand = TRUE;
+ class_fields[is_static].need_brand = true;
}
if (js_parse_function_decl2(s, JS_PARSE_FUNC_GETTER + is_set,
JS_FUNC_NORMAL, JS_ATOM_NULL,
- start_ptr, s->token.line_num,
+ start_ptr,
+ s->token.line_num,
+ s->token.col_num,
JS_PARSE_EXPORT_NONE, &method_fd))
goto fail;
if (is_private) {
- method_fd->need_home_object = TRUE; /* needed for brand check */
+ method_fd->need_home_object = true; /* needed for brand check */
emit_op(s, OP_set_home_object);
/* XXX: missing function name */
emit_op(s, OP_scope_put_var_init);
@@ -23379,6 +22184,14 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
emit_atom(s, JS_ATOM_this);
emit_u16(s, 0);
+ // expose class name to static initializers
+ if (is_static && class_name != JS_ATOM_NULL) {
+ emit_op(s, OP_dup);
+ emit_op(s, OP_scope_put_var_init);
+ emit_atom(s, class_name);
+ emit_u16(s, s->cur_func->scope_level);
+ }
+
if (name == JS_ATOM_NULL) {
emit_op(s, OP_scope_get_var);
emit_atom(s, field_var_name);
@@ -23437,15 +22250,19 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;
}
if (is_private) {
- class_fields[is_static].need_brand = TRUE;
+ class_fields[is_static].need_brand = true;
}
- if (js_parse_function_decl2(s, func_type, func_kind, JS_ATOM_NULL, start_ptr, s->token.line_num, JS_PARSE_EXPORT_NONE, &method_fd))
+ if (js_parse_function_decl2(s, func_type, func_kind, JS_ATOM_NULL,
+ start_ptr,
+ s->token.line_num,
+ s->token.col_num,
+ JS_PARSE_EXPORT_NONE, &method_fd))
goto fail;
if (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR ||
func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) {
ctor_fd = method_fd;
} else if (is_private) {
- method_fd->need_home_object = TRUE; /* needed for brand check */
+ method_fd->need_home_object = true; /* needed for brand check */
if (find_private_class_field(ctx, fd, name,
fd->scope_level) >= 0) {
private_field_already_defined:
@@ -23490,14 +22307,11 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
put_u32(fd->byte_code.buf + ctor_cpool_offset, ctor_fd->parent_cpool_idx);
/* store the class source code in the constructor. */
- if (!(fd->js_mode & JS_MODE_STRIP)) {
- js_free(ctx, ctor_fd->source);
- ctor_fd->source_len = s->buf_ptr - class_start_ptr;
- ctor_fd->source = js_strndup(ctx, (const char *)class_start_ptr,
- ctor_fd->source_len);
- if (!ctor_fd->source)
- goto fail;
- }
+ js_free(ctx, ctor_fd->source);
+ ctor_fd->source_len = s->buf_ptr - class_start_ptr;
+ ctor_fd->source = js_strndup(ctx, (const char *)class_start_ptr, ctor_fd->source_len);
+ if (!ctor_fd->source)
+ goto fail;
/* consume the '}' */
if (next_token(s))
@@ -23550,16 +22364,6 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
emit_op(s, OP_add_brand);
}
- if (class_name != JS_ATOM_NULL) {
- /* store the class name in the scoped class name variable (it
- is independent from the class statement variable
- definition) */
- emit_op(s, OP_dup);
- emit_op(s, OP_scope_put_var_init);
- emit_atom(s, class_name);
- emit_u16(s, fd->scope_level);
- }
-
/* initialize the static fields */
if (class_fields[1].fields_init_fd != NULL) {
ClassFieldsDef *cf = &class_fields[1];
@@ -23570,6 +22374,15 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
emit_op(s, OP_drop);
}
+ if (class_name != JS_ATOM_NULL) {
+ /* store the class name in the scoped class name variable (it
+ is independent from the class statement variable
+ definition) */
+ emit_op(s, OP_dup);
+ emit_op(s, OP_scope_put_var_init);
+ emit_atom(s, class_name);
+ emit_u16(s, fd->scope_level);
+ }
pop_scope(s);
pop_scope(s);
@@ -23600,20 +22413,20 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
JS_FreeAtom(ctx, class_name);
JS_FreeAtom(ctx, class_var_name);
- fd->js_mode = saved_js_mode;
+ fd->is_strict_mode = is_strict_mode;
return 0;
fail:
JS_FreeAtom(ctx, name);
JS_FreeAtom(ctx, class_name);
JS_FreeAtom(ctx, class_var_name);
- fd->js_mode = saved_js_mode;
+ fd->is_strict_mode = is_strict_mode;
return -1;
}
static __exception int js_parse_array_literal(JSParseState *s)
{
uint32_t idx;
- BOOL need_length;
+ bool need_length;
if (next_token(s))
return -1;
@@ -23637,17 +22450,17 @@ static __exception int js_parse_array_literal(JSParseState *s)
emit_u16(s, idx);
/* larger arrays and holes are handled with explicit indices */
- need_length = FALSE;
+ need_length = false;
while (s->token.val != ']' && idx < 0x7fffffff) {
if (s->token.val == TOK_ELLIPSIS)
break;
- need_length = TRUE;
+ need_length = true;
if (s->token.val != ',') {
if (js_parse_assign_expr(s))
return -1;
emit_op(s, OP_define_field);
emit_u32(s, __JS_AtomFromUInt32(idx));
- need_length = FALSE;
+ need_length = false;
}
idx++;
/* accept trailing comma */
@@ -23680,41 +22493,15 @@ static __exception int js_parse_array_literal(JSParseState *s)
return -1;
if (js_parse_assign_expr(s))
return -1;
-#if 1
emit_op(s, OP_append);
-#else
- int label_next, label_done;
- label_next = new_label(s);
- label_done = new_label(s);
- /* enumerate object */
- emit_op(s, OP_for_of_start);
- emit_op(s, OP_rot5l);
- emit_op(s, OP_rot5l);
- emit_label(s, label_next);
- /* on stack: enum_rec array idx */
- emit_op(s, OP_for_of_next);
- emit_u8(s, 2);
- emit_goto(s, OP_if_true, label_done);
- /* append element */
- /* enum_rec array idx val -> enum_rec array new_idx */
- emit_op(s, OP_define_array_el);
- emit_op(s, OP_inc);
- emit_goto(s, OP_goto, label_next);
- emit_label(s, label_done);
- /* close enumeration */
- emit_op(s, OP_drop); /* drop undef val */
- emit_op(s, OP_nip1); /* drop enum_rec */
- emit_op(s, OP_nip1);
- emit_op(s, OP_nip1);
-#endif
} else {
- need_length = TRUE;
+ need_length = true;
if (s->token.val != ',') {
if (js_parse_assign_expr(s))
return -1;
/* a idx val */
emit_op(s, OP_define_array_el);
- need_length = FALSE;
+ need_length = false;
}
emit_op(s, OP_inc);
}
@@ -23737,7 +22524,7 @@ done:
}
/* XXX: remove */
-static BOOL has_with_scope(JSFunctionDef *s, int scope_level)
+static bool has_with_scope(JSFunctionDef *s, int scope_level)
{
/* check if scope chain contains a with statement */
while (s) {
@@ -23746,18 +22533,18 @@ static BOOL has_with_scope(JSFunctionDef *s, int scope_level)
JSVarDef *vd = &s->vars[scope_idx];
if (vd->var_name == JS_ATOM__with_)
- return TRUE;
+ return true;
scope_idx = vd->scope_next;
}
/* check parent scopes */
scope_level = s->parent_scope_level;
s = s->parent;
}
- return FALSE;
+ return false;
}
static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
- JSAtom *pname, int *plabel, int *pdepth, BOOL keep,
+ JSAtom *pname, int *plabel, int *pdepth, bool keep,
int tok)
{
JSFunctionDef *fd;
@@ -23775,7 +22562,7 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);
if ((name == JS_ATOM_arguments || name == JS_ATOM_eval) &&
- (fd->js_mode & JS_MODE_STRICT)) {
+ fd->is_strict_mode) {
return js_parse_error(s, "invalid lvalue in strict mode");
}
if (name == JS_ATOM_this || name == JS_ATOM_new_target)
@@ -23893,7 +22680,7 @@ typedef enum {
OP_scope_get_var which is never generated by get_lvalue(). */
static void put_lvalue(JSParseState *s, int opcode, int scope,
JSAtom name, int label, PutLValueEnum special,
- BOOL is_let)
+ bool is_let)
{
switch(opcode) {
case OP_get_field:
@@ -24023,12 +22810,20 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
return js_parse_error(s, "yield is a reserved identifier");
}
if ((name == JS_ATOM_arguments || name == JS_ATOM_eval)
- && (fd->js_mode & JS_MODE_STRICT)) {
+ && fd->is_strict_mode) {
return js_parse_error(s, "invalid variable name in strict mode");
}
- if ((name == JS_ATOM_let || name == JS_ATOM_undefined)
- && (tok == TOK_LET || tok == TOK_CONST)) {
- return js_parse_error(s, "invalid lexical variable name");
+ if (tok == TOK_LET || tok == TOK_CONST) {
+ if (name == JS_ATOM_let)
+ return js_parse_error(s, "invalid lexical variable name 'let'");
+ // |undefined| is allowed as an identifier except at the global
+ // scope of a classic script; sloppy or strict doesn't matter
+ if (name == JS_ATOM_undefined
+ && fd->scope_level == 1
+ && fd->is_global_var
+ && !fd->module) {
+ return js_parse_error(s, "'undefined' already declared");
+ }
}
switch(tok) {
case TOK_LET:
@@ -24093,15 +22888,15 @@ static int js_parse_check_duplicate_parameter(JSParseState *s, JSAtom name)
return 0;
duplicate:
- return js_parse_error(s, "duplicate parameter names not allowed in this context");
+ return js_parse_error(s, "Duplicate parameter name not allowed in this context");
}
-static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)
+static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, bool is_arg)
{
JSAtom name;
if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)
- || ((s->cur_func->js_mode & JS_MODE_STRICT) &&
+ || (s->cur_func->is_strict_mode &&
(s->token.u.ident.atom == JS_ATOM_eval || s->token.u.ident.atom == JS_ATOM_arguments))) {
js_parse_error(s, "invalid destructuring target");
return JS_ATOM_NULL;
@@ -24120,19 +22915,23 @@ fail:
/* Return -1 if error, 0 if no initializer, 1 if an initializer is
present at the top level. */
-static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
- int hasval, int has_ellipsis,
- BOOL allow_initializer)
+static int js_parse_destructuring_element(JSParseState *s, int tok,
+ bool is_arg, bool hasval,
+ int has_ellipsis, // tri-state
+ bool allow_initializer,
+ bool export_flag)
{
int label_parse, label_assign, label_done, label_lvalue, depth_lvalue;
int start_addr, assign_addr;
JSAtom prop_name, var_name;
int opcode, scope, tok1, skip_bits;
- BOOL has_initializer;
+ bool has_initializer;
+
+ label_lvalue = -1;
if (has_ellipsis < 0) {
/* pre-parse destructuration target for spread detection */
- js_parse_skip_parens_token(s, &skip_bits, FALSE);
+ js_parse_skip_parens_token(s, &skip_bits, false);
has_ellipsis = skip_bits & SKIP_HAS_ELLIPSIS;
}
@@ -24186,7 +22985,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
return -1;
if (get_lvalue(s, &opcode, &scope, &var_name,
- &label_lvalue, &depth_lvalue, FALSE, '{'))
+ &label_lvalue, &depth_lvalue, false, '{'))
return -1;
}
if (s->token.val != '}') {
@@ -24198,7 +22997,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
emit_u8(s, 0 | ((depth_lvalue + 1) << 2) | ((depth_lvalue + 2) << 5));
goto set_val;
}
- prop_type = js_parse_property_name(s, &prop_name, FALSE, TRUE, FALSE);
+ prop_type = js_parse_property_name(s, &prop_name, false, true, false);
if (prop_type < 0)
return -1;
var_name = JS_ATOM_NULL;
@@ -24210,7 +23009,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
if (next_token(s))
goto prop_error;
if ((s->token.val == '[' || s->token.val == '{')
- && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == ',' ||
+ && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, false)) == ',' ||
tok1 == '=' || tok1 == '}')) {
if (prop_name == JS_ATOM_NULL) {
/* computed property name on stack */
@@ -24238,7 +23037,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
emit_op(s, OP_get_field2);
emit_u32(s, prop_name);
}
- if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE) < 0)
+ if (js_parse_destructuring_element(s, tok, is_arg, true, -1, true, export_flag) < 0)
return -1;
if (s->token.val == '}')
break;
@@ -24279,7 +23078,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
goto prop_error;
lvalue:
if (get_lvalue(s, &opcode, &scope, &var_name,
- &label_lvalue, &depth_lvalue, FALSE, '{'))
+ &label_lvalue, &depth_lvalue, false, '{'))
goto prop_error;
/* swap ref and lvalue object if any */
if (prop_name == JS_ATOM_NULL) {
@@ -24331,7 +23130,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
/* prop_type = PROP_TYPE_VAR, cannot be a computed property */
if (is_arg && js_parse_check_duplicate_parameter(s, prop_name))
goto prop_error;
- if ((s->cur_func->js_mode & JS_MODE_STRICT) &&
+ if (s->cur_func->is_strict_mode &&
(prop_name == JS_ATOM_eval || prop_name == JS_ATOM_arguments)) {
js_parse_error(s, "invalid destructuring target");
goto prop_error;
@@ -24362,6 +23161,11 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
if (tok) {
if (js_define_var(s, var_name, tok))
goto var_error;
+ if (export_flag) {
+ if (!add_export_entry(s, s->cur_func->module, var_name, var_name,
+ JS_EXPORT_TYPE_LOCAL))
+ goto var_error;
+ }
scope = s->cur_func->scope_level;
}
if (s->token.val == '=') { /* handle optional default value */
@@ -24397,7 +23201,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
if (next_token(s))
return -1;
} else if (s->token.val == '[') {
- BOOL has_spread;
+ bool has_spread;
int enum_depth;
BlockEnv block_env;
@@ -24407,9 +23211,9 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
'yield' triggers a 'return' */
push_break_entry(s->cur_func, &block_env,
JS_ATOM_NULL, -1, -1, 2);
- block_env.has_iterator = TRUE;
+ block_env.has_iterator = true;
emit_op(s, OP_for_of_start);
- has_spread = FALSE;
+ has_spread = false;
while (s->token.val != ']') {
/* get the next value */
if (s->token.val == TOK_ELLIPSIS) {
@@ -24417,7 +23221,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
return -1;
if (s->token.val == ',' || s->token.val == ']')
return js_parse_error(s, "missing binding pattern...");
- has_spread = TRUE;
+ has_spread = true;
}
if (s->token.val == ',') {
/* do nothing, skip the value, has_spread is false */
@@ -24426,7 +23230,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
emit_op(s, OP_drop);
emit_op(s, OP_drop);
} else if ((s->token.val == '[' || s->token.val == '{')
- && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == ',' ||
+ && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, false)) == ',' ||
tok1 == '=' || tok1 == ']')) {
if (has_spread) {
if (tok1 == '=')
@@ -24437,7 +23241,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
emit_u8(s, 0);
emit_op(s, OP_drop);
}
- if (js_parse_destructuring_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)
+ if (js_parse_destructuring_element(s, tok, is_arg, true, skip_bits & SKIP_HAS_ELLIPSIS, true, export_flag) < 0)
return -1;
} else {
var_name = JS_ATOM_NULL;
@@ -24454,7 +23258,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
if (js_parse_left_hand_side_expr(s))
return -1;
if (get_lvalue(s, &opcode, &scope, &var_name,
- &label_lvalue, &enum_depth, FALSE, '[')) {
+ &label_lvalue, &enum_depth, false, '[')) {
return -1;
}
}
@@ -24514,7 +23318,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
return -1;
emit_goto(s, OP_goto, label_assign);
emit_label(s, label_done);
- has_initializer = TRUE;
+ has_initializer = true;
} else {
/* normally hasval is true except if
js_parse_skip_parens_token() was wrong in the parsing */
@@ -24527,7 +23331,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
memset(s->cur_func->byte_code.buf + start_addr, OP_nop,
assign_addr - start_addr);
s->cur_func->label_slots[label_parse].ref_count--;
- has_initializer = FALSE;
+ has_initializer = false;
}
return has_initializer;
@@ -24567,7 +23371,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
{
FuncCallType call_type;
int optional_chaining_label;
- BOOL accept_lparen = (parse_flags & PF_POSTFIX_CALL) != 0;
+ bool accept_lparen = (parse_flags & PF_POSTFIX_CALL) != 0;
call_type = FUNC_CALL_NORMAL;
switch(s->token.val) {
@@ -24579,34 +23383,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) {
emit_op(s, OP_push_i32);
emit_u32(s, JS_VALUE_GET_INT(val));
- } else
-#ifdef CONFIG_BIGNUM
- if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) {
- slimb_t e;
- int ret;
-
- /* need a runtime conversion */
- /* XXX: could add a cache and/or do it once at
- the start of the function */
- if (emit_push_const(s, val, 0) < 0)
- return -1;
- e = s->token.u.num.exponent;
- if (e == (int32_t)e) {
- emit_op(s, OP_push_i32);
- emit_u32(s, e);
- } else {
- val = JS_NewBigInt64_1(s->ctx, e);
- if (JS_IsException(val))
- return -1;
- ret = emit_push_const(s, val, 0);
- JS_FreeValue(s->ctx, val);
- if (ret < 0)
- return -1;
- }
- emit_op(s, OP_mul_pow10);
- } else
-#endif
- {
+ } else {
if (emit_push_const(s, val, 0) < 0)
return -1;
}
@@ -24647,8 +23424,10 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
backtrace_flags = 0;
if (s->cur_func && s->cur_func->backtrace_barrier)
backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL;
- build_backtrace(s->ctx, s->ctx->rt->current_exception,
- s->filename, s->token.line_num,
+ build_backtrace(s->ctx, s->ctx->rt->current_exception, JS_UNDEFINED,
+ s->filename,
+ s->token.line_num,
+ s->token.col_num,
backtrace_flags);
return -1;
}
@@ -24671,11 +23450,13 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
case TOK_FUNCTION:
if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,
JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num))
+ s->token.ptr,
+ s->token.line_num,
+ s->token.col_num))
return -1;
break;
case TOK_CLASS:
- if (js_parse_class(s, TRUE, JS_PARSE_EXPORT_NONE))
+ if (js_parse_class(s, true, JS_PARSE_EXPORT_NONE))
return -1;
break;
case TOK_NULL:
@@ -24707,18 +23488,22 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
return js_parse_error_reserved_identifier(s);
}
if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
- peek_token(s, TRUE) != '\n') {
+ peek_token(s, true) != '\n') {
const uint8_t *source_ptr;
int source_line_num;
+ int source_col_num;
source_ptr = s->token.ptr;
source_line_num = s->token.line_num;
+ source_col_num = s->token.col_num;
if (next_token(s))
return -1;
if (s->token.val == TOK_FUNCTION) {
if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,
JS_FUNC_ASYNC, JS_ATOM_NULL,
- source_ptr, source_line_num))
+ source_ptr,
+ source_line_num,
+ source_col_num))
return -1;
} else {
name = JS_DupAtom(s->ctx, JS_ATOM_async);
@@ -24731,7 +23516,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
return -1;
}
name = JS_DupAtom(s->ctx, s->token.u.ident.atom);
- if (next_token(s)) { /* update line number before emitting code */
+ if (next_token(s)) { /* update line number before emitting code */
JS_FreeAtom(s->ctx, name);
return -1;
}
@@ -24746,8 +23531,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
case '[':
{
int skip_bits;
- if (js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') {
- if (js_parse_destructuring_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)
+ if (js_parse_skip_parens_token(s, &skip_bits, false) == '=') {
+ if (js_parse_destructuring_element(s, 0, false, false, skip_bits & SKIP_HAS_ELLIPSIS, true, false) < 0)
return -1;
} else {
if (s->token.val == '{') {
@@ -24776,9 +23561,10 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
emit_atom(s, JS_ATOM_new_target);
emit_u16(s, 0);
} else {
+ emit_source_loc(s);
if (js_parse_postfix_expr(s, 0))
return -1;
- accept_lparen = TRUE;
+ accept_lparen = true;
if (s->token.val != '(') {
/* new operator on an object */
emit_op(s, OP_dup);
@@ -24844,13 +23630,13 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
optional_chaining_label = -1;
for(;;) {
JSFunctionDef *fd = s->cur_func;
- BOOL has_optional_chain = FALSE;
+ bool has_optional_chain = false;
if (s->token.val == TOK_QUESTION_MARK_DOT) {
/* optional chaining */
if (next_token(s))
return -1;
- has_optional_chain = TRUE;
+ has_optional_chain = true;
if (s->token.val == '(' && accept_lparen) {
goto parse_func_call;
} else if (s->token.val == '[') {
@@ -24875,6 +23661,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
if (call_type == FUNC_CALL_NORMAL) {
parse_func_call2:
+ emit_source_loc(s);
switch(opcode = get_prev_opcode(fd)) {
case OP_get_field:
/* keep the object on the stack */
@@ -24996,7 +23783,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
arg_count = 0;
while (s->token.val != ')') {
if (arg_count >= 65535) {
- return js_parse_error(s, "Too many call arguments");
+ return js_parse_error(s, "Too many arguments in function call (only %d allowed)",
+ 65535 - 1);
}
if (s->token.val == TOK_ELLIPSIS)
break;
@@ -25022,34 +23810,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
return -1;
if (js_parse_assign_expr(s))
return -1;
-#if 1
/* XXX: could pass is_last indicator? */
emit_op(s, OP_append);
-#else
- int label_next, label_done;
- label_next = new_label(s);
- label_done = new_label(s);
- /* push enumerate object below array/idx pair */
- emit_op(s, OP_for_of_start);
- emit_op(s, OP_rot5l);
- emit_op(s, OP_rot5l);
- emit_label(s, label_next);
- /* on stack: enum_rec array idx */
- emit_op(s, OP_for_of_next);
- emit_u8(s, 2);
- emit_goto(s, OP_if_true, label_done);
- /* append element */
- /* enum_rec array idx val -> enum_rec array new_idx */
- emit_op(s, OP_define_array_el);
- emit_op(s, OP_inc);
- emit_goto(s, OP_goto, label_next);
- emit_label(s, label_done);
- /* close enumeration, drop enum_rec and idx */
- emit_op(s, OP_drop); /* drop undef */
- emit_op(s, OP_nip1); /* drop enum_rec */
- emit_op(s, OP_nip1);
- emit_op(s, OP_nip1);
-#endif
} else {
if (js_parse_assign_expr(s))
return -1;
@@ -25082,7 +23844,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
case OP_eval:
emit_op(s, OP_apply_eval);
emit_u16(s, fd->scope_level);
- fd->has_eval_call = TRUE;
+ fd->has_eval_call = true;
break;
default:
if (call_type == FUNC_CALL_SUPER_CTOR) {
@@ -25125,7 +23887,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
emit_op(s, OP_eval);
emit_u16(s, arg_count);
emit_u16(s, fd->scope_level);
- fd->has_eval_call = TRUE;
+ fd->has_eval_call = true;
break;
default:
if (call_type == FUNC_CALL_SUPER_CTOR) {
@@ -25299,7 +24061,7 @@ static __exception int js_parse_delete(JSParseState *s)
name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
if (name == JS_ATOM_this || name == JS_ATOM_new_target)
goto ret_true;
- if (fd->js_mode & JS_MODE_STRICT) {
+ if (fd->is_strict_mode) {
return js_parse_error(s, "cannot delete a direct reference in strict mode");
} else {
fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_delete_var;
@@ -25371,11 +24133,11 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
return -1;
if (js_parse_unary(s, 0))
return -1;
- if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))
+ if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, true, op))
return -1;
emit_op(s, OP_dec + op - TOK_DEC);
put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP,
- FALSE);
+ false);
}
break;
case TOK_TYPEOF:
@@ -25409,7 +24171,7 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
return -1;
if (js_parse_unary(s, PF_POW_FORBIDDEN))
return -1;
- s->cur_func->has_await = TRUE;
+ s->cur_func->has_await = true;
emit_op(s, OP_await);
parse_flags = 0;
break;
@@ -25421,52 +24183,31 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
int opcode, op, scope, label;
JSAtom name;
op = s->token.val;
- if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))
+ if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, true, op))
return -1;
emit_op(s, OP_post_dec + op - TOK_DEC);
put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_SECOND,
- FALSE);
+ false);
if (next_token(s))
return -1;
}
break;
}
if (parse_flags & (PF_POW_ALLOWED | PF_POW_FORBIDDEN)) {
-#ifdef CONFIG_BIGNUM
- if (s->token.val == TOK_POW || s->token.val == TOK_MATH_POW) {
- /* Extended exponentiation syntax rules: we extend the ES7
- grammar in order to have more intuitive semantics:
- -2**2 evaluates to -4. */
- if (!(s->cur_func->js_mode & JS_MODE_MATH)) {
- if (parse_flags & PF_POW_FORBIDDEN) {
- JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'");
- return -1;
- }
- }
- if (next_token(s))
- return -1;
- if (js_parse_unary(s, PF_POW_ALLOWED))
- return -1;
- emit_op(s, OP_pow);
- }
-#else
if (s->token.val == TOK_POW) {
/* Strict ES7 exponentiation syntax rules: To solve
conficting semantics between different implementations
regarding the precedence of prefix operators and the
postifx exponential, ES7 specifies that -2**2 is a
syntax error. */
- if (parse_flags & PF_POW_FORBIDDEN) {
- JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'");
- return -1;
- }
+ if (parse_flags & PF_POW_FORBIDDEN)
+ return js_parse_error(s, "unparenthesized unary expression can't appear on the left-hand side of '**'");
if (next_token(s))
return -1;
if (js_parse_unary(s, PF_POW_ALLOWED))
return -1;
emit_op(s, OP_pow);
}
-#endif
}
return 0;
}
@@ -25481,9 +24222,8 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
return js_parse_unary(s, PF_POW_ALLOWED);
} else if (s->token.val == TOK_PRIVATE_NAME &&
(parse_flags & PF_IN_ACCEPTED) && level == 4 &&
- peek_token(s, FALSE) == TOK_IN) {
+ peek_token(s, false) == TOK_IN) {
JSAtom atom;
-
atom = JS_DupAtom(s->ctx, s->token.u.ident.atom);
if (next_token(s))
goto fail_private_in;
@@ -25517,12 +24257,7 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
opcode = OP_div;
break;
case '%':
-#ifdef CONFIG_BIGNUM
- if (s->cur_func->js_mode & JS_MODE_MATH)
- opcode = OP_math_mod;
- else
-#endif
- opcode = OP_mod;
+ opcode = OP_mod;
break;
default:
return 0;
@@ -25633,6 +24368,7 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
}
if (next_token(s))
return -1;
+ emit_source_loc(s);
if (js_parse_expr_binary(s, level - 1, parse_flags))
return -1;
emit_op(s, opcode);
@@ -25667,8 +24403,7 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op,
if (js_parse_expr_binary(s, 8, parse_flags))
return -1;
} else {
- if (js_parse_logical_and_or(s, TOK_LAND,
- parse_flags))
+ if (js_parse_logical_and_or(s, TOK_LAND, parse_flags))
return -1;
}
if (s->token.val != op) {
@@ -25739,8 +24474,6 @@ static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
return 0;
}
-static void emit_return(JSParseState *s, BOOL hasval);
-
/* allowed parse_flags: PF_IN_ACCEPTED */
static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
{
@@ -25749,7 +24482,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
JSAtom name;
if (s->token.val == TOK_YIELD) {
- BOOL is_star = FALSE, is_async;
+ bool is_star = false, is_async;
if (!(s->cur_func->func_kind & JS_FUNC_GENERATOR))
return js_parse_error(s, "unexpected 'yield' keyword");
@@ -25763,7 +24496,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
s->token.val != ']' && s->token.val != '}' &&
s->token.val != ',' && s->token.val != ':' && !s->got_lf) {
if (s->token.val == '*') {
- is_star = TRUE;
+ is_star = true;
if (next_token(s))
return -1;
}
@@ -25840,7 +24573,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
emit_op(s, OP_nip);
emit_op(s, OP_nip);
emit_op(s, OP_nip);
- emit_return(s, TRUE);
+ emit_return(s, true);
/* throw handling */
emit_label(s, label_throw);
@@ -25881,47 +24614,51 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
emit_op(s, OP_await);
emit_op(s, OP_yield);
label_next = emit_goto(s, OP_if_false, -1);
- emit_return(s, TRUE);
+ emit_return(s, true);
emit_label(s, label_next);
}
return 0;
} else if (s->token.val == '(' &&
- js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {
+ js_parse_skip_parens_token(s, NULL, true) == TOK_ARROW) {
return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num);
+ s->token.ptr, s->token.line_num,
+ s->token.col_num);
} else if (token_is_pseudo_keyword(s, JS_ATOM_async)) {
const uint8_t *source_ptr;
- int source_line_num, tok;
+ int tok, source_line_num, source_col_num;
JSParsePos pos;
/* fast test */
- tok = peek_token(s, TRUE);
+ tok = peek_token(s, true);
if (tok == TOK_FUNCTION || tok == '\n')
goto next;
source_ptr = s->token.ptr;
source_line_num = s->token.line_num;
+ source_col_num = s->token.col_num;
js_parse_get_pos(s, &pos);
if (next_token(s))
return -1;
if ((s->token.val == '(' &&
- js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||
+ js_parse_skip_parens_token(s, NULL, true) == TOK_ARROW) ||
(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&
- peek_token(s, TRUE) == TOK_ARROW)) {
+ peek_token(s, true) == TOK_ARROW)) {
return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
JS_FUNC_ASYNC, JS_ATOM_NULL,
- source_ptr, source_line_num);
+ source_ptr, source_line_num,
+ source_col_num);
} else {
/* undo the token parsing */
if (js_parse_seek_token(s, &pos))
return -1;
}
} else if (s->token.val == TOK_IDENT &&
- peek_token(s, TRUE) == TOK_ARROW) {
+ peek_token(s, true) == TOK_ARROW) {
return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num);
+ s->token.ptr, s->token.line_num,
+ s->token.col_num);
}
next:
if (s->token.val == TOK_IDENT) {
@@ -25939,41 +24676,55 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, (op != '='), op) < 0)
return -1;
+ // comply with rather obtuse evaluation order of computed properties:
+ // obj[key]=val evaluates val->obj->key when obj is null/undefined
+ // but key->obj->val when an object
+ // FIXME(bnoordhuis) less stack shuffling; don't to_propkey twice in
+ // happy path; replace `dup is_undefined_or_null if_true` with new
+ // opcode if_undefined_or_null? replace `swap dup` with over?
+ if (op == '=' && opcode == OP_get_array_el) {
+ int label_next = -1;
+ JSFunctionDef *fd = s->cur_func;
+ assert(OP_to_propkey2 == fd->byte_code.buf[fd->last_opcode_pos]);
+ fd->byte_code.size = fd->last_opcode_pos;
+ fd->last_opcode_pos = -1;
+ emit_op(s, OP_swap); // obj key -> key obj
+ emit_op(s, OP_dup);
+ emit_op(s, OP_is_undefined_or_null);
+ label_next = emit_goto(s, OP_if_true, -1);
+ emit_op(s, OP_swap);
+ emit_op(s, OP_to_propkey);
+ emit_op(s, OP_swap);
+ emit_label(s, label_next);
+ emit_op(s, OP_swap);
+ }
+
if (js_parse_assign_expr2(s, parse_flags)) {
JS_FreeAtom(s->ctx, name);
return -1;
}
+ if (op == '=' && opcode == OP_get_array_el) {
+ emit_op(s, OP_swap); // obj key val -> obj val key
+ emit_op(s, OP_to_propkey);
+ emit_op(s, OP_swap);
+ }
+
if (op == '=') {
if (opcode == OP_get_ref_value && name == name0) {
set_object_name(s, name);
}
} else {
- static const uint8_t assign_opcodes[] = {
- OP_mul, OP_div, OP_mod, OP_add, OP_sub,
- OP_shl, OP_sar, OP_shr, OP_and, OP_xor, OP_or,
-#ifdef CONFIG_BIGNUM
- OP_pow,
-#endif
- OP_pow,
- };
- op = assign_opcodes[op - TOK_MUL_ASSIGN];
-#ifdef CONFIG_BIGNUM
- if (s->cur_func->js_mode & JS_MODE_MATH) {
- if (op == OP_mod)
- op = OP_math_mod;
- }
-#endif
- emit_op(s, op);
+ emit_op(s, op - TOK_MUL_ASSIGN + OP_mul);
}
- put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE);
+ put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, false);
} else if (op >= TOK_LAND_ASSIGN && op <= TOK_DOUBLE_QUESTION_MARK_ASSIGN) {
int label, label1, depth_lvalue, label2;
if (next_token(s))
return -1;
if (get_lvalue(s, &opcode, &scope, &name, &label,
- &depth_lvalue, TRUE, op) < 0)
+ &depth_lvalue, true, op) < 0)
return -1;
emit_op(s, OP_dup);
@@ -26009,7 +24760,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
/* XXX: we disable the OP_put_ref_value optimization by not
using put_lvalue() otherwise depth_lvalue is not correct */
put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_NOKEEP_DEPTH,
- FALSE);
+ false);
label2 = emit_goto(s, OP_goto, -1);
emit_label(s, label1);
@@ -26033,7 +24784,7 @@ static __exception int js_parse_assign_expr(JSParseState *s)
/* allowed parse_flags: PF_IN_ACCEPTED */
static __exception int js_parse_expr2(JSParseState *s, int parse_flags)
{
- BOOL comma = FALSE;
+ bool comma = false;
for(;;) {
if (js_parse_assign_expr2(s, parse_flags))
return -1;
@@ -26047,7 +24798,7 @@ static __exception int js_parse_expr2(JSParseState *s, int parse_flags)
}
if (s->token.val != ',')
break;
- comma = TRUE;
+ comma = true;
if (next_token(s))
return -1;
emit_op(s, OP_drop);
@@ -26073,7 +24824,8 @@ static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,
be->drop_count = drop_count;
be->label_finally = -1;
be->scope_level = fd->scope_level;
- be->has_iterator = FALSE;
+ be->has_iterator = false;
+ be->is_regular_stmt = false;
}
static void pop_break_entry(JSFunctionDef *fd)
@@ -26100,11 +24852,12 @@ static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont)
emit_goto(s, OP_goto, top->label_cont);
return 0;
}
- if (!is_cont &&
- top->label_break != -1 &&
- (name == JS_ATOM_NULL || top->label_name == name)) {
- emit_goto(s, OP_goto, top->label_break);
- return 0;
+ if (!is_cont && top->label_break != -1) {
+ if (top->label_name == name ||
+ (name == JS_ATOM_NULL && !top->is_regular_stmt)) {
+ emit_goto(s, OP_goto, top->label_break);
+ return 0;
+ }
}
i = 0;
if (top->has_iterator) {
@@ -26132,7 +24885,7 @@ static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont)
}
/* execute the finally blocks before return */
-static void emit_return(JSParseState *s, BOOL hasval)
+static void emit_return(JSParseState *s, bool hasval)
{
BlockEnv *top;
@@ -26140,7 +24893,7 @@ static void emit_return(JSParseState *s, BOOL hasval)
if (!hasval) {
/* no value: direct return in case of async generator */
emit_op(s, OP_undefined);
- hasval = TRUE;
+ hasval = true;
} else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
/* the await must be done before handling the "finally" in
case it raises an exception */
@@ -26153,7 +24906,7 @@ static void emit_return(JSParseState *s, BOOL hasval)
if (top->has_iterator || top->label_finally != -1) {
if (!hasval) {
emit_op(s, OP_undefined);
- hasval = TRUE;
+ hasval = true;
}
/* Remove the stack elements up to and including the catch
offset. When 'yield' is used in an expression we have
@@ -26206,9 +24959,9 @@ static void emit_return(JSParseState *s, BOOL hasval)
label_return = -1;
}
- /* The error should be raised in the caller context, so we use
- a specific opcode */
- emit_op(s, OP_scope_get_var_checkthis);
+ /* XXX: if this is not initialized, should throw the
+ ReferenceError in the caller realm */
+ emit_op(s, OP_scope_get_var);
emit_atom(s, JS_ATOM_this);
emit_u16(s, 0);
@@ -26256,7 +25009,7 @@ static __exception int js_parse_block(JSParseState *s)
/* allowed parse_flags: PF_IN_ACCEPTED */
static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
- BOOL export_flag)
+ bool export_flag)
{
JSContext *ctx = s->ctx;
JSFunctionDef *fd = s->cur_func;
@@ -26293,7 +25046,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
emit_op(s, OP_scope_get_var);
emit_atom(s, name);
emit_u16(s, fd->scope_level);
- if (get_lvalue(s, &opcode, &scope, &name1, &label, NULL, FALSE, '=') < 0)
+ if (get_lvalue(s, &opcode, &scope, &name1, &label, NULL, false, '=') < 0)
goto var_error;
if (js_parse_assign_expr2(s, parse_flags)) {
JS_FreeAtom(ctx, name1);
@@ -26301,7 +25054,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
}
set_object_name(s, name);
put_lvalue(s, opcode, scope, name1, label,
- PUT_LVALUE_NOKEEP, FALSE);
+ PUT_LVALUE_NOKEEP, false);
} else {
if (js_parse_assign_expr2(s, parse_flags))
goto var_error;
@@ -26328,9 +25081,9 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
} else {
int skip_bits;
if ((s->token.val == '[' || s->token.val == '{')
- && js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') {
+ && js_parse_skip_parens_token(s, &skip_bits, false) == '=') {
emit_op(s, OP_undefined);
- if (js_parse_destructuring_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)
+ if (js_parse_destructuring_element(s, tok, false, true, skip_bits & SKIP_HAS_ELLIPSIS, true, export_flag) < 0)
return -1;
} else {
return js_parse_error(s, "variable name expected");
@@ -26349,16 +25102,16 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
}
/* test if the current token is a label. Use simplistic look-ahead scanner */
-static BOOL is_label(JSParseState *s)
+static bool is_label(JSParseState *s)
{
return (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&
- peek_token(s, FALSE) == ':');
+ peek_token(s, false) == ':');
}
/* test if the current token is a let keyword. Use simplistic look-ahead scanner */
static int is_let(JSParseState *s, int decl_mask)
{
- int res = FALSE;
+ int res = false;
if (token_is_pseudo_keyword(s, JS_ATOM_let)) {
JSParsePos pos;
@@ -26371,7 +25124,7 @@ static int is_let(JSParseState *s, int decl_mask)
if (s->token.val == '[') {
/* let [ is a syntax restriction:
it never introduces an ExpressionStatement */
- res = TRUE;
+ res = true;
break;
}
if (s->token.val == '{' ||
@@ -26383,7 +25136,7 @@ static int is_let(JSParseState *s, int decl_mask)
/* XXX: should also check that `{` introduces a BindingPattern,
but Firefox does not and rejects eval("let=1;let\n{if(1)2;}") */
if (s->last_line_num == s->token.line_num || (decl_mask & DECL_MASK_OTHER)) {
- res = TRUE;
+ res = true;
break;
}
break;
@@ -26400,20 +25153,20 @@ static int is_let(JSParseState *s, int decl_mask)
/* XXX: handle IteratorClose when exiting the loop before the
enumeration is done */
static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
- BOOL is_async)
+ bool is_async)
{
JSContext *ctx = s->ctx;
JSFunctionDef *fd = s->cur_func;
JSAtom var_name;
- BOOL has_initializer, is_for_of, has_destructuring;
+ bool has_initializer, is_for_of, has_destructuring;
int tok, tok1, opcode, scope, block_scope_level;
int label_next, label_expr, label_cont, label_body, label_break;
int pos_next, pos_expr;
BlockEnv break_entry;
- has_initializer = FALSE;
- has_destructuring = FALSE;
- is_for_of = FALSE;
+ has_initializer = false;
+ has_destructuring = false;
+ is_for_of = false;
block_scope_level = fd->scope_level;
label_cont = new_label(s);
label_body = new_label(s);
@@ -26438,10 +25191,10 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
tok = s->token.val;
switch (is_let(s, DECL_MASK_OTHER)) {
- case TRUE:
+ case true:
tok = TOK_LET;
break;
- case FALSE:
+ case false:
break;
default:
return -1;
@@ -26452,9 +25205,9 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {
if (s->token.val == '[' || s->token.val == '{') {
- if (js_parse_destructuring_element(s, tok, 0, TRUE, -1, FALSE) < 0)
+ if (js_parse_destructuring_element(s, tok, false, true, -1, false, false) < 0)
return -1;
- has_destructuring = TRUE;
+ has_destructuring = true;
} else {
return js_parse_error(s, "variable name expected");
}
@@ -26474,24 +25227,23 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
emit_atom(s, var_name);
emit_u16(s, fd->scope_level);
}
- } else if (!is_async && token_is_pseudo_keyword(s, JS_ATOM_async) &&
- peek_token(s, FALSE) == TOK_OF) {
+ } else if (!is_async && token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, false) == TOK_OF) {
return js_parse_error(s, "'for of' expression cannot start with 'async'");
} else {
int skip_bits;
if ((s->token.val == '[' || s->token.val == '{')
- && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == TOK_IN || tok1 == TOK_OF)) {
- if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)
+ && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, false)) == TOK_IN || tok1 == TOK_OF)) {
+ if (js_parse_destructuring_element(s, 0, false, true, skip_bits & SKIP_HAS_ELLIPSIS, true, false) < 0)
return -1;
} else {
int lvalue_label;
if (js_parse_left_hand_side_expr(s))
return -1;
if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label,
- NULL, FALSE, TOK_FOR))
+ NULL, false, TOK_FOR))
return -1;
put_lvalue(s, opcode, scope, var_name, lvalue_label,
- PUT_LVALUE_NOKEEP_BOTTOM, FALSE);
+ PUT_LVALUE_NOKEEP_BOTTOM, false);
}
var_name = JS_ATOM_NULL;
}
@@ -26501,7 +25253,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
emit_label(s, label_expr);
if (s->token.val == '=') {
/* XXX: potential scoping issue if inside `with` statement */
- has_initializer = TRUE;
+ has_initializer = true;
/* parse and evaluate initializer prior to evaluating the
object (only used with "for in" with a non lexical variable
in non strict mode */
@@ -26518,7 +25270,8 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
JS_FreeAtom(ctx, var_name);
if (token_is_pseudo_keyword(s, JS_ATOM_of)) {
- break_entry.has_iterator = is_for_of = TRUE;
+ is_for_of = true;
+ break_entry.has_iterator = true;
break_entry.drop_count += 2;
if (has_initializer)
goto initializer_error;
@@ -26526,8 +25279,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
if (is_async)
return js_parse_error(s, "'for await' loop should be used with 'of'");
if (has_initializer &&
- (tok != TOK_VAR || (fd->js_mode & JS_MODE_STRICT) ||
- has_destructuring)) {
+ (tok != TOK_VAR || fd->is_strict_mode || has_destructuring)) {
initializer_error:
return js_parse_error(s, "a declaration in the head of a for-%s loop can't have an initializer",
is_for_of ? "of" : "in");
@@ -26562,7 +25314,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
if (js_parse_expect(s, ')'))
return -1;
- if (OPTIMIZE) {
+ {
/* move the `next` code here */
DynBuf *bc = &s->cur_func->byte_code;
int chunk_size = pos_expr - pos_next;
@@ -26663,13 +25415,14 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
&& s->token.val != TOK_DO
&& s->token.val != TOK_WHILE) {
/* labelled regular statement */
+ JSFunctionDef *fd = s->cur_func;
int label_break, mask;
BlockEnv break_entry;
label_break = new_label(s);
- push_break_entry(s->cur_func, &break_entry,
- label_name, label_break, -1, 0);
- if (!(s->cur_func->js_mode & JS_MODE_STRICT) &&
+ push_break_entry(fd, &break_entry, label_name, label_break, -1, 0);
+ fd->top_break->is_regular_stmt = 1;
+ if (!fd->is_strict_mode &&
(decl_mask & DECL_MASK_FUNC_WITH_LABEL)) {
mask = DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL;
} else {
@@ -26678,7 +25431,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
if (js_parse_statement_or_decl(s, mask))
goto fail;
emit_label(s, label_break);
- pop_break_entry(s->cur_func);
+ pop_break_entry(fd);
goto done;
}
}
@@ -26702,9 +25455,9 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
if (s->token.val != ';' && s->token.val != '}' && !s->got_lf) {
if (js_parse_expr(s))
goto fail;
- emit_return(s, TRUE);
+ emit_return(s, true);
} else {
- emit_return(s, FALSE);
+ emit_return(s, false);
}
if (js_parse_expect_semi(s))
goto fail;
@@ -26716,6 +25469,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
js_parse_error(s, "line terminator not allowed after throw");
goto fail;
}
+ emit_source_loc(s);
if (js_parse_expr(s))
goto fail;
emit_op(s, OP_throw);
@@ -26733,7 +25487,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
case TOK_VAR:
if (next_token(s))
goto fail;
- if (js_parse_var(s, TRUE, tok, FALSE))
+ if (js_parse_var(s, PF_IN_ACCEPTED, tok, /*export_flag*/false))
goto fail;
if (js_parse_expect_semi(s))
goto fail;
@@ -26749,7 +25503,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
if (js_parse_expr_paren(s))
goto fail;
label1 = emit_goto(s, OP_if_false, -1);
- if (s->cur_func->js_mode & JS_MODE_STRICT)
+ if (s->cur_func->is_strict_mode)
mask = 0;
else
mask = DECL_MASK_FUNC; /* Annex B.3.4 */
@@ -26847,25 +25601,25 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
int pos_cont, pos_body, block_scope_level;
BlockEnv break_entry;
int tok, bits;
- BOOL is_async;
+ bool is_async;
if (next_token(s))
goto fail;
set_eval_ret_undefined(s);
bits = 0;
- is_async = FALSE;
+ is_async = false;
if (s->token.val == '(') {
- js_parse_skip_parens_token(s, &bits, FALSE);
+ js_parse_skip_parens_token(s, &bits, false);
} else if (s->token.val == TOK_AWAIT) {
if (!(s->cur_func->func_kind & JS_FUNC_ASYNC)) {
js_parse_error(s, "for await is only valid in asynchronous functions");
goto fail;
}
- is_async = TRUE;
+ is_async = true;
if (next_token(s))
goto fail;
- s->cur_func->has_await = TRUE;
+ s->cur_func->has_await = true;
}
if (js_parse_expect(s, '('))
goto fail;
@@ -26885,10 +25639,10 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
tok = s->token.val;
if (tok != ';') {
switch (is_let(s, DECL_MASK_OTHER)) {
- case TRUE:
+ case true:
tok = TOK_LET;
break;
- case FALSE:
+ case false:
break;
default:
goto fail;
@@ -26896,10 +25650,10 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST) {
if (next_token(s))
goto fail;
- if (js_parse_var(s, FALSE, tok, FALSE))
+ if (js_parse_var(s, 0, tok, /*export_flag*/false))
goto fail;
} else {
- if (js_parse_expr2(s, FALSE))
+ if (js_parse_expr2(s, false))
goto fail;
emit_op(s, OP_drop);
}
@@ -26959,7 +25713,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
/* XXX: check continue case */
close_scopes(s, s->cur_func->scope_level, block_scope_level);
- if (OPTIMIZE && label_test != label_body && label_cont != label_test) {
+ if (label_test != label_body && label_cont != label_test) {
/* move the increment code here */
DynBuf *bc = &s->cur_func->byte_code;
int chunk_size = pos_body - pos_cont;
@@ -27158,7 +25912,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {
if (s->token.val == '[' || s->token.val == '{') {
/* XXX: TOK_LET is not completely correct */
- if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE) < 0)
+ if (js_parse_destructuring_element(s, TOK_LET, false, true, -1, true, false) < 0)
goto fail;
} else {
js_parse_error(s, "identifier expected");
@@ -27267,7 +26021,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
goto fail;
break;
case TOK_WITH:
- if (s->cur_func->js_mode & JS_MODE_STRICT) {
+ if (s->cur_func->is_strict_mode) {
js_parse_error(s, "invalid keyword: with");
goto fail;
} else {
@@ -27300,7 +26054,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
/* ES6 Annex B.3.2 and B.3.3 semantics */
if (!(decl_mask & DECL_MASK_FUNC))
goto func_decl_error;
- if (!(decl_mask & DECL_MASK_OTHER) && peek_token(s, FALSE) == '*')
+ if (!(decl_mask & DECL_MASK_OTHER) && peek_token(s, false) == '*')
goto func_decl_error;
goto parse_func_var;
case TOK_IDENT:
@@ -27310,16 +26064,16 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
}
/* Determine if `let` introduces a Declaration or an ExpressionStatement */
switch (is_let(s, decl_mask)) {
- case TRUE:
+ case true:
tok = TOK_LET;
goto haslet;
- case FALSE:
+ case false:
break;
default:
goto fail;
}
if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
- peek_token(s, TRUE) == TOK_FUNCTION) {
+ peek_token(s, true) == TOK_FUNCTION) {
if (!(decl_mask & DECL_MASK_OTHER)) {
func_decl_error:
js_parse_error(s, "function declarations can't appear in single-statement context");
@@ -27328,7 +26082,9 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
parse_func_var:
if (js_parse_function_decl(s, JS_PARSE_FUNC_VAR,
JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num))
+ s->token.ptr,
+ s->token.line_num,
+ s->token.col_num))
goto fail;
break;
}
@@ -27339,7 +26095,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
js_parse_error(s, "class declarations can't appear in single-statement context");
goto fail;
}
- if (js_parse_class(s, FALSE, JS_PARSE_EXPORT_NONE))
+ if (js_parse_class(s, false, JS_PARSE_EXPORT_NONE))
return -1;
break;
@@ -27359,6 +26115,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
default:
hasexpr:
+ emit_source_loc(s);
if (js_parse_expr(s))
goto fail;
if (s->cur_func->eval_ret_idx >= 0) {
@@ -27490,7 +26247,7 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,
return i;
}
-static JSExportEntry *find_export_entry(JSContext *ctx, JSModuleDef *m,
+static JSExportEntry *find_export_entry(JSContext *ctx, const JSModuleDef *m,
JSAtom export_name)
{
JSExportEntry *me;
@@ -27558,6 +26315,7 @@ static int add_star_export_entry(JSContext *ctx, JSModuleDef *m,
}
/* create a C module */
+/* `name_str` may be pure ASCII or UTF-8 encoded */
JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,
JSModuleInitFunc *func)
{
@@ -27571,6 +26329,7 @@ JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,
return m;
}
+/* `export_name` may be pure ASCII or UTF-8 encoded */
int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name)
{
JSExportEntry *me;
@@ -27587,6 +26346,7 @@ int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name)
return 0;
}
+/* `export_name` may be pure ASCII or UTF-8 encoded */
int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
JSValue val)
{
@@ -27669,8 +26429,8 @@ static char *js_default_module_normalize_name(JSContext *ctx,
}
}
if (filename[0] != '\0')
- pstrcat(filename, cap, "/");
- pstrcat(filename, cap, r);
+ js__pstrcat(filename, cap, "/");
+ js__pstrcat(filename, cap, r);
// printf("normalize: %s %s -> %s\n", base_name, name, filename);
return filename;
}
@@ -27690,6 +26450,7 @@ static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name)
}
/* return NULL in case of exception (e.g. module could not be loaded) */
+/* `base_cname` and `cname1` may be pure ASCII or UTF-8 encoded */
static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,
const char *base_cname,
const char *cname1)
@@ -27727,6 +26488,7 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,
/* load the module */
if (!rt->module_loader_func) {
/* XXX: use a syntax error ? */
+ // XXX: update JS_DetectModule when you change this
JS_ThrowReferenceError(ctx, "could not load module '%s'",
cname);
js_free(ctx, cname);
@@ -27972,7 +26734,7 @@ static int find_exported_name(GetExportNamesState *s, JSAtom name)
static __exception int get_exported_names(JSContext *ctx,
GetExportNamesState *s,
- JSModuleDef *m, BOOL from_star)
+ JSModuleDef *m, bool from_star)
{
ExportedNameEntry *en;
int i, j;
@@ -28013,14 +26775,14 @@ static __exception int get_exported_names(JSContext *ctx,
JSStarExportEntry *se = &m->star_export_entries[i];
JSModuleDef *m1;
m1 = m->req_module_entries[se->req_module_idx].module;
- if (get_exported_names(ctx, s, m1, TRUE))
+ if (get_exported_names(ctx, s, m1, true))
return -1;
}
return 0;
}
/* Unfortunately, the spec gives a different behavior from GetOwnProperty ! */
-static int js_module_ns_has(JSContext *ctx, JSValueConst obj, JSAtom atom)
+static int js_module_ns_has(JSContext *ctx, JSValue obj, JSAtom atom)
{
return (find_own_property1(JS_VALUE_GET_OBJ(obj), atom) != NULL);
}
@@ -28044,7 +26806,7 @@ static int exported_names_cmp(const void *p1, const void *p2, void *opaque)
/* XXX: raise an error ? */
ret = 0;
} else {
- ret = js_string_compare(ctx, JS_VALUE_GET_STRING(str1),
+ ret = js_string_compare(JS_VALUE_GET_STRING(str1),
JS_VALUE_GET_STRING(str2));
}
JS_FreeValue(ctx, str1);
@@ -28073,7 +26835,7 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
p = JS_VALUE_GET_OBJ(obj);
memset(s, 0, sizeof(*s));
- ret = get_exported_names(ctx, s, m, FALSE);
+ ret = get_exported_names(ctx, s, m, false);
js_free(ctx, s->modules);
if (ret)
goto fail;
@@ -28109,6 +26871,7 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
en->u.var_ref = res_me->u.local.var_ref;
} else {
JSObject *p1 = JS_VALUE_GET_OBJ(res_m->func_obj);
+ p1 = JS_VALUE_GET_OBJ(res_m->func_obj);
en->u.var_ref = p1->u.func.var_refs[res_me->u.local.var_idx];
}
}
@@ -28125,6 +26888,11 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
case EXPORTED_NAME_NORMAL:
{
JSVarRef *var_ref = en->u.var_ref;
+ if (!var_ref) {
+ js_resolve_export_throw_error(ctx, JS_RESOLVE_RES_CIRCULAR,
+ m, en->export_name);
+ goto fail;
+ }
pr = add_property(ctx, p, en->export_name,
JS_PROP_ENUMERABLE | JS_PROP_WRITABLE |
JS_PROP_VARREF);
@@ -28153,7 +26921,7 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
JS_AtomToString(ctx, JS_ATOM_Module),
0);
- p->extensible = FALSE;
+ p->extensible = false;
return obj;
fail:
js_free(ctx, s->exported_names);
@@ -28170,9 +26938,19 @@ JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m)
return JS_EXCEPTION;
m->module_ns = val;
}
- return JS_DupValue(ctx, m->module_ns);
+ return js_dup(m->module_ns);
}
+#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE
+#define module_trace(ctx, ...) \
+ do { \
+ if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) \
+ printf(__VA_ARGS__); \
+ } while (0)
+#else
+#define module_trace(...)
+#endif
+
/* Load all the required modules for module 'm' */
static int js_resolve_module(JSContext *ctx, JSModuleDef *m)
{
@@ -28181,13 +26959,13 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m)
if (m->resolved)
return 0;
-#ifdef DUMP_MODULE_RESOLVE
- {
+#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE
+ if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) {
char buf1[ATOM_GET_STR_BUF_SIZE];
printf("resolving module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
}
#endif
- m->resolved = TRUE;
+ m->resolved = true;
/* resolve each requested module */
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
@@ -28204,7 +26982,7 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m)
return 0;
}
-static JSVarRef *js_create_module_var(JSContext *ctx, BOOL is_lexical)
+static JSVarRef *js_create_module_var(JSContext *ctx, bool is_lexical)
{
JSVarRef *var_ref;
var_ref = js_malloc(ctx, sizeof(JSVarRef));
@@ -28216,7 +26994,7 @@ static JSVarRef *js_create_module_var(JSContext *ctx, BOOL is_lexical)
else
var_ref->value = JS_UNDEFINED;
var_ref->pvalue = &var_ref->value;
- var_ref->is_detached = TRUE;
+ var_ref->is_detached = true;
add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);
return var_ref;
}
@@ -28258,9 +27036,9 @@ static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m)
var_ref = js_create_module_var(ctx, cv->is_lexical);
if (!var_ref)
goto fail;
-#ifdef DUMP_MODULE_RESOLVE
- printf("local %d: %p\n", i, var_ref);
-#endif
+
+ module_trace(ctx, "local %d: %p\n", i, (void *)var_ref);
+
var_refs[i] = var_ref;
}
}
@@ -28276,7 +27054,7 @@ static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m)
/* must be done before js_link_module() because of cyclic references */
static int js_create_module_function(JSContext *ctx, JSModuleDef *m)
{
- BOOL is_c_module;
+ bool is_c_module;
int i;
JSVarRef *var_ref;
@@ -28290,7 +27068,7 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m)
for(i = 0; i < m->export_entries_count; i++) {
JSExportEntry *me = &m->export_entries[i];
if (me->export_type == JS_EXPORT_TYPE_LOCAL) {
- var_ref = js_create_module_var(ctx, FALSE);
+ var_ref = js_create_module_var(ctx, false);
if (!var_ref)
return -1;
me->u.local.var_ref = var_ref;
@@ -28300,7 +27078,7 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m)
if (js_create_module_bytecode_function(ctx, m))
return -1;
}
- m->func_created = TRUE;
+ m->func_created = true;
/* do it on the dependencies */
@@ -28324,7 +27102,7 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
JSModuleDef *m1;
JSVarRef **var_refs, *var_ref;
JSObject *p;
- BOOL is_c_module;
+ bool is_c_module;
JSValue ret_val;
if (js_check_stack_overflow(ctx->rt, 0)) {
@@ -28332,8 +27110,8 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
return -1;
}
-#ifdef DUMP_MODULE_RESOLVE
- {
+#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE
+ if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) {
char buf1[ATOM_GET_STR_BUF_SIZE];
printf("js_inner_module_linking '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
}
@@ -28370,8 +27148,8 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
}
}
-#ifdef DUMP_MODULE_RESOLVE
- {
+#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE
+ if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) {
char buf1[ATOM_GET_STR_BUF_SIZE];
printf("instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
}
@@ -28393,8 +27171,8 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
}
}
-#ifdef DUMP_MODULE_RESOLVE
- {
+#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE
+ if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) {
printf("exported bindings:\n");
for(i = 0; i < m->export_entries_count; i++) {
JSExportEntry *me = &m->export_entries[i];
@@ -28413,10 +27191,12 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
for(i = 0; i < m->import_entries_count; i++) {
mi = &m->import_entries[i];
-#ifdef DUMP_MODULE_RESOLVE
- printf("import var_idx=%d name=", mi->var_idx);
- print_atom(ctx, mi->import_name);
- printf(": ");
+#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE
+ if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) {
+ printf("import var_idx=%d name=", mi->var_idx);
+ print_atom(ctx, mi->import_name);
+ printf(": ");
+ }
#endif
m1 = m->req_module_entries[mi->req_module_idx].module;
if (mi->import_name == JS_ATOM__star_) {
@@ -28426,9 +27206,9 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
if (JS_IsException(val))
goto fail;
set_value(ctx, &var_refs[mi->var_idx]->value, val);
-#ifdef DUMP_MODULE_RESOLVE
- printf("namespace\n");
-#endif
+
+ module_trace(ctx, "namespace\n");
+
} else {
JSResolveResultEnum ret;
JSExportEntry *res_me;
@@ -28449,16 +27229,16 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
val = JS_GetModuleNamespace(ctx, m2);
if (JS_IsException(val))
goto fail;
- var_ref = js_create_module_var(ctx, TRUE);
+ var_ref = js_create_module_var(ctx, true);
if (!var_ref) {
JS_FreeValue(ctx, val);
goto fail;
}
set_value(ctx, &var_ref->value, val);
var_refs[mi->var_idx] = var_ref;
-#ifdef DUMP_MODULE_RESOLVE
- printf("namespace from\n");
-#endif
+
+ module_trace(ctx, "namespace from\n");
+
} else {
var_ref = res_me->u.local.var_ref;
if (!var_ref) {
@@ -28467,9 +27247,8 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
}
var_ref->header.ref_count++;
var_refs[mi->var_idx] = var_ref;
-#ifdef DUMP_MODULE_RESOLVE
- printf("local export (var_ref=%p)\n", var_ref);
-#endif
+
+ module_trace(ctx, "local export (var_ref=%p)\n", (void *)var_ref);
}
}
}
@@ -28505,8 +27284,10 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
}
}
-#ifdef DUMP_MODULE_RESOLVE
- printf("js_inner_module_linking done\n");
+#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE
+ if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) {
+ printf("js_inner_module_linking done\n");
+ }
#endif
return index;
fail:
@@ -28519,8 +27300,8 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m)
{
JSModuleDef *stack_top, *m1;
-#ifdef DUMP_MODULE_RESOLVE
- {
+#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE
+ if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) {
char buf1[ATOM_GET_STR_BUF_SIZE];
printf("js_link_module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
}
@@ -28554,8 +27335,8 @@ JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)
JSFunctionBytecode *b;
JSObject *p;
/* XXX: currently we just use the filename of the englobing
- function from the debug info. May need to add a ScriptOrModule
- info in JSFunctionBytecode. */
+ function. It does not work for eval(). Need to add a
+ ScriptOrModule info in JSFunctionBytecode */
sf = ctx->rt->current_stack_frame;
if (!sf)
return JS_ATOM_NULL;
@@ -28564,23 +27345,13 @@ JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)
if (!sf)
return JS_ATOM_NULL;
}
- for(;;) {
- if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT)
- return JS_ATOM_NULL;
- p = JS_VALUE_GET_OBJ(sf->cur_func);
- if (!js_class_has_bytecode(p->class_id))
- return JS_ATOM_NULL;
- b = p->u.func.function_bytecode;
- if (!b->is_direct_or_indirect_eval) {
- if (!b->has_debug)
- return JS_ATOM_NULL;
- return JS_DupAtom(ctx, b->debug.filename);
- } else {
- sf = sf->prev_frame;
- if (!sf)
- return JS_ATOM_NULL;
- }
- }
+ if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT)
+ return JS_ATOM_NULL;
+ p = JS_VALUE_GET_OBJ(sf->cur_func);
+ if (!js_class_has_bytecode(p->class_id))
+ return JS_ATOM_NULL;
+ b = p->u.func.function_bytecode;
+ return JS_DupAtom(ctx, b->filename);
}
JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m)
@@ -28599,7 +27370,7 @@ JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m)
return JS_EXCEPTION;
m->meta_obj = obj;
}
- return JS_DupValue(ctx, obj);
+ return js_dup(obj);
}
static JSValue js_import_meta(JSContext *ctx)
@@ -28628,11 +27399,12 @@ static JSValue JS_NewModuleValue(JSContext *ctx, JSModuleDef *m)
return JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
}
-static JSValue js_load_module_rejected(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic, JSValue *func_data)
+static JSValue js_load_module_rejected(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic,
+ JSValue *func_data)
{
- JSValueConst *resolving_funcs = (JSValueConst *)func_data;
- JSValueConst error;
+ JSValue *resolving_funcs = func_data;
+ JSValue error;
JSValue ret;
/* XXX: check if the test is necessary */
@@ -28640,16 +27412,16 @@ static JSValue js_load_module_rejected(JSContext *ctx, JSValueConst this_val,
error = argv[0];
else
error = JS_UNDEFINED;
- ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
- 1, &error);
+ ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, &error);
JS_FreeValue(ctx, ret);
return JS_UNDEFINED;
}
-static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic, JSValue *func_data)
+static JSValue js_load_module_fulfilled(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic,
+ JSValue *func_data)
{
- JSValueConst *resolving_funcs = (JSValueConst *)func_data;
+ JSValue *resolving_funcs = func_data;
JSModuleDef *m = JS_VALUE_GET_PTR(func_data[2]);
JSValue ret, ns;
@@ -28657,11 +27429,10 @@ static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val,
ns = JS_GetModuleNamespace(ctx, m);
if (JS_IsException(ns)) {
JSValue err = JS_GetException(ctx);
- js_load_module_rejected(ctx, JS_UNDEFINED, 1, (JSValueConst *)&err, 0, func_data);
+ js_load_module_rejected(ctx, JS_UNDEFINED, 1, &err, 0, func_data);
return JS_UNDEFINED;
}
- ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
- 1, (JSValueConst *)&ns);
+ ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED, 1, &ns);
JS_FreeValue(ctx, ret);
JS_FreeValue(ctx, ns);
return JS_UNDEFINED;
@@ -28669,12 +27440,12 @@ static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val,
static void JS_LoadModuleInternal(JSContext *ctx, const char *basename,
const char *filename,
- JSValueConst *resolving_funcs)
+ JSValue *resolving_funcs)
{
JSValue evaluate_promise;
JSModuleDef *m;
JSValue ret, err, func_obj, evaluate_resolving_funcs[2];
- JSValueConst func_data[3];
+ JSValue func_data[3];
m = js_host_resolve_imported_module(ctx, basename, filename);
if (!m)
@@ -28691,8 +27462,7 @@ static void JS_LoadModuleInternal(JSContext *ctx, const char *basename,
if (JS_IsException(evaluate_promise)) {
fail:
err = JS_GetException(ctx);
- ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
- 1, (JSValueConst *)&err);
+ ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, &err);
JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
JS_FreeValue(ctx, err);
return;
@@ -28705,7 +27475,7 @@ static void JS_LoadModuleInternal(JSContext *ctx, const char *basename,
evaluate_resolving_funcs[0] = JS_NewCFunctionData(ctx, js_load_module_fulfilled, 0, 0, 3, func_data);
evaluate_resolving_funcs[1] = JS_NewCFunctionData(ctx, js_load_module_rejected, 0, 0, 3, func_data);
JS_FreeValue(ctx, func_obj);
- ret = js_promise_then(ctx, evaluate_promise, 2, (JSValueConst *)evaluate_resolving_funcs);
+ ret = js_promise_then(ctx, evaluate_promise, 2, evaluate_resolving_funcs);
JS_FreeValue(ctx, ret);
JS_FreeValue(ctx, evaluate_resolving_funcs[0]);
JS_FreeValue(ctx, evaluate_resolving_funcs[1]);
@@ -28722,19 +27492,18 @@ JSValue JS_LoadModule(JSContext *ctx, const char *basename,
promise = JS_NewPromiseCapability(ctx, resolving_funcs);
if (JS_IsException(promise))
return JS_EXCEPTION;
- JS_LoadModuleInternal(ctx, basename, filename,
- (JSValueConst *)resolving_funcs);
+ JS_LoadModuleInternal(ctx, basename, filename, resolving_funcs);
JS_FreeValue(ctx, resolving_funcs[0]);
JS_FreeValue(ctx, resolving_funcs[1]);
return promise;
}
static JSValue js_dynamic_import_job(JSContext *ctx,
- int argc, JSValueConst *argv)
+ int argc, JSValue *argv)
{
- JSValueConst *resolving_funcs = argv;
- JSValueConst basename_val = argv[2];
- JSValueConst specifier = argv[3];
+ JSValue *resolving_funcs = argv;
+ JSValue basename_val = argv[2];
+ JSValue specifier = argv[3];
const char *basename = NULL, *filename;
JSValue ret, err;
@@ -28758,18 +27527,18 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
exception:
err = JS_GetException(ctx);
ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
- 1, (JSValueConst *)&err);
+ 1, &err);
JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
JS_FreeValue(ctx, err);
JS_FreeCString(ctx, basename);
return JS_UNDEFINED;
}
-static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
+static JSValue js_dynamic_import(JSContext *ctx, JSValue specifier)
{
JSAtom basename;
JSValue promise, resolving_funcs[2], basename_val;
- JSValueConst args[4];
+ JSValue args[4];
basename = JS_GetScriptOrModuleName(ctx, 0);
if (basename == JS_ATOM_NULL)
@@ -28808,8 +27577,7 @@ static void js_set_module_evaluated(JSContext *ctx, JSModuleDef *m)
JSValue value, ret_val;
assert(m->cycle_root == m);
value = JS_UNDEFINED;
- ret_val = JS_Call(ctx, m->resolving_funcs[0], JS_UNDEFINED,
- 1, (JSValueConst *)&value);
+ ret_val = JS_Call(ctx, m->resolving_funcs[0], JS_UNDEFINED, 1, &value);
JS_FreeValue(ctx, ret_val);
}
}
@@ -28821,14 +27589,14 @@ typedef struct {
} ExecModuleList;
/* XXX: slow. Could use a linked list instead of ExecModuleList */
-static BOOL find_in_exec_module_list(ExecModuleList *exec_list, JSModuleDef *m)
+static bool find_in_exec_module_list(ExecModuleList *exec_list, JSModuleDef *m)
{
int i;
for(i = 0; i < exec_list->count; i++) {
if (exec_list->tab[i] == m)
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
static int gather_available_ancestors(JSContext *ctx, JSModuleDef *module,
@@ -28876,11 +27644,12 @@ static int js_execute_async_module(JSContext *ctx, JSModuleDef *m);
static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m,
JSValue *pvalue);
-static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic, JSValue *func_data)
+static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic,
+ JSValue *func_data)
{
JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]);
- JSValueConst error = argv[0];
+ JSValue error = argv[0];
int i;
if (js_check_stack_overflow(ctx->rt, 0))
@@ -28895,7 +27664,7 @@ static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst t
assert(!module->eval_has_exception);
assert(module->async_evaluation);
- module->eval_has_exception = TRUE;
+ module->eval_has_exception = true;
module->eval_exception = JS_DupValue(ctx, error);
module->status = JS_MODULE_STATUS_EVALUATED;
@@ -28917,8 +27686,9 @@ static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst t
return JS_UNDEFINED;
}
-static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic, JSValue *func_data)
+static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic,
+ JSValue *func_data)
{
JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]);
ExecModuleList exec_list_s, *exec_list = &exec_list_s;
@@ -28931,7 +27701,7 @@ static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst
assert(module->status == JS_MODULE_STATUS_EVALUATING_ASYNC);
assert(!module->eval_has_exception);
assert(module->async_evaluation);
- module->async_evaluation = FALSE;
+ module->async_evaluation = false;
js_set_module_evaluated(ctx, module);
exec_list->tab = NULL;
@@ -28958,8 +27728,7 @@ static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst
if (js_execute_sync_module(ctx, m, &error) < 0) {
JSValue m_obj = JS_NewModuleValue(ctx, m);
js_async_module_execution_rejected(ctx, JS_UNDEFINED,
- 1, (JSValueConst *)&error, 0,
- &m_obj);
+ 1, &error, 0, &m_obj);
JS_FreeValue(ctx, m_obj);
JS_FreeValue(ctx, error);
} else {
@@ -28979,9 +27748,9 @@ static int js_execute_async_module(JSContext *ctx, JSModuleDef *m)
if (JS_IsException(promise))
return -1;
m_obj = JS_NewModuleValue(ctx, m);
- resolve_funcs[0] = JS_NewCFunctionData(ctx, js_async_module_execution_fulfilled, 0, 0, 1, (JSValueConst *)&m_obj);
- resolve_funcs[1] = JS_NewCFunctionData(ctx, js_async_module_execution_rejected, 0, 0, 1, (JSValueConst *)&m_obj);
- ret_val = js_promise_then(ctx, promise, 2, (JSValueConst *)resolve_funcs);
+ resolve_funcs[0] = JS_NewCFunctionData(ctx, js_async_module_execution_fulfilled, 0, 0, 1, &m_obj);
+ resolve_funcs[1] = JS_NewCFunctionData(ctx, js_async_module_execution_rejected, 0, 0, 1, &m_obj);
+ ret_val = js_promise_then(ctx, promise, 2, resolve_funcs);
JS_FreeValue(ctx, ret_val);
JS_FreeValue(ctx, m_obj);
JS_FreeValue(ctx, resolve_funcs[0]);
@@ -29039,8 +27808,8 @@ static int js_inner_module_evaluation(JSContext *ctx, JSModuleDef *m,
return -1;
}
-#ifdef DUMP_MODULE_RESOLVE
- {
+#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE
+ if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) {
char buf1[ATOM_GET_STR_BUF_SIZE];
printf("js_inner_module_evaluation '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
}
@@ -29104,12 +27873,12 @@ static int js_inner_module_evaluation(JSContext *ctx, JSModuleDef *m,
if (m->pending_async_dependencies > 0) {
assert(!m->async_evaluation);
- m->async_evaluation = TRUE;
+ m->async_evaluation = true;
m->async_evaluation_timestamp =
ctx->rt->module_async_evaluation_next_timestamp++;
} else if (m->has_tla) {
assert(!m->async_evaluation);
- m->async_evaluation = TRUE;
+ m->async_evaluation = true;
m->async_evaluation_timestamp =
ctx->rt->module_async_evaluation_next_timestamp++;
js_execute_async_module(ctx, m);
@@ -29166,7 +27935,7 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
m1 = stack_top;
assert(m1->status == JS_MODULE_STATUS_EVALUATING);
m1->status = JS_MODULE_STATUS_EVALUATED;
- m1->eval_has_exception = TRUE;
+ m1->eval_has_exception = true;
m1->eval_exception = JS_DupValue(ctx, result);
m1->cycle_root = m; /* spec bug: should be present */
stack_top = m1->stack_prev;
@@ -29175,7 +27944,7 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
assert(m->status == JS_MODULE_STATUS_EVALUATED);
assert(m->eval_has_exception);
ret_val = JS_Call(ctx, m->resolving_funcs[1], JS_UNDEFINED,
- 1, (JSValueConst *)&m->eval_exception);
+ 1, &m->eval_exception);
JS_FreeValue(ctx, ret_val);
} else {
assert(m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
@@ -29186,7 +27955,7 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
assert(m->status == JS_MODULE_STATUS_EVALUATED);
value = JS_UNDEFINED;
ret_val = JS_Call(ctx, m->resolving_funcs[0], JS_UNDEFINED,
- 1, (JSValueConst *)&value);
+ 1, &value);
JS_FreeValue(ctx, ret_val);
}
assert(stack_top == NULL);
@@ -29231,13 +28000,15 @@ static __exception int js_parse_export(JSParseState *s)
tok = s->token.val;
if (tok == TOK_CLASS) {
- return js_parse_class(s, FALSE, JS_PARSE_EXPORT_NAMED);
+ return js_parse_class(s, false, JS_PARSE_EXPORT_NAMED);
} else if (tok == TOK_FUNCTION ||
(token_is_pseudo_keyword(s, JS_ATOM_async) &&
- peek_token(s, TRUE) == TOK_FUNCTION)) {
+ peek_token(s, true) == TOK_FUNCTION)) {
return js_parse_function_decl2(s, JS_PARSE_FUNC_STATEMENT,
JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num,
+ s->token.ptr,
+ s->token.line_num,
+ s->token.col_num,
JS_PARSE_EXPORT_NAMED, NULL);
}
@@ -29341,13 +28112,15 @@ static __exception int js_parse_export(JSParseState *s)
break;
case TOK_DEFAULT:
if (s->token.val == TOK_CLASS) {
- return js_parse_class(s, FALSE, JS_PARSE_EXPORT_DEFAULT);
+ return js_parse_class(s, false, JS_PARSE_EXPORT_DEFAULT);
} else if (s->token.val == TOK_FUNCTION ||
(token_is_pseudo_keyword(s, JS_ATOM_async) &&
- peek_token(s, TRUE) == TOK_FUNCTION)) {
+ peek_token(s, true) == TOK_FUNCTION)) {
return js_parse_function_decl2(s, JS_PARSE_FUNC_STATEMENT,
JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num,
+ s->token.ptr,
+ s->token.line_num,
+ s->token.col_num,
JS_PARSE_EXPORT_DEFAULT, NULL);
} else {
if (js_parse_assign_expr(s))
@@ -29372,7 +28145,7 @@ static __exception int js_parse_export(JSParseState *s)
case TOK_VAR:
case TOK_LET:
case TOK_CONST:
- return js_parse_var(s, TRUE, tok, TRUE);
+ return js_parse_var(s, PF_IN_ACCEPTED, tok, /*export_flag*/true);
default:
return js_parse_error(s, "invalid export syntax");
}
@@ -29380,9 +28153,9 @@ static __exception int js_parse_export(JSParseState *s)
}
static int add_closure_var(JSContext *ctx, JSFunctionDef *s,
- BOOL is_local, BOOL is_arg,
+ bool is_local, bool is_arg,
int var_idx, JSAtom var_name,
- BOOL is_const, BOOL is_lexical,
+ bool is_const, bool is_lexical,
JSVarKindEnum var_kind);
static int add_import(JSParseState *s, JSModuleDef *m,
@@ -29391,7 +28164,7 @@ static int add_import(JSParseState *s, JSModuleDef *m,
JSContext *ctx = s->ctx;
int i, var_idx;
JSImportEntry *mi;
- BOOL is_local;
+ bool is_local;
if (local_name == JS_ATOM_arguments || local_name == JS_ATOM_eval)
return js_parse_error(s, "invalid import binding");
@@ -29404,9 +28177,9 @@ static int add_import(JSParseState *s, JSModuleDef *m,
}
is_local = (import_name == JS_ATOM__star_);
- var_idx = add_closure_var(ctx, s->cur_func, is_local, FALSE,
+ var_idx = add_closure_var(ctx, s->cur_func, is_local, false,
m->import_entries_count,
- local_name, TRUE, TRUE, FALSE);
+ local_name, true, true, JS_VAR_NORMAL);
if (var_idx < 0)
return -1;
if (js_resize_array(ctx, (void **)&m->import_entries,
@@ -29542,16 +28315,18 @@ static __exception int js_parse_source_element(JSParseState *s)
if (s->token.val == TOK_FUNCTION ||
(token_is_pseudo_keyword(s, JS_ATOM_async) &&
- peek_token(s, TRUE) == TOK_FUNCTION)) {
+ peek_token(s, true) == TOK_FUNCTION)) {
if (js_parse_function_decl(s, JS_PARSE_FUNC_STATEMENT,
JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num))
+ s->token.ptr,
+ s->token.line_num,
+ s->token.col_num))
return -1;
} else if (s->token.val == TOK_EXPORT && fd->module) {
if (js_parse_export(s))
return -1;
} else if (s->token.val == TOK_IMPORT && fd->module &&
- ((tok = peek_token(s, FALSE)) != '(' && tok != '.')) {
+ ((tok = peek_token(s, false)) != '(' && tok != '.')) {
/* the peek_token is needed to avoid confusion with ImportCall
(dynamic import) or import.meta */
if (js_parse_import(s))
@@ -29563,11 +28338,14 @@ static __exception int js_parse_source_element(JSParseState *s)
return 0;
}
+/* `filename` may be pure ASCII or UTF-8 encoded */
static JSFunctionDef *js_new_function_def(JSContext *ctx,
JSFunctionDef *parent,
- BOOL is_eval,
- BOOL is_func_expr,
- const char *filename, int line_num)
+ bool is_eval,
+ bool is_func_expr,
+ const char *filename,
+ int line_num,
+ int col_num)
{
JSFunctionDef *fd;
@@ -29583,7 +28361,7 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx,
fd->parent_cpool_idx = -1;
if (parent) {
list_add_tail(&fd->link, &parent->child_list);
- fd->js_mode = parent->js_mode;
+ fd->is_strict_mode = parent->is_strict_mode;
fd->parent_scope_level = parent->scope_level;
}
@@ -29615,18 +28393,18 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx,
fd->filename = JS_NewAtom(ctx, filename);
fd->line_num = line_num;
+ fd->col_num = col_num;
js_dbuf_init(ctx, &fd->pc2line);
//fd->pc2line_last_line_num = line_num;
//fd->pc2line_last_pc = 0;
- fd->last_opcode_line_num = line_num;
return fd;
}
static void free_bytecode_atoms(JSRuntime *rt,
const uint8_t *bc_buf, int bc_len,
- BOOL use_short_opcodes)
+ bool use_short_opcodes)
{
int pos, len, op;
JSAtom atom;
@@ -29674,7 +28452,7 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd)
dbuf_free(&fd->byte_code);
js_free(ctx, fd->jump_slots);
js_free(ctx, fd->label_slots);
- js_free(ctx, fd->line_number_slots);
+ js_free(ctx, fd->source_loc_slots);
for(i = 0; i < fd->cpool_count; i++) {
JS_FreeValue(ctx, fd->cpool[i]);
@@ -29687,6 +28465,7 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd)
JS_FreeAtom(ctx, fd->vars[i].var_name);
}
js_free(ctx, fd->vars);
+ js_free(ctx, fd->vars_htab); // XXX can probably be freed earlier?
for(i = 0; i < fd->arg_count; i++) {
JS_FreeAtom(ctx, fd->args[i].var_name);
}
@@ -29718,9 +28497,9 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd)
js_free(ctx, fd);
}
-#ifdef DUMP_BYTECODE
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_*
static const char *skip_lines(const char *p, int n) {
- while (n-- > 0 && *p) {
+ while (p && n-- > 0 && *p) {
while (*p && *p++ != '\n')
continue;
}
@@ -29730,7 +28509,7 @@ static const char *skip_lines(const char *p, int n) {
static void print_lines(const char *source, int line, int line1) {
const char *s = source;
const char *p = skip_lines(s, line);
- if (*p) {
+ if (p && *p) {
while (line++ < line1) {
p = skip_lines(s = p, 1);
printf(";; %.*s", (int)(p - s), s);
@@ -29750,12 +28529,16 @@ static void dump_byte_code(JSContext *ctx, int pass,
const JSClosureVar *closure_var, int closure_var_count,
const JSValue *cpool, uint32_t cpool_count,
const char *source, int line_num,
- const LabelSlot *label_slots, JSFunctionBytecode *b)
+ const LabelSlot *label_slots, JSFunctionBytecode *b,
+ int start_pos)
{
const JSOpCode *oi;
int pos, pos_next, op, size, idx, addr, line, line1, in_source;
uint8_t *bits = js_mallocz(ctx, len * sizeof(*bits));
- BOOL use_short_opcodes = (b != NULL);
+ bool use_short_opcodes = (b != NULL);
+
+ if (start_pos != 0 || bits == NULL)
+ goto no_labels;
/* scan for jump targets */
for (pos = 0; pos < len; pos = pos_next) {
@@ -29767,7 +28550,6 @@ static void dump_byte_code(JSContext *ctx, int pass,
pos_next = pos + oi->size;
if (op < OP_COUNT) {
switch (oi->fmt) {
-#if SHORT_OPCODES
case OP_FMT_label8:
pos++;
addr = (int8_t)tab[pos];
@@ -29776,7 +28558,6 @@ static void dump_byte_code(JSContext *ctx, int pass,
pos++;
addr = (int16_t)get_u16(tab + pos);
goto has_addr;
-#endif
case OP_FMT_atom_label_u8:
case OP_FMT_atom_label_u16:
pos += 4;
@@ -29799,6 +28580,7 @@ static void dump_byte_code(JSContext *ctx, int pass,
}
}
}
+ no_labels:
in_source = 0;
if (source) {
/* Always print first line: needed if single line */
@@ -29811,8 +28593,9 @@ static void dump_byte_code(JSContext *ctx, int pass,
op = tab[pos];
if (source) {
if (b) {
- line1 = find_line_num(ctx, b, pos) - line_num + 1;
- } else if (op == OP_line_num) {
+ int col1;
+ line1 = find_line_num(ctx, b, pos, &col1) - line_num + 1;
+ } else if (op == OP_source_loc) {
line1 = get_u32(tab + pos + 1) - line_num + 1;
}
if (line1 > line) {
@@ -29841,8 +28624,8 @@ static void dump_byte_code(JSContext *ctx, int pass,
printf("truncated opcode (0x%02x)\n", op);
break;
}
-#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 16)
- {
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_HEX
+ if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_HEX)) {
int i, x, x0;
x = x0 = printf("%5d ", pos);
for (i = 0; i < size; i++) {
@@ -29854,12 +28637,12 @@ static void dump_byte_code(JSContext *ctx, int pass,
printf("%*s", x0 + 20 - x, "");
}
#endif
- if (bits[pos]) {
+ if (bits && bits[pos]) {
printf("%5d: ", pos);
} else {
printf(" ");
}
- printf("%s", oi->name);
+ printf("%-15s", oi->name); /* align opcode arguments */
pos++;
switch(oi->fmt) {
case OP_FMT_none_int:
@@ -29890,47 +28673,42 @@ static void dump_byte_code(JSContext *ctx, int pass,
case OP_FMT_u32:
printf(" %u", get_u32(tab + pos));
break;
-#if SHORT_OPCODES
+ case OP_FMT_u32x2:
+ printf(" %u:%u", get_u32(tab + pos), get_u32(tab + pos + 4));
+ break;
case OP_FMT_label8:
addr = get_i8(tab + pos);
goto has_addr1;
case OP_FMT_label16:
addr = get_i16(tab + pos);
goto has_addr1;
-#endif
case OP_FMT_label:
- addr = get_u32(tab + pos);
- goto has_addr1;
- has_addr1:
- if (pass == 1)
- printf(" %u:%u", addr, label_slots[addr].pos);
- if (pass == 2)
- printf(" %u:%u", addr, label_slots[addr].pos2);
- if (pass == 3)
- printf(" %u", addr + pos);
- break;
case OP_FMT_label_u16:
addr = get_u32(tab + pos);
+ has_addr1:
if (pass == 1)
- printf(" %u:%u", addr, label_slots[addr].pos);
+ printf(" %d:%u", addr, label_slots[addr].pos);
if (pass == 2)
- printf(" %u:%u", addr, label_slots[addr].pos2);
- if (pass == 3)
- printf(" %u", addr + pos);
- printf(",%u", get_u16(tab + pos + 4));
+ printf(" %d:%u", addr, label_slots[addr].pos2);
+ if (pass == 3) {
+ if (start_pos)
+ printf(" %04x", addr + pos + start_pos);
+ else
+ printf(" %d", addr + pos);
+ }
+ if (oi->fmt == OP_FMT_label_u16)
+ printf(",%u", get_u16(tab + pos + 4));
break;
-#if SHORT_OPCODES
case OP_FMT_const8:
idx = get_u8(tab + pos);
goto has_pool_idx;
-#endif
case OP_FMT_const:
idx = get_u32(tab + pos);
goto has_pool_idx;
has_pool_idx:
- printf(" %u: ", idx);
+ printf(" %-4u ; ", idx);
if (idx < cpool_count) {
- JS_DumpValue(ctx, cpool[idx]);
+ JS_DumpValue(ctx->rt, cpool[idx]);
}
break;
case OP_FMT_atom:
@@ -29964,15 +28742,24 @@ static void dump_byte_code(JSContext *ctx, int pass,
printf(",%u", get_u16(tab + pos + 8));
break;
case OP_FMT_none_loc:
- idx = (op - OP_get_loc0) % 4;
- goto has_loc;
+ if (op == OP_get_loc0_loc1) {
+ printf(" 0, 1 ; ");
+ if (var_count > 0)
+ print_atom(ctx, vars[0].var_name);
+ if (var_count > 1)
+ print_atom(ctx, vars[1].var_name);
+ } else {
+ idx = (op - OP_get_loc0) % 4;
+ goto has_loc;
+ }
+ break;
case OP_FMT_loc8:
idx = get_u8(tab + pos);
goto has_loc;
case OP_FMT_loc:
idx = get_u16(tab + pos);
has_loc:
- printf(" %d: ", idx);
+ printf(" %-4d ; ", idx);
if (idx < var_count) {
print_atom(ctx, vars[idx].var_name);
}
@@ -29983,7 +28770,7 @@ static void dump_byte_code(JSContext *ctx, int pass,
case OP_FMT_arg:
idx = get_u16(tab + pos);
has_arg:
- printf(" %d: ", idx);
+ printf(" %-4d ; ", idx);
if (idx < arg_count) {
print_atom(ctx, args[idx].var_name);
}
@@ -29994,7 +28781,7 @@ static void dump_byte_code(JSContext *ctx, int pass,
case OP_FMT_var_ref:
idx = get_u16(tab + pos);
has_var_ref:
- printf(" %d: ", idx);
+ printf(" %-4d ; ", idx);
if (idx < closure_var_count) {
print_atom(ctx, closure_var[idx].var_name);
}
@@ -30013,8 +28800,35 @@ static void dump_byte_code(JSContext *ctx, int pass,
js_free(ctx, bits);
}
-static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int len,
- int line_num)
+// caveat emptor: intended to be called during execution of bytecode
+// and only works for pass3 bytecode
+static __maybe_unused void dump_single_byte_code(JSContext *ctx,
+ const uint8_t *pc,
+ JSFunctionBytecode *b,
+ int start_pos)
+{
+ JSVarDef *args, *vars;
+
+ args = vars = b->vardefs;
+ if (vars)
+ vars = &vars[b->arg_count];
+
+ dump_byte_code(ctx, /*pass*/3, pc, short_opcode_info(*pc).size,
+ args, b->arg_count, vars, b->var_count,
+ b->closure_var, b->closure_var_count,
+ b->cpool, b->cpool_count,
+ NULL, b->line_num,
+ NULL, b, start_pos);
+}
+
+static __maybe_unused void print_func_name(JSFunctionBytecode *b)
+{
+ print_lines(b->source, 0, 1);
+}
+
+static __maybe_unused void dump_pc2line(JSContext *ctx,
+ const uint8_t *buf, int len,
+ int line_num, int col_num)
{
const uint8_t *p_end, *p_next, *p;
int pc, v;
@@ -30023,7 +28837,7 @@ static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int
if (len <= 0)
return;
- printf("%5s %5s\n", "PC", "LINE");
+ printf("%5s %5s %5s\n", "PC", "LINE", "COLUMN");
p = buf;
p_end = buf + len;
@@ -30031,21 +28845,18 @@ static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int
while (p < p_end) {
op = *p++;
if (op == 0) {
- v = unicode_from_utf8(p, p_end - p, &p_next);
+ v = utf8_decode_len(p, p_end - p, &p_next);
if (v < 0)
goto fail;
pc += v;
p = p_next;
- v = unicode_from_utf8(p, p_end - p, &p_next);
- if (v < 0) {
- fail:
- printf("invalid pc2line encode pos=%d\n", (int)(p - buf));
- return;
- }
- if (!(v & 1)) {
- v = v >> 1;
- } else {
+ v = utf8_decode_len(p, p_end - p, &p_next);
+ if (v < 0)
+ goto fail;
+ if (v & 1) {
v = -(v >> 1) - 1;
+ } else {
+ v = v >> 1;
}
line_num += v;
p = p_next;
@@ -30054,8 +28865,21 @@ static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int
pc += (op / PC2LINE_RANGE);
line_num += (op % PC2LINE_RANGE) + PC2LINE_BASE;
}
- printf("%5d %5d\n", pc, line_num);
+ v = utf8_decode_len(p, p_end - p, &p_next);
+ if (v < 0)
+ goto fail;
+ if (v & 1) {
+ v = -(v >> 1) - 1;
+ } else {
+ v = v >> 1;
+ }
+ col_num += v;
+ p = p_next;
+ printf("%5d %5d %5d\n", pc, line_num, col_num);
}
+ return;
+fail:
+ printf("invalid pc2line encode pos=%d\n", (int)(p - buf));
}
static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionBytecode *b)
@@ -30064,23 +28888,14 @@ static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionB
char atom_buf[ATOM_GET_STR_BUF_SIZE];
const char *str;
- if (b->has_debug && b->debug.filename != JS_ATOM_NULL) {
- str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->debug.filename);
- printf("%s:%d: ", str, b->debug.line_num);
+ if (b->filename != JS_ATOM_NULL) {
+ str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->filename);
+ printf("%s:%d:%d: ", str, b->line_num, b->col_num);
}
str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->func_name);
printf("function: %s%s\n", &"*"[b->func_kind != JS_FUNC_GENERATOR], str);
- if (b->js_mode) {
- printf(" mode:");
- if (b->js_mode & JS_MODE_STRICT)
- printf(" strict");
-#ifdef CONFIG_BIGNUM
- if (b->js_mode & JS_MODE_MATH)
- printf(" math");
-#endif
- printf("\n");
- }
+ printf(" mode: %s\n", b->is_strict_mode ? "strict" : "sloppy");
if (b->arg_count && b->vardefs) {
printf(" args:");
for(i = 0; i < b->arg_count; i++) {
@@ -30124,27 +28939,28 @@ static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionB
b->vardefs ? b->vardefs + b->arg_count : NULL, b->var_count,
b->closure_var, b->closure_var_count,
b->cpool, b->cpool_count,
- b->has_debug ? b->debug.source : NULL,
- b->has_debug ? b->debug.line_num : -1, NULL, b);
-#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 32)
- if (b->has_debug)
- dump_pc2line(ctx, b->debug.pc2line_buf, b->debug.pc2line_len, b->debug.line_num);
+ b->source, b->line_num, NULL, b, 0);
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_PC2LINE
+ if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_PC2LINE))
+ dump_pc2line(ctx, b->pc2line_buf, b->pc2line_len, b->line_num, b->col_num);
#endif
printf("\n");
}
#endif
static int add_closure_var(JSContext *ctx, JSFunctionDef *s,
- BOOL is_local, BOOL is_arg,
+ bool is_local, bool is_arg,
int var_idx, JSAtom var_name,
- BOOL is_const, BOOL is_lexical,
+ bool is_const, bool is_lexical,
JSVarKindEnum var_kind)
{
JSClosureVar *cv;
/* the closure variable indexes are currently stored on 16 bits */
if (s->closure_var_count >= JS_MAX_LOCAL_VARS) {
- JS_ThrowInternalError(ctx, "too many closure variables");
+ // XXX: add_closure_var() should take JSParseState *s and use js_parse_error
+ JS_ThrowSyntaxError(ctx, "too many closure variables used (only %d allowed)",
+ JS_MAX_LOCAL_VARS - 1);
return -1;
}
@@ -30176,12 +28992,12 @@ static int find_closure_var(JSContext *ctx, JSFunctionDef *s,
}
/* 'fd' must be a parent of 's'. Create in 's' a closure referencing a
- local variable (is_local = TRUE) or a closure (is_local = FALSE) in
+ local variable (is_local = true) or a closure (is_local = false) in
'fd' */
static int get_closure_var2(JSContext *ctx, JSFunctionDef *s,
- JSFunctionDef *fd, BOOL is_local,
- BOOL is_arg, int var_idx, JSAtom var_name,
- BOOL is_const, BOOL is_lexical,
+ JSFunctionDef *fd, bool is_local,
+ bool is_arg, int var_idx, JSAtom var_name,
+ bool is_const, bool is_lexical,
JSVarKindEnum var_kind)
{
int i;
@@ -30192,7 +29008,7 @@ static int get_closure_var2(JSContext *ctx, JSFunctionDef *s,
is_const, is_lexical, var_kind);
if (var_idx < 0)
return -1;
- is_local = FALSE;
+ is_local = false;
}
for(i = 0; i < s->closure_var_count; i++) {
JSClosureVar *cv = &s->closure_var[i];
@@ -30205,12 +29021,12 @@ static int get_closure_var2(JSContext *ctx, JSFunctionDef *s,
}
static int get_closure_var(JSContext *ctx, JSFunctionDef *s,
- JSFunctionDef *fd, BOOL is_arg,
+ JSFunctionDef *fd, bool is_arg,
int var_idx, JSAtom var_name,
- BOOL is_const, BOOL is_lexical,
+ bool is_const, bool is_lexical,
JSVarKindEnum var_kind)
{
- return get_closure_var2(ctx, s, fd, TRUE, is_arg,
+ return get_closure_var2(ctx, s, fd, true, is_arg,
var_idx, var_name, is_const, is_lexical,
var_kind);
}
@@ -30223,7 +29039,7 @@ static int get_with_scope_opcode(int op)
return OP_with_get_var + (op - OP_scope_get_var);
}
-static BOOL can_opt_put_ref_value(const uint8_t *bc_buf, int pos)
+static bool can_opt_put_ref_value(const uint8_t *bc_buf, int pos)
{
int opcode = bc_buf[pos];
return (bc_buf[pos + 1] == OP_put_ref_value &&
@@ -30233,7 +29049,7 @@ static BOOL can_opt_put_ref_value(const uint8_t *bc_buf, int pos)
opcode == OP_rot3l));
}
-static BOOL can_opt_put_global_ref_value(const uint8_t *bc_buf, int pos)
+static bool can_opt_put_global_ref_value(const uint8_t *bc_buf, int pos)
{
int opcode = bc_buf[pos];
return (bc_buf[pos + 1] == OP_put_ref_value &&
@@ -30293,12 +29109,11 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s,
JSAtom var_name)
{
int label_pos, end_pos, pos, op;
- BOOL is_strict;
- is_strict = ((s->js_mode & JS_MODE_STRICT) != 0);
+ bool is_strict_mode = s->is_strict_mode;
/* replace the reference get/put with normal variable
accesses */
- if (is_strict) {
+ if (is_strict_mode) {
/* need to check if the variable exists before evaluating the right
expression */
/* XXX: need an extra OP_true if destructuring an array */
@@ -30320,7 +29135,7 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s,
assert(bc_buf[pos] == OP_label);
end_pos = label_pos + 2;
op = bc_buf[label_pos];
- if (is_strict) {
+ if (is_strict_mode) {
if (op != OP_nop) {
switch(op) {
case OP_insert3:
@@ -30341,7 +29156,7 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s,
if (op == OP_insert3)
bc_buf[pos++] = OP_dup;
}
- if (is_strict) {
+ if (is_strict_mode) {
bc_buf[pos] = OP_put_var_strict;
/* XXX: need 1 extra OP_drop if destructuring an array */
} else {
@@ -30412,7 +29227,7 @@ static int resolve_pseudo_var(JSContext *ctx, JSFunctionDef *s,
the case, handle it and jump to 'label_done' */
static void var_object_test(JSContext *ctx, JSFunctionDef *s,
JSAtom var_name, int op, DynBuf *bc,
- int *plabel_done, BOOL is_with)
+ int *plabel_done, bool is_with)
{
dbuf_putc(bc, get_with_scope_opcode(op));
dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
@@ -30433,7 +29248,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
int label_done;
JSFunctionDef *fd;
JSVarDef *vd;
- BOOL is_pseudo_var, is_arg_scope;
+ bool is_pseudo_var, is_arg_scope;
label_done = -1;
@@ -30545,7 +29360,6 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
case OP_scope_get_ref:
dbuf_putc(bc, OP_undefined);
/* fall thru */
- case OP_scope_get_var_checkthis:
case OP_scope_get_var_undef:
case OP_scope_get_var:
case OP_scope_put_var:
@@ -30571,12 +29385,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
}
} else {
if (s->vars[var_idx].is_lexical) {
- if (op == OP_scope_get_var_checkthis) {
- /* only used for 'this' return in derived class constructors */
- dbuf_putc(bc, OP_get_loc_checkthis);
- } else {
- dbuf_putc(bc, OP_get_loc_check);
- }
+ dbuf_putc(bc, OP_get_loc_check);
} else {
dbuf_putc(bc, OP_get_loc);
}
@@ -30622,7 +29431,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
break;
} else if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {
vd->is_captured = 1;
- idx = get_closure_var(ctx, s, fd, FALSE, idx, vd->var_name, FALSE, FALSE, JS_VAR_NORMAL);
+ idx = get_closure_var(ctx, s, fd, false, idx, vd->var_name, false, false, JS_VAR_NORMAL);
if (idx >= 0) {
dbuf_putc(bc, OP_get_var_ref);
dbuf_put_u16(bc, idx);
@@ -30659,9 +29468,9 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
if (!is_arg_scope && fd->var_object_idx >= 0 && !is_pseudo_var) {
vd = &fd->vars[fd->var_object_idx];
vd->is_captured = 1;
- idx = get_closure_var(ctx, s, fd, FALSE,
+ idx = get_closure_var(ctx, s, fd, false,
fd->var_object_idx, vd->var_name,
- FALSE, FALSE, JS_VAR_NORMAL);
+ false, false, JS_VAR_NORMAL);
dbuf_putc(bc, OP_get_var_ref);
dbuf_put_u16(bc, idx);
var_object_test(ctx, s, var_name, op, bc, &label_done, 0);
@@ -30671,9 +29480,9 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
if (fd->arg_var_object_idx >= 0 && !is_pseudo_var) {
vd = &fd->vars[fd->arg_var_object_idx];
vd->is_captured = 1;
- idx = get_closure_var(ctx, s, fd, FALSE,
+ idx = get_closure_var(ctx, s, fd, false,
fd->arg_var_object_idx, vd->var_name,
- FALSE, FALSE, JS_VAR_NORMAL);
+ false, false, JS_VAR_NORMAL);
dbuf_putc(bc, OP_get_var_ref);
dbuf_put_u16(bc, idx);
var_object_test(ctx, s, var_name, op, bc, &label_done, 0);
@@ -30694,7 +29503,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
if (var_name == cv->var_name) {
if (fd != s) {
idx = get_closure_var2(ctx, s, fd,
- FALSE,
+ false,
cv->is_arg, idx1,
cv->var_name, cv->is_const,
cv->is_lexical, cv->var_kind);
@@ -30708,9 +29517,9 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
int is_with = (cv->var_name == JS_ATOM__with_);
if (fd != s) {
idx = get_closure_var2(ctx, s, fd,
- FALSE,
+ false,
cv->is_arg, idx1,
- cv->var_name, FALSE, FALSE,
+ cv->var_name, false, false,
JS_VAR_NORMAL);
} else {
idx = idx1;
@@ -30727,12 +29536,12 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
if (var_idx & ARGUMENT_VAR_OFFSET) {
fd->args[var_idx - ARGUMENT_VAR_OFFSET].is_captured = 1;
idx = get_closure_var(ctx, s, fd,
- TRUE, var_idx - ARGUMENT_VAR_OFFSET,
- var_name, FALSE, FALSE, JS_VAR_NORMAL);
+ true, var_idx - ARGUMENT_VAR_OFFSET,
+ var_name, false, false, JS_VAR_NORMAL);
} else {
fd->vars[var_idx].is_captured = 1;
idx = get_closure_var(ctx, s, fd,
- FALSE, var_idx,
+ false, var_idx,
var_name,
fd->vars[var_idx].is_const,
fd->vars[var_idx].is_lexical,
@@ -30877,7 +29686,7 @@ static int find_private_class_field_all(JSContext *ctx, JSFunctionDef *fd,
return -1;
}
-static void get_loc_or_ref(DynBuf *bc, BOOL is_ref, int idx)
+static void get_loc_or_ref(DynBuf *bc, bool is_ref, int idx)
{
/* if the field is not initialized, the error is catched when
accessing it */
@@ -30889,23 +29698,23 @@ static void get_loc_or_ref(DynBuf *bc, BOOL is_ref, int idx)
}
static int resolve_scope_private_field1(JSContext *ctx,
- BOOL *pis_ref, int *pvar_kind,
+ bool *pis_ref, int *pvar_kind,
JSFunctionDef *s,
JSAtom var_name, int scope_level)
{
int idx, var_kind;
JSFunctionDef *fd;
- BOOL is_ref;
+ bool is_ref;
fd = s;
- is_ref = FALSE;
+ is_ref = false;
for(;;) {
idx = find_private_class_field_all(ctx, fd, var_name, scope_level);
if (idx >= 0) {
var_kind = fd->vars[idx].var_kind;
if (is_ref) {
- idx = get_closure_var(ctx, s, fd, FALSE, idx, var_name,
- TRUE, TRUE, JS_VAR_NORMAL);
+ idx = get_closure_var(ctx, s, fd, false, idx, var_name,
+ true, true, JS_VAR_NORMAL);
if (idx < 0)
return -1;
}
@@ -30919,10 +29728,10 @@ static int resolve_scope_private_field1(JSContext *ctx,
JSClosureVar *cv = &fd->closure_var[idx];
if (cv->var_name == var_name) {
var_kind = cv->var_kind;
- is_ref = TRUE;
+ is_ref = true;
if (fd != s) {
idx = get_closure_var2(ctx, s, fd,
- FALSE,
+ false,
cv->is_arg, idx,
cv->var_name, cv->is_const,
cv->is_lexical,
@@ -30935,13 +29744,14 @@ static int resolve_scope_private_field1(JSContext *ctx,
}
}
/* XXX: no line number info */
+ // XXX: resolve_scope_private_field1() should take JSParseState *s and use js_parse_error_atom
JS_ThrowSyntaxErrorAtom(ctx, "undefined private field '%s'",
var_name);
return -1;
} else {
fd = fd->parent;
}
- is_ref = TRUE;
+ is_ref = true;
}
done:
*pis_ref = is_ref;
@@ -30955,7 +29765,7 @@ static int resolve_scope_private_field(JSContext *ctx, JSFunctionDef *s,
DynBuf *bc)
{
int idx, var_kind;
- BOOL is_ref;
+ bool is_ref;
idx = resolve_scope_private_field1(ctx, &is_ref, &var_kind, s,
var_name, scope_level);
@@ -31064,7 +29874,7 @@ static void mark_eval_captured_variables(JSContext *ctx, JSFunctionDef *s,
}
/* XXX: should handle the argument scope generically */
-static BOOL is_var_in_arg_scope(const JSVarDef *vd)
+static bool is_var_in_arg_scope(const JSVarDef *vd)
{
return (vd->var_name == JS_ATOM_home_object ||
vd->var_name == JS_ATOM_this_active_func ||
@@ -31079,11 +29889,11 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
JSFunctionDef *fd;
JSVarDef *vd;
int i, scope_level, scope_idx;
- BOOL has_arguments_binding, has_this_binding, is_arg_scope;
+ bool has_arguments_binding, has_this_binding, is_arg_scope;
/* in non strict mode, variables are created in the caller's
environment object */
- if (!s->is_eval && !(s->js_mode & JS_MODE_STRICT)) {
+ if (!s->is_eval && !s->is_strict_mode) {
s->var_object_idx = add_var(ctx, s, JS_ATOM__var_);
if (s->has_parameter_expressions) {
/* an additional variable object is needed for the
@@ -31110,7 +29920,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
/* also add an arguments binding in the argument scope to
raise an error if a direct eval in the argument scope tries
to redefine it */
- if (s->has_parameter_expressions && !(s->js_mode & JS_MODE_STRICT))
+ if (s->has_parameter_expressions && !s->is_strict_mode)
add_arguments_arg(ctx, s);
}
if (s->is_func_expr && s->func_name != JS_ATOM_NULL)
@@ -31139,12 +29949,12 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
fd->this_active_func_var_idx = add_var(ctx, fd, JS_ATOM_this_active_func);
if (fd->has_home_object && fd->home_object_var_idx < 0)
fd->home_object_var_idx = add_var(ctx, fd, JS_ATOM_home_object);
- has_this_binding = TRUE;
+ has_this_binding = true;
}
/* add 'arguments' if it was not previously added */
if (!has_arguments_binding && fd->has_arguments_binding) {
add_arguments_var(ctx, fd);
- has_arguments_binding = TRUE;
+ has_arguments_binding = true;
}
/* add function name */
if (fd->is_func_expr && fd->func_name != JS_ATOM_NULL)
@@ -31155,7 +29965,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
while (scope_idx >= 0) {
vd = &fd->vars[scope_idx];
vd->is_captured = 1;
- get_closure_var(ctx, s, fd, FALSE, scope_idx,
+ get_closure_var(ctx, s, fd, false, scope_idx,
vd->var_name, vd->is_const, vd->is_lexical, vd->var_kind);
scope_idx = vd->scope_next;
}
@@ -31167,7 +29977,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
vd = &fd->args[i];
if (vd->var_name != JS_ATOM_NULL) {
get_closure_var(ctx, s, fd,
- TRUE, i, vd->var_name, FALSE,
+ true, i, vd->var_name, false,
vd->is_lexical, JS_VAR_NORMAL);
}
}
@@ -31178,7 +29988,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
vd->var_name != JS_ATOM__ret_ &&
vd->var_name != JS_ATOM_NULL) {
get_closure_var(ctx, s, fd,
- FALSE, i, vd->var_name, FALSE,
+ false, i, vd->var_name, false,
vd->is_lexical, JS_VAR_NORMAL);
}
}
@@ -31188,7 +29998,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
/* do not close top level last result */
if (vd->scope_level == 0 && is_var_in_arg_scope(vd)) {
get_closure_var(ctx, s, fd,
- FALSE, i, vd->var_name, FALSE,
+ false, i, vd->var_name, false,
vd->is_lexical, JS_VAR_NORMAL);
}
}
@@ -31200,7 +30010,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
for (idx = 0; idx < fd->closure_var_count; idx++) {
JSClosureVar *cv = &fd->closure_var[idx];
get_closure_var2(ctx, s, fd,
- FALSE, cv->is_arg,
+ false, cv->is_arg,
idx, cv->var_name, cv->is_const,
cv->is_lexical, cv->var_kind);
}
@@ -31211,8 +30021,8 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
static void set_closure_from_var(JSContext *ctx, JSClosureVar *cv,
JSVarDef *vd, int var_idx)
{
- cv->is_local = TRUE;
- cv->is_arg = FALSE;
+ cv->is_local = true;
+ cv->is_arg = false;
cv->is_const = vd->is_const;
cv->is_lexical = vd->is_lexical;
cv->var_kind = vd->var_kind;
@@ -31227,7 +30037,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
{
int i, count;
JSVarDef *vd;
- BOOL is_arg_scope;
+ bool is_arg_scope;
count = b->arg_count + b->var_count + b->closure_var_count;
s->closure_var = NULL;
@@ -31253,10 +30063,10 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
for(i = 0; i < b->arg_count; i++) {
JSClosureVar *cv = &s->closure_var[s->closure_var_count++];
vd = &b->vardefs[i];
- cv->is_local = TRUE;
- cv->is_arg = TRUE;
- cv->is_const = FALSE;
- cv->is_lexical = FALSE;
+ cv->is_local = true;
+ cv->is_arg = true;
+ cv->is_const = false;
+ cv->is_lexical = false;
cv->var_kind = JS_VAR_NORMAL;
cv->var_idx = i;
cv->var_name = JS_DupAtom(ctx, vd->var_name);
@@ -31282,7 +30092,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
for(i = 0; i < b->closure_var_count; i++) {
JSClosureVar *cv0 = &b->closure_var[i];
JSClosureVar *cv = &s->closure_var[s->closure_var_count++];
- cv->is_local = FALSE;
+ cv->is_local = false;
cv->is_arg = cv0->is_arg;
cv->is_const = cv0->is_const;
cv->is_lexical = cv0->is_lexical;
@@ -31297,7 +30107,8 @@ typedef struct CodeContext {
const uint8_t *bc_buf; /* code buffer */
int bc_len; /* length of the code buffer */
int pos; /* position past the matched code pattern */
- int line_num; /* last visited OP_line_num parameter or -1 */
+ int line_num; /* last visited OP_source_loc parameter or -1 */
+ int col_num; /* last visited OP_source_loc parameter or -1 */
int op;
int idx;
int label;
@@ -31305,18 +30116,19 @@ typedef struct CodeContext {
JSAtom atom;
} CodeContext;
-#define M2(op1, op2) ((op1) | ((op2) << 8))
-#define M3(op1, op2, op3) ((op1) | ((op2) << 8) | ((op3) << 16))
-#define M4(op1, op2, op3, op4) ((op1) | ((op2) << 8) | ((op3) << 16) | ((op4) << 24))
+#define M2(op1, op2) ((uint32_t)(op1) | ((uint32_t)(op2) << 8))
+#define M3(op1, op2, op3) ((uint32_t)(op1) | ((uint32_t)(op2) << 8) | ((uint32_t)(op3) << 16))
+#define M4(op1, op2, op3, op4) ((uint32_t)(op1) | ((uint32_t)(op2) << 8) | ((uint32_t)(op3) << 16) | ((uint32_t)(op4) << 24))
-static BOOL code_match(CodeContext *s, int pos, ...)
+static bool code_match(CodeContext *s, int pos, ...)
{
const uint8_t *tab = s->bc_buf;
- int op, len, op1, line_num, pos_next;
+ int op, len, op1, line_num, col_num, pos_next;
va_list ap;
- BOOL ret = FALSE;
+ bool ret = false;
line_num = -1;
+ col_num = -1;
va_start(ap, pos);
for(;;) {
@@ -31324,7 +30136,8 @@ static BOOL code_match(CodeContext *s, int pos, ...)
if (op1 == -1) {
s->pos = pos;
s->line_num = line_num;
- ret = TRUE;
+ s->col_num = col_num;
+ ret = true;
break;
}
for (;;) {
@@ -31335,8 +30148,9 @@ static BOOL code_match(CodeContext *s, int pos, ...)
pos_next = pos + len;
if (pos_next > s->bc_len)
goto done;
- if (op == OP_line_num) {
+ if (op == OP_source_loc) {
line_num = get_u32(tab + pos + 1);
+ col_num = get_u32(tab + pos + 5);
pos = pos_next;
} else {
break;
@@ -31476,7 +30290,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy
for(i = 0; i < s->global_var_count; i++) {
JSGlobalVar *hf = &s->global_vars[i];
int has_closure = 0;
- BOOL force_init = hf->force_init;
+ bool force_init = hf->force_init;
/* we are in an eval, so the closure contains all the
enclosing variables */
/* If the outer function has a variable environment,
@@ -31485,7 +30299,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy
JSClosureVar *cv = &s->closure_var[idx];
if (cv->var_name == hf->var_name) {
has_closure = 2;
- force_init = FALSE;
+ force_init = false;
break;
}
if (cv->var_name == JS_ATOM__var_ ||
@@ -31493,7 +30307,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy
dbuf_putc(bc, OP_get_var_ref);
dbuf_put_u16(bc, idx);
has_closure = 1;
- force_init = TRUE;
+ force_init = true;
break;
}
}
@@ -31568,26 +30382,20 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy
}
static int skip_dead_code(JSFunctionDef *s, const uint8_t *bc_buf, int bc_len,
- int pos, int *linep)
+ int pos, int *linep, int *colp)
{
int op, len, label;
for (; pos < bc_len; pos += len) {
op = bc_buf[pos];
len = opcode_info[op].size;
- if (op == OP_line_num) {
+ if (op == OP_source_loc) {
*linep = get_u32(bc_buf + pos + 1);
- } else
- if (op == OP_label) {
+ *colp = get_u32(bc_buf + pos + 5);
+ } else if (op == OP_label) {
label = get_u32(bc_buf + pos + 1);
if (update_label(s, label, 0) > 0)
break;
-#if 0
- if (s->label_slots[label].first_reloc) {
- printf("line %d: unreferenced label %d:%d has relocations\n",
- *linep, label, s->label_slots[label].pos2);
- }
-#endif
assert(s->label_slots[label].first_reloc == NULL);
} else {
/* XXX: output a warning for unreachable code? */
@@ -31624,7 +30432,9 @@ static int get_label_pos(JSFunctionDef *s, int label)
pos = s->label_slots[label].pos;
for (;;) {
switch (s->byte_code.buf[pos]) {
- case OP_line_num:
+ case OP_source_loc:
+ pos += 9;
+ continue;
case OP_label:
pos += 5;
continue;
@@ -31644,7 +30454,7 @@ static int get_label_pos(JSFunctionDef *s, int label)
variables when necessary */
static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
{
- int pos, pos_next, bc_len, op, len, i, idx, line_num;
+ int pos, pos_next, bc_len, op, len, i, idx, line_num, col_num;
uint8_t *bc_buf;
JSAtom var_name;
DynBuf bc_out;
@@ -31695,14 +30505,16 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
}
line_num = 0; /* avoid warning */
+ col_num = 0;
for (pos = 0; pos < bc_len; pos = pos_next) {
op = bc_buf[pos];
len = opcode_info[op].size;
pos_next = pos + len;
switch(op) {
- case OP_line_num:
+ case OP_source_loc:
line_num = get_u32(bc_buf + pos + 1);
- s->line_number_size++;
+ col_num = get_u32(bc_buf + pos + 5);
+ s->source_loc_size++;
goto no_change;
case OP_eval: /* convert scope index to adjusted variable index */
@@ -31721,7 +30533,6 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
dbuf_putc(&bc_out, op);
dbuf_put_u16(&bc_out, s->scopes[scope].first + 1);
break;
- case OP_scope_get_var_checkthis:
case OP_scope_get_var_undef:
case OP_scope_get_var:
case OP_scope_put_var:
@@ -31764,7 +30575,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
break;
case OP_gosub:
s->jump_size++;
- if (OPTIMIZE) {
+ {
/* remove calls to empty finalizers */
int label;
LabelSlot *ls;
@@ -31778,43 +30589,22 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
}
}
goto no_change;
- case OP_drop:
- if (0) {
- /* remove drops before return_undef */
- /* do not perform this optimization in pass2 because
- it breaks patterns recognised in resolve_labels */
- int pos1 = pos_next;
- int line1 = line_num;
- while (code_match(&cc, pos1, OP_drop, -1)) {
- if (cc.line_num >= 0) line1 = cc.line_num;
- pos1 = cc.pos;
- }
- if (code_match(&cc, pos1, OP_return_undef, -1)) {
- pos_next = pos1;
- if (line1 != -1 && line1 != line_num) {
- line_num = line1;
- s->line_number_size++;
- dbuf_putc(&bc_out, OP_line_num);
- dbuf_put_u32(&bc_out, line_num);
- }
- break;
- }
- }
- goto no_change;
case OP_insert3:
- if (OPTIMIZE) {
- /* Transformation: insert3 put_array_el|put_ref_value drop -> put_array_el|put_ref_value */
- if (code_match(&cc, pos_next, M2(OP_put_array_el, OP_put_ref_value), OP_drop, -1)) {
- dbuf_putc(&bc_out, cc.op);
- pos_next = cc.pos;
- if (cc.line_num != -1 && cc.line_num != line_num) {
- line_num = cc.line_num;
- s->line_number_size++;
- dbuf_putc(&bc_out, OP_line_num);
- dbuf_put_u32(&bc_out, line_num);
- }
+ /* Transformation: insert3 put_array_el|put_ref_value drop -> put_array_el|put_ref_value */
+ if (code_match(&cc, pos_next, M2(OP_put_array_el, OP_put_ref_value), OP_drop, -1)) {
+ dbuf_putc(&bc_out, cc.op);
+ pos_next = cc.pos;
+ if (cc.line_num == -1)
break;
+ if (cc.line_num != line_num || cc.col_num != col_num) {
+ line_num = cc.line_num;
+ col_num = cc.col_num;
+ s->source_loc_size++;
+ dbuf_putc(&bc_out, OP_source_loc);
+ dbuf_put_u32(&bc_out, line_num);
+ dbuf_put_u32(&bc_out, col_num);
}
+ break;
}
goto no_change;
@@ -31828,17 +30618,23 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
case OP_throw:
case OP_throw_error:
case OP_ret:
- if (OPTIMIZE) {
+ {
/* remove dead code */
int line = -1;
+ int col = -1;
dbuf_put(&bc_out, bc_buf + pos, len);
- pos = skip_dead_code(s, bc_buf, bc_len, pos + len, &line);
+ pos = skip_dead_code(s, bc_buf, bc_len, pos + len,
+ &line, &col);
pos_next = pos;
- if (pos < bc_len && line >= 0 && line_num != line) {
+ if (line < 0 || pos >= bc_len)
+ break;
+ if (line_num != line || col_num != col) {
line_num = line;
- s->line_number_size++;
- dbuf_putc(&bc_out, OP_line_num);
+ col_num = col;
+ s->source_loc_size++;
+ dbuf_putc(&bc_out, OP_source_loc);
dbuf_put_u32(&bc_out, line_num);
+ dbuf_put_u32(&bc_out, col_num);
}
break;
}
@@ -31925,34 +30721,37 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
goto no_change;
case OP_dup:
- if (OPTIMIZE) {
- /* Transformation: dup if_false(l1) drop, l1: if_false(l2) -> if_false(l2) */
- /* Transformation: dup if_true(l1) drop, l1: if_true(l2) -> if_true(l2) */
- if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), OP_drop, -1)) {
- int lab0, lab1, op1, pos1, line1, pos2;
- lab0 = lab1 = cc.label;
- assert(lab1 >= 0 && lab1 < s->label_count);
- op1 = cc.op;
- pos1 = cc.pos;
- line1 = cc.line_num;
- while (code_match(&cc, (pos2 = get_label_pos(s, lab1)), OP_dup, op1, OP_drop, -1)) {
- lab1 = cc.label;
- }
- if (code_match(&cc, pos2, op1, -1)) {
- s->jump_size++;
- update_label(s, lab0, -1);
- update_label(s, cc.label, +1);
- dbuf_putc(&bc_out, op1);
- dbuf_put_u32(&bc_out, cc.label);
- pos_next = pos1;
- if (line1 != -1 && line1 != line_num) {
- line_num = line1;
- s->line_number_size++;
- dbuf_putc(&bc_out, OP_line_num);
- dbuf_put_u32(&bc_out, line_num);
- }
+ /* Transformation: dup if_false(l1) drop, l1: if_false(l2) -> if_false(l2) */
+ /* Transformation: dup if_true(l1) drop, l1: if_true(l2) -> if_true(l2) */
+ if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), OP_drop, -1)) {
+ int lab0, lab1, op1, pos1, line1, col1, pos2;
+ lab0 = lab1 = cc.label;
+ assert(lab1 >= 0 && lab1 < s->label_count);
+ op1 = cc.op;
+ pos1 = cc.pos;
+ line1 = cc.line_num;
+ col1 = cc.col_num;
+ while (code_match(&cc, (pos2 = get_label_pos(s, lab1)), OP_dup, op1, OP_drop, -1)) {
+ lab1 = cc.label;
+ }
+ if (code_match(&cc, pos2, op1, -1)) {
+ s->jump_size++;
+ update_label(s, lab0, -1);
+ update_label(s, cc.label, +1);
+ dbuf_putc(&bc_out, op1);
+ dbuf_put_u32(&bc_out, cc.label);
+ pos_next = pos1;
+ if (line1 == -1)
break;
+ if (line1 != line_num || col1 != col_num) {
+ line_num = line1;
+ col_num = col1;
+ s->source_loc_size++;
+ dbuf_putc(&bc_out, OP_source_loc);
+ dbuf_put_u32(&bc_out, line_num);
+ dbuf_put_u32(&bc_out, col_num);
}
+ break;
}
}
goto no_change;
@@ -32005,39 +30804,52 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
}
/* the pc2line table gives a line number for each PC value */
-static void add_pc2line_info(JSFunctionDef *s, uint32_t pc, int line_num)
+static void add_pc2line_info(JSFunctionDef *s, uint32_t pc,
+ int line_num, int col_num)
{
- if (s->line_number_slots != NULL
- && s->line_number_count < s->line_number_size
- && pc >= s->line_number_last_pc
- && line_num != s->line_number_last) {
- s->line_number_slots[s->line_number_count].pc = pc;
- s->line_number_slots[s->line_number_count].line_num = line_num;
- s->line_number_count++;
- s->line_number_last_pc = pc;
- s->line_number_last = line_num;
- }
+ if (s->source_loc_slots == NULL)
+ return;
+ if (s->source_loc_count >= s->source_loc_size)
+ return;
+ if (pc < s->line_number_last_pc)
+ return;
+ if (line_num == s->line_number_last)
+ if (col_num == s->col_number_last)
+ return;
+ s->source_loc_slots[s->source_loc_count].pc = pc;
+ s->source_loc_slots[s->source_loc_count].line_num = line_num;
+ s->source_loc_slots[s->source_loc_count].col_num = col_num;
+ s->source_loc_count++;
+ s->line_number_last_pc = pc;
+ s->line_number_last = line_num;
+ s->col_number_last = col_num;
}
static void compute_pc2line_info(JSFunctionDef *s)
{
- if (!(s->js_mode & JS_MODE_STRIP) && s->line_number_slots) {
+ if (s->source_loc_slots) {
int last_line_num = s->line_num;
+ int last_col_num = s->col_num;
uint32_t last_pc = 0;
int i;
js_dbuf_init(s->ctx, &s->pc2line);
- for (i = 0; i < s->line_number_count; i++) {
- uint32_t pc = s->line_number_slots[i].pc;
- int line_num = s->line_number_slots[i].line_num;
- int diff_pc, diff_line;
+ for (i = 0; i < s->source_loc_count; i++) {
+ uint32_t pc = s->source_loc_slots[i].pc;
+ int line_num = s->source_loc_slots[i].line_num;
+ int col_num = s->source_loc_slots[i].col_num;
+ int diff_pc, diff_line, diff_col;
if (line_num < 0)
continue;
diff_pc = pc - last_pc;
+ if (diff_pc < 0)
+ continue;
+
diff_line = line_num - last_line_num;
- if (diff_line == 0 || diff_pc < 0)
+ diff_col = col_num - last_col_num;
+ if (diff_line == 0 && diff_col == 0)
continue;
if (diff_line >= PC2LINE_BASE &&
@@ -32051,8 +30863,11 @@ static void compute_pc2line_info(JSFunctionDef *s)
dbuf_put_leb128(&s->pc2line, diff_pc);
dbuf_put_sleb128(&s->pc2line, diff_line);
}
+ dbuf_put_sleb128(&s->pc2line, diff_col);
+
last_pc = pc;
last_line_num = line_num;
+ last_col_num = col_num;
}
}
}
@@ -32070,35 +30885,35 @@ static RelocEntry *add_reloc(JSContext *ctx, LabelSlot *ls, uint32_t addr, int s
return re;
}
-static BOOL code_has_label(CodeContext *s, int pos, int label)
+static bool code_has_label(CodeContext *s, int pos, int label)
{
while (pos < s->bc_len) {
int op = s->bc_buf[pos];
- if (op == OP_line_num) {
- pos += 5;
+ if (op == OP_source_loc) {
+ pos += 9;
continue;
}
if (op == OP_label) {
int lab = get_u32(s->bc_buf + pos + 1);
if (lab == label)
- return TRUE;
+ return true;
pos += 5;
continue;
}
if (op == OP_goto) {
int lab = get_u32(s->bc_buf + pos + 1);
if (lab == label)
- return TRUE;
+ return true;
}
break;
}
- return FALSE;
+ return false;
}
/* return the target label, following the OP_goto jumps
the first opcode at destination is stored in *pop
*/
-static int find_jump_target(JSFunctionDef *s, int label, int *pop, int *pline)
+static int find_jump_target(JSFunctionDef *s, int label, int *pop)
{
int i, pos, op;
@@ -32108,10 +30923,7 @@ static int find_jump_target(JSFunctionDef *s, int label, int *pop, int *pline)
pos = s->label_slots[label].pos2;
for (;;) {
switch(op = s->byte_code.buf[pos]) {
- case OP_line_num:
- if (pline)
- *pline = get_u32(s->byte_code.buf + pos + 1);
- /* fall thru */
+ case OP_source_loc:
case OP_label:
pos += opcode_info[op].size;
continue;
@@ -32140,7 +30952,6 @@ static int find_jump_target(JSFunctionDef *s, int label, int *pop, int *pline)
static void push_short_int(DynBuf *bc_out, int val)
{
-#if SHORT_OPCODES
if (val >= -1 && val <= 7) {
dbuf_putc(bc_out, OP_push_0 + val);
return;
@@ -32155,14 +30966,12 @@ static void push_short_int(DynBuf *bc_out, int val)
dbuf_put_u16(bc_out, val);
return;
}
-#endif
dbuf_putc(bc_out, OP_push_i32);
dbuf_put_u32(bc_out, val);
}
static void put_short_code(DynBuf *bc_out, int op, int idx)
{
-#if SHORT_OPCODES
if (idx < 4) {
switch (op) {
case OP_get_loc:
@@ -32213,7 +31022,6 @@ static void put_short_code(DynBuf *bc_out, int op, int idx)
return;
}
}
-#endif
dbuf_putc(bc_out, op);
dbuf_put_u16(bc_out, idx);
}
@@ -32221,38 +31029,36 @@ static void put_short_code(DynBuf *bc_out, int op, int idx)
/* peephole optimizations and resolve goto/labels */
static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
{
- int pos, pos_next, bc_len, op, op1, len, i, line_num;
+ int pos, pos_next, bc_len, op, op1, len, i, line_num, col_num, patch_offsets;
const uint8_t *bc_buf;
DynBuf bc_out;
LabelSlot *label_slots, *ls;
RelocEntry *re, *re_next;
CodeContext cc;
int label;
-#if SHORT_OPCODES
JumpSlot *jp;
-#endif
label_slots = s->label_slots;
line_num = s->line_num;
+ col_num = s->col_num;
cc.bc_buf = bc_buf = s->byte_code.buf;
cc.bc_len = bc_len = s->byte_code.size;
js_dbuf_init(ctx, &bc_out);
-#if SHORT_OPCODES
if (s->jump_size) {
s->jump_slots = js_mallocz(s->ctx, sizeof(*s->jump_slots) * s->jump_size);
if (s->jump_slots == NULL)
return -1;
}
-#endif
- /* XXX: Should skip this phase if not generating SHORT_OPCODES */
- if (s->line_number_size && !(s->js_mode & JS_MODE_STRIP)) {
- s->line_number_slots = js_mallocz(s->ctx, sizeof(*s->line_number_slots) * s->line_number_size);
- if (s->line_number_slots == NULL)
+
+ if (s->source_loc_size) {
+ s->source_loc_slots = js_mallocz(s->ctx, sizeof(*s->source_loc_slots) * s->source_loc_size);
+ if (s->source_loc_slots == NULL)
return -1;
s->line_number_last = s->line_num;
+ s->col_number_last = s->col_num;
s->line_number_last_pc = 0;
}
@@ -32287,7 +31093,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
}
/* initialize the 'arguments' variable if needed */
if (s->arguments_var_idx >= 0) {
- if ((s->js_mode & JS_MODE_STRICT) || !s->has_simple_parameter_list) {
+ if (s->is_strict_mode || !s->has_simple_parameter_list) {
dbuf_putc(&bc_out, OP_special_object);
dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_ARGUMENTS);
} else {
@@ -32322,11 +31128,12 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
len = opcode_info[op].size;
pos_next = pos + len;
switch(op) {
- case OP_line_num:
+ case OP_source_loc:
/* line number info (for debug). We put it in a separate
compressed table to reduce memory usage and get better
performance */
line_num = get_u32(bc_buf + pos + 1);
+ col_num = get_u32(bc_buf + pos + 5);
break;
case OP_label:
@@ -32367,12 +31174,14 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
argc = get_u16(bc_buf + pos + 1);
if (code_match(&cc, pos_next, OP_return, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
put_short_code(&bc_out, op + 1, argc);
- pos_next = skip_dead_code(s, bc_buf, bc_len, cc.pos, &line_num);
+ pos_next = skip_dead_code(s, bc_buf, bc_len, cc.pos,
+ &line_num, &col_num);
break;
}
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
put_short_code(&bc_out, op, argc);
break;
}
@@ -32383,16 +31192,16 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
case OP_return_async:
case OP_throw:
case OP_throw_error:
- pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num);
+ pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next,
+ &line_num, &col_num);
goto no_change;
case OP_goto:
label = get_u32(bc_buf + pos + 1);
has_goto:
- if (OPTIMIZE) {
- int line1 = -1;
+ {
/* Use custom matcher because multiple labels can follow */
- label = find_jump_target(s, label, &op1, &line1);
+ label = find_jump_target(s, label, &op1);
if (code_has_label(&cc, pos_next, label)) {
/* jump to next instruction: remove jump */
update_label(s, label, -1);
@@ -32401,11 +31210,11 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
if (op1 == OP_return || op1 == OP_return_undef || op1 == OP_throw) {
/* jump to return/throw: remove jump, append return/throw */
/* updating the line number obfuscates assembly listing */
- //if (line1 >= 0) line_num = line1;
update_label(s, label, -1);
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
dbuf_putc(&bc_out, op1);
- pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num);
+ pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next,
+ &line_num, &col_num);
break;
}
/* XXX: should duplicate single instructions followed by goto or return */
@@ -32419,14 +31228,6 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
case OP_gosub:
label = get_u32(bc_buf + pos + 1);
- if (0 && OPTIMIZE) {
- label = find_jump_target(s, label, &op1, NULL);
- if (op1 == OP_ret) {
- update_label(s, label, -1);
- /* empty finally clause: remove gosub */
- break;
- }
- }
goto has_label;
case OP_catch:
@@ -32436,35 +31237,35 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
case OP_if_true:
case OP_if_false:
label = get_u32(bc_buf + pos + 1);
- if (OPTIMIZE) {
- label = find_jump_target(s, label, &op1, NULL);
- /* transform if_false/if_true(l1) label(l1) -> drop label(l1) */
- if (code_has_label(&cc, pos_next, label)) {
+ label = find_jump_target(s, label, &op1);
+ /* transform if_false/if_true(l1) label(l1) -> drop label(l1) */
+ if (code_has_label(&cc, pos_next, label)) {
+ update_label(s, label, -1);
+ dbuf_putc(&bc_out, OP_drop);
+ break;
+ }
+ /* transform if_false(l1) goto(l2) label(l1) -> if_false(l2) label(l1) */
+ if (code_match(&cc, pos_next, OP_goto, -1)) {
+ int pos1 = cc.pos;
+ int line1 = cc.line_num;
+ int col1 = cc.col_num;
+ if (code_has_label(&cc, pos1, label)) {
+ if (line1 >= 0) line_num = line1;
+ if (col1 >= 0) col_num = col1;
+ pos_next = pos1;
update_label(s, label, -1);
- dbuf_putc(&bc_out, OP_drop);
- break;
- }
- /* transform if_false(l1) goto(l2) label(l1) -> if_false(l2) label(l1) */
- if (code_match(&cc, pos_next, OP_goto, -1)) {
- int pos1 = cc.pos;
- int line1 = cc.line_num;
- if (code_has_label(&cc, pos1, label)) {
- if (line1 >= 0) line_num = line1;
- pos_next = pos1;
- update_label(s, label, -1);
- label = cc.label;
- op ^= OP_if_true ^ OP_if_false;
- }
+ label = cc.label;
+ op ^= OP_if_true ^ OP_if_false;
}
}
has_label:
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
if (op == OP_goto) {
- pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num);
+ pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next,
+ &line_num, &col_num);
}
assert(label >= 0 && label < s->label_count);
ls = &label_slots[label];
-#if SHORT_OPCODES
jp = &s->jump_slots[s->jump_count++];
jp->op = op;
jp->size = 4;
@@ -32508,7 +31309,6 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
break;
}
}
-#endif
dbuf_putc(&bc_out, op);
dbuf_put_u32(&bc_out, ls->addr - bc_out.size);
if (ls->addr == -1) {
@@ -32530,19 +31330,15 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
atom = get_u32(bc_buf + pos + 1);
label = get_u32(bc_buf + pos + 5);
is_with = bc_buf[pos + 9];
- if (OPTIMIZE) {
- label = find_jump_target(s, label, &op1, NULL);
- }
+ label = find_jump_target(s, label, &op1);
assert(label >= 0 && label < s->label_count);
ls = &label_slots[label];
- add_pc2line_info(s, bc_out.size, line_num);
-#if SHORT_OPCODES
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
jp = &s->jump_slots[s->jump_count++];
jp->op = op;
jp->size = 4;
jp->pos = bc_out.size + 5;
jp->label = label;
-#endif
dbuf_putc(&bc_out, op);
dbuf_put_u32(&bc_out, atom);
dbuf_put_u32(&bc_out, ls->addr - bc_out.size);
@@ -32556,106 +31352,101 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
break;
case OP_drop:
- if (OPTIMIZE) {
- /* remove useless drops before return */
- if (code_match(&cc, pos_next, OP_return_undef, -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- break;
- }
+ /* remove useless drops before return */
+ if (code_match(&cc, pos_next, OP_return_undef, -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ break;
}
goto no_change;
case OP_null:
-#if SHORT_OPCODES
- if (OPTIMIZE) {
- /* transform null strict_eq into is_null */
- if (code_match(&cc, pos_next, OP_strict_eq, -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
- dbuf_putc(&bc_out, OP_is_null);
- pos_next = cc.pos;
- break;
- }
- /* transform null strict_neq if_false/if_true -> is_null if_true/if_false */
- if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
- dbuf_putc(&bc_out, OP_is_null);
- pos_next = cc.pos;
- label = cc.label;
- op = cc.op ^ OP_if_false ^ OP_if_true;
- goto has_label;
- }
+ /* transform null strict_eq into is_null */
+ if (code_match(&cc, pos_next, OP_strict_eq, -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ dbuf_putc(&bc_out, OP_is_null);
+ pos_next = cc.pos;
+ break;
+ }
+ /* transform null strict_neq if_false/if_true -> is_null if_true/if_false */
+ if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ dbuf_putc(&bc_out, OP_is_null);
+ pos_next = cc.pos;
+ label = cc.label;
+ op = cc.op ^ OP_if_false ^ OP_if_true;
+ goto has_label;
}
-#endif
/* fall thru */
case OP_push_false:
case OP_push_true:
- if (OPTIMIZE) {
- val = (op == OP_push_true);
- if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {
- has_constant_test:
- if (cc.line_num >= 0) line_num = cc.line_num;
- if (val == cc.op - OP_if_false) {
- /* transform null if_false(l1) -> goto l1 */
- /* transform false if_false(l1) -> goto l1 */
- /* transform true if_true(l1) -> goto l1 */
- pos_next = cc.pos;
- op = OP_goto;
- label = cc.label;
- goto has_goto;
- } else {
- /* transform null if_true(l1) -> nop */
- /* transform false if_true(l1) -> nop */
- /* transform true if_false(l1) -> nop */
- pos_next = cc.pos;
- update_label(s, cc.label, -1);
- break;
- }
+ val = (op == OP_push_true);
+ if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {
+ has_constant_test:
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ if (val == cc.op - OP_if_false) {
+ /* transform null if_false(l1) -> goto l1 */
+ /* transform false if_false(l1) -> goto l1 */
+ /* transform true if_true(l1) -> goto l1 */
+ pos_next = cc.pos;
+ op = OP_goto;
+ label = cc.label;
+ goto has_goto;
+ } else {
+ /* transform null if_true(l1) -> nop */
+ /* transform false if_true(l1) -> nop */
+ /* transform true if_false(l1) -> nop */
+ pos_next = cc.pos;
+ update_label(s, cc.label, -1);
+ break;
}
}
goto no_change;
case OP_push_i32:
- if (OPTIMIZE) {
- /* transform i32(val) neg -> i32(-val) */
- val = get_i32(bc_buf + pos + 1);
- if ((val != INT32_MIN && val != 0)
- && code_match(&cc, pos_next, OP_neg, -1)) {
+ /* transform i32(val) neg -> i32(-val) */
+ val = get_i32(bc_buf + pos + 1);
+ if ((val != INT32_MIN && val != 0)
+ && code_match(&cc, pos_next, OP_neg, -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ if (code_match(&cc, cc.pos, OP_drop, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
- if (code_match(&cc, cc.pos, OP_drop, -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- } else {
- add_pc2line_info(s, bc_out.size, line_num);
- push_short_int(&bc_out, -val);
- }
- pos_next = cc.pos;
- break;
- }
- /* remove push/drop pairs generated by the parser */
- if (code_match(&cc, pos_next, OP_drop, -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- pos_next = cc.pos;
- break;
- }
- /* Optimize constant tests: `if (0)`, `if (1)`, `if (!0)`... */
- if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {
- val = (val != 0);
- goto has_constant_test;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ } else {
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ push_short_int(&bc_out, -val);
}
- add_pc2line_info(s, bc_out.size, line_num);
- push_short_int(&bc_out, val);
+ pos_next = cc.pos;
break;
}
- goto no_change;
+ /* remove push/drop pairs generated by the parser */
+ if (code_match(&cc, pos_next, OP_drop, -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ pos_next = cc.pos;
+ break;
+ }
+ /* Optimize constant tests: `if (0)`, `if (1)`, `if (!0)`... */
+ if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {
+ val = (val != 0);
+ goto has_constant_test;
+ }
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ push_short_int(&bc_out, val);
+ break;
-#if SHORT_OPCODES
case OP_push_const:
case OP_fclosure:
- if (OPTIMIZE) {
+ {
int idx = get_u32(bc_buf + pos + 1);
if (idx < 256) {
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
dbuf_putc(&bc_out, OP_push_const8 + op - OP_push_const);
dbuf_putc(&bc_out, idx);
break;
@@ -32664,122 +31455,120 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
goto no_change;
case OP_get_field:
- if (OPTIMIZE) {
+ {
JSAtom atom = get_u32(bc_buf + pos + 1);
if (atom == JS_ATOM_length) {
JS_FreeAtom(ctx, atom);
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
dbuf_putc(&bc_out, OP_get_length);
break;
}
}
goto no_change;
-#endif
+
case OP_push_atom_value:
- if (OPTIMIZE) {
+ {
JSAtom atom = get_u32(bc_buf + pos + 1);
/* remove push/drop pairs generated by the parser */
if (code_match(&cc, pos_next, OP_drop, -1)) {
JS_FreeAtom(ctx, atom);
if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
pos_next = cc.pos;
break;
}
-#if SHORT_OPCODES
if (atom == JS_ATOM_empty_string) {
JS_FreeAtom(ctx, atom);
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
dbuf_putc(&bc_out, OP_push_empty_string);
break;
}
-#endif
}
goto no_change;
case OP_to_propkey:
case OP_to_propkey2:
- if (OPTIMIZE) {
- /* remove redundant to_propkey/to_propkey2 opcodes when storing simple data */
- if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_put_array_el, -1)
- || code_match(&cc, pos_next, M3(OP_push_i32, OP_push_const, OP_push_atom_value), OP_put_array_el, -1)
- || code_match(&cc, pos_next, M4(OP_undefined, OP_null, OP_push_true, OP_push_false), OP_put_array_el, -1)) {
- break;
- }
+ /* remove redundant to_propkey/to_propkey2 opcodes when storing simple data */
+ if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_put_array_el, -1)
+ || code_match(&cc, pos_next, M3(OP_push_i32, OP_push_const, OP_push_atom_value), OP_put_array_el, -1)
+ || code_match(&cc, pos_next, M4(OP_undefined, OP_null, OP_push_true, OP_push_false), OP_put_array_el, -1)) {
+ break;
}
goto no_change;
case OP_undefined:
- if (OPTIMIZE) {
- /* remove push/drop pairs generated by the parser */
- if (code_match(&cc, pos_next, OP_drop, -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- pos_next = cc.pos;
- break;
- }
- /* transform undefined return -> return_undefined */
- if (code_match(&cc, pos_next, OP_return, -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
- dbuf_putc(&bc_out, OP_return_undef);
- pos_next = cc.pos;
- break;
- }
- /* transform undefined if_true(l1)/if_false(l1) -> nop/goto(l1) */
- if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {
- val = 0;
- goto has_constant_test;
- }
-#if SHORT_OPCODES
- /* transform undefined strict_eq -> is_undefined */
- if (code_match(&cc, pos_next, OP_strict_eq, -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
- dbuf_putc(&bc_out, OP_is_undefined);
- pos_next = cc.pos;
- break;
- }
- /* transform undefined strict_neq if_false/if_true -> is_undefined if_true/if_false */
- if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
- dbuf_putc(&bc_out, OP_is_undefined);
- pos_next = cc.pos;
- label = cc.label;
- op = cc.op ^ OP_if_false ^ OP_if_true;
- goto has_label;
- }
-#endif
+ /* remove push/drop pairs generated by the parser */
+ if (code_match(&cc, pos_next, OP_drop, -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ pos_next = cc.pos;
+ break;
+ }
+ /* transform undefined return -> return_undefined */
+ if (code_match(&cc, pos_next, OP_return, -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ dbuf_putc(&bc_out, OP_return_undef);
+ pos_next = cc.pos;
+ break;
+ }
+ /* transform undefined if_true(l1)/if_false(l1) -> nop/goto(l1) */
+ if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {
+ val = 0;
+ goto has_constant_test;
+ }
+ /* transform undefined strict_eq -> is_undefined */
+ if (code_match(&cc, pos_next, OP_strict_eq, -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ dbuf_putc(&bc_out, OP_is_undefined);
+ pos_next = cc.pos;
+ break;
+ }
+ /* transform undefined strict_neq if_false/if_true -> is_undefined if_true/if_false */
+ if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ dbuf_putc(&bc_out, OP_is_undefined);
+ pos_next = cc.pos;
+ label = cc.label;
+ op = cc.op ^ OP_if_false ^ OP_if_true;
+ goto has_label;
}
goto no_change;
case OP_insert2:
- if (OPTIMIZE) {
- /* Transformation:
- insert2 put_field(a) drop -> put_field(a)
- insert2 put_var_strict(a) drop -> put_var_strict(a)
- */
- if (code_match(&cc, pos_next, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
- dbuf_putc(&bc_out, cc.op);
- dbuf_put_u32(&bc_out, cc.atom);
- pos_next = cc.pos;
- break;
- }
+ /* Transformation:
+ insert2 put_field(a) drop -> put_field(a)
+ insert2 put_var_strict(a) drop -> put_var_strict(a)
+ */
+ if (code_match(&cc, pos_next, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ dbuf_putc(&bc_out, cc.op);
+ dbuf_put_u32(&bc_out, cc.atom);
+ pos_next = cc.pos;
+ break;
}
goto no_change;
case OP_dup:
- if (OPTIMIZE) {
+ {
/* Transformation: dup put_x(n) drop -> put_x(n) */
int op1, line2 = -1;
/* Transformation: dup put_x(n) -> set_x(n) */
if (code_match(&cc, pos_next, M3(OP_put_loc, OP_put_arg, OP_put_var_ref), -1, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
op1 = cc.op + 1; /* put_x -> set_x */
pos_next = cc.pos;
if (code_match(&cc, cc.pos, OP_drop, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
op1 -= 1; /* set_x drop -> put_x */
pos_next = cc.pos;
if (code_match(&cc, cc.pos, op1 - 1, cc.idx, -1)) {
@@ -32788,7 +31577,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
pos_next = cc.pos;
}
}
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
put_short_code(&bc_out, op1, cc.idx);
if (line2 >= 0) line_num = line2;
break;
@@ -32796,8 +31585,18 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
}
goto no_change;
+ case OP_swap:
+ // transformation: swap swap -> nothing!
+ if (code_match(&cc, pos_next, OP_swap, -1, -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ pos_next = cc.pos;
+ break;
+ }
+ goto no_change;
+
case OP_get_loc:
- if (OPTIMIZE) {
+ {
/* transformation:
get_loc(n) post_dec put_loc(n) drop -> dec_loc(n)
get_loc(n) post_inc put_loc(n) drop -> inc_loc(n)
@@ -32811,7 +31610,8 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
if (code_match(&cc, pos_next, M2(OP_post_dec, OP_post_inc), OP_put_loc, idx, OP_drop, -1) ||
code_match(&cc, pos_next, M2(OP_dec, OP_inc), OP_dup, OP_put_loc, idx, OP_drop, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
dbuf_putc(&bc_out, (cc.op == OP_inc || cc.op == OP_post_inc) ? OP_inc_loc : OP_dec_loc);
dbuf_putc(&bc_out, idx);
pos_next = cc.pos;
@@ -32822,14 +31622,12 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
*/
if (code_match(&cc, pos_next, OP_push_atom_value, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
-#if SHORT_OPCODES
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
if (cc.atom == JS_ATOM_empty_string) {
JS_FreeAtom(ctx, cc.atom);
dbuf_putc(&bc_out, OP_push_empty_string);
- } else
-#endif
- {
+ } else {
dbuf_putc(&bc_out, OP_push_atom_value);
dbuf_put_u32(&bc_out, cc.atom);
}
@@ -32843,7 +31641,8 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
*/
if (code_match(&cc, pos_next, OP_push_i32, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
push_short_int(&bc_out, cc.label);
dbuf_putc(&bc_out, OP_add_loc);
dbuf_putc(&bc_out, idx);
@@ -32857,53 +31656,59 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
*/
if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
put_short_code(&bc_out, cc.op, cc.idx);
dbuf_putc(&bc_out, OP_add_loc);
dbuf_putc(&bc_out, idx);
pos_next = cc.pos;
break;
}
- add_pc2line_info(s, bc_out.size, line_num);
+ /* transformation: get_loc(0) get_loc(1) -> get_loc0_loc1 */
+ if (idx == 0 && code_match(&cc, pos_next, OP_get_loc, 1, -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ dbuf_putc(&bc_out, OP_get_loc0_loc1);
+ pos_next = cc.pos;
+ break;
+ }
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
put_short_code(&bc_out, op, idx);
- break;
}
- goto no_change;
-#if SHORT_OPCODES
+ break;
case OP_get_arg:
case OP_get_var_ref:
- if (OPTIMIZE) {
+ {
int idx;
idx = get_u16(bc_buf + pos + 1);
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
put_short_code(&bc_out, op, idx);
- break;
}
- goto no_change;
-#endif
+ break;
case OP_put_loc:
case OP_put_arg:
case OP_put_var_ref:
- if (OPTIMIZE) {
+ {
/* transformation: put_x(n) get_x(n) -> set_x(n) */
int idx;
idx = get_u16(bc_buf + pos + 1);
if (code_match(&cc, pos_next, op - 1, idx, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
put_short_code(&bc_out, op + 1, idx);
pos_next = cc.pos;
break;
}
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
put_short_code(&bc_out, op, idx);
- break;
}
- goto no_change;
+ break;
case OP_post_inc:
case OP_post_dec:
- if (OPTIMIZE) {
+ {
/* transformation:
post_inc put_x drop -> inc put_x
post_inc perm3 put_field drop -> inc put_field
@@ -32913,22 +31718,25 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
int op1, idx;
if (code_match(&cc, pos_next, M3(OP_put_loc, OP_put_arg, OP_put_var_ref), -1, OP_drop, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
op1 = cc.op;
idx = cc.idx;
pos_next = cc.pos;
if (code_match(&cc, cc.pos, op1 - 1, idx, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
op1 += 1; /* put_x(n) get_x(n) -> set_x(n) */
pos_next = cc.pos;
}
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec));
put_short_code(&bc_out, op1, idx);
break;
}
if (code_match(&cc, pos_next, OP_perm3, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec));
dbuf_putc(&bc_out, cc.op);
dbuf_put_u32(&bc_out, cc.atom);
@@ -32937,7 +31745,8 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
}
if (code_match(&cc, pos_next, OP_perm4, OP_put_array_el, OP_drop, -1)) {
if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec));
dbuf_putc(&bc_out, OP_put_array_el);
pos_next = cc.pos;
@@ -32946,51 +31755,49 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
}
goto no_change;
-#if SHORT_OPCODES
case OP_typeof:
- if (OPTIMIZE) {
- /* simplify typeof tests */
- if (code_match(&cc, pos_next, OP_push_atom_value, M4(OP_strict_eq, OP_strict_neq, OP_eq, OP_neq), -1)) {
- if (cc.line_num >= 0) line_num = cc.line_num;
- int op1 = (cc.op == OP_strict_eq || cc.op == OP_eq) ? OP_strict_eq : OP_strict_neq;
- int op2 = -1;
- switch (cc.atom) {
- case JS_ATOM_undefined:
- op2 = OP_typeof_is_undefined;
- break;
- case JS_ATOM_function:
- op2 = OP_typeof_is_function;
+ /* simplify typeof tests */
+ if (code_match(&cc, pos_next, OP_push_atom_value, M4(OP_strict_eq, OP_strict_neq, OP_eq, OP_neq), -1)) {
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ int op1 = (cc.op == OP_strict_eq || cc.op == OP_eq) ? OP_strict_eq : OP_strict_neq;
+ int op2 = -1;
+ switch (cc.atom) {
+ case JS_ATOM_undefined:
+ op2 = OP_typeof_is_undefined;
+ break;
+ case JS_ATOM_function:
+ op2 = OP_typeof_is_function;
+ break;
+ }
+ if (op2 >= 0) {
+ /* transform typeof(s) == "<type>" into is_<type> */
+ if (op1 == OP_strict_eq) {
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ dbuf_putc(&bc_out, op2);
+ JS_FreeAtom(ctx, cc.atom);
+ pos_next = cc.pos;
break;
}
- if (op2 >= 0) {
- /* transform typeof(s) == "<type>" into is_<type> */
- if (op1 == OP_strict_eq) {
- add_pc2line_info(s, bc_out.size, line_num);
- dbuf_putc(&bc_out, op2);
- JS_FreeAtom(ctx, cc.atom);
- pos_next = cc.pos;
- break;
- }
- if (op1 == OP_strict_neq && code_match(&cc, cc.pos, OP_if_false, -1)) {
- /* transform typeof(s) != "<type>" if_false into is_<type> if_true */
- if (cc.line_num >= 0) line_num = cc.line_num;
- add_pc2line_info(s, bc_out.size, line_num);
- dbuf_putc(&bc_out, op2);
- JS_FreeAtom(ctx, cc.atom);
- pos_next = cc.pos;
- label = cc.label;
- op = OP_if_true;
- goto has_label;
- }
+ if (op1 == OP_strict_neq && code_match(&cc, cc.pos, OP_if_false, -1)) {
+ /* transform typeof(s) != "<type>" if_false into is_<type> if_true */
+ if (cc.line_num >= 0) line_num = cc.line_num;
+ if (cc.col_num >= 0) col_num = cc.col_num;
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
+ dbuf_putc(&bc_out, op2);
+ JS_FreeAtom(ctx, cc.atom);
+ pos_next = cc.pos;
+ label = cc.label;
+ op = OP_if_true;
+ goto has_label;
}
}
}
goto no_change;
-#endif
default:
no_change:
- add_pc2line_info(s, bc_out.size, line_num);
+ add_pc2line_info(s, bc_out.size, line_num, col_num);
dbuf_put(&bc_out, bc_buf + pos, len);
break;
}
@@ -33000,95 +31807,94 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
for(i = 0; i < s->label_count; i++) {
assert(label_slots[i].first_reloc == NULL);
}
-#if SHORT_OPCODES
- if (OPTIMIZE) {
- /* more jump optimizations */
- int patch_offsets = 0;
- for (i = 0, jp = s->jump_slots; i < s->jump_count; i++, jp++) {
- LabelSlot *ls;
- JumpSlot *jp1;
- int j, pos, diff, delta;
-
- delta = 3;
- switch (op = jp->op) {
- case OP_goto16:
- delta = 1;
- /* fall thru */
- case OP_if_false:
- case OP_if_true:
- case OP_goto:
- pos = jp->pos;
- diff = s->label_slots[jp->label].addr - pos;
- if (diff >= -128 && diff <= 127 + delta) {
- //put_u8(bc_out.buf + pos, diff);
- jp->size = 1;
- if (op == OP_goto16) {
- bc_out.buf[pos - 1] = jp->op = OP_goto8;
- } else {
- bc_out.buf[pos - 1] = jp->op = OP_if_false8 + (op - OP_if_false);
- }
- goto shrink;
- } else
- if (diff == (int16_t)diff && op == OP_goto) {
- //put_u16(bc_out.buf + pos, diff);
- jp->size = 2;
- delta = 2;
- bc_out.buf[pos - 1] = jp->op = OP_goto16;
- shrink:
- /* XXX: should reduce complexity, using 2 finger copy scheme */
- memmove(bc_out.buf + pos + jp->size, bc_out.buf + pos + jp->size + delta,
- bc_out.size - pos - jp->size - delta);
- bc_out.size -= delta;
- patch_offsets++;
- for (j = 0, ls = s->label_slots; j < s->label_count; j++, ls++) {
- if (ls->addr > pos)
- ls->addr -= delta;
- }
- for (j = i + 1, jp1 = jp + 1; j < s->jump_count; j++, jp1++) {
- if (jp1->pos > pos)
- jp1->pos -= delta;
- }
- for (j = 0; j < s->line_number_count; j++) {
- if (s->line_number_slots[j].pc > pos)
- s->line_number_slots[j].pc -= delta;
- }
- continue;
+
+ /* more jump optimizations */
+ patch_offsets = 0;
+ for (i = 0, jp = s->jump_slots; i < s->jump_count; i++, jp++) {
+ LabelSlot *ls;
+ JumpSlot *jp1;
+ int j, pos, diff, delta;
+
+ delta = 3;
+ switch (op = jp->op) {
+ case OP_goto16:
+ delta = 1;
+ /* fall thru */
+ case OP_if_false:
+ case OP_if_true:
+ case OP_goto:
+ pos = jp->pos;
+ diff = s->label_slots[jp->label].addr - pos;
+ if (diff >= -128 && diff <= 127 + delta) {
+ //put_u8(bc_out.buf + pos, diff);
+ jp->size = 1;
+ if (op == OP_goto16) {
+ bc_out.buf[pos - 1] = jp->op = OP_goto8;
+ } else {
+ bc_out.buf[pos - 1] = jp->op = OP_if_false8 + (op - OP_if_false);
}
- break;
+ goto shrink;
+ } else
+ if (diff == (int16_t)diff && op == OP_goto) {
+ //put_u16(bc_out.buf + pos, diff);
+ jp->size = 2;
+ delta = 2;
+ bc_out.buf[pos - 1] = jp->op = OP_goto16;
+ shrink:
+ /* XXX: should reduce complexity, using 2 finger copy scheme */
+ memmove(bc_out.buf + pos + jp->size, bc_out.buf + pos + jp->size + delta,
+ bc_out.size - pos - jp->size - delta);
+ bc_out.size -= delta;
+ patch_offsets++;
+ for (j = 0, ls = s->label_slots; j < s->label_count; j++, ls++) {
+ if (ls->addr > pos)
+ ls->addr -= delta;
+ }
+ for (j = i + 1, jp1 = jp + 1; j < s->jump_count; j++, jp1++) {
+ if (jp1->pos > pos)
+ jp1->pos -= delta;
+ }
+ for (j = 0; j < s->source_loc_count; j++) {
+ if (s->source_loc_slots[j].pc > pos)
+ s->source_loc_slots[j].pc -= delta;
+ }
+ continue;
}
+ break;
}
- if (patch_offsets) {
- JumpSlot *jp1;
- int j;
- for (j = 0, jp1 = s->jump_slots; j < s->jump_count; j++, jp1++) {
- int diff1 = s->label_slots[jp1->label].addr - jp1->pos;
- switch (jp1->size) {
- case 1:
- put_u8(bc_out.buf + jp1->pos, diff1);
- break;
- case 2:
- put_u16(bc_out.buf + jp1->pos, diff1);
- break;
- case 4:
- put_u32(bc_out.buf + jp1->pos, diff1);
- break;
- }
+ }
+
+ if (patch_offsets) {
+ JumpSlot *jp1;
+ int j;
+ for (j = 0, jp1 = s->jump_slots; j < s->jump_count; j++, jp1++) {
+ int diff1 = s->label_slots[jp1->label].addr - jp1->pos;
+ switch (jp1->size) {
+ case 1:
+ put_u8(bc_out.buf + jp1->pos, diff1);
+ break;
+ case 2:
+ put_u16(bc_out.buf + jp1->pos, diff1);
+ break;
+ case 4:
+ put_u32(bc_out.buf + jp1->pos, diff1);
+ break;
}
}
}
+
js_free(ctx, s->jump_slots);
s->jump_slots = NULL;
-#endif
js_free(ctx, s->label_slots);
s->label_slots = NULL;
/* XXX: should delay until copying to runtime bytecode function */
compute_pc2line_info(s);
- js_free(ctx, s->line_number_slots);
- s->line_number_slots = NULL;
+ js_free(ctx, s->source_loc_slots);
+ s->source_loc_slots = NULL;
/* set the new byte code */
dbuf_free(&s->byte_code);
s->byte_code = bc_out;
- s->use_short_opcodes = TRUE;
+ s->use_short_opcodes = true;
if (dbuf_error(&s->byte_code)) {
JS_ThrowOutOfMemory(ctx);
return -1;
@@ -33173,8 +31979,7 @@ static __exception int compute_stack_size(JSContext *ctx,
for(i = 0; i < s->bc_len; i++)
s->stack_level_tab[i] = 0xffff;
s->pc_stack = NULL;
- s->catch_pos_tab = js_malloc(ctx, sizeof(s->catch_pos_tab[0]) *
- s->bc_len);
+ s->catch_pos_tab = js_malloc(ctx, sizeof(s->catch_pos_tab[0]) * s->bc_len);
if (!s->catch_pos_tab)
goto fail;
@@ -33196,8 +32001,9 @@ static __exception int compute_stack_size(JSContext *ctx,
goto fail;
}
oi = &short_opcode_info(op);
-#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 64)
- printf("%5d: %10s %5d %5d\n", pos, oi->name, stack_len, catch_pos);
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_STACK
+ if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_STACK))
+ printf("%5d: %10s %5d %5d\n", pos, oi->name, stack_len, catch_pos);
#endif
pos_next = pos + oi->size;
if (pos_next > s->bc_len) {
@@ -33208,12 +32014,8 @@ static __exception int compute_stack_size(JSContext *ctx,
/* call pops a variable number of arguments */
if (oi->fmt == OP_FMT_npop || oi->fmt == OP_FMT_npop_u16) {
n_pop += get_u16(bc_buf + pos + 1);
- } else {
-#if SHORT_OPCODES
- if (oi->fmt == OP_FMT_npopx) {
- n_pop += op - OP_call0;
- }
-#endif
+ } else if (oi->fmt == OP_FMT_npopx) {
+ n_pop += op - OP_call0;
}
if (stack_len < n_pop) {
@@ -33242,7 +32044,6 @@ static __exception int compute_stack_size(JSContext *ctx,
diff = get_u32(bc_buf + pos + 1);
pos_next = pos + 1 + diff;
break;
-#if SHORT_OPCODES
case OP_goto16:
diff = (int16_t)get_u16(bc_buf + pos + 1);
pos_next = pos + 1 + diff;
@@ -33257,7 +32058,6 @@ static __exception int compute_stack_size(JSContext *ctx,
if (ss_check(ctx, s, pos + 1 + diff, op, stack_len, catch_pos))
goto fail;
break;
-#endif
case OP_if_true:
case OP_if_false:
diff = get_u32(bc_buf + pos + 1);
@@ -33369,8 +32169,8 @@ static int add_module_variables(JSContext *ctx, JSFunctionDef *fd)
for(i = 0; i < fd->global_var_count; i++) {
hf = &fd->global_vars[i];
- if (add_closure_var(ctx, fd, TRUE, FALSE, i, hf->var_name, hf->is_const,
- hf->is_lexical, FALSE) < 0)
+ if (add_closure_var(ctx, fd, true, false, i, hf->var_name, hf->is_const,
+ hf->is_lexical, JS_VAR_NORMAL) < 0)
return -1;
}
@@ -33380,6 +32180,7 @@ static int add_module_variables(JSContext *ctx, JSFunctionDef *fd)
if (me->export_type == JS_EXPORT_TYPE_LOCAL) {
idx = find_closure_var(ctx, fd, me->local_name);
if (idx < 0) {
+ // XXX: add_module_variables() should take JSParseState *s and use js_parse_error_atom
JS_ThrowSyntaxErrorAtom(ctx, "exported variable '%s' does not exist",
me->local_name);
return -1;
@@ -33456,14 +32257,14 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
fd->cpool[cpool_idx] = func_obj;
}
-#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 4)
- if (!(fd->js_mode & JS_MODE_STRIP)) {
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_PASS1
+ if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_PASS1)) {
printf("pass 1\n");
dump_byte_code(ctx, 1, fd->byte_code.buf, fd->byte_code.size,
fd->args, fd->arg_count, fd->vars, fd->var_count,
fd->closure_var, fd->closure_var_count,
fd->cpool, fd->cpool_count, fd->source, fd->line_num,
- fd->label_slots, NULL);
+ fd->label_slots, NULL, 0);
printf("\n");
}
#endif
@@ -33471,14 +32272,14 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
if (resolve_variables(ctx, fd))
goto fail;
-#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 2)
- if (!(fd->js_mode & JS_MODE_STRIP)) {
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_PASS2
+ if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_PASS2)) {
printf("pass 2\n");
dump_byte_code(ctx, 2, fd->byte_code.buf, fd->byte_code.size,
fd->args, fd->arg_count, fd->vars, fd->var_count,
fd->closure_var, fd->closure_var_count,
fd->cpool, fd->cpool_count, fd->source, fd->line_num,
- fd->label_slots, NULL);
+ fd->label_slots, NULL, 0);
printf("\n");
}
#endif
@@ -33489,17 +32290,11 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
if (compute_stack_size(ctx, fd, &stack_size) < 0)
goto fail;
- if (fd->js_mode & JS_MODE_STRIP) {
- function_size = offsetof(JSFunctionBytecode, debug);
- } else {
- function_size = sizeof(*b);
- }
+ function_size = sizeof(*b);
cpool_offset = function_size;
function_size += fd->cpool_count * sizeof(*fd->cpool);
vardefs_offset = function_size;
- if (!(fd->js_mode & JS_MODE_STRIP) || fd->has_eval_call) {
- function_size += (fd->arg_count + fd->var_count) * sizeof(*b->vardefs);
- }
+ function_size += (fd->arg_count + fd->var_count) * sizeof(*b->vardefs);
closure_var_offset = function_size;
function_size += fd->closure_var_count * sizeof(*fd->closure_var);
byte_code_offset = function_size;
@@ -33518,29 +32313,17 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->func_name = fd->func_name;
if (fd->arg_count + fd->var_count > 0) {
- if ((fd->js_mode & JS_MODE_STRIP) && !fd->has_eval_call) {
- /* Strip variable definitions not needed at runtime */
- int i;
- for(i = 0; i < fd->var_count; i++) {
- JS_FreeAtom(ctx, fd->vars[i].var_name);
- }
- for(i = 0; i < fd->arg_count; i++) {
- JS_FreeAtom(ctx, fd->args[i].var_name);
- }
- for(i = 0; i < fd->closure_var_count; i++) {
- JS_FreeAtom(ctx, fd->closure_var[i].var_name);
- fd->closure_var[i].var_name = JS_ATOM_NULL;
- }
- } else {
- b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
- memcpy_no_ub(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));
- memcpy_no_ub(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));
- }
+ b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
+ if (fd->arg_count > 0)
+ memcpy(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));
+ if (fd->var_count > 0)
+ memcpy(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));
b->var_count = fd->var_count;
b->arg_count = fd->arg_count;
b->defined_arg_count = fd->defined_arg_count;
js_free(ctx, fd->args);
js_free(ctx, fd->vars);
+ js_free(ctx, fd->vars_htab);
}
b->cpool_count = fd->cpool_count;
if (b->cpool_count) {
@@ -33552,27 +32335,20 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->stack_size = stack_size;
- if (fd->js_mode & JS_MODE_STRIP) {
- JS_FreeAtom(ctx, fd->filename);
- dbuf_free(&fd->pc2line); // probably useless
- } else {
- /* XXX: source and pc2line info should be packed at the end of the
- JSFunctionBytecode structure, avoiding allocation overhead
- */
- b->has_debug = 1;
- b->debug.filename = fd->filename;
- b->debug.line_num = fd->line_num;
-
- //DynBuf pc2line;
- //compute_pc2line_info(fd, &pc2line);
- //js_free(ctx, fd->line_number_slots)
- b->debug.pc2line_buf = js_realloc(ctx, fd->pc2line.buf, fd->pc2line.size);
- if (!b->debug.pc2line_buf)
- b->debug.pc2line_buf = fd->pc2line.buf;
- b->debug.pc2line_len = fd->pc2line.size;
- b->debug.source = fd->source;
- b->debug.source_len = fd->source_len;
- }
+ /* XXX: source and pc2line info should be packed at the end of the
+ JSFunctionBytecode structure, avoiding allocation overhead
+ */
+ b->filename = fd->filename;
+ b->line_num = fd->line_num;
+ b->col_num = fd->col_num;
+
+ b->pc2line_buf = js_realloc(ctx, fd->pc2line.buf, fd->pc2line.size);
+ if (!b->pc2line_buf)
+ b->pc2line_buf = fd->pc2line.buf;
+ b->pc2line_len = fd->pc2line.size;
+ b->source = fd->source;
+ b->source_len = fd->source_len;
+
if (fd->scopes != fd->def_scope_array)
js_free(ctx, fd->scopes);
@@ -33586,7 +32362,7 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->has_prototype = fd->has_prototype;
b->has_simple_parameter_list = fd->has_simple_parameter_list;
- b->js_mode = fd->js_mode;
+ b->is_strict_mode = fd->is_strict_mode;
b->is_derived_class_constructor = fd->is_derived_class_constructor;
b->func_kind = fd->func_kind;
b->need_home_object = (fd->home_object_var_idx >= 0 ||
@@ -33596,16 +32372,13 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->super_allowed = fd->super_allowed;
b->arguments_allowed = fd->arguments_allowed;
b->backtrace_barrier = fd->backtrace_barrier;
- b->is_direct_or_indirect_eval = (fd->eval_type == JS_EVAL_TYPE_DIRECT ||
- fd->eval_type == JS_EVAL_TYPE_INDIRECT);
b->realm = JS_DupContext(ctx);
add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
-#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 1)
- if (!(fd->js_mode & JS_MODE_STRIP)) {
+#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_FINAL
+ if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_FINAL))
js_dump_function_bytecode(ctx, b);
- }
#endif
if (fd->parent) {
@@ -33624,14 +32397,7 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b)
{
int i;
-#if 0
- {
- char buf[ATOM_GET_STR_BUF_SIZE];
- printf("freeing %s\n",
- JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));
- }
-#endif
- free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len, TRUE);
+ free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len, true);
if (b->vardefs) {
for(i = 0; i < b->arg_count + b->var_count; i++) {
@@ -33649,11 +32415,9 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b)
JS_FreeContext(b->realm);
JS_FreeAtomRT(rt, b->func_name);
- if (b->has_debug) {
- JS_FreeAtomRT(rt, b->debug.filename);
- js_free_rt(rt, b->debug.pc2line_buf);
- js_free_rt(rt, b->debug.source);
- }
+ JS_FreeAtomRT(rt, b->filename);
+ js_free_rt(rt, b->pc2line_buf);
+ js_free_rt(rt, b->source);
remove_gc_object(&b->header);
if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && b->header.ref_count != 0) {
@@ -33667,7 +32431,7 @@ static __exception int js_parse_directives(JSParseState *s)
{
char str[20];
JSParsePos pos;
- BOOL has_semi;
+ bool has_semi;
if (s->token.val != TOK_STRING)
return 0;
@@ -33682,16 +32446,16 @@ static __exception int js_parse_directives(JSParseState *s)
if (next_token(s))
return -1;
- has_semi = FALSE;
+ has_semi = false;
switch (s->token.val) {
case ';':
if (next_token(s))
return -1;
- has_semi = TRUE;
+ has_semi = true;
break;
case '}':
case TOK_EOF:
- has_semi = TRUE;
+ has_semi = true;
break;
case TOK_NUMBER:
case TOK_STRING:
@@ -33734,7 +32498,7 @@ static __exception int js_parse_directives(JSParseState *s)
case TOK_STATIC:
/* automatic insertion of ';' */
if (s->got_lf)
- has_semi = TRUE;
+ has_semi = true;
break;
default:
break;
@@ -33742,46 +32506,54 @@ static __exception int js_parse_directives(JSParseState *s)
if (!has_semi)
break;
if (!strcmp(str, "use strict")) {
- s->cur_func->has_use_strict = TRUE;
- s->cur_func->js_mode |= JS_MODE_STRICT;
- }
-#if !defined(DUMP_BYTECODE) || !(DUMP_BYTECODE & 8)
- else if (!strcmp(str, "use strip")) {
- s->cur_func->js_mode |= JS_MODE_STRIP;
+ s->cur_func->has_use_strict = true;
+ s->cur_func->is_strict_mode = true;
}
-#endif
-#ifdef CONFIG_BIGNUM
- else if (s->ctx->bignum_ext && !strcmp(str, "use math")) {
- s->cur_func->js_mode |= JS_MODE_MATH;
- }
-#endif
}
return js_parse_seek_token(s, &pos);
}
+static bool js_invalid_strict_name(JSAtom name) {
+ switch (name) {
+ case JS_ATOM_eval:
+ case JS_ATOM_arguments:
+ case JS_ATOM_implements: // future strict reserved words
+ case JS_ATOM_interface:
+ case JS_ATOM_let:
+ case JS_ATOM_package:
+ case JS_ATOM_private:
+ case JS_ATOM_protected:
+ case JS_ATOM_public:
+ case JS_ATOM_static:
+ case JS_ATOM_yield:
+ return true;
+ default:
+ return false;
+ }
+}
+
static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,
JSAtom func_name)
{
JSAtom name;
int i, idx;
- if (fd->js_mode & JS_MODE_STRICT) {
+ if (fd->is_strict_mode) {
if (!fd->has_simple_parameter_list && fd->has_use_strict) {
return js_parse_error(s, "\"use strict\" not allowed in function with default or destructuring parameter");
}
- if (func_name == JS_ATOM_eval || func_name == JS_ATOM_arguments) {
+ if (js_invalid_strict_name(func_name)) {
return js_parse_error(s, "invalid function name in strict code");
}
for (idx = 0; idx < fd->arg_count; idx++) {
name = fd->args[idx].var_name;
-
- if (name == JS_ATOM_eval || name == JS_ATOM_arguments) {
+ if (js_invalid_strict_name(name)) {
return js_parse_error(s, "invalid argument name in strict code");
}
}
}
/* check async_generator case */
- if ((fd->js_mode & JS_MODE_STRICT)
+ if (fd->is_strict_mode
|| !fd->has_simple_parameter_list
|| (fd->func_type == JS_PARSE_FUNC_METHOD && fd->func_kind == JS_FUNC_ASYNC)
|| fd->func_type == JS_PARSE_FUNC_ARROW
@@ -33806,7 +32578,7 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,
return 0;
duplicate:
- return js_parse_error(s, "duplicate argument names not allowed in this context");
+ return js_parse_error(s, "Duplicate parameter name not allowed in this context");
}
/* create a function to initialize class fields */
@@ -33814,21 +32586,21 @@ static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s)
{
JSFunctionDef *fd;
- fd = js_new_function_def(s->ctx, s->cur_func, FALSE, FALSE,
- s->filename, 0);
+ fd = js_new_function_def(s->ctx, s->cur_func, false, false,
+ s->filename, 0, 0);
if (!fd)
return NULL;
fd->func_name = JS_ATOM_NULL;
- fd->has_prototype = FALSE;
- fd->has_home_object = TRUE;
-
- fd->has_arguments_binding = FALSE;
- fd->has_this_binding = TRUE;
- fd->is_derived_class_constructor = FALSE;
- fd->new_target_allowed = TRUE;
- fd->super_call_allowed = FALSE;
+ fd->has_prototype = false;
+ fd->has_home_object = true;
+
+ fd->has_arguments_binding = false;
+ fd->has_this_binding = true;
+ fd->is_derived_class_constructor = false;
+ fd->new_target_allowed = true;
+ fd->super_call_allowed = false;
fd->super_allowed = fd->has_home_object;
- fd->arguments_allowed = FALSE;
+ fd->arguments_allowed = false;
fd->func_kind = JS_FUNC_NORMAL;
fd->func_type = JS_PARSE_FUNC_METHOD;
@@ -33843,15 +32615,16 @@ static __exception int js_parse_function_decl2(JSParseState *s,
JSAtom func_name,
const uint8_t *ptr,
int function_line_num,
+ int function_col_num,
JSParseExportEnum export_flag,
JSFunctionDef **pfd)
{
JSContext *ctx = s->ctx;
JSFunctionDef *fd = s->cur_func;
- BOOL is_expr;
+ bool is_expr;
int func_idx, lexical_func_idx = -1;
- BOOL has_opt_arg;
- BOOL create_func_var = FALSE;
+ bool has_opt_arg;
+ bool create_func_var = false;
is_expr = (func_type != JS_PARSE_FUNC_STATEMENT &&
func_type != JS_PARSE_FUNC_VAR);
@@ -33861,7 +32634,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
func_type == JS_PARSE_FUNC_EXPR) {
if (func_kind == JS_FUNC_NORMAL &&
token_is_pseudo_keyword(s, JS_ATOM_async) &&
- peek_token(s, TRUE) != '\n') {
+ peek_token(s, true) != '\n') {
if (next_token(s))
return -1;
func_kind = JS_FUNC_ASYNC;
@@ -33887,7 +32660,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
}
}
if (s->token.val == TOK_IDENT ||
- (((s->token.val == TOK_YIELD && !(fd->js_mode & JS_MODE_STRICT)) ||
+ (((s->token.val == TOK_YIELD && !fd->is_strict_mode) ||
(s->token.val == TOK_AWAIT && !s->is_module)) &&
func_type == JS_PARSE_FUNC_EXPR)) {
func_name = JS_DupAtom(ctx, s->token.u.ident.atom);
@@ -33918,12 +32691,12 @@ static __exception int js_parse_function_decl2(JSParseState *s,
}
if (func_type == JS_PARSE_FUNC_VAR) {
- if (!(fd->js_mode & JS_MODE_STRICT)
+ if (!fd->is_strict_mode
&& func_kind == JS_FUNC_NORMAL
- && find_lexical_decl(ctx, fd, func_name, fd->scope_first, FALSE) < 0
+ && find_lexical_decl(ctx, fd, func_name, fd->scope_first, false) < 0
&& !((func_idx = find_var(ctx, fd, func_name)) >= 0 && (func_idx & ARGUMENT_VAR_OFFSET))
&& !(func_name == JS_ATOM_arguments && fd->has_arguments_binding)) {
- create_func_var = TRUE;
+ create_func_var = true;
}
/* Create the lexical name here so that the function closure
contains it */
@@ -33956,8 +32729,8 @@ static __exception int js_parse_function_decl2(JSParseState *s,
}
}
- fd = js_new_function_def(ctx, fd, FALSE, is_expr,
- s->filename, function_line_num);
+ fd = js_new_function_def(ctx, fd, false, is_expr, s->filename,
+ function_line_num, function_col_num);
if (!fd) {
JS_FreeAtom(ctx, func_name);
return -1;
@@ -33986,18 +32759,18 @@ static __exception int js_parse_function_decl2(JSParseState *s,
fd->super_allowed = fd->parent->super_allowed;
fd->arguments_allowed = fd->parent->arguments_allowed;
} else if (func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) {
- fd->new_target_allowed = TRUE; // although new.target === undefined
- fd->super_call_allowed = FALSE;
- fd->super_allowed = TRUE;
- fd->arguments_allowed = FALSE;
+ fd->new_target_allowed = true; // although new.target === undefined
+ fd->super_call_allowed = false;
+ fd->super_allowed = true;
+ fd->arguments_allowed = false;
} else {
- fd->new_target_allowed = TRUE;
+ fd->new_target_allowed = true;
fd->super_call_allowed = fd->is_derived_class_constructor;
fd->super_allowed = fd->has_home_object;
- fd->arguments_allowed = TRUE;
+ fd->arguments_allowed = true;
}
- /* fd->in_function_body == FALSE prevents yield/await during the parsing
+ /* fd->in_function_body == false prevents yield/await during the parsing
of the arguments in generator/async functions. They are parsed as
regular identifiers for other function kinds. */
fd->func_kind = func_kind;
@@ -34014,9 +32787,9 @@ static __exception int js_parse_function_decl2(JSParseState *s,
}
/* parse arguments */
- fd->has_simple_parameter_list = TRUE;
- fd->has_parameter_expressions = FALSE;
- has_opt_arg = FALSE;
+ fd->has_simple_parameter_list = true;
+ fd->has_parameter_expressions = false;
+ has_opt_arg = false;
if (func_type == JS_PARSE_FUNC_ARROW && s->token.val == TOK_IDENT) {
JSAtom name;
if (s->token.u.ident.is_reserved) {
@@ -34032,9 +32805,9 @@ static __exception int js_parse_function_decl2(JSParseState *s,
int skip_bits;
/* if there is an '=' inside the parameter list, we
consider there is a parameter expression inside */
- js_parse_skip_parens_token(s, &skip_bits, FALSE);
+ js_parse_skip_parens_token(s, &skip_bits, false);
if (skip_bits & SKIP_HAS_ASSIGNMENT)
- fd->has_parameter_expressions = TRUE;
+ fd->has_parameter_expressions = true;
if (next_token(s))
goto fail;
} else {
@@ -34050,17 +32823,17 @@ static __exception int js_parse_function_decl2(JSParseState *s,
while (s->token.val != ')') {
JSAtom name;
- BOOL rest = FALSE;
+ bool rest = false;
int idx, has_initializer;
if (s->token.val == TOK_ELLIPSIS) {
- fd->has_simple_parameter_list = FALSE;
- rest = TRUE;
+ fd->has_simple_parameter_list = false;
+ rest = true;
if (next_token(s))
goto fail;
}
if (s->token.val == '[' || s->token.val == '{') {
- fd->has_simple_parameter_list = FALSE;
+ fd->has_simple_parameter_list = false;
if (rest) {
emit_op(s, OP_rest);
emit_u16(s, fd->arg_count);
@@ -34070,11 +32843,11 @@ static __exception int js_parse_function_decl2(JSParseState *s,
emit_op(s, OP_get_arg);
emit_u16(s, idx);
}
- has_initializer = js_parse_destructuring_element(s, fd->has_parameter_expressions ? TOK_LET : TOK_VAR, 1, TRUE, -1, TRUE);
+ has_initializer = js_parse_destructuring_element(s, fd->has_parameter_expressions ? TOK_LET : TOK_VAR, true, true, -1, true, false);
if (has_initializer < 0)
goto fail;
if (has_initializer)
- has_opt_arg = TRUE;
+ has_opt_arg = true;
if (!has_opt_arg)
fd->defined_arg_count++;
} else if (s->token.val == TOK_IDENT) {
@@ -34110,13 +32883,13 @@ static __exception int js_parse_function_decl2(JSParseState *s,
}
emit_op(s, OP_put_arg);
emit_u16(s, idx);
- fd->has_simple_parameter_list = FALSE;
- has_opt_arg = TRUE;
+ fd->has_simple_parameter_list = false;
+ has_opt_arg = true;
} else if (s->token.val == '=') {
int label;
- fd->has_simple_parameter_list = FALSE;
- has_opt_arg = TRUE;
+ fd->has_simple_parameter_list = false;
+ has_opt_arg = true;
if (next_token(s))
goto fail;
@@ -34217,7 +32990,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
/* in generators, yield expression is forbidden during the parsing
of the arguments */
- fd->in_function_body = TRUE;
+ fd->in_function_body = true;
push_scope(s); /* enter body scope */
fd->body_scope = fd->scope_level;
@@ -34237,23 +33010,22 @@ static __exception int js_parse_function_decl2(JSParseState *s,
else
emit_op(s, OP_return);
- if (!(fd->js_mode & JS_MODE_STRIP)) {
- /* save the function source code */
- /* the end of the function source code is after the last
- token of the function source stored into s->last_ptr */
- fd->source_len = s->last_ptr - ptr;
- fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len);
- if (!fd->source)
- goto fail;
- }
+ /* save the function source code */
+ /* the end of the function source code is after the last
+ token of the function source stored into s->last_ptr */
+ fd->source_len = s->last_ptr - ptr;
+ fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len);
+ if (!fd->source)
+ goto fail;
+
goto done;
}
}
- if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) {
+ // js_parse_class() already consumed the '{'
+ if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT)
if (js_parse_expect(s, '{'))
goto fail;
- }
if (js_parse_directives(s))
goto fail;
@@ -34266,13 +33038,12 @@ static __exception int js_parse_function_decl2(JSParseState *s,
if (js_parse_source_element(s))
goto fail;
}
- if (!(fd->js_mode & JS_MODE_STRIP)) {
- /* save the function source code */
- fd->source_len = s->buf_ptr - ptr;
- fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len);
- if (!fd->source)
- goto fail;
- }
+
+ /* save the function source code */
+ fd->source_len = s->buf_ptr - ptr;
+ fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len);
+ if (!fd->source)
+ goto fail;
if (next_token(s)) {
/* consume the '}' */
@@ -34281,9 +33052,9 @@ static __exception int js_parse_function_decl2(JSParseState *s,
/* in case there is no return, add one */
if (js_is_live_code(s)) {
- emit_return(s, FALSE);
+ emit_return(s, false);
}
- done:
+done:
s->cur_func = fd->parent;
/* Reparse identifiers after the function is terminated so that
@@ -34329,7 +33100,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
(needed for annex B.3.3.4 and B.3.3.5
checks) */
hf->scope_level = 0;
- hf->force_init = ((s->cur_func->js_mode & JS_MODE_STRICT) != 0);
+ hf->force_init = s->cur_func->is_strict_mode;
/* store directly into global var, bypass lexical scope */
emit_op(s, OP_dup);
emit_op(s, OP_scope_put_var);
@@ -34407,11 +33178,12 @@ static __exception int js_parse_function_decl(JSParseState *s,
JSFunctionKindEnum func_kind,
JSAtom func_name,
const uint8_t *ptr,
- int function_line_num)
+ int start_line,
+ int start_col)
{
return js_parse_function_decl2(s, func_type, func_kind, func_name, ptr,
- function_line_num, JS_PARSE_EXPORT_NONE,
- NULL);
+ start_line, start_col,
+ JS_PARSE_EXPORT_NONE, NULL);
}
static __exception int js_parse_program(JSParseState *s)
@@ -34427,7 +33199,7 @@ static __exception int js_parse_program(JSParseState *s)
fd->is_global_var = (fd->eval_type == JS_EVAL_TYPE_GLOBAL) ||
(fd->eval_type == JS_EVAL_TYPE_MODULE) ||
- !(fd->js_mode & JS_MODE_STRICT);
+ !fd->is_strict_mode;
if (!s->is_module) {
/* hidden variable for the return value */
@@ -34458,9 +33230,9 @@ static __exception int js_parse_program(JSParseState *s)
emit_op(s, OP_get_loc);
emit_u16(s, fd->eval_ret_idx);
}
- emit_return(s, TRUE);
+ emit_return(s, true);
} else {
- emit_return(s, FALSE);
+ emit_return(s, false);
}
return 0;
@@ -34474,14 +33246,18 @@ static void js_parse_init(JSContext *ctx, JSParseState *s,
s->ctx = ctx;
s->filename = filename;
s->line_num = line;
- s->buf_ptr = (const uint8_t *)input;
+ s->col_num = 1;
+ s->buf_start = s->buf_ptr = (const uint8_t *)input;
s->buf_end = s->buf_ptr + input_len;
+ s->mark = s->buf_ptr + min_int(1, input_len);
+ s->eol = s->buf_ptr;
s->token.val = ' ';
s->token.line_num = 1;
+ s->token.col_num = 1;
}
static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj,
- JSValueConst this_obj,
+ JSValue this_obj,
JSVarRef **var_refs, JSStackFrame *sf)
{
JSValue ret_val;
@@ -34518,18 +33294,20 @@ JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj)
}
/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
-static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
+/* `export_name` and `input` may be pure ASCII or UTF-8 encoded */
+static JSValue __JS_EvalInternal(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
const char *filename, int line, int flags, int scope_idx)
{
JSParseState s1, *s = &s1;
- int err, js_mode, eval_type;
+ int err, eval_type;
JSValue fun_obj, ret_val;
JSStackFrame *sf;
JSVarRef **var_refs;
JSFunctionBytecode *b;
JSFunctionDef *fd;
JSModuleDef *m;
+ bool is_strict_mode;
js_parse_init(ctx, s, input, input_len, filename, line);
skip_shebang(&s->buf_ptr, s->buf_end);
@@ -34545,16 +33323,12 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
assert(js_class_has_bytecode(p->class_id));
b = p->u.func.function_bytecode;
var_refs = p->u.func.var_refs;
- js_mode = b->js_mode;
+ is_strict_mode = b->is_strict_mode;
} else {
sf = NULL;
b = NULL;
var_refs = NULL;
- js_mode = 0;
- if (flags & JS_EVAL_FLAG_STRICT)
- js_mode |= JS_MODE_STRICT;
- if (flags & JS_EVAL_FLAG_STRIP)
- js_mode |= JS_MODE_STRIP;
+ is_strict_mode = (flags & JS_EVAL_FLAG_STRICT) != 0;
if (eval_type == JS_EVAL_TYPE_MODULE) {
JSAtom module_name = JS_NewAtom(ctx, filename);
if (module_name == JS_ATOM_NULL)
@@ -34562,10 +33336,10 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
m = js_new_module_def(ctx, module_name);
if (!m)
return JS_EXCEPTION;
- js_mode |= JS_MODE_STRICT;
+ is_strict_mode = true;
}
}
- fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, line);
+ fd = js_new_function_def(ctx, NULL, true, false, filename, line, 1);
if (!fd)
goto fail1;
s->cur_func = fd;
@@ -34578,12 +33352,12 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
fd->super_allowed = b->super_allowed;
fd->arguments_allowed = b->arguments_allowed;
} else {
- fd->new_target_allowed = FALSE;
- fd->super_call_allowed = FALSE;
- fd->super_allowed = FALSE;
- fd->arguments_allowed = TRUE;
+ fd->new_target_allowed = false;
+ fd->super_call_allowed = false;
+ fd->super_allowed = false;
+ fd->arguments_allowed = true;
}
- fd->js_mode = js_mode;
+ fd->is_strict_mode = is_strict_mode;
fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_);
if (b) {
if (add_closure_variables(ctx, fd, b, scope_idx))
@@ -34591,7 +33365,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
}
fd->module = m;
if (m != NULL || (flags & JS_EVAL_FLAG_ASYNC)) {
- fd->in_function_body = TRUE;
+ fd->in_function_body = true;
fd->func_kind = JS_FUNC_ASYNC;
}
s->is_module = (m != NULL);
@@ -34636,26 +33410,32 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
}
/* the indirection is needed to make 'eval' optional */
-static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
+static JSValue JS_EvalInternal(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
const char *filename, int line, int flags, int scope_idx)
{
+ JSRuntime *rt = ctx->rt;
+
if (unlikely(!ctx->eval_internal)) {
return JS_ThrowTypeError(ctx, "eval is not supported");
}
+ if (!rt->current_stack_frame) {
+ JS_FreeValueRT(rt, ctx->error_back_trace);
+ ctx->error_back_trace = JS_UNDEFINED;
+ }
return ctx->eval_internal(ctx, this_obj, input, input_len, filename, line,
flags, scope_idx);
}
-static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
- JSValueConst val, int flags, int scope_idx)
+static JSValue JS_EvalObject(JSContext *ctx, JSValue this_obj,
+ JSValue val, int flags, int scope_idx)
{
JSValue ret;
const char *str;
size_t len;
if (!JS_IsString(val))
- return JS_DupValue(ctx, val);
+ return js_dup(val);
str = JS_ToCStringLen(ctx, &len, val);
if (!str)
return JS_EXCEPTION;
@@ -34665,15 +33445,38 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
}
-JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
+JSValue JS_EvalThis(JSContext *ctx, JSValue this_obj,
const char *input, size_t input_len,
- const char *filename, int line, int eval_flags)
+ const char *filename, int eval_flags)
{
- int eval_type = eval_flags & JS_EVAL_TYPE_MASK;
+ JSEvalOptions options = {
+ .version = JS_EVAL_OPTIONS_VERSION,
+ .filename = filename,
+ .line_num = 1,
+ .eval_flags = eval_flags
+ };
+ return JS_EvalThis2(ctx, this_obj, input, input_len, &options);
+}
+
+JSValue JS_EvalThis2(JSContext *ctx, JSValue this_obj,
+ const char *input, size_t input_len,
+ JSEvalOptions *options)
+{
+ const char *filename = "<unnamed>";
+ int line = 1;
+ int eval_flags = 0;
+ if (options) {
+ if (options->version != JS_EVAL_OPTIONS_VERSION)
+ return JS_ThrowInternalError(ctx, "bad JSEvalOptions version");
+ if (options->filename)
+ filename = options->filename;
+ line = options->line_num;
+ eval_flags = options->eval_flags;
+ }
JSValue ret;
- assert(eval_type == JS_EVAL_TYPE_GLOBAL ||
- eval_type == JS_EVAL_TYPE_MODULE);
+ assert((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_GLOBAL ||
+ (eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE);
ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename, line,
eval_flags, -1);
return ret;
@@ -34682,11 +33485,21 @@ JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
const char *filename, int eval_flags)
{
- return JS_EvalThis(ctx, ctx->global_obj, input, input_len, filename, 1,
- eval_flags);
+ JSEvalOptions options = {
+ .version = JS_EVAL_OPTIONS_VERSION,
+ .filename = filename,
+ .line_num = 1,
+ .eval_flags = eval_flags
+ };
+ return JS_EvalThis2(ctx, ctx->global_obj, input, input_len, &options);
}
-int JS_ResolveModule(JSContext *ctx, JSValueConst obj)
+JSValue JS_Eval2(JSContext *ctx, const char *input, size_t input_len, JSEvalOptions *options)
+{
+ return JS_EvalThis2(ctx, ctx->global_obj, input, input_len, options);
+}
+
+int JS_ResolveModule(JSContext *ctx, JSValue obj)
{
if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) {
JSModuleDef *m = JS_VALUE_GET_PTR(obj);
@@ -34822,27 +33635,25 @@ typedef enum BCTagEnum {
BC_TAG_TYPED_ARRAY,
BC_TAG_ARRAY_BUFFER,
BC_TAG_SHARED_ARRAY_BUFFER,
+ BC_TAG_REGEXP,
BC_TAG_DATE,
BC_TAG_OBJECT_VALUE,
BC_TAG_OBJECT_REFERENCE,
-#ifdef CONFIG_BIGNUM
- BC_TAG_BIG_FLOAT,
- BC_TAG_BIG_DECIMAL,
-#endif
+ BC_TAG_MAP,
+ BC_TAG_SET,
+ BC_TAG_SYMBOL,
} BCTagEnum;
-#ifdef CONFIG_BIGNUM
-#define BC_VERSION 0x43
-#else
-#define BC_VERSION 3
-#endif
+#define BC_VERSION 19
typedef struct BCWriterState {
JSContext *ctx;
DynBuf dbuf;
- BOOL allow_bytecode : 8;
- BOOL allow_sab : 8;
- BOOL allow_reference : 8;
+ bool allow_bytecode;
+ bool allow_sab;
+ bool allow_reference;
+ bool allow_source;
+ bool allow_debug;
uint32_t first_atom;
uint32_t *atom_to_idx;
int atom_to_idx_size;
@@ -34852,11 +33663,11 @@ typedef struct BCWriterState {
uint8_t **sab_tab;
int sab_tab_len;
int sab_tab_size;
- /* list of referenced objects (used if allow_reference = TRUE) */
+ /* list of referenced objects (used if allow_reference = true) */
JSObjectList object_list;
} BCWriterState;
-#ifdef DUMP_READ_OBJECT
+#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT
static const char * const bc_tag_str[] = {
"invalid",
"null",
@@ -34868,32 +33679,23 @@ static const char * const bc_tag_str[] = {
"string",
"object",
"array",
- "bigint",
+ "BigInt",
"template",
"function",
"module",
"TypedArray",
"ArrayBuffer",
"SharedArrayBuffer",
+ "RegExp",
"Date",
"ObjectValue",
"ObjectReference",
-#ifdef CONFIG_BIGNUM
- "bigfloat",
- "bigdecimal",
-#endif
+ "Map",
+ "Set",
+ "Symbol",
};
#endif
-static inline BOOL is_be(void)
-{
- union {
- uint16_t a;
- uint8_t b;
- } u = {0x100};
- return u.b;
-}
-
static void bc_put_u8(BCWriterState *s, uint8_t v)
{
dbuf_putc(&s->dbuf, v);
@@ -35052,17 +33854,18 @@ static void bc_byte_swap(uint8_t *bc_buf, int bc_len)
}
static int JS_WriteFunctionBytecode(BCWriterState *s,
- const uint8_t *bc_buf1, int bc_len)
+ const JSFunctionBytecode *b)
{
- int pos, len, op;
+ int pos, len, bc_len, op;
JSAtom atom;
uint8_t *bc_buf;
uint32_t val;
+ bc_len = b->byte_code_len;
bc_buf = js_malloc(s->ctx, bc_len);
if (!bc_buf)
return -1;
- memcpy(bc_buf, bc_buf1, bc_len);
+ memcpy(bc_buf, b->byte_code_buf, bc_len);
pos = 0;
while (pos < bc_len) {
@@ -35109,11 +33912,11 @@ static void JS_WriteString(BCWriterState *s, JSString *p)
}
}
-static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
+static int JS_WriteBigInt(BCWriterState *s, JSValue obj)
{
uint32_t tag, tag1;
int64_t e;
- JSBigFloat *bf = JS_VALUE_GET_PTR(obj);
+ JSBigInt *bf = JS_VALUE_GET_PTR(obj);
bf_t *a = &bf->num;
size_t len, i, n1, j;
limb_t v;
@@ -35123,14 +33926,6 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
case JS_TAG_BIG_INT:
tag1 = BC_TAG_BIG_INT;
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- tag1 = BC_TAG_BIG_FLOAT;
- break;
- case JS_TAG_BIG_DECIMAL:
- tag1 = BC_TAG_BIG_DECIMAL;
- break;
-#endif
default:
abort();
}
@@ -35149,100 +33944,49 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
e = a->expn;
e = (e * 2) | a->sign;
if (e < INT32_MIN || e > INT32_MAX) {
- JS_ThrowInternalError(s->ctx, "bignum exponent is too large");
+ JS_ThrowRangeError(s->ctx, "maximum BigInt size exceeded");
return -1;
}
bc_put_sleb128(s, e);
/* mantissa */
if (a->len != 0) {
- if (tag != JS_TAG_BIG_DECIMAL) {
- i = 0;
- while (i < a->len && a->tab[i] == 0)
- i++;
- assert(i < a->len);
- v = a->tab[i];
- n1 = sizeof(limb_t);
- while ((v & 0xff) == 0) {
- n1--;
- v >>= 8;
- }
+ i = 0;
+ while (i < a->len && a->tab[i] == 0)
i++;
- len = (a->len - i) * sizeof(limb_t) + n1;
- if (len > INT32_MAX) {
- JS_ThrowInternalError(s->ctx, "bignum is too large");
- return -1;
- }
- bc_put_leb128(s, len);
- /* always saved in byte based little endian representation */
- for(j = 0; j < n1; j++) {
- bc_put_u8(s, v >> (j * 8));
- }
- for(; i < a->len; i++) {
- limb_t v = a->tab[i];
+ assert(i < a->len);
+ v = a->tab[i];
+ n1 = sizeof(limb_t);
+ while ((v & 0xff) == 0) {
+ n1--;
+ v >>= 8;
+ }
+ i++;
+ len = (a->len - i) * sizeof(limb_t) + n1;
+ if (len > INT32_MAX) {
+ JS_ThrowRangeError(s->ctx, "maximum BigInt size exceeded");
+ return -1;
+ }
+ bc_put_leb128(s, len);
+ /* always saved in byte based little endian representation */
+ for(j = 0; j < n1; j++) {
+ bc_put_u8(s, v >> (j * 8));
+ }
+ for(; i < a->len; i++) {
+ limb_t v = a->tab[i];
#if LIMB_BITS == 32
- bc_put_u32(s, v);
+ bc_put_u32(s, v);
#else
- bc_put_u64(s, v);
+ bc_put_u64(s, v);
#endif
- }
- } else {
- int bpos, d;
- uint8_t v8;
- size_t i0;
-
- /* little endian BCD */
- i = 0;
- while (i < a->len && a->tab[i] == 0)
- i++;
- assert(i < a->len);
- len = a->len * LIMB_DIGITS;
- v = a->tab[i];
- j = 0;
- while ((v % 10) == 0) {
- j++;
- v /= 10;
- }
- len -= j;
- assert(len > 0);
- if (len > INT32_MAX) {
- JS_ThrowInternalError(s->ctx, "bignum is too large");
- return -1;
- }
- bc_put_leb128(s, len);
-
- bpos = 0;
- v8 = 0;
- i0 = i;
- for(; i < a->len; i++) {
- if (i != i0) {
- v = a->tab[i];
- j = 0;
- }
- for(; j < LIMB_DIGITS; j++) {
- d = v % 10;
- v /= 10;
- if (bpos == 0) {
- v8 = d;
- bpos = 1;
- } else {
- bc_put_u8(s, v8 | (d << 4));
- bpos = 0;
- }
- }
- }
- /* flush the last digit */
- if (bpos) {
- bc_put_u8(s, v8);
- }
}
}
return 0;
}
-static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj);
+static int JS_WriteObjectRec(BCWriterState *s, JSValue obj);
-static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
+static int JS_WriteFunctionTag(BCWriterState *s, JSValue obj)
{
JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj);
uint32_t flags;
@@ -35259,12 +34003,11 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
bc_set_flags(&flags, &idx, b->super_call_allowed, 1);
bc_set_flags(&flags, &idx, b->super_allowed, 1);
bc_set_flags(&flags, &idx, b->arguments_allowed, 1);
- bc_set_flags(&flags, &idx, b->has_debug, 1);
bc_set_flags(&flags, &idx, b->backtrace_barrier, 1);
- bc_set_flags(&flags, &idx, b->is_direct_or_indirect_eval, 1);
+ bc_set_flags(&flags, &idx, s->allow_debug, 1);
assert(idx <= 16);
bc_put_u16(s, flags);
- bc_put_u8(s, b->js_mode);
+ bc_put_u8(s, b->is_strict_mode);
bc_put_atom(s, b->func_name);
bc_put_leb128(s, b->arg_count);
@@ -35308,26 +34051,35 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
bc_put_u8(s, flags);
}
- if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len))
- goto fail;
-
- if (b->has_debug) {
- bc_put_atom(s, b->debug.filename);
- bc_put_leb128(s, b->debug.line_num);
- bc_put_leb128(s, b->debug.pc2line_len);
- dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len);
- }
-
+ // write constant pool before code so code can be disassembled
+ // on the fly at read time
for(i = 0; i < b->cpool_count; i++) {
if (JS_WriteObjectRec(s, b->cpool[i]))
goto fail;
}
+
+ if (JS_WriteFunctionBytecode(s, b))
+ goto fail;
+
+ if (s->allow_debug) {
+ bc_put_atom(s, b->filename);
+ bc_put_leb128(s, b->line_num);
+ bc_put_leb128(s, b->col_num);
+ bc_put_leb128(s, b->pc2line_len);
+ dbuf_put(&s->dbuf, b->pc2line_buf, b->pc2line_len);
+ if (s->allow_source && b->source) {
+ bc_put_leb128(s, b->source_len);
+ dbuf_put(&s->dbuf, b->source, b->source_len);
+ } else {
+ bc_put_leb128(s, 0);
+ }
+ }
return 0;
fail:
return -1;
}
-static int JS_WriteModule(BCWriterState *s, JSValueConst obj)
+static int JS_WriteModule(BCWriterState *s, JSValue obj)
{
JSModuleDef *m = JS_VALUE_GET_PTR(obj);
int i;
@@ -35377,22 +34129,22 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj)
return -1;
}
-static int JS_WriteArray(BCWriterState *s, JSValueConst obj)
+static int JS_WriteArray(BCWriterState *s, JSValue obj)
{
JSObject *p = JS_VALUE_GET_OBJ(obj);
uint32_t i, len;
JSValue val;
int ret;
- BOOL is_template;
+ bool is_template;
if (s->allow_bytecode && !p->extensible) {
/* not extensible array: we consider it is a
template when we are saving bytecode */
bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT);
- is_template = TRUE;
+ is_template = true;
} else {
bc_put_u8(s, BC_TAG_ARRAY);
- is_template = FALSE;
+ is_template = false;
}
if (js_get_length32(s->ctx, &len, obj))
goto fail1;
@@ -35420,7 +34172,7 @@ static int JS_WriteArray(BCWriterState *s, JSValueConst obj)
return -1;
}
-static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj)
+static int JS_WriteObjectTag(BCWriterState *s, JSValue obj)
{
JSObject *p = JS_VALUE_GET_OBJ(obj);
uint32_t i, prop_count;
@@ -35437,9 +34189,7 @@ static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj)
bc_put_leb128(s, prop_count);
for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) {
atom = pr->atom;
- if (atom != JS_ATOM_NULL &&
- JS_AtomIsString(s->ctx, atom) &&
- (pr->flags & JS_PROP_ENUMERABLE)) {
+ if (atom != JS_ATOM_NULL && (pr->flags & JS_PROP_ENUMERABLE)) {
if (pr->flags & JS_PROP_TMASK) {
JS_ThrowTypeError(s->ctx, "only value properties are supported");
goto fail;
@@ -35459,7 +34209,7 @@ static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj)
return -1;
}
-static int JS_WriteTypedArray(BCWriterState *s, JSValueConst obj)
+static int JS_WriteTypedArray(BCWriterState *s, JSValue obj)
{
JSObject *p = JS_VALUE_GET_OBJ(obj);
JSTypedArray *ta = p->u.typed_array;
@@ -35473,7 +34223,7 @@ static int JS_WriteTypedArray(BCWriterState *s, JSValueConst obj)
return 0;
}
-static int JS_WriteArrayBuffer(BCWriterState *s, JSValueConst obj)
+static int JS_WriteArrayBuffer(BCWriterState *s, JSValue obj)
{
JSObject *p = JS_VALUE_GET_OBJ(obj);
JSArrayBuffer *abuf = p->u.array_buffer;
@@ -35483,17 +34233,19 @@ static int JS_WriteArrayBuffer(BCWriterState *s, JSValueConst obj)
}
bc_put_u8(s, BC_TAG_ARRAY_BUFFER);
bc_put_leb128(s, abuf->byte_length);
+ bc_put_leb128(s, abuf->max_byte_length);
dbuf_put(&s->dbuf, abuf->data, abuf->byte_length);
return 0;
}
-static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValueConst obj)
+static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValue obj)
{
JSObject *p = JS_VALUE_GET_OBJ(obj);
JSArrayBuffer *abuf = p->u.array_buffer;
assert(!abuf->detached); /* SharedArrayBuffer are never detached */
bc_put_u8(s, BC_TAG_SHARED_ARRAY_BUFFER);
bc_put_leb128(s, abuf->byte_length);
+ bc_put_leb128(s, abuf->max_byte_length);
bc_put_u64(s, (uintptr_t)abuf->data);
if (js_resize_array(s->ctx, (void **)&s->sab_tab, sizeof(s->sab_tab[0]),
&s->sab_tab_size, s->sab_tab_len + 1))
@@ -35503,7 +34255,28 @@ static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValueConst obj)
return 0;
}
-static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
+static int JS_WriteRegExp(BCWriterState *s, JSRegExp regexp)
+{
+ JSString *bc = regexp.bytecode;
+ assert(!bc->is_wide_char);
+
+ JS_WriteString(s, regexp.pattern);
+
+ if (is_be())
+ lre_byte_swap(bc->u.str8, bc->len, /*is_byte_swapped*/false);
+
+ JS_WriteString(s, bc);
+
+ if (is_be())
+ lre_byte_swap(bc->u.str8, bc->len, /*is_byte_swapped*/true);
+
+ return 0;
+}
+
+static int JS_WriteMap(BCWriterState *s, struct JSMapState *map_state);
+static int JS_WriteSet(BCWriterState *s, struct JSMapState *map_state);
+
+static int JS_WriteObjectRec(BCWriterState *s, JSValue obj)
{
uint32_t tag;
@@ -35591,6 +34364,10 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
goto invalid_tag;
ret = JS_WriteSharedArrayBuffer(s, obj);
break;
+ case JS_CLASS_REGEXP:
+ bc_put_u8(s, BC_TAG_REGEXP);
+ ret = JS_WriteRegExp(s, p->u.regexp);
+ break;
case JS_CLASS_DATE:
bc_put_u8(s, BC_TAG_DATE);
ret = JS_WriteObjectRec(s, p->u.object_data);
@@ -35599,16 +34376,19 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
case JS_CLASS_STRING:
case JS_CLASS_BOOLEAN:
case JS_CLASS_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_CLASS_BIG_FLOAT:
- case JS_CLASS_BIG_DECIMAL:
-#endif
bc_put_u8(s, BC_TAG_OBJECT_VALUE);
ret = JS_WriteObjectRec(s, p->u.object_data);
break;
+ case JS_CLASS_MAP:
+ bc_put_u8(s, BC_TAG_MAP);
+ ret = JS_WriteMap(s, p->u.map_state);
+ break;
+ case JS_CLASS_SET:
+ bc_put_u8(s, BC_TAG_SET);
+ ret = JS_WriteSet(s, p->u.map_state);
+ break;
default:
- if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
+ if (is_typed_array(p->class_id)) {
ret = JS_WriteTypedArray(s, obj);
} else {
JS_ThrowTypeError(s->ctx, "unsupported object class");
@@ -35622,13 +34402,21 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
}
break;
case JS_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- case JS_TAG_BIG_DECIMAL:
-#endif
- if (JS_WriteBigNum(s, obj))
+ if (JS_WriteBigInt(s, obj))
goto fail;
break;
+ case JS_TAG_SYMBOL:
+ {
+ JSAtomStruct *p = JS_VALUE_GET_PTR(obj);
+ if (p->atom_type != JS_ATOM_TYPE_GLOBAL_SYMBOL && p->atom_type != JS_ATOM_TYPE_SYMBOL) {
+ JS_ThrowTypeError(s->ctx, "unsupported symbol type");
+ goto fail;
+ }
+ JSAtom atom = js_get_atom_index(s->ctx->rt, p);
+ bc_put_u8(s, BC_TAG_SYMBOL);
+ bc_put_atom(s, atom);
+ }
+ break;
default:
invalid_tag:
JS_ThrowInternalError(s->ctx, "unsupported tag (%d)", tag);
@@ -35653,8 +34441,19 @@ static int JS_WriteObjectAtoms(BCWriterState *s)
bc_put_leb128(s, s->idx_to_atom_count);
for(i = 0; i < s->idx_to_atom_count; i++) {
- JSAtomStruct *p = rt->atom_array[s->idx_to_atom[i]];
- JS_WriteString(s, p);
+ JSAtom atom = s->idx_to_atom[i];
+ if (__JS_AtomIsConst(atom)) {
+ bc_put_u8(s, 0 /* the type */);
+ /* TODO(saghul): encoding for tagged integers and keyword-ish atoms could be
+ more efficient. */
+ bc_put_u32(s, atom);
+ } else {
+ JSAtomStruct *p = rt->atom_array[atom];
+ uint8_t type = p->atom_type;
+ assert(type != JS_ATOM_TYPE_PRIVATE);
+ bc_put_u8(s, type);
+ JS_WriteString(s, p);
+ }
}
/* XXX: should check for OOM in above phase */
@@ -35675,8 +34474,8 @@ static int JS_WriteObjectAtoms(BCWriterState *s)
return -1;
}
-uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
- int flags, uint8_t ***psab_tab, size_t *psab_tab_len)
+uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValue obj,
+ int flags, JSSABTab *psab_tab)
{
BCWriterState ss, *s = &ss;
@@ -35685,6 +34484,8 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0);
s->allow_sab = ((flags & JS_WRITE_OBJ_SAB) != 0);
s->allow_reference = ((flags & JS_WRITE_OBJ_REFERENCE) != 0);
+ s->allow_source = ((flags & JS_WRITE_OBJ_STRIP_SOURCE) == 0);
+ s->allow_debug = ((flags & JS_WRITE_OBJ_STRIP_DEBUG) == 0);
/* XXX: could use a different version when bytecode is included */
if (s->allow_bytecode)
s->first_atom = JS_ATOM_END;
@@ -35701,10 +34502,12 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
js_free(ctx, s->atom_to_idx);
js_free(ctx, s->idx_to_atom);
*psize = s->dbuf.size;
- if (psab_tab)
- *psab_tab = s->sab_tab;
- if (psab_tab_len)
- *psab_tab_len = s->sab_tab_len;
+ if (psab_tab) {
+ psab_tab->tab = s->sab_tab;
+ psab_tab->len = s->sab_tab_len;
+ } else {
+ js_free(ctx, s->sab_tab);
+ }
return s->dbuf.buf;
fail:
js_object_list_end(ctx, &s->object_list);
@@ -35712,17 +34515,17 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
js_free(ctx, s->idx_to_atom);
dbuf_free(&s->dbuf);
*psize = 0;
- if (psab_tab)
- *psab_tab = NULL;
- if (psab_tab_len)
- *psab_tab_len = 0;
+ if (psab_tab) {
+ psab_tab->tab = NULL;
+ psab_tab->len = 0;
+ }
return NULL;
}
-uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,
+uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValue obj,
int flags)
{
- return JS_WriteObject2(ctx, psize, obj, flags, NULL, NULL);
+ return JS_WriteObject2(ctx, psize, obj, flags, NULL);
}
typedef struct BCReaderState {
@@ -35732,26 +34535,30 @@ typedef struct BCReaderState {
uint32_t idx_to_atom_count;
JSAtom *idx_to_atom;
int error_state;
- BOOL allow_sab : 8;
- BOOL allow_bytecode : 8;
- BOOL is_rom_data : 8;
- BOOL allow_reference : 8;
+ bool allow_sab;
+ bool allow_bytecode;
+ bool allow_reference;
/* object references */
JSObject **objects;
int objects_count;
int objects_size;
-
-#ifdef DUMP_READ_OBJECT
+ /* SAB references */
+ uint8_t **sab_tab;
+ int sab_tab_len;
+ int sab_tab_size;
+ /* used for JS_DUMP_READ_OBJECT */
const uint8_t *ptr_last;
int level;
-#endif
} BCReaderState;
-#ifdef DUMP_READ_OBJECT
-static void FORMAT_ATTR(2, 3) bc_read_trace(BCReaderState *s, const char *fmt, ...) {
+#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT
+static void JS_PRINTF_FORMAT_ATTR(2, 3) bc_read_trace(BCReaderState *s, JS_PRINTF_FORMAT const char *fmt, ...) {
va_list ap;
int i, n, n0;
+ if (!check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT))
+ return;
+
if (!s->ptr_last)
s->ptr_last = s->buf_start;
@@ -35882,7 +34689,7 @@ static int bc_get_leb128_u16(BCReaderState *s, uint16_t *pval)
return 0;
}
-static int bc_get_buf(BCReaderState *s, uint8_t *buf, uint32_t buf_len)
+static int bc_get_buf(BCReaderState *s, void *buf, uint32_t buf_len)
{
if (buf_len != 0) {
if (unlikely(!buf || s->buf_end - s->ptr < buf_len))
@@ -35932,7 +34739,7 @@ static JSString *JS_ReadString(BCReaderState *s)
{
uint32_t len;
size_t size;
- BOOL is_wide_char;
+ bool is_wide_char;
JSString *p;
if (bc_get_leb128(s, &len))
@@ -35961,8 +34768,12 @@ static JSString *JS_ReadString(BCReaderState *s)
} else {
p->u.str8[size] = '\0'; /* add the trailing zero for 8 bit strings */
}
-#ifdef DUMP_READ_OBJECT
- JS_DumpString(s->ctx->rt, p); printf("\n");
+#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT
+ if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) {
+ bc_read_trace(s, "%s", ""); // hex dump and indentation
+ JS_DumpString(s->ctx->rt, p);
+ printf("\n");
+ }
#endif
return p;
}
@@ -35984,17 +34795,9 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,
JSAtom atom;
uint32_t idx;
- if (s->is_rom_data) {
- /* directly use the input buffer */
- if (unlikely(s->buf_end - s->ptr < bc_len))
- return bc_read_error_end(s);
- bc_buf = (uint8_t *)s->ptr;
- s->ptr += bc_len;
- } else {
- bc_buf = (void *)((uint8_t*)b + byte_code_offset);
- if (bc_get_buf(s, bc_buf, bc_len))
- return -1;
- }
+ bc_buf = (uint8_t*)b + byte_code_offset;
+ if (bc_get_buf(s, bc_buf, bc_len))
+ return -1;
b->byte_code_buf = bc_buf;
if (is_be())
@@ -36011,64 +34814,52 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,
case OP_FMT_atom_label_u8:
case OP_FMT_atom_label_u16:
idx = get_u32(bc_buf + pos + 1);
- if (s->is_rom_data) {
- /* just increment the reference count of the atom */
- JS_DupAtom(s->ctx, (JSAtom)idx);
- } else {
- if (bc_idx_to_atom(s, &atom, idx)) {
- /* Note: the atoms will be freed up to this position */
- b->byte_code_len = pos;
- return -1;
- }
- put_u32(bc_buf + pos + 1, atom);
-#ifdef DUMP_READ_OBJECT
- bc_read_trace(s, "at %d, fixup atom: ", pos + 1); print_atom(s->ctx, atom); printf("\n");
-#endif
+ if (bc_idx_to_atom(s, &atom, idx)) {
+ /* Note: the atoms will be freed up to this position */
+ b->byte_code_len = pos;
+ return -1;
}
+ put_u32(bc_buf + pos + 1, atom);
break;
default:
break;
}
+#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT
+ if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) {
+ const uint8_t *save_ptr = s->ptr;
+ s->ptr = s->ptr_last + len;
+ s->level -= 4;
+ bc_read_trace(s, "%s", ""); // hex dump + indent
+ dump_single_byte_code(s->ctx, bc_buf + pos, b,
+ s->ptr - s->buf_start - len);
+ s->level += 4;
+ s->ptr = save_ptr;
+ }
+#endif
pos += len;
}
return 0;
}
-static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
+static JSValue JS_ReadBigInt(BCReaderState *s)
{
- JSValue obj = JS_UNDEFINED;
+ JSValue obj;
uint8_t v8;
int32_t e;
uint32_t len;
limb_t l, i, n;
- JSBigFloat *p;
limb_t v;
bf_t *a;
- p = js_new_bf(s->ctx);
- if (!p)
+ obj = JS_NewBigInt(s->ctx);
+ if (JS_IsException(obj))
goto fail;
- switch(tag) {
- case BC_TAG_BIG_INT:
- obj = JS_MKPTR(JS_TAG_BIG_INT, p);
- break;
-#ifdef CONFIG_BIGNUM
- case BC_TAG_BIG_FLOAT:
- obj = JS_MKPTR(JS_TAG_BIG_FLOAT, p);
- break;
- case BC_TAG_BIG_DECIMAL:
- obj = JS_MKPTR(JS_TAG_BIG_DECIMAL, p);
- break;
-#endif
- default:
- abort();
- }
/* sign + exponent */
if (bc_get_sleb128(s, &e))
goto fail;
- a = &p->num;
+ a = JS_GetBigInt(obj);
a->sign = e & 1;
e >>= 1;
if (e == 0)
@@ -36090,81 +34881,38 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
goto fail;
bc_read_trace(s, "len=%" PRId64 "\n", (int64_t)len);
if (len == 0) {
- JS_ThrowInternalError(s->ctx, "invalid bignum length");
+ JS_ThrowRangeError(s->ctx, "maximum BigInt size exceeded");
goto fail;
}
-#ifdef CONFIG_BIGNUM
- if (tag == BC_TAG_BIG_DECIMAL) {
- l = (len + LIMB_DIGITS - 1) / LIMB_DIGITS;
- } else
-#endif
- {
- l = (len + sizeof(limb_t) - 1) / sizeof(limb_t);
- }
+ l = (len + sizeof(limb_t) - 1) / sizeof(limb_t);
if (bf_resize(a, l)) {
JS_ThrowOutOfMemory(s->ctx);
goto fail;
}
-#ifdef CONFIG_BIGNUM
- if (tag == BC_TAG_BIG_DECIMAL) {
- limb_t j;
- int bpos, d;
-
- bpos = 0;
- for(i = 0; i < l; i++) {
- if (i == 0 && (n = len % LIMB_DIGITS) != 0) {
- j = LIMB_DIGITS - n;
- } else {
- j = 0;
- }
- v = 0;
- for(; j < LIMB_DIGITS; j++) {
- if (bpos == 0) {
- if (bc_get_u8(s, &v8))
- goto fail;
- d = v8 & 0xf;
- bpos = 1;
- } else {
- d = v8 >> 4;
- bpos = 0;
- }
- if (d >= 10) {
- JS_ThrowInternalError(s->ctx, "invalid digit");
- goto fail;
- }
- v += mp_pow_dec[j] * d;
- }
- a->tab[i] = v;
- }
- } else
-#endif /* CONFIG_BIGNUM */
- {
- n = len & (sizeof(limb_t) - 1);
- if (n != 0) {
- v = 0;
- for(i = 0; i < n; i++) {
- if (bc_get_u8(s, &v8))
- goto fail;
- v |= (limb_t)v8 << ((sizeof(limb_t) - n + i) * 8);
- }
- a->tab[0] = v;
- i = 1;
- } else {
- i = 0;
+ n = len & (sizeof(limb_t) - 1);
+ if (n != 0) {
+ v = 0;
+ for(i = 0; i < n; i++) {
+ if (bc_get_u8(s, &v8))
+ goto fail;
+ v |= (limb_t)v8 << ((sizeof(limb_t) - n + i) * 8);
}
- for(; i < l; i++) {
+ a->tab[0] = v;
+ i = 1;
+ } else {
+ i = 0;
+ }
+ for(; i < l; i++) {
#if LIMB_BITS == 32
- if (bc_get_u32(s, &v))
- goto fail;
+ if (bc_get_u32(s, &v))
+ goto fail;
#else
- if (bc_get_u64(s, &v))
- goto fail;
+ if (bc_get_u64(s, &v))
+ goto fail;
#endif
- a->tab[i] = v;
- }
+ a->tab[i] = v;
}
}
- bc_read_trace(s, "}\n");
return obj;
fail:
JS_FreeValue(s->ctx, obj);
@@ -36185,7 +34933,7 @@ static int BC_add_object_ref1(BCReaderState *s, JSObject *p)
return 0;
}
-static int BC_add_object_ref(BCReaderState *s, JSValueConst obj)
+static int BC_add_object_ref(BCReaderState *s, JSValue obj)
{
return BC_add_object_ref1(s, JS_VALUE_GET_OBJ(obj));
}
@@ -36197,7 +34945,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
JSValue obj = JS_UNDEFINED;
uint16_t v16;
uint8_t v8;
- int idx, i, local_count;
+ int idx, i, local_count, has_debug_info;
int function_size, cpool_offset, byte_code_offset;
int closure_var_offset, vardefs_offset;
@@ -36217,14 +34965,12 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
bc.super_call_allowed = bc_get_flags(v16, &idx, 1);
bc.super_allowed = bc_get_flags(v16, &idx, 1);
bc.arguments_allowed = bc_get_flags(v16, &idx, 1);
- bc.has_debug = bc_get_flags(v16, &idx, 1);
bc.backtrace_barrier = bc_get_flags(v16, &idx, 1);
- bc.is_direct_or_indirect_eval = bc_get_flags(v16, &idx, 1);
- bc.read_only_bytecode = s->is_rom_data;
+ has_debug_info = bc_get_flags(v16, &idx, 1);
if (bc_get_u8(s, &v8))
goto fail;
- bc.js_mode = v8;
- if (bc_get_atom(s, &bc.func_name)) //@ atom leak if failure
+ bc.is_strict_mode = (v8 > 0);
+ if (bc_get_atom(s, &bc.func_name))
goto fail;
if (bc_get_leb128_u16(s, &bc.arg_count))
goto fail;
@@ -36243,11 +34989,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
if (bc_get_leb128_int(s, &local_count))
goto fail;
- if (bc.has_debug) {
- function_size = sizeof(*b);
- } else {
- function_size = offsetof(JSFunctionBytecode, debug);
- }
+ function_size = sizeof(*b);
cpool_offset = function_size;
function_size += bc.cpool_count * sizeof(*bc.cpool);
vardefs_offset = function_size;
@@ -36255,15 +34997,14 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
closure_var_offset = function_size;
function_size += bc.closure_var_count * sizeof(*bc.closure_var);
byte_code_offset = function_size;
- if (!bc.read_only_bytecode) {
- function_size += bc.byte_code_len;
- }
+ function_size += bc.byte_code_len;
b = js_mallocz(ctx, function_size);
if (!b)
- return JS_EXCEPTION;
+ goto fail;
- memcpy(b, &bc, offsetof(JSFunctionBytecode, debug));
+ memcpy(b, &bc, sizeof(*b));
+ bc.func_name = JS_ATOM_NULL;
b->header.ref_count = 1;
if (local_count != 0) {
b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
@@ -36279,8 +35020,14 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b);
-#ifdef DUMP_READ_OBJECT
- bc_read_trace(s, "name: "); print_atom(s->ctx, b->func_name); printf("\n");
+#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT
+ if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) {
+ if (b->func_name) {
+ bc_read_trace(s, "name: ");
+ print_atom(s->ctx, b->func_name);
+ printf("\n");
+ }
+ }
#endif
bc_read_trace(s, "args=%d vars=%d defargs=%d closures=%d cpool=%d\n",
b->arg_count, b->var_count, b->defined_arg_count,
@@ -36290,6 +35037,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
if (local_count != 0) {
bc_read_trace(s, "vars {\n");
+ bc_read_trace(s, "off flags scope name\n");
for(i = 0; i < local_count; i++) {
JSVarDef *vd = &b->vardefs[i];
if (bc_get_atom(s, &vd->var_name))
@@ -36306,14 +35054,24 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
vd->is_const = bc_get_flags(v8, &idx, 1);
vd->is_lexical = bc_get_flags(v8, &idx, 1);
vd->is_captured = bc_get_flags(v8, &idx, 1);
-#ifdef DUMP_READ_OBJECT
- bc_read_trace(s, "name: "); print_atom(s->ctx, vd->var_name); printf("\n");
+#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT
+ if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) {
+ bc_read_trace(s, "%3d %d%c%c%c %4d ",
+ i, vd->var_kind,
+ vd->is_const ? 'C' : '.',
+ vd->is_lexical ? 'L' : '.',
+ vd->is_captured ? 'X' : '.',
+ vd->scope_level);
+ print_atom(s->ctx, vd->var_name);
+ printf("\n");
+ }
#endif
}
bc_read_trace(s, "}\n");
}
if (b->closure_var_count != 0) {
bc_read_trace(s, "closure vars {\n");
+ bc_read_trace(s, "off flags idx name\n");
for(i = 0; i < b->closure_var_count; i++) {
JSClosureVar *cv = &b->closure_var[i];
int var_idx;
@@ -36330,39 +35088,22 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
cv->is_const = bc_get_flags(v8, &idx, 1);
cv->is_lexical = bc_get_flags(v8, &idx, 1);
cv->var_kind = bc_get_flags(v8, &idx, 4);
-#ifdef DUMP_READ_OBJECT
- bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n");
+#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT
+ if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) {
+ bc_read_trace(s, "%3d %d%c%c%c%c %3d ",
+ i, cv->var_kind,
+ cv->is_local ? 'L' : '.',
+ cv->is_arg ? 'A' : '.',
+ cv->is_const ? 'C' : '.',
+ cv->is_lexical ? 'X' : '.',
+ cv->var_idx);
+ print_atom(s->ctx, cv->var_name);
+ printf("\n");
+ }
#endif
}
bc_read_trace(s, "}\n");
}
- {
- bc_read_trace(s, "bytecode {\n");
- if (JS_ReadFunctionBytecode(s, b, byte_code_offset, b->byte_code_len))
- goto fail;
- bc_read_trace(s, "}\n");
- }
- if (b->has_debug) {
- /* read optional debug information */
- bc_read_trace(s, "debug {\n");
- if (bc_get_atom(s, &b->debug.filename))
- goto fail;
- if (bc_get_leb128_int(s, &b->debug.line_num))
- goto fail;
- if (bc_get_leb128_int(s, &b->debug.pc2line_len))
- goto fail;
- if (b->debug.pc2line_len) {
- b->debug.pc2line_buf = js_mallocz(ctx, b->debug.pc2line_len);
- if (!b->debug.pc2line_buf)
- goto fail;
- if (bc_get_buf(s, b->debug.pc2line_buf, b->debug.pc2line_len))
- goto fail;
- }
-#ifdef DUMP_READ_OBJECT
- bc_read_trace(s, "filename: "); print_atom(s->ctx, b->debug.filename); printf("\n");
-#endif
- bc_read_trace(s, "}\n");
- }
if (b->cpool_count != 0) {
bc_read_trace(s, "cpool {\n");
for(i = 0; i < b->cpool_count; i++) {
@@ -36374,9 +35115,61 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
}
bc_read_trace(s, "}\n");
}
+ {
+ bc_read_trace(s, "bytecode {\n");
+ if (JS_ReadFunctionBytecode(s, b, byte_code_offset, b->byte_code_len))
+ goto fail;
+ bc_read_trace(s, "}\n");
+ }
+ if (!has_debug_info)
+ goto nodebug;
+
+ /* read optional debug information */
+ bc_read_trace(s, "debug {\n");
+ if (bc_get_atom(s, &b->filename))
+ goto fail;
+ if (bc_get_leb128_int(s, &b->line_num))
+ goto fail;
+ if (bc_get_leb128_int(s, &b->col_num))
+ goto fail;
+#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT
+ if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) {
+ bc_read_trace(s, "filename: ");
+ print_atom(s->ctx, b->filename);
+ printf(", line: %d, column: %d\n", b->line_num, b->col_num);
+ }
+#endif
+ if (bc_get_leb128_int(s, &b->pc2line_len))
+ goto fail;
+ if (b->pc2line_len) {
+ bc_read_trace(s, "positions: %d bytes\n", b->pc2line_len);
+ b->pc2line_buf = js_mallocz(ctx, b->pc2line_len);
+ if (!b->pc2line_buf)
+ goto fail;
+ if (bc_get_buf(s, b->pc2line_buf, b->pc2line_len))
+ goto fail;
+ }
+ if (bc_get_leb128_int(s, &b->source_len))
+ goto fail;
+ if (b->source_len) {
+ bc_read_trace(s, "source: %d bytes\n", b->source_len);
+ if (s->ptr_last)
+ s->ptr_last += b->source_len; // omit source code hex dump
+ /* b->source is a UTF-8 encoded null terminated C string */
+ b->source = js_mallocz(ctx, b->source_len + 1);
+ if (!b->source)
+ goto fail;
+ if (bc_get_buf(s, b->source, b->source_len))
+ goto fail;
+ }
+ bc_read_trace(s, "}\n");
+
+ nodebug:
b->realm = JS_DupContext(ctx);
return obj;
+
fail:
+ JS_FreeAtom(ctx, bc.func_name);
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
@@ -36392,15 +35185,20 @@ static JSValue JS_ReadModule(BCReaderState *s)
if (bc_get_atom(s, &module_name))
goto fail;
-#ifdef DUMP_READ_OBJECT
- bc_read_trace(s, "name: "); print_atom(s->ctx, module_name); printf("\n");
+#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT
+ if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) {
+ bc_read_trace(s, "name: ");
+ print_atom(s->ctx, module_name);
+ printf("\n");
+ }
#endif
m = js_new_module_def(ctx, module_name);
if (!m)
goto fail;
- obj = JS_NewModuleValue(ctx, m);
+ obj = js_dup(JS_MKPTR(JS_TAG_MODULE, m));
if (bc_get_leb128_int(s, &m->req_module_entries_count))
goto fail;
+ obj = JS_NewModuleValue(ctx, m);
if (m->req_module_entries_count != 0) {
m->req_module_entries_size = m->req_module_entries_count;
m->req_module_entries = js_mallocz(ctx, sizeof(m->req_module_entries[0]) * m->req_module_entries_size);
@@ -36503,8 +35301,12 @@ static JSValue JS_ReadObjectTag(BCReaderState *s)
for(i = 0; i < prop_count; i++) {
if (bc_get_atom(s, &atom))
goto fail;
-#ifdef DUMP_READ_OBJECT
- bc_read_trace(s, "propname: "); print_atom(s->ctx, atom); printf("\n");
+#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT
+ if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) {
+ bc_read_trace(s, "propname: ");
+ print_atom(s->ctx, atom);
+ printf("\n");
+ }
#endif
val = JS_ReadObjectRec(s);
if (JS_IsException(val)) {
@@ -36529,7 +35331,7 @@ static JSValue JS_ReadArray(BCReaderState *s, int tag)
uint32_t len, i;
JSValue val;
int ret, prop_flags;
- BOOL is_template;
+ bool is_template;
obj = JS_NewArray(ctx);
if (BC_add_object_ref(s, obj))
@@ -36572,7 +35374,7 @@ static JSValue JS_ReadTypedArray(BCReaderState *s)
JSContext *ctx = s->ctx;
JSValue obj = JS_UNDEFINED, array_buffer = JS_UNDEFINED;
uint8_t array_tag;
- JSValueConst args[3];
+ JSValue args[3];
uint32_t offset, len, idx;
if (bc_get_u8(s, &array_tag))
@@ -36596,8 +35398,8 @@ static JSValue JS_ReadTypedArray(BCReaderState *s)
return JS_EXCEPTION;
}
args[0] = array_buffer;
- args[1] = JS_NewInt64(ctx, offset);
- args[2] = JS_NewInt64(ctx, len);
+ args[1] = js_int64(offset);
+ args[2] = js_int64(len);
obj = js_typed_array_constructor(ctx, JS_UNDEFINED,
3, args,
JS_CLASS_UINT8C_ARRAY + array_tag);
@@ -36617,16 +35419,31 @@ static JSValue JS_ReadTypedArray(BCReaderState *s)
static JSValue JS_ReadArrayBuffer(BCReaderState *s)
{
JSContext *ctx = s->ctx;
- uint32_t byte_length;
+ uint32_t byte_length, max_byte_length;
+ uint64_t max_byte_length_u64, *pmax_byte_length = NULL;
JSValue obj;
if (bc_get_leb128(s, &byte_length))
return JS_EXCEPTION;
+ if (bc_get_leb128(s, &max_byte_length))
+ return JS_EXCEPTION;
+ if (max_byte_length < byte_length)
+ return JS_ThrowTypeError(ctx, "invalid array buffer");
+ if (max_byte_length != UINT32_MAX) {
+ max_byte_length_u64 = max_byte_length;
+ pmax_byte_length = &max_byte_length_u64;
+ }
if (unlikely(s->buf_end - s->ptr < byte_length)) {
bc_read_error_end(s);
return JS_EXCEPTION;
}
- obj = JS_NewArrayBufferCopy(ctx, s->ptr, byte_length);
+ // makes a copy of the input
+ obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED,
+ byte_length, pmax_byte_length,
+ JS_CLASS_ARRAY_BUFFER,
+ (uint8_t*)s->ptr,
+ js_array_buffer_free, NULL,
+ /*alloc_flag*/true);
if (JS_IsException(obj))
goto fail;
if (BC_add_object_ref(s, obj))
@@ -36641,21 +35458,36 @@ static JSValue JS_ReadArrayBuffer(BCReaderState *s)
static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s)
{
JSContext *ctx = s->ctx;
- uint32_t byte_length;
+ uint32_t byte_length, max_byte_length;
+ uint64_t max_byte_length_u64, *pmax_byte_length = NULL;
uint8_t *data_ptr;
JSValue obj;
uint64_t u64;
if (bc_get_leb128(s, &byte_length))
return JS_EXCEPTION;
+ if (bc_get_leb128(s, &max_byte_length))
+ return JS_EXCEPTION;
+ if (max_byte_length < byte_length)
+ return JS_ThrowTypeError(ctx, "invalid array buffer");
+ if (max_byte_length != UINT32_MAX) {
+ max_byte_length_u64 = max_byte_length;
+ pmax_byte_length = &max_byte_length_u64;
+ }
if (bc_get_u64(s, &u64))
return JS_EXCEPTION;
data_ptr = (uint8_t *)(uintptr_t)u64;
+ if (js_resize_array(s->ctx, (void **)&s->sab_tab, sizeof(s->sab_tab[0]),
+ &s->sab_tab_size, s->sab_tab_len + 1))
+ return JS_EXCEPTION;
+ /* keep the SAB pointer so that the user can clone it or free it */
+ s->sab_tab[s->sab_tab_len++] = data_ptr;
/* the SharedArrayBuffer is cloned */
- obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED, byte_length,
+ obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED,
+ byte_length, pmax_byte_length,
JS_CLASS_SHARED_ARRAY_BUFFER,
data_ptr,
- NULL, NULL, FALSE);
+ NULL, NULL, false);
if (JS_IsException(obj))
goto fail;
if (BC_add_object_ref(s, obj))
@@ -36666,6 +35498,36 @@ static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s)
return JS_EXCEPTION;
}
+static JSValue JS_ReadRegExp(BCReaderState *s)
+{
+ JSContext *ctx = s->ctx;
+ JSString *pattern;
+ JSString *bc;
+
+ pattern = JS_ReadString(s);
+ if (!pattern)
+ return JS_EXCEPTION;
+
+ bc = JS_ReadString(s);
+ if (!bc) {
+ js_free_string(ctx->rt, pattern);
+ return JS_EXCEPTION;
+ }
+
+ if (bc->is_wide_char) {
+ js_free_string(ctx->rt, pattern);
+ js_free_string(ctx->rt, bc);
+ return JS_ThrowInternalError(ctx, "bad regexp bytecode");
+ }
+
+ if (is_be())
+ lre_byte_swap(bc->u.str8, bc->len, /*is_byte_swapped*/true);
+
+ return js_regexp_constructor_internal(ctx, JS_UNDEFINED,
+ JS_MKPTR(JS_TAG_STRING, pattern),
+ JS_MKPTR(JS_TAG_STRING, bc));
+}
+
static JSValue JS_ReadDate(BCReaderState *s)
{
JSContext *ctx = s->ctx;
@@ -36713,6 +35575,9 @@ static JSValue JS_ReadObjectValue(BCReaderState *s)
return JS_EXCEPTION;
}
+static JSValue JS_ReadMap(BCReaderState *s);
+static JSValue JS_ReadSet(BCReaderState *s);
+
static JSValue JS_ReadObjectRec(BCReaderState *s)
{
JSContext *ctx = s->ctx;
@@ -36736,7 +35601,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
break;
case BC_TAG_BOOL_FALSE:
case BC_TAG_BOOL_TRUE:
- obj = JS_NewBool(ctx, tag - BC_TAG_BOOL_FALSE);
+ obj = js_bool(tag - BC_TAG_BOOL_FALSE);
break;
case BC_TAG_INT32:
{
@@ -36744,7 +35609,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
if (bc_get_sleb128(s, &val))
return JS_EXCEPTION;
bc_read_trace(s, "%d\n", val);
- obj = JS_NewInt32(ctx, val);
+ obj = js_int32(val);
}
break;
case BC_TAG_FLOAT64:
@@ -36753,7 +35618,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
if (bc_get_u64(s, &u.u64))
return JS_EXCEPTION;
bc_read_trace(s, "%g\n", u.d);
- obj = __JS_NewFloat64(ctx, u.d);
+ obj = js_float64(u.d);
}
break;
case BC_TAG_STRING:
@@ -36767,12 +35632,14 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
break;
case BC_TAG_FUNCTION_BYTECODE:
if (!s->allow_bytecode)
- goto invalid_tag;
+ goto no_allow_bytecode;
obj = JS_ReadFunctionTag(s);
break;
case BC_TAG_MODULE:
- if (!s->allow_bytecode)
- goto invalid_tag;
+ if (!s->allow_bytecode) {
+ no_allow_bytecode:
+ return JS_ThrowSyntaxError(ctx, "no bytecode allowed");
+ }
obj = JS_ReadModule(s);
break;
case BC_TAG_OBJECT:
@@ -36793,6 +35660,9 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
goto invalid_tag;
obj = JS_ReadSharedArrayBuffer(s);
break;
+ case BC_TAG_REGEXP:
+ obj = JS_ReadRegExp(s);
+ break;
case BC_TAG_DATE:
obj = JS_ReadDate(s);
break;
@@ -36800,11 +35670,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
obj = JS_ReadObjectValue(s);
break;
case BC_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case BC_TAG_BIG_FLOAT:
- case BC_TAG_BIG_DECIMAL:
-#endif
- obj = JS_ReadBigNum(s, tag);
+ obj = JS_ReadBigInt(s);
break;
case BC_TAG_OBJECT_REFERENCE:
{
@@ -36818,7 +35684,26 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
return JS_ThrowSyntaxError(ctx, "invalid object reference (%u >= %u)",
val, s->objects_count);
}
- obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, s->objects[val]));
+ obj = js_dup(JS_MKPTR(JS_TAG_OBJECT, s->objects[val]));
+ }
+ break;
+ case BC_TAG_MAP:
+ obj = JS_ReadMap(s);
+ break;
+ case BC_TAG_SET:
+ obj = JS_ReadSet(s);
+ break;
+ case BC_TAG_SYMBOL:
+ {
+ JSAtom atom;
+ if (bc_get_atom(s, &atom))
+ return JS_EXCEPTION;
+ if (__JS_AtomIsConst(atom)) {
+ obj = JS_AtomToValue(s->ctx, atom);
+ } else {
+ JSAtomStruct *p = s->ctx->rt->atom_array[atom];
+ obj = JS_NewSymbolFromAtom(s->ctx, atom, p->atom_type);
+ }
}
break;
default:
@@ -36832,7 +35717,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
static int JS_ReadObjectAtoms(BCReaderState *s)
{
- uint8_t v8;
+ uint8_t v8, type;
JSString *p;
int i;
JSAtom atom;
@@ -36846,8 +35731,13 @@ static int JS_ReadObjectAtoms(BCReaderState *s)
}
if (bc_get_leb128(s, &s->idx_to_atom_count))
return -1;
+ if (s->idx_to_atom_count > 1000*1000) {
+ JS_ThrowInternalError(s->ctx, "unreasonable atom count: %u",
+ s->idx_to_atom_count);
+ return -1;
+ }
- bc_read_trace(s, "%d atom indexes {\n", s->idx_to_atom_count);
+ bc_read_trace(s, "%u atom indexes {\n", s->idx_to_atom_count);
if (s->idx_to_atom_count != 0) {
s->idx_to_atom = js_mallocz(s->ctx, s->idx_to_atom_count *
@@ -36856,15 +35746,29 @@ static int JS_ReadObjectAtoms(BCReaderState *s)
return s->error_state = -1;
}
for(i = 0; i < s->idx_to_atom_count; i++) {
- p = JS_ReadString(s);
- if (!p)
+ if (bc_get_u8(s, &type)) {
return -1;
- atom = JS_NewAtomStr(s->ctx, p);
+ }
+ if (type == 0) {
+ if (bc_get_u32(s, &atom))
+ return -1;
+ if (!__JS_AtomIsConst(atom)) {
+ JS_ThrowInternalError(s->ctx, "out of range atom");
+ return -1;
+ }
+ } else {
+ if (type < JS_ATOM_TYPE_STRING || type >= JS_ATOM_TYPE_PRIVATE) {
+ JS_ThrowInternalError(s->ctx, "invalid symbol type %d", type);
+ return -1;
+ }
+ p = JS_ReadString(s);
+ if (!p)
+ return -1;
+ atom = __JS_NewAtom(s->ctx->rt, p, type);
+ }
if (atom == JS_ATOM_NULL)
return s->error_state = -1;
s->idx_to_atom[i] = atom;
- if (s->is_rom_data && (atom != (i + s->first_atom)))
- s->is_rom_data = FALSE; /* atoms must be relocated */
}
bc_read_trace(s, "}\n");
return 0;
@@ -36882,8 +35786,8 @@ static void bc_reader_free(BCReaderState *s)
js_free(s->ctx, s->objects);
}
-JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
- int flags)
+JSValue JS_ReadObject2(JSContext *ctx, const uint8_t *buf, size_t buf_len,
+ int flags, JSSABTab *psab_tab)
{
BCReaderState ss, *s = &ss;
JSValue obj;
@@ -36897,7 +35801,6 @@ JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
s->buf_end = buf + buf_len;
s->ptr = buf;
s->allow_bytecode = ((flags & JS_READ_OBJ_BYTECODE) != 0);
- s->is_rom_data = ((flags & JS_READ_OBJ_ROM_DATA) != 0);
s->allow_sab = ((flags & JS_READ_OBJ_SAB) != 0);
s->allow_reference = ((flags & JS_READ_OBJ_REFERENCE) != 0);
if (s->allow_bytecode)
@@ -36909,25 +35812,37 @@ JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
} else {
obj = JS_ReadObjectRec(s);
}
+ if (psab_tab) {
+ psab_tab->tab = s->sab_tab;
+ psab_tab->len = s->sab_tab_len;
+ } else {
+ js_free(ctx, s->sab_tab);
+ }
bc_reader_free(s);
return obj;
}
+JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
+ int flags)
+{
+ return JS_ReadObject2(ctx, buf, buf_len, flags, NULL);
+}
+
/*******************************************************************/
/* runtime functions & objects */
-static JSValue js_string_constructor(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv);
-static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv);
-static JSValue js_number_constructor(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv);
+static JSValue js_string_constructor(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv);
+static JSValue js_boolean_constructor(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv);
+static JSValue js_number_constructor(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv);
-static int check_function(JSContext *ctx, JSValueConst obj)
+static int check_function(JSContext *ctx, JSValue obj)
{
if (likely(JS_IsFunction(ctx, obj)))
return 0;
- JS_ThrowTypeError(ctx, "not a function");
+ JS_ThrowTypeErrorNotAFunction(ctx);
return -1;
}
@@ -36937,6 +35852,7 @@ static int check_exception_free(JSContext *ctx, JSValue obj)
return JS_IsException(obj);
}
+/* `export_name` may be pure ASCII or UTF-8 encoded */
static JSAtom find_atom(JSContext *ctx, const char *name)
{
JSAtom atom;
@@ -36984,7 +35900,7 @@ static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p,
return val;
}
-static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
+static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValue obj,
JSAtom atom,
const JSCFunctionListEntry *e)
{
@@ -37054,13 +35970,13 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
}
break;
case JS_DEF_PROP_INT32:
- val = JS_NewInt32(ctx, e->u.i32);
+ val = js_int32(e->u.i32);
break;
case JS_DEF_PROP_INT64:
- val = JS_NewInt64(ctx, e->u.i64);
+ val = js_int64(e->u.i64);
break;
case JS_DEF_PROP_DOUBLE:
- val = __JS_NewFloat64(ctx, e->u.f64);
+ val = js_float64(e->u.f64);
break;
case JS_DEF_PROP_UNDEFINED:
val = JS_UNDEFINED;
@@ -37077,7 +35993,7 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
return 0;
}
-void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
+void JS_SetPropertyFunctionList(JSContext *ctx, JSValue obj,
const JSCFunctionListEntry *tab, int len)
{
int i;
@@ -37115,16 +36031,17 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
e->name, e->u.func.length, e->u.func.cproto, e->magic);
break;
case JS_DEF_PROP_STRING:
+ /* `e->u.str` may be pure ASCII or UTF-8 encoded */
val = JS_NewString(ctx, e->u.str);
break;
case JS_DEF_PROP_INT32:
- val = JS_NewInt32(ctx, e->u.i32);
+ val = js_int32(e->u.i32);
break;
case JS_DEF_PROP_INT64:
- val = JS_NewInt64(ctx, e->u.i64);
+ val = js_int64(e->u.i64);
break;
case JS_DEF_PROP_DOUBLE:
- val = __JS_NewFloat64(ctx, e->u.f64);
+ val = js_float64(e->u.f64);
break;
case JS_DEF_OBJECT:
val = JS_NewObject(ctx);
@@ -37141,21 +36058,20 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
/* Note: 'func_obj' is not necessarily a constructor */
static void JS_SetConstructor2(JSContext *ctx,
- JSValueConst func_obj,
- JSValueConst proto,
+ JSValue func_obj,
+ JSValue proto,
int proto_flags, int ctor_flags)
{
JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype,
- JS_DupValue(ctx, proto), proto_flags);
+ js_dup(proto), proto_flags);
JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor,
- JS_DupValue(ctx, func_obj),
- ctor_flags);
+ js_dup(func_obj), ctor_flags);
set_cycle_flag(ctx, func_obj);
set_cycle_flag(ctx, proto);
}
-void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj,
- JSValueConst proto)
+void JS_SetConstructor(JSContext *ctx, JSValue func_obj,
+ JSValue proto)
{
JS_SetConstructor2(ctx, func_obj, proto,
0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
@@ -37164,18 +36080,18 @@ void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj,
static void JS_NewGlobalCConstructor2(JSContext *ctx,
JSValue func_obj,
const char *name,
- JSValueConst proto)
+ JSValue proto)
{
JS_DefinePropertyValueStr(ctx, ctx->global_obj, name,
- JS_DupValue(ctx, func_obj),
+ js_dup(func_obj),
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
JS_SetConstructor(ctx, func_obj, proto);
JS_FreeValue(ctx, func_obj);
}
-static JSValueConst JS_NewGlobalCConstructor(JSContext *ctx, const char *name,
+static JSValue JS_NewGlobalCConstructor(JSContext *ctx, const char *name,
JSCFunction *func, int length,
- JSValueConst proto)
+ JSValue proto)
{
JSValue func_obj;
func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor_or_func, 0);
@@ -37183,9 +36099,9 @@ static JSValueConst JS_NewGlobalCConstructor(JSContext *ctx, const char *name,
return func_obj;
}
-static JSValueConst JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *name,
+static JSValue JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *name,
JSCFunction *func, int length,
- JSValueConst proto)
+ JSValue proto)
{
JSValue func_obj;
func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor, 0);
@@ -37193,35 +36109,52 @@ static JSValueConst JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *nam
return func_obj;
}
-static JSValue js_global_eval(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_global_eval(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return JS_EvalObject(ctx, ctx->global_obj, argv[0], JS_EVAL_TYPE_INDIRECT, -1);
}
-static JSValue js_global_isNaN(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_global_isNaN(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
double d;
- /* XXX: does this work for bigfloat? */
if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))
return JS_EXCEPTION;
- return JS_NewBool(ctx, isnan(d));
+ return js_bool(isnan(d));
}
-static JSValue js_global_isFinite(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_global_isFinite(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
+ bool res;
double d;
if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))
return JS_EXCEPTION;
- return JS_NewBool(ctx, isfinite(d));
+ res = isfinite(d);
+ return js_bool(res);
+}
+
+static JSValue js_microtask_job(JSContext *ctx,
+ int argc, JSValue *argv)
+{
+ return JS_Call(ctx, argv[0], ctx->global_obj, 0, NULL);
+}
+
+static JSValue js_global_queueMicrotask(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ if (check_function(ctx, argv[0]))
+ return JS_EXCEPTION;
+ if (JS_EnqueueJob(ctx, js_microtask_job, 1, &argv[0]))
+ return JS_EXCEPTION;
+ return JS_UNDEFINED;
}
/* Object class */
-static JSValue JS_ToObject(JSContext *ctx, JSValueConst val)
+JSValue JS_ToObject(JSContext *ctx, JSValue val)
{
int tag = JS_VALUE_GET_NORM_TAG(val);
JSValue obj;
@@ -37230,21 +36163,13 @@ static JSValue JS_ToObject(JSContext *ctx, JSValueConst val)
default:
case JS_TAG_NULL:
case JS_TAG_UNDEFINED:
- return JS_ThrowTypeError(ctx, "cannot convert to object");
+ return JS_ThrowTypeError(ctx, "Cannot convert undefined or null to object");
case JS_TAG_OBJECT:
case JS_TAG_EXCEPTION:
- return JS_DupValue(ctx, val);
+ return js_dup(val);
case JS_TAG_BIG_INT:
obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_INT);
goto set_value;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_FLOAT);
- goto set_value;
- case JS_TAG_BIG_DECIMAL:
- obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_DECIMAL);
- goto set_value;
-#endif
case JS_TAG_INT:
case JS_TAG_FLOAT64:
obj = JS_NewObjectClass(ctx, JS_CLASS_NUMBER);
@@ -37254,7 +36179,7 @@ static JSValue JS_ToObject(JSContext *ctx, JSValueConst val)
{
JSString *p1 = JS_VALUE_GET_STRING(val);
obj = JS_NewObjectClass(ctx, JS_CLASS_STRING);
- JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, JS_NewInt32(ctx, p1->len), 0);
+ JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, js_int32(p1->len), 0);
}
goto set_value;
case JS_TAG_BOOL:
@@ -37264,7 +36189,7 @@ static JSValue JS_ToObject(JSContext *ctx, JSValueConst val)
obj = JS_NewObjectClass(ctx, JS_CLASS_SYMBOL);
set_value:
if (!JS_IsException(obj))
- JS_SetObjectData(ctx, obj, JS_DupValue(ctx, val));
+ JS_SetObjectData(ctx, obj, js_dup(val));
return obj;
}
}
@@ -37277,20 +36202,35 @@ static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val)
}
static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
- JSValueConst desc)
+ JSValue desc)
{
JSValue val, getter, setter;
+ int present;
int flags;
if (!JS_IsObject(desc)) {
- JS_ThrowTypeErrorNotAnObject(ctx);
+ JS_ThrowTypeError(ctx, "Property description must be an object");
return -1;
}
flags = 0;
val = JS_UNDEFINED;
getter = JS_UNDEFINED;
setter = JS_UNDEFINED;
- if (JS_HasProperty(ctx, desc, JS_ATOM_configurable)) {
+ present = JS_HasProperty(ctx, desc, JS_ATOM_enumerable);
+ if (present < 0)
+ goto fail;
+ if (present) {
+ JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_enumerable);
+ if (JS_IsException(prop))
+ goto fail;
+ flags |= JS_PROP_HAS_ENUMERABLE;
+ if (JS_ToBoolFree(ctx, prop))
+ flags |= JS_PROP_ENUMERABLE;
+ }
+ present = JS_HasProperty(ctx, desc, JS_ATOM_configurable);
+ if (present < 0)
+ goto fail;
+ if (present) {
JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_configurable);
if (JS_IsException(prop))
goto fail;
@@ -37298,7 +36238,19 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
if (JS_ToBoolFree(ctx, prop))
flags |= JS_PROP_CONFIGURABLE;
}
- if (JS_HasProperty(ctx, desc, JS_ATOM_writable)) {
+ present = JS_HasProperty(ctx, desc, JS_ATOM_value);
+ if (present < 0)
+ goto fail;
+ if (present) {
+ flags |= JS_PROP_HAS_VALUE;
+ val = JS_GetProperty(ctx, desc, JS_ATOM_value);
+ if (JS_IsException(val))
+ goto fail;
+ }
+ present = JS_HasProperty(ctx, desc, JS_ATOM_writable);
+ if (present < 0)
+ goto fail;
+ if (present) {
JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_writable);
if (JS_IsException(prop))
goto fail;
@@ -37306,41 +36258,33 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
if (JS_ToBoolFree(ctx, prop))
flags |= JS_PROP_WRITABLE;
}
- if (JS_HasProperty(ctx, desc, JS_ATOM_enumerable)) {
- JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_enumerable);
- if (JS_IsException(prop))
- goto fail;
- flags |= JS_PROP_HAS_ENUMERABLE;
- if (JS_ToBoolFree(ctx, prop))
- flags |= JS_PROP_ENUMERABLE;
- }
- if (JS_HasProperty(ctx, desc, JS_ATOM_value)) {
- flags |= JS_PROP_HAS_VALUE;
- val = JS_GetProperty(ctx, desc, JS_ATOM_value);
- if (JS_IsException(val))
- goto fail;
- }
- if (JS_HasProperty(ctx, desc, JS_ATOM_get)) {
+ present = JS_HasProperty(ctx, desc, JS_ATOM_get);
+ if (present < 0)
+ goto fail;
+ if (present) {
flags |= JS_PROP_HAS_GET;
getter = JS_GetProperty(ctx, desc, JS_ATOM_get);
if (JS_IsException(getter) ||
!(JS_IsUndefined(getter) || JS_IsFunction(ctx, getter))) {
- JS_ThrowTypeError(ctx, "invalid getter");
+ JS_ThrowTypeError(ctx, "Getter must be a function");
goto fail;
}
}
- if (JS_HasProperty(ctx, desc, JS_ATOM_set)) {
+ present = JS_HasProperty(ctx, desc, JS_ATOM_set);
+ if (present < 0)
+ goto fail;
+ if (present) {
flags |= JS_PROP_HAS_SET;
setter = JS_GetProperty(ctx, desc, JS_ATOM_set);
if (JS_IsException(setter) ||
!(JS_IsUndefined(setter) || JS_IsFunction(ctx, setter))) {
- JS_ThrowTypeError(ctx, "invalid setter");
+ JS_ThrowTypeError(ctx, "Setter must be a function");
goto fail;
}
}
if ((flags & (JS_PROP_HAS_SET | JS_PROP_HAS_GET)) &&
(flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE))) {
- JS_ThrowTypeError(ctx, "cannot have setter/getter and value or writable");
+ JS_ThrowTypeError(ctx, "Invalid property descriptor. Cannot both specify accessors and a value or writable attribute");
goto fail;
}
d->flags = flags;
@@ -37355,8 +36299,8 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
return -1;
}
-static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
- JSAtom prop, JSValueConst desc,
+static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValue obj,
+ JSAtom prop, JSValue desc,
int flags)
{
JSPropertyDescriptor d;
@@ -37372,8 +36316,8 @@ static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
}
static __exception int JS_ObjectDefineProperties(JSContext *ctx,
- JSValueConst obj,
- JSValueConst properties)
+ JSValue obj,
+ JSValue properties)
{
JSValue props, desc;
JSObject *p;
@@ -37382,7 +36326,7 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx,
int ret = -1;
if (!JS_IsObject(obj)) {
- JS_ThrowTypeErrorNotAnObject(ctx);
+ JS_ThrowTypeError(ctx, "Object.defineProperties called on non-object");
return -1;
}
desc = JS_UNDEFINED;
@@ -37392,12 +36336,16 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx,
p = JS_VALUE_GET_OBJ(props);
if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK) < 0)
goto exception;
+ // XXX: ECMA specifies that all descriptions should be validated before
+ // modifying the object. This would require allocating an array
+ // JSPropertyDescriptor and use 2 separate loops.
for(i = 0; i < len; i++) {
JS_FreeValue(ctx, desc);
desc = JS_GetProperty(ctx, props, atoms[i].atom);
if (JS_IsException(desc))
goto exception;
- if (JS_DefinePropertyDesc(ctx, obj, atoms[i].atom, desc, JS_PROP_THROW) < 0)
+ if (JS_DefinePropertyDesc(ctx, obj, atoms[i].atom, desc,
+ JS_PROP_THROW | JS_PROP_DEFINE_PROPERTY) < 0)
goto exception;
}
ret = 0;
@@ -37409,8 +36357,8 @@ exception:
return ret;
}
-static JSValue js_object_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_object_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
{
JSValue ret;
if (!JS_IsUndefined(new_target) &&
@@ -37432,15 +36380,15 @@ static JSValue js_object_constructor(JSContext *ctx, JSValueConst new_target,
return ret;
}
-static JSValue js_object_create(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_create(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst proto, props;
+ JSValue proto, props;
JSValue obj;
proto = argv[0];
if (!JS_IsObject(proto) && !JS_IsNull(proto))
- return JS_ThrowTypeError(ctx, "not a prototype");
+ return JS_ThrowTypeError(ctx, "object prototype may only be an Object or null");
obj = JS_NewObjectProto(ctx, proto);
if (JS_IsException(obj))
return JS_EXCEPTION;
@@ -37454,10 +36402,10 @@ static JSValue js_object_create(JSContext *ctx, JSValueConst this_val,
return obj;
}
-static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
- JSValueConst val;
+ JSValue val;
val = argv[0];
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) {
@@ -37470,21 +36418,21 @@ static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValueConst this_val,
return JS_GetPrototype(ctx, val);
}
-static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst obj;
+ JSValue obj;
obj = argv[0];
- if (JS_SetPrototypeInternal(ctx, obj, argv[1], TRUE) < 0)
+ if (JS_SetPrototypeInternal(ctx, obj, argv[1], true) < 0)
return JS_EXCEPTION;
- return JS_DupValue(ctx, obj);
+ return js_dup(obj);
}
/* magic = 1 if called as Reflect.defineProperty */
-static JSValue js_object_defineProperty(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_object_defineProperty(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
- JSValueConst obj, prop, desc;
+ JSValue obj, prop, desc;
int ret, flags;
JSAtom atom;
@@ -37497,38 +36445,38 @@ static JSValue js_object_defineProperty(JSContext *ctx, JSValueConst this_val,
atom = JS_ValueToAtom(ctx, prop);
if (unlikely(atom == JS_ATOM_NULL))
return JS_EXCEPTION;
- flags = 0;
- if (!magic)
- flags |= JS_PROP_THROW;
+ flags = JS_PROP_THROW | JS_PROP_DEFINE_PROPERTY;
+ if (magic)
+ flags = JS_PROP_REFLECT_DEFINE_PROPERTY;
ret = JS_DefinePropertyDesc(ctx, obj, atom, desc, flags);
JS_FreeAtom(ctx, atom);
if (ret < 0) {
return JS_EXCEPTION;
} else if (magic) {
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
} else {
- return JS_DupValue(ctx, obj);
+ return js_dup(obj);
}
}
-static JSValue js_object_defineProperties(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_defineProperties(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// defineProperties(obj, properties)
- JSValueConst obj = argv[0];
+ JSValue obj = argv[0];
if (JS_ObjectDefineProperties(ctx, obj, argv[1]))
return JS_EXCEPTION;
else
- return JS_DupValue(ctx, obj);
+ return js_dup(obj);
}
/* magic = 1 if called as __defineSetter__ */
-static JSValue js_object___defineGetter__(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_object___defineGetter__(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSValue obj;
- JSValueConst prop, value, get, set;
+ JSValue prop, value, get, set;
int ret, flags;
JSAtom atom;
@@ -37570,10 +36518,10 @@ static JSValue js_object___defineGetter__(JSContext *ctx, JSValueConst this_val,
}
}
-static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
- JSValueConst prop;
+ JSValue prop;
JSAtom atom;
JSValue ret, obj;
JSPropertyDescriptor desc;
@@ -37583,7 +36531,7 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t
/* Reflect.getOwnPropertyDescriptor case */
if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT)
return JS_ThrowTypeErrorNotAnObject(ctx);
- obj = JS_DupValue(ctx, argv[0]);
+ obj = js_dup(argv[0]);
} else {
obj = JS_ToObject(ctx, argv[0]);
if (JS_IsException(obj))
@@ -37604,19 +36552,22 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t
goto exception1;
flags = JS_PROP_C_W_E | JS_PROP_THROW;
if (desc.flags & JS_PROP_GETSET) {
- if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, JS_DupValue(ctx, desc.getter), flags) < 0
- || JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, desc.setter), flags) < 0)
+ if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, js_dup(desc.getter), flags) < 0
+ || JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, js_dup(desc.setter), flags) < 0)
goto exception1;
} else {
- if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, desc.value), flags) < 0
+ if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, js_dup(desc.value), flags) < 0
|| JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable,
- JS_NewBool(ctx, desc.flags & JS_PROP_WRITABLE), flags) < 0)
+ js_bool(desc.flags & JS_PROP_WRITABLE),
+ flags) < 0)
goto exception1;
}
if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable,
- JS_NewBool(ctx, desc.flags & JS_PROP_ENUMERABLE), flags) < 0
+ js_bool(desc.flags & JS_PROP_ENUMERABLE),
+ flags) < 0
|| JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable,
- JS_NewBool(ctx, desc.flags & JS_PROP_CONFIGURABLE), flags) < 0)
+ js_bool(desc.flags & JS_PROP_CONFIGURABLE),
+ flags) < 0)
goto exception1;
js_free_desc(ctx, &desc);
}
@@ -37634,8 +36585,8 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
//getOwnPropertyDescriptors(obj)
JSValue obj, r;
@@ -37657,7 +36608,7 @@ static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValueConst
goto exception;
for(i = 0; i < len; i++) {
JSValue atomValue, desc;
- JSValueConst args[2];
+ JSValue args[2];
atomValue = JS_AtomToValue(ctx, props[i].atom);
if (JS_IsException(atomValue))
@@ -37685,7 +36636,7 @@ exception:
return JS_EXCEPTION;
}
-static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1,
+static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValue obj1,
int flags, int kind)
{
JSValue obj, r, val, key, value;
@@ -37764,31 +36715,121 @@ done:
return r;
}
-static JSValue js_object_getOwnPropertyNames(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_getOwnPropertyNames(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return JS_GetOwnPropertyNames2(ctx, argv[0],
JS_GPN_STRING_MASK, JS_ITERATOR_KIND_KEY);
}
-static JSValue js_object_getOwnPropertySymbols(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_getOwnPropertySymbols(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return JS_GetOwnPropertyNames2(ctx, argv[0],
JS_GPN_SYMBOL_MASK, JS_ITERATOR_KIND_KEY);
}
-static JSValue js_object_keys(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int kind)
+static JSValue js_object_groupBy(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue cb, res, iter, next, groups, k, v, prop;
+ JSValue args[2];
+ int64_t idx;
+ int done;
+
+ // "is function?" check must be observed before argv[0] is accessed
+ cb = argv[1];
+ if (check_function(ctx, cb))
+ return JS_EXCEPTION;
+
+ // TODO(bnoordhuis) add fast path for arrays but as groupBy() is
+ // defined in terms of iterators, the fast path must check that
+ // this[Symbol.iterator] is the built-in array iterator
+ iter = JS_GetIterator(ctx, argv[0], /*is_async*/false);
+ if (JS_IsException(iter))
+ return JS_EXCEPTION;
+
+ k = JS_UNDEFINED;
+ v = JS_UNDEFINED;
+ prop = JS_UNDEFINED;
+ groups = JS_UNDEFINED;
+
+ next = JS_GetProperty(ctx, iter, JS_ATOM_next);
+ if (JS_IsException(next))
+ goto exception;
+
+ groups = JS_NewObjectProto(ctx, JS_NULL);
+ if (JS_IsException(groups))
+ goto exception;
+
+ for (idx = 0; ; idx++) {
+ v = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
+ if (JS_IsException(v))
+ goto exception;
+ if (done)
+ break; // v is JS_UNDEFINED
+
+ args[0] = v;
+ args[1] = js_int64(idx);
+ k = JS_Call(ctx, cb, ctx->global_obj, 2, args);
+ if (JS_IsException(k))
+ goto exception;
+
+ k = js_dup(k);
+ prop = JS_GetPropertyValue(ctx, groups, k);
+ if (JS_IsException(prop))
+ goto exception;
+
+ if (JS_IsUndefined(prop)) {
+ prop = JS_NewArray(ctx);
+ if (JS_IsException(prop))
+ goto exception;
+ k = js_dup(k);
+ prop = js_dup(prop);
+ if (JS_SetPropertyValue(ctx, groups, k, prop,
+ JS_PROP_C_W_E|JS_PROP_THROW) < 0) {
+ goto exception;
+ }
+ }
+
+ res = js_array_push(ctx, prop, 1, &v, /*unshift*/0);
+ if (JS_IsException(res))
+ goto exception;
+ // res is an int64
+
+ JS_FreeValue(ctx, prop);
+ JS_FreeValue(ctx, k);
+ JS_FreeValue(ctx, v);
+ prop = JS_UNDEFINED;
+ k = JS_UNDEFINED;
+ v = JS_UNDEFINED;
+ }
+
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return groups;
+
+exception:
+ JS_FreeValue(ctx, prop);
+ JS_FreeValue(ctx, k);
+ JS_FreeValue(ctx, v);
+ JS_FreeValue(ctx, groups);
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return JS_EXCEPTION;
+}
+
+static JSValue js_object_keys(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int kind)
{
return JS_GetOwnPropertyNames2(ctx, argv[0],
JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK, kind);
}
-static JSValue js_object_isExtensible(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int reflect)
+static JSValue js_object_isExtensible(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int reflect)
{
- JSValueConst obj;
+ JSValue obj;
int ret;
obj = argv[0];
@@ -37802,13 +36843,13 @@ static JSValue js_object_isExtensible(JSContext *ctx, JSValueConst this_val,
if (ret < 0)
return JS_EXCEPTION;
else
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
-static JSValue js_object_preventExtensions(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int reflect)
+static JSValue js_object_preventExtensions(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int reflect)
{
- JSValueConst obj;
+ JSValue obj;
int ret;
obj = argv[0];
@@ -37816,27 +36857,27 @@ static JSValue js_object_preventExtensions(JSContext *ctx, JSValueConst this_val
if (reflect)
return JS_ThrowTypeErrorNotAnObject(ctx);
else
- return JS_DupValue(ctx, obj);
+ return js_dup(obj);
}
ret = JS_PreventExtensions(ctx, obj);
if (ret < 0)
return JS_EXCEPTION;
if (reflect) {
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
} else {
if (!ret)
return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false");
- return JS_DupValue(ctx, obj);
+ return js_dup(obj);
}
}
-static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj;
JSAtom atom;
JSObject *p;
- BOOL ret;
+ int ret;
atom = JS_ValueToAtom(ctx, argv[0]); /* must be done first */
if (unlikely(atom == JS_ATOM_NULL))
@@ -37853,16 +36894,16 @@ static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val,
if (ret < 0)
return JS_EXCEPTION;
else
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
-static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_hasOwn(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj;
JSAtom atom;
JSObject *p;
- BOOL ret;
+ int ret;
obj = JS_ToObject(ctx, argv[0]);
if (JS_IsException(obj))
@@ -37879,17 +36920,17 @@ static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val,
if (ret < 0)
return JS_EXCEPTION;
else
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
-static JSValue js_object_valueOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_valueOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return JS_ToObject(ctx, this_val);
}
-static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_toString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, tag;
int is_array;
@@ -37897,9 +36938,9 @@ static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val,
JSObject *p;
if (JS_IsNull(this_val)) {
- tag = JS_NewString(ctx, "Null");
+ tag = js_new_string8(ctx, "Null");
} else if (JS_IsUndefined(this_val)) {
- tag = JS_NewString(ctx, "Undefined");
+ tag = js_new_string8(ctx, "Undefined");
} else {
obj = JS_ToObject(ctx, this_val);
if (JS_IsException(obj))
@@ -37943,14 +36984,19 @@ static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val,
return JS_ConcatString3(ctx, "[object ", tag, "]");
}
-static JSValue js_object_toLocaleString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+JSValue JS_ToObjectString(JSContext *ctx, JSValue val)
+{
+ return js_object_toString(ctx, val, 0, NULL);
+}
+
+static JSValue js_object_toLocaleString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return JS_Invoke(ctx, this_val, JS_ATOM_toString, 0, NULL);
}
-static JSValue js_object_assign(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_assign(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// Object.assign(obj, source1)
JSValue obj, s;
@@ -37965,7 +37011,7 @@ static JSValue js_object_assign(JSContext *ctx, JSValueConst this_val,
s = JS_ToObject(ctx, argv[i]);
if (JS_IsException(s))
goto exception;
- if (JS_CopyDataProperties(ctx, obj, s, JS_UNDEFINED, TRUE))
+ if (JS_CopyDataProperties(ctx, obj, s, JS_UNDEFINED, true))
goto exception;
JS_FreeValue(ctx, s);
}
@@ -37977,17 +37023,25 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int freeze_flag)
+static JSValue js_object_seal(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int freeze_flag)
{
- JSValueConst obj = argv[0];
+ JSValue obj = argv[0];
JSObject *p;
+ JSTypedArray *ta;
+ JSArrayBuffer *abuf;
JSPropertyEnum *props;
uint32_t len, i;
int flags, desc_flags, res;
if (!JS_IsObject(obj))
- return JS_DupValue(ctx, obj);
+ return js_dup(obj);
+
+ p = JS_VALUE_GET_OBJ(obj);
+ if (p->class_id == JS_CLASS_MODULE_NS) {
+ return JS_ThrowTypeError(ctx, "cannot %s module namespace",
+ freeze_flag ? "freeze" : "seal");
+ }
res = JS_PreventExtensions(ctx, obj);
if (res < 0)
@@ -37996,7 +37050,13 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val,
return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false");
}
- p = JS_VALUE_GET_OBJ(obj);
+ if (freeze_flag && is_typed_array(p->class_id)) {
+ ta = p->u.typed_array;
+ abuf = ta->buffer->u.array_buffer;
+ if (array_buffer_is_resizable(abuf) || typed_array_is_oob(p))
+ return JS_ThrowTypeError(ctx, "cannot freeze resizable typed array");
+ }
+
flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK;
if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags))
return JS_EXCEPTION;
@@ -38021,17 +37081,17 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val,
goto exception;
}
js_free_prop_enum(ctx, props, len);
- return JS_DupValue(ctx, obj);
+ return js_dup(obj);
exception:
js_free_prop_enum(ctx, props, len);
return JS_EXCEPTION;
}
-static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int is_frozen)
+static JSValue js_object_isSealed(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int is_frozen)
{
- JSValueConst obj = argv[0];
+ JSValue obj = argv[0];
JSObject *p;
JSPropertyEnum *props;
uint32_t len, i;
@@ -38056,7 +37116,7 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val,
js_free_desc(ctx, &desc);
if ((desc.flags & JS_PROP_CONFIGURABLE)
|| (is_frozen && (desc.flags & JS_PROP_WRITABLE))) {
- res = FALSE;
+ res = false;
goto done;
}
}
@@ -38067,26 +37127,35 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val,
res ^= 1;
done:
js_free_prop_enum(ctx, props, len);
- return JS_NewBool(ctx, res);
+ return js_bool(res);
exception:
js_free_prop_enum(ctx, props, len);
return JS_EXCEPTION;
}
-JSValue JS_ObjectSeal(JSContext *ctx, JSValueConst obj, int freeze)
+int JS_SealObject(JSContext *ctx, JSValue obj)
{
- JSValueConst argv[] = {obj};
- JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, argv, freeze));
- return obj;
+ JSValue value = js_object_seal(ctx, JS_UNDEFINED, 1, &obj, 0);
+ int result = JS_IsException(value) ? -1 : true;
+ JS_FreeValue(ctx, value);
+ return result;
+}
+
+int JS_FreezeObject(JSContext *ctx, JSValue obj)
+{
+ JSValue value = js_object_seal(ctx, JS_UNDEFINED, 1, &obj, 1);
+ int result = JS_IsException(value) ? -1 : true;
+ JS_FreeValue(ctx, value);
+ return result;
}
-static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_fromEntries(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, iter, next_method = JS_UNDEFINED;
- JSValueConst iterable;
- BOOL done;
+ JSValue iterable;
+ int done;
/* RequireObjectCoercible() not necessary because it is tested in
JS_GetIterator() by JS_GetProperty() */
@@ -38096,7 +37165,7 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(obj))
return obj;
- iter = JS_GetIterator(ctx, iterable, FALSE);
+ iter = JS_GetIterator(ctx, iterable, false);
if (JS_IsException(iter))
goto fail;
next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);
@@ -38141,7 +37210,7 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val,
fail:
if (JS_IsObject(iter)) {
/* close the iterator object, preserving pending exception */
- JS_IteratorClose(ctx, iter, TRUE);
+ JS_IteratorClose(ctx, iter, true);
}
JS_FreeValue(ctx, next_method);
JS_FreeValue(ctx, iter);
@@ -38149,109 +37218,14 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-#if 0
-/* Note: corresponds to ECMA spec: CreateDataPropertyOrThrow() */
-static JSValue js_object___setOwnProperty(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_is(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- int ret;
- ret = JS_DefinePropertyValueValue(ctx, argv[0], JS_DupValue(ctx, argv[1]),
- JS_DupValue(ctx, argv[2]),
- JS_PROP_C_W_E | JS_PROP_THROW);
- if (ret < 0)
- return JS_EXCEPTION;
- else
- return JS_NewBool(ctx, ret);
+ return js_bool(js_same_value(ctx, argv[0], argv[1]));
}
-static JSValue js_object___toObject(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_ToObject(ctx, argv[0]);
-}
-
-static JSValue js_object___toPrimitive(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- int hint = HINT_NONE;
-
- if (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_INT)
- hint = JS_VALUE_GET_INT(argv[1]);
-
- return JS_ToPrimitive(ctx, argv[0], hint);
-}
-#endif
-
-/* return an empty string if not an object */
-static JSValue js_object___getClass(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSAtom atom;
- JSObject *p;
- uint32_t tag;
- int class_id;
-
- tag = JS_VALUE_GET_NORM_TAG(argv[0]);
- if (tag == JS_TAG_OBJECT) {
- p = JS_VALUE_GET_OBJ(argv[0]);
- class_id = p->class_id;
- if (class_id == JS_CLASS_PROXY && JS_IsFunction(ctx, argv[0]))
- class_id = JS_CLASS_BYTECODE_FUNCTION;
- atom = ctx->rt->class_array[class_id].class_name;
- } else {
- atom = JS_ATOM_empty_string;
- }
- return JS_AtomToString(ctx, atom);
-}
-
-static JSValue js_object_is(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_NewBool(ctx, js_same_value(ctx, argv[0], argv[1]));
-}
-
-#if 0
-static JSValue js_object___getObjectData(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_GetObjectData(ctx, argv[0]);
-}
-
-static JSValue js_object___setObjectData(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- if (JS_SetObjectData(ctx, argv[0], JS_DupValue(ctx, argv[1])))
- return JS_EXCEPTION;
- return JS_DupValue(ctx, argv[1]);
-}
-
-static JSValue js_object___toPropertyKey(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_ToPropertyKey(ctx, argv[0]);
-}
-
-static JSValue js_object___isObject(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_NewBool(ctx, JS_IsObject(argv[0]));
-}
-
-static JSValue js_object___isSameValueZero(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_NewBool(ctx, js_same_value_zero(ctx, argv[0], argv[1]));
-}
-
-static JSValue js_object___isConstructor(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_NewBool(ctx, JS_IsConstructor(ctx, argv[0]));
-}
-#endif
-
-static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj,
- JSValueConst defaultConstructor)
+static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValue obj,
+ JSValue defaultConstructor)
{
JSValue ctor, species;
@@ -38261,7 +37235,7 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj,
if (JS_IsException(ctor))
return ctor;
if (JS_IsUndefined(ctor))
- return JS_DupValue(ctx, defaultConstructor);
+ return js_dup(defaultConstructor);
if (!JS_IsObject(ctor)) {
JS_FreeValue(ctx, ctor);
return JS_ThrowTypeErrorNotAnObject(ctx);
@@ -38271,7 +37245,7 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj,
if (JS_IsException(species))
return species;
if (JS_IsUndefined(species) || JS_IsNull(species))
- return JS_DupValue(ctx, defaultConstructor);
+ return js_dup(defaultConstructor);
if (!JS_IsConstructor(ctx, species)) {
JS_FreeValue(ctx, species);
return JS_ThrowTypeError(ctx, "not a constructor");
@@ -38279,15 +37253,7 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj,
return species;
}
-#if 0
-static JSValue js_object___speciesConstructor(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_SpeciesConstructor(ctx, argv[0], argv[1]);
-}
-#endif
-
-static JSValue js_object_get___proto__(JSContext *ctx, JSValueConst this_val)
+static JSValue js_object_get___proto__(JSContext *ctx, JSValue this_val)
{
JSValue val, ret;
@@ -38299,24 +37265,24 @@ static JSValue js_object_get___proto__(JSContext *ctx, JSValueConst this_val)
return ret;
}
-static JSValue js_object_set___proto__(JSContext *ctx, JSValueConst this_val,
- JSValueConst proto)
+static JSValue js_object_set___proto__(JSContext *ctx, JSValue this_val,
+ JSValue proto)
{
if (JS_IsUndefined(this_val) || JS_IsNull(this_val))
return JS_ThrowTypeErrorNotAnObject(ctx);
if (!JS_IsObject(proto) && !JS_IsNull(proto))
return JS_UNDEFINED;
- if (JS_SetPrototypeInternal(ctx, this_val, proto, TRUE) < 0)
+ if (JS_SetPrototypeInternal(ctx, this_val, proto, true) < 0)
return JS_EXCEPTION;
else
return JS_UNDEFINED;
}
-static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, v1;
- JSValueConst v;
+ JSValue v;
int res;
v = argv[0];
@@ -38325,17 +37291,17 @@ static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val,
obj = JS_ToObject(ctx, this_val);
if (JS_IsException(obj))
return JS_EXCEPTION;
- v1 = JS_DupValue(ctx, v);
+ v1 = js_dup(v);
for(;;) {
v1 = JS_GetPrototypeFree(ctx, v1);
if (JS_IsException(v1))
goto exception;
if (JS_IsNull(v1)) {
- res = FALSE;
+ res = false;
break;
}
if (JS_VALUE_GET_OBJ(obj) == JS_VALUE_GET_OBJ(v1)) {
- res = TRUE;
+ res = true;
break;
}
/* avoid infinite loop (possible with proxies) */
@@ -38344,7 +37310,7 @@ static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val,
}
JS_FreeValue(ctx, v1);
JS_FreeValue(ctx, obj);
- return JS_NewBool(ctx, res);
+ return js_bool(res);
exception:
JS_FreeValue(ctx, v1);
@@ -38352,8 +37318,8 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, res = JS_EXCEPTION;
JSAtom prop = JS_ATOM_NULL;
@@ -38371,7 +37337,7 @@ static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_
if (has_prop < 0)
goto exception;
if (has_prop) {
- res = JS_NewBool(ctx, desc.flags & JS_PROP_ENUMERABLE);
+ res = js_bool(desc.flags & JS_PROP_ENUMERABLE);
js_free_desc(ctx, &desc);
} else {
res = JS_FALSE;
@@ -38383,8 +37349,8 @@ exception:
return res;
}
-static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int setter)
+static JSValue js_object___lookupGetter__(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int setter)
{
JSValue obj, res = JS_EXCEPTION;
JSAtom prop = JS_ATOM_NULL;
@@ -38404,7 +37370,7 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val,
goto exception;
if (has_prop) {
if (desc.flags & JS_PROP_GETSET)
- res = JS_DupValue(ctx, setter ? desc.setter : desc.getter);
+ res = js_dup(setter ? desc.setter : desc.getter);
else
res = JS_UNDEFINED;
js_free_desc(ctx, &desc);
@@ -38436,7 +37402,7 @@ static const JSCFunctionListEntry js_object_funcs[] = {
JS_CFUNC_DEF("defineProperties", 2, js_object_defineProperties ),
JS_CFUNC_DEF("getOwnPropertyNames", 1, js_object_getOwnPropertyNames ),
JS_CFUNC_DEF("getOwnPropertySymbols", 1, js_object_getOwnPropertySymbols ),
- JS_CFUNC_MAGIC_DEF("groupBy", 2, js_object_groupBy, 0 ),
+ JS_CFUNC_DEF("groupBy", 2, js_object_groupBy ),
JS_CFUNC_MAGIC_DEF("keys", 1, js_object_keys, JS_ITERATOR_KIND_KEY ),
JS_CFUNC_MAGIC_DEF("values", 1, js_object_keys, JS_ITERATOR_KIND_VALUE ),
JS_CFUNC_MAGIC_DEF("entries", 1, js_object_keys, JS_ITERATOR_KIND_KEY_AND_VALUE ),
@@ -38450,17 +37416,6 @@ static const JSCFunctionListEntry js_object_funcs[] = {
JS_CFUNC_MAGIC_DEF("freeze", 1, js_object_seal, 1 ),
JS_CFUNC_MAGIC_DEF("isSealed", 1, js_object_isSealed, 0 ),
JS_CFUNC_MAGIC_DEF("isFrozen", 1, js_object_isSealed, 1 ),
- JS_CFUNC_DEF("__getClass", 1, js_object___getClass ),
- //JS_CFUNC_DEF("__isObject", 1, js_object___isObject ),
- //JS_CFUNC_DEF("__isConstructor", 1, js_object___isConstructor ),
- //JS_CFUNC_DEF("__toObject", 1, js_object___toObject ),
- //JS_CFUNC_DEF("__setOwnProperty", 3, js_object___setOwnProperty ),
- //JS_CFUNC_DEF("__toPrimitive", 2, js_object___toPrimitive ),
- //JS_CFUNC_DEF("__toPropertyKey", 1, js_object___toPropertyKey ),
- //JS_CFUNC_DEF("__speciesConstructor", 2, js_object___speciesConstructor ),
- //JS_CFUNC_DEF("__isSameValueZero", 2, js_object___isSameValueZero ),
- //JS_CFUNC_DEF("__getObjectData", 1, js_object___getObjectData ),
- //JS_CFUNC_DEF("__setObjectData", 2, js_object___setObjectData ),
JS_CFUNC_DEF("fromEntries", 1, js_object_fromEntries ),
JS_CFUNC_DEF("hasOwn", 2, js_object_hasOwn ),
};
@@ -38481,15 +37436,15 @@ static const JSCFunctionListEntry js_object_proto_funcs[] = {
/* Function class */
-static JSValue js_function_proto(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_function_proto(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return JS_UNDEFINED;
}
/* XXX: add a specific eval mode so that Function("}), ({") is rejected */
-static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_function_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv, int magic)
{
JSFunctionKindEnum func_kind = magic;
int i, n, ret;
@@ -38542,9 +37497,9 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,
realm = JS_GetFunctionRealm(ctx, new_target);
if (!realm)
goto fail1;
- proto = JS_DupValue(ctx, realm->class_proto[func_kind_to_class_id[func_kind]]);
+ proto = js_dup(realm->class_proto[func_kind_to_class_id[func_kind]]);
}
- ret = JS_SetPrototypeInternal(ctx, obj, proto, TRUE);
+ ret = JS_SetPrototypeInternal(ctx, obj, proto, true);
JS_FreeValue(ctx, proto);
if (ret < 0)
goto fail1;
@@ -38559,7 +37514,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,
}
static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
- JSValueConst obj)
+ JSValue obj)
{
JSValue len_val;
len_val = JS_GetProperty(ctx, obj, JS_ATOM_length);
@@ -38571,7 +37526,7 @@ static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
}
static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
- JSValueConst obj)
+ JSValue obj)
{
JSValue len_val;
len_val = JS_GetProperty(ctx, obj, JS_ATOM_length);
@@ -38582,6 +37537,11 @@ static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
return JS_ToLengthFree(ctx, pres, len_val);
}
+static __exception int js_set_length64(JSContext *ctx, JSValue obj, int64_t len)
+{
+ return JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(len));
+}
+
static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len)
{
uint32_t i;
@@ -38593,7 +37553,7 @@ static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len)
/* XXX: should use ValueArray */
static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
- JSValueConst array_arg)
+ JSValue array_arg)
{
uint32_t len, i;
JSValue *tab, ret;
@@ -38620,7 +37580,7 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
p->fast_array &&
len == p->u.array.count) {
for(i = 0; i < len; i++) {
- tab[i] = JS_DupValue(ctx, p->u.array.u.values[i]);
+ tab[i] = js_dup(p->u.array.u.values[i]);
}
} else {
for(i = 0; i < len; i++) {
@@ -38638,10 +37598,10 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
/* magic value: 0 = normal apply, 1 = apply for constructor, 2 =
Reflect.apply */
-static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_function_apply(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
- JSValueConst this_arg, array_arg;
+ JSValue this_arg, array_arg;
uint32_t len;
JSValue *tab, ret;
@@ -38657,16 +37617,16 @@ static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
if (!tab)
return JS_EXCEPTION;
if (magic & 1) {
- ret = JS_CallConstructor2(ctx, this_val, this_arg, len, (JSValueConst *)tab);
+ ret = JS_CallConstructor2(ctx, this_val, this_arg, len, tab);
} else {
- ret = JS_Call(ctx, this_val, this_arg, len, (JSValueConst *)tab);
+ ret = JS_Call(ctx, this_val, this_arg, len, tab);
}
free_arg_list(ctx, tab, len);
return ret;
}
-static JSValue js_function_call(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_function_call(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
if (argc <= 0) {
return JS_Call(ctx, this_val, JS_UNDEFINED, 0, NULL);
@@ -38675,8 +37635,8 @@ static JSValue js_function_call(JSContext *ctx, JSValueConst this_val,
}
}
-static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_function_bind(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSBoundFunction *bf;
JSValue func_obj, name1, len_val;
@@ -38696,11 +37656,11 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val,
bf = js_malloc(ctx, sizeof(*bf) + arg_count * sizeof(JSValue));
if (!bf)
goto exception;
- bf->func_obj = JS_DupValue(ctx, this_val);
- bf->this_val = JS_DupValue(ctx, argv[0]);
+ bf->func_obj = js_dup(this_val);
+ bf->this_val = js_dup(argv[0]);
bf->argc = arg_count;
for(i = 0; i < arg_count; i++) {
- bf->argv[i] = JS_DupValue(ctx, argv[i + 1]);
+ bf->argv[i] = js_dup(argv[i + 1]);
}
p->u.bound_function = bf;
@@ -38709,7 +37669,7 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val,
if (ret < 0)
goto exception;
if (!ret) {
- len_val = JS_NewInt32(ctx, 0);
+ len_val = js_int32(0);
} else {
len_val = JS_GetProperty(ctx, this_val, JS_ATOM_length);
if (JS_IsException(len_val))
@@ -38721,7 +37681,7 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val,
len1 = 0;
else
len1 -= arg_count;
- len_val = JS_NewInt32(ctx, len1);
+ len_val = js_int32(len1);
} else if (JS_VALUE_GET_NORM_TAG(len_val) == JS_TAG_FLOAT64) {
double d = JS_VALUE_GET_FLOAT64(len_val);
if (isnan(d)) {
@@ -38733,10 +37693,10 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val,
else
d -= (double)arg_count; /* also converts -0 to +0 */
}
- len_val = JS_NewFloat64(ctx, d);
+ len_val = js_number(d);
} else {
JS_FreeValue(ctx, len_val);
- len_val = JS_NewInt32(ctx, 0);
+ len_val = js_int32(0);
}
}
JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length,
@@ -38760,8 +37720,8 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_function_toString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSObject *p;
JSFunctionKindEnum func_kind = JS_FUNC_NORMAL;
@@ -38772,10 +37732,9 @@ static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val,
p = JS_VALUE_GET_OBJ(this_val);
if (js_class_has_bytecode(p->class_id)) {
JSFunctionBytecode *b = p->u.func.function_bytecode;
- if (b->has_debug && b->debug.source) {
- return JS_NewStringLen(ctx, b->debug.source, b->debug.source_len);
- }
- func_kind = b->func_kind;
+ /* `b->source` must be pure ASCII or UTF-8 encoded */
+ if (b->source)
+ return JS_NewStringLen(ctx, b->source, b->source_len);
}
{
JSValue name;
@@ -38804,15 +37763,15 @@ static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val,
}
}
-static JSValue js_function_hasInstance(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_function_hasInstance(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
int ret;
ret = JS_OrdinaryIsInstanceOf(ctx, argv[0], this_val);
if (ret < 0)
return JS_EXCEPTION;
else
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
static const JSCFunctionListEntry js_function_proto_funcs[] = {
@@ -38822,19 +37781,22 @@ static const JSCFunctionListEntry js_function_proto_funcs[] = {
JS_CFUNC_DEF("toString", 0, js_function_toString ),
JS_CFUNC_DEF("[Symbol.hasInstance]", 1, js_function_hasInstance ),
JS_CGETSET_DEF("fileName", js_function_proto_fileName, NULL ),
- JS_CGETSET_DEF("lineNumber", js_function_proto_lineNumber, NULL ),
+ JS_CGETSET_MAGIC_DEF("lineNumber", js_function_proto_int32, NULL,
+ offsetof(JSFunctionBytecode, line_num)),
+ JS_CGETSET_MAGIC_DEF("columnNumber", js_function_proto_int32, NULL,
+ offsetof(JSFunctionBytecode, col_num)),
};
/* Error class */
-static JSValue iterator_to_array(JSContext *ctx, JSValueConst items)
+static JSValue iterator_to_array(JSContext *ctx, JSValue items)
{
JSValue iter, next_method = JS_UNDEFINED;
JSValue v, r = JS_UNDEFINED;
int64_t k;
- BOOL done;
+ int done;
- iter = JS_GetIterator(ctx, items, FALSE);
+ iter = JS_GetIterator(ctx, items, false);
if (JS_IsException(iter))
goto exception;
next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);
@@ -38858,19 +37820,19 @@ static JSValue iterator_to_array(JSContext *ctx, JSValueConst items)
JS_FreeValue(ctx, iter);
return r;
exception_close:
- JS_IteratorClose(ctx, iter, TRUE);
+ JS_IteratorClose(ctx, iter, true);
exception:
JS_FreeValue(ctx, r);
r = JS_EXCEPTION;
goto done;
}
-static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_error_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv, int magic)
{
- JSValue obj, msg, proto;
- JSValueConst message, options;
- int arg_index;
+ JSValue obj, msg, proto, cause;
+ JSValue message;
+ int present, opts;
if (JS_IsUndefined(new_target))
new_target = JS_GetActiveFunction(ctx);
@@ -38879,7 +37841,7 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
return proto;
if (!JS_IsObject(proto)) {
JSContext *realm;
- JSValueConst proto1;
+ JSValue proto1;
JS_FreeValue(ctx, proto);
realm = JS_GetFunctionRealm(ctx, new_target);
@@ -38890,15 +37852,20 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
} else {
proto1 = realm->native_error_proto[magic];
}
- proto = JS_DupValue(ctx, proto1);
+ proto = js_dup(proto1);
}
obj = JS_NewObjectProtoClass(ctx, proto, JS_CLASS_ERROR);
JS_FreeValue(ctx, proto);
if (JS_IsException(obj))
return obj;
- arg_index = (magic == JS_AGGREGATE_ERROR);
+ if (magic == JS_AGGREGATE_ERROR) {
+ message = argv[1];
+ opts = 2;
+ } else {
+ message = argv[0];
+ opts = 1;
+ }
- message = argv[arg_index++];
if (!JS_IsUndefined(message)) {
msg = JS_ToString(ctx, message);
if (unlikely(JS_IsException(msg)))
@@ -38907,19 +37874,16 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
}
- if (arg_index < argc) {
- options = argv[arg_index];
- if (JS_IsObject(options)) {
- int present = JS_HasProperty(ctx, options, JS_ATOM_cause);
- if (present < 0)
+ if (argc > opts && JS_VALUE_GET_TAG(argv[opts]) == JS_TAG_OBJECT) {
+ present = JS_HasProperty(ctx, argv[opts], JS_ATOM_cause);
+ if (unlikely(present < 0))
+ goto exception;
+ if (present) {
+ cause = JS_GetProperty(ctx, argv[opts], JS_ATOM_cause);
+ if (unlikely(JS_IsException(cause)))
goto exception;
- if (present) {
- JSValue cause = JS_GetProperty(ctx, options, JS_ATOM_cause);
- if (JS_IsException(cause))
- goto exception;
- JS_DefinePropertyValue(ctx, obj, JS_ATOM_cause, cause,
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- }
+ JS_DefinePropertyValue(ctx, obj, JS_ATOM_cause, cause,
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
}
}
@@ -38932,15 +37896,15 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
}
/* skip the Error() function in the backtrace */
- build_backtrace(ctx, obj, NULL, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL);
+ build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL);
return obj;
exception:
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
-static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_error_toString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue name, msg;
@@ -38974,11 +37938,73 @@ static const JSCFunctionListEntry js_error_proto_funcs[] = {
JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),
};
+static JSValue js_error_isError(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ return js_bool(JS_IsError(ctx, argv[0]));
+}
+
+static JSValue js_error_get_stackTraceLimit(JSContext *ctx, JSValue this_val)
+{
+ JSValue val;
+
+ val = JS_ToObject(ctx, this_val);
+ if (JS_IsException(val))
+ return val;
+ JS_FreeValue(ctx, val);
+ return js_dup(ctx->error_stack_trace_limit);
+}
+
+static JSValue js_error_set_stackTraceLimit(JSContext *ctx, JSValue this_val, JSValue value)
+{
+ if (JS_IsUndefined(this_val) || JS_IsNull(this_val))
+ return JS_ThrowTypeErrorNotAnObject(ctx);
+ ctx->error_stack_trace_limit = js_dup(value);
+ return JS_UNDEFINED;
+}
+
+static JSValue js_error_get_prepareStackTrace(JSContext *ctx, JSValue this_val)
+{
+ JSValue val;
+
+ val = JS_ToObject(ctx, this_val);
+ if (JS_IsException(val))
+ return val;
+ JS_FreeValue(ctx, val);
+ return js_dup(ctx->error_prepare_stack);
+}
+
+static JSValue js_error_set_prepareStackTrace(JSContext *ctx, JSValue this_val, JSValue value)
+{
+ if (JS_IsUndefined(this_val) || JS_IsNull(this_val))
+ return JS_ThrowTypeErrorNotAnObject(ctx);
+ JS_FreeValue(ctx, ctx->error_prepare_stack);
+ ctx->error_prepare_stack = js_dup(value);
+ return JS_UNDEFINED;
+}
+
+static JSValue js_error_capture_stack_trace(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue v = argv[0];
+ if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
+ return JS_ThrowTypeErrorNotAnObject(ctx);
+ build_backtrace(ctx, v, argv[1], NULL, 0, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL|JS_BACKTRACE_FLAG_FILTER_FUNC);
+ return JS_UNDEFINED;
+}
+
+static const JSCFunctionListEntry js_error_funcs[] = {
+ JS_CFUNC_DEF("isError", 1, js_error_isError ),
+ JS_CFUNC_DEF("captureStackTrace", 2, js_error_capture_stack_trace),
+ JS_CGETSET_DEF("stackTraceLimit", js_error_get_stackTraceLimit, js_error_set_stackTraceLimit ),
+ JS_CGETSET_DEF("prepareStackTrace", js_error_get_prepareStackTrace, js_error_set_prepareStackTrace ),
+};
+
/* AggregateError */
/* used by C code. */
static JSValue js_aggregate_error_constructor(JSContext *ctx,
- JSValueConst errors)
+ JSValue errors)
{
JSValue obj;
@@ -38987,7 +38013,7 @@ static JSValue js_aggregate_error_constructor(JSContext *ctx,
JS_CLASS_ERROR);
if (JS_IsException(obj))
return obj;
- JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, JS_DupValue(ctx, errors),
+ JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, js_dup(errors),
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
return obj;
}
@@ -38995,7 +38021,7 @@ static JSValue js_aggregate_error_constructor(JSContext *ctx,
/* Array */
static int JS_CopySubArray(JSContext *ctx,
- JSValueConst obj, int64_t to_pos,
+ JSValue obj, int64_t to_pos,
int64_t from_pos, int64_t count, int dir)
{
JSObject *p;
@@ -39032,14 +38058,14 @@ static int JS_CopySubArray(JSContext *ctx,
l = min_int64(l, to + 1);
for(j = 0; j < l; j++) {
set_value(ctx, &p->u.array.u.values[to - j],
- JS_DupValue(ctx, p->u.array.u.values[from - j]));
+ js_dup(p->u.array.u.values[from - j]));
}
} else {
l = min_int64(l, len - from);
l = min_int64(l, len - to);
for(j = 0; j < l; j++) {
set_value(ctx, &p->u.array.u.values[to + j],
- JS_DupValue(ctx, p->u.array.u.values[from + j]));
+ js_dup(p->u.array.u.values[from + j]));
}
}
i += l;
@@ -39064,8 +38090,8 @@ static int JS_CopySubArray(JSContext *ctx,
return -1;
}
-static JSValue js_array_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_array_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
{
JSValue obj;
int i;
@@ -39075,13 +38101,13 @@ static JSValue js_array_constructor(JSContext *ctx, JSValueConst new_target,
return obj;
if (argc == 1 && JS_IsNumber(argv[0])) {
uint32_t len;
- if (JS_ToArrayLengthFree(ctx, &len, JS_DupValue(ctx, argv[0]), TRUE))
+ if (JS_ToArrayLengthFree(ctx, &len, js_dup(argv[0]), true))
goto fail;
- if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, len)) < 0)
+ if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_uint32(len)) < 0)
goto fail;
} else {
for(i = 0; i < argc; i++) {
- if (JS_SetPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i])) < 0)
+ if (JS_SetPropertyUint32(ctx, obj, i, js_dup(argv[i])) < 0)
goto fail;
}
}
@@ -39091,18 +38117,18 @@ fail:
return JS_EXCEPTION;
}
-static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_from(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// from(items, mapfn = void 0, this_arg = void 0)
- JSValueConst items = argv[0], mapfn, this_arg;
- JSValueConst args[2];
+ JSValue items = argv[0], mapfn, this_arg;
+ JSValue args[2];
JSValue stack[2];
JSValue iter, r, v, v2, arrayLike;
int64_t k, len;
int done, mapping;
- mapping = FALSE;
+ mapping = false;
mapfn = JS_UNDEFINED;
this_arg = JS_UNDEFINED;
r = JS_UNDEFINED;
@@ -39131,8 +38157,8 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,
r = JS_NewArray(ctx);
if (JS_IsException(r))
goto exception;
- stack[0] = JS_DupValue(ctx, items);
- if (js_for_of_start(ctx, &stack[1], FALSE))
+ stack[0] = js_dup(items);
+ if (js_for_of_start(ctx, &stack[1], false))
goto exception;
for (k = 0;; k++) {
v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done);
@@ -39142,7 +38168,7 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,
break;
if (mapping) {
args[0] = v;
- args[1] = JS_NewInt32(ctx, k);
+ args[1] = js_int32(k);
v2 = JS_Call(ctx, mapfn, this_arg, 2, args);
JS_FreeValue(ctx, v);
v = v2;
@@ -39159,7 +38185,7 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,
goto exception;
if (js_get_length64(ctx, &len, arrayLike) < 0)
goto exception;
- v = JS_NewInt64(ctx, len);
+ v = js_int64(len);
args[0] = v;
if (JS_IsConstructor(ctx, this_val)) {
r = JS_CallConstructor(ctx, this_val, 1, args);
@@ -39175,7 +38201,7 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,
goto exception;
if (mapping) {
args[0] = v;
- args[1] = JS_NewInt32(ctx, k);
+ args[1] = js_int32(k);
v2 = JS_Call(ctx, mapfn, this_arg, 2, args);
JS_FreeValue(ctx, v);
v = v2;
@@ -39187,13 +38213,13 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,
goto exception;
}
}
- if (JS_SetProperty(ctx, r, JS_ATOM_length, JS_NewUint32(ctx, k)) < 0)
+ if (JS_SetProperty(ctx, r, JS_ATOM_length, js_uint32(k)) < 0)
goto exception;
goto done;
exception_close:
if (!JS_IsUndefined(stack[0]))
- JS_IteratorClose(ctx, stack[0], TRUE);
+ JS_IteratorClose(ctx, stack[0], true);
exception:
JS_FreeValue(ctx, r);
r = JS_EXCEPTION;
@@ -39204,27 +38230,27 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,
return r;
}
-static JSValue js_array_of(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_of(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, args[1];
int i;
if (JS_IsConstructor(ctx, this_val)) {
- args[0] = JS_NewInt32(ctx, argc);
- obj = JS_CallConstructor(ctx, this_val, 1, (JSValueConst *)args);
+ args[0] = js_int32(argc);
+ obj = JS_CallConstructor(ctx, this_val, 1, args);
} else {
obj = JS_NewArray(ctx);
}
if (JS_IsException(obj))
return JS_EXCEPTION;
for(i = 0; i < argc; i++) {
- if (JS_CreateDataPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i]),
+ if (JS_CreateDataPropertyUint32(ctx, obj, i, js_dup(argv[i]),
JS_PROP_THROW) < 0) {
goto fail;
}
}
- if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, argc)) < 0) {
+ if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_uint32(argc)) < 0) {
fail:
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
@@ -39232,25 +38258,25 @@ static JSValue js_array_of(JSContext *ctx, JSValueConst this_val,
return obj;
}
-static JSValue js_array_isArray(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_isArray(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
int ret;
ret = JS_IsArray(ctx, argv[0]);
if (ret < 0)
return JS_EXCEPTION;
else
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
static JSValue js_get_this(JSContext *ctx,
- JSValueConst this_val)
+ JSValue this_val)
{
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
}
-static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValueConst obj,
- JSValueConst len_val)
+static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValue obj,
+ JSValue len_val)
{
JSValue ctor, ret, species;
int res;
@@ -39302,12 +38328,12 @@ static const JSCFunctionListEntry js_array_funcs[] = {
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
};
-static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj)
+static int JS_isConcatSpreadable(JSContext *ctx, JSValue obj)
{
JSValue val;
if (!JS_IsObject(obj))
- return FALSE;
+ return false;
val = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_isConcatSpreadable);
if (JS_IsException(val))
return -1;
@@ -39316,14 +38342,13 @@ static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj)
return JS_IsArray(ctx, obj);
}
-static JSValue js_array_at(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_at(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, ret;
int64_t len, idx;
- JSValue *arrp;
- uint32_t count;
+ ret = JS_EXCEPTION;
obj = JS_ToObject(ctx, this_val);
if (js_get_length64(ctx, &len, obj))
goto exception;
@@ -39333,26 +38358,20 @@ static JSValue js_array_at(JSContext *ctx, JSValueConst this_val,
if (idx < 0)
idx = len + idx;
+
if (idx < 0 || idx >= len) {
ret = JS_UNDEFINED;
- } else if (js_get_fast_array(ctx, obj, &arrp, &count) && idx < count) {
- ret = JS_DupValue(ctx, arrp[idx]);
} else {
- int present = JS_TryGetPropertyInt64(ctx, obj, idx, &ret);
- if (present < 0)
- goto exception;
- if (!present)
- ret = JS_UNDEFINED;
+ ret = JS_GetPropertyInt64(ctx, obj, idx);
}
- JS_FreeValue(ctx, obj);
- return ret;
+
exception:
JS_FreeValue(ctx, obj);
- return JS_EXCEPTION;
+ return ret;
}
-static JSValue js_array_with(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_with(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue arr, obj, ret, *arrp, *pval;
JSObject *p;
@@ -39365,6 +38384,11 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val,
if (js_get_length64(ctx, &len, obj))
goto exception;
+ if (len > UINT32_MAX) {
+ JS_ThrowRangeError(ctx, "invalid array length");
+ goto exception;
+ }
+
if (JS_ToInt64Sat(ctx, &idx, argv[0]))
goto exception;
@@ -39376,24 +38400,28 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val,
goto exception;
}
- arr = js_allocate_fast_array(ctx, len);
+ arr = JS_NewArray(ctx);
if (JS_IsException(arr))
goto exception;
p = JS_VALUE_GET_OBJ(arr);
+ if (expand_fast_array(ctx, p, len) < 0)
+ goto exception;
+ p->u.array.count = len;
+
i = 0;
pval = p->u.array.u.values;
if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
for (; i < idx; i++, pval++)
- *pval = JS_DupValue(ctx, arrp[i]);
- *pval = JS_DupValue(ctx, argv[1]);
+ *pval = js_dup(arrp[i]);
+ *pval = js_dup(argv[1]);
for (i++, pval++; i < len; i++, pval++)
- *pval = JS_DupValue(ctx, arrp[i]);
+ *pval = js_dup(arrp[i]);
} else {
for (; i < idx; i++, pval++)
if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval))
goto fill_and_fail;
- *pval = JS_DupValue(ctx, argv[1]);
+ *pval = js_dup(argv[1]);
for (i++, pval++; i < len; i++, pval++) {
if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) {
fill_and_fail:
@@ -39404,7 +38432,7 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val,
}
}
- if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0)
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0)
goto exception;
ret = arr;
@@ -39416,11 +38444,11 @@ exception:
return ret;
}
-static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_concat(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, arr, val;
- JSValueConst e;
+ JSValue e;
int64_t len, k, n;
int i, res;
@@ -39429,7 +38457,7 @@ static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(obj))
goto exception;
- arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0));
+ arr = JS_ArraySpeciesCreate(ctx, obj, js_int32(0));
if (JS_IsException(arr))
goto exception;
n = 0;
@@ -39464,13 +38492,13 @@ static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val,
JS_ThrowTypeError(ctx, "Array loo long");
goto exception;
}
- if (JS_DefinePropertyValueInt64(ctx, arr, n, JS_DupValue(ctx, e),
+ if (JS_DefinePropertyValueInt64(ctx, arr, n, js_dup(e),
JS_PROP_C_W_E | JS_PROP_THROW) < 0)
goto exception;
n++;
}
}
- if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0)
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(n)) < 0)
goto exception;
JS_FreeValue(ctx, obj);
@@ -39489,26 +38517,59 @@ exception:
#define special_filter 4
#define special_TA 8
-static int js_typed_array_get_length_internal(JSContext *ctx, JSValueConst obj);
+static JSObject *get_typed_array(JSContext *ctx, JSValue this_val)
+{
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
+ goto fail;
+ p = JS_VALUE_GET_OBJ(this_val);
+ if (!is_typed_array(p->class_id)) {
+ fail:
+ JS_ThrowTypeError(ctx, "not a TypedArray");
+ return NULL;
+ }
+ return p;
+}
+
+// Be *very* careful if you touch the typed array's memory directly:
+// the length is only valid until the next call into JS land because
+// JS code can detach or resize the backing array buffer. Functions
+// like JS_GetProperty and JS_ToIndex call JS code.
+//
+// Exclusively reading or writing elements with JS_GetProperty,
+// JS_GetPropertyInt64, JS_SetProperty, etc. is safe because they
+// perform bounds checks, as does js_get_fast_array_element.
+static int js_typed_array_get_length_unsafe(JSContext *ctx, JSValue obj)
+{
+ JSObject *p;
+ p = get_typed_array(ctx, obj);
+ if (!p)
+ return -1;
+ if (typed_array_is_oob(p)) {
+ JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ return -1;
+ }
+ return p->u.array.count;
+}
static JSValue js_typed_array___speciesCreate(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv);
+ JSValue this_val,
+ int argc, JSValue *argv);
-static JSValue js_array_every(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int special)
+static JSValue js_array_every(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int special)
{
JSValue obj, val, index_val, res, ret;
- JSValueConst args[3];
- JSValueConst func, this_arg;
+ JSValue args[3];
+ JSValue func, this_arg;
int64_t len, k, n;
int present;
ret = JS_UNDEFINED;
val = JS_UNDEFINED;
if (special & special_TA) {
- obj = JS_DupValue(ctx, this_val);
- len = js_typed_array_get_length_internal(ctx, obj);
+ obj = js_dup(this_val);
+ len = js_typed_array_get_length_unsafe(ctx, obj);
if (len < 0)
goto exception;
} else {
@@ -39535,18 +38596,18 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val,
break;
case special_map:
/* XXX: JS_ArraySpeciesCreate should take int64_t */
- ret = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt64(ctx, len));
+ ret = JS_ArraySpeciesCreate(ctx, obj, js_int64(len));
if (JS_IsException(ret))
goto exception;
break;
case special_filter:
- ret = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0));
+ ret = JS_ArraySpeciesCreate(ctx, obj, js_int32(0));
if (JS_IsException(ret))
goto exception;
break;
case special_map | special_TA:
args[0] = obj;
- args[1] = JS_NewInt32(ctx, len);
+ args[1] = js_int32(len);
ret = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args);
if (JS_IsException(ret))
goto exception;
@@ -39564,16 +38625,14 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val,
val = JS_GetPropertyInt64(ctx, obj, k);
if (JS_IsException(val))
goto exception;
- present = TRUE;
+ present = true;
} else {
present = JS_TryGetPropertyInt64(ctx, obj, k, &val);
if (present < 0)
goto exception;
}
if (present) {
- index_val = JS_NewInt64(ctx, k);
- if (JS_IsException(index_val))
- goto exception;
+ index_val = js_int64(k);
args[0] = val;
args[1] = index_val;
args[2] = obj;
@@ -39602,13 +38661,13 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val,
goto exception;
break;
case special_map | special_TA:
- if (JS_SetPropertyValue(ctx, ret, JS_NewInt32(ctx, k), res, JS_PROP_THROW) < 0)
+ if (JS_SetPropertyValue(ctx, ret, js_int32(k), res, JS_PROP_THROW) < 0)
goto exception;
break;
case special_filter:
case special_filter | special_TA:
if (JS_ToBoolFree(ctx, res)) {
- if (JS_DefinePropertyValueInt64(ctx, ret, n++, JS_DupValue(ctx, val),
+ if (JS_DefinePropertyValueInt64(ctx, ret, n++, js_dup(val),
JS_PROP_C_W_E | JS_PROP_THROW) < 0)
goto exception;
}
@@ -39625,7 +38684,7 @@ done:
if (special == (special_filter | special_TA)) {
JSValue arr;
args[0] = obj;
- args[1] = JS_NewInt32(ctx, n);
+ args[1] = js_int32(n);
arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args);
if (JS_IsException(arr))
goto exception;
@@ -39650,20 +38709,20 @@ exception:
#define special_reduce 0
#define special_reduceRight 1
-static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int special)
+static JSValue js_array_reduce(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int special)
{
JSValue obj, val, index_val, acc, acc1;
- JSValueConst args[4];
- JSValueConst func;
+ JSValue args[4];
+ JSValue func;
int64_t len, k, k1;
int present;
acc = JS_UNDEFINED;
val = JS_UNDEFINED;
if (special & special_TA) {
- obj = JS_DupValue(ctx, this_val);
- len = js_typed_array_get_length_internal(ctx, obj);
+ obj = js_dup(this_val);
+ len = js_typed_array_get_length_unsafe(ctx, obj);
if (len < 0)
goto exception;
} else {
@@ -39678,7 +38737,7 @@ static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val,
k = 0;
if (argc > 1) {
- acc = JS_DupValue(ctx, argv[1]);
+ acc = js_dup(argv[1]);
} else {
for(;;) {
if (k >= len) {
@@ -39707,16 +38766,14 @@ static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val,
val = JS_GetPropertyInt64(ctx, obj, k1);
if (JS_IsException(val))
goto exception;
- present = TRUE;
+ present = true;
} else {
present = JS_TryGetPropertyInt64(ctx, obj, k1, &val);
if (present < 0)
goto exception;
}
if (present) {
- index_val = JS_NewInt64(ctx, k1);
- if (JS_IsException(index_val))
- goto exception;
+ index_val = js_int64(k1);
args[0] = acc;
args[1] = val;
args[2] = index_val;
@@ -39741,8 +38798,8 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_array_fill(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_fill(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj;
int64_t len, start, end;
@@ -39765,8 +38822,7 @@ static JSValue js_array_fill(JSContext *ctx, JSValueConst this_val,
/* XXX: should special case fast arrays */
while (start < end) {
- if (JS_SetPropertyInt64(ctx, obj, start,
- JS_DupValue(ctx, argv[0])) < 0)
+ if (JS_SetPropertyInt64(ctx, obj, start, js_dup(argv[0])) < 0)
goto exception;
start++;
}
@@ -39777,8 +38833,8 @@ static JSValue js_array_fill(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_includes(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, val;
int64_t len, n;
@@ -39790,7 +38846,7 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val,
if (js_get_length64(ctx, &len, obj))
goto exception;
- res = FALSE;
+ res = true;
if (len > 0) {
n = 0;
if (argc > 1) {
@@ -39799,10 +38855,8 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val,
}
if (js_get_fast_array(ctx, obj, &arrp, &count)) {
for (; n < count; n++) {
- if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]),
- JS_DupValue(ctx, arrp[n]),
+ if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]),
JS_EQ_SAME_VALUE_ZERO)) {
- res = TRUE;
goto done;
}
}
@@ -39811,27 +38865,27 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val,
val = JS_GetPropertyInt64(ctx, obj, n);
if (JS_IsException(val))
goto exception;
- if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val,
+ if (js_strict_eq2(ctx, js_dup(argv[0]), val,
JS_EQ_SAME_VALUE_ZERO)) {
- res = TRUE;
- break;
+ goto done;
}
}
}
+ res = false;
done:
JS_FreeValue(ctx, obj);
- return JS_NewBool(ctx, res);
+ return js_bool(res);
exception:
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
-static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_indexOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, val;
- int64_t len, n, res;
+ int64_t len, n;
JSValue *arrp;
uint32_t count;
@@ -39839,7 +38893,6 @@ static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val,
if (js_get_length64(ctx, &len, obj))
goto exception;
- res = -1;
if (len > 0) {
n = 0;
if (argc > 1) {
@@ -39848,9 +38901,8 @@ static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val,
}
if (js_get_fast_array(ctx, obj, &arrp, &count)) {
for (; n < count; n++) {
- if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]),
- JS_DupValue(ctx, arrp[n]), JS_EQ_STRICT)) {
- res = n;
+ if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]),
+ JS_EQ_STRICT)) {
goto done;
}
}
@@ -39860,55 +38912,63 @@ static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val,
if (present < 0)
goto exception;
if (present) {
- if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_STRICT)) {
- res = n;
- break;
+ if (js_strict_eq2(ctx, js_dup(argv[0]), val, JS_EQ_STRICT)) {
+ goto done;
}
}
}
}
+ n = -1;
done:
JS_FreeValue(ctx, obj);
- return JS_NewInt64(ctx, res);
+ return js_int64(n);
exception:
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
-static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_lastIndexOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, val;
- int64_t len, n, res;
- int present;
+ int64_t len, n;
+ JSValue *arrp;
+ uint32_t count;
obj = JS_ToObject(ctx, this_val);
if (js_get_length64(ctx, &len, obj))
goto exception;
- res = -1;
if (len > 0) {
n = len - 1;
if (argc > 1) {
if (JS_ToInt64Clamp(ctx, &n, argv[1], -1, len - 1, len))
goto exception;
}
- /* XXX: should special case fast arrays */
+ if (js_get_fast_array(ctx, obj, &arrp, &count) && count == len) {
+ for (; n >= 0; n--) {
+ if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]),
+ JS_EQ_STRICT)) {
+ goto done;
+ }
+ }
+ }
for (; n >= 0; n--) {
- present = JS_TryGetPropertyInt64(ctx, obj, n, &val);
+ int present = JS_TryGetPropertyInt64(ctx, obj, n, &val);
if (present < 0)
goto exception;
if (present) {
- if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_STRICT)) {
- res = n;
- break;
+ if (js_strict_eq2(ctx, js_dup(argv[0]), val, JS_EQ_STRICT)) {
+ goto done;
}
}
}
}
+ n = -1;
+ done:
JS_FreeValue(ctx, obj);
- return JS_NewInt64(ctx, res);
+ return js_int64(n);
exception:
JS_FreeValue(ctx, obj);
@@ -39922,11 +38982,11 @@ enum {
ArrayFindLastIndex,
};
-static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int mode)
+static JSValue js_array_find(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int mode)
{
- JSValueConst func, this_arg;
- JSValueConst args[3];
+ JSValue func, this_arg;
+ JSValue args[3];
JSValue obj, val, index_val, res;
int64_t len, k, end;
int dir;
@@ -39956,9 +39016,7 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
// TODO(bnoordhuis) add fast path for fast arrays
for(; k != end; k += dir) {
- index_val = JS_NewInt64(ctx, k);
- if (JS_IsException(index_val))
- goto exception;
+ index_val = js_int64(k);
val = JS_GetPropertyValue(ctx, obj, index_val);
if (JS_IsException(val))
goto exception;
@@ -39984,7 +39042,7 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
}
JS_FreeValue(ctx, obj);
if (mode == ArrayFindIndex || mode == ArrayFindLastIndex)
- return JS_NewInt32(ctx, -1);
+ return js_int32(-1);
else
return JS_UNDEFINED;
@@ -39995,8 +39053,8 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_array_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_toString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, method, ret;
@@ -40018,8 +39076,8 @@ static JSValue js_array_toString(JSContext *ctx, JSValueConst this_val,
return ret;
}
-static JSValue js_array_join(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int toLocaleString)
+static JSValue js_array_join(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int toLocaleString)
{
JSValue obj, sep = JS_UNDEFINED, el;
StringBuffer b_s, *b = &b_s;
@@ -40075,8 +39133,8 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_array_pop(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int shift)
+static JSValue js_array_pop(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int shift)
{
JSValue obj, res = JS_UNDEFINED;
int64_t len, newLen;
@@ -40116,7 +39174,7 @@ static JSValue js_array_pop(JSContext *ctx, JSValueConst this_val,
goto exception;
}
}
- if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0)
+ if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(newLen)) < 0)
goto exception;
JS_FreeValue(ctx, obj);
@@ -40128,8 +39186,8 @@ static JSValue js_array_pop(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-static JSValue js_array_push(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int unshift)
+static JSValue js_array_push(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int unshift)
{
JSValue obj;
int i;
@@ -40150,23 +39208,22 @@ static JSValue js_array_push(JSContext *ctx, JSValueConst this_val,
from = 0;
}
for(i = 0; i < argc; i++) {
- if (JS_SetPropertyInt64(ctx, obj, from + i,
- JS_DupValue(ctx, argv[i])) < 0)
+ if (JS_SetPropertyInt64(ctx, obj, from + i, js_dup(argv[i])) < 0)
goto exception;
}
- if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0)
+ if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(newLen)) < 0)
goto exception;
JS_FreeValue(ctx, obj);
- return JS_NewInt64(ctx, newLen);
+ return js_int64(newLen);
exception:
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
-static JSValue js_array_reverse(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_reverse(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, lval, hval;
JSValue *arrp;
@@ -40238,8 +39295,8 @@ static JSValue js_array_reverse(JSContext *ctx, JSValueConst this_val,
// leaves holes in sparse arrays intact whereas a.toReversed() replaces them
// with undefined, thus in effect creating a dense array.
// Does not use Array[@@species], always returns a base Array.
-static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_toReversed(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue arr, obj, ret, *arrp, *pval;
JSObject *p;
@@ -40252,18 +39309,26 @@ static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val,
if (js_get_length64(ctx, &len, obj))
goto exception;
- arr = js_allocate_fast_array(ctx, len);
+ if (len > UINT32_MAX) {
+ JS_ThrowRangeError(ctx, "invalid array length");
+ goto exception;
+ }
+
+ arr = JS_NewArray(ctx);
if (JS_IsException(arr))
goto exception;
if (len > 0) {
p = JS_VALUE_GET_OBJ(arr);
+ if (expand_fast_array(ctx, p, len) < 0)
+ goto exception;
+ p->u.array.count = len;
i = len - 1;
pval = p->u.array.u.values;
if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
for (; i >= 0; i--, pval++)
- *pval = JS_DupValue(ctx, arrp[i]);
+ *pval = js_dup(arrp[i]);
} else {
// Query order is observable; test262 expects descending order.
for (; i >= 0; i--, pval++) {
@@ -40276,7 +39341,7 @@ static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val,
}
}
- if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0)
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0)
goto exception;
}
@@ -40289,8 +39354,8 @@ exception:
return ret;
}
-static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int splice)
+static JSValue js_array_slice(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int splice)
{
JSValue obj, arr, val, len_val;
int64_t len, start, k, final, n, count, del_count, new_len;
@@ -40310,8 +39375,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
if (argc == 0) {
item_count = 0;
del_count = 0;
- } else
- if (argc == 1) {
+ } else if (argc == 1) {
item_count = 0;
del_count = len - start;
} else {
@@ -40333,7 +39397,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
}
count = max_int64(final - start, 0);
}
- len_val = JS_NewInt64(ctx, count);
+ len_val = js_int64(count);
arr = JS_ArraySpeciesCreate(ctx, obj, len_val);
JS_FreeValue(ctx, len_val);
if (JS_IsException(arr))
@@ -40350,7 +39414,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
js_is_fast_array(ctx, arr)) {
/* XXX: should share code with fast array constructor */
for (; k < final && k < count32; k++, n++) {
- if (JS_CreateDataPropertyUint32(ctx, arr, n, JS_DupValue(ctx, arrp[k]), JS_PROP_THROW) < 0)
+ if (JS_CreateDataPropertyUint32(ctx, arr, n, js_dup(arrp[k]), JS_PROP_THROW) < 0)
goto exception;
}
}
@@ -40364,7 +39428,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
goto exception;
}
}
- if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0)
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(n)) < 0)
goto exception;
if (splice) {
@@ -40381,10 +39445,10 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
}
}
for (i = 0; i < item_count; i++) {
- if (JS_SetPropertyInt64(ctx, obj, start + i, JS_DupValue(ctx, argv[i + 2])) < 0)
+ if (JS_SetPropertyInt64(ctx, obj, start + i, js_dup(argv[i + 2])) < 0)
goto exception;
}
- if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, new_len)) < 0)
+ if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(new_len)) < 0)
goto exception;
}
JS_FreeValue(ctx, obj);
@@ -40396,8 +39460,8 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_toSpliced(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue arr, obj, ret, *arrp, *pval, *last;
JSObject *p;
@@ -40430,12 +39494,17 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val,
add = argc - 2;
newlen = len + add - del;
- if (newlen > MAX_SAFE_INTEGER) {
- JS_ThrowTypeError(ctx, "invalid array length");
+ if (newlen > UINT32_MAX) {
+ // Per spec: TypeError if newlen >= 2**53, RangeError below
+ if (newlen > MAX_SAFE_INTEGER) {
+ JS_ThrowTypeError(ctx, "invalid array length");
+ } else {
+ JS_ThrowRangeError(ctx, "invalid array length");
+ }
goto exception;
}
- arr = js_allocate_fast_array(ctx, newlen);
+ arr = JS_NewArray(ctx);
if (JS_IsException(arr))
goto exception;
@@ -40443,22 +39512,26 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val,
goto done;
p = JS_VALUE_GET_OBJ(arr);
+ if (expand_fast_array(ctx, p, newlen) < 0)
+ goto exception;
+
+ p->u.array.count = newlen;
pval = &p->u.array.u.values[0];
last = &p->u.array.u.values[newlen];
if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
for (i = 0; i < start; i++, pval++)
- *pval = JS_DupValue(ctx, arrp[i]);
+ *pval = js_dup(arrp[i]);
for (j = 0; j < add; j++, pval++)
- *pval = JS_DupValue(ctx, argv[2 + j]);
+ *pval = js_dup(argv[2 + j]);
for (i += del; i < len; i++, pval++)
- *pval = JS_DupValue(ctx, arrp[i]);
+ *pval = js_dup(arrp[i]);
} else {
for (i = 0; i < start; i++, pval++)
if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval))
goto exception;
for (j = 0; j < add; j++, pval++)
- *pval = JS_DupValue(ctx, argv[2 + j]);
+ *pval = js_dup(argv[2 + j]);
for (i += del; i < len; i++, pval++)
if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval))
goto exception;
@@ -40466,7 +39539,7 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val,
assert(pval == last);
- if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, newlen)) < 0)
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(newlen)) < 0)
goto exception;
done:
@@ -40482,8 +39555,8 @@ exception:
return ret;
}
-static JSValue js_array_copyWithin(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_copyWithin(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj;
int64_t len, from, to, final, count;
@@ -40517,11 +39590,11 @@ static JSValue js_array_copyWithin(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target,
- JSValueConst source, int64_t sourceLen,
+static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValue target,
+ JSValue source, int64_t sourceLen,
int64_t targetIndex, int depth,
- JSValueConst mapperFunction,
- JSValueConst thisArg)
+ JSValue mapperFunction,
+ JSValue thisArg)
{
JSValue element;
int64_t sourceIndex, elementLen;
@@ -40539,7 +39612,7 @@ static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target,
if (!present)
continue;
if (!JS_IsUndefined(mapperFunction)) {
- JSValueConst args[3] = { element, JS_NewInt64(ctx, sourceIndex), source };
+ JSValue args[3] = { element, js_int64(sourceIndex), source };
element = JS_Call(ctx, mapperFunction, thisArg, 3, args);
JS_FreeValue(ctx, args[0]);
JS_FreeValue(ctx, args[1]);
@@ -40579,11 +39652,11 @@ fail:
return -1;
}
-static JSValue js_array_flatten(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int map)
+static JSValue js_array_flatten(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int map)
{
JSValue obj, arr;
- JSValueConst mapperFunction, thisArg;
+ JSValue mapperFunction, thisArg;
int64_t sourceLen;
int depthNum;
@@ -40608,7 +39681,7 @@ static JSValue js_array_flatten(JSContext *ctx, JSValueConst this_val,
goto exception;
}
}
- arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0));
+ arr = JS_ArraySpeciesCreate(ctx, obj, js_int32(0));
if (JS_IsException(arr))
goto exception;
if (JS_FlattenIntoArray(ctx, arr, obj, sourceLen, 0, depthNum,
@@ -40635,13 +39708,13 @@ struct array_sort_context {
JSContext *ctx;
int exception;
int has_method;
- JSValueConst method;
+ JSValue method;
};
static int js_array_cmp_generic(const void *a, const void *b, void *opaque) {
struct array_sort_context *psc = opaque;
JSContext *ctx = psc->ctx;
- JSValueConst argv[2];
+ JSValue argv[2];
JSValue res;
ValueSlot *ap = (ValueSlot *)(void *)a;
ValueSlot *bp = (ValueSlot *)(void *)b;
@@ -40686,7 +39759,7 @@ static int js_array_cmp_generic(const void *a, const void *b, void *opaque) {
goto exception;
bp->str = JS_VALUE_GET_STRING(str);
}
- cmp = js_string_compare(ctx, ap->str, bp->str);
+ cmp = js_string_compare(ap->str, bp->str);
}
if (cmp != 0)
return cmp;
@@ -40699,8 +39772,8 @@ exception:
return 0;
}
-static JSValue js_array_sort(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_sort(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
struct array_sort_context asc = { ctx, 0, 0, argv[0] };
JSValue obj = JS_UNDEFINED;
@@ -40789,8 +39862,8 @@ fail:
// leaves holes in sparse arrays intact whereas a.toSorted() replaces them
// with undefined, thus in effect creating a dense array.
// Does not use Array[@@species], always returns a base Array.
-static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_array_toSorted(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue arr, obj, ret, *arrp, *pval;
JSObject *p;
@@ -40800,7 +39873,7 @@ static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val,
ok = JS_IsUndefined(argv[0]) || JS_IsFunction(ctx, argv[0]);
if (!ok)
- return JS_ThrowTypeError(ctx, "not a function");
+ return JS_ThrowTypeErrorNotAFunction(ctx);
ret = JS_EXCEPTION;
arr = JS_UNDEFINED;
@@ -40808,17 +39881,26 @@ static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val,
if (js_get_length64(ctx, &len, obj))
goto exception;
- arr = js_allocate_fast_array(ctx, len);
+ if (len > UINT32_MAX) {
+ JS_ThrowRangeError(ctx, "invalid array length");
+ goto exception;
+ }
+
+ arr = JS_NewArray(ctx);
if (JS_IsException(arr))
goto exception;
if (len > 0) {
p = JS_VALUE_GET_OBJ(arr);
+ if (expand_fast_array(ctx, p, len) < 0)
+ goto exception;
+ p->u.array.count = len;
+
i = 0;
pval = p->u.array.u.values;
if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
for (; i < len; i++, pval++)
- *pval = JS_DupValue(ctx, arrp[i]);
+ *pval = js_dup(arrp[i]);
} else {
for (; i < len; i++, pval++) {
if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) {
@@ -40829,7 +39911,7 @@ static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val,
}
}
- if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0)
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0)
goto exception;
}
@@ -40863,7 +39945,7 @@ static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val)
}
}
-static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val,
+static void js_array_iterator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -40873,7 +39955,7 @@ static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val,
}
}
-static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab)
+static JSValue js_create_array(JSContext *ctx, int len, JSValue *tab)
{
JSValue obj;
int i;
@@ -40882,7 +39964,7 @@ static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab)
if (JS_IsException(obj))
return JS_EXCEPTION;
for(i = 0; i < len; i++) {
- if (JS_CreateDataPropertyUint32(ctx, obj, i, JS_DupValue(ctx, tab[i]), 0) < 0) {
+ if (JS_CreateDataPropertyUint32(ctx, obj, i, js_dup(tab[i]), 0) < 0) {
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
@@ -40890,8 +39972,8 @@ static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab)
return obj;
}
-static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_create_array_iterator(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSValue enum_obj, arr;
JSArrayIteratorData *it;
@@ -40918,7 +40000,7 @@ static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val,
it->obj = arr;
it->kind = kind;
it->idx = 0;
- JS_SetOpaque(enum_obj, it);
+ JS_SetOpaqueInternal(enum_obj, it);
return enum_obj;
fail1:
JS_FreeValue(ctx, enum_obj);
@@ -40927,9 +40009,9 @@ static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
- BOOL *pdone, int magic)
+static JSValue js_array_iterator_next(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
+ int *pdone, int magic)
{
JSArrayIteratorData *it;
uint32_t len, idx;
@@ -40942,17 +40024,16 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,
if (JS_IsUndefined(it->obj))
goto done;
p = JS_VALUE_GET_OBJ(it->obj);
- if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
- if (typed_array_is_detached(ctx, p)) {
- JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ if (is_typed_array(p->class_id)) {
+ if (typed_array_is_oob(p)) {
+ JS_ThrowTypeErrorArrayBufferOOB(ctx);
goto fail1;
}
len = p->u.array.count;
} else {
if (js_get_length32(ctx, &len, it->obj)) {
fail1:
- *pdone = FALSE;
+ *pdone = false;
return JS_EXCEPTION;
}
}
@@ -40961,13 +40042,13 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, it->obj);
it->obj = JS_UNDEFINED;
done:
- *pdone = TRUE;
+ *pdone = true;
return JS_UNDEFINED;
}
it->idx = idx + 1;
- *pdone = FALSE;
+ *pdone = false;
if (it->kind == JS_ITERATOR_KIND_KEY) {
- return JS_NewUint32(ctx, idx);
+ return js_uint32(idx);
} else {
val = JS_GetPropertyUint32(ctx, it->obj, idx);
if (JS_IsException(val))
@@ -40975,9 +40056,9 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,
if (it->kind == JS_ITERATOR_KIND_VALUE) {
return val;
} else {
- JSValueConst args[2];
+ JSValue args[2];
JSValue num;
- num = JS_NewUint32(ctx, idx);
+ num = js_uint32(idx);
args[0] = num;
args[1] = val;
obj = js_create_array(ctx, 2, args);
@@ -40988,14 +40069,813 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,
}
}
-static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+typedef struct JSIteratorWrapData {
+ JSValue wrapped_iter;
+ JSValue wrapped_next;
+} JSIteratorWrapData;
+
+static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValue val)
+{
+ JSObject *p = JS_VALUE_GET_OBJ(val);
+ JSIteratorWrapData *it = p->u.iterator_wrap_data;
+ if (it) {
+ JS_FreeValueRT(rt, it->wrapped_iter);
+ JS_FreeValueRT(rt, it->wrapped_next);
+ js_free_rt(rt, it);
+ }
+}
+
+static void js_iterator_wrap_mark(JSRuntime *rt, JSValue val,
+ JS_MarkFunc *mark_func)
+{
+ JSObject *p = JS_VALUE_GET_OBJ(val);
+ JSIteratorWrapData *it = p->u.iterator_wrap_data;
+ if (it) {
+ JS_MarkValue(rt, it->wrapped_iter, mark_func);
+ JS_MarkValue(rt, it->wrapped_next, mark_func);
+ }
+}
+
+static JSValue js_iterator_wrap_next(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
+ int *pdone, int magic)
+{
+ JSIteratorWrapData *it;
+ JSValue method, ret;
+ it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_WRAP);
+ if (!it)
+ return JS_EXCEPTION;
+ if (magic == GEN_MAGIC_NEXT)
+ return JS_IteratorNext(ctx, it->wrapped_iter, it->wrapped_next, argc, argv, pdone);
+ method = JS_GetProperty(ctx, it->wrapped_iter, JS_ATOM_return);
+ if (JS_IsException(method))
+ return JS_EXCEPTION;
+ if (JS_IsNull(method) || JS_IsUndefined(method)) {
+ *pdone = true;
+ return JS_UNDEFINED;
+ }
+ ret = JS_IteratorNext2(ctx, it->wrapped_iter, method, argc, argv, pdone);
+ JS_FreeValue(ctx, method);
+ return ret;
+}
+
+static const JSCFunctionListEntry js_iterator_wrap_proto_funcs[] = {
+ JS_ITERATOR_NEXT_DEF("next", 0, js_iterator_wrap_next, GEN_MAGIC_NEXT ),
+ JS_ITERATOR_NEXT_DEF("return", 0, js_iterator_wrap_next, GEN_MAGIC_RETURN ),
+};
+
+static JSValue js_iterator_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
+{
+ JSObject *p;
+
+ if (JS_TAG_OBJECT != JS_VALUE_GET_TAG(new_target))
+ return JS_ThrowTypeError(ctx, "constructor requires 'new'");
+ p = JS_VALUE_GET_OBJ(new_target);
+ if (p->class_id == JS_CLASS_C_FUNCTION)
+ if (p->u.cfunc.c_function.generic == js_iterator_constructor)
+ return JS_ThrowTypeError(ctx, "abstract class not constructable");
+ return js_create_from_ctor(ctx, new_target, JS_CLASS_ITERATOR);
+}
+
+static JSValue js_iterator_from(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue obj, method, iter;
+ JSIteratorWrapData *it;
+ int ret;
+
+ obj = argv[0];
+ if (JS_IsString(obj)) {
+ method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);
+ if (JS_IsException(method))
+ return JS_EXCEPTION;
+ return JS_CallFree(ctx, method, obj, 0, NULL);
+ }
+ if (!JS_IsObject(obj))
+ return JS_ThrowTypeError(ctx, "Iterator.from called on non-object");
+ ret = JS_OrdinaryIsInstanceOf(ctx, obj, ctx->iterator_ctor);
+ if (ret < 0)
+ return JS_EXCEPTION;
+ if (ret)
+ return js_dup(obj);
+ method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);
+ if (JS_IsException(method))
+ return JS_EXCEPTION;
+ if (JS_IsNull(method) || JS_IsUndefined(method)) {
+ method = JS_GetProperty(ctx, obj, JS_ATOM_next);
+ if (JS_IsException(method))
+ return JS_EXCEPTION;
+ iter = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_WRAP);
+ if (JS_IsException(iter))
+ goto fail;
+ it = js_malloc(ctx, sizeof(*it));
+ if (!it)
+ goto fail;
+ it->wrapped_iter = js_dup(obj);
+ it->wrapped_next = method;
+ JS_SetOpaqueInternal(iter, it);
+ } else {
+ iter = JS_GetIterator2(ctx, obj, method);
+ JS_FreeValue(ctx, method);
+ if (JS_IsException(iter))
+ return JS_EXCEPTION;
+ }
+ return iter;
+fail:
+ JS_FreeValue(ctx, method);
+ JS_FreeValue(ctx, iter);
+ return JS_EXCEPTION;
+}
+
+static int check_iterator(JSContext *ctx, JSValue obj)
+{
+ if (!JS_IsObject(obj)) {
+ JS_ThrowTypeErrorNotAnObject(ctx);
+ return -1;
+ }
+ return 0;
+}
+
+typedef struct JSIteratorHelperData {
+ JSValue obj;
+ JSValue next;
+ JSValue func; // predicate (filter) or mapper (flatMap, map)
+ JSValue inner; // innerValue (flatMap)
+ int64_t count; // limit (drop, take) or counter (filter, map, flatMap)
+ JSIteratorHelperKindEnum kind : 8;
+ uint8_t executing : 1;
+ uint8_t done : 1;
+} JSIteratorHelperData;
+
+static JSValue js_create_iterator_helper(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
+{
+ JSValue func, obj, method;
+ int64_t count;
+ JSIteratorHelperData *it;
+
+ if (check_iterator(ctx, this_val) < 0)
+ return JS_EXCEPTION;
+ func = JS_UNDEFINED;
+ count = 0;
+
+ switch(magic) {
+ case JS_ITERATOR_HELPER_KIND_DROP:
+ case JS_ITERATOR_HELPER_KIND_TAKE:
+ {
+ JSValue v;
+ double dlimit;
+ v = JS_ToNumber(ctx, argv[0]);
+ if (JS_IsException(v))
+ return JS_EXCEPTION;
+ // Check for Infinity.
+ if (JS_ToFloat64(ctx, &dlimit, v)) {
+ JS_FreeValue(ctx, v);
+ return JS_EXCEPTION;
+ }
+ if (isnan(dlimit)) {
+ JS_FreeValue(ctx, v);
+ goto fail;
+ }
+ if (!isfinite(dlimit)) {
+ JS_FreeValue(ctx, v);
+ if (dlimit < 0)
+ goto fail;
+ else
+ count = MAX_SAFE_INTEGER;
+ } else {
+ v = JS_ToIntegerFree(ctx, v);
+ if (JS_IsException(v))
+ return JS_EXCEPTION;
+ if (JS_ToInt64Free(ctx, &count, v))
+ return JS_EXCEPTION;
+ }
+ if (count < 0) {
+ fail:
+ return JS_ThrowRangeError(ctx, "must be positive");
+ }
+ }
+ break;
+ case JS_ITERATOR_HELPER_KIND_FILTER:
+ case JS_ITERATOR_HELPER_KIND_FLAT_MAP:
+ case JS_ITERATOR_HELPER_KIND_MAP:
+ {
+ func = argv[0];
+ if (check_function(ctx, func))
+ return JS_EXCEPTION;
+ }
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ method = JS_GetProperty(ctx, this_val, JS_ATOM_next);
+ if (JS_IsException(method))
+ return JS_EXCEPTION;
+ obj = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_HELPER);
+ if (JS_IsException(obj)) {
+ JS_FreeValue(ctx, method);
+ return JS_EXCEPTION;
+ }
+ it = js_malloc(ctx, sizeof(*it));
+ if (!it) {
+ JS_FreeValue(ctx, obj);
+ JS_FreeValue(ctx, method);
+ return JS_EXCEPTION;
+ }
+ it->kind = magic;
+ it->obj = js_dup(this_val);
+ it->func = js_dup(func);
+ it->next = method;
+ it->inner = JS_UNDEFINED;
+ it->count = count;
+ it->executing = 0;
+ it->done = 0;
+ JS_SetOpaqueInternal(obj, it);
+ return obj;
+}
+
+static JSValue js_iterator_proto_func(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
+{
+ JSValue item, method, ret, func, index_val, r;
+ JSValue args[2];
+ int64_t idx;
+ int done;
+
+ if (check_iterator(ctx, this_val) < 0)
+ return JS_EXCEPTION;
+ if (check_function(ctx, argv[0]))
+ return JS_EXCEPTION;
+ func = js_dup(argv[0]);
+ method = JS_GetProperty(ctx, this_val, JS_ATOM_next);
+ if (JS_IsException(method))
+ goto fail;
+
+ r = JS_UNDEFINED;
+
+ switch(magic) {
+ case JS_ITERATOR_HELPER_KIND_EVERY:
+ {
+ r = JS_TRUE;
+ for (idx = 0; /*empty*/; idx++) {
+ item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto fail;
+ if (done)
+ break;
+ index_val = js_int64(idx);
+ args[0] = item;
+ args[1] = index_val;
+ ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
+ JS_FreeValue(ctx, item);
+ JS_FreeValue(ctx, index_val);
+ if (JS_IsException(ret))
+ goto fail;
+ if (!JS_ToBoolFree(ctx, ret)) {
+ if (JS_IteratorClose(ctx, this_val, false) < 0)
+ r = JS_EXCEPTION;
+ else
+ r = JS_FALSE;
+ break;
+ }
+ index_val = JS_UNDEFINED;
+ ret = JS_UNDEFINED;
+ item = JS_UNDEFINED;
+ }
+ }
+ break;
+ case JS_ITERATOR_HELPER_KIND_FIND:
+ {
+ for (idx = 0; /*empty*/; idx++) {
+ item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto fail;
+ if (done)
+ break;
+ index_val = js_int64(idx);
+ args[0] = item;
+ args[1] = index_val;
+ ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
+ JS_FreeValue(ctx, index_val);
+ if (JS_IsException(ret)) {
+ JS_FreeValue(ctx, item);
+ goto fail;
+ }
+ if (JS_ToBoolFree(ctx, ret)) {
+ if (JS_IteratorClose(ctx, this_val, false) < 0) {
+ JS_FreeValue(ctx, item);
+ r = JS_EXCEPTION;
+ } else {
+ r = item;
+ }
+ break;
+ }
+ index_val = JS_UNDEFINED;
+ ret = JS_UNDEFINED;
+ item = JS_UNDEFINED;
+ }
+ }
+ break;
+ case JS_ITERATOR_HELPER_KIND_FOR_EACH:
+ {
+ for (idx = 0; /*empty*/; idx++) {
+ item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto fail;
+ if (done)
+ break;
+ index_val = js_int64(idx);
+ args[0] = item;
+ args[1] = index_val;
+ ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
+ JS_FreeValue(ctx, item);
+ JS_FreeValue(ctx, index_val);
+ if (JS_IsException(ret))
+ goto fail;
+ JS_FreeValue(ctx, ret);
+ index_val = JS_UNDEFINED;
+ ret = JS_UNDEFINED;
+ item = JS_UNDEFINED;
+ }
+ }
+ break;
+ case JS_ITERATOR_HELPER_KIND_SOME:
+ {
+ r = JS_FALSE;
+ for (idx = 0; /*empty*/; idx++) {
+ item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto fail;
+ if (done)
+ break;
+ index_val = js_int64(idx);
+ args[0] = item;
+ args[1] = index_val;
+ ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
+ JS_FreeValue(ctx, item);
+ JS_FreeValue(ctx, index_val);
+ if (JS_IsException(ret))
+ goto fail;
+ if (JS_ToBoolFree(ctx, ret)) {
+ if (JS_IteratorClose(ctx, this_val, false) < 0)
+ r = JS_EXCEPTION;
+ else
+ r = JS_TRUE;
+ break;
+ }
+ index_val = JS_UNDEFINED;
+ ret = JS_UNDEFINED;
+ item = JS_UNDEFINED;
+ }
+ }
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ JS_FreeValue(ctx, func);
+ JS_FreeValue(ctx, method);
+ return r;
+fail:
+ JS_IteratorClose(ctx, this_val, true);
+ JS_FreeValue(ctx, func);
+ JS_FreeValue(ctx, method);
+ return JS_EXCEPTION;
+}
+
+static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue item, method, ret, func, index_val, acc;
+ JSValue args[3];
+ int64_t idx;
+ int done;
+
+ if (check_iterator(ctx, this_val) < 0)
+ return JS_EXCEPTION;
+ if (check_function(ctx, argv[0]))
+ return JS_EXCEPTION;
+ acc = JS_UNDEFINED;
+ func = js_dup(argv[0]);
+ method = JS_GetProperty(ctx, this_val, JS_ATOM_next);
+ if (JS_IsException(method))
+ goto exception;
+ if (argc > 1) {
+ acc = js_dup(argv[1]);
+ idx = 0;
+ } else {
+ acc = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
+ if (JS_IsException(acc))
+ goto exception;
+ if (done) {
+ JS_ThrowTypeError(ctx, "empty iterator");
+ goto exception;
+ }
+ idx = 1;
+ }
+ for (/* empty */; /*empty*/; idx++) {
+ item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto exception;
+ if (done)
+ break;
+ index_val = js_int64(idx);
+ args[0] = acc;
+ args[1] = item;
+ args[2] = index_val;
+ ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
+ JS_FreeValue(ctx, item);
+ JS_FreeValue(ctx, index_val);
+ if (JS_IsException(ret))
+ goto exception;
+ JS_FreeValue(ctx, acc);
+ acc = ret;
+ index_val = JS_UNDEFINED;
+ ret = JS_UNDEFINED;
+ item = JS_UNDEFINED;
+ }
+ JS_FreeValue(ctx, func);
+ JS_FreeValue(ctx, method);
+ return acc;
+exception:
+ JS_IteratorClose(ctx, this_val, true);
+ JS_FreeValue(ctx, acc);
+ JS_FreeValue(ctx, func);
+ JS_FreeValue(ctx, method);
+ return JS_EXCEPTION;
+}
+
+static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- return JS_DupValue(ctx, this_val);
+ JSValue item, method, result;
+ int64_t idx;
+ int done;
+
+ result = JS_UNDEFINED;
+ if (check_iterator(ctx, this_val) < 0)
+ return JS_EXCEPTION;
+ method = JS_GetProperty(ctx, this_val, JS_ATOM_next);
+ if (JS_IsException(method))
+ return JS_EXCEPTION;
+ result = JS_NewArray(ctx);
+ if (JS_IsException(result))
+ goto exception;
+ for (idx = 0; /*empty*/; idx++) {
+ item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto exception;
+ if (done)
+ break;
+ if (JS_DefinePropertyValueInt64(ctx, result, idx, item,
+ JS_PROP_C_W_E | JS_PROP_THROW) < 0)
+ goto exception;
+ }
+ if (JS_SetProperty(ctx, result, JS_ATOM_length, js_uint32(idx)) < 0)
+ goto exception;
+ JS_FreeValue(ctx, method);
+ return result;
+exception:
+ JS_FreeValue(ctx, result);
+ JS_FreeValue(ctx, method);
+ return JS_EXCEPTION;
+}
+
+static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ return js_dup(this_val);
}
+static JSValue js_iterator_proto_get_toStringTag(JSContext *ctx, JSValue this_val)
+{
+ return JS_AtomToString(ctx, JS_ATOM_Iterator);
+}
+
+static JSValue js_iterator_proto_set_toStringTag(JSContext *ctx, JSValue this_val, JSValue val)
+{
+ int res;
+
+ if (check_iterator(ctx, this_val) < 0)
+ return JS_EXCEPTION;
+ if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_ITERATOR]))
+ return JS_ThrowTypeError(ctx, "Cannot assign to read only property");
+ res = JS_GetOwnProperty(ctx, NULL, this_val, JS_ATOM_Symbol_toStringTag);
+ if (res < 0)
+ return JS_EXCEPTION;
+ if (res) {
+ if (JS_SetProperty(ctx, this_val, JS_ATOM_Symbol_toStringTag, js_dup(val)) < 0)
+ return JS_EXCEPTION;
+ } else {
+ if (JS_DefinePropertyValue(ctx, this_val, JS_ATOM_Symbol_toStringTag, js_dup(val), JS_PROP_C_W_E) < 0)
+ return JS_EXCEPTION;
+ }
+ return JS_UNDEFINED;
+}
+
+static void js_iterator_helper_finalizer(JSRuntime *rt, JSValue val)
+{
+ JSObject *p = JS_VALUE_GET_OBJ(val);
+ JSIteratorHelperData *it = p->u.iterator_helper_data;
+ if (it) {
+ JS_FreeValueRT(rt, it->obj);
+ JS_FreeValueRT(rt, it->func);
+ JS_FreeValueRT(rt, it->next);
+ JS_FreeValueRT(rt, it->inner);
+ js_free_rt(rt, it);
+ }
+}
+
+static void js_iterator_helper_mark(JSRuntime *rt, JSValue val,
+ JS_MarkFunc *mark_func)
+{
+ JSObject *p = JS_VALUE_GET_OBJ(val);
+ JSIteratorHelperData *it = p->u.iterator_helper_data;
+ if (it) {
+ JS_MarkValue(rt, it->obj, mark_func);
+ JS_MarkValue(rt, it->func, mark_func);
+ JS_MarkValue(rt, it->next, mark_func);
+ JS_MarkValue(rt, it->inner, mark_func);
+ }
+}
+
+static JSValue js_iterator_helper_next(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
+ int *pdone, int magic)
+{
+ JSIteratorHelperData *it;
+ JSValue ret;
+
+ *pdone = false;
+
+ it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_HELPER);
+ if (!it)
+ return JS_EXCEPTION;
+ if (it->executing)
+ return JS_ThrowTypeError(ctx, "cannot invoke a running iterator");
+ if (it->done) {
+ *pdone = true;
+ return JS_UNDEFINED;
+ }
+
+ it->executing = 1;
+
+ switch (it->kind) {
+ case JS_ITERATOR_HELPER_KIND_DROP:
+ {
+ JSValue item, method;
+ if (magic == GEN_MAGIC_NEXT) {
+ method = js_dup(it->next);
+ } else {
+ method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
+ if (JS_IsException(method))
+ goto fail;
+ }
+ while (it->count > 0) {
+ it->count--;
+ item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
+ if (JS_IsException(item)) {
+ JS_FreeValue(ctx, method);
+ goto fail;
+ }
+ JS_FreeValue(ctx, item);
+ if (magic == GEN_MAGIC_RETURN)
+ *pdone = true;
+ if (*pdone) {
+ JS_FreeValue(ctx, method);
+ ret = JS_UNDEFINED;
+ goto done;
+ }
+ }
+
+ item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
+ JS_FreeValue(ctx, method);
+ if (JS_IsException(item))
+ goto fail;
+ ret = item;
+ goto done;
+ }
+ break;
+ case JS_ITERATOR_HELPER_KIND_FILTER:
+ {
+ JSValue item, method, selected, index_val, args[2];
+ if (magic == GEN_MAGIC_NEXT) {
+ method = js_dup(it->next);
+ } else {
+ method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
+ if (JS_IsException(method))
+ goto fail;
+ }
+ filter_again:
+ item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
+ if (JS_IsException(item)) {
+ JS_FreeValue(ctx, method);
+ goto fail;
+ }
+ if (*pdone || magic == GEN_MAGIC_RETURN) {
+ JS_FreeValue(ctx, method);
+ ret = item;
+ goto done;
+ }
+ index_val = js_int64(it->count++);
+ args[0] = item;
+ args[1] = index_val;
+ selected = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
+ JS_FreeValue(ctx, index_val);
+ if (JS_IsException(selected)) {
+ JS_FreeValue(ctx, method);
+ goto fail;
+ }
+ if (JS_ToBoolFree(ctx, selected)) {
+ JS_FreeValue(ctx, method);
+ ret = item;
+ goto done;
+ }
+ goto filter_again;
+ }
+ break;
+ case JS_ITERATOR_HELPER_KIND_FLAT_MAP:
+ {
+ JSValue item, method, index_val, args[2], iter;
+ flat_map_again:
+ if (JS_IsUndefined(it->inner)) {
+ if (magic == GEN_MAGIC_NEXT) {
+ method = js_dup(it->next);
+ } else {
+ method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
+ if (JS_IsException(method))
+ goto fail;
+ }
+ item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
+ JS_FreeValue(ctx, method);
+ if (JS_IsException(item))
+ goto fail;
+ if (*pdone || magic == GEN_MAGIC_RETURN) {
+ ret = item;
+ goto done;
+ }
+ index_val = js_int64(it->count++);
+ args[0] = item;
+ args[1] = index_val;
+ ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
+ JS_FreeValue(ctx, item);
+ JS_FreeValue(ctx, index_val);
+ if (JS_IsException(ret))
+ goto fail;
+ if (!JS_IsObject(ret)) {
+ JS_FreeValue(ctx, ret);
+ JS_ThrowTypeError(ctx, "not an object");
+ goto fail;
+ }
+ method = JS_GetProperty(ctx, ret, JS_ATOM_Symbol_iterator);
+ if (JS_IsException(method)) {
+ JS_FreeValue(ctx, ret);
+ goto fail;
+ }
+ if (JS_IsNull(method) || JS_IsUndefined(method)) {
+ JS_FreeValue(ctx, method);
+ iter = ret;
+ } else {
+ iter = JS_GetIterator2(ctx, ret, method);
+ JS_FreeValue(ctx, method);
+ JS_FreeValue(ctx, ret);
+ if (JS_IsException(iter))
+ goto fail;
+ }
+
+ it->inner = iter;
+ }
+
+ if (magic == GEN_MAGIC_NEXT)
+ method = JS_GetProperty(ctx, it->inner, JS_ATOM_next);
+ else
+ method = JS_GetProperty(ctx, it->inner, JS_ATOM_return);
+ if (JS_IsException(method)) {
+ inner_fail:
+ JS_IteratorClose(ctx, it->inner, false);
+ JS_FreeValue(ctx, it->inner);
+ it->inner = JS_UNDEFINED;
+ goto fail;
+ }
+ if (magic == GEN_MAGIC_RETURN && (JS_IsUndefined(method) || JS_IsNull(method))) {
+ goto inner_end;
+ } else {
+ item = JS_IteratorNext(ctx, it->inner, method, 0, NULL, pdone);
+ JS_FreeValue(ctx, method);
+ if (JS_IsException(item))
+ goto inner_fail;
+ }
+ if (*pdone) {
+ inner_end:
+ *pdone = false; // The outer iterator must continue.
+ JS_IteratorClose(ctx, it->inner, false);
+ JS_FreeValue(ctx, it->inner);
+ it->inner = JS_UNDEFINED;
+ goto flat_map_again;
+ }
+ ret = item;
+ goto done;
+ }
+ break;
+ case JS_ITERATOR_HELPER_KIND_MAP:
+ {
+ JSValue item, method, index_val, args[2];
+ if (magic == GEN_MAGIC_NEXT) {
+ method = js_dup(it->next);
+ } else {
+ method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
+ if (JS_IsException(method))
+ goto fail;
+ }
+ item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
+ JS_FreeValue(ctx, method);
+ if (JS_IsException(item))
+ goto fail;
+ if (*pdone || magic == GEN_MAGIC_RETURN) {
+ ret = item;
+ goto done;
+ }
+ index_val = js_int64(it->count++);
+ args[0] = item;
+ args[1] = index_val;
+ ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
+ JS_FreeValue(ctx, index_val);
+ if (JS_IsException(ret))
+ goto fail;
+ goto done;
+ }
+ break;
+ case JS_ITERATOR_HELPER_KIND_TAKE:
+ {
+ JSValue item, method;
+ if (it->count > 0) {
+ if (magic == GEN_MAGIC_NEXT) {
+ method = js_dup(it->next);
+ } else {
+ method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
+ if (JS_IsException(method))
+ goto fail;
+ }
+ it->count--;
+ item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
+ JS_FreeValue(ctx, method);
+ if (JS_IsException(item))
+ goto fail;
+ ret = item;
+ goto done;
+ }
+
+ *pdone = true;
+ if (JS_IteratorClose(ctx, it->obj, false))
+ ret = JS_EXCEPTION;
+ else
+ ret = JS_UNDEFINED;
+ goto done;
+ }
+ break;
+ default:
+ abort();
+ }
+
+done:
+ it->done = magic == GEN_MAGIC_NEXT ? *pdone : 1;
+ it->executing = 0;
+ return ret;
+fail:
+ /* close the iterator object, preserving pending exception */
+ JS_IteratorClose(ctx, it->obj, true);
+ ret = JS_EXCEPTION;
+ goto done;
+}
+
+static const JSCFunctionListEntry js_iterator_funcs[] = {
+ JS_CFUNC_DEF("from", 1, js_iterator_from ),
+};
+
static const JSCFunctionListEntry js_iterator_proto_funcs[] = {
+ JS_CFUNC_MAGIC_DEF("drop", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_DROP ),
+ JS_CFUNC_MAGIC_DEF("filter", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_FILTER ),
+ JS_CFUNC_MAGIC_DEF("flatMap", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_FLAT_MAP ),
+ JS_CFUNC_MAGIC_DEF("map", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_MAP ),
+ JS_CFUNC_MAGIC_DEF("take", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_TAKE ),
+ JS_CFUNC_MAGIC_DEF("every", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_EVERY ),
+ JS_CFUNC_MAGIC_DEF("find", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_FIND),
+ JS_CFUNC_MAGIC_DEF("forEach", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_FOR_EACH ),
+ JS_CFUNC_MAGIC_DEF("some", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_SOME ),
+ JS_CFUNC_DEF("reduce", 1, js_iterator_proto_reduce ),
+ JS_CFUNC_DEF("toArray", 0, js_iterator_proto_toArray ),
JS_CFUNC_DEF("[Symbol.iterator]", 0, js_iterator_proto_iterator ),
+ JS_CGETSET_DEF("[Symbol.toStringTag]", js_iterator_proto_get_toStringTag, js_iterator_proto_set_toStringTag),
+};
+
+static const JSCFunctionListEntry js_iterator_helper_proto_funcs[] = {
+ JS_ITERATOR_NEXT_DEF("next", 0, js_iterator_helper_next, GEN_MAGIC_NEXT ),
+ JS_ITERATOR_NEXT_DEF("return", 0, js_iterator_helper_next, GEN_MAGIC_RETURN ),
+ JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Iterator Helper", JS_PROP_CONFIGURABLE ),
};
static const JSCFunctionListEntry js_array_proto_funcs[] = {
@@ -41047,39 +40927,26 @@ static const JSCFunctionListEntry js_array_iterator_proto_funcs[] = {
/* Number */
-static JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_number_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
{
JSValue val, obj;
if (argc == 0) {
- val = JS_NewInt32(ctx, 0);
+ val = js_int32(0);
} else {
val = JS_ToNumeric(ctx, argv[0]);
if (JS_IsException(val))
return val;
switch(JS_VALUE_GET_TAG(val)) {
case JS_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
-#endif
{
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
+ JSBigInt *p = JS_VALUE_GET_PTR(val);
double d;
bf_get_float64(&p->num, &d, BF_RNDN);
JS_FreeValue(ctx, val);
- val = JS_NewFloat64(ctx, d);
+ val = js_float64(d);
}
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_DECIMAL:
- val = JS_ToStringFree(ctx, val);
- if (JS_IsException(val))
- return val;
- val = JS_ToNumberFree(ctx, val);
- if (JS_IsException(val))
- return val;
- break;
-#endif
default:
break;
}
@@ -41094,59 +40961,42 @@ static JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target,
}
}
-#if 0
-static JSValue js_number___toInteger(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[0]));
-}
-
-static JSValue js_number___toLength(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- int64_t v;
- if (JS_ToLengthFree(ctx, &v, JS_DupValue(ctx, argv[0])))
- return JS_EXCEPTION;
- return JS_NewInt64(ctx, v);
-}
-#endif
-
-static JSValue js_number_isNaN(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_number_isNaN(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
if (!JS_IsNumber(argv[0]))
return JS_FALSE;
return js_global_isNaN(ctx, this_val, argc, argv);
}
-static JSValue js_number_isFinite(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_number_isFinite(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
if (!JS_IsNumber(argv[0]))
return JS_FALSE;
return js_global_isFinite(ctx, this_val, argc, argv);
}
-static JSValue js_number_isInteger(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_number_isInteger(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
int ret;
ret = JS_NumberIsInteger(ctx, argv[0]);
if (ret < 0)
return JS_EXCEPTION;
else
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
-static JSValue js_number_isSafeInteger(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_number_isSafeInteger(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
double d;
if (!JS_IsNumber(argv[0]))
return JS_FALSE;
if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))
return JS_EXCEPTION;
- return JS_NewBool(ctx, is_safe_integer(d));
+ return js_bool(is_safe_integer(d));
}
static const JSCFunctionListEntry js_number_funcs[] = {
@@ -41159,52 +41009,51 @@ static const JSCFunctionListEntry js_number_funcs[] = {
JS_CFUNC_DEF("isSafeInteger", 1, js_number_isSafeInteger ),
JS_PROP_DOUBLE_DEF("MAX_VALUE", 1.7976931348623157e+308, 0 ),
JS_PROP_DOUBLE_DEF("MIN_VALUE", 5e-324, 0 ),
- JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ),
+ JS_PROP_U2D_DEF("NaN", 0x7FF8ull<<48, 0 ), // workaround for msvc
JS_PROP_DOUBLE_DEF("NEGATIVE_INFINITY", -INFINITY, 0 ),
JS_PROP_DOUBLE_DEF("POSITIVE_INFINITY", INFINITY, 0 ),
JS_PROP_DOUBLE_DEF("EPSILON", 2.220446049250313e-16, 0 ), /* ES6 */
JS_PROP_DOUBLE_DEF("MAX_SAFE_INTEGER", 9007199254740991.0, 0 ), /* ES6 */
JS_PROP_DOUBLE_DEF("MIN_SAFE_INTEGER", -9007199254740991.0, 0 ), /* ES6 */
- //JS_CFUNC_DEF("__toInteger", 1, js_number___toInteger ),
- //JS_CFUNC_DEF("__toLength", 1, js_number___toLength ),
};
-static JSValue js_thisNumberValue(JSContext *ctx, JSValueConst this_val)
+static JSValue js_thisNumberValue(JSContext *ctx, JSValue this_val)
{
if (JS_IsNumber(this_val))
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(this_val);
if (p->class_id == JS_CLASS_NUMBER) {
if (JS_IsNumber(p->u.object_data))
- return JS_DupValue(ctx, p->u.object_data);
+ return js_dup(p->u.object_data);
}
}
return JS_ThrowTypeError(ctx, "not a number");
}
-static JSValue js_number_valueOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_number_valueOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return js_thisNumberValue(ctx, this_val);
}
-static int js_get_radix(JSContext *ctx, JSValueConst val)
+static int js_get_radix(JSContext *ctx, JSValue val)
{
int radix;
if (JS_ToInt32Sat(ctx, &radix, val))
return -1;
if (radix < 2 || radix > 36) {
- JS_ThrowRangeError(ctx, "radix must be between 2 and 36");
+ JS_ThrowRangeError(ctx, "toString() radix argument must be between 2 and 36");
return -1;
}
return radix;
}
-static JSValue js_number_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_number_toString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
+ char buf[72];
JSValue val;
int base;
double d;
@@ -41213,30 +41062,32 @@ static JSValue js_number_toString(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(val))
return val;
if (magic || JS_IsUndefined(argv[0])) {
+ if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) {
+ size_t len = i32toa(buf, JS_VALUE_GET_INT(val));
+ return js_new_string8_len(ctx, buf, len);
+ }
base = 10;
} else {
base = js_get_radix(ctx, argv[0]);
- if (base < 0)
- goto fail;
+ if (base < 0) {
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
}
if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) {
- char buf1[70], *ptr;
- ptr = i64toa(buf1 + sizeof(buf1), JS_VALUE_GET_INT(val), base);
- return JS_NewString(ctx, ptr);
+ size_t len = i32toa_radix(buf, JS_VALUE_GET_INT(val), base);
+ return js_new_string8_len(ctx, buf, len);
}
if (JS_ToFloat64Free(ctx, &d, val))
return JS_EXCEPTION;
- if (base != 10 && isfinite(d)) {
+ if (base != 10)
return js_dtoa_radix(ctx, d, base);
- }
- return js_dtoa(ctx, d, base, 0, JS_DTOA_VAR_FORMAT);
- fail:
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
+
+ return js_dtoa(ctx, d, 0, JS_DTOA_TOSTRING);
}
-static JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_number_toFixed(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue val;
int f;
@@ -41249,21 +41100,23 @@ static JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
if (JS_ToInt32Sat(ctx, &f, argv[0]))
return JS_EXCEPTION;
- if (f < 0 || f > 100)
- return JS_ThrowRangeError(ctx, "invalid number of digits");
+ if (f < 0 || f > 100) {
+ return JS_ThrowRangeError(ctx, "toFixed() digits argument must be between 0 and 100");
+ }
if (fabs(d) >= 1e21) {
- return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
+ // use ToString(d)
+ return js_dtoa(ctx, d, 0, JS_DTOA_TOSTRING);
} else {
- return js_dtoa(ctx, d, 10, f, JS_DTOA_FRAC_FORMAT);
+ return js_dtoa(ctx, d, f, JS_DTOA_FIXED);
}
}
-static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_number_toExponential(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue val;
- int f, flags;
double d;
+ int f;
val = js_thisNumberValue(ctx, this_val);
if (JS_IsException(val))
@@ -41272,23 +41125,19 @@ static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
if (JS_ToInt32Sat(ctx, &f, argv[0]))
return JS_EXCEPTION;
- if (!isfinite(d)) {
- return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
- }
- if (JS_IsUndefined(argv[0])) {
- flags = 0;
- f = 0;
- } else {
- if (f < 0 || f > 100)
- return JS_ThrowRangeError(ctx, "invalid number of digits");
- f++;
- flags = JS_DTOA_FIXED_FORMAT;
+ if (!isfinite(d))
+ return js_dtoa_infinite(ctx, d);
+ if (!JS_IsUndefined(argv[0])) {
+ if (f < 0 || f > 100) {
+ return JS_ThrowRangeError(ctx, "toExponential() argument must be between 0 and 100");
+ }
+ f += 1; /* number of significant digits between 1 and 101 */
}
- return js_dtoa(ctx, d, 10, f, flags | JS_DTOA_FORCE_EXP);
+ return js_dtoa(ctx, d, f, JS_DTOA_EXPONENTIAL);
}
-static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_number_toPrecision(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue val;
int p;
@@ -41300,16 +41149,15 @@ static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val,
if (JS_ToFloat64Free(ctx, &d, val))
return JS_EXCEPTION;
if (JS_IsUndefined(argv[0]))
- goto to_string;
+ return js_dtoa(ctx, d, 0, JS_DTOA_TOSTRING);
if (JS_ToInt32Sat(ctx, &p, argv[0]))
return JS_EXCEPTION;
- if (!isfinite(d)) {
- to_string:
- return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
+ if (!isfinite(d))
+ return js_dtoa_infinite(ctx, d);
+ if (p < 1 || p > 100) {
+ return JS_ThrowRangeError(ctx, "toPrecision() argument must be between 1 and 100");
}
- if (p < 1 || p > 100)
- return JS_ThrowRangeError(ctx, "invalid number of digits");
- return js_dtoa(ctx, d, 10, p, JS_DTOA_FIXED_FORMAT);
+ return js_dtoa(ctx, d, p, JS_DTOA_PRECISION);
}
static const JSCFunctionListEntry js_number_proto_funcs[] = {
@@ -41321,54 +41169,54 @@ static const JSCFunctionListEntry js_number_proto_funcs[] = {
JS_CFUNC_DEF("valueOf", 0, js_number_valueOf ),
};
-static JSValue js_parseInt(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_parseInt(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- const char *str, *p;
+ const char *str;
int radix, flags;
JSValue ret;
+ size_t len;
- str = JS_ToCString(ctx, argv[0]);
+ str = JS_ToCStringLen(ctx, &len, argv[0]);
if (!str)
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &radix, argv[1])) {
JS_FreeCString(ctx, str);
return JS_EXCEPTION;
}
- if (radix != 0 && (radix < 2 || radix > 36)) {
- ret = JS_NAN;
- } else {
- p = str;
- p += skip_spaces(p);
- flags = ATOD_INT_ONLY | ATOD_ACCEPT_PREFIX_AFTER_SIGN;
- ret = js_atof(ctx, p, NULL, radix, flags);
+ flags = ATOD_TRIM_SPACES;
+ if (radix == 0) {
+ flags |= ATOD_ACCEPT_HEX_PREFIX; // Only 0x and 0X are supported
+ radix = 10;
}
+ ret = js_atof(ctx, str, len, NULL, radix, flags);
JS_FreeCString(ctx, str);
return ret;
}
-static JSValue js_parseFloat(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_parseFloat(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- const char *str, *p;
+ const char *str;
JSValue ret;
+ int flags;
+ size_t len;
- str = JS_ToCString(ctx, argv[0]);
+ str = JS_ToCStringLen(ctx, &len, argv[0]);
if (!str)
return JS_EXCEPTION;
- p = str;
- p += skip_spaces(p);
- ret = js_atof(ctx, p, NULL, 10, 0);
+ flags = ATOD_TRIM_SPACES | ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_INFINITY;
+ ret = js_atof(ctx, str, len, NULL, 10, flags);
JS_FreeCString(ctx, str);
return ret;
}
/* Boolean */
-static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_boolean_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
{
JSValue val, obj;
- val = JS_NewBool(ctx, JS_ToBool(ctx, argv[0]));
+ val = js_bool(JS_ToBool(ctx, argv[0]));
if (!JS_IsUndefined(new_target)) {
obj = js_create_from_ctor(ctx, new_target, JS_CLASS_BOOLEAN);
if (!JS_IsException(obj))
@@ -41379,10 +41227,10 @@ static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst new_target,
}
}
-static JSValue js_thisBooleanValue(JSContext *ctx, JSValueConst this_val)
+static JSValue js_thisBooleanValue(JSContext *ctx, JSValue this_val)
{
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_BOOL)
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(this_val);
@@ -41394,8 +41242,8 @@ static JSValue js_thisBooleanValue(JSContext *ctx, JSValueConst this_val)
return JS_ThrowTypeError(ctx, "not a boolean");
}
-static JSValue js_boolean_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_boolean_toString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue val = js_thisBooleanValue(ctx, this_val);
if (JS_IsException(val))
@@ -41404,8 +41252,8 @@ static JSValue js_boolean_toString(JSContext *ctx, JSValueConst this_val,
JS_ATOM_true : JS_ATOM_false);
}
-static JSValue js_boolean_valueOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_boolean_valueOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return js_thisBooleanValue(ctx, this_val);
}
@@ -41419,7 +41267,7 @@ static const JSCFunctionListEntry js_boolean_proto_funcs[] = {
static int js_string_get_own_property(JSContext *ctx,
JSPropertyDescriptor *desc,
- JSValueConst obj, JSAtom prop)
+ JSValue obj, JSAtom prop)
{
JSObject *p;
JSString *p1;
@@ -41439,18 +41287,18 @@ static int js_string_get_own_property(JSContext *ctx,
desc->getter = JS_UNDEFINED;
desc->setter = JS_UNDEFINED;
}
- return TRUE;
+ return true;
}
}
}
- return FALSE;
+ return false;
}
static int js_string_define_own_property(JSContext *ctx,
- JSValueConst this_obj,
- JSAtom prop, JSValueConst val,
- JSValueConst getter,
- JSValueConst setter, int flags)
+ JSValue this_obj,
+ JSAtom prop, JSValue val,
+ JSValue getter,
+ JSValue setter, int flags)
{
uint32_t idx;
JSObject *p;
@@ -41478,7 +41326,7 @@ static int js_string_define_own_property(JSContext *ctx,
return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");
}
}
- return TRUE;
+ return true;
} else {
def:
return JS_DefineProperty(ctx, this_obj, prop, val, getter, setter,
@@ -41487,17 +41335,17 @@ static int js_string_define_own_property(JSContext *ctx,
}
static int js_string_delete_property(JSContext *ctx,
- JSValueConst obj, JSAtom prop)
+ JSValue obj, JSAtom prop)
{
uint32_t idx;
if (__JS_AtomIsTaggedInt(prop)) {
idx = __JS_AtomToUInt32(prop);
if (idx < js_string_obj_get_length(ctx, obj)) {
- return FALSE;
+ return false;
}
}
- return TRUE;
+ return true;
}
static const JSClassExoticMethods js_string_exotic_methods = {
@@ -41506,8 +41354,8 @@ static const JSClassExoticMethods js_string_exotic_methods = {
.delete_property = js_string_delete_property,
};
-static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_string_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
{
JSValue val, obj;
if (argc == 0) {
@@ -41528,7 +41376,7 @@ static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target,
obj = js_create_from_ctor(ctx, new_target, JS_CLASS_STRING);
if (!JS_IsException(obj)) {
JS_SetObjectData(ctx, obj, val);
- JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, JS_NewInt32(ctx, p1->len), 0);
+ JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, js_int32(p1->len), 0);
}
return obj;
} else {
@@ -41536,27 +41384,33 @@ static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target,
}
}
-static JSValue js_thisStringValue(JSContext *ctx, JSValueConst this_val)
+static JSValue js_thisStringValue(JSContext *ctx, JSValue this_val)
{
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_STRING)
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(this_val);
if (p->class_id == JS_CLASS_STRING) {
if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING)
- return JS_DupValue(ctx, p->u.object_data);
+ return js_dup(p->u.object_data);
}
}
return JS_ThrowTypeError(ctx, "not a string");
}
-static JSValue js_string_fromCharCode(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_fromCharCode(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
int i;
StringBuffer b_s, *b = &b_s;
+ // shortcut for single argument common case
+ if (argc == 1 && JS_VALUE_GET_TAG(argv[0]) == JS_TAG_INT) {
+ uint16_t c16 = JS_VALUE_GET_INT(argv[0]);
+ return js_new_string_char(ctx, c16);
+ }
+
string_buffer_init(ctx, b, argc);
for(i = 0; i < argc; i++) {
@@ -41569,15 +41423,30 @@ static JSValue js_string_fromCharCode(JSContext *ctx, JSValueConst this_val,
return string_buffer_end(b);
}
-static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_fromCodePoint(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
double d;
int i, c;
- StringBuffer b_s, *b = &b_s;
+ StringBuffer b_s, *b = NULL;
- /* XXX: could pre-compute string length if all arguments are JS_TAG_INT */
+ // shortcut for single argument common case
+ if (argc == 1 && JS_VALUE_GET_TAG(argv[0]) == JS_TAG_INT) {
+ c = JS_VALUE_GET_INT(argv[0]);
+ if (c < 0 || c > 0x10ffff)
+ goto range_error;
+ if (c <= 0xffff) {
+ return js_new_string_char(ctx, c);
+ } else {
+ uint16_t c16[2];
+ c16[0] = get_hi_surrogate(c);
+ c16[1] = get_lo_surrogate(c);
+ return js_new_string16_len(ctx, c16, 2);
+ }
+ }
+ /* XXX: could pre-compute string length if all arguments are JS_TAG_INT */
+ b = &b_s;
if (string_buffer_init(ctx, b, argc))
goto fail;
for(i = 0; i < argc; i++) {
@@ -41588,7 +41457,7 @@ static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val,
} else {
if (JS_ToFloat64(ctx, &d, argv[i]))
goto fail;
- if (isnan(d) || d < 0 || d > 0x10ffff || (c = (int)d) != d)
+ if (!(d >= 0 && d <= 0x10ffff) || (c = (int)d) != d)
goto range_error;
}
if (string_buffer_putc(b, c))
@@ -41599,12 +41468,12 @@ static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val,
range_error:
JS_ThrowRangeError(ctx, "invalid code point");
fail:
- string_buffer_free(b);
+ if (b) string_buffer_free(b);
return JS_EXCEPTION;
}
-static JSValue js_string_raw(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_raw(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// raw(temp,...a)
JSValue cooked, val, raw;
@@ -41644,8 +41513,8 @@ exception:
}
/* only used in test262 */
-JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+JSValue js_string_codePointRange(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
uint32_t start, end, i, n;
StringBuffer b_s, *b = &b_s;
@@ -41670,19 +41539,35 @@ JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val,
return string_buffer_end(b);
}
-#if 0
-static JSValue js_string___isSpace(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_at(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- int c;
- if (JS_ToInt32(ctx, &c, argv[0]))
+ JSValue val, ret;
+ JSString *p;
+ int idx, c;
+
+ val = JS_ToStringCheckObject(ctx, this_val);
+ if (JS_IsException(val))
+ return val;
+ p = JS_VALUE_GET_STRING(val);
+ if (JS_ToInt32Sat(ctx, &idx, argv[0])) {
+ JS_FreeValue(ctx, val);
return JS_EXCEPTION;
- return JS_NewBool(ctx, lre_is_space(c));
+ }
+ if (idx < 0)
+ idx = p->len + idx;
+ if (idx < 0 || idx >= p->len) {
+ ret = JS_UNDEFINED;
+ } else {
+ c = string_get(p, idx);
+ ret = js_new_string_char(ctx, c);
+ }
+ JS_FreeValue(ctx, val);
+ return ret;
}
-#endif
-static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_charCodeAt(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue val, ret;
JSString *p;
@@ -41700,14 +41585,14 @@ static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val,
ret = JS_NAN;
} else {
c = string_get(p, idx);
- ret = JS_NewInt32(ctx, c);
+ ret = js_int32(c);
}
JS_FreeValue(ctx, val);
return ret;
}
-static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int is_at)
+static JSValue js_string_charAt(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue val, ret;
JSString *p;
@@ -41721,13 +41606,8 @@ static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, val);
return JS_EXCEPTION;
}
- if (idx < 0 && is_at)
- idx += p->len;
if (idx < 0 || idx >= p->len) {
- if (is_at)
- ret = JS_UNDEFINED;
- else
- ret = js_new_string8(ctx, NULL, 0);
+ ret = JS_AtomToString(ctx, JS_ATOM_empty_string);
} else {
c = string_get(p, idx);
ret = js_new_string_char(ctx, c);
@@ -41736,8 +41616,8 @@ static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val,
return ret;
}
-static JSValue js_string_codePointAt(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_codePointAt(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue val, ret;
JSString *p;
@@ -41755,14 +41635,14 @@ static JSValue js_string_codePointAt(JSContext *ctx, JSValueConst this_val,
ret = JS_UNDEFINED;
} else {
c = string_getc(p, &idx);
- ret = JS_NewInt32(ctx, c);
+ ret = js_int32(c);
}
JS_FreeValue(ctx, val);
return ret;
}
-static JSValue js_string_concat(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_concat(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue r;
int i;
@@ -41774,7 +41654,7 @@ static JSValue js_string_concat(JSContext *ctx, JSValueConst this_val,
for (i = 0; i < argc; i++) {
if (JS_IsException(r))
break;
- r = JS_ConcatString(ctx, r, JS_DupValue(ctx, argv[i]));
+ r = JS_ConcatString(ctx, r, js_dup(argv[i]));
}
return r;
}
@@ -41825,7 +41705,7 @@ static int string_indexof(JSString *p1, JSString *p2, int from)
return -1;
}
-static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode)
+static int64_t string_advance_index(JSString *p, int64_t index, bool unicode)
{
if (!unicode || index >= p->len || !p->is_wide_char) {
index++;
@@ -41837,82 +41717,83 @@ static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode)
return index;
}
-/* return the position of the first invalid character in the string or
- -1 if none */
-static int js_string_find_invalid_codepoint(JSString *p)
-{
- int i;
- if (!p->is_wide_char)
- return -1;
- for(i = 0; i < p->len; i++) {
- uint32_t c = p->u.str16[i];
- if (is_surrogate(c)) {
- if (is_hi_surrogate(c) && (i + 1) < p->len
- && is_lo_surrogate(p->u.str16[i + 1])) {
- i++;
- } else {
- return i;
- }
- }
- }
- return -1;
-}
-
-static JSValue js_string_isWellFormed(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_isWellFormed(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue str;
+ JSValue ret;
JSString *p;
- BOOL ret;
+ uint32_t c, i, n;
+ ret = JS_TRUE;
str = JS_ToStringCheckObject(ctx, this_val);
if (JS_IsException(str))
return JS_EXCEPTION;
+
p = JS_VALUE_GET_STRING(str);
- ret = (js_string_find_invalid_codepoint(p) < 0);
+ if (!p->is_wide_char || p->len == 0)
+ goto done; // by definition well-formed
+
+ for (i = 0, n = p->len; i < n; i++) {
+ c = p->u.str16[i];
+ if (!is_surrogate(c))
+ continue;
+ if (is_lo_surrogate(c) || i + 1 == n)
+ break;
+ c = p->u.str16[++i];
+ if (!is_lo_surrogate(c))
+ break;
+ }
+
+ if (i < n)
+ ret = JS_FALSE;
+
+done:
JS_FreeValue(ctx, str);
- return JS_NewBool(ctx, ret);
+ return ret;
}
-static JSValue js_string_toWellFormed(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_toWellFormed(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValue str, ret;
+ JSValue str;
+ JSValue ret;
JSString *p;
- int i;
+ uint32_t c, i, n;
str = JS_ToStringCheckObject(ctx, this_val);
if (JS_IsException(str))
return JS_EXCEPTION;
p = JS_VALUE_GET_STRING(str);
- /* avoid reallocating the string if it is well-formed */
- i = js_string_find_invalid_codepoint(p);
- if (i < 0)
- return str;
+ if (!p->is_wide_char || p->len == 0)
+ return str; // by definition well-formed
- ret = js_new_string16(ctx, p->u.str16, p->len);
+ // TODO(bnoordhuis) don't clone when input is well-formed
+ ret = js_new_string16_len(ctx, p->u.str16, p->len);
JS_FreeValue(ctx, str);
if (JS_IsException(ret))
return JS_EXCEPTION;
p = JS_VALUE_GET_STRING(ret);
- for (; i < p->len; i++) {
- uint32_t c = p->u.str16[i];
- if (is_surrogate(c)) {
- if (is_hi_surrogate(c) && (i + 1) < p->len
- && is_lo_surrogate(p->u.str16[i + 1])) {
- i++;
- } else {
- p->u.str16[i] = 0xFFFD;
- }
+ for (i = 0, n = p->len; i < n; i++) {
+ c = p->u.str16[i];
+ if (!is_surrogate(c))
+ continue;
+ if (is_lo_surrogate(c) || i + 1 == n) {
+ p->u.str16[i] = 0xFFFD;
+ continue;
}
+ c = p->u.str16[++i];
+ if (!is_lo_surrogate(c))
+ p->u.str16[--i] = 0xFFFD;
}
+
return ret;
}
-static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int lastIndexOf)
+static JSValue js_string_indexOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int lastIndexOf)
{
JSValue str, v;
int i, len, v_len, pos, start, stop, ret, inc;
@@ -41968,7 +41849,7 @@ static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val,
}
JS_FreeValue(ctx, str);
JS_FreeValue(ctx, v);
- return JS_NewInt32(ctx, ret);
+ return js_int32(ret);
fail:
JS_FreeValue(ctx, str);
@@ -41976,11 +41857,11 @@ fail:
return JS_EXCEPTION;
}
-/* return < 0 if exception or TRUE/FALSE */
-static int js_is_regexp(JSContext *ctx, JSValueConst obj);
+/* return < 0 if exception or true/false */
+static int js_is_regexp(JSContext *ctx, JSValue obj);
-static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_string_includes(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSValue str, v = JS_UNDEFINED;
int i, len, v_len, pos, start, stop, ret;
@@ -42035,7 +41916,7 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val,
done:
JS_FreeValue(ctx, str);
JS_FreeValue(ctx, v);
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
fail:
JS_FreeValue(ctx, str);
@@ -42043,7 +41924,7 @@ fail:
return JS_EXCEPTION;
}
-static int check_regexp_g_flag(JSContext *ctx, JSValueConst regexp)
+static int check_regexp_g_flag(JSContext *ctx, JSValue regexp)
{
int ret;
JSValue flags;
@@ -42072,12 +41953,12 @@ static int check_regexp_g_flag(JSContext *ctx, JSValueConst regexp)
return 0;
}
-static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int atom)
+static JSValue js_string_match(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int atom)
{
// match(rx), search(rx), matchAll(rx)
// atom is JS_ATOM_Symbol_match, JS_ATOM_Symbol_search, or JS_ATOM_Symbol_matchAll
- JSValueConst O = this_val, regexp = argv[0], args[2];
+ JSValue O = this_val, regexp = argv[0], args[2];
JSValue matcher, S, rx, result, str;
int args_len;
@@ -42105,7 +41986,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,
args[0] = regexp;
str = JS_UNDEFINED;
if (atom == JS_ATOM_Symbol_matchAll) {
- str = JS_NewString(ctx, "g");
+ str = js_new_string8(ctx, "g");
if (JS_IsException(str))
goto fail;
args[args_len++] = str;
@@ -42117,16 +41998,16 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, S);
return JS_EXCEPTION;
}
- result = JS_InvokeFree(ctx, rx, atom, 1, (JSValueConst *)&S);
+ result = JS_InvokeFree(ctx, rx, atom, 1, &S);
JS_FreeValue(ctx, S);
return result;
}
-static JSValue js_string___GetSubstitution(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string___GetSubstitution(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// GetSubstitution(matched, str, position, captures, namedCaptures, rep)
- JSValueConst matched, str, captures, namedCaptures, rep;
+ JSValue matched, str, captures, namedCaptures, rep;
JSValue capture, name, s;
uint32_t position, len, matched_len, captures_len;
int i, j, j0, k, k1;
@@ -42230,18 +42111,18 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
+static JSValue js_string_replace(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
int is_replaceAll)
{
// replace(rx, rep)
- JSValueConst O = this_val, searchValue = argv[0], replaceValue = argv[1];
- JSValueConst args[6];
+ JSValue O = this_val, searchValue = argv[0], replaceValue = argv[1];
+ JSValue args[6];
JSValue str, search_str, replaceValue_str, repl_str;
JSString *sp, *searchp;
StringBuffer b_s, *b = &b_s;
int pos, functionalReplace, endOfLastMatch;
- BOOL is_first;
+ bool is_first;
if (JS_IsUndefined(O) || JS_IsNull(O))
return JS_ThrowTypeError(ctx, "cannot convert to object");
@@ -42283,7 +42164,7 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val,
sp = JS_VALUE_GET_STRING(str);
searchp = JS_VALUE_GET_STRING(search_str);
endOfLastMatch = 0;
- is_first = TRUE;
+ is_first = true;
for(;;) {
if (unlikely(searchp->len == 0)) {
if (is_first)
@@ -42307,13 +42188,13 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val,
}
if (functionalReplace) {
args[0] = search_str;
- args[1] = JS_NewInt32(ctx, pos);
+ args[1] = js_int32(pos);
args[2] = str;
repl_str = JS_ToStringFree(ctx, JS_Call(ctx, replaceValue, JS_UNDEFINED, 3, args));
} else {
args[0] = search_str;
args[1] = str;
- args[2] = JS_NewInt32(ctx, pos);
+ args[2] = js_int32(pos);
args[3] = JS_UNDEFINED;
args[4] = JS_UNDEFINED;
args[5] = replaceValue_str;
@@ -42325,7 +42206,7 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val,
string_buffer_concat(b, sp, endOfLastMatch, pos);
string_buffer_concat_value_free(b, repl_str);
endOfLastMatch = pos + searchp->len;
- is_first = FALSE;
+ is_first = false;
if (!is_replaceAll)
break;
}
@@ -42343,12 +42224,12 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_string_split(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_split(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// split(sep, limit)
- JSValueConst O = this_val, separator = argv[0], limit = argv[1];
- JSValueConst args[2];
+ JSValue O = this_val, separator = argv[0], limit = argv[1];
+ JSValue args[2];
JSValue S, A, R, T;
uint32_t lim, lengthA;
int64_t p, q, s, r, e;
@@ -42433,8 +42314,8 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_string_substring(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_substring(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue str, ret;
int a, b, start, end;
@@ -42467,8 +42348,8 @@ static JSValue js_string_substring(JSContext *ctx, JSValueConst this_val,
return ret;
}
-static JSValue js_string_substr(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_substr(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue str, ret;
int a, len, n;
@@ -42495,8 +42376,8 @@ static JSValue js_string_substr(JSContext *ctx, JSValueConst this_val,
return ret;
}
-static JSValue js_string_slice(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_slice(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue str, ret;
int len, start, end;
@@ -42523,8 +42404,8 @@ static JSValue js_string_slice(JSContext *ctx, JSValueConst this_val,
return ret;
}
-static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int padEnd)
+static JSValue js_string_pad(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int padEnd)
{
JSValue str, v = JS_UNDEFINED;
StringBuffer b_s, *b = &b_s;
@@ -42594,8 +42475,8 @@ fail1:
return JS_EXCEPTION;
}
-static JSValue js_string_repeat(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_repeat(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue str;
StringBuffer b_s, *b = &b_s;
@@ -42617,7 +42498,6 @@ static JSValue js_string_repeat(JSContext *ctx, JSValueConst this_val,
len = p->len;
if (len == 0 || n == 1)
return str;
- // XXX: potential arithmetic overflow
if (val * len > JS_STRING_LEN_MAX) {
JS_ThrowRangeError(ctx, "invalid string length");
goto fail;
@@ -42639,8 +42519,8 @@ fail:
return JS_EXCEPTION;
}
-static JSValue js_string_trim(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_string_trim(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSValue str, ret;
int a, b, len;
@@ -42665,12 +42545,6 @@ static JSValue js_string_trim(JSContext *ctx, JSValueConst this_val,
return ret;
}
-static JSValue js_string___quote(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_ToQuotedString(ctx, this_val);
-}
-
/* return 0 if before the first char */
static int string_prevc(JSString *p, int *pidx)
{
@@ -42696,7 +42570,7 @@ static int string_prevc(JSString *p, int *pidx)
return c;
}
-static BOOL test_final_sigma(JSString *p, int sigma_pos)
+static bool test_final_sigma(JSString *p, int sigma_pos)
{
int k, c1;
@@ -42709,14 +42583,14 @@ static BOOL test_final_sigma(JSString *p, int sigma_pos)
break;
}
if (!lre_is_cased(c1))
- return FALSE;
+ return false;
/* after C: skip case ignorable chars and check there is
no cased letter */
k = sigma_pos + 1;
for(;;) {
if (k >= p->len)
- return TRUE;
+ return true;
c1 = string_getc(p, &k);
if (!lre_is_case_ignorable(c1))
break;
@@ -42724,8 +42598,84 @@ static BOOL test_final_sigma(JSString *p, int sigma_pos)
return !lre_is_cased(c1);
}
-static JSValue js_string_toLowerCase(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int to_lower)
+static int to_utf32_buf(JSContext *ctx, JSString *p, uint32_t **pbuf)
+{
+ uint32_t *b;
+ int i, j, n;
+
+ j = -1;
+ n = p->len;
+ b = js_malloc(ctx, max_int(1, n) * sizeof(*b));
+ if (b)
+ for (i = j = 0; i < n;)
+ b[j++] = string_getc(p, &i);
+ *pbuf = b;
+ return j;
+}
+
+static JSValue js_string_localeCompare(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ int i, n, an, bn, cmp;
+ uint32_t *as, *bs, *ts;
+ JSValue a, b, ret;
+
+ ret = JS_EXCEPTION;
+ as = NULL;
+ bs = NULL;
+
+ a = JS_ToStringCheckObject(ctx, this_val);
+ if (JS_IsException(a))
+ return JS_EXCEPTION;
+
+ b = JS_ToString(ctx, argv[0]);
+ if (JS_IsException(b))
+ goto exception;
+
+ an = to_utf32_buf(ctx, JS_VALUE_GET_STRING(a), &as);
+ if (an == -1)
+ goto exception;
+
+ bn = to_utf32_buf(ctx, JS_VALUE_GET_STRING(b), &bs);
+ if (bn == -1)
+ goto exception;
+
+ // TODO(bnoordhuis) skip normalization when input is latin1
+ an = unicode_normalize(&ts, as, an, UNICODE_NFC, ctx,
+ (DynBufReallocFunc *)js_realloc);
+ if (an == -1)
+ goto exception;
+ js_free(ctx, as);
+ as = ts;
+
+ // TODO(bnoordhuis) skip normalization when input is latin1
+ bn = unicode_normalize(&ts, bs, bn, UNICODE_NFC, ctx,
+ (DynBufReallocFunc *)js_realloc);
+ if (bn == -1)
+ goto exception;
+ js_free(ctx, bs);
+ bs = ts;
+
+ n = min_int(an, bn);
+ for (i = 0; i < n; i++)
+ if (as[i] != bs[i])
+ break;
+ if (i < n)
+ cmp = compare_u32(as[i], bs[i]);
+ else
+ cmp = compare_u32(an, bn);
+ ret = js_int32(cmp);
+
+exception:
+ JS_FreeValue(ctx, a);
+ JS_FreeValue(ctx, b);
+ js_free(ctx, as);
+ js_free(ctx, bs);
+ return ret;
+}
+
+static JSValue js_string_toLowerCase(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int to_lower)
{
JSValue val;
StringBuffer b_s, *b = &b_s;
@@ -42762,35 +42712,18 @@ static JSValue js_string_toLowerCase(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-#ifdef CONFIG_ALL_UNICODE
-
/* return (-1, NULL) if exception, otherwise (len, buf) */
-static int JS_ToUTF32String(JSContext *ctx, uint32_t **pbuf, JSValueConst val1)
+static int JS_ToUTF32String(JSContext *ctx, uint32_t **pbuf, JSValue val1)
{
JSValue val;
- JSString *p;
- uint32_t *buf;
- int i, j, len;
+ int len;
val = JS_ToString(ctx, val1);
if (JS_IsException(val))
return -1;
- p = JS_VALUE_GET_STRING(val);
- len = p->len;
- /* UTF32 buffer length is len minus the number of correct surrogates pairs */
- buf = js_malloc(ctx, sizeof(buf[0]) * max_int(len, 1));
- if (!buf) {
- JS_FreeValue(ctx, val);
- goto fail;
- }
- for(i = j = 0; i < len;)
- buf[j++] = string_getc(p, &i);
+ len = to_utf32_buf(ctx, JS_VALUE_GET_STRING(val), pbuf);
JS_FreeValue(ctx, val);
- *pbuf = buf;
- return j;
- fail:
- *pbuf = NULL;
- return -1;
+ return len;
}
static JSValue JS_NewUTF32String(JSContext *ctx, const uint32_t *buf, int len)
@@ -42809,38 +42742,23 @@ static JSValue JS_NewUTF32String(JSContext *ctx, const uint32_t *buf, int len)
return JS_EXCEPTION;
}
-static int js_string_normalize1(JSContext *ctx, uint32_t **pout_buf,
- JSValueConst val,
- UnicodeNormalizationEnum n_type)
-{
- int buf_len, out_len;
- uint32_t *buf, *out_buf;
-
- buf_len = JS_ToUTF32String(ctx, &buf, val);
- if (buf_len < 0)
- return -1;
- out_len = unicode_normalize(&out_buf, buf, buf_len, n_type,
- ctx->rt, (DynBufReallocFunc *)js_realloc_rt);
- js_free(ctx, buf);
- if (out_len < 0)
- return -1;
- *pout_buf = out_buf;
- return out_len;
-}
-
-static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_normalize(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
const char *form, *p;
size_t form_len;
- int is_compat, out_len;
+ int is_compat, buf_len, out_len;
UnicodeNormalizationEnum n_type;
JSValue val;
- uint32_t *out_buf;
+ uint32_t *buf, *out_buf;
val = JS_ToStringCheckObject(ctx, this_val);
if (JS_IsException(val))
return val;
+ buf_len = JS_ToUTF32String(ctx, &buf, val);
+ JS_FreeValue(ctx, val);
+ if (buf_len < 0)
+ return JS_EXCEPTION;
if (argc == 0 || JS_IsUndefined(argv[0])) {
n_type = UNICODE_NFC;
@@ -42852,9 +42770,9 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val,
if (p[0] != 'N' || p[1] != 'F')
goto bad_form;
p += 2;
- is_compat = FALSE;
+ is_compat = false;
if (*p == 'K') {
- is_compat = TRUE;
+ is_compat = true;
p++;
}
if (*p == 'C' || *p == 'D') {
@@ -42866,14 +42784,15 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val,
JS_FreeCString(ctx, form);
JS_ThrowRangeError(ctx, "bad normalization form");
fail1:
- JS_FreeValue(ctx, val);
+ js_free(ctx, buf);
return JS_EXCEPTION;
}
JS_FreeCString(ctx, form);
}
- out_len = js_string_normalize1(ctx, &out_buf, val, n_type);
- JS_FreeValue(ctx, val);
+ out_len = unicode_normalize(&out_buf, buf, buf_len, n_type,
+ ctx->rt, (DynBufReallocFunc *)js_realloc_rt);
+ js_free(ctx, buf);
if (out_len < 0)
return JS_EXCEPTION;
val = JS_NewUTF32String(ctx, out_buf, out_len);
@@ -42881,135 +42800,18 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val,
return val;
}
-/* return < 0, 0 or > 0 */
-static int js_UTF32_compare(const uint32_t *buf1, int buf1_len,
- const uint32_t *buf2, int buf2_len)
-{
- int i, len, c, res;
- len = min_int(buf1_len, buf2_len);
- for(i = 0; i < len; i++) {
- /* Note: range is limited so a subtraction is valid */
- c = buf1[i] - buf2[i];
- if (c != 0)
- return c;
- }
- if (buf1_len == buf2_len)
- res = 0;
- else if (buf1_len < buf2_len)
- res = -1;
- else
- res = 1;
- return res;
-}
-
-static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue a, b;
- int cmp, a_len, b_len;
- uint32_t *a_buf, *b_buf;
-
- a = JS_ToStringCheckObject(ctx, this_val);
- if (JS_IsException(a))
- return JS_EXCEPTION;
- b = JS_ToString(ctx, argv[0]);
- if (JS_IsException(b)) {
- JS_FreeValue(ctx, a);
- return JS_EXCEPTION;
- }
- a_len = js_string_normalize1(ctx, &a_buf, a, UNICODE_NFC);
- JS_FreeValue(ctx, a);
- if (a_len < 0) {
- JS_FreeValue(ctx, b);
- return JS_EXCEPTION;
- }
-
- b_len = js_string_normalize1(ctx, &b_buf, b, UNICODE_NFC);
- JS_FreeValue(ctx, b);
- if (b_len < 0) {
- js_free(ctx, a_buf);
- return JS_EXCEPTION;
- }
- cmp = js_UTF32_compare(a_buf, a_len, b_buf, b_len);
- js_free(ctx, a_buf);
- js_free(ctx, b_buf);
- return JS_NewInt32(ctx, cmp);
-}
-#else /* CONFIG_ALL_UNICODE */
-static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue a, b;
- int cmp;
-
- a = JS_ToStringCheckObject(ctx, this_val);
- if (JS_IsException(a))
- return JS_EXCEPTION;
- b = JS_ToString(ctx, argv[0]);
- if (JS_IsException(b)) {
- JS_FreeValue(ctx, a);
- return JS_EXCEPTION;
- }
- cmp = js_string_compare(ctx, JS_VALUE_GET_STRING(a), JS_VALUE_GET_STRING(b));
- JS_FreeValue(ctx, a);
- JS_FreeValue(ctx, b);
- return JS_NewInt32(ctx, cmp);
-}
-#endif /* !CONFIG_ALL_UNICODE */
-
/* also used for String.prototype.valueOf */
-static JSValue js_string_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_string_toString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return js_thisStringValue(ctx, this_val);
}
-#if 0
-static JSValue js_string___toStringCheckObject(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_ToStringCheckObject(ctx, argv[0]);
-}
-
-static JSValue js_string___toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_ToString(ctx, argv[0]);
-}
-
-static JSValue js_string___advanceStringIndex(JSContext *ctx, JSValueConst
- this_val,
- int argc, JSValueConst *argv)
-{
- JSValue str;
- int idx;
- BOOL is_unicode;
- JSString *p;
-
- str = JS_ToString(ctx, argv[0]);
- if (JS_IsException(str))
- return str;
- if (JS_ToInt32Sat(ctx, &idx, argv[1])) {
- JS_FreeValue(ctx, str);
- return JS_EXCEPTION;
- }
- is_unicode = JS_ToBool(ctx, argv[2]);
- p = JS_VALUE_GET_STRING(str);
- if (!is_unicode || (unsigned)idx >= p->len || !p->is_wide_char) {
- idx++;
- } else {
- string_getc(p, &idx);
- }
- JS_FreeValue(ctx, str);
- return JS_NewInt32(ctx, idx);
-}
-#endif
-
/* String Iterator */
-static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
- BOOL *pdone, int magic)
+static JSValue js_string_iterator_next(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
+ int *pdone, int magic)
{
JSArrayIteratorData *it;
uint32_t idx, c, start;
@@ -43017,7 +42819,7 @@ static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val,
it = JS_GetOpaque2(ctx, this_val, JS_CLASS_STRING_ITERATOR);
if (!it) {
- *pdone = FALSE;
+ *pdone = false;
return JS_EXCEPTION;
}
if (JS_IsUndefined(it->obj))
@@ -43028,18 +42830,18 @@ static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, it->obj);
it->obj = JS_UNDEFINED;
done:
- *pdone = TRUE;
+ *pdone = true;
return JS_UNDEFINED;
}
start = idx;
c = string_getc(p, (int *)&idx);
it->idx = idx;
- *pdone = FALSE;
+ *pdone = false;
if (c <= 0xffff) {
return js_new_string_char(ctx, c);
} else {
- return js_new_string16(ctx, p->u.str16 + start, 2);
+ return js_new_string16_len(ctx, p->u.str16 + start, 2);
}
}
@@ -43060,8 +42862,8 @@ enum {
magic_string_sup,
};
-static JSValue js_string_CreateHTML(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_string_CreateHTML(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSValue str;
const JSString *p;
@@ -43118,18 +42920,13 @@ static const JSCFunctionListEntry js_string_funcs[] = {
JS_CFUNC_DEF("fromCharCode", 1, js_string_fromCharCode ),
JS_CFUNC_DEF("fromCodePoint", 1, js_string_fromCodePoint ),
JS_CFUNC_DEF("raw", 1, js_string_raw ),
- //JS_CFUNC_DEF("__toString", 1, js_string___toString ),
- //JS_CFUNC_DEF("__isSpace", 1, js_string___isSpace ),
- //JS_CFUNC_DEF("__toStringCheckObject", 1, js_string___toStringCheckObject ),
- //JS_CFUNC_DEF("__advanceStringIndex", 3, js_string___advanceStringIndex ),
- //JS_CFUNC_DEF("__GetSubstitution", 6, js_string___GetSubstitution ),
};
static const JSCFunctionListEntry js_string_proto_funcs[] = {
JS_PROP_INT32_DEF("length", 0, JS_PROP_CONFIGURABLE ),
- JS_CFUNC_MAGIC_DEF("at", 1, js_string_charAt, 1 ),
+ JS_CFUNC_DEF("at", 1, js_string_at ),
JS_CFUNC_DEF("charCodeAt", 1, js_string_charCodeAt ),
- JS_CFUNC_MAGIC_DEF("charAt", 1, js_string_charAt, 0 ),
+ JS_CFUNC_DEF("charAt", 1, js_string_charAt ),
JS_CFUNC_DEF("concat", 1, js_string_concat ),
JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ),
JS_CFUNC_DEF("isWellFormed", 0, js_string_isWellFormed ),
@@ -43158,8 +42955,8 @@ static const JSCFunctionListEntry js_string_proto_funcs[] = {
JS_ALIAS_DEF("trimLeft", "trimStart" ),
JS_CFUNC_DEF("toString", 0, js_string_toString ),
JS_CFUNC_DEF("valueOf", 0, js_string_toString ),
- JS_CFUNC_DEF("__quote", 1, js_string___quote ),
JS_CFUNC_DEF("localeCompare", 1, js_string_localeCompare ),
+ JS_CFUNC_DEF("normalize", 0, js_string_normalize ),
JS_CFUNC_MAGIC_DEF("toLowerCase", 0, js_string_toLowerCase, 1 ),
JS_CFUNC_MAGIC_DEF("toUpperCase", 0, js_string_toLowerCase, 0 ),
JS_CFUNC_MAGIC_DEF("toLocaleLowerCase", 0, js_string_toLowerCase, 1 ),
@@ -43186,19 +42983,6 @@ static const JSCFunctionListEntry js_string_iterator_proto_funcs[] = {
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "String Iterator", JS_PROP_CONFIGURABLE ),
};
-#ifdef CONFIG_ALL_UNICODE
-static const JSCFunctionListEntry js_string_proto_normalize[] = {
- JS_CFUNC_DEF("normalize", 0, js_string_normalize ),
-};
-#endif
-
-void JS_AddIntrinsicStringNormalize(JSContext *ctx)
-{
-#ifdef CONFIG_ALL_UNICODE
- JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_normalize,
- countof(js_string_proto_normalize));
-#endif
-}
/* Math */
@@ -43230,16 +43014,16 @@ static double js_fmax(double a, double b)
}
}
-static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_math_min_max(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
- BOOL is_max = magic;
+ bool is_max = magic;
double r, a;
int i;
uint32_t tag;
if (unlikely(argc == 0)) {
- return __JS_NewFloat64(ctx, is_max ? INFINITY : -INFINITY);
+ return js_float64(is_max ? NEG_INF : INF);
}
tag = JS_VALUE_GET_TAG(argv[0]);
@@ -43258,7 +43042,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val,
r1 = min_int(r1, a1);
}
- return JS_NewInt32(ctx, r1);
+ return js_int32(r1);
} else {
if (JS_ToFloat64(ctx, &r, argv[0]))
return JS_EXCEPTION;
@@ -43279,7 +43063,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val,
}
i++;
}
- return JS_NewFloat64(ctx, r);
+ return js_number(r);
}
}
@@ -43321,8 +43105,8 @@ static double js_math_round(double a)
return u.d;
}
-static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_math_hypot(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
double r, a;
int i;
@@ -43342,7 +43126,12 @@ static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val,
}
}
}
- return JS_NewFloat64(ctx, r);
+ return js_float64(r);
+}
+
+static double js_math_f16round(double a)
+{
+ return fromfp16(tofp16(a));
}
static double js_math_fround(double a)
@@ -43350,8 +43139,8 @@ static double js_math_fround(double a)
return (float)a;
}
-static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_math_imul(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
uint32_t a, b, c;
int32_t d;
@@ -43362,11 +43151,11 @@ static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
c = a * b;
memcpy(&d, &c, sizeof(d));
- return JS_NewInt32(ctx, d);
+ return js_int32(d);
}
-static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_math_clz32(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
uint32_t a, r;
@@ -43376,7 +43165,65 @@ static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val,
r = 32;
else
r = clz32(a);
- return JS_NewInt32(ctx, r);
+ return js_int32(r);
+}
+
+static JSValue js_math_sumPrecise(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue iter, next, item, ret;
+ bf_t a, b;
+ int done;
+ double d;
+ int r;
+
+ iter = JS_GetIterator(ctx, argv[0], /*async*/false);
+ if (JS_IsException(iter))
+ return JS_EXCEPTION;
+ bf_init(ctx->bf_ctx, &a);
+ bf_init(ctx->bf_ctx, &b);
+ ret = JS_EXCEPTION;
+ next = JS_GetProperty(ctx, iter, JS_ATOM_next);
+ if (JS_IsException(next))
+ goto fail;
+ bf_set_zero(&a, /*is_neg*/true);
+ for (;;) {
+ item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto fail;
+ if (done)
+ break; // item == JS_UNDEFINED
+ switch (JS_VALUE_GET_TAG(item)) {
+ default:
+ JS_FreeValue(ctx, item);
+ JS_ThrowTypeError(ctx, "not a number");
+ goto fail;
+ case JS_TAG_INT:
+ d = JS_VALUE_GET_INT(item);
+ break;
+ case JS_TAG_FLOAT64:
+ d = JS_VALUE_GET_FLOAT64(item);
+ break;
+ }
+ if (bf_set_float64(&b, d))
+ goto oom;
+ // Infinity + -Infinity results in BF_ST_INVALID_OP, sets |a| to nan
+ if ((r = bf_add(&a, &a, &b, BF_PREC_INF, BF_RNDN)))
+ if (r != BF_ST_INVALID_OP)
+ goto oom;
+ }
+ bf_get_float64(&a, &d, BF_RNDN); // return value deliberately ignored
+ ret = js_float64(d);
+fail:
+ JS_IteratorClose(ctx, iter, JS_IsException(ret));
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ bf_delete(&a);
+ bf_delete(&b);
+ return ret;
+oom:
+ JS_ThrowOutOfMemory(ctx);
+ goto fail;
}
/* xorshift* random number generator by Marsaglia */
@@ -43393,20 +43240,14 @@ static uint64_t xorshift64star(uint64_t *pstate)
static void js_random_init(JSContext *ctx)
{
-#ifdef _MSC_VER
- ctx->random_state = time(NULL);
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- ctx->random_state = ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
-#endif
+ ctx->random_state = js__gettimeofday_us();
/* the state must be non zero */
if (ctx->random_state == 0)
ctx->random_state = 1;
}
-static JSValue js_math_random(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_math_random(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSFloat64Union u;
uint64_t v;
@@ -43414,53 +43255,79 @@ static JSValue js_math_random(JSContext *ctx, JSValueConst this_val,
v = xorshift64star(&ctx->random_state);
/* 1.0 <= u.d < 2 */
u.u64 = ((uint64_t)0x3ff << 52) | (v >> 12);
- return __JS_NewFloat64(ctx, u.d - 1.0);
+ return js_float64(u.d - 1.0);
}
-// MSVC inexplicably refuses to initialize the array below with
-// these functions, so use wrappers.
-static double floorWrapper(double x) { return floor(x); }
-static double ceilWrapper(double x) { return ceil(x); }
-static double log2Wrapper(double x) { return log2(x); }
+/* use local wrappers for math functions to
+ - avoid initializing data with dynamic library entry points.
+ - avoid some overhead if the call can be inlined at compile or link time.
+ */
+static double js_math_fabs(double d) { return fabs(d); }
+static double js_math_floor(double d) { return floor(d); }
+static double js_math_ceil(double d) { return ceil(d); }
+static double js_math_sqrt(double d) { return sqrt(d); }
+static double js_math_acos(double d) { return acos(d); }
+static double js_math_asin(double d) { return asin(d); }
+static double js_math_atan(double d) { return atan(d); }
+static double js_math_atan2(double a, double b) { return atan2(a, b); }
+static double js_math_cos(double d) { return cos(d); }
+static double js_math_exp(double d) { return exp(d); }
+static double js_math_log(double d) { return log(d); }
+static double js_math_sin(double d) { return sin(d); }
+static double js_math_tan(double d) { return tan(d); }
+static double js_math_trunc(double d) { return trunc(d); }
+static double js_math_cosh(double d) { return cosh(d); }
+static double js_math_sinh(double d) { return sinh(d); }
+static double js_math_tanh(double d) { return tanh(d); }
+static double js_math_acosh(double d) { return acosh(d); }
+static double js_math_asinh(double d) { return asinh(d); }
+static double js_math_atanh(double d) { return atanh(d); }
+static double js_math_expm1(double d) { return expm1(d); }
+static double js_math_log1p(double d) { return log1p(d); }
+static double js_math_log2(double d) { return log2(d); }
+static double js_math_log10(double d) { return log10(d); }
+static double js_math_cbrt(double d) { return cbrt(d); }
static const JSCFunctionListEntry js_math_funcs[] = {
JS_CFUNC_MAGIC_DEF("min", 2, js_math_min_max, 0 ),
JS_CFUNC_MAGIC_DEF("max", 2, js_math_min_max, 1 ),
- JS_CFUNC_SPECIAL_DEF("abs", 1, f_f, fabs ),
- JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, floorWrapper ),
- JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, ceilWrapper ),
+ JS_CFUNC_SPECIAL_DEF("abs", 1, f_f, js_math_fabs ),
+ JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, js_math_floor ),
+ JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, js_math_ceil ),
JS_CFUNC_SPECIAL_DEF("round", 1, f_f, js_math_round ),
- JS_CFUNC_SPECIAL_DEF("sqrt", 1, f_f, sqrt ),
-
- JS_CFUNC_SPECIAL_DEF("acos", 1, f_f, acos ),
- JS_CFUNC_SPECIAL_DEF("asin", 1, f_f, asin ),
- JS_CFUNC_SPECIAL_DEF("atan", 1, f_f, atan ),
- JS_CFUNC_SPECIAL_DEF("atan2", 2, f_f_f, atan2 ),
- JS_CFUNC_SPECIAL_DEF("cos", 1, f_f, cos ),
- JS_CFUNC_SPECIAL_DEF("exp", 1, f_f, exp ),
- JS_CFUNC_SPECIAL_DEF("log", 1, f_f, log ),
- JS_CFUNC_SPECIAL_DEF("pow", 2, f_f_f, js_pow ),
- JS_CFUNC_SPECIAL_DEF("sin", 1, f_f, sin ),
- JS_CFUNC_SPECIAL_DEF("tan", 1, f_f, tan ),
+ JS_CFUNC_SPECIAL_DEF("sqrt", 1, f_f, js_math_sqrt ),
+
+ JS_CFUNC_SPECIAL_DEF("acos", 1, f_f, js_math_acos ),
+ JS_CFUNC_SPECIAL_DEF("asin", 1, f_f, js_math_asin ),
+ JS_CFUNC_SPECIAL_DEF("atan", 1, f_f, js_math_atan ),
+ JS_CFUNC_SPECIAL_DEF("atan2", 2, f_f_f, js_math_atan2 ),
+ JS_CFUNC_SPECIAL_DEF("cos", 1, f_f, js_math_cos ),
+ JS_CFUNC_SPECIAL_DEF("exp", 1, f_f, js_math_exp ),
+ JS_CFUNC_SPECIAL_DEF("log", 1, f_f, js_math_log ),
+ JS_CFUNC_SPECIAL_DEF("pow", 2, f_f_f, js_math_pow ),
+ JS_CFUNC_SPECIAL_DEF("sin", 1, f_f, js_math_sin ),
+ JS_CFUNC_SPECIAL_DEF("tan", 1, f_f, js_math_tan ),
/* ES6 */
- JS_CFUNC_SPECIAL_DEF("trunc", 1, f_f, trunc ),
+ JS_CFUNC_SPECIAL_DEF("trunc", 1, f_f, js_math_trunc ),
JS_CFUNC_SPECIAL_DEF("sign", 1, f_f, js_math_sign ),
- JS_CFUNC_SPECIAL_DEF("cosh", 1, f_f, cosh ),
- JS_CFUNC_SPECIAL_DEF("sinh", 1, f_f, sinh ),
- JS_CFUNC_SPECIAL_DEF("tanh", 1, f_f, tanh ),
- JS_CFUNC_SPECIAL_DEF("acosh", 1, f_f, acosh ),
- JS_CFUNC_SPECIAL_DEF("asinh", 1, f_f, asinh ),
- JS_CFUNC_SPECIAL_DEF("atanh", 1, f_f, atanh ),
- JS_CFUNC_SPECIAL_DEF("expm1", 1, f_f, expm1 ),
- JS_CFUNC_SPECIAL_DEF("log1p", 1, f_f, log1p ),
- JS_CFUNC_SPECIAL_DEF("log2", 1, f_f, log2Wrapper ),
- JS_CFUNC_SPECIAL_DEF("log10", 1, f_f, log10 ),
- JS_CFUNC_SPECIAL_DEF("cbrt", 1, f_f, cbrt ),
+ JS_CFUNC_SPECIAL_DEF("cosh", 1, f_f, js_math_cosh ),
+ JS_CFUNC_SPECIAL_DEF("sinh", 1, f_f, js_math_sinh ),
+ JS_CFUNC_SPECIAL_DEF("tanh", 1, f_f, js_math_tanh ),
+ JS_CFUNC_SPECIAL_DEF("acosh", 1, f_f, js_math_acosh ),
+ JS_CFUNC_SPECIAL_DEF("asinh", 1, f_f, js_math_asinh ),
+ JS_CFUNC_SPECIAL_DEF("atanh", 1, f_f, js_math_atanh ),
+ JS_CFUNC_SPECIAL_DEF("expm1", 1, f_f, js_math_expm1 ),
+ JS_CFUNC_SPECIAL_DEF("log1p", 1, f_f, js_math_log1p ),
+ JS_CFUNC_SPECIAL_DEF("log2", 1, f_f, js_math_log2 ),
+ JS_CFUNC_SPECIAL_DEF("log10", 1, f_f, js_math_log10 ),
+ JS_CFUNC_SPECIAL_DEF("cbrt", 1, f_f, js_math_cbrt ),
JS_CFUNC_DEF("hypot", 2, js_math_hypot ),
JS_CFUNC_DEF("random", 0, js_math_random ),
+ JS_CFUNC_SPECIAL_DEF("f16round", 1, f_f, js_math_f16round ),
JS_CFUNC_SPECIAL_DEF("fround", 1, f_f, js_math_fround ),
JS_CFUNC_DEF("imul", 2, js_math_imul ),
JS_CFUNC_DEF("clz32", 1, js_math_clz32 ),
+ JS_CFUNC_DEF("sumPrecise", 1, js_math_sumPrecise ),
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Math", JS_PROP_CONFIGURABLE ),
JS_PROP_DOUBLE_DEF("E", 2.718281828459045, 0 ),
JS_PROP_DOUBLE_DEF("LN10", 2.302585092994046, 0 ),
@@ -43480,10 +43347,19 @@ static const JSCFunctionListEntry js_math_obj[] = {
/* OS dependent. d = argv[0] is in ms from 1970. Return the difference
between UTC time and local time 'd' in minutes */
-static int getTimezoneOffset(int64_t time)
-{
+static int getTimezoneOffset(int64_t time) {
+#if defined(_WIN32)
+ DWORD r;
+ TIME_ZONE_INFORMATION t;
+ r = GetTimeZoneInformation(&t);
+ if (r == TIME_ZONE_ID_INVALID)
+ return 0;
+ if (r == TIME_ZONE_ID_DAYLIGHT)
+ return (int)(t.Bias + t.DaylightBias);
+ return (int)t.Bias;
+#else
time_t ti;
- int res;
+ struct tm tm;
time /= 1000; /* convert to seconds */
if (sizeof(time_t) == 4) {
@@ -43507,73 +43383,21 @@ static int getTimezoneOffset(int64_t time)
}
}
ti = time;
-#if defined(_WIN32)
- {
- struct tm *tm;
- time_t gm_ti, loc_ti;
-
- tm = gmtime(&ti);
- gm_ti = mktime(tm);
+ localtime_r(&ti, &tm);
+#ifdef NO_TM_GMTOFF
+ struct tm gmt;
+ gmtime_r(&ti, &gmt);
- tm = localtime(&ti);
- loc_ti = mktime(tm);
+ /* disable DST adjustment on the local tm struct */
+ tm.tm_isdst = 0;
- res = (gm_ti - loc_ti) / 60;
- }
+ return (int)difftime(mktime(&gmt), mktime(&tm)) / 60;
#else
- {
- struct tm tm;
- localtime_r(&ti, &tm);
- res = -tm.tm_gmtoff / 60;
- }
+ return -tm.tm_gmtoff / 60;
+#endif /* NO_TM_GMTOFF */
#endif
- return res;
-}
-
-#if 0
-static JSValue js___date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- double dd;
-
- if (JS_ToFloat64(ctx, &dd, argv[0]))
- return JS_EXCEPTION;
- if (isnan(dd))
- return JS_NewFloat64(ctx, dd);
- else
- return JS_NewInt32(ctx, getTimezoneOffset((int64_t)dd));
-}
-
-static JSValue js_get_prototype_from_ctor(JSContext *ctx, JSValueConst ctor,
- JSValueConst def_proto)
-{
- JSValue proto;
- proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype);
- if (JS_IsException(proto))
- return proto;
- if (!JS_IsObject(proto)) {
- JS_FreeValue(ctx, proto);
- proto = JS_DupValue(ctx, def_proto);
- }
- return proto;
}
-/* create a new date object */
-static JSValue js___date_create(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue obj, proto;
- proto = js_get_prototype_from_ctor(ctx, argv[0], argv[1]);
- if (JS_IsException(proto))
- return proto;
- obj = JS_NewObjectProtoClass(ctx, proto, JS_CLASS_DATE);
- JS_FreeValue(ctx, proto);
- if (!JS_IsException(obj))
- JS_SetObjectData(ctx, obj, JS_DupValue(ctx, argv[2]));
- return obj;
-}
-#endif
-
/* RegExp */
static void js_regexp_finalizer(JSRuntime *rt, JSValue val)
@@ -43585,8 +43409,8 @@ static void js_regexp_finalizer(JSRuntime *rt, JSValue val)
}
/* create a string containing the RegExp bytecode */
-static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
- JSValueConst flags)
+static JSValue js_compile_regexp(JSContext *ctx, JSValue pattern,
+ JSValue flags)
{
const char *str;
int re_flags, mask;
@@ -43622,6 +43446,9 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
case 'u':
mask = LRE_FLAG_UNICODE;
break;
+ case 'v':
+ mask = LRE_FLAG_UNICODE_SETS;
+ break;
case 'y':
mask = LRE_FLAG_STICKY;
break;
@@ -43638,6 +43465,10 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
JS_FreeCString(ctx, str);
}
+ if (re_flags & LRE_FLAG_UNICODE)
+ if (re_flags & LRE_FLAG_UNICODE_SETS)
+ return JS_ThrowSyntaxError(ctx, "invalid regular expression flags");
+
str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UNICODE));
if (!str)
return JS_EXCEPTION;
@@ -43649,14 +43480,14 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
return JS_EXCEPTION;
}
- ret = js_new_string8(ctx, re_bytecode_buf, re_bytecode_len);
+ ret = js_new_string8_len(ctx, (char *)re_bytecode_buf, re_bytecode_len);
js_free(ctx, re_bytecode_buf);
return ret;
}
/* create a RegExp object from a string containing the RegExp bytecode
and the source pattern */
-static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor,
+static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValue ctor,
JSValue pattern, JSValue bc)
{
JSValue obj;
@@ -43680,12 +43511,12 @@ static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor,
re = &p->u.regexp;
re->pattern = JS_VALUE_GET_STRING(pattern);
re->bytecode = JS_VALUE_GET_STRING(bc);
- JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0),
+ JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, js_int32(0),
JS_PROP_WRITABLE);
return obj;
}
-static JSRegExp *js_get_regexp(JSContext *ctx, JSValueConst obj, BOOL throw_error)
+static JSRegExp *js_get_regexp(JSContext *ctx, JSValue obj, bool throw_error)
{
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(obj);
@@ -43698,26 +43529,26 @@ static JSRegExp *js_get_regexp(JSContext *ctx, JSValueConst obj, BOOL throw_erro
return NULL;
}
-/* return < 0 if exception or TRUE/FALSE */
-static int js_is_regexp(JSContext *ctx, JSValueConst obj)
+/* return < 0 if exception or true/false */
+static int js_is_regexp(JSContext *ctx, JSValue obj)
{
JSValue m;
if (!JS_IsObject(obj))
- return FALSE;
+ return false;
m = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_match);
if (JS_IsException(m))
return -1;
if (!JS_IsUndefined(m))
return JS_ToBoolFree(ctx, m);
- return js_get_regexp(ctx, obj, FALSE) != NULL;
+ return js_get_regexp(ctx, obj, false) != NULL;
}
-static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_regexp_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
{
JSValue pattern, flags, bc, val;
- JSValueConst pat, flags1;
+ JSValue pat, flags1;
JSRegExp *re;
int pat_is_regexp;
@@ -43731,21 +43562,21 @@ static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target,
new_target = JS_GetActiveFunction(ctx);
if (pat_is_regexp && JS_IsUndefined(flags1)) {
JSValue ctor;
- BOOL res;
+ bool res;
ctor = JS_GetProperty(ctx, pat, JS_ATOM_constructor);
if (JS_IsException(ctor))
return ctor;
res = js_same_value(ctx, ctor, new_target);
JS_FreeValue(ctx, ctor);
if (res)
- return JS_DupValue(ctx, pat);
+ return js_dup(pat);
}
}
- re = js_get_regexp(ctx, pat, FALSE);
+ re = js_get_regexp(ctx, pat, false);
if (re) {
- pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern));
+ pattern = js_dup(JS_MKPTR(JS_TAG_STRING, re->pattern));
if (JS_IsUndefined(flags1)) {
- bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->bytecode));
+ bc = js_dup(JS_MKPTR(JS_TAG_STRING, re->bytecode));
goto no_compilation;
} else {
flags = JS_ToString(ctx, flags1);
@@ -43763,11 +43594,11 @@ static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target,
if (JS_IsException(flags))
goto fail;
} else {
- flags = JS_DupValue(ctx, flags1);
+ flags = js_dup(flags1);
}
} else {
- pattern = JS_DupValue(ctx, pat);
- flags = JS_DupValue(ctx, flags1);
+ pattern = js_dup(pat);
+ flags = js_dup(flags1);
}
if (JS_IsUndefined(pattern)) {
pattern = JS_AtomToString(ctx, JS_ATOM_empty_string);
@@ -43791,24 +43622,24 @@ static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target,
return JS_EXCEPTION;
}
-static JSValue js_regexp_compile(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_regexp_compile(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSRegExp *re1, *re;
- JSValueConst pattern1, flags1;
+ JSValue pattern1, flags1;
JSValue bc, pattern;
- re = js_get_regexp(ctx, this_val, TRUE);
+ re = js_get_regexp(ctx, this_val, true);
if (!re)
return JS_EXCEPTION;
pattern1 = argv[0];
flags1 = argv[1];
- re1 = js_get_regexp(ctx, pattern1, FALSE);
+ re1 = js_get_regexp(ctx, pattern1, false);
if (re1) {
if (!JS_IsUndefined(flags1))
return JS_ThrowTypeError(ctx, "flags must be undefined");
- pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re1->pattern));
- bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re1->bytecode));
+ pattern = js_dup(JS_MKPTR(JS_TAG_STRING, re1->pattern));
+ bc = js_dup(JS_MKPTR(JS_TAG_STRING, re1->bytecode));
} else {
bc = JS_UNDEFINED;
if (JS_IsUndefined(pattern1))
@@ -43826,37 +43657,16 @@ static JSValue js_regexp_compile(JSContext *ctx, JSValueConst this_val,
re->pattern = JS_VALUE_GET_STRING(pattern);
re->bytecode = JS_VALUE_GET_STRING(bc);
if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,
- JS_NewInt32(ctx, 0)) < 0)
+ js_int32(0)) < 0)
return JS_EXCEPTION;
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
fail:
JS_FreeValue(ctx, pattern);
JS_FreeValue(ctx, bc);
return JS_EXCEPTION;
}
-#if 0
-static JSValue js_regexp_get___source(JSContext *ctx, JSValueConst this_val)
-{
- JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);
- if (!re)
- return JS_EXCEPTION;
- return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern));
-}
-
-static JSValue js_regexp_get___flags(JSContext *ctx, JSValueConst this_val)
-{
- JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);
- int flags;
-
- if (!re)
- return JS_EXCEPTION;
- flags = lre_get_flags(re->bytecode->u.str8);
- return JS_NewInt32(ctx, flags);
-}
-#endif
-
-static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val)
+static JSValue js_regexp_get_source(JSContext *ctx, JSValue this_val)
{
JSRegExp *re;
JSString *p;
@@ -43869,7 +43679,7 @@ static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val)
if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_REGEXP]))
goto empty_regex;
- re = js_get_regexp(ctx, this_val, TRUE);
+ re = js_get_regexp(ctx, this_val, true);
if (!re)
return JS_EXCEPTION;
@@ -43877,7 +43687,7 @@ static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val)
if (p->len == 0) {
empty_regex:
- return JS_NewString(ctx, "(?:)");
+ return js_new_string8(ctx, "(?:)");
}
string_buffer_init2(ctx, b, p->len, p->is_wide_char);
@@ -43922,7 +43732,7 @@ static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val)
return string_buffer_end(b);
}
-static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mask)
+static JSValue js_regexp_get_flag(JSContext *ctx, JSValue this_val, int mask)
{
JSRegExp *re;
int flags;
@@ -43930,7 +43740,7 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas
if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
return JS_ThrowTypeErrorNotAnObject(ctx);
- re = js_get_regexp(ctx, this_val, FALSE);
+ re = js_get_regexp(ctx, this_val, false);
if (!re) {
if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_REGEXP]))
return JS_UNDEFINED;
@@ -43939,10 +43749,10 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas
}
flags = lre_get_flags(re->bytecode->u.str8);
- return JS_NewBool(ctx, flags & mask);
+ return js_bool(flags & mask);
}
-static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val)
+static JSValue js_regexp_get_flags(JSContext *ctx, JSValue this_val)
{
char str[8], *p = str;
int res;
@@ -43980,19 +43790,26 @@ static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val)
goto exception;
if (res)
*p++ = 'u';
+ res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "unicodeSets"));
+ if (res < 0)
+ goto exception;
+ if (res)
+ *p++ = 'v';
res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "sticky"));
if (res < 0)
goto exception;
if (res)
*p++ = 'y';
- return JS_NewStringLen(ctx, str, p - str);
+ if (p == str)
+ return JS_AtomToString(ctx, JS_ATOM_empty_string);
+ return js_new_string8_len(ctx, str, p - str);
exception:
return JS_EXCEPTION;
}
-static JSValue js_regexp_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_regexp_toString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue pattern, flags;
StringBuffer b_s, *b = &b_s;
@@ -44016,7 +43833,7 @@ fail:
return JS_EXCEPTION;
}
-BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size)
+bool lre_check_stack_overflow(void *opaque, size_t alloca_size)
{
JSContext *ctx = opaque;
return js_check_stack_overflow(ctx->rt, alloca_size);
@@ -44029,10 +43846,57 @@ void *lre_realloc(void *opaque, void *ptr, size_t size)
return js_realloc_rt(ctx->rt, ptr, size);
}
-static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_regexp_escape(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);
+ StringBuffer b_s, *b = &b_s;
+ JSString *p;
+ uint32_t c, i;
+ char s[16];
+
+ if (!JS_IsString(argv[0]))
+ return JS_ThrowTypeError(ctx, "not a string");
+ p = JS_VALUE_GET_STRING(argv[0]);
+ string_buffer_init2(ctx, b, 0, p->is_wide_char);
+ for (i = 0; i < p->len; i++) {
+ c = p->is_wide_char ? (uint32_t)p->u.str16[i] : (uint32_t)p->u.str8[i];
+ if (c < 33) {
+ if (c >= 9 && c <= 13) {
+ string_buffer_putc8(b, '\\');
+ string_buffer_putc8(b, "tnvfr"[c - 9]);
+ } else {
+ goto hex2;
+ }
+ } else if (c < 128) {
+ if ((c >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= 'a' && c <= 'z')) {
+ if (i == 0)
+ goto hex2;
+ } else if (strchr(",-=<>#&!%:;@~'`\"", c)) {
+ goto hex2;
+ } else if (c != '_') {
+ string_buffer_putc8(b, '\\');
+ }
+ string_buffer_putc8(b, c);
+ } else if (c < 256) {
+ hex2:
+ snprintf(s, sizeof(s), "\\x%02x", c);
+ string_buffer_puts8(b, s);
+ } else if (is_surrogate(c) || lre_is_white_space(c) || c == 0xFEFF) {
+ snprintf(s, sizeof(s), "\\u%04x", c);
+ string_buffer_puts8(b, s);
+ } else {
+ string_buffer_putc16(b, c);
+ }
+ }
+ return string_buffer_end(b);
+}
+
+static JSValue js_regexp_exec(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSRegExp *re = js_get_regexp(ctx, this_val, true);
JSString *str;
JSValue t, ret, str_val, obj, val, groups;
JSValue indices, indices_groups;
@@ -44085,7 +43949,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
if (rc >= 0) {
if (rc == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {
if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,
- JS_NewInt32(ctx, 0)) < 0)
+ js_int32(0)) < 0)
goto fail;
}
} else {
@@ -44096,7 +43960,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
int prop_flags;
if (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) {
if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,
- JS_NewInt32(ctx, (capture[1] - str_buf) >> shift)) < 0)
+ js_int32((capture[1] - str_buf) >> shift)) < 0)
goto fail;
}
obj = JS_NewArray(ctx);
@@ -44125,7 +43989,6 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
uint8_t **match = &capture[2 * i];
int start = -1;
int end = -1;
- JSValue val;
if (group_name_ptr && i > 0) {
if (*group_name_ptr) name = group_name_ptr;
@@ -44138,26 +44001,26 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
}
if (!JS_IsUndefined(indices)) {
- val = JS_UNDEFINED;
+ JSValue val = JS_UNDEFINED;
if (start != -1) {
val = JS_NewArray(ctx);
if (JS_IsException(val))
goto fail;
if (JS_DefinePropertyValueUint32(ctx, val, 0,
- JS_NewInt32(ctx, start),
+ js_int32(start),
prop_flags) < 0) {
JS_FreeValue(ctx, val);
goto fail;
}
if (JS_DefinePropertyValueUint32(ctx, val, 1,
- JS_NewInt32(ctx, end),
+ js_int32(end),
prop_flags) < 0) {
JS_FreeValue(ctx, val);
goto fail;
}
}
if (name && !JS_IsUndefined(indices_groups)) {
- val = JS_DupValue(ctx, val);
+ val = js_dup(val);
if (JS_DefinePropertyValueStr(ctx, indices_groups,
name, val, prop_flags) < 0) {
JS_FreeValue(ctx, val);
@@ -44170,7 +44033,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
}
}
- val = JS_UNDEFINED;
+ JSValue val = JS_UNDEFINED;
if (start != -1) {
val = js_sub_string(ctx, str, start, end);
if (JS_IsException(val))
@@ -44179,7 +44042,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
if (name) {
if (JS_DefinePropertyValueStr(ctx, groups, name,
- JS_DupValue(ctx, val),
+ js_dup(val),
prop_flags) < 0) {
JS_FreeValue(ctx, val);
goto fail;
@@ -44196,7 +44059,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
goto fail;
}
- t = JS_NewInt32(ctx, (capture[0] - str_buf) >> shift);
+ t = js_int32((capture[0] - str_buf) >> shift);
if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index, t, prop_flags) < 0)
goto fail;
@@ -44230,9 +44093,9 @@ fail:
}
/* delete portions of a string that match a given regex */
-static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueConst arg)
+static JSValue JS_RegExpDelete(JSContext *ctx, JSValue this_val, JSValue arg)
{
- JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);
+ JSRegExp *re = js_get_regexp(ctx, this_val, true);
JSString *str;
JSValue str_val, val;
uint8_t *re_bytecode;
@@ -44281,7 +44144,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueCon
if (ret >= 0) {
if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {
if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,
- JS_NewInt32(ctx, 0)) < 0)
+ js_int32(0)) < 0)
goto fail;
}
} else {
@@ -44300,7 +44163,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueCon
next_src_pos = end;
if (!(re_flags & LRE_FLAG_GLOBAL)) {
if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,
- JS_NewInt32(ctx, end)) < 0)
+ js_int32(end)) < 0)
goto fail;
break;
}
@@ -44325,7 +44188,7 @@ fail:
return JS_EXCEPTION;
}
-static JSValue JS_RegExpExec(JSContext *ctx, JSValueConst r, JSValueConst s)
+static JSValue JS_RegExpExec(JSContext *ctx, JSValue r, JSValue s)
{
JSValue method, ret;
@@ -44346,38 +44209,25 @@ static JSValue JS_RegExpExec(JSContext *ctx, JSValueConst r, JSValueConst s)
return js_regexp_exec(ctx, r, 1, &s);
}
-#if 0
-static JSValue js_regexp___RegExpExec(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_RegExpExec(ctx, argv[0], argv[1]);
-}
-static JSValue js_regexp___RegExpDelete(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return JS_RegExpDelete(ctx, argv[0], argv[1]);
-}
-#endif
-
-static JSValue js_regexp_test(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_regexp_test(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue val;
- BOOL ret;
+ bool ret;
val = JS_RegExpExec(ctx, this_val, argv[0]);
if (JS_IsException(val))
return JS_EXCEPTION;
ret = !JS_IsNull(val);
JS_FreeValue(ctx, val);
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
-static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// [Symbol.match](str)
- JSValueConst rx = this_val;
+ JSValue rx = this_val;
JSValue A, S, flags, result, matchStr;
int global, n, fullUnicode, isEmpty;
JSString *p;
@@ -44410,7 +44260,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
if (fullUnicode < 0)
goto exception;
- if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0)
+ if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0)
goto exception;
A = JS_NewArray(ctx);
if (JS_IsException(A))
@@ -44436,7 +44286,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
goto exception;
p = JS_VALUE_GET_STRING(S);
nextIndex = string_advance_index(p, thisIndex, fullUnicode);
- if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt64(ctx, nextIndex)) < 0)
+ if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int64(nextIndex)) < 0)
goto exception;
}
}
@@ -44461,9 +44311,9 @@ exception:
typedef struct JSRegExpStringIteratorData {
JSValue iterating_regexp;
JSValue iterated_string;
- BOOL global;
- BOOL unicode;
- BOOL done;
+ bool global;
+ bool unicode;
+ int done;
} JSRegExpStringIteratorData;
static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val)
@@ -44477,7 +44327,7 @@ static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val)
}
}
-static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val,
+static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -44489,12 +44339,12 @@ static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val,
}
static JSValue js_regexp_string_iterator_next(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv,
- BOOL *pdone, int magic)
+ JSValue this_val,
+ int argc, JSValue *argv,
+ int *pdone, int magic)
{
JSRegExpStringIteratorData *it;
- JSValueConst R, S;
+ JSValue R, S;
JSValue matchStr = JS_UNDEFINED, match = JS_UNDEFINED;
JSString *sp;
@@ -44502,7 +44352,7 @@ static JSValue js_regexp_string_iterator_next(JSContext *ctx,
if (!it)
goto exception;
if (it->done) {
- *pdone = TRUE;
+ *pdone = true;
return JS_UNDEFINED;
}
R = it->iterating_regexp;
@@ -44511,8 +44361,8 @@ static JSValue js_regexp_string_iterator_next(JSContext *ctx,
if (JS_IsException(match))
goto exception;
if (JS_IsNull(match)) {
- it->done = TRUE;
- *pdone = TRUE;
+ it->done = true;
+ *pdone = true;
return JS_UNDEFINED;
} else if (it->global) {
matchStr = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, match, 0));
@@ -44525,30 +44375,29 @@ static JSValue js_regexp_string_iterator_next(JSContext *ctx,
goto exception;
sp = JS_VALUE_GET_STRING(S);
nextIndex = string_advance_index(sp, thisIndex, it->unicode);
- if (JS_SetProperty(ctx, R, JS_ATOM_lastIndex,
- JS_NewInt64(ctx, nextIndex)) < 0)
+ if (JS_SetProperty(ctx, R, JS_ATOM_lastIndex, js_int64(nextIndex)) < 0)
goto exception;
}
JS_FreeValue(ctx, matchStr);
} else {
- it->done = TRUE;
+ it->done = true;
}
- *pdone = FALSE;
+ *pdone = false;
return match;
exception:
JS_FreeValue(ctx, match);
JS_FreeValue(ctx, matchStr);
- *pdone = FALSE;
+ *pdone = false;
return JS_EXCEPTION;
}
-static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// [Symbol.matchAll](str)
- JSValueConst R = this_val;
+ JSValue R = this_val;
JSValue S, C, flags, matcher, iter;
- JSValueConst args[2];
+ JSValue args[2];
JSString *strp;
int64_t lastIndex;
JSRegExpStringIteratorData *it;
@@ -44578,8 +44427,7 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val,
if (JS_ToLengthFree(ctx, &lastIndex,
JS_GetProperty(ctx, R, JS_ATOM_lastIndex)))
goto exception;
- if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex,
- JS_NewInt64(ctx, lastIndex)) < 0)
+ if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex, js_int64(lastIndex)) < 0)
goto exception;
iter = JS_NewObjectClass(ctx, JS_CLASS_REGEXP_STRING_ITERATOR);
@@ -44593,8 +44441,8 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val,
strp = JS_VALUE_GET_STRING(flags);
it->global = string_indexof_char(strp, 'g', 0) >= 0;
it->unicode = string_indexof_char(strp, 'u', 0) >= 0;
- it->done = FALSE;
- JS_SetOpaque(iter, it);
+ it->done = false;
+ JS_SetOpaqueInternal(iter, it);
JS_FreeValue(ctx, C);
JS_FreeValue(ctx, flags);
@@ -44668,7 +44516,7 @@ static int value_buffer_append(ValueBuffer *b, JSValue val)
return 0;
}
-static int js_is_standard_regexp(JSContext *ctx, JSValueConst rx)
+static int js_is_standard_regexp(JSContext *ctx, JSValue rx)
{
JSValue val;
int res;
@@ -44690,12 +44538,12 @@ static int js_is_standard_regexp(JSContext *ctx, JSValueConst rx)
return res;
}
-static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// [Symbol.replace](str, rep)
- JSValueConst rx = this_val, rep = argv[1];
- JSValueConst args[6];
+ JSValue rx = this_val, rep = argv[1];
+ JSValue args[6];
JSValue flags, str, rep_val, matched, tab, rep_str, namedCaptures, res;
JSString *p, *sp, *rp;
StringBuffer b_s, *b = &b_s;
@@ -44746,7 +44594,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode));
if (fullUnicode < 0)
goto exception;
- if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0)
+ if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0)
goto exception;
}
@@ -44776,13 +44624,13 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
if (JS_ToLengthFree(ctx, &thisIndex, JS_GetProperty(ctx, rx, JS_ATOM_lastIndex)) < 0)
goto exception;
nextIndex = string_advance_index(sp, thisIndex, fullUnicode);
- if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt64(ctx, nextIndex)) < 0)
+ if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int64(nextIndex)) < 0)
goto exception;
}
}
nextSourcePosition = 0;
for(j = 0; j < results->len; j++) {
- JSValueConst result;
+ JSValue result;
result = results->arr[j];
if (js_get_length32(ctx, &nCaptures, result) < 0)
goto exception;
@@ -44802,7 +44650,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
tab = JS_NewArray(ctx);
if (JS_IsException(tab))
goto exception;
- if (JS_DefinePropertyValueInt64(ctx, tab, 0, JS_DupValue(ctx, matched),
+ if (JS_DefinePropertyValueInt64(ctx, tab, 0, js_dup(matched),
JS_PROP_C_W_E | JS_PROP_THROW) < 0)
goto exception;
for(n = 1; n < nCaptures; n++) {
@@ -44824,12 +44672,12 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(namedCaptures))
goto exception;
if (functionalReplace) {
- if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_NewInt32(ctx, position), JS_PROP_C_W_E | JS_PROP_THROW) < 0)
+ if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_int32(position), JS_PROP_C_W_E | JS_PROP_THROW) < 0)
goto exception;
- if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_DupValue(ctx, str), JS_PROP_C_W_E | JS_PROP_THROW) < 0)
+ if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_dup(str), JS_PROP_C_W_E | JS_PROP_THROW) < 0)
goto exception;
if (!JS_IsUndefined(namedCaptures)) {
- if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_DupValue(ctx, namedCaptures), JS_PROP_C_W_E | JS_PROP_THROW) < 0)
+ if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_dup(namedCaptures), JS_PROP_C_W_E | JS_PROP_THROW) < 0)
goto exception;
}
args[0] = JS_UNDEFINED;
@@ -44847,7 +44695,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
}
args[0] = matched;
args[1] = str;
- args[2] = JS_NewInt32(ctx, position);
+ args[2] = js_int32(position);
args[3] = tab;
args[4] = namedCaptures1;
args[5] = rep_val;
@@ -44883,10 +44731,10 @@ done1:
return res;
}
-static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst rx = this_val;
+ JSValue rx = this_val;
JSValue str, previousLastIndex, currentLastIndex, result, index;
if (!JS_IsObject(rx))
@@ -44903,8 +44751,8 @@ static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(previousLastIndex))
goto exception;
- if (!js_same_value(ctx, previousLastIndex, JS_NewInt32(ctx, 0))) {
- if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0) {
+ if (!js_same_value(ctx, previousLastIndex, js_int32(0))) {
+ if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0) {
goto exception;
}
}
@@ -44926,7 +44774,7 @@ static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, currentLastIndex);
if (JS_IsNull(result)) {
- return JS_NewInt32(ctx, -1);
+ return js_int32(-1);
} else {
index = JS_GetProperty(ctx, result, JS_ATOM_index);
JS_FreeValue(ctx, result);
@@ -44941,12 +44789,12 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// [Symbol.split](str, limit)
- JSValueConst rx = this_val;
- JSValueConst args[2];
+ JSValue rx = this_val;
+ JSValue args[2];
JSValue str, ctor, splitter, A, flags, z, sub;
JSString *strp;
uint32_t lim, size, p, q;
@@ -45006,7 +44854,7 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val,
goto done;
}
while (q < size) {
- if (JS_SetProperty(ctx, splitter, JS_ATOM_lastIndex, JS_NewInt32(ctx, q)) < 0)
+ if (JS_SetProperty(ctx, splitter, JS_ATOM_lastIndex, js_int32(q)) < 0)
goto exception;
JS_FreeValue(ctx, z);
z = JS_RegExpExec(ctx, splitter, str);
@@ -45034,9 +44882,14 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val,
if (js_get_length64(ctx, &numberOfCaptures, z))
goto exception;
for(i = 1; i < numberOfCaptures; i++) {
- sub = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, z, i));
+ sub = JS_GetPropertyInt64(ctx, z, i);
if (JS_IsException(sub))
goto exception;
+ if (!JS_IsUndefined(sub)) {
+ sub = JS_ToStringFree(ctx, sub);
+ if (JS_IsException(sub))
+ goto exception;
+ }
if (JS_DefinePropertyValueInt64(ctx, A, lengthA++, sub, JS_PROP_C_W_E | JS_PROP_THROW) < 0)
goto exception;
if (lengthA == lim)
@@ -45068,9 +44921,8 @@ done:
}
static const JSCFunctionListEntry js_regexp_funcs[] = {
+ JS_CFUNC_DEF("escape", 1, js_regexp_escape ),
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
- //JS_CFUNC_DEF("__RegExpExec", 2, js_regexp___RegExpExec ),
- //JS_CFUNC_DEF("__RegExpDelete", 2, js_regexp___RegExpDelete ),
};
static const JSCFunctionListEntry js_regexp_proto_funcs[] = {
@@ -45081,6 +44933,7 @@ static const JSCFunctionListEntry js_regexp_proto_funcs[] = {
JS_CGETSET_MAGIC_DEF("multiline", js_regexp_get_flag, NULL, LRE_FLAG_MULTILINE ),
JS_CGETSET_MAGIC_DEF("dotAll", js_regexp_get_flag, NULL, LRE_FLAG_DOTALL ),
JS_CGETSET_MAGIC_DEF("unicode", js_regexp_get_flag, NULL, LRE_FLAG_UNICODE ),
+ JS_CGETSET_MAGIC_DEF("unicodeSets", js_regexp_get_flag, NULL, LRE_FLAG_UNICODE_SETS ),
JS_CGETSET_MAGIC_DEF("sticky", js_regexp_get_flag, NULL, LRE_FLAG_STICKY ),
JS_CGETSET_MAGIC_DEF("hasIndices", js_regexp_get_flag, NULL, LRE_FLAG_INDICES ),
JS_CFUNC_DEF("exec", 1, js_regexp_exec ),
@@ -45092,8 +44945,6 @@ static const JSCFunctionListEntry js_regexp_proto_funcs[] = {
JS_CFUNC_DEF("[Symbol.matchAll]", 1, js_regexp_Symbol_matchAll ),
JS_CFUNC_DEF("[Symbol.search]", 1, js_regexp_Symbol_search ),
JS_CFUNC_DEF("[Symbol.split]", 2, js_regexp_Symbol_split ),
- //JS_CGETSET_DEF("__source", js_regexp_get___source, NULL ),
- //JS_CGETSET_DEF("__flags", js_regexp_get___flags, NULL ),
};
static const JSCFunctionListEntry js_regexp_string_iterator_proto_funcs[] = {
@@ -45108,7 +44959,7 @@ void JS_AddIntrinsicRegExpCompiler(JSContext *ctx)
void JS_AddIntrinsicRegExp(JSContext *ctx)
{
- JSValueConst obj;
+ JSValue obj;
JS_AddIntrinsicRegExpCompiler(ctx);
@@ -45117,11 +44968,11 @@ void JS_AddIntrinsicRegExp(JSContext *ctx)
countof(js_regexp_proto_funcs));
obj = JS_NewGlobalCConstructor(ctx, "RegExp", js_regexp_constructor, 2,
ctx->class_proto[JS_CLASS_REGEXP]);
- ctx->regexp_ctor = JS_DupValue(ctx, obj);
+ ctx->regexp_ctor = js_dup(obj);
JS_SetPropertyFunctionList(ctx, obj, js_regexp_funcs, countof(js_regexp_funcs));
ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR] =
- JS_NewObjectProto(ctx, ctx->iterator_proto);
+ JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR],
js_regexp_string_iterator_proto_funcs,
countof(js_regexp_string_iterator_proto_funcs));
@@ -45129,15 +44980,6 @@ void JS_AddIntrinsicRegExp(JSContext *ctx)
/* JSON */
-static int json_parse_expect(JSParseState *s, int tok)
-{
- if (s->token.val != tok) {
- /* XXX: dump token correctly in all cases */
- return js_parse_error(s, "expecting '%c'", tok);
- }
- return json_next_token(s);
-}
-
static JSValue json_parse_value(JSParseState *s)
{
JSContext *ctx = s->ctx;
@@ -45161,15 +45003,17 @@ static JSValue json_parse_value(JSParseState *s)
prop_name = JS_ValueToAtom(ctx, s->token.u.str.str);
if (prop_name == JS_ATOM_NULL)
goto fail;
- } else if (s->ext_json && s->token.val == TOK_IDENT) {
- prop_name = JS_DupAtom(ctx, s->token.u.ident.atom);
} else {
- js_parse_error(s, "expecting property name");
+ json_parse_error(s, s->token.ptr, "Expected property name or '}'");
goto fail;
}
if (json_next_token(s))
goto fail1;
- if (json_parse_expect(s, ':'))
+ if (s->token.val != ':') {
+ json_parse_error(s, s->token.ptr, "Expected ':' after property name");
+ goto fail1;
+ }
+ if (json_next_token(s))
goto fail1;
prop_val = json_parse_value(s);
if (JS_IsException(prop_val)) {
@@ -45183,15 +45027,17 @@ static JSValue json_parse_value(JSParseState *s)
if (ret < 0)
goto fail;
- if (s->token.val != ',')
+ if (s->token.val == '}')
break;
+ if (s->token.val != ',') {
+ json_parse_error(s, s->token.ptr, "Expected ',' or '}' after property value");
+ goto fail;
+ }
if (json_next_token(s))
goto fail;
- if (s->ext_json && s->token.val == '}')
- break;
}
}
- if (json_parse_expect(s, '}'))
+ if (json_next_token(s))
goto fail;
}
break;
@@ -45206,29 +45052,29 @@ static JSValue json_parse_value(JSParseState *s)
if (JS_IsException(val))
goto fail;
if (s->token.val != ']') {
- idx = 0;
- for(;;) {
+ for(idx = 0;; idx++) {
el = json_parse_value(s);
if (JS_IsException(el))
goto fail;
ret = JS_DefinePropertyValueUint32(ctx, val, idx, el, JS_PROP_C_W_E);
if (ret < 0)
goto fail;
- if (s->token.val != ',')
+ if (s->token.val == ']')
break;
+ if (s->token.val != ',') {
+ json_parse_error(s, s->token.ptr, "Expected ',' or ']' after array element");
+ goto fail;
+ }
if (json_next_token(s))
goto fail;
- idx++;
- if (s->ext_json && s->token.val == ']')
- break;
}
}
- if (json_parse_expect(s, ']'))
+ if (json_next_token(s))
goto fail;
}
break;
case TOK_STRING:
- val = JS_DupValue(ctx, s->token.u.str.str);
+ val = js_dup(s->token.u.str.str);
if (json_next_token(s))
goto fail;
break;
@@ -45240,7 +45086,7 @@ static JSValue json_parse_value(JSParseState *s)
case TOK_IDENT:
if (s->token.u.ident.atom == JS_ATOM_false ||
s->token.u.ident.atom == JS_ATOM_true) {
- val = JS_NewBool(ctx, s->token.u.ident.atom == JS_ATOM_true);
+ val = js_bool(s->token.u.ident.atom == JS_ATOM_true);
} else if (s->token.u.ident.atom == JS_ATOM_null) {
val = JS_NULL;
} else {
@@ -45265,14 +45111,13 @@ static JSValue json_parse_value(JSParseState *s)
return JS_EXCEPTION;
}
-JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,
- const char *filename, int flags)
+/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */
+JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, const char *filename)
{
JSParseState s1, *s = &s1;
JSValue val = JS_UNDEFINED;
js_parse_init(ctx, s, buf, buf_len, filename, 1);
- s->ext_json = ((flags & JS_PARSE_JSON_EXT) != 0);
if (json_next_token(s))
goto fail;
val = json_parse_value(s);
@@ -45289,17 +45134,11 @@ JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,
return JS_EXCEPTION;
}
-JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
- const char *filename)
-{
- return JS_ParseJSON2(ctx, buf, buf_len, filename, 0);
-}
-
-static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,
- JSAtom name, JSValueConst reviver)
+static JSValue internalize_json_property(JSContext *ctx, JSValue holder,
+ JSAtom name, JSValue reviver)
{
JSValue val, new_el, name_val, res;
- JSValueConst args[2];
+ JSValue args[2];
int ret, is_array;
uint32_t i, len = 0;
JSAtom prop;
@@ -45364,11 +45203,11 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,
return JS_EXCEPTION;
}
-static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_json_parse(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj, root;
- JSValueConst reviver;
+ JSValue reviver;
const char *str;
size_t len;
@@ -45399,7 +45238,7 @@ static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val,
}
typedef struct JSONStringifyContext {
- JSValueConst replacer_func;
+ JSValue replacer_func;
JSValue stack;
JSValue property_list;
JSValue gap;
@@ -45414,32 +45253,25 @@ static JSValue JS_ToQuotedStringFree(JSContext *ctx, JSValue val) {
}
static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
- JSValueConst holder, JSValue val, JSValueConst key)
+ JSValue holder, JSValue val, JSValue key)
{
JSValue v;
- JSValueConst args[2];
-
- /* check for object.toJSON method */
- /* ECMA specifies this is done only for Object and BigInt */
- /* we do it for BigFloat and BigDecimal as an extension */
- if (JS_IsObject(val) || JS_IsBigInt(ctx, val)
-#ifdef CONFIG_BIGNUM
- || JS_IsBigFloat(val) || JS_IsBigDecimal(val)
-#endif
- ) {
- JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);
- if (JS_IsException(f))
- goto exception;
- if (JS_IsFunction(ctx, f)) {
- v = JS_CallFree(ctx, f, val, 1, &key);
- JS_FreeValue(ctx, val);
- val = v;
- if (JS_IsException(val))
- goto exception;
- } else {
- JS_FreeValue(ctx, f);
- }
- }
+ JSValue args[2];
+
+ if (JS_IsObject(val) || JS_IsBigInt(ctx, val)) {
+ JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);
+ if (JS_IsException(f))
+ goto exception;
+ if (JS_IsFunction(ctx, f)) {
+ v = JS_CallFree(ctx, f, val, 1, &key);
+ JS_FreeValue(ctx, val);
+ val = v;
+ if (JS_IsException(val))
+ goto exception;
+ } else {
+ JS_FreeValue(ctx, f);
+ }
+ }
if (!JS_IsUndefined(jsc->replacer_func)) {
args[0] = key;
@@ -45461,10 +45293,6 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
case JS_TAG_BOOL:
case JS_TAG_NULL:
case JS_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- case JS_TAG_BIG_DECIMAL:
-#endif
case JS_TAG_EXCEPTION:
return val;
default:
@@ -45479,14 +45307,14 @@ exception:
}
static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
- JSValueConst holder, JSValue val,
- JSValueConst indent)
+ JSValue holder, JSValue val,
+ JSValue indent)
{
JSValue indent1, sep, sep1, tab, v, prop;
JSObject *p;
int64_t i, len;
int cl, ret;
- BOOL has_content;
+ bool has_content;
indent1 = JS_UNDEFINED;
sep = JS_UNDEFINED;
@@ -45507,39 +45335,32 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
if (JS_IsException(val))
goto exception;
goto concat_primitive;
- } else if (cl == JS_CLASS_BOOLEAN || cl == JS_CLASS_BIG_INT
-#ifdef CONFIG_BIGNUM
- || cl == JS_CLASS_BIG_FLOAT
- || cl == JS_CLASS_BIG_DECIMAL
-#endif
- )
- {
- /* This will thow the same error as for the primitive object */
- set_value(ctx, &val, JS_DupValue(ctx, p->u.object_data));
+ } else if (cl == JS_CLASS_BOOLEAN || cl == JS_CLASS_BIG_INT) {
+ set_value(ctx, &val, js_dup(p->u.object_data));
goto concat_primitive;
}
- v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val);
+ v = js_array_includes(ctx, jsc->stack, 1, &val);
if (JS_IsException(v))
goto exception;
if (JS_ToBoolFree(ctx, v)) {
JS_ThrowTypeError(ctx, "circular reference");
goto exception;
}
- indent1 = JS_ConcatString(ctx, JS_DupValue(ctx, indent), JS_DupValue(ctx, jsc->gap));
+ indent1 = JS_ConcatString(ctx, js_dup(indent), js_dup(jsc->gap));
if (JS_IsException(indent1))
goto exception;
if (!JS_IsEmptyString(jsc->gap)) {
- sep = JS_ConcatString3(ctx, "\n", JS_DupValue(ctx, indent1), "");
+ sep = JS_ConcatString3(ctx, "\n", js_dup(indent1), "");
if (JS_IsException(sep))
goto exception;
- sep1 = JS_NewString(ctx, " ");
+ sep1 = js_new_string8(ctx, " ");
if (JS_IsException(sep1))
goto exception;
} else {
- sep = JS_DupValue(ctx, jsc->empty);
- sep1 = JS_DupValue(ctx, jsc->empty);
+ sep = js_dup(jsc->empty);
+ sep1 = js_dup(jsc->empty);
}
- v = js_array_push(ctx, jsc->stack, 1, (JSValueConst *)&val, 0);
+ v = js_array_push(ctx, jsc->stack, 1, &val, 0);
if (check_exception_free(ctx, v))
goto exception;
ret = JS_IsArray(ctx, val);
@@ -45557,7 +45378,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
if (JS_IsException(v))
goto exception;
/* XXX: could do this string conversion only when needed */
- prop = JS_ToStringFree(ctx, JS_NewInt64(ctx, i));
+ prop = JS_ToStringFree(ctx, js_int64(i));
if (JS_IsException(prop))
goto exception;
v = js_json_check(ctx, jsc, val, v, prop);
@@ -45577,21 +45398,21 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
string_buffer_putc8(jsc->b, ']');
} else {
if (!JS_IsUndefined(jsc->property_list))
- tab = JS_DupValue(ctx, jsc->property_list);
+ tab = js_dup(jsc->property_list);
else
- tab = js_object_keys(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY);
+ tab = js_object_keys(ctx, JS_UNDEFINED, 1, &val, JS_ITERATOR_KIND_KEY);
if (JS_IsException(tab))
goto exception;
if (js_get_length64(ctx, &len, tab))
goto exception;
string_buffer_putc8(jsc->b, '{');
- has_content = FALSE;
+ has_content = false;
for(i = 0; i < len; i++) {
JS_FreeValue(ctx, prop);
prop = JS_GetPropertyInt64(ctx, tab, i);
if (JS_IsException(prop))
goto exception;
- v = JS_GetPropertyValue(ctx, val, JS_DupValue(ctx, prop));
+ v = JS_GetPropertyValue(ctx, val, js_dup(prop));
if (JS_IsException(v))
goto exception;
v = js_json_check(ctx, jsc, val, v, prop);
@@ -45611,10 +45432,10 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
string_buffer_concat_value(jsc->b, sep1);
if (js_json_to_str(ctx, jsc, val, v, indent1))
goto exception;
- has_content = TRUE;
+ has_content = true;
}
}
- if (has_content && !JS_IsEmptyString(jsc->gap)) {
+ if (has_content && JS_VALUE_GET_STRING(jsc->gap)->len != 0) {
string_buffer_putc8(jsc->b, '\n');
string_buffer_concat_value(jsc->b, indent);
}
@@ -45648,12 +45469,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
concat_value:
return string_buffer_concat_value_free(jsc->b, val);
case JS_TAG_BIG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
- case JS_TAG_BIG_DECIMAL:
-#endif
- /* reject big numbers: use toJSON method to override */
- JS_ThrowTypeError(ctx, "Do not know how to serialize a BigInt");
+ JS_ThrowTypeError(ctx, "BigInt are forbidden in JSON.stringify");
goto exception;
default:
JS_FreeValue(ctx, val);
@@ -45670,8 +45486,8 @@ exception:
return -1;
}
-JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
- JSValueConst replacer, JSValueConst space0)
+JSValue JS_JSONStringify(JSContext *ctx, JSValue obj,
+ JSValue replacer, JSValue space0)
{
StringBuffer b_s;
JSONStringifyContext jsc_s, *jsc = &jsc_s;
@@ -45730,7 +45546,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
continue;
}
present = js_array_includes(ctx, jsc->property_list,
- 1, (JSValueConst *)&v);
+ 1, &v);
if (JS_IsException(present)) {
JS_FreeValue(ctx, v);
goto exception;
@@ -45743,7 +45559,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
}
}
}
- space = JS_DupValue(ctx, space0);
+ space = js_dup(space0);
if (JS_IsObject(space)) {
JSObject *p = JS_VALUE_GET_OBJ(space);
if (p->class_id == JS_CLASS_NUMBER) {
@@ -45765,7 +45581,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
JSString *p = JS_VALUE_GET_STRING(space);
jsc->gap = js_sub_string(ctx, p, 0, min_int(p->len, 10));
} else {
- jsc->gap = JS_DupValue(ctx, jsc->empty);
+ jsc->gap = js_dup(jsc->empty);
}
JS_FreeValue(ctx, space);
if (JS_IsException(jsc->gap))
@@ -45774,9 +45590,9 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
if (JS_IsException(wrapper))
goto exception;
if (JS_DefinePropertyValue(ctx, wrapper, JS_ATOM_empty_string,
- JS_DupValue(ctx, obj), JS_PROP_C_W_E) < 0)
+ js_dup(obj), JS_PROP_C_W_E) < 0)
goto exception;
- val = JS_DupValue(ctx, obj);
+ val = js_dup(obj);
val = js_json_check(ctx, jsc, wrapper, val, jsc->empty);
if (JS_IsException(val))
@@ -45804,8 +45620,8 @@ done:
return ret;
}
-static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_json_stringify(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// stringify(val, replacer, space)
return JS_JSONStringify(ctx, argv[0], argv[1], argv[2]);
@@ -45829,16 +45645,16 @@ void JS_AddIntrinsicJSON(JSContext *ctx)
/* Reflect */
-static JSValue js_reflect_apply(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_reflect_apply(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return js_function_apply(ctx, argv[0], max_int(0, argc - 1), argv + 1, 2);
}
-static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_reflect_construct(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst func, array_arg, new_target;
+ JSValue func, array_arg, new_target;
JSValue *tab, ret;
uint32_t len;
@@ -45854,15 +45670,15 @@ static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,
tab = build_arg_list(ctx, &len, array_arg);
if (!tab)
return JS_EXCEPTION;
- ret = JS_CallConstructor2(ctx, func, new_target, len, (JSValueConst *)tab);
+ ret = JS_CallConstructor2(ctx, func, new_target, len, tab);
free_arg_list(ctx, tab, len);
return ret;
}
-static JSValue js_reflect_deleteProperty(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_reflect_deleteProperty(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst obj;
+ JSValue obj;
JSAtom atom;
int ret;
@@ -45877,13 +45693,13 @@ static JSValue js_reflect_deleteProperty(JSContext *ctx, JSValueConst this_val,
if (ret < 0)
return JS_EXCEPTION;
else
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
-static JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_reflect_get(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst obj, prop, receiver;
+ JSValue obj, prop, receiver;
JSAtom atom;
JSValue ret;
@@ -45898,15 +45714,15 @@ static JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val,
atom = JS_ValueToAtom(ctx, prop);
if (unlikely(atom == JS_ATOM_NULL))
return JS_EXCEPTION;
- ret = JS_GetPropertyInternal(ctx, obj, atom, receiver, FALSE);
+ ret = JS_GetPropertyInternal(ctx, obj, atom, receiver, false);
JS_FreeAtom(ctx, atom);
return ret;
}
-static JSValue js_reflect_has(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_reflect_has(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst obj, prop;
+ JSValue obj, prop;
JSAtom atom;
int ret;
@@ -45922,13 +45738,13 @@ static JSValue js_reflect_has(JSContext *ctx, JSValueConst this_val,
if (ret < 0)
return JS_EXCEPTION;
else
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
-static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_reflect_set(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst obj, prop, val, receiver;
+ JSValue obj, prop, val, receiver;
int ret;
JSAtom atom;
@@ -45944,28 +45760,27 @@ static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val,
atom = JS_ValueToAtom(ctx, prop);
if (unlikely(atom == JS_ATOM_NULL))
return JS_EXCEPTION;
- ret = JS_SetPropertyInternal(ctx, obj, atom,
- JS_DupValue(ctx, val), receiver, 0);
+ ret = JS_SetPropertyInternal2(ctx, obj, atom, js_dup(val), receiver, 0);
JS_FreeAtom(ctx, atom);
if (ret < 0)
return JS_EXCEPTION;
else
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
-static JSValue js_reflect_setPrototypeOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_reflect_setPrototypeOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
int ret;
- ret = JS_SetPrototypeInternal(ctx, argv[0], argv[1], FALSE);
+ ret = JS_SetPrototypeInternal(ctx, argv[0], argv[1], false);
if (ret < 0)
return JS_EXCEPTION;
else
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
-static JSValue js_reflect_ownKeys(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_reflect_ownKeys(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT)
return JS_ThrowTypeErrorNotAnObject(ctx);
@@ -46007,7 +45822,7 @@ static void js_proxy_finalizer(JSRuntime *rt, JSValue val)
}
}
-static void js_proxy_mark(JSRuntime *rt, JSValueConst val,
+static void js_proxy_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSProxyData *s = JS_GetOpaque(val, JS_CLASS_PROXY);
@@ -46023,7 +45838,7 @@ static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx)
}
static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod,
- JSValueConst obj, JSAtom name)
+ JSValue obj, JSAtom name)
{
JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY);
JSValue method;
@@ -46048,7 +45863,7 @@ static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod,
return s;
}
-static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)
+static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValue obj)
{
JSProxyData *s;
JSValue method, ret, proto1;
@@ -46059,7 +45874,7 @@ static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)
return JS_EXCEPTION;
if (JS_IsUndefined(method))
return JS_GetPrototype(ctx, s->target);
- ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
+ ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
if (JS_IsException(ret))
return ret;
if (JS_VALUE_GET_TAG(ret) != JS_TAG_NULL &&
@@ -46089,13 +45904,13 @@ static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)
return ret;
}
-static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
- JSValueConst proto_val, BOOL throw_flag)
+static int js_proxy_setPrototypeOf(JSContext *ctx, JSValue obj,
+ JSValue proto_val, bool throw_flag)
{
JSProxyData *s;
JSValue method, ret, proto1;
- JSValueConst args[2];
- BOOL res;
+ JSValue args[2];
+ bool res;
int res2;
s = get_proxy_method(ctx, &method, obj, JS_ATOM_setPrototypeOf);
@@ -46114,7 +45929,7 @@ static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
JS_ThrowTypeError(ctx, "proxy: bad prototype");
return -1;
} else {
- return FALSE;
+ return false;
}
}
res2 = JS_IsExtensible(ctx, s->target);
@@ -46131,14 +45946,14 @@ static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
}
JS_FreeValue(ctx, proto1);
}
- return TRUE;
+ return true;
}
-static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj)
+static int js_proxy_isExtensible(JSContext *ctx, JSValue obj)
{
JSProxyData *s;
JSValue method, ret;
- BOOL res;
+ bool res;
int res2;
s = get_proxy_method(ctx, &method, obj, JS_ATOM_isExtensible);
@@ -46146,7 +45961,7 @@ static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj)
return -1;
if (JS_IsUndefined(method))
return JS_IsExtensible(ctx, s->target);
- ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
+ ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
if (JS_IsException(ret))
return -1;
res = JS_ToBoolFree(ctx, ret);
@@ -46160,11 +45975,11 @@ static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj)
return res;
}
-static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj)
+static int js_proxy_preventExtensions(JSContext *ctx, JSValue obj)
{
JSProxyData *s;
JSValue method, ret;
- BOOL res;
+ bool res;
int res2;
s = get_proxy_method(ctx, &method, obj, JS_ATOM_preventExtensions);
@@ -46172,7 +45987,7 @@ static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj)
return -1;
if (JS_IsUndefined(method))
return JS_PreventExtensions(ctx, s->target);
- ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
+ ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
if (JS_IsException(ret))
return -1;
res = JS_ToBoolFree(ctx, ret);
@@ -46188,14 +46003,14 @@ static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj)
return res;
}
-static int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom)
+static int js_proxy_has(JSContext *ctx, JSValue obj, JSAtom atom)
{
JSProxyData *s;
JSValue method, ret1, atom_val;
- int ret, res;
+ int res;
JSObject *p;
- JSValueConst args[2];
- BOOL res2;
+ JSValue args[2];
+ bool ret, res2;
s = get_proxy_method(ctx, &method, obj, JS_ATOM_has);
if (!s)
@@ -46232,13 +46047,13 @@ static int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom)
return ret;
}
-static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom,
- JSValueConst receiver)
+static JSValue js_proxy_get(JSContext *ctx, JSValue obj, JSAtom atom,
+ JSValue receiver)
{
JSProxyData *s;
JSValue method, ret, atom_val;
int res;
- JSValueConst args[3];
+ JSValue args[3];
JSPropertyDescriptor desc;
s = get_proxy_method(ctx, &method, obj, JS_ATOM_get);
@@ -46246,7 +46061,7 @@ static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom,
return JS_EXCEPTION;
/* Note: recursion is possible thru the prototype of s->target */
if (JS_IsUndefined(method))
- return JS_GetPropertyInternal(ctx, s->target, atom, receiver, FALSE);
+ return JS_GetPropertyInternal(ctx, s->target, atom, receiver, false);
atom_val = JS_AtomToValue(ctx, atom);
if (JS_IsException(atom_val)) {
JS_FreeValue(ctx, method);
@@ -46260,8 +46075,10 @@ static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom,
if (JS_IsException(ret))
return JS_EXCEPTION;
res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom);
- if (res < 0)
+ if (res < 0) {
+ JS_FreeValue(ctx, ret);
return JS_EXCEPTION;
+ }
if (res) {
if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0) {
if (!js_same_value(ctx, desc.value, ret)) {
@@ -46280,21 +46097,21 @@ static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom,
return ret;
}
-static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom,
- JSValueConst value, JSValueConst receiver, int flags)
+static int js_proxy_set(JSContext *ctx, JSValue obj, JSAtom atom,
+ JSValue value, JSValue receiver, int flags)
{
JSProxyData *s;
JSValue method, ret1, atom_val;
- int ret, res;
- JSValueConst args[4];
+ bool ret;
+ int res;
+ JSValue args[4];
s = get_proxy_method(ctx, &method, obj, JS_ATOM_set);
if (!s)
return -1;
if (JS_IsUndefined(method)) {
- return JS_SetPropertyInternal(ctx, s->target, atom,
- JS_DupValue(ctx, value), receiver,
- flags);
+ return JS_SetPropertyInternal2(ctx, s->target, atom,
+ js_dup(value), receiver, flags);
}
atom_val = JS_AtomToValue(ctx, atom);
if (JS_IsException(atom_val)) {
@@ -46338,8 +46155,8 @@ static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom,
return ret;
}
-static JSValue js_create_desc(JSContext *ctx, JSValueConst val,
- JSValueConst getter, JSValueConst setter,
+static JSValue js_create_desc(JSContext *ctx, JSValue val,
+ JSValue getter, JSValue setter,
int flags)
{
JSValue ret;
@@ -46347,43 +46164,43 @@ static JSValue js_create_desc(JSContext *ctx, JSValueConst val,
if (JS_IsException(ret))
return ret;
if (flags & JS_PROP_HAS_GET) {
- JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, JS_DupValue(ctx, getter),
+ JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, js_dup(getter),
JS_PROP_C_W_E);
}
if (flags & JS_PROP_HAS_SET) {
- JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, setter),
+ JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, js_dup(setter),
JS_PROP_C_W_E);
}
if (flags & JS_PROP_HAS_VALUE) {
- JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, val),
+ JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, js_dup(val),
JS_PROP_C_W_E);
}
if (flags & JS_PROP_HAS_WRITABLE) {
JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable,
- JS_NewBool(ctx, flags & JS_PROP_WRITABLE),
+ js_bool(flags & JS_PROP_WRITABLE),
JS_PROP_C_W_E);
}
if (flags & JS_PROP_HAS_ENUMERABLE) {
JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable,
- JS_NewBool(ctx, flags & JS_PROP_ENUMERABLE),
+ js_bool(flags & JS_PROP_ENUMERABLE),
JS_PROP_C_W_E);
}
if (flags & JS_PROP_HAS_CONFIGURABLE) {
JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable,
- JS_NewBool(ctx, flags & JS_PROP_CONFIGURABLE),
+ js_bool(flags & JS_PROP_CONFIGURABLE),
JS_PROP_C_W_E);
}
return ret;
}
static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc,
- JSValueConst obj, JSAtom prop)
+ JSValue obj, JSAtom prop)
{
JSProxyData *s;
JSValue method, trap_result_obj, prop_val;
int res, target_desc_ret, ret;
JSObject *p;
- JSValueConst args[2];
+ JSValue args[2];
JSPropertyDescriptor result_desc, target_desc;
s = get_proxy_method(ctx, &method, obj, JS_ATOM_getOwnPropertyDescriptor);
@@ -46420,7 +46237,7 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc
if (!(target_desc.flags & JS_PROP_CONFIGURABLE) || !p->extensible)
goto fail;
}
- ret = FALSE;
+ ret = false;
} else {
int flags1, extensible_target;
extensible_target = JS_IsExtensible(ctx, s->target);
@@ -46463,7 +46280,7 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc
return -1;
}
}
- ret = TRUE;
+ ret = true;
if (pdesc) {
*pdesc = result_desc;
} else {
@@ -46473,18 +46290,18 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc
return ret;
}
-static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj,
- JSAtom prop, JSValueConst val,
- JSValueConst getter, JSValueConst setter,
+static int js_proxy_define_own_property(JSContext *ctx, JSValue obj,
+ JSAtom prop, JSValue val,
+ JSValue getter, JSValue setter,
int flags)
{
JSProxyData *s;
JSValue method, ret1, prop_val, desc_val;
- int res, ret;
+ int res;
JSObject *p;
- JSValueConst args[3];
+ JSValue args[3];
JSPropertyDescriptor desc;
- BOOL setting_not_configurable;
+ bool ret, setting_not_configurable;
s = get_proxy_method(ctx, &method, obj, JS_ATOM_defineProperty);
if (!s)
@@ -46573,13 +46390,14 @@ static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj,
return 1;
}
-static int js_proxy_delete_property(JSContext *ctx, JSValueConst obj,
+static int js_proxy_delete_property(JSContext *ctx, JSValue obj,
JSAtom atom)
{
JSProxyData *s;
JSValue method, ret, atom_val;
- int res, res2, is_extensible;
- JSValueConst args[2];
+ int res2, is_extensible;
+ bool res;
+ JSValue args[2];
s = get_proxy_method(ctx, &method, obj, JS_ATOM_deleteProperty);
if (!s)
@@ -46638,7 +46456,7 @@ static int find_prop_key(const JSPropertyEnum *tab, int n, JSAtom atom)
static int js_proxy_get_own_property_names(JSContext *ctx,
JSPropertyEnum **ptab,
uint32_t *plen,
- JSValueConst obj)
+ JSValue obj)
{
JSProxyData *s;
JSValue method, prop_array, val;
@@ -46656,7 +46474,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx,
JS_VALUE_GET_OBJ(s->target),
JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK);
}
- prop_array = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
+ prop_array = JS_CallFree(ctx, method, s->handler, 1, &s->target);
if (JS_IsException(prop_array))
return -1;
tab = NULL;
@@ -46684,7 +46502,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx,
if (atom == JS_ATOM_NULL)
goto fail;
tab[i].atom = atom;
- tab[i].is_enumerable = FALSE; /* XXX: redundant? */
+ tab[i].is_enumerable = false; /* XXX: redundant? */
}
/* check duplicate properties (XXX: inefficient, could store the
@@ -46727,7 +46545,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx,
}
/* mark the property as found */
if (!is_extensible)
- tab[idx].is_enumerable = TRUE;
+ tab[idx].is_enumerable = true;
}
}
}
@@ -46753,13 +46571,13 @@ static int js_proxy_get_own_property_names(JSContext *ctx,
return -1;
}
-static JSValue js_proxy_call_constructor(JSContext *ctx, JSValueConst func_obj,
- JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_proxy_call_constructor(JSContext *ctx, JSValue func_obj,
+ JSValue new_target,
+ int argc, JSValue *argv)
{
JSProxyData *s;
JSValue method, arg_array, ret;
- JSValueConst args[3];
+ JSValue args[3];
s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_construct);
if (!s)
@@ -46787,13 +46605,13 @@ static JSValue js_proxy_call_constructor(JSContext *ctx, JSValueConst func_obj,
return ret;
}
-static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_obj,
- int argc, JSValueConst *argv, int flags)
+static JSValue js_proxy_call(JSContext *ctx, JSValue func_obj,
+ JSValue this_obj,
+ int argc, JSValue *argv, int flags)
{
JSProxyData *s;
JSValue method, arg_array, ret;
- JSValueConst args[3];
+ JSValue args[3];
if (flags & JS_CALL_FLAG_CONSTRUCTOR)
return js_proxy_call_constructor(ctx, func_obj, this_obj, argc, argv);
@@ -46803,7 +46621,7 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj,
return JS_EXCEPTION;
if (!s->is_func) {
JS_FreeValue(ctx, method);
- return JS_ThrowTypeError(ctx, "not a function");
+ return JS_ThrowTypeErrorNotAFunction(ctx);
}
if (JS_IsUndefined(method))
return JS_Call(ctx, s->target, this_obj, argc, argv);
@@ -46822,35 +46640,22 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj,
return ret;
}
-/* `js_resolve_proxy`: resolve the proxy chain
- `*pval` is updated with to ultimate proxy target
- `throw_exception` controls whether exceptions are thown or not
- - return -1 in case of error
- - otherwise return 0
- */
-static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, BOOL throw_exception) {
- int depth = 0;
- JSObject *p;
- JSProxyData *s;
+static int js_proxy_isArray(JSContext *ctx, JSValue obj)
+{
+ JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY);
+ if (!s)
+ return false;
- while (JS_VALUE_GET_TAG(*pval) == JS_TAG_OBJECT) {
- p = JS_VALUE_GET_OBJ(*pval);
- if (p->class_id != JS_CLASS_PROXY)
- break;
- if (depth++ > 1000) {
- if (throw_exception)
- JS_ThrowStackOverflow(ctx);
- return -1;
- }
- s = p->u.opaque;
- if (s->is_revoked) {
- if (throw_exception)
- JS_ThrowTypeErrorRevokedProxy(ctx);
- return -1;
- }
- *pval = s->target;
+ if (js_check_stack_overflow(ctx->rt, 0)) {
+ JS_ThrowStackOverflow(ctx);
+ return -1;
}
- return 0;
+
+ if (s->is_revoked) {
+ JS_ThrowTypeErrorRevokedProxy(ctx);
+ return -1;
+ }
+ return JS_IsArray(ctx, s->target);
}
static const JSClassExoticMethods js_proxy_exotic_methods = {
@@ -46863,10 +46668,10 @@ static const JSClassExoticMethods js_proxy_exotic_methods = {
.set_property = js_proxy_set,
};
-static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_proxy_constructor(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst target, handler;
+ JSValue target, handler;
JSValue obj;
JSProxyData *s;
@@ -46884,24 +46689,24 @@ static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
- s->target = JS_DupValue(ctx, target);
- s->handler = JS_DupValue(ctx, handler);
+ s->target = js_dup(target);
+ s->handler = js_dup(handler);
s->is_func = JS_IsFunction(ctx, target);
- s->is_revoked = FALSE;
- JS_SetOpaque(obj, s);
+ s->is_revoked = false;
+ JS_SetOpaqueInternal(obj, s);
JS_SetConstructorBit(ctx, obj, JS_IsConstructor(ctx, target));
return obj;
}
-static JSValue js_proxy_revoke(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic,
+static JSValue js_proxy_revoke(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic,
JSValue *func_data)
{
JSProxyData *s = JS_GetOpaque(func_data[0], JS_CLASS_PROXY);
if (s) {
/* We do not free the handler and target in case they are
referenced as constants in the C call stack */
- s->is_revoked = TRUE;
+ s->is_revoked = true;
JS_FreeValue(ctx, func_data[0]);
func_data[0] = JS_NULL;
}
@@ -46909,13 +46714,13 @@ static JSValue js_proxy_revoke(JSContext *ctx, JSValueConst this_val,
}
static JSValue js_proxy_revoke_constructor(JSContext *ctx,
- JSValueConst proxy_obj)
+ JSValue proxy_obj)
{
return JS_NewCFunctionData(ctx, js_proxy_revoke, 0, 0, 1, &proxy_obj);
}
-static JSValue js_proxy_revocable(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_proxy_revocable(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue proxy_obj, revoke_obj = JS_UNDEFINED, obj;
@@ -46960,7 +46765,7 @@ void JS_AddIntrinsicProxy(JSContext *ctx)
obj1 = JS_NewCFunction2(ctx, js_proxy_constructor, "Proxy", 2,
JS_CFUNC_constructor, 0);
- JS_SetConstructorBit(ctx, obj1, TRUE);
+ JS_SetConstructorBit(ctx, obj1, true);
JS_SetPropertyFunctionList(ctx, obj1, js_proxy_funcs,
countof(js_proxy_funcs));
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Proxy",
@@ -46969,8 +46774,8 @@ void JS_AddIntrinsicProxy(JSContext *ctx)
/* Symbol */
-static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_symbol_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
{
JSValue str;
JSString *p;
@@ -46985,44 +46790,44 @@ static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target,
return JS_EXCEPTION;
p = JS_VALUE_GET_STRING(str);
}
- return JS_NewSymbol(ctx, p, JS_ATOM_TYPE_SYMBOL);
+ return JS_NewSymbolInternal(ctx, p, JS_ATOM_TYPE_SYMBOL);
}
-static JSValue js_thisSymbolValue(JSContext *ctx, JSValueConst this_val)
+static JSValue js_thisSymbolValue(JSContext *ctx, JSValue this_val)
{
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_SYMBOL)
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(this_val);
if (p->class_id == JS_CLASS_SYMBOL) {
if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_SYMBOL)
- return JS_DupValue(ctx, p->u.object_data);
+ return js_dup(p->u.object_data);
}
}
return JS_ThrowTypeError(ctx, "not a symbol");
}
-static JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_symbol_toString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue val, ret;
val = js_thisSymbolValue(ctx, this_val);
if (JS_IsException(val))
return val;
/* XXX: use JS_ToStringInternal() with a flags */
- ret = js_string_constructor(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val);
+ ret = js_string_constructor(ctx, JS_UNDEFINED, 1, &val);
JS_FreeValue(ctx, val);
return ret;
}
-static JSValue js_symbol_valueOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_symbol_valueOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return js_thisSymbolValue(ctx, this_val);
}
-static JSValue js_symbol_get_description(JSContext *ctx, JSValueConst this_val)
+static JSValue js_symbol_get_description(JSContext *ctx, JSValue this_val)
{
JSValue val, ret;
JSAtomStruct *p;
@@ -47049,19 +46854,19 @@ static const JSCFunctionListEntry js_symbol_proto_funcs[] = {
JS_CGETSET_DEF("description", js_symbol_get_description, NULL ),
};
-static JSValue js_symbol_for(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_symbol_for(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue str;
str = JS_ToString(ctx, argv[0]);
if (JS_IsException(str))
return JS_EXCEPTION;
- return JS_NewSymbol(ctx, JS_VALUE_GET_STRING(str), JS_ATOM_TYPE_GLOBAL_SYMBOL);
+ return JS_NewSymbolInternal(ctx, JS_VALUE_GET_STRING(str), JS_ATOM_TYPE_GLOBAL_SYMBOL);
}
-static JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_symbol_keyFor(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSAtomStruct *p;
@@ -47070,7 +46875,7 @@ static JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val,
p = JS_VALUE_GET_PTR(argv[0]);
if (p->atom_type != JS_ATOM_TYPE_GLOBAL_SYMBOL)
return JS_UNDEFINED;
- return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
+ return js_dup(JS_MKPTR(JS_TAG_STRING, p));
}
static const JSCFunctionListEntry js_symbol_funcs[] = {
@@ -47082,9 +46887,8 @@ static const JSCFunctionListEntry js_symbol_funcs[] = {
typedef struct JSMapRecord {
int ref_count; /* used during enumeration to avoid freeing the record */
- BOOL empty; /* TRUE if the record is deleted */
+ bool empty; /* true if the record is deleted */
struct JSMapState *map;
- struct JSMapRecord *next_weak_ref;
struct list_head link;
struct list_head hash_link;
JSValue key;
@@ -47092,7 +46896,7 @@ typedef struct JSMapRecord {
} JSMapRecord;
typedef struct JSMapState {
- BOOL is_weak; /* TRUE if WeakSet/WeakMap */
+ bool is_weak; /* true if WeakSet/WeakMap */
struct list_head records; /* list of JSMapRecord.link */
uint32_t record_count;
struct list_head *hash_table;
@@ -47104,13 +46908,13 @@ typedef struct JSMapState {
#define MAGIC_SET (1 << 0)
#define MAGIC_WEAK (1 << 1)
-static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_map_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv, int magic)
{
JSMapState *s;
JSValue obj, adder = JS_UNDEFINED, iter = JS_UNDEFINED, next_method = JS_UNDEFINED;
- JSValueConst arr;
- BOOL is_set, is_weak;
+ JSValue arr;
+ bool is_set, is_weak;
is_set = magic & MAGIC_SET;
is_weak = ((magic & MAGIC_WEAK) != 0);
@@ -47122,7 +46926,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
goto fail;
init_list_head(&s->records);
s->is_weak = is_weak;
- JS_SetOpaque(obj, s);
+ JS_SetOpaqueInternal(obj, s);
s->hash_size = 1;
s->hash_table = js_malloc(ctx, sizeof(s->hash_table[0]) * s->hash_size);
if (!s->hash_table)
@@ -47135,7 +46939,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
arr = argv[0];
if (!JS_IsUndefined(arr) && !JS_IsNull(arr)) {
JSValue item, ret;
- BOOL done;
+ int done;
adder = JS_GetProperty(ctx, obj, is_set ? JS_ATOM_add : JS_ATOM_set);
if (JS_IsException(adder))
@@ -47145,7 +46949,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
goto fail;
}
- iter = JS_GetIterator(ctx, arr, FALSE);
+ iter = JS_GetIterator(ctx, arr, false);
if (JS_IsException(iter))
goto fail;
next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);
@@ -47161,14 +46965,14 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
break;
}
if (is_set) {
- ret = JS_Call(ctx, adder, obj, 1, (JSValueConst *)&item);
+ ret = JS_Call(ctx, adder, obj, 1, &item);
if (JS_IsException(ret)) {
JS_FreeValue(ctx, item);
goto fail;
}
} else {
JSValue key, value;
- JSValueConst args[2];
+ JSValue args[2];
key = JS_UNDEFINED;
value = JS_UNDEFINED;
if (!JS_IsObject(item)) {
@@ -47205,7 +47009,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
fail:
if (JS_IsObject(iter)) {
/* close the iterator object, preserving pending exception */
- JS_IteratorClose(ctx, iter, TRUE);
+ JS_IteratorClose(ctx, iter, true);
}
JS_FreeValue(ctx, next_method);
JS_FreeValue(ctx, iter);
@@ -47215,23 +47019,24 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
}
/* XXX: could normalize strings to speed up comparison */
-static JSValueConst map_normalize_key(JSContext *ctx, JSValueConst key)
+static JSValue map_normalize_key(JSContext *ctx, JSValue key)
{
uint32_t tag = JS_VALUE_GET_TAG(key);
/* convert -0.0 to +0.0 */
if (JS_TAG_IS_FLOAT64(tag) && JS_VALUE_GET_FLOAT64(key) == 0.0) {
- key = JS_NewInt32(ctx, 0);
+ key = js_int32(0);
}
return key;
}
/* XXX: better hash ? */
-static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
+static uint32_t map_hash_key(JSContext *ctx, JSValue key)
{
uint32_t tag = JS_VALUE_GET_NORM_TAG(key);
uint32_t h;
double d;
JSFloat64Union u;
+ bf_t *a;
switch(tag) {
case JS_TAG_BOOL:
@@ -47247,17 +47052,21 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
case JS_TAG_INT:
d = JS_VALUE_GET_INT(key);
goto hash_float64;
+ case JS_TAG_BIG_INT:
+ a = JS_GetBigInt(key);
+ h = hash_string8((void *)a->tab, a->len * sizeof(*a->tab), 0);
+ break;
case JS_TAG_FLOAT64:
d = JS_VALUE_GET_FLOAT64(key);
/* normalize the NaN */
if (isnan(d))
- d = JS_FLOAT64_NAN;
+ d = NAN;
hash_float64:
u.d = d;
h = (u.u32[0] ^ u.u32[1]) * 3163;
return h ^= JS_TAG_FLOAT64;
default:
- h = 0; /* XXX: bignum support */
+ h = 0;
break;
}
h ^= tag;
@@ -47265,7 +47074,7 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
}
static JSMapRecord *map_find_record(JSContext *ctx, JSMapState *s,
- JSValueConst key)
+ JSValue key)
{
struct list_head *el;
JSMapRecord *mr;
@@ -47312,8 +47121,29 @@ static void map_hash_resize(JSContext *ctx, JSMapState *s)
s->record_count_threshold = new_hash_size * 2;
}
+static JSWeakRefRecord **get_first_weak_ref(JSValue key)
+{
+ switch (JS_VALUE_GET_TAG(key)) {
+ case JS_TAG_OBJECT:
+ {
+ JSObject *p = JS_VALUE_GET_OBJ(key);
+ return &p->first_weak_ref;
+ }
+ break;
+ case JS_TAG_SYMBOL:
+ {
+ JSAtomStruct *p = JS_VALUE_GET_PTR(key);
+ return &p->first_weak_ref;
+ }
+ break;
+ default:
+ abort();
+ }
+ return NULL; // pacify compiler
+}
+
static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,
- JSValueConst key)
+ JSValue key)
{
uint32_t h;
JSMapRecord *mr;
@@ -47323,14 +47153,18 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,
return NULL;
mr->ref_count = 1;
mr->map = s;
- mr->empty = FALSE;
+ mr->empty = false;
if (s->is_weak) {
- JSObject *p = JS_VALUE_GET_OBJ(key);
- /* Add the weak reference */
- mr->next_weak_ref = p->first_weak_ref;
- p->first_weak_ref = mr;
+ JSWeakRefRecord *wr = js_malloc(ctx, sizeof(*wr));
+ if (!wr) {
+ js_free(ctx, mr);
+ return NULL;
+ }
+ wr->kind = JS_WEAK_REF_KIND_MAP;
+ wr->u.map_record = mr;
+ insert_weakref_record(key, wr);
} else {
- JS_DupValue(ctx, key);
+ js_dup(key);
}
mr->key = key;
h = map_hash_key(ctx, key) & (s->hash_size - 1);
@@ -47347,21 +47181,20 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,
reference list. we don't use a doubly linked list to
save space, assuming a given object has few weak
references to it */
-static void delete_weak_ref(JSRuntime *rt, JSMapRecord *mr)
+static void delete_map_weak_ref(JSRuntime *rt, JSMapRecord *mr)
{
- JSMapRecord **pmr, *mr1;
- JSObject *p;
+ JSWeakRefRecord **pwr, *wr;
- p = JS_VALUE_GET_OBJ(mr->key);
- pmr = &p->first_weak_ref;
+ pwr = get_first_weak_ref(mr->key);
for(;;) {
- mr1 = *pmr;
- assert(mr1 != NULL);
- if (mr1 == mr)
+ wr = *pwr;
+ assert(wr != NULL);
+ if (wr->kind == JS_WEAK_REF_KIND_MAP && wr->u.map_record == mr)
break;
- pmr = &mr1->next_weak_ref;
+ pwr = &wr->next_weak_ref;
}
- *pmr = mr1->next_weak_ref;
+ *pwr = wr->next_weak_ref;
+ js_free_rt(rt, wr);
}
static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr)
@@ -47370,7 +47203,7 @@ static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr)
return;
list_del(&mr->hash_link);
if (s->is_weak) {
- delete_weak_ref(rt, mr);
+ delete_map_weak_ref(rt, mr);
} else {
JS_FreeValueRT(rt, mr->key);
}
@@ -47380,7 +47213,7 @@ static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr)
js_free_rt(rt, mr);
} else {
/* keep a zombie record for iterators */
- mr->empty = TRUE;
+ mr->empty = true;
mr->key = JS_UNDEFINED;
mr->value = JS_UNDEFINED;
}
@@ -47397,45 +47230,21 @@ static void map_decref_record(JSRuntime *rt, JSMapRecord *mr)
}
}
-static void reset_weak_ref(JSRuntime *rt, JSObject *p)
-{
- JSMapRecord *mr, *mr_next;
- JSMapState *s;
-
- /* first pass to remove the records from the WeakMap/WeakSet
- lists */
- for(mr = p->first_weak_ref; mr != NULL; mr = mr->next_weak_ref) {
- s = mr->map;
- assert(s->is_weak);
- assert(!mr->empty); /* no iterator on WeakMap/WeakSet */
- list_del(&mr->hash_link);
- list_del(&mr->link);
- }
-
- /* second pass to free the values to avoid modifying the weak
- reference list while traversing it. */
- for(mr = p->first_weak_ref; mr != NULL; mr = mr_next) {
- mr_next = mr->next_weak_ref;
- JS_FreeValueRT(rt, mr->value);
- js_free_rt(rt, mr);
- }
-
- p->first_weak_ref = NULL; /* fail safe */
-}
-
-static JSValue js_map_set(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_map_set(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);
JSMapRecord *mr;
- JSValueConst key, value;
+ JSValue key, value;
+ int is_set;
if (!s)
return JS_EXCEPTION;
+ is_set = (magic & MAGIC_SET);
key = map_normalize_key(ctx, argv[0]);
- if (s->is_weak && !JS_IsObject(key))
- return JS_ThrowTypeErrorNotAnObject(ctx);
- if (magic & MAGIC_SET)
+ if (s->is_weak && !is_valid_weakref_target(key))
+ return JS_ThrowTypeError(ctx, "invalid value used as %s key", is_set ? "WeakSet" : "WeakMap");
+ if (is_set)
value = JS_UNDEFINED;
else
value = argv[1];
@@ -47447,16 +47256,16 @@ static JSValue js_map_set(JSContext *ctx, JSValueConst this_val,
if (!mr)
return JS_EXCEPTION;
}
- mr->value = JS_DupValue(ctx, value);
- return JS_DupValue(ctx, this_val);
+ mr->value = js_dup(value);
+ return js_dup(this_val);
}
-static JSValue js_map_get(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_map_get(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);
JSMapRecord *mr;
- JSValueConst key;
+ JSValue key;
if (!s)
return JS_EXCEPTION;
@@ -47465,29 +47274,29 @@ static JSValue js_map_get(JSContext *ctx, JSValueConst this_val,
if (!mr)
return JS_UNDEFINED;
else
- return JS_DupValue(ctx, mr->value);
+ return js_dup(mr->value);
}
-static JSValue js_map_has(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_map_has(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);
JSMapRecord *mr;
- JSValueConst key;
+ JSValue key;
if (!s)
return JS_EXCEPTION;
key = map_normalize_key(ctx, argv[0]);
mr = map_find_record(ctx, s, key);
- return JS_NewBool(ctx, mr != NULL);
+ return js_bool(mr != NULL);
}
-static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_map_delete(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);
JSMapRecord *mr;
- JSValueConst key;
+ JSValue key;
if (!s)
return JS_EXCEPTION;
@@ -47499,8 +47308,8 @@ static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val,
return JS_TRUE;
}
-static JSValue js_map_clear(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_map_clear(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);
struct list_head *el, *el1;
@@ -47515,19 +47324,19 @@ static JSValue js_map_clear(JSContext *ctx, JSValueConst this_val,
return JS_UNDEFINED;
}
-static JSValue js_map_get_size(JSContext *ctx, JSValueConst this_val, int magic)
+static JSValue js_map_get_size(JSContext *ctx, JSValue this_val, int magic)
{
JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);
if (!s)
return JS_EXCEPTION;
- return JS_NewUint32(ctx, s->record_count);
+ return js_uint32(s->record_count);
}
-static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_map_forEach(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);
- JSValueConst func, this_arg;
+ JSValue func, this_arg;
JSValue ret, args[3];
struct list_head *el;
JSMapRecord *mr;
@@ -47549,13 +47358,13 @@ static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val,
if (!mr->empty) {
mr->ref_count++;
/* must duplicate in case the record is deleted */
- args[1] = JS_DupValue(ctx, mr->key);
+ args[1] = js_dup(mr->key);
if (magic)
args[0] = args[1];
else
- args[0] = JS_DupValue(ctx, mr->value);
+ args[0] = js_dup(mr->value);
args[2] = this_val;
- ret = JS_Call(ctx, func, this_arg, 3, (JSValueConst *)args);
+ ret = JS_Call(ctx, func, this_arg, 3, args);
JS_FreeValue(ctx, args[0]);
if (!magic)
JS_FreeValue(ctx, args[1]);
@@ -47571,26 +47380,24 @@ static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val,
return JS_UNDEFINED;
}
-static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int is_map)
+static JSValue js_map_groupBy(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst cb, args[2];
- JSValue res, iter, next, groups, key, v, prop;
- JSAtom key_atom = JS_ATOM_NULL;
+ JSValue cb, res, iter, next, groups, k, v, prop;
+ JSValue args[2];
int64_t idx;
- BOOL done;
+ int done;
// "is function?" check must be observed before argv[0] is accessed
cb = argv[1];
if (check_function(ctx, cb))
return JS_EXCEPTION;
- iter = JS_GetIterator(ctx, argv[0], /*is_async*/FALSE);
+ iter = JS_GetIterator(ctx, argv[0], /*is_async*/false);
if (JS_IsException(iter))
return JS_EXCEPTION;
- key = JS_UNDEFINED;
- key_atom = JS_ATOM_NULL;
+ k = JS_UNDEFINED;
v = JS_UNDEFINED;
prop = JS_UNDEFINED;
groups = JS_UNDEFINED;
@@ -47599,19 +47406,11 @@ static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(next))
goto exception;
- if (is_map) {
- groups = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, 0);
- } else {
- groups = JS_NewObjectProto(ctx, JS_NULL);
- }
+ groups = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, 0);
if (JS_IsException(groups))
goto exception;
for (idx = 0; ; idx++) {
- if (idx >= MAX_SAFE_INTEGER) {
- JS_ThrowTypeError(ctx, "too many elements");
- goto iterator_close_exception;
- }
v = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
if (JS_IsException(v))
goto exception;
@@ -47619,21 +47418,12 @@ static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
break; // v is JS_UNDEFINED
args[0] = v;
- args[1] = JS_NewInt64(ctx, idx);
- key = JS_Call(ctx, cb, ctx->global_obj, 2, args);
- if (JS_IsException(key))
- goto iterator_close_exception;
+ args[1] = js_int64(idx);
+ k = JS_Call(ctx, cb, ctx->global_obj, 2, args);
+ if (JS_IsException(k))
+ goto exception;
- if (is_map) {
- prop = js_map_get(ctx, groups, 1, (JSValueConst *)&key, 0);
- } else {
- key_atom = JS_ValueToAtom(ctx, key);
- JS_FreeValue(ctx, key);
- key = JS_UNDEFINED;
- if (key_atom == JS_ATOM_NULL)
- goto iterator_close_exception;
- prop = JS_GetProperty(ctx, groups, key_atom);
- }
+ prop = js_map_get(ctx, groups, 1, &k, 0);
if (JS_IsException(prop))
goto exception;
@@ -47641,33 +47431,24 @@ static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
prop = JS_NewArray(ctx);
if (JS_IsException(prop))
goto exception;
- if (is_map) {
- args[0] = key;
- args[1] = prop;
- res = js_map_set(ctx, groups, 2, args, 0);
- if (JS_IsException(res))
- goto exception;
- JS_FreeValue(ctx, res);
- } else {
- prop = JS_DupValue(ctx, prop);
- if (JS_DefinePropertyValue(ctx, groups, key_atom, prop,
- JS_PROP_C_W_E) < 0) {
- goto exception;
- }
- }
+ args[0] = k;
+ args[1] = prop;
+ res = js_map_set(ctx, groups, 2, args, 0);
+ if (JS_IsException(res))
+ goto exception;
+ JS_FreeValue(ctx, res);
}
- res = js_array_push(ctx, prop, 1, (JSValueConst *)&v, /*unshift*/0);
+
+ res = js_array_push(ctx, prop, 1, &v, /*unshift*/0);
if (JS_IsException(res))
goto exception;
// res is an int64
JS_FreeValue(ctx, prop);
- JS_FreeValue(ctx, key);
- JS_FreeAtom(ctx, key_atom);
+ JS_FreeValue(ctx, k);
JS_FreeValue(ctx, v);
prop = JS_UNDEFINED;
- key = JS_UNDEFINED;
- key_atom = JS_ATOM_NULL;
+ k = JS_UNDEFINED;
v = JS_UNDEFINED;
}
@@ -47675,12 +47456,9 @@ static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, next);
return groups;
- iterator_close_exception:
- JS_IteratorClose(ctx, iter, TRUE);
- exception:
- JS_FreeAtom(ctx, key_atom);
+exception:
JS_FreeValue(ctx, prop);
- JS_FreeValue(ctx, key);
+ JS_FreeValue(ctx, k);
JS_FreeValue(ctx, v);
JS_FreeValue(ctx, groups);
JS_FreeValue(ctx, iter);
@@ -47704,7 +47482,7 @@ static void js_map_finalizer(JSRuntime *rt, JSValue val)
mr = list_entry(el, JSMapRecord, link);
if (!mr->empty) {
if (s->is_weak)
- delete_weak_ref(rt, mr);
+ delete_map_weak_ref(rt, mr);
else
JS_FreeValueRT(rt, mr->key);
JS_FreeValueRT(rt, mr->value);
@@ -47716,7 +47494,7 @@ static void js_map_finalizer(JSRuntime *rt, JSValue val)
}
}
-static void js_map_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)
+static void js_map_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
JSMapState *s;
@@ -47760,7 +47538,7 @@ static void js_map_iterator_finalizer(JSRuntime *rt, JSValue val)
}
}
-static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val,
+static void js_map_iterator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -47772,8 +47550,8 @@ static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val,
}
}
-static JSValue js_create_map_iterator(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_create_map_iterator(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSIteratorKindEnum kind;
JSMapState *s;
@@ -47793,18 +47571,18 @@ static JSValue js_create_map_iterator(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, enum_obj);
goto fail;
}
- it->obj = JS_DupValue(ctx, this_val);
+ it->obj = js_dup(this_val);
it->kind = kind;
it->cur_record = NULL;
- JS_SetOpaque(enum_obj, it);
+ JS_SetOpaqueInternal(enum_obj, it);
return enum_obj;
fail:
return JS_EXCEPTION;
}
-static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
- BOOL *pdone, int magic)
+static JSValue js_map_iterator_next(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
+ int *pdone, int magic)
{
JSMapIteratorData *it;
JSMapState *s;
@@ -47813,7 +47591,7 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val,
it = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP_ITERATOR + magic);
if (!it) {
- *pdone = FALSE;
+ *pdone = false;
return JS_EXCEPTION;
}
if (JS_IsUndefined(it->obj))
@@ -47835,7 +47613,7 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val,
it->obj = JS_UNDEFINED;
done:
/* end of enumeration */
- *pdone = TRUE;
+ *pdone = true;
return JS_UNDEFINED;
}
mr = list_entry(el, JSMapRecord, link);
@@ -47848,27 +47626,705 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val,
/* lock the record so that it won't be freed */
mr->ref_count++;
it->cur_record = mr;
- *pdone = FALSE;
+ *pdone = false;
if (it->kind == JS_ITERATOR_KIND_KEY) {
- return JS_DupValue(ctx, mr->key);
+ return js_dup(mr->key);
} else {
- JSValueConst args[2];
+ JSValue args[2];
args[0] = mr->key;
if (magic)
args[1] = mr->key;
else
args[1] = mr->value;
if (it->kind == JS_ITERATOR_KIND_VALUE) {
- return JS_DupValue(ctx, args[1]);
+ return js_dup(args[1]);
} else {
return js_create_array(ctx, 2, args);
}
}
}
+static JSValue js_map_read(BCReaderState *s, int magic)
+{
+ JSContext *ctx = s->ctx;
+ JSValue obj, rv, argv[2];
+ uint32_t i, prop_count;
+
+ argv[0] = JS_UNDEFINED;
+ argv[1] = JS_UNDEFINED;
+ obj = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, magic);
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+ if (BC_add_object_ref(s, obj))
+ goto fail;
+ if (bc_get_leb128(s, &prop_count))
+ goto fail;
+ for(i = 0; i < prop_count; i++) {
+ argv[0] = JS_ReadObjectRec(s);
+ if (JS_IsException(argv[0]))
+ goto fail;
+ if (!(magic & MAGIC_SET)) {
+ argv[1] = JS_ReadObjectRec(s);
+ if (JS_IsException(argv[1]))
+ goto fail;
+ }
+ rv = js_map_set(ctx, obj, countof(argv), argv, magic);
+ if (JS_IsException(rv))
+ goto fail;
+ JS_FreeValue(ctx, rv);
+ JS_FreeValue(ctx, argv[0]);
+ JS_FreeValue(ctx, argv[1]);
+ argv[0] = JS_UNDEFINED;
+ argv[1] = JS_UNDEFINED;
+ }
+ return obj;
+ fail:
+ JS_FreeValue(ctx, obj);
+ JS_FreeValue(ctx, argv[0]);
+ JS_FreeValue(ctx, argv[1]);
+ return JS_EXCEPTION;
+}
+
+static int js_map_write(BCWriterState *s, struct JSMapState *map_state,
+ int magic)
+{
+ struct list_head *el;
+ JSMapRecord *mr;
+
+ bc_put_leb128(s, map_state ? map_state->record_count : 0);
+ if (map_state) {
+ list_for_each(el, &map_state->records) {
+ mr = list_entry(el, JSMapRecord, link);
+ if (JS_WriteObjectRec(s, mr->key))
+ return -1;
+ // mr->value is always JS_UNDEFINED for sets
+ if (!(magic & MAGIC_SET))
+ if (JS_WriteObjectRec(s, mr->value))
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static JSValue JS_ReadMap(BCReaderState *s)
+{
+ return js_map_read(s, 0);
+}
+
+static JSValue JS_ReadSet(BCReaderState *s)
+{
+ return js_map_read(s, MAGIC_SET);
+}
+
+static int JS_WriteMap(BCWriterState *s, struct JSMapState *map_state)
+{
+ return js_map_write(s, map_state, 0);
+}
+
+static int JS_WriteSet(BCWriterState *s, struct JSMapState *map_state)
+{
+ return js_map_write(s, map_state, MAGIC_SET);
+}
+
+static int js_setlike_get_size(JSContext *ctx, JSValue setlike, int64_t *pout)
+{
+ JSMapState *s;
+ JSValue v;
+ double d;
+
+ s = JS_GetOpaque(setlike, JS_CLASS_SET);
+ if (s) {
+ *pout = s->record_count;
+ } else {
+ v = JS_GetProperty(ctx, setlike, JS_ATOM_size);
+ if (JS_IsException(v))
+ return -1;
+ if (JS_IsUndefined(v)) {
+ JS_ThrowTypeError(ctx, ".size is undefined");
+ return -1;
+ }
+ if (JS_ToFloat64Free(ctx, &d, v) < 0)
+ return -1;
+ if (isnan(d)) {
+ JS_ThrowTypeError(ctx, ".size is not a number");
+ return -1;
+ }
+ *pout = d;
+ }
+ return 0;
+}
+
+static int js_setlike_get_has(JSContext *ctx, JSValue setlike, JSValue *pout)
+{
+ JSValue v;
+
+ v = JS_GetProperty(ctx, setlike, JS_ATOM_has);
+ if (JS_IsException(v))
+ return -1;
+ if (JS_IsUndefined(v)) {
+ JS_ThrowTypeError(ctx, ".has is undefined");
+ return -1;
+ }
+ if (!JS_IsFunction(ctx, v)) {
+ JS_ThrowTypeError(ctx, ".has is not a function");
+ JS_FreeValue(ctx, v);
+ return -1;
+ }
+ *pout = v;
+ return 0;
+}
+
+static int js_setlike_get_keys(JSContext *ctx, JSValue setlike, JSValue *pout)
+{
+ JSValue v;
+
+ v = JS_GetProperty(ctx, setlike, JS_ATOM_keys);
+ if (JS_IsException(v))
+ return -1;
+ if (JS_IsUndefined(v)) {
+ JS_ThrowTypeError(ctx, ".keys is undefined");
+ return -1;
+ }
+ if (!JS_IsFunction(ctx, v)) {
+ JS_ThrowTypeError(ctx, ".keys is not a function");
+ JS_FreeValue(ctx, v);
+ return -1;
+ }
+ *pout = v;
+ return 0;
+}
+
+static JSValue js_set_isDisjointFrom(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue item, iter, keys, has, next, rv, rval;
+ int done;
+ bool found;
+ JSMapState *s;
+ int64_t size;
+ int ok;
+
+ has = JS_UNDEFINED;
+ iter = JS_UNDEFINED;
+ keys = JS_UNDEFINED;
+ next = JS_UNDEFINED;
+ rval = JS_EXCEPTION;
+ s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET);
+ if (!s)
+ goto exception;
+ // order matters!
+ if (js_setlike_get_size(ctx, argv[0], &size) < 0)
+ goto exception;
+ if (js_setlike_get_has(ctx, argv[0], &has) < 0)
+ goto exception;
+ if (js_setlike_get_keys(ctx, argv[0], &keys) < 0)
+ goto exception;
+ if (s->record_count > size) {
+ iter = JS_Call(ctx, keys, argv[0], 0, NULL);
+ if (JS_IsException(iter))
+ goto exception;
+ next = JS_GetProperty(ctx, iter, JS_ATOM_next);
+ if (JS_IsException(next))
+ goto exception;
+ found = false;
+ do {
+ item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto exception;
+ if (done) // item is JS_UNDEFINED
+ break;
+ item = map_normalize_key(ctx, item);
+ found = (NULL != map_find_record(ctx, s, item));
+ JS_FreeValue(ctx, item);
+ } while (!found);
+ } else {
+ iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET);
+ if (JS_IsException(iter))
+ goto exception;
+ found = false;
+ do {
+ item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET);
+ if (JS_IsException(item))
+ goto exception;
+ if (done) // item is JS_UNDEFINED
+ break;
+ rv = JS_Call(ctx, has, argv[0], 1, &item);
+ JS_FreeValue(ctx, item);
+ ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION
+ if (ok < 0)
+ goto exception;
+ found = (ok > 0);
+ } while (!found);
+ }
+ rval = !found ? JS_TRUE : JS_FALSE;
+exception:
+ JS_FreeValue(ctx, has);
+ JS_FreeValue(ctx, keys);
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return rval;
+}
+
+static JSValue js_set_isSubsetOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue item, iter, keys, has, next, rv, rval;
+ bool found;
+ JSMapState *s;
+ int64_t size;
+ int done, ok;
+
+ has = JS_UNDEFINED;
+ iter = JS_UNDEFINED;
+ keys = JS_UNDEFINED;
+ next = JS_UNDEFINED;
+ rval = JS_EXCEPTION;
+ s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET);
+ if (!s)
+ goto exception;
+ // order matters!
+ if (js_setlike_get_size(ctx, argv[0], &size) < 0)
+ goto exception;
+ if (js_setlike_get_has(ctx, argv[0], &has) < 0)
+ goto exception;
+ if (js_setlike_get_keys(ctx, argv[0], &keys) < 0)
+ goto exception;
+ found = false;
+ if (s->record_count > size)
+ goto fini;
+ iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET);
+ if (JS_IsException(iter))
+ goto exception;
+ found = true;
+ do {
+ item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET);
+ if (JS_IsException(item))
+ goto exception;
+ if (done) // item is JS_UNDEFINED
+ break;
+ rv = JS_Call(ctx, has, argv[0], 1, &item);
+ JS_FreeValue(ctx, item);
+ ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION
+ if (ok < 0)
+ goto exception;
+ found = (ok > 0);
+ } while (found);
+fini:
+ rval = found ? JS_TRUE : JS_FALSE;
+exception:
+ JS_FreeValue(ctx, has);
+ JS_FreeValue(ctx, keys);
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return rval;
+}
+
+static JSValue js_set_isSupersetOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue item, iter, keys, has, next, rval;
+ int done;
+ bool found;
+ JSMapState *s;
+ int64_t size;
+
+ has = JS_UNDEFINED;
+ iter = JS_UNDEFINED;
+ keys = JS_UNDEFINED;
+ next = JS_UNDEFINED;
+ rval = JS_EXCEPTION;
+ s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET);
+ if (!s)
+ goto exception;
+ // order matters!
+ if (js_setlike_get_size(ctx, argv[0], &size) < 0)
+ goto exception;
+ if (js_setlike_get_has(ctx, argv[0], &has) < 0)
+ goto exception;
+ if (js_setlike_get_keys(ctx, argv[0], &keys) < 0)
+ goto exception;
+ found = false;
+ if (s->record_count < size)
+ goto fini;
+ iter = JS_Call(ctx, keys, argv[0], 0, NULL);
+ if (JS_IsException(iter))
+ goto exception;
+ next = JS_GetProperty(ctx, iter, JS_ATOM_next);
+ if (JS_IsException(next))
+ goto exception;
+ found = true;
+ do {
+ item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto exception;
+ if (done) // item is JS_UNDEFINED
+ break;
+ item = map_normalize_key(ctx, item);
+ found = (NULL != map_find_record(ctx, s, item));
+ JS_FreeValue(ctx, item);
+ } while (found);
+fini:
+ rval = found ? JS_TRUE : JS_FALSE;
+exception:
+ JS_FreeValue(ctx, has);
+ JS_FreeValue(ctx, keys);
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return rval;
+}
+
+static JSValue js_set_intersection(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue newset, item, iter, keys, has, next, rv;
+ JSMapState *s, *t;
+ JSMapRecord *mr;
+ int64_t size;
+ int done, ok;
+
+ has = JS_UNDEFINED;
+ iter = JS_UNDEFINED;
+ keys = JS_UNDEFINED;
+ next = JS_UNDEFINED;
+ newset = JS_UNDEFINED;
+ s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET);
+ if (!s)
+ goto exception;
+ // order matters!
+ if (js_setlike_get_size(ctx, argv[0], &size) < 0)
+ goto exception;
+ if (js_setlike_get_has(ctx, argv[0], &has) < 0)
+ goto exception;
+ if (js_setlike_get_keys(ctx, argv[0], &keys) < 0)
+ goto exception;
+ if (s->record_count > size) {
+ iter = JS_Call(ctx, keys, argv[0], 0, NULL);
+ if (JS_IsException(iter))
+ goto exception;
+ next = JS_GetProperty(ctx, iter, JS_ATOM_next);
+ if (JS_IsException(next))
+ goto exception;
+ newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
+ if (JS_IsException(newset))
+ goto exception;
+ t = JS_GetOpaque(newset, JS_CLASS_SET);
+ for (;;) {
+ item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto exception;
+ if (done) // item is JS_UNDEFINED
+ break;
+ item = map_normalize_key(ctx, item);
+ if (!map_find_record(ctx, s, item)) {
+ JS_FreeValue(ctx, item);
+ } else if (map_find_record(ctx, t, item)) {
+ JS_FreeValue(ctx, item); // no duplicates
+ } else if ((mr = map_add_record(ctx, t, item))) {
+ mr->value = JS_UNDEFINED;
+ } else {
+ JS_FreeValue(ctx, item);
+ goto exception;
+ }
+ }
+ } else {
+ iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET);
+ if (JS_IsException(iter))
+ goto exception;
+ newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
+ if (JS_IsException(newset))
+ goto exception;
+ t = JS_GetOpaque(newset, JS_CLASS_SET);
+ for (;;) {
+ item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET);
+ if (JS_IsException(item))
+ goto exception;
+ if (done) // item is JS_UNDEFINED
+ break;
+ rv = JS_Call(ctx, has, argv[0], 1, &item);
+ ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION
+ if (ok > 0) {
+ item = map_normalize_key(ctx, item);
+ if (map_find_record(ctx, t, item)) {
+ JS_FreeValue(ctx, item); // no duplicates
+ } else if ((mr = map_add_record(ctx, t, item))) {
+ mr->value = JS_UNDEFINED;
+ } else {
+ JS_FreeValue(ctx, item);
+ goto exception;
+ }
+ } else {
+ JS_FreeValue(ctx, item);
+ if (ok < 0)
+ goto exception;
+ }
+ }
+ }
+ goto fini;
+exception:
+ JS_FreeValue(ctx, newset);
+ newset = JS_EXCEPTION;
+fini:
+ JS_FreeValue(ctx, has);
+ JS_FreeValue(ctx, keys);
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return newset;
+}
+
+static JSValue js_set_difference(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue newset, item, iter, keys, has, next, rv;
+ JSMapState *s, *t;
+ JSMapRecord *mr;
+ int64_t size;
+ int done;
+ int ok;
+
+ has = JS_UNDEFINED;
+ iter = JS_UNDEFINED;
+ keys = JS_UNDEFINED;
+ next = JS_UNDEFINED;
+ newset = JS_UNDEFINED;
+ s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET);
+ if (!s)
+ goto exception;
+ // order matters!
+ if (js_setlike_get_size(ctx, argv[0], &size) < 0)
+ goto exception;
+ if (js_setlike_get_has(ctx, argv[0], &has) < 0)
+ goto exception;
+ if (js_setlike_get_keys(ctx, argv[0], &keys) < 0)
+ goto exception;
+ if (s->record_count > size) {
+ iter = JS_Call(ctx, keys, argv[0], 0, NULL);
+ if (JS_IsException(iter))
+ goto exception;
+ next = JS_GetProperty(ctx, iter, JS_ATOM_next);
+ if (JS_IsException(next))
+ goto exception;
+ newset = js_map_constructor(ctx, JS_UNDEFINED, 1, &this_val, MAGIC_SET);
+ if (JS_IsException(newset))
+ goto exception;
+ t = JS_GetOpaque(newset, JS_CLASS_SET);
+ for (;;) {
+ item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto exception;
+ if (done) // item is JS_UNDEFINED
+ break;
+ item = map_normalize_key(ctx, item);
+ mr = map_find_record(ctx, t, item);
+ if (mr)
+ map_delete_record(ctx->rt, t, mr);
+ JS_FreeValue(ctx, item);
+ }
+ } else {
+ iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET);
+ if (JS_IsException(iter))
+ goto exception;
+ newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
+ if (JS_IsException(newset))
+ goto exception;
+ t = JS_GetOpaque(newset, JS_CLASS_SET);
+ for (;;) {
+ item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET);
+ if (JS_IsException(item))
+ goto exception;
+ if (done) // item is JS_UNDEFINED
+ break;
+ rv = JS_Call(ctx, has, argv[0], 1, &item);
+ ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION
+ if (ok == 0) {
+ item = map_normalize_key(ctx, item);
+ if (map_find_record(ctx, t, item)) {
+ JS_FreeValue(ctx, item); // no duplicates
+ } else if ((mr = map_add_record(ctx, t, item))) {
+ mr->value = JS_UNDEFINED;
+ } else {
+ JS_FreeValue(ctx, item);
+ goto exception;
+ }
+ } else {
+ JS_FreeValue(ctx, item);
+ if (ok < 0)
+ goto exception;
+ }
+ }
+ }
+ goto fini;
+exception:
+ JS_FreeValue(ctx, newset);
+ newset = JS_EXCEPTION;
+fini:
+ JS_FreeValue(ctx, has);
+ JS_FreeValue(ctx, keys);
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return newset;
+}
+
+static JSValue js_set_symmetricDifference(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue newset, item, iter, next, rv;
+ struct list_head *el;
+ JSMapState *s, *t;
+ JSMapRecord *mr;
+ int64_t size;
+ int done;
+ bool present;
+
+ s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET);
+ if (!s)
+ return JS_EXCEPTION;
+ // order matters! they're JS-observable side effects
+ if (js_setlike_get_size(ctx, argv[0], &size) < 0)
+ return JS_EXCEPTION;
+ if (js_setlike_get_has(ctx, argv[0], &rv) < 0)
+ return JS_EXCEPTION;
+ JS_FreeValue(ctx, rv);
+ newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
+ if (JS_IsException(newset))
+ return JS_EXCEPTION;
+ t = JS_GetOpaque(newset, JS_CLASS_SET);
+ iter = JS_UNDEFINED;
+ next = JS_UNDEFINED;
+ // can't clone this_val using js_map_constructor(),
+ // test262 mandates we don't call the .add method
+ list_for_each(el, &s->records) {
+ mr = list_entry(el, JSMapRecord, link);
+ if (mr->empty)
+ continue;
+ mr = map_add_record(ctx, t, js_dup(mr->key));
+ if (!mr)
+ goto exception;
+ mr->value = JS_UNDEFINED;
+ }
+ iter = JS_GetProperty(ctx, argv[0], JS_ATOM_keys);
+ if (JS_IsException(iter))
+ goto exception;
+ iter = JS_CallFree(ctx, iter, argv[0], 0, NULL);
+ if (JS_IsException(iter))
+ goto exception;
+ next = JS_GetProperty(ctx, iter, JS_ATOM_next);
+ if (JS_IsException(next))
+ goto exception;
+ for (;;) {
+ item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto exception;
+ if (done) // item is JS_UNDEFINED
+ break;
+ // note the subtlety here: due to mutating iterators, it's
+ // possible for keys to disappear during iteration; test262
+ // still expects us to maintain insertion order though, so
+ // we first check |this|, then |new|; |new| is a copy of |this|
+ // - if item exists in |this|, delete (if it exists) from |new|
+ // - if item misses in |this| and |new|, add to |new|
+ // - if item exists in |new| but misses in |this|, *don't* add it,
+ // mutating iterator erased it
+ item = map_normalize_key(ctx, item);
+ present = (NULL != map_find_record(ctx, s, item));
+ mr = map_find_record(ctx, t, item);
+ if (present) {
+ if (mr)
+ map_delete_record(ctx->rt, t, mr);
+ JS_FreeValue(ctx, item);
+ } else if (mr) {
+ JS_FreeValue(ctx, item);
+ } else {
+ mr = map_add_record(ctx, t, item);
+ if (!mr) {
+ JS_FreeValue(ctx, item);
+ goto exception;
+ }
+ mr->value = JS_UNDEFINED;
+ }
+ }
+ goto fini;
+exception:
+ JS_FreeValue(ctx, newset);
+ newset = JS_EXCEPTION;
+fini:
+ JS_FreeValue(ctx, next);
+ JS_FreeValue(ctx, iter);
+ return newset;
+}
+
+static JSValue js_set_union(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue newset, item, iter, next, rv;
+ struct list_head *el;
+ JSMapState *s, *t;
+ JSMapRecord *mr;
+ int64_t size;
+ int done;
+
+ s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET);
+ if (!s)
+ return JS_EXCEPTION;
+ // order matters! they're JS-observable side effects
+ if (js_setlike_get_size(ctx, argv[0], &size) < 0)
+ return JS_EXCEPTION;
+ if (js_setlike_get_has(ctx, argv[0], &rv) < 0)
+ return JS_EXCEPTION;
+ JS_FreeValue(ctx, rv);
+ newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
+ if (JS_IsException(newset))
+ return JS_EXCEPTION;
+ t = JS_GetOpaque(newset, JS_CLASS_SET);
+ iter = JS_UNDEFINED;
+ next = JS_UNDEFINED;
+ list_for_each(el, &s->records) {
+ mr = list_entry(el, JSMapRecord, link);
+ if (mr->empty)
+ continue;
+ mr = map_add_record(ctx, t, js_dup(mr->key));
+ if (!mr)
+ goto exception;
+ mr->value = JS_UNDEFINED;
+ }
+ iter = JS_GetProperty(ctx, argv[0], JS_ATOM_keys);
+ if (JS_IsException(iter))
+ goto exception;
+ iter = JS_CallFree(ctx, iter, argv[0], 0, NULL);
+ if (JS_IsException(iter))
+ goto exception;
+ next = JS_GetProperty(ctx, iter, JS_ATOM_next);
+ if (JS_IsException(next))
+ goto exception;
+ for (;;) {
+ item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
+ if (JS_IsException(item))
+ goto exception;
+ if (done) // item is JS_UNDEFINED
+ break;
+ rv = js_map_set(ctx, newset, 1, &item, MAGIC_SET);
+ JS_FreeValue(ctx, item);
+ if (JS_IsException(rv))
+ goto exception;
+ JS_FreeValue(ctx, rv);
+ }
+ goto fini;
+exception:
+ JS_FreeValue(ctx, newset);
+ newset = JS_EXCEPTION;
+fini:
+ JS_FreeValue(ctx, next);
+ JS_FreeValue(ctx, iter);
+ return newset;
+}
+
static const JSCFunctionListEntry js_map_funcs[] = {
- JS_CFUNC_MAGIC_DEF("groupBy", 2, js_object_groupBy, 1 ),
+ JS_CFUNC_DEF("groupBy", 2, js_map_groupBy ),
+ JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
+};
+
+static const JSCFunctionListEntry js_set_funcs[] = {
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
};
@@ -47899,6 +48355,13 @@ static const JSCFunctionListEntry js_set_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("clear", 0, js_map_clear, MAGIC_SET ),
JS_CGETSET_MAGIC_DEF("size", js_map_get_size, NULL, MAGIC_SET ),
JS_CFUNC_MAGIC_DEF("forEach", 1, js_map_forEach, MAGIC_SET ),
+ JS_CFUNC_DEF("isDisjointFrom", 1, js_set_isDisjointFrom ),
+ JS_CFUNC_DEF("isSubsetOf", 1, js_set_isSubsetOf ),
+ JS_CFUNC_DEF("isSupersetOf", 1, js_set_isSupersetOf ),
+ JS_CFUNC_DEF("intersection", 1, js_set_intersection ),
+ JS_CFUNC_DEF("difference", 1, js_set_difference ),
+ JS_CFUNC_DEF("symmetricDifference", 1, js_set_symmetricDifference ),
+ JS_CFUNC_DEF("union", 1, js_set_union ),
JS_CFUNC_MAGIC_DEF("values", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY << 2) | MAGIC_SET ),
JS_ALIAS_DEF("keys", "values" ),
JS_ALIAS_DEF("[Symbol.iterator]", "values" ),
@@ -47953,22 +48416,24 @@ void JS_AddIntrinsicMapSet(JSContext *ctx)
for(i = 0; i < 4; i++) {
const char *name = JS_AtomGetStr(ctx, buf, sizeof(buf),
JS_ATOM_Map + i);
- ctx->class_proto[JS_CLASS_MAP + i] = JS_NewObject(ctx);
- JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_MAP + i],
+ int class_id = JS_CLASS_MAP + i;
+ ctx->class_proto[class_id] = JS_NewObject(ctx);
+ JS_SetPropertyFunctionList(ctx, ctx->class_proto[class_id],
js_map_proto_funcs_ptr[i],
js_map_proto_funcs_count[i]);
obj1 = JS_NewCFunctionMagic(ctx, js_map_constructor, name, 0,
JS_CFUNC_constructor_magic, i);
- if (i < 2) {
- JS_SetPropertyFunctionList(ctx, obj1, js_map_funcs,
- countof(js_map_funcs));
- }
- JS_NewGlobalCConstructor2(ctx, obj1, name, ctx->class_proto[JS_CLASS_MAP + i]);
+ if (class_id == JS_CLASS_MAP)
+ JS_SetPropertyFunctionList(ctx, obj1, js_map_funcs, countof(js_map_funcs));
+ else if (class_id == JS_CLASS_SET)
+ JS_SetPropertyFunctionList(ctx, obj1, js_set_funcs, countof(js_set_funcs));
+
+ JS_NewGlobalCConstructor2(ctx, obj1, name, ctx->class_proto[class_id]);
}
for(i = 0; i < 2; i++) {
ctx->class_proto[JS_CLASS_MAP_ITERATOR + i] =
- JS_NewObjectProto(ctx, ctx->iterator_proto);
+ JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_MAP_ITERATOR + i],
js_map_proto_funcs_ptr[i + 4],
js_map_proto_funcs_count[i + 4]);
@@ -47993,13 +48458,13 @@ typedef struct JSPromiseData {
JSPromiseStateEnum promise_state;
/* 0=fulfill, 1=reject, list of JSPromiseReactionData.link */
struct list_head promise_reactions[2];
- BOOL is_handled; /* Note: only useful to debug */
+ bool is_handled; /* Note: only useful to debug */
JSValue promise_result;
} JSPromiseData;
typedef struct JSPromiseFunctionDataResolved {
int ref_count;
- BOOL already_resolved;
+ bool already_resolved;
} JSPromiseFunctionDataResolved;
typedef struct JSPromiseFunctionData {
@@ -48013,7 +48478,7 @@ typedef struct JSPromiseReactionData {
JSValue handler;
} JSPromiseReactionData;
-JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise)
+ JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise)
{
JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);
if (!s)
@@ -48029,8 +48494,15 @@ JSValue JS_PromiseResult(JSContext *ctx, JSValue promise)
return JS_DupValue(ctx, s->promise_result);
}
+bool JS_IsPromise(JSValue val)
+{
+ if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
+ return false;
+ return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_PROMISE;
+}
+
static int js_create_resolving_functions(JSContext *ctx, JSValue *args,
- JSValueConst promise);
+ JSValue promise);
static void promise_reaction_data_free(JSRuntime *rt,
JSPromiseReactionData *rd)
@@ -48041,40 +48513,52 @@ static void promise_reaction_data_free(JSRuntime *rt,
js_free_rt(rt, rd);
}
+#ifdef ENABLE_DUMPS // JS_DUMP_PROMISE
+#define promise_trace(ctx, ...) \
+ do { \
+ if (check_dump_flag(ctx->rt, JS_DUMP_PROMISE)) \
+ printf(__VA_ARGS__); \
+ } while (0)
+#else
+#define promise_trace(...)
+#endif
+
static JSValue promise_reaction_job(JSContext *ctx, int argc,
- JSValueConst *argv)
+ JSValue *argv)
{
- JSValueConst handler, arg, func;
+ JSValue handler, arg, func;
JSValue res, res2;
- BOOL is_reject;
+ bool is_reject;
assert(argc == 5);
handler = argv[2];
is_reject = JS_ToBool(ctx, argv[3]);
arg = argv[4];
-#ifdef DUMP_PROMISE
- printf("promise_reaction_job: is_reject=%d\n", is_reject);
-#endif
+
+ promise_trace(ctx, "promise_reaction_job: is_reject=%d\n", is_reject);
if (JS_IsUndefined(handler)) {
if (is_reject) {
- res = JS_Throw(ctx, JS_DupValue(ctx, arg));
+ res = JS_Throw(ctx, js_dup(arg));
} else {
- res = JS_DupValue(ctx, arg);
+ res = js_dup(arg);
}
} else {
res = JS_Call(ctx, handler, JS_UNDEFINED, 1, &arg);
}
is_reject = JS_IsException(res);
- if (is_reject)
+ if (is_reject) {
+ if (unlikely(JS_IsUncatchableError(ctx, ctx->rt->current_exception)))
+ return JS_EXCEPTION;
res = JS_GetException(ctx);
+ }
func = argv[is_reject];
/* as an extension, we support undefined as value to avoid
creating a dummy promise in the 'await' implementation of async
functions */
if (!JS_IsUndefined(func)) {
res2 = JS_Call(ctx, func, JS_UNDEFINED,
- 1, (JSValueConst *)&res);
+ 1, &res);
} else {
res2 = JS_UNDEFINED;
}
@@ -48091,25 +48575,25 @@ void JS_SetHostPromiseRejectionTracker(JSRuntime *rt,
rt->host_promise_rejection_tracker_opaque = opaque;
}
-static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise,
- JSValueConst value, BOOL is_reject)
+static void fulfill_or_reject_promise(JSContext *ctx, JSValue promise,
+ JSValue value, bool is_reject)
{
JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);
struct list_head *el, *el1;
JSPromiseReactionData *rd;
- JSValueConst args[5];
+ JSValue args[5];
if (!s || s->promise_state != JS_PROMISE_PENDING)
return; /* should never happen */
- set_value(ctx, &s->promise_result, JS_DupValue(ctx, value));
+ set_value(ctx, &s->promise_result, js_dup(value));
s->promise_state = JS_PROMISE_FULFILLED + is_reject;
-#ifdef DUMP_PROMISE
- printf("fulfill_or_reject_promise: is_reject=%d\n", is_reject);
-#endif
+
+ promise_trace(ctx, "fulfill_or_reject_promise: is_reject=%d\n", is_reject);
+
if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) {
JSRuntime *rt = ctx->rt;
if (rt->host_promise_rejection_tracker) {
- rt->host_promise_rejection_tracker(ctx, promise, value, FALSE,
+ rt->host_promise_rejection_tracker(ctx, promise, value, false,
rt->host_promise_rejection_tracker_opaque);
}
}
@@ -48119,7 +48603,7 @@ static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise,
args[0] = rd->resolving_funcs[0];
args[1] = rd->resolving_funcs[1];
args[2] = rd->handler;
- args[3] = JS_NewBool(ctx, is_reject);
+ args[3] = js_bool(is_reject);
args[4] = value;
JS_EnqueueJob(ctx, promise_reaction_job, 5, args);
list_del(&rd->link);
@@ -48133,31 +48617,30 @@ static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise,
}
}
-static void reject_promise(JSContext *ctx, JSValueConst promise,
- JSValueConst value)
+static void reject_promise(JSContext *ctx, JSValue promise,
+ JSValue value)
{
- fulfill_or_reject_promise(ctx, promise, value, TRUE);
+ fulfill_or_reject_promise(ctx, promise, value, true);
}
static JSValue js_promise_resolve_thenable_job(JSContext *ctx,
- int argc, JSValueConst *argv)
+ int argc, JSValue *argv)
{
- JSValueConst promise, thenable, then;
+ JSValue promise, thenable, then;
JSValue args[2], res;
-#ifdef DUMP_PROMISE
- printf("js_promise_resolve_thenable_job\n");
-#endif
+ promise_trace(ctx, "js_promise_resolve_thenable_job\n");
+
assert(argc == 3);
promise = argv[0];
thenable = argv[1];
then = argv[2];
if (js_create_resolving_functions(ctx, args, promise) < 0)
return JS_EXCEPTION;
- res = JS_Call(ctx, then, thenable, 2, (JSValueConst *)args);
+ res = JS_Call(ctx, then, thenable, 2, args);
if (JS_IsException(res)) {
JSValue error = JS_GetException(ctx);
- res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);
+ res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error);
JS_FreeValue(ctx, error);
}
JS_FreeValue(ctx, args[0]);
@@ -48175,7 +48658,7 @@ static void js_promise_resolve_function_free_resolved(JSRuntime *rt,
static int js_create_resolving_functions(JSContext *ctx,
JSValue *resolving_funcs,
- JSValueConst promise)
+ JSValue promise)
{
JSValue obj;
@@ -48187,7 +48670,7 @@ static int js_create_resolving_functions(JSContext *ctx,
if (!sr)
return -1;
sr->ref_count = 1;
- sr->already_resolved = FALSE; /* must be shared between the two functions */
+ sr->already_resolved = false; /* must be shared between the two functions */
ret = 0;
for(i = 0; i < 2; i++) {
obj = JS_NewObjectProtoClass(ctx, ctx->function_proto,
@@ -48206,8 +48689,8 @@ static int js_create_resolving_functions(JSContext *ctx,
}
sr->ref_count++;
s->presolved = sr;
- s->promise = JS_DupValue(ctx, promise);
- JS_SetOpaque(obj, s);
+ s->promise = js_dup(promise);
+ JS_SetOpaqueInternal(obj, s);
js_function_set_properties(ctx, obj, JS_ATOM_empty_string, 1);
resolving_funcs[i] = obj;
}
@@ -48225,7 +48708,7 @@ static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValue val)
}
}
-static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val,
+static void js_promise_resolve_function_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSPromiseFunctionData *s = JS_VALUE_GET_OBJ(val)->u.promise_function_data;
@@ -48235,30 +48718,32 @@ static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val,
}
static JSValue js_promise_resolve_function_call(JSContext *ctx,
- JSValueConst func_obj,
- JSValueConst this_val,
- int argc, JSValueConst *argv,
+ JSValue func_obj,
+ JSValue this_val,
+ int argc, JSValue *argv,
int flags)
{
JSObject *p = JS_VALUE_GET_OBJ(func_obj);
JSPromiseFunctionData *s;
- JSValueConst resolution, args[3];
+ JSValue resolution, args[3];
JSValue then;
- BOOL is_reject;
+ bool is_reject;
s = p->u.promise_function_data;
if (!s || s->presolved->already_resolved)
return JS_UNDEFINED;
- s->presolved->already_resolved = TRUE;
+ s->presolved->already_resolved = true;
is_reject = p->class_id - JS_CLASS_PROMISE_RESOLVE_FUNCTION;
if (argc > 0)
resolution = argv[0];
else
resolution = JS_UNDEFINED;
-#ifdef DUMP_PROMISE
- printf("js_promise_resolving_function_call: is_reject=%d resolution=", is_reject);
- JS_DumpValue(ctx, resolution);
- printf("\n");
+#ifdef ENABLE_DUMPS // JS_DUMP_PROMISE
+ if (check_dump_flag(ctx->rt, JS_DUMP_PROMISE)) {
+ printf("js_promise_resolving_function_call: is_reject=%d resolution=", is_reject);
+ JS_DumpValue(ctx->rt, resolution);
+ printf("\n");
+ }
#endif
if (is_reject || !JS_IsObject(resolution)) {
goto done;
@@ -48306,7 +48791,7 @@ static void js_promise_finalizer(JSRuntime *rt, JSValue val)
js_free_rt(rt, s);
}
-static void js_promise_mark(JSRuntime *rt, JSValueConst val,
+static void js_promise_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSPromiseData *s = JS_GetOpaque(val, JS_CLASS_PROMISE);
@@ -48327,10 +48812,10 @@ static void js_promise_mark(JSRuntime *rt, JSValueConst val,
JS_MarkValue(rt, s->promise_result, mark_func);
}
-static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_promise_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
{
- JSValueConst executor;
+ JSValue executor;
JSValue obj;
JSPromiseData *s;
JSValue args[2], ret;
@@ -48346,18 +48831,18 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target,
if (!s)
goto fail;
s->promise_state = JS_PROMISE_PENDING;
- s->is_handled = FALSE;
+ s->is_handled = false;
for(i = 0; i < 2; i++)
init_list_head(&s->promise_reactions[i]);
s->promise_result = JS_UNDEFINED;
- JS_SetOpaque(obj, s);
+ JS_SetOpaqueInternal(obj, s);
if (js_create_resolving_functions(ctx, args, obj))
goto fail;
- ret = JS_Call(ctx, executor, JS_UNDEFINED, 2, (JSValueConst *)args);
+ ret = JS_Call(ctx, executor, JS_UNDEFINED, 2, args);
if (JS_IsException(ret)) {
JSValue ret2, error;
error = JS_GetException(ctx);
- ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);
+ ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error);
JS_FreeValue(ctx, error);
if (JS_IsException(ret2))
goto fail1;
@@ -48376,8 +48861,8 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target,
}
static JSValue js_promise_executor(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv,
+ JSValue this_val,
+ int argc, JSValue *argv,
int magic, JSValue *func_data)
{
int i;
@@ -48385,14 +48870,14 @@ static JSValue js_promise_executor(JSContext *ctx,
for(i = 0; i < 2; i++) {
if (!JS_IsUndefined(func_data[i]))
return JS_ThrowTypeError(ctx, "resolving function already set");
- func_data[i] = JS_DupValue(ctx, argv[i]);
+ func_data[i] = js_dup(argv[i]);
}
return JS_UNDEFINED;
}
static JSValue js_promise_executor_new(JSContext *ctx)
{
- JSValueConst func_data[2];
+ JSValue func_data[2];
func_data[0] = JS_UNDEFINED;
func_data[1] = JS_UNDEFINED;
@@ -48402,7 +48887,7 @@ static JSValue js_promise_executor_new(JSContext *ctx)
static JSValue js_new_promise_capability(JSContext *ctx,
JSValue *resolving_funcs,
- JSValueConst ctor)
+ JSValue ctor)
{
JSValue executor, result_promise;
JSCFunctionDataRecord *s;
@@ -48414,10 +48899,10 @@ static JSValue js_new_promise_capability(JSContext *ctx,
if (JS_IsUndefined(ctor)) {
result_promise = js_promise_constructor(ctx, ctor, 1,
- (JSValueConst *)&executor);
+ &executor);
} else {
result_promise = JS_CallConstructor(ctx, ctor, 1,
- (JSValueConst *)&executor);
+ &executor);
}
if (JS_IsException(result_promise))
goto fail;
@@ -48427,7 +48912,7 @@ static JSValue js_new_promise_capability(JSContext *ctx,
goto fail;
}
for(i = 0; i < 2; i++)
- resolving_funcs[i] = JS_DupValue(ctx, s->data[i]);
+ resolving_funcs[i] = js_dup(s->data[i]);
JS_FreeValue(ctx, executor);
return result_promise;
fail:
@@ -48441,24 +48926,24 @@ JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs)
return js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED);
}
-static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_promise_resolve(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSValue result_promise, resolving_funcs[2], ret;
- BOOL is_reject = magic;
+ bool is_reject = magic;
if (!JS_IsObject(this_val))
return JS_ThrowTypeErrorNotAnObject(ctx);
if (!is_reject && JS_GetOpaque(argv[0], JS_CLASS_PROMISE)) {
JSValue ctor;
- BOOL is_same;
+ bool is_same;
ctor = JS_GetProperty(ctx, argv[0], JS_ATOM_constructor);
if (JS_IsException(ctor))
return ctor;
is_same = js_same_value(ctx, ctor, this_val);
JS_FreeValue(ctx, ctor);
if (is_same)
- return JS_DupValue(ctx, argv[0]);
+ return js_dup(argv[0]);
}
result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);
if (JS_IsException(result_promise))
@@ -48474,16 +48959,15 @@ static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val,
return result_promise;
}
-static JSValue js_promise_withResolvers(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_promise_withResolvers(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue result_promise, resolving_funcs[2], obj;
if (!JS_IsObject(this_val))
return JS_ThrowTypeErrorNotAnObject(ctx);
result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);
if (JS_IsException(result_promise))
- return result_promise;
+ return JS_EXCEPTION;
obj = JS_NewObject(ctx);
if (JS_IsException(obj)) {
JS_FreeValue(ctx, resolving_funcs[0]);
@@ -48497,8 +48981,36 @@ static JSValue js_promise_withResolvers(JSContext *ctx,
return obj;
}
+static JSValue js_promise_try(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
+{
+ JSValue result_promise, resolving_funcs[2], ret, ret2;
+ bool is_reject = 0;
+
+ if (!JS_IsObject(this_val))
+ return JS_ThrowTypeErrorNotAnObject(ctx);
+ result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);
+ if (JS_IsException(result_promise))
+ return result_promise;
+ ret = JS_Call(ctx, argv[0], JS_UNDEFINED, argc - 1, argv + 1);
+ if (JS_IsException(ret)) {
+ is_reject = 1;
+ ret = JS_GetException(ctx);
+ }
+ ret2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, 1, &ret);
+ JS_FreeValue(ctx, resolving_funcs[0]);
+ JS_FreeValue(ctx, resolving_funcs[1]);
+ JS_FreeValue(ctx, ret);
+ if (JS_IsException(ret2)) {
+ JS_FreeValue(ctx, result_promise);
+ return ret2;
+ }
+ JS_FreeValue(ctx, ret2);
+ return result_promise;
+}
+
static __exception int remainingElementsCount_add(JSContext *ctx,
- JSValueConst resolve_element_env,
+ JSValue resolve_element_env,
int addend)
{
JSValue val;
@@ -48511,7 +49023,7 @@ static __exception int remainingElementsCount_add(JSContext *ctx,
return -1;
remainingElementsCount += addend;
if (JS_SetPropertyUint32(ctx, resolve_element_env, 0,
- JS_NewInt32(ctx, remainingElementsCount)) < 0)
+ js_int32(remainingElementsCount)) < 0)
return -1;
return (remainingElementsCount == 0);
}
@@ -48521,17 +49033,17 @@ static __exception int remainingElementsCount_add(JSContext *ctx,
#define PROMISE_MAGIC_any 2
static JSValue js_promise_all_resolve_element(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv,
+ JSValue this_val,
+ int argc, JSValue *argv,
int magic,
JSValue *func_data)
{
int resolve_type = magic & 3;
int is_reject = magic & 4;
- BOOL alreadyCalled = JS_ToBool(ctx, func_data[0]);
- JSValueConst values = func_data[2];
- JSValueConst resolve = func_data[3];
- JSValueConst resolve_element_env = func_data[4];
+ bool alreadyCalled = JS_ToBool(ctx, func_data[0]);
+ JSValue values = func_data[2];
+ JSValue resolve = func_data[3];
+ JSValue resolve_element_env = func_data[4];
JSValue ret, obj;
int is_zero, index;
@@ -48539,7 +49051,7 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
return JS_EXCEPTION;
if (alreadyCalled)
return JS_UNDEFINED;
- func_data[0] = JS_NewBool(ctx, TRUE);
+ func_data[0] = JS_TRUE;
if (resolve_type == PROMISE_MAGIC_allSettled) {
JSValue str;
@@ -48547,7 +49059,7 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
obj = JS_NewObject(ctx);
if (JS_IsException(obj))
return JS_EXCEPTION;
- str = JS_NewString(ctx, is_reject ? "rejected" : "fulfilled");
+ str = js_new_string8(ctx, is_reject ? "rejected" : "fulfilled");
if (JS_IsException(str))
goto fail1;
if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_status,
@@ -48556,14 +49068,14 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
goto fail1;
if (JS_DefinePropertyValue(ctx, obj,
is_reject ? JS_ATOM_reason : JS_ATOM_value,
- JS_DupValue(ctx, argv[0]),
+ js_dup(argv[0]),
JS_PROP_C_W_E) < 0) {
fail1:
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
} else {
- obj = JS_DupValue(ctx, argv[0]);
+ obj = js_dup(argv[0]);
}
if (JS_DefinePropertyValueUint32(ctx, values, index,
obj, JS_PROP_C_W_E) < 0)
@@ -48578,10 +49090,10 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
error = js_aggregate_error_constructor(ctx, values);
if (JS_IsException(error))
return JS_EXCEPTION;
- ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&error);
+ ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &error);
JS_FreeValue(ctx, error);
} else {
- ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values);
+ ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &values);
}
if (JS_IsException(ret))
return ret;
@@ -48591,16 +49103,15 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
}
/* magic = 0: Promise.all 1: Promise.allSettled */
-static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_promise_all(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
JSValue result_promise, resolving_funcs[2], item, next_promise, ret;
JSValue next_method = JS_UNDEFINED, values = JS_UNDEFINED;
JSValue resolve_element_env = JS_UNDEFINED, resolve_element, reject_element;
JSValue promise_resolve = JS_UNDEFINED, iter = JS_UNDEFINED;
- JSValueConst then_args[2], resolve_element_data[5];
- BOOL done;
- int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any);
+ JSValue then_args[2], resolve_element_data[5];
+ int done, index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any);
if (!JS_IsObject(this_val))
return JS_ThrowTypeErrorNotAnObject(ctx);
@@ -48611,13 +49122,13 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(promise_resolve) ||
check_function(ctx, promise_resolve))
goto fail_reject;
- iter = JS_GetIterator(ctx, argv[0], FALSE);
+ iter = JS_GetIterator(ctx, argv[0], false);
if (JS_IsException(iter)) {
JSValue error;
fail_reject:
error = JS_GetException(ctx);
ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,
- (JSValueConst *)&error);
+ &error);
JS_FreeValue(ctx, error);
if (JS_IsException(ret))
goto fail;
@@ -48634,7 +49145,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
goto fail_reject;
/* remainingElementsCount field */
if (JS_DefinePropertyValueUint32(ctx, resolve_element_env, 0,
- JS_NewInt32(ctx, 1),
+ js_int32(1),
JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)
goto fail_reject;
@@ -48648,15 +49159,15 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
if (done)
break;
next_promise = JS_Call(ctx, promise_resolve,
- this_val, 1, (JSValueConst *)&item);
+ this_val, 1, &item);
JS_FreeValue(ctx, item);
if (JS_IsException(next_promise)) {
fail_reject1:
- JS_IteratorClose(ctx, iter, TRUE);
+ JS_IteratorClose(ctx, iter, true);
goto fail_reject;
}
- resolve_element_data[0] = JS_NewBool(ctx, FALSE);
- resolve_element_data[1] = JS_NewInt32(ctx, index);
+ resolve_element_data[0] = JS_FALSE;
+ resolve_element_data[1] = js_int32(index);
resolve_element_data[2] = values;
resolve_element_data[3] = resolving_funcs[is_promise_any];
resolve_element_data[4] = resolve_element_env;
@@ -48681,9 +49192,9 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
JS_UNDEFINED, JS_PROP_C_W_E) < 0)
goto fail_reject1;
reject_element = resolve_element;
- resolve_element = JS_DupValue(ctx, resolving_funcs[0]);
+ resolve_element = js_dup(resolving_funcs[0]);
} else {
- reject_element = JS_DupValue(ctx, resolving_funcs[1]);
+ reject_element = js_dup(resolving_funcs[1]);
}
if (remainingElementsCount_add(ctx, resolve_element_env, 1) < 0) {
@@ -48716,7 +49227,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
values = error;
}
ret = JS_Call(ctx, resolving_funcs[is_promise_any], JS_UNDEFINED,
- 1, (JSValueConst *)&values);
+ 1, &values);
if (check_exception_free(ctx, ret))
goto fail_reject;
}
@@ -48736,13 +49247,13 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
goto done;
}
-static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_promise_race(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue result_promise, resolving_funcs[2], item, next_promise, ret;
JSValue next_method = JS_UNDEFINED, iter = JS_UNDEFINED;
JSValue promise_resolve = JS_UNDEFINED;
- BOOL done;
+ int done;
if (!JS_IsObject(this_val))
return JS_ThrowTypeErrorNotAnObject(ctx);
@@ -48753,13 +49264,13 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(promise_resolve) ||
check_function(ctx, promise_resolve))
goto fail_reject;
- iter = JS_GetIterator(ctx, argv[0], FALSE);
+ iter = JS_GetIterator(ctx, argv[0], false);
if (JS_IsException(iter)) {
JSValue error;
fail_reject:
error = JS_GetException(ctx);
ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,
- (JSValueConst *)&error);
+ &error);
JS_FreeValue(ctx, error);
if (JS_IsException(ret))
goto fail;
@@ -48778,15 +49289,15 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
if (done)
break;
next_promise = JS_Call(ctx, promise_resolve,
- this_val, 1, (JSValueConst *)&item);
+ this_val, 1, &item);
JS_FreeValue(ctx, item);
if (JS_IsException(next_promise)) {
fail_reject1:
- JS_IteratorClose(ctx, iter, TRUE);
+ JS_IteratorClose(ctx, iter, true);
goto fail_reject;
}
ret = JS_InvokeFree(ctx, next_promise, JS_ATOM_then, 2,
- (JSValueConst *)resolving_funcs);
+ resolving_funcs);
if (check_exception_free(ctx, ret))
goto fail_reject1;
}
@@ -48806,9 +49317,9 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
}
static __exception int perform_promise_then(JSContext *ctx,
- JSValueConst promise,
- JSValueConst *resolve_reject,
- JSValueConst *cap_resolving_funcs)
+ JSValue promise,
+ JSValue *resolve_reject,
+ JSValue *cap_resolving_funcs)
{
JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);
JSPromiseReactionData *rd_array[2], *rd;
@@ -48817,7 +49328,7 @@ static __exception int perform_promise_then(JSContext *ctx,
rd_array[0] = NULL;
rd_array[1] = NULL;
for(i = 0; i < 2; i++) {
- JSValueConst handler;
+ JSValue handler;
rd = js_mallocz(ctx, sizeof(*rd));
if (!rd) {
if (i == 1)
@@ -48825,11 +49336,11 @@ static __exception int perform_promise_then(JSContext *ctx,
return -1;
}
for(j = 0; j < 2; j++)
- rd->resolving_funcs[j] = JS_DupValue(ctx, cap_resolving_funcs[j]);
+ rd->resolving_funcs[j] = js_dup(cap_resolving_funcs[j]);
handler = resolve_reject[i];
if (!JS_IsFunction(ctx, handler))
handler = JS_UNDEFINED;
- rd->handler = JS_DupValue(ctx, handler);
+ rd->handler = js_dup(handler);
rd_array[i] = rd;
}
@@ -48837,12 +49348,12 @@ static __exception int perform_promise_then(JSContext *ctx,
for(i = 0; i < 2; i++)
list_add_tail(&rd_array[i]->link, &s->promise_reactions[i]);
} else {
- JSValueConst args[5];
+ JSValue args[5];
if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) {
JSRuntime *rt = ctx->rt;
if (rt->host_promise_rejection_tracker) {
rt->host_promise_rejection_tracker(ctx, promise, s->promise_result,
- TRUE, rt->host_promise_rejection_tracker_opaque);
+ true, rt->host_promise_rejection_tracker_opaque);
}
}
i = s->promise_state - JS_PROMISE_FULFILLED;
@@ -48850,18 +49361,18 @@ static __exception int perform_promise_then(JSContext *ctx,
args[0] = rd->resolving_funcs[0];
args[1] = rd->resolving_funcs[1];
args[2] = rd->handler;
- args[3] = JS_NewBool(ctx, i);
+ args[3] = js_bool(i);
args[4] = s->promise_result;
JS_EnqueueJob(ctx, promise_reaction_job, 5, args);
for(i = 0; i < 2; i++)
promise_reaction_data_free(ctx->rt, rd_array[i]);
}
- s->is_handled = TRUE;
+ s->is_handled = true;
return 0;
}
-static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_promise_then(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue ctor, result_promise, resolving_funcs[2];
JSPromiseData *s;
@@ -48879,7 +49390,7 @@ static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(result_promise))
return result_promise;
ret = perform_promise_then(ctx, this_val, argv,
- (JSValueConst *)resolving_funcs);
+ resolving_funcs);
for(i = 0; i < 2; i++)
JS_FreeValue(ctx, resolving_funcs[i]);
if (ret) {
@@ -48889,41 +49400,41 @@ static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val,
return result_promise;
}
-static JSValue js_promise_catch(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_promise_catch(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst args[2];
+ JSValue args[2];
args[0] = JS_UNDEFINED;
args[1] = argv[0];
return JS_Invoke(ctx, this_val, JS_ATOM_then, 2, args);
}
-static JSValue js_promise_finally_value_thunk(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
+static JSValue js_promise_finally_value_thunk(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
int magic, JSValue *func_data)
{
- return JS_DupValue(ctx, func_data[0]);
+ return js_dup(func_data[0]);
}
-static JSValue js_promise_finally_thrower(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
+static JSValue js_promise_finally_thrower(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
int magic, JSValue *func_data)
{
- return JS_Throw(ctx, JS_DupValue(ctx, func_data[0]));
+ return JS_Throw(ctx, js_dup(func_data[0]));
}
-static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
+static JSValue js_promise_then_finally_func(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
int magic, JSValue *func_data)
{
- JSValueConst ctor = func_data[0];
- JSValueConst onFinally = func_data[1];
+ JSValue ctor = func_data[0];
+ JSValue onFinally = func_data[1];
JSValue res, promise, ret, then_func;
res = JS_Call(ctx, onFinally, JS_UNDEFINED, 0, NULL);
if (JS_IsException(res))
return res;
- promise = js_promise_resolve(ctx, ctor, 1, (JSValueConst *)&res, 0);
+ promise = js_promise_resolve(ctx, ctor, 1, &res, 0);
JS_FreeValue(ctx, res);
if (JS_IsException(promise))
return promise;
@@ -48938,26 +49449,26 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
JS_FreeValue(ctx, promise);
return then_func;
}
- ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, (JSValueConst *)&then_func);
+ ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, &then_func);
JS_FreeValue(ctx, then_func);
return ret;
}
-static JSValue js_promise_finally(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_promise_finally(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst onFinally = argv[0];
+ JSValue onFinally = argv[0];
JSValue ctor, ret;
JSValue then_funcs[2];
- JSValueConst func_data[2];
+ JSValue func_data[2];
int i;
ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED);
if (JS_IsException(ctor))
return ctor;
if (!JS_IsFunction(ctx, onFinally)) {
- then_funcs[0] = JS_DupValue(ctx, onFinally);
- then_funcs[1] = JS_DupValue(ctx, onFinally);
+ then_funcs[0] = js_dup(onFinally);
+ then_funcs[1] = js_dup(onFinally);
} else {
func_data[0] = ctor;
func_data[1] = onFinally;
@@ -48972,7 +49483,7 @@ static JSValue js_promise_finally(JSContext *ctx, JSValueConst this_val,
}
}
JS_FreeValue(ctx, ctor);
- ret = JS_Invoke(ctx, this_val, JS_ATOM_then, 2, (JSValueConst *)then_funcs);
+ ret = JS_Invoke(ctx, this_val, JS_ATOM_then, 2, then_funcs);
JS_FreeValue(ctx, then_funcs[0]);
JS_FreeValue(ctx, then_funcs[1]);
return ret;
@@ -48984,6 +49495,7 @@ static const JSCFunctionListEntry js_promise_funcs[] = {
JS_CFUNC_MAGIC_DEF("all", 1, js_promise_all, PROMISE_MAGIC_all ),
JS_CFUNC_MAGIC_DEF("allSettled", 1, js_promise_all, PROMISE_MAGIC_allSettled ),
JS_CFUNC_MAGIC_DEF("any", 1, js_promise_all, PROMISE_MAGIC_any ),
+ JS_CFUNC_DEF("try", 1, js_promise_try ),
JS_CFUNC_DEF("race", 1, js_promise_race ),
JS_CFUNC_DEF("withResolvers", 0, js_promise_withResolvers ),
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL),
@@ -49002,20 +49514,20 @@ static const JSCFunctionListEntry js_async_function_proto_funcs[] = {
};
static JSValue js_async_from_sync_iterator_unwrap(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv,
+ JSValue this_val,
+ int argc, JSValue *argv,
int magic, JSValue *func_data)
{
- return js_create_iterator_result(ctx, JS_DupValue(ctx, argv[0]),
+ return js_create_iterator_result(ctx, js_dup(argv[0]),
JS_ToBool(ctx, func_data[0]));
}
static JSValue js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx,
- BOOL done)
+ bool done)
{
- JSValueConst func_data[1];
+ JSValue func_data[1];
- func_data[0] = JS_NewBool(ctx, done);
+ func_data[0] = js_bool(done);
return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap,
1, 0, 1, func_data);
}
@@ -49044,7 +49556,7 @@ static void js_async_from_sync_iterator_finalizer(JSRuntime *rt, JSValue val)
}
}
-static void js_async_from_sync_iterator_mark(JSRuntime *rt, JSValueConst val,
+static void js_async_from_sync_iterator_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSAsyncFromSyncIteratorData *s =
@@ -49056,7 +49568,7 @@ static void js_async_from_sync_iterator_mark(JSRuntime *rt, JSValueConst val,
}
static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx,
- JSValueConst sync_iter)
+ JSValue sync_iter)
{
JSValue async_iter, next_method;
JSAsyncFromSyncIteratorData *s;
@@ -49075,14 +49587,14 @@ static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx,
JS_FreeValue(ctx, next_method);
return JS_EXCEPTION;
}
- s->sync_iter = JS_DupValue(ctx, sync_iter);
+ s->sync_iter = js_dup(sync_iter);
s->next_method = next_method;
- JS_SetOpaque(async_iter, s);
+ JS_SetOpaqueInternal(async_iter, s);
return async_iter;
}
-static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
+static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
int magic)
{
JSValue promise, resolving_funcs[2], value, err, method;
@@ -49100,7 +49612,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
}
if (magic == GEN_MAGIC_NEXT) {
- method = JS_DupValue(ctx, s->next_method);
+ method = js_dup(s->next_method);
} else {
method = JS_GetProperty(ctx, s->sync_iter,
magic == GEN_MAGIC_RETURN ? JS_ATOM_return :
@@ -49109,10 +49621,11 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
goto reject;
if (JS_IsUndefined(method) || JS_IsNull(method)) {
if (magic == GEN_MAGIC_RETURN) {
- err = js_create_iterator_result(ctx, JS_DupValue(ctx, argv[0]), TRUE);
+ err = js_create_iterator_result(ctx, js_dup(argv[0]), true);
is_reject = 0;
} else {
- err = JS_DupValue(ctx, argv[0]);
+ err = JS_MakeError(ctx, JS_TYPE_ERROR, "throw is not a method",
+ true);
is_reject = 1;
}
goto done_resolve;
@@ -49138,7 +49651,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
is_reject = 1;
done_resolve:
res2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED,
- 1, (JSValueConst *)&err);
+ 1, &err);
JS_FreeValue(ctx, err);
JS_FreeValue(ctx, res2);
JS_FreeValue(ctx, resolving_funcs[0]);
@@ -49150,7 +49663,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
int res;
value_wrapper_promise = js_promise_resolve(ctx, ctx->promise_ctor,
- 1, (JSValueConst *)&value, 0);
+ 1, &value, 0);
if (JS_IsException(value_wrapper_promise)) {
JS_FreeValue(ctx, value);
goto reject;
@@ -49166,8 +49679,8 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
resolve_reject[1] = JS_UNDEFINED;
res = perform_promise_then(ctx, value_wrapper_promise,
- (JSValueConst *)resolve_reject,
- (JSValueConst *)resolving_funcs);
+ resolve_reject,
+ resolving_funcs);
JS_FreeValue(ctx, resolve_reject[0]);
JS_FreeValue(ctx, value_wrapper_promise);
JS_FreeValue(ctx, resolving_funcs[0]);
@@ -49242,16 +49755,20 @@ void JS_AddIntrinsicPromise(JSContext *ctx)
countof(js_promise_proto_funcs));
obj1 = JS_NewCFunction2(ctx, js_promise_constructor, "Promise", 1,
JS_CFUNC_constructor, 0);
- ctx->promise_ctor = JS_DupValue(ctx, obj1);
+ ctx->promise_ctor = js_dup(obj1);
JS_SetPropertyFunctionList(ctx, obj1,
js_promise_funcs,
countof(js_promise_funcs));
JS_NewGlobalCConstructor2(ctx, obj1, "Promise",
ctx->class_proto[JS_CLASS_PROMISE]);
+ /* Used to squelch a -Wcast-function-type warning. */
+ JSCFunctionType ft;
+
/* AsyncFunction */
ctx->class_proto[JS_CLASS_ASYNC_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto);
- obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor,
+ ft.generic_magic = js_function_constructor;
+ obj1 = JS_NewCFunction3(ctx, ft.generic,
"AsyncFunction", 1,
JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC,
ctx->function_ctor);
@@ -49287,7 +49804,8 @@ void JS_AddIntrinsicPromise(JSContext *ctx)
/* AsyncGeneratorFunction */
ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION] =
JS_NewObjectProto(ctx, ctx->function_proto);
- obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor,
+ ft.generic_magic = js_function_constructor;
+ obj1 = JS_NewCFunction3(ctx, ft.generic,
"AsyncGeneratorFunction", 1,
JS_CFUNC_constructor_or_func_magic,
JS_FUNC_ASYNC_GENERATOR,
@@ -49320,7 +49838,7 @@ static int isURIReserved(int c) {
return c < 0x100 && memchr(";/?:@&=+$,#", c, sizeof(";/?:@&=+$,#") - 1) != NULL;
}
-static int FORMAT_ATTR(2, 3) js_throw_URIError(JSContext *ctx, const char *fmt, ...)
+static int JS_PRINTF_FORMAT_ATTR(2, 3) js_throw_URIError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...)
{
va_list ap;
@@ -49341,8 +49859,8 @@ static int hex_decode(JSContext *ctx, JSString *p, int k) {
return c;
}
-static JSValue js_global_decodeURI(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int isComponent)
+static JSValue js_global_decodeURI(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int isComponent)
{
JSValue str;
StringBuffer b_s, *b = &b_s;
@@ -49452,8 +49970,8 @@ static int encodeURI_hex(StringBuffer *b, int c) {
return string_buffer_write8(b, buf, n);
}
-static JSValue js_global_encodeURI(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv,
+static JSValue js_global_encodeURI(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv,
int isComponent)
{
JSValue str;
@@ -49517,8 +50035,8 @@ fail:
return JS_EXCEPTION;
}
-static JSValue js_global_escape(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_global_escape(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue str;
StringBuffer b_s, *b = &b_s;
@@ -49543,8 +50061,8 @@ static JSValue js_global_escape(JSContext *ctx, JSValueConst this_val,
return string_buffer_end(b);
}
-static JSValue js_global_unescape(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_global_unescape(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue str;
StringBuffer b_s, *b = &b_s;
@@ -49585,6 +50103,7 @@ static const JSCFunctionListEntry js_global_funcs[] = {
JS_CFUNC_DEF("parseFloat", 1, js_parseFloat ),
JS_CFUNC_DEF("isNaN", 1, js_global_isNaN ),
JS_CFUNC_DEF("isFinite", 1, js_global_isFinite ),
+ JS_CFUNC_DEF("queueMicrotask", 1, js_global_queueMicrotask ),
JS_CFUNC_MAGIC_DEF("decodeURI", 1, js_global_decodeURI, 0 ),
JS_CFUNC_MAGIC_DEF("decodeURIComponent", 1, js_global_decodeURI, 1 ),
@@ -49593,7 +50112,7 @@ static const JSCFunctionListEntry js_global_funcs[] = {
JS_CFUNC_DEF("escape", 1, js_global_escape ),
JS_CFUNC_DEF("unescape", 1, js_global_unescape ),
JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ),
- JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ),
+ JS_PROP_U2D_DEF("NaN", 0x7FF8ull<<48, 0 ), // workaround for msvc
JS_PROP_UNDEFINED_DEF("undefined", 0 ),
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ),
};
@@ -49606,16 +50125,16 @@ static int64_t math_mod(int64_t a, int64_t b) {
return m + (m < 0) * b;
}
-static int64_t floor_div(int64_t a, int64_t b) {
+static int64_t floor_div_int64(int64_t a, int64_t b) {
/* integer division rounding toward -Infinity */
int64_t m = a % b;
return (a - (m + (m < 0) * b)) / b;
}
-static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv);
+static JSValue js_Date_parse(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv);
-static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)
+static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValue this_val)
{
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(this_val);
@@ -49626,22 +50145,22 @@ static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueCon
return -1;
}
-static JSValue JS_SetThisTimeValue(JSContext *ctx, JSValueConst this_val, double v)
+static JSValue JS_SetThisTimeValue(JSContext *ctx, JSValue this_val, double v)
{
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(this_val);
if (p->class_id == JS_CLASS_DATE) {
JS_FreeValue(ctx, p->u.object_data);
- p->u.object_data = JS_NewFloat64(ctx, v);
- return JS_DupValue(ctx, p->u.object_data);
+ p->u.object_data = js_float64(v);
+ return js_dup(p->u.object_data);
}
}
return JS_ThrowTypeError(ctx, "not a Date object");
}
static int64_t days_from_year(int64_t y) {
- return 365 * (y - 1970) + floor_div(y - 1969, 4) -
- floor_div(y - 1901, 100) + floor_div(y - 1601, 400);
+ return 365 * (y - 1970) + floor_div_int64(y - 1969, 4) -
+ floor_div_int64(y - 1901, 100) + floor_div_int64(y - 1601, 400);
}
static int64_t days_in_year(int64_t y) {
@@ -49651,7 +50170,7 @@ static int64_t days_in_year(int64_t y) {
/* return the year, update days */
static int64_t year_from_days(int64_t *days) {
int64_t y, d1, nd, d = *days;
- y = floor_div(d * 10000, 3652425) + 1970;
+ y = floor_div_int64(d * 10000, 3652425) + 1970;
/* the initial approximation is very good, so only a few
iterations are necessary */
for(;;) {
@@ -49675,8 +50194,9 @@ static int const month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
static char const day_names[] = "SunMonTueWedThuFriSat";
-static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,
- double fields[minimum_length(9)], int is_local, int force)
+static __exception int get_date_fields(JSContext *ctx, JSValue obj,
+ double fields[minimum_length(9)],
+ int is_local, int force)
{
double dval;
int64_t d, days, wd, y, i, md, h, m, s, ms, tz = 0;
@@ -49686,7 +50206,7 @@ static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,
if (isnan(dval)) {
if (!force)
- return FALSE; /* NaN */
+ return false; /* NaN */
d = 0; /* initialize all fields to 0 */
} else {
d = dval; /* assuming -8.64e15 <= dval <= -8.64e15 */
@@ -49725,7 +50245,7 @@ static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,
fields[6] = ms;
fields[7] = wd;
fields[8] = tz;
- return TRUE;
+ return true;
}
static double time_clip(double t) {
@@ -49794,8 +50314,8 @@ static double set_date_fields(double fields[minimum_length(7)], int is_local) {
return time_clip(tv);
}
-static JSValue get_date_field(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue get_date_field(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
// get_date_field(obj, n, is_local)
double fields[9];
@@ -49812,11 +50332,11 @@ static JSValue get_date_field(JSContext *ctx, JSValueConst this_val,
if (magic & 0x100) { // getYear
fields[0] -= 1900;
}
- return JS_NewFloat64(ctx, fields[n]);
+ return js_number(fields[n]);
}
-static JSValue set_date_field(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue set_date_field(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
// _field(obj, first_field, end_field, args, is_local)
double fields[9];
@@ -49838,10 +50358,14 @@ static JSValue set_date_field(JSContext *ctx, JSValueConst this_val,
if (JS_ToFloat64(ctx, &a, argv[i]))
return JS_EXCEPTION;
if (!isfinite(a))
- res = FALSE;
+ res = false;
fields[first_field + i] = trunc(a);
}
- if (res && argc > 0)
+
+ if (!res)
+ return JS_NAN;
+
+ if (argc > 0)
d = set_date_fields(fields, is_local);
return JS_SetThisTimeValue(ctx, this_val, d);
@@ -49855,8 +50379,8 @@ static JSValue set_date_field(JSContext *ctx, JSValueConst this_val,
part: 1=date, 2=time 3=all
XXX: should use a variant of strftime().
*/
-static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue get_date_string(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
// _string(obj, fmt, part)
char buf[64];
@@ -49874,7 +50398,7 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,
if (fmt == 2)
return JS_ThrowRangeError(ctx, "Date value is NaN");
else
- return JS_NewString(ctx, "Invalid Date");
+ return js_new_string8(ctx, "Invalid Date");
}
y = fields[0];
@@ -49958,26 +50482,20 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,
break;
}
}
- return JS_NewStringLen(ctx, buf, pos);
+ if (!pos) {
+ // XXX: should throw exception?
+ return JS_AtomToString(ctx, JS_ATOM_empty_string);
+ }
+ return js_new_string8_len(ctx, buf, pos);
}
/* OS dependent: return the UTC time in ms since 1970. */
static int64_t date_now(void) {
-#ifdef _MSC_VER
- SYSTEMTIME st;
- GetSystemTime(&st);
- int64_t d;
- SystemTimeToFileTime(&st, (FILETIME *) &d);
- return (d - 116444736000000000ULL) / 10000;
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
-#endif
+ return js__gettimeofday_us() / 1000;
}
-static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_date_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
{
// Date(y, mon, d, h, m, s, ms)
JSValue rv;
@@ -50004,7 +50522,7 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
}
v = JS_ToPrimitive(ctx, argv[0], HINT_NONE);
if (JS_IsString(v)) {
- dv = js_Date_parse(ctx, JS_UNDEFINED, 1, (JSValueConst *)&v);
+ dv = js_Date_parse(ctx, JS_UNDEFINED, 1, &v);
JS_FreeValue(ctx, v);
if (JS_IsException(dv))
return JS_EXCEPTION;
@@ -50031,17 +50549,9 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
val = (i == n) ? set_date_fields(fields, 1) : NAN;
}
has_val:
-#if 0
- JSValueConst args[3];
- args[0] = new_target;
- args[1] = ctx->class_proto[JS_CLASS_DATE];
- args[2] = JS_NewFloat64(ctx, val);
- rv = js___date_create(ctx, JS_UNDEFINED, 3, args);
-#else
rv = js_create_from_ctor(ctx, new_target, JS_CLASS_DATE);
if (!JS_IsException(rv))
- JS_SetObjectData(ctx, rv, JS_NewFloat64(ctx, val));
-#endif
+ JS_SetObjectData(ctx, rv, js_float64(val));
if (!JS_IsException(rv) && JS_IsUndefined(new_target)) {
/* invoked as a function, return (new Date()).toString(); */
JSValue s;
@@ -50052,8 +50562,8 @@ has_val:
return rv;
}
-static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_Date_UTC(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// UTC(y, mon, d, h, m, s, ms)
double fields[] = { 0, 0, 1, 0, 0, 0, 0 };
@@ -50074,17 +50584,17 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val,
if (i == 0 && fields[0] >= 0 && fields[0] < 100)
fields[0] += 1900;
}
- return JS_NewFloat64(ctx, set_date_fields(fields, 0));
+ return js_float64(set_date_fields(fields, 0));
}
/* Date string parsing */
-static BOOL string_skip_char(const uint8_t *sp, int *pp, int c) {
+static bool string_skip_char(const uint8_t *sp, int *pp, int c) {
if (sp[*pp] == c) {
*pp += 1;
- return TRUE;
+ return true;
} else {
- return FALSE;
+ return false;
}
}
@@ -50113,7 +50623,7 @@ static int string_skip_until(const uint8_t *sp, int *pp, const char *stoplist) {
}
/* parse a numeric field (max_digits = 0 -> no maximum) */
-static BOOL string_get_digits(const uint8_t *sp, int *pp, int *pval,
+static bool string_get_digits(const uint8_t *sp, int *pp, int *pval,
int min_digits, int max_digits)
{
int v = 0;
@@ -50127,13 +50637,13 @@ static BOOL string_get_digits(const uint8_t *sp, int *pp, int *pval,
break;
}
if (p - p_start < min_digits)
- return FALSE;
+ return false;
*pval = v;
*pp = p;
- return TRUE;
+ return true;
}
-static BOOL string_get_milliseconds(const uint8_t *sp, int *pp, int *pval) {
+static bool string_get_milliseconds(const uint8_t *sp, int *pp, int *pval) {
/* parse optional fractional part as milliseconds and truncate. */
/* spec does not indicate which rounding should be used */
int mul = 100, ms = 0, c, p_start, p = *pp;
@@ -50155,24 +50665,20 @@ static BOOL string_get_milliseconds(const uint8_t *sp, int *pp, int *pval) {
*pp = p;
}
}
- return TRUE;
+ return true;
}
-static uint8_t upper_ascii(uint8_t c) {
- return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c;
-}
-
-static BOOL string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, BOOL strict) {
+static bool string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, bool strict) {
int tz = 0, sgn, hh, mm, p = *pp;
sgn = sp[p++];
if (sgn == '+' || sgn == '-') {
int n = p;
if (!string_get_digits(sp, &p, &hh, 1, 9))
- return FALSE;
+ return false;
n = p - n;
if (strict && n != 2 && n != 4)
- return FALSE;
+ return false;
while (n > 4) {
n -= 2;
hh /= 100;
@@ -50184,31 +50690,31 @@ static BOOL string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, BOOL stric
mm = 0;
if (string_skip_char(sp, &p, ':') /* optional separator */
&& !string_get_digits(sp, &p, &mm, 2, 2))
- return FALSE;
+ return false;
}
if (hh > 23 || mm > 59)
- return FALSE;
+ return false;
tz = hh * 60 + mm;
if (sgn != '+')
tz = -tz;
} else
if (sgn != 'Z') {
- return FALSE;
+ return false;
}
*pp = p;
*tzp = tz;
- return TRUE;
+ return true;
}
-static BOOL string_match(const uint8_t *sp, int *pp, const char *s) {
+static bool string_match(const uint8_t *sp, int *pp, const char *s) {
int p = *pp;
while (*s != '\0') {
- if (upper_ascii(sp[p]) != upper_ascii(*s++))
- return FALSE;
+ if (to_upper_ascii(sp[p]) != to_upper_ascii(*s++))
+ return false;
p++;
}
*pp = p;
- return TRUE;
+ return true;
}
static int find_abbrev(const uint8_t *sp, int p, const char *list, int count) {
@@ -50216,7 +50722,7 @@ static int find_abbrev(const uint8_t *sp, int p, const char *list, int count) {
for (n = 0; n < count; n++) {
for (i = 0;; i++) {
- if (upper_ascii(sp[p + i]) != upper_ascii(list[n * 3 + i]))
+ if (to_upper_ascii(sp[p + i]) != to_upper_ascii(list[n * 3 + i]))
break;
if (i == 2)
return n;
@@ -50225,75 +50731,75 @@ static int find_abbrev(const uint8_t *sp, int p, const char *list, int count) {
return -1;
}
-static BOOL string_get_month(const uint8_t *sp, int *pp, int *pval) {
+static bool string_get_month(const uint8_t *sp, int *pp, int *pval) {
int n;
n = find_abbrev(sp, *pp, month_names, 12);
if (n < 0)
- return FALSE;
+ return false;
*pval = n + 1;
*pp += 3;
- return TRUE;
+ return true;
}
/* parse toISOString format */
-static BOOL js_date_parse_isostring(const uint8_t *sp, int fields[9], BOOL *is_local) {
+static bool js_date_parse_isostring(const uint8_t *sp, int fields[9], bool *is_local) {
int sgn, i, p = 0;
/* initialize fields to the beginning of the Epoch */
for (i = 0; i < 9; i++) {
fields[i] = (i == 2);
}
- *is_local = FALSE;
+ *is_local = false;
/* year is either yyyy digits or [+-]yyyyyy */
sgn = sp[p];
if (sgn == '-' || sgn == '+') {
p++;
if (!string_get_digits(sp, &p, &fields[0], 6, 6))
- return FALSE;
+ return false;
if (sgn == '-') {
if (fields[0] == 0)
- return FALSE; // reject -000000
+ return false; // reject -000000
fields[0] = -fields[0];
}
} else {
if (!string_get_digits(sp, &p, &fields[0], 4, 4))
- return FALSE;
+ return false;
}
if (string_skip_char(sp, &p, '-')) {
if (!string_get_digits(sp, &p, &fields[1], 2, 2)) /* month */
- return FALSE;
+ return false;
if (fields[1] < 1)
- return FALSE;
+ return false;
fields[1] -= 1;
if (string_skip_char(sp, &p, '-')) {
if (!string_get_digits(sp, &p, &fields[2], 2, 2)) /* day */
- return FALSE;
+ return false;
if (fields[2] < 1)
- return FALSE;
+ return false;
}
}
if (string_skip_char(sp, &p, 'T')) {
- *is_local = TRUE;
+ *is_local = true;
if (!string_get_digits(sp, &p, &fields[3], 2, 2) /* hour */
|| !string_skip_char(sp, &p, ':')
|| !string_get_digits(sp, &p, &fields[4], 2, 2)) { /* minute */
fields[3] = 100; // reject unconditionally
- return TRUE;
+ return true;
}
if (string_skip_char(sp, &p, ':')) {
if (!string_get_digits(sp, &p, &fields[5], 2, 2)) /* second */
- return FALSE;
+ return false;
string_get_milliseconds(sp, &p, &fields[6]);
}
}
/* parse the time zone offset if present: [+-]HH:mm or [+-]HHmm */
if (sp[p]) {
- *is_local = FALSE;
- if (!string_get_tzoffset(sp, &p, &fields[8], TRUE))
- return FALSE;
+ *is_local = false;
+ if (!string_get_tzoffset(sp, &p, &fields[8], true))
+ return false;
}
/* error if extraneous characters */
return sp[p] == '\0';
@@ -50323,25 +50829,27 @@ static struct {
{ "EEST", +3 * 60 }, // Eastern European Summer Time
};
-static BOOL string_get_tzabbr(const uint8_t *sp, int *pp, int *offset) {
- for (size_t i = 0; i < countof(js_tzabbr); i++) {
+static bool string_get_tzabbr(const uint8_t *sp, int *pp, int *offset) {
+ size_t i;
+
+ for (i = 0; i < countof(js_tzabbr); i++) {
if (string_match(sp, pp, js_tzabbr[i].name)) {
*offset = js_tzabbr[i].offset;
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
/* parse toString, toUTCString and other formats */
-static BOOL js_date_parse_otherstring(const uint8_t *sp,
+static bool js_date_parse_otherstring(const uint8_t *sp,
int fields[minimum_length(9)],
- BOOL *is_local) {
+ bool *is_local) {
int c, i, val, p = 0, p_start;
int num[3];
- BOOL has_year = FALSE;
- BOOL has_mon = FALSE;
- BOOL has_time = FALSE;
+ bool has_year = false;
+ bool has_mon = false;
+ bool has_time = false;
int num_index = 0;
/* initialize fields to the beginning of 2001-01-01 */
@@ -50351,23 +50859,23 @@ static BOOL js_date_parse_otherstring(const uint8_t *sp,
for (i = 3; i < 9; i++) {
fields[i] = 0;
}
- *is_local = TRUE;
+ *is_local = true;
while (string_skip_spaces(sp, &p)) {
p_start = p;
if ((c = sp[p]) == '+' || c == '-') {
- if (has_time && string_get_tzoffset(sp, &p, &fields[8], FALSE)) {
- *is_local = FALSE;
+ if (has_time && string_get_tzoffset(sp, &p, &fields[8], false)) {
+ *is_local = false;
} else {
p++;
if (string_get_digits(sp, &p, &val, 1, 9)) {
if (c == '-') {
if (val == 0)
- return FALSE;
+ return false;
val = -val;
}
fields[0] = val;
- has_year = TRUE;
+ has_year = true;
}
}
} else
@@ -50376,44 +50884,52 @@ static BOOL js_date_parse_otherstring(const uint8_t *sp,
/* time part */
fields[3] = val;
if (!string_get_digits(sp, &p, &fields[4], 1, 2))
- return FALSE;
+ return false;
if (string_skip_char(sp, &p, ':')) {
if (!string_get_digits(sp, &p, &fields[5], 1, 2))
- return FALSE;
+ return false;
string_get_milliseconds(sp, &p, &fields[6]);
- }
- has_time = TRUE;
+ } else
+ if (sp[p] != '\0' && sp[p] != ' ')
+ return false;
+ has_time = true;
} else {
if (p - p_start > 2) {
fields[0] = val;
- has_year = TRUE;
+ has_year = true;
} else
if (val < 1 || val > 31) {
fields[0] = val + (val < 100) * 1900 + (val < 50) * 100;
- has_year = TRUE;
+ has_year = true;
} else {
if (num_index == 3)
- return FALSE;
+ return false;
num[num_index++] = val;
}
}
} else
if (string_get_month(sp, &p, &fields[1])) {
- has_mon = TRUE;
+ has_mon = true;
string_skip_until(sp, &p, "0123456789 -/(");
} else
if (has_time && string_match(sp, &p, "PM")) {
- if (fields[3] < 12)
+ /* hours greater than 12 will be incremented and
+ rejected by the range check in js_Date_parse */
+ /* 00:00 PM will be silently converted as 12:00 */
+ if (fields[3] != 12)
fields[3] += 12;
continue;
} else
if (has_time && string_match(sp, &p, "AM")) {
+ /* 00:00 AM will be silently accepted */
+ if (fields[3] > 12)
+ return false;
if (fields[3] == 12)
fields[3] -= 12;
continue;
} else
if (string_get_tzabbr(sp, &p, &fields[8])) {
- *is_local = FALSE;
+ *is_local = false;
continue;
} else
if (c == '(') { /* skip parenthesized phrase */
@@ -50426,25 +50942,25 @@ static BOOL js_date_parse_otherstring(const uint8_t *sp,
break;
}
if (level > 0)
- return FALSE;
+ return false;
} else
if (c == ')') {
- return FALSE;
+ return false;
} else {
if (has_year + has_mon + has_time + num_index)
- return FALSE;
+ return false;
/* skip a word */
string_skip_until(sp, &p, " -/(");
}
string_skip_separators(sp, &p);
}
if (num_index + has_year + has_mon > 3)
- return FALSE;
+ return false;
switch (num_index) {
case 0:
if (!has_year)
- return FALSE;
+ return false;
break;
case 1:
if (has_mon)
@@ -50471,16 +50987,16 @@ static BOOL js_date_parse_otherstring(const uint8_t *sp,
fields[2] = num[1];
break;
default:
- return FALSE;
+ return false;
}
if (fields[1] < 1 || fields[2] < 1)
- return FALSE;
+ return false;
fields[1] -= 1;
- return TRUE;
+ return true;
}
-static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_Date_parse(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue s, rv;
int fields[9];
@@ -50489,7 +51005,7 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
int i, c;
JSString *sp;
uint8_t buf[128];
- BOOL is_local;
+ bool is_local;
rv = JS_NAN;
@@ -50509,15 +51025,15 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
if (js_date_parse_isostring(buf, fields, &is_local)
|| js_date_parse_otherstring(buf, fields, &is_local)) {
static int const field_max[6] = { 0, 11, 31, 24, 59, 59 };
- BOOL valid = TRUE;
+ bool valid = true;
/* check field maximum values */
for (i = 1; i < 6; i++) {
if (fields[i] > field_max[i])
- valid = FALSE;
+ valid = false;
}
/* special case 24:00:00.000 */
if (fields[3] == 24 && (fields[4] | fields[5] | fields[6]))
- valid = FALSE;
+ valid = false;
if (valid) {
for(i = 0; i < 7; i++)
fields1[i] = fields[i];
@@ -50529,18 +51045,18 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
return rv;
}
-static JSValue js_Date_now(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_Date_now(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// now()
- return JS_NewInt64(ctx, date_now());
+ return js_int64(date_now());
}
-static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// Symbol_toPrimitive(hint)
- JSValueConst obj = this_val;
+ JSValue obj = this_val;
JSAtom hint = JS_ATOM_NULL;
int hint_num;
@@ -50568,8 +51084,8 @@ static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val,
return JS_ToPrimitive(ctx, obj, hint_num | HINT_FORCE_ORDINARY);
}
-static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// getTimezoneOffset()
double v;
@@ -50580,22 +51096,22 @@ static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val,
return JS_NAN;
else
/* assuming -8.64e15 <= v <= -8.64e15 */
- return JS_NewInt64(ctx, getTimezoneOffset((int64_t)trunc(v)));
+ return js_int64(getTimezoneOffset((int64_t)trunc(v)));
}
-static JSValue js_date_getTime(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_date_getTime(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// getTime()
double v;
if (JS_ThisTimeValue(ctx, &v, this_val))
return JS_EXCEPTION;
- return JS_NewFloat64(ctx, v);
+ return js_float64(v);
}
-static JSValue js_date_setTime(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_date_setTime(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// setTime(v)
double v;
@@ -50605,27 +51121,29 @@ static JSValue js_date_setTime(JSContext *ctx, JSValueConst this_val,
return JS_SetThisTimeValue(ctx, this_val, time_clip(v));
}
-static JSValue js_date_setYear(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_date_setYear(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// setYear(y)
double y;
- JSValueConst args[1];
+ JSValue args[1];
if (JS_ThisTimeValue(ctx, &y, this_val) || JS_ToFloat64(ctx, &y, argv[0]))
return JS_EXCEPTION;
y = +y;
+ if (isnan(y))
+ return JS_SetThisTimeValue(ctx, this_val, y);
if (isfinite(y)) {
y = trunc(y);
if (y >= 0 && y < 100)
y += 1900;
}
- args[0] = JS_NewFloat64(ctx, y);
+ args[0] = js_float64(y);
return set_date_field(ctx, this_val, 1, args, 0x011);
}
-static JSValue js_date_toJSON(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_date_toJSON(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// toJSON(key)
JSValue obj, tv, method, rv;
@@ -50723,21 +51241,20 @@ JSValue JS_NewDate(JSContext *ctx, double epoch_ms)
JSValue obj = js_create_from_ctor(ctx, JS_UNDEFINED, JS_CLASS_DATE);
if (JS_IsException(obj))
return JS_EXCEPTION;
- JS_SetObjectData(ctx, obj, __JS_NewFloat64(ctx, time_clip(epoch_ms)));
+ JS_SetObjectData(ctx, obj, js_float64(time_clip(epoch_ms)));
return obj;
}
-JS_BOOL JS_IsDate(JSValue v)
+bool JS_IsDate(JSValue v)
{
- JSObject *p;
if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
- return FALSE;
+ return false;
return JS_VALUE_GET_OBJ(v)->class_id == JS_CLASS_DATE;
}
void JS_AddIntrinsicDate(JSContext *ctx)
{
- JSValueConst obj;
+ JSValue obj;
/* Date */
ctx->class_proto[JS_CLASS_DATE] = JS_NewObject(ctx);
@@ -50755,307 +51272,6 @@ void JS_AddIntrinsicEval(JSContext *ctx)
ctx->eval_internal = __JS_EvalInternal;
}
-#ifdef CONFIG_BIGNUM
-
-/* Operators */
-
-static void js_operator_set_finalizer(JSRuntime *rt, JSValue val)
-{
- JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET);
- int i, j;
- JSBinaryOperatorDefEntry *ent;
-
- if (opset) {
- for(i = 0; i < JS_OVOP_COUNT; i++) {
- if (opset->self_ops[i])
- JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[i]));
- }
- for(j = 0; j < opset->left.count; j++) {
- ent = &opset->left.tab[j];
- for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {
- if (ent->ops[i])
- JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]));
- }
- }
- js_free_rt(rt, opset->left.tab);
- for(j = 0; j < opset->right.count; j++) {
- ent = &opset->right.tab[j];
- for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {
- if (ent->ops[i])
- JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]));
- }
- }
- js_free_rt(rt, opset->right.tab);
- js_free_rt(rt, opset);
- }
-}
-
-static void js_operator_set_mark(JSRuntime *rt, JSValueConst val,
- JS_MarkFunc *mark_func)
-{
- JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET);
- int i, j;
- JSBinaryOperatorDefEntry *ent;
-
- if (opset) {
- for(i = 0; i < JS_OVOP_COUNT; i++) {
- if (opset->self_ops[i])
- JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[i]),
- mark_func);
- }
- for(j = 0; j < opset->left.count; j++) {
- ent = &opset->left.tab[j];
- for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {
- if (ent->ops[i])
- JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]),
- mark_func);
- }
- }
- for(j = 0; j < opset->right.count; j++) {
- ent = &opset->right.tab[j];
- for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {
- if (ent->ops[i])
- JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]),
- mark_func);
- }
- }
- }
-}
-
-
-/* create an OperatorSet object */
-static JSValue js_operators_create_internal(JSContext *ctx,
- int argc, JSValueConst *argv,
- BOOL is_primitive)
-{
- JSValue opset_obj, prop, obj;
- JSOperatorSetData *opset, *opset1;
- JSBinaryOperatorDef *def;
- JSValueConst arg;
- int i, j;
- JSBinaryOperatorDefEntry *new_tab;
- JSBinaryOperatorDefEntry *ent;
- uint32_t op_count;
-
- if (ctx->rt->operator_count == UINT32_MAX) {
- return JS_ThrowTypeError(ctx, "too many operators");
- }
- opset_obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_OPERATOR_SET);
- if (JS_IsException(opset_obj))
- goto fail;
- opset = js_mallocz(ctx, sizeof(*opset));
- if (!opset)
- goto fail;
- JS_SetOpaque(opset_obj, opset);
- if (argc >= 1) {
- arg = argv[0];
- /* self operators */
- for(i = 0; i < JS_OVOP_COUNT; i++) {
- prop = JS_GetPropertyStr(ctx, arg, js_overloadable_operator_names[i]);
- if (JS_IsException(prop))
- goto fail;
- if (!JS_IsUndefined(prop)) {
- if (check_function(ctx, prop)) {
- JS_FreeValue(ctx, prop);
- goto fail;
- }
- opset->self_ops[i] = JS_VALUE_GET_OBJ(prop);
- }
- }
- }
- /* left & right operators */
- for(j = 1; j < argc; j++) {
- arg = argv[j];
- prop = JS_GetPropertyStr(ctx, arg, "left");
- if (JS_IsException(prop))
- goto fail;
- def = &opset->right;
- if (JS_IsUndefined(prop)) {
- prop = JS_GetPropertyStr(ctx, arg, "right");
- if (JS_IsException(prop))
- goto fail;
- if (JS_IsUndefined(prop)) {
- JS_ThrowTypeError(ctx, "left or right property must be present");
- goto fail;
- }
- def = &opset->left;
- }
- /* get the operator set */
- obj = JS_GetProperty(ctx, prop, JS_ATOM_prototype);
- JS_FreeValue(ctx, prop);
- if (JS_IsException(obj))
- goto fail;
- prop = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_operatorSet);
- JS_FreeValue(ctx, obj);
- if (JS_IsException(prop))
- goto fail;
- opset1 = JS_GetOpaque2(ctx, prop, JS_CLASS_OPERATOR_SET);
- if (!opset1) {
- JS_FreeValue(ctx, prop);
- goto fail;
- }
- op_count = opset1->operator_counter;
- JS_FreeValue(ctx, prop);
-
- /* we assume there are few entries */
- new_tab = js_realloc(ctx, def->tab,
- (def->count + 1) * sizeof(def->tab[0]));
- if (!new_tab)
- goto fail;
- def->tab = new_tab;
- def->count++;
- ent = def->tab + def->count - 1;
- memset(ent, 0, sizeof(def->tab[0]));
- ent->operator_index = op_count;
-
- for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {
- prop = JS_GetPropertyStr(ctx, arg,
- js_overloadable_operator_names[i]);
- if (JS_IsException(prop))
- goto fail;
- if (!JS_IsUndefined(prop)) {
- if (check_function(ctx, prop)) {
- JS_FreeValue(ctx, prop);
- goto fail;
- }
- ent->ops[i] = JS_VALUE_GET_OBJ(prop);
- }
- }
- }
- opset->is_primitive = is_primitive;
- opset->operator_counter = ctx->rt->operator_count++;
- return opset_obj;
- fail:
- JS_FreeValue(ctx, opset_obj);
- return JS_EXCEPTION;
-}
-
-static JSValue js_operators_create(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return js_operators_create_internal(ctx, argc, argv, FALSE);
-}
-
-static JSValue js_operators_updateBigIntOperators(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue opset_obj, prop;
- JSOperatorSetData *opset;
- const JSOverloadableOperatorEnum ops[2] = { JS_OVOP_DIV, JS_OVOP_POW };
- JSOverloadableOperatorEnum op;
- int i;
-
- opset_obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_BIG_INT],
- JS_ATOM_Symbol_operatorSet);
- if (JS_IsException(opset_obj))
- goto fail;
- opset = JS_GetOpaque2(ctx, opset_obj, JS_CLASS_OPERATOR_SET);
- if (!opset)
- goto fail;
- for(i = 0; i < countof(ops); i++) {
- op = ops[i];
- prop = JS_GetPropertyStr(ctx, argv[0],
- js_overloadable_operator_names[op]);
- if (JS_IsException(prop))
- goto fail;
- if (!JS_IsUndefined(prop)) {
- if (!JS_IsNull(prop) && check_function(ctx, prop)) {
- JS_FreeValue(ctx, prop);
- goto fail;
- }
- if (opset->self_ops[op])
- JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[op]));
- if (JS_IsNull(prop)) {
- opset->self_ops[op] = NULL;
- } else {
- opset->self_ops[op] = JS_VALUE_GET_PTR(prop);
- }
- }
- }
- JS_FreeValue(ctx, opset_obj);
- return JS_UNDEFINED;
- fail:
- JS_FreeValue(ctx, opset_obj);
- return JS_EXCEPTION;
-}
-
-static int js_operators_set_default(JSContext *ctx, JSValueConst obj)
-{
- JSValue opset_obj;
-
- if (!JS_IsObject(obj)) /* in case the prototype is not defined */
- return 0;
- opset_obj = js_operators_create_internal(ctx, 0, NULL, TRUE);
- if (JS_IsException(opset_obj))
- return -1;
- /* cannot be modified by the user */
- JS_DefinePropertyValue(ctx, obj, JS_ATOM_Symbol_operatorSet,
- opset_obj, 0);
- return 0;
-}
-
-static JSValue js_dummy_operators_ctor(JSContext *ctx, JSValueConst new_target,
- int argc, JSValueConst *argv)
-{
- return js_create_from_ctor(ctx, new_target, JS_CLASS_OBJECT);
-}
-
-static JSValue js_global_operators(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue func_obj, proto, opset_obj;
-
- func_obj = JS_UNDEFINED;
- proto = JS_NewObject(ctx);
- if (JS_IsException(proto))
- return JS_EXCEPTION;
- opset_obj = js_operators_create_internal(ctx, argc, argv, FALSE);
- if (JS_IsException(opset_obj))
- goto fail;
- JS_DefinePropertyValue(ctx, proto, JS_ATOM_Symbol_operatorSet,
- opset_obj, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- func_obj = JS_NewCFunction2(ctx, js_dummy_operators_ctor, "Operators",
- 0, JS_CFUNC_constructor, 0);
- if (JS_IsException(func_obj))
- goto fail;
- JS_SetConstructor2(ctx, func_obj, proto,
- 0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- JS_FreeValue(ctx, proto);
- return func_obj;
- fail:
- JS_FreeValue(ctx, proto);
- JS_FreeValue(ctx, func_obj);
- return JS_EXCEPTION;
-}
-
-static const JSCFunctionListEntry js_operators_funcs[] = {
- JS_CFUNC_DEF("create", 1, js_operators_create ),
- JS_CFUNC_DEF("updateBigIntOperators", 2, js_operators_updateBigIntOperators ),
-};
-
-/* must be called after all overloadable base types are initialized */
-void JS_AddIntrinsicOperators(JSContext *ctx)
-{
- JSValue obj;
-
- ctx->allow_operator_overloading = TRUE;
- obj = JS_NewCFunction(ctx, js_global_operators, "Operators", 1);
- JS_SetPropertyFunctionList(ctx, obj,
- js_operators_funcs,
- countof(js_operators_funcs));
- JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_Operators,
- obj,
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- /* add default operatorSets */
- js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BOOLEAN]);
- js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_NUMBER]);
- js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_STRING]);
- js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_INT]);
- js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT]);
- js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL]);
-}
-#endif /* CONFIG_BIGNUM */
-
/* BigInt */
static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
@@ -51072,17 +51288,10 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
case JS_TAG_BIG_INT:
break;
case JS_TAG_FLOAT64:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
-#endif
{
bf_t *a, a_s;
- a = JS_ToBigFloat(ctx, &a_s, val);
- if (!a) {
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
- }
+ a = JS_ToBigInt1(ctx, &a_s, val);
if (!bf_is_finite(a)) {
JS_FreeValue(ctx, val);
val = JS_ThrowRangeError(ctx, "cannot convert NaN or Infinity to BigInt");
@@ -51112,13 +51321,6 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
bf_delete(a);
}
break;
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_DECIMAL:
- val = JS_ToStringFree(ctx, val);
- if (JS_IsException(val))
- break;
- goto redo;
-#endif
case JS_TAG_STRING:
val = JS_StringToBigIntErr(ctx, val);
break;
@@ -51137,31 +51339,31 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
}
static JSValue js_bigint_constructor(JSContext *ctx,
- JSValueConst new_target,
- int argc, JSValueConst *argv)
+ JSValue new_target,
+ int argc, JSValue *argv)
{
if (!JS_IsUndefined(new_target))
return JS_ThrowTypeError(ctx, "not a constructor");
- return JS_ToBigIntCtorFree(ctx, JS_DupValue(ctx, argv[0]));
+ return JS_ToBigIntCtorFree(ctx, js_dup(argv[0]));
}
-static JSValue js_thisBigIntValue(JSContext *ctx, JSValueConst this_val)
+static JSValue js_thisBigIntValue(JSContext *ctx, JSValue this_val)
{
if (JS_IsBigInt(ctx, this_val))
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(this_val);
if (p->class_id == JS_CLASS_BIG_INT) {
if (JS_IsBigInt(ctx, p->u.object_data))
- return JS_DupValue(ctx, p->u.object_data);
+ return js_dup(p->u.object_data);
}
}
return JS_ThrowTypeError(ctx, "not a BigInt");
}
-static JSValue js_bigint_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_bigint_toString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue val;
int base;
@@ -51185,146 +51387,15 @@ static JSValue js_bigint_toString(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-static JSValue js_bigint_valueOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_bigint_valueOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
return js_thisBigIntValue(ctx, this_val);
}
-#ifdef CONFIG_BIGNUM
-static JSValue js_bigint_div(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
-{
- bf_t a_s, b_s, *a, *b, *r, *q;
- int status;
- JSValue q_val, r_val;
-
- q_val = JS_NewBigInt(ctx);
- if (JS_IsException(q_val))
- return JS_EXCEPTION;
- r_val = JS_NewBigInt(ctx);
- if (JS_IsException(r_val))
- goto fail;
- b = NULL;
- a = JS_ToBigInt(ctx, &a_s, argv[0]);
- if (!a)
- goto fail;
- b = JS_ToBigInt(ctx, &b_s, argv[1]);
- if (!b) {
- JS_FreeBigInt(ctx, a, &a_s);
- goto fail;
- }
- q = JS_GetBigInt(q_val);
- r = JS_GetBigInt(r_val);
- status = bf_divrem(q, r, a, b, BF_PREC_INF, BF_RNDZ, magic & 0xf);
- JS_FreeBigInt(ctx, a, &a_s);
- JS_FreeBigInt(ctx, b, &b_s);
- if (unlikely(status)) {
- throw_bf_exception(ctx, status);
- goto fail;
- }
- q_val = JS_CompactBigInt(ctx, q_val);
- if (magic & 0x10) {
- JSValue ret;
- ret = JS_NewArray(ctx);
- if (JS_IsException(ret))
- goto fail;
- JS_SetPropertyUint32(ctx, ret, 0, q_val);
- JS_SetPropertyUint32(ctx, ret, 1, JS_CompactBigInt(ctx, r_val));
- return ret;
- } else {
- JS_FreeValue(ctx, r_val);
- return q_val;
- }
- fail:
- JS_FreeValue(ctx, q_val);
- JS_FreeValue(ctx, r_val);
- return JS_EXCEPTION;
-}
-
-static JSValue js_bigint_sqrt(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
-{
- bf_t a_s, *a, *r, *rem;
- int status;
- JSValue r_val, rem_val;
-
- r_val = JS_NewBigInt(ctx);
- if (JS_IsException(r_val))
- return JS_EXCEPTION;
- rem_val = JS_NewBigInt(ctx);
- if (JS_IsException(rem_val))
- return JS_EXCEPTION;
- r = JS_GetBigInt(r_val);
- rem = JS_GetBigInt(rem_val);
-
- a = JS_ToBigInt(ctx, &a_s, argv[0]);
- if (!a)
- goto fail;
- status = bf_sqrtrem(r, rem, a);
- JS_FreeBigInt(ctx, a, &a_s);
- if (unlikely(status & ~BF_ST_INEXACT)) {
- throw_bf_exception(ctx, status);
- goto fail;
- }
- r_val = JS_CompactBigInt(ctx, r_val);
- if (magic) {
- JSValue ret;
- ret = JS_NewArray(ctx);
- if (JS_IsException(ret))
- goto fail;
- JS_SetPropertyUint32(ctx, ret, 0, r_val);
- JS_SetPropertyUint32(ctx, ret, 1, JS_CompactBigInt(ctx, rem_val));
- return ret;
- } else {
- JS_FreeValue(ctx, rem_val);
- return r_val;
- }
- fail:
- JS_FreeValue(ctx, r_val);
- JS_FreeValue(ctx, rem_val);
- return JS_EXCEPTION;
-}
-
-static JSValue js_bigint_op1(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv,
- int magic)
-{
- bf_t a_s, *a;
- int64_t res;
-
- a = JS_ToBigInt(ctx, &a_s, argv[0]);
- if (!a)
- return JS_EXCEPTION;
- switch(magic) {
- case 0: /* floorLog2 */
- if (a->sign || a->expn <= 0) {
- res = -1;
- } else {
- res = a->expn - 1;
- }
- break;
- case 1: /* ctz */
- if (bf_is_zero(a)) {
- res = -1;
- } else {
- res = bf_get_exp_min(a);
- }
- break;
- default:
- abort();
- }
- JS_FreeBigInt(ctx, a, &a_s);
- return JS_NewBigInt64(ctx, res);
-}
-#endif
-
static JSValue js_bigint_asUintN(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv, int asIntN)
+ JSValue this_val,
+ int argc, JSValue *argv, int asIntN)
{
uint64_t bits;
bf_t a_s, *a = &a_s, *r, mask_s, *mask = &mask_s;
@@ -51335,7 +51406,6 @@ static JSValue js_bigint_asUintN(JSContext *ctx,
res = JS_NewBigInt(ctx);
if (JS_IsException(res))
return JS_EXCEPTION;
- r = JS_GetBigInt(res);
a = JS_ToBigInt(ctx, &a_s, argv[1]);
if (!a) {
JS_FreeValue(ctx, res);
@@ -51365,21 +51435,6 @@ static JSValue js_bigint_asUintN(JSContext *ctx,
static const JSCFunctionListEntry js_bigint_funcs[] = {
JS_CFUNC_MAGIC_DEF("asUintN", 2, js_bigint_asUintN, 0 ),
JS_CFUNC_MAGIC_DEF("asIntN", 2, js_bigint_asUintN, 1 ),
-#ifdef CONFIG_BIGNUM
- /* QuickJS extensions */
- JS_CFUNC_MAGIC_DEF("tdiv", 2, js_bigint_div, BF_RNDZ ),
- JS_CFUNC_MAGIC_DEF("fdiv", 2, js_bigint_div, BF_RNDD ),
- JS_CFUNC_MAGIC_DEF("cdiv", 2, js_bigint_div, BF_RNDU ),
- JS_CFUNC_MAGIC_DEF("ediv", 2, js_bigint_div, BF_DIVREM_EUCLIDIAN ),
- JS_CFUNC_MAGIC_DEF("tdivrem", 2, js_bigint_div, BF_RNDZ | 0x10 ),
- JS_CFUNC_MAGIC_DEF("fdivrem", 2, js_bigint_div, BF_RNDD | 0x10 ),
- JS_CFUNC_MAGIC_DEF("cdivrem", 2, js_bigint_div, BF_RNDU | 0x10 ),
- JS_CFUNC_MAGIC_DEF("edivrem", 2, js_bigint_div, BF_DIVREM_EUCLIDIAN | 0x10 ),
- JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigint_sqrt, 0 ),
- JS_CFUNC_MAGIC_DEF("sqrtrem", 1, js_bigint_sqrt, 1 ),
- JS_CFUNC_MAGIC_DEF("floorLog2", 1, js_bigint_op1, 0 ),
- JS_CFUNC_MAGIC_DEF("ctz", 1, js_bigint_op1, 1 ),
-#endif
};
static const JSCFunctionListEntry js_bigint_proto_funcs[] = {
@@ -51390,14 +51445,7 @@ static const JSCFunctionListEntry js_bigint_proto_funcs[] = {
void JS_AddIntrinsicBigInt(JSContext *ctx)
{
- JSRuntime *rt = ctx->rt;
- JSValueConst obj1;
-
- rt->bigint_ops.to_string = js_bigint_to_string;
- rt->bigint_ops.from_string = js_string_to_bigint;
- rt->bigint_ops.unary_arith = js_unary_arith_bigint;
- rt->bigint_ops.binary_arith = js_binary_arith_bigint;
- rt->bigint_ops.compare = js_compare_bigfloat;
+ JSValue obj1;
ctx->class_proto[JS_CLASS_BIG_INT] = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_INT],
@@ -51409,1413 +51457,6 @@ void JS_AddIntrinsicBigInt(JSContext *ctx)
countof(js_bigint_funcs));
}
-#ifdef CONFIG_BIGNUM
-
-/* BigFloat */
-
-static JSValue js_thisBigFloatValue(JSContext *ctx, JSValueConst this_val)
-{
- if (JS_IsBigFloat(this_val))
- return JS_DupValue(ctx, this_val);
-
- if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
- JSObject *p = JS_VALUE_GET_OBJ(this_val);
- if (p->class_id == JS_CLASS_BIG_FLOAT) {
- if (JS_IsBigFloat(p->u.object_data))
- return JS_DupValue(ctx, p->u.object_data);
- }
- }
- return JS_ThrowTypeError(ctx, "not a bigfloat");
-}
-
-static JSValue js_bigfloat_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue val;
- int base;
- JSValue ret;
-
- val = js_thisBigFloatValue(ctx, this_val);
- if (JS_IsException(val))
- return val;
- if (argc == 0 || JS_IsUndefined(argv[0])) {
- base = 10;
- } else {
- base = js_get_radix(ctx, argv[0]);
- if (base < 0)
- goto fail;
- }
- ret = js_ftoa(ctx, val, base, 0, BF_RNDN | BF_FTOA_FORMAT_FREE_MIN);
- JS_FreeValue(ctx, val);
- return ret;
- fail:
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
-}
-
-static JSValue js_bigfloat_valueOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return js_thisBigFloatValue(ctx, this_val);
-}
-
-static int bigfloat_get_rnd_mode(JSContext *ctx, JSValueConst val)
-{
- int rnd_mode;
- if (JS_ToInt32Sat(ctx, &rnd_mode, val))
- return -1;
- if (rnd_mode < BF_RNDN || rnd_mode > BF_RNDF) {
- JS_ThrowRangeError(ctx, "invalid rounding mode");
- return -1;
- }
- return rnd_mode;
-}
-
-static JSValue js_bigfloat_toFixed(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue val, ret;
- int64_t f;
- int rnd_mode, radix;
-
- val = js_thisBigFloatValue(ctx, this_val);
- if (JS_IsException(val))
- return val;
- if (JS_ToInt64Sat(ctx, &f, argv[0]))
- goto fail;
- if (f < 0 || f > BF_PREC_MAX) {
- JS_ThrowRangeError(ctx, "invalid number of digits");
- goto fail;
- }
- rnd_mode = BF_RNDNA;
- radix = 10;
- /* XXX: swap parameter order for rounding mode and radix */
- if (argc > 1) {
- rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]);
- if (rnd_mode < 0)
- goto fail;
- }
- if (argc > 2) {
- radix = js_get_radix(ctx, argv[2]);
- if (radix < 0)
- goto fail;
- }
- ret = js_ftoa(ctx, val, radix, f, rnd_mode | BF_FTOA_FORMAT_FRAC);
- JS_FreeValue(ctx, val);
- return ret;
- fail:
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
-}
-
-static BOOL js_bigfloat_is_finite(JSContext *ctx, JSValueConst val)
-{
- BOOL res;
- uint32_t tag;
-
- tag = JS_VALUE_GET_NORM_TAG(val);
- switch(tag) {
- case JS_TAG_BIG_FLOAT:
- {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- res = bf_is_finite(&p->num);
- }
- break;
- default:
- res = FALSE;
- break;
- }
- return res;
-}
-
-static JSValue js_bigfloat_toExponential(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue val, ret;
- int64_t f;
- int rnd_mode, radix;
-
- val = js_thisBigFloatValue(ctx, this_val);
- if (JS_IsException(val))
- return val;
- if (JS_ToInt64Sat(ctx, &f, argv[0]))
- goto fail;
- if (!js_bigfloat_is_finite(ctx, val)) {
- ret = JS_ToString(ctx, val);
- } else if (JS_IsUndefined(argv[0])) {
- ret = js_ftoa(ctx, val, 10, 0,
- BF_RNDN | BF_FTOA_FORMAT_FREE_MIN | BF_FTOA_FORCE_EXP);
- } else {
- if (f < 0 || f > BF_PREC_MAX) {
- JS_ThrowRangeError(ctx, "invalid number of digits");
- goto fail;
- }
- rnd_mode = BF_RNDNA;
- radix = 10;
- if (argc > 1) {
- rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]);
- if (rnd_mode < 0)
- goto fail;
- }
- if (argc > 2) {
- radix = js_get_radix(ctx, argv[2]);
- if (radix < 0)
- goto fail;
- }
- ret = js_ftoa(ctx, val, radix, f + 1,
- rnd_mode | BF_FTOA_FORMAT_FIXED | BF_FTOA_FORCE_EXP);
- }
- JS_FreeValue(ctx, val);
- return ret;
- fail:
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
-}
-
-static JSValue js_bigfloat_toPrecision(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue val, ret;
- int64_t p;
- int rnd_mode, radix;
-
- val = js_thisBigFloatValue(ctx, this_val);
- if (JS_IsException(val))
- return val;
- if (JS_IsUndefined(argv[0]))
- goto to_string;
- if (JS_ToInt64Sat(ctx, &p, argv[0]))
- goto fail;
- if (!js_bigfloat_is_finite(ctx, val)) {
- to_string:
- ret = JS_ToString(ctx, this_val);
- } else {
- if (p < 1 || p > BF_PREC_MAX) {
- JS_ThrowRangeError(ctx, "invalid number of digits");
- goto fail;
- }
- rnd_mode = BF_RNDNA;
- radix = 10;
- if (argc > 1) {
- rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]);
- if (rnd_mode < 0)
- goto fail;
- }
- if (argc > 2) {
- radix = js_get_radix(ctx, argv[2]);
- if (radix < 0)
- goto fail;
- }
- ret = js_ftoa(ctx, val, radix, p, rnd_mode | BF_FTOA_FORMAT_FIXED);
- }
- JS_FreeValue(ctx, val);
- return ret;
- fail:
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
-}
-
-static const JSCFunctionListEntry js_bigfloat_proto_funcs[] = {
- JS_CFUNC_DEF("toString", 0, js_bigfloat_toString ),
- JS_CFUNC_DEF("valueOf", 0, js_bigfloat_valueOf ),
- JS_CFUNC_DEF("toPrecision", 1, js_bigfloat_toPrecision ),
- JS_CFUNC_DEF("toFixed", 1, js_bigfloat_toFixed ),
- JS_CFUNC_DEF("toExponential", 1, js_bigfloat_toExponential ),
-};
-
-static JSValue js_bigfloat_constructor(JSContext *ctx,
- JSValueConst new_target,
- int argc, JSValueConst *argv)
-{
- JSValue val;
- if (!JS_IsUndefined(new_target))
- return JS_ThrowTypeError(ctx, "not a constructor");
- if (argc == 0) {
- bf_t *r;
- val = JS_NewBigFloat(ctx);
- if (JS_IsException(val))
- return val;
- r = JS_GetBigFloat(val);
- bf_set_zero(r, 0);
- } else {
- val = JS_DupValue(ctx, argv[0]);
- redo:
- switch(JS_VALUE_GET_NORM_TAG(val)) {
- case JS_TAG_BIG_FLOAT:
- break;
- case JS_TAG_FLOAT64:
- {
- bf_t *r;
- double d = JS_VALUE_GET_FLOAT64(val);
- val = JS_NewBigFloat(ctx);
- if (JS_IsException(val))
- break;
- r = JS_GetBigFloat(val);
- if (bf_set_float64(r, d))
- goto fail;
- }
- break;
- case JS_TAG_INT:
- {
- bf_t *r;
- int32_t v = JS_VALUE_GET_INT(val);
- val = JS_NewBigFloat(ctx);
- if (JS_IsException(val))
- break;
- r = JS_GetBigFloat(val);
- if (bf_set_si(r, v))
- goto fail;
- }
- break;
- case JS_TAG_BIG_INT:
- /* We keep the full precision of the integer */
- {
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- val = JS_MKPTR(JS_TAG_BIG_FLOAT, p);
- }
- break;
- case JS_TAG_BIG_DECIMAL:
- val = JS_ToStringFree(ctx, val);
- if (JS_IsException(val))
- break;
- goto redo;
- case JS_TAG_STRING:
- {
- const char *str, *p;
- size_t len;
- int err;
-
- str = JS_ToCStringLen(ctx, &len, val);
- JS_FreeValue(ctx, val);
- if (!str)
- return JS_EXCEPTION;
- p = str;
- p += skip_spaces(p);
- if ((p - str) == len) {
- bf_t *r;
- val = JS_NewBigFloat(ctx);
- if (JS_IsException(val))
- break;
- r = JS_GetBigFloat(val);
- bf_set_zero(r, 0);
- err = 0;
- } else {
- val = js_atof(ctx, p, &p, 0, ATOD_ACCEPT_BIN_OCT |
- ATOD_TYPE_BIG_FLOAT |
- ATOD_ACCEPT_PREFIX_AFTER_SIGN);
- if (JS_IsException(val)) {
- JS_FreeCString(ctx, str);
- return JS_EXCEPTION;
- }
- p += skip_spaces(p);
- err = ((p - str) != len);
- }
- JS_FreeCString(ctx, str);
- if (err) {
- JS_FreeValue(ctx, val);
- return JS_ThrowSyntaxError(ctx, "invalid bigfloat literal");
- }
- }
- break;
- case JS_TAG_OBJECT:
- val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);
- if (JS_IsException(val))
- break;
- goto redo;
- case JS_TAG_NULL:
- case JS_TAG_UNDEFINED:
- default:
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert to bigfloat");
- }
- }
- return val;
- fail:
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
-}
-
-static JSValue js_bigfloat_get_const(JSContext *ctx,
- JSValueConst this_val, int magic)
-{
- bf_t *r;
- JSValue val;
- val = JS_NewBigFloat(ctx);
- if (JS_IsException(val))
- return val;
- r = JS_GetBigFloat(val);
- switch(magic) {
- case 0: /* PI */
- bf_const_pi(r, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case 1: /* LN2 */
- bf_const_log2(r, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case 2: /* MIN_VALUE */
- case 3: /* MAX_VALUE */
- {
- slimb_t e_range, e;
- e_range = (limb_t)1 << (bf_get_exp_bits(ctx->fp_env.flags) - 1);
- bf_set_ui(r, 1);
- if (magic == 2) {
- e = -e_range + 2;
- if (ctx->fp_env.flags & BF_FLAG_SUBNORMAL)
- e -= ctx->fp_env.prec - 1;
- bf_mul_2exp(r, e, ctx->fp_env.prec, ctx->fp_env.flags);
- } else {
- bf_mul_2exp(r, ctx->fp_env.prec, ctx->fp_env.prec,
- ctx->fp_env.flags);
- bf_add_si(r, r, -1, ctx->fp_env.prec, ctx->fp_env.flags);
- bf_mul_2exp(r, e_range - ctx->fp_env.prec, ctx->fp_env.prec,
- ctx->fp_env.flags);
- }
- }
- break;
- case 4: /* EPSILON */
- bf_set_ui(r, 1);
- bf_mul_2exp(r, 1 - ctx->fp_env.prec,
- ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- default:
- abort();
- }
- return val;
-}
-
-static JSValue js_bigfloat_parseFloat(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- bf_t *a;
- const char *str;
- JSValue ret;
- int radix;
- JSFloatEnv *fe;
-
- str = JS_ToCString(ctx, argv[0]);
- if (!str)
- return JS_EXCEPTION;
- if (JS_ToInt32(ctx, &radix, argv[1])) {
- fail:
- JS_FreeCString(ctx, str);
- return JS_EXCEPTION;
- }
- if (radix != 0 && (radix < 2 || radix > 36)) {
- JS_ThrowRangeError(ctx, "radix must be between 2 and 36");
- goto fail;
- }
- fe = &ctx->fp_env;
- if (argc > 2) {
- fe = JS_GetOpaque2(ctx, argv[2], JS_CLASS_FLOAT_ENV);
- if (!fe)
- goto fail;
- }
- ret = JS_NewBigFloat(ctx);
- if (JS_IsException(ret))
- goto done;
- a = JS_GetBigFloat(ret);
- /* XXX: use js_atof() */
- bf_atof(a, str, NULL, radix, fe->prec, fe->flags);
- done:
- JS_FreeCString(ctx, str);
- return ret;
-}
-
-static JSValue js_bigfloat_isFinite(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValueConst val = argv[0];
- JSBigFloat *p;
-
- if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT)
- return JS_FALSE;
- p = JS_VALUE_GET_PTR(val);
- return JS_NewBool(ctx, bf_is_finite(&p->num));
-}
-
-static JSValue js_bigfloat_isNaN(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValueConst val = argv[0];
- JSBigFloat *p;
-
- if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT)
- return JS_FALSE;
- p = JS_VALUE_GET_PTR(val);
- return JS_NewBool(ctx, bf_is_nan(&p->num));
-}
-
-enum {
- MATH_OP_ABS,
- MATH_OP_FLOOR,
- MATH_OP_CEIL,
- MATH_OP_ROUND,
- MATH_OP_TRUNC,
- MATH_OP_SQRT,
- MATH_OP_FPROUND,
- MATH_OP_ACOS,
- MATH_OP_ASIN,
- MATH_OP_ATAN,
- MATH_OP_ATAN2,
- MATH_OP_COS,
- MATH_OP_EXP,
- MATH_OP_LOG,
- MATH_OP_POW,
- MATH_OP_SIN,
- MATH_OP_TAN,
- MATH_OP_FMOD,
- MATH_OP_REM,
- MATH_OP_SIGN,
-
- MATH_OP_ADD,
- MATH_OP_SUB,
- MATH_OP_MUL,
- MATH_OP_DIV,
-};
-
-static JSValue js_bigfloat_fop(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
-{
- bf_t a_s, *a, *r;
- JSFloatEnv *fe;
- int rnd_mode;
- JSValue op1, res;
-
- op1 = JS_ToNumeric(ctx, argv[0]);
- if (JS_IsException(op1))
- return op1;
- a = JS_ToBigFloat(ctx, &a_s, op1);
- if (!a) {
- JS_FreeValue(ctx, op1);
- return JS_EXCEPTION;
- }
- fe = &ctx->fp_env;
- if (argc > 1) {
- fe = JS_GetOpaque2(ctx, argv[1], JS_CLASS_FLOAT_ENV);
- if (!fe)
- goto fail;
- }
- res = JS_NewBigFloat(ctx);
- if (JS_IsException(res)) {
- fail:
- if (a == &a_s)
- bf_delete(a);
- JS_FreeValue(ctx, op1);
- return JS_EXCEPTION;
- }
- r = JS_GetBigFloat(res);
- switch (magic) {
- case MATH_OP_ABS:
- bf_set(r, a);
- r->sign = 0;
- break;
- case MATH_OP_FLOOR:
- rnd_mode = BF_RNDD;
- goto rint;
- case MATH_OP_CEIL:
- rnd_mode = BF_RNDU;
- goto rint;
- case MATH_OP_ROUND:
- rnd_mode = BF_RNDNA;
- goto rint;
- case MATH_OP_TRUNC:
- rnd_mode = BF_RNDZ;
- rint:
- bf_set(r, a);
- fe->status |= bf_rint(r, rnd_mode);
- break;
- case MATH_OP_SQRT:
- fe->status |= bf_sqrt(r, a, fe->prec, fe->flags);
- break;
- case MATH_OP_FPROUND:
- bf_set(r, a);
- fe->status |= bf_round(r, fe->prec, fe->flags);
- break;
- case MATH_OP_ACOS:
- fe->status |= bf_acos(r, a, fe->prec, fe->flags);
- break;
- case MATH_OP_ASIN:
- fe->status |= bf_asin(r, a, fe->prec, fe->flags);
- break;
- case MATH_OP_ATAN:
- fe->status |= bf_atan(r, a, fe->prec, fe->flags);
- break;
- case MATH_OP_COS:
- fe->status |= bf_cos(r, a, fe->prec, fe->flags);
- break;
- case MATH_OP_EXP:
- fe->status |= bf_exp(r, a, fe->prec, fe->flags);
- break;
- case MATH_OP_LOG:
- fe->status |= bf_log(r, a, fe->prec, fe->flags);
- break;
- case MATH_OP_SIN:
- fe->status |= bf_sin(r, a, fe->prec, fe->flags);
- break;
- case MATH_OP_TAN:
- fe->status |= bf_tan(r, a, fe->prec, fe->flags);
- break;
- case MATH_OP_SIGN:
- if (bf_is_nan(a) || bf_is_zero(a)) {
- bf_set(r, a);
- } else {
- bf_set_si(r, 1 - 2 * a->sign);
- }
- break;
- default:
- abort();
- }
- if (a == &a_s)
- bf_delete(a);
- JS_FreeValue(ctx, op1);
- return res;
-}
-
-static JSValue js_bigfloat_fop2(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
-{
- bf_t a_s, *a, b_s, *b, r_s, *r = &r_s;
- JSFloatEnv *fe;
- JSValue op1, op2, res;
-
- op1 = JS_ToNumeric(ctx, argv[0]);
- if (JS_IsException(op1))
- return op1;
- op2 = JS_ToNumeric(ctx, argv[1]);
- if (JS_IsException(op2)) {
- JS_FreeValue(ctx, op1);
- return op2;
- }
- a = JS_ToBigFloat(ctx, &a_s, op1);
- if (!a)
- goto fail1;
- b = JS_ToBigFloat(ctx, &b_s, op2);
- if (!b)
- goto fail2;
- fe = &ctx->fp_env;
- if (argc > 2) {
- fe = JS_GetOpaque2(ctx, argv[2], JS_CLASS_FLOAT_ENV);
- if (!fe)
- goto fail;
- }
- res = JS_NewBigFloat(ctx);
- if (JS_IsException(res)) {
- fail:
- if (b == &b_s)
- bf_delete(b);
- fail2:
- if (a == &a_s)
- bf_delete(a);
- fail1:
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- return JS_EXCEPTION;
- }
- r = JS_GetBigFloat(res);
- switch (magic) {
- case MATH_OP_ATAN2:
- fe->status |= bf_atan2(r, a, b, fe->prec, fe->flags);
- break;
- case MATH_OP_POW:
- fe->status |= bf_pow(r, a, b, fe->prec, fe->flags | BF_POW_JS_QUIRKS);
- break;
- case MATH_OP_FMOD:
- fe->status |= bf_rem(r, a, b, fe->prec, fe->flags, BF_RNDZ);
- break;
- case MATH_OP_REM:
- fe->status |= bf_rem(r, a, b, fe->prec, fe->flags, BF_RNDN);
- break;
- case MATH_OP_ADD:
- fe->status |= bf_add(r, a, b, fe->prec, fe->flags);
- break;
- case MATH_OP_SUB:
- fe->status |= bf_sub(r, a, b, fe->prec, fe->flags);
- break;
- case MATH_OP_MUL:
- fe->status |= bf_mul(r, a, b, fe->prec, fe->flags);
- break;
- case MATH_OP_DIV:
- fe->status |= bf_div(r, a, b, fe->prec, fe->flags);
- break;
- default:
- abort();
- }
- if (a == &a_s)
- bf_delete(a);
- if (b == &b_s)
- bf_delete(b);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- return res;
-}
-
-static const JSCFunctionListEntry js_bigfloat_funcs[] = {
- JS_CGETSET_MAGIC_DEF("PI", js_bigfloat_get_const, NULL, 0 ),
- JS_CGETSET_MAGIC_DEF("LN2", js_bigfloat_get_const, NULL, 1 ),
- JS_CGETSET_MAGIC_DEF("MIN_VALUE", js_bigfloat_get_const, NULL, 2 ),
- JS_CGETSET_MAGIC_DEF("MAX_VALUE", js_bigfloat_get_const, NULL, 3 ),
- JS_CGETSET_MAGIC_DEF("EPSILON", js_bigfloat_get_const, NULL, 4 ),
- JS_CFUNC_DEF("parseFloat", 1, js_bigfloat_parseFloat ),
- JS_CFUNC_DEF("isFinite", 1, js_bigfloat_isFinite ),
- JS_CFUNC_DEF("isNaN", 1, js_bigfloat_isNaN ),
- JS_CFUNC_MAGIC_DEF("abs", 1, js_bigfloat_fop, MATH_OP_ABS ),
- JS_CFUNC_MAGIC_DEF("fpRound", 1, js_bigfloat_fop, MATH_OP_FPROUND ),
- JS_CFUNC_MAGIC_DEF("floor", 1, js_bigfloat_fop, MATH_OP_FLOOR ),
- JS_CFUNC_MAGIC_DEF("ceil", 1, js_bigfloat_fop, MATH_OP_CEIL ),
- JS_CFUNC_MAGIC_DEF("round", 1, js_bigfloat_fop, MATH_OP_ROUND ),
- JS_CFUNC_MAGIC_DEF("trunc", 1, js_bigfloat_fop, MATH_OP_TRUNC ),
- JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigfloat_fop, MATH_OP_SQRT ),
- JS_CFUNC_MAGIC_DEF("acos", 1, js_bigfloat_fop, MATH_OP_ACOS ),
- JS_CFUNC_MAGIC_DEF("asin", 1, js_bigfloat_fop, MATH_OP_ASIN ),
- JS_CFUNC_MAGIC_DEF("atan", 1, js_bigfloat_fop, MATH_OP_ATAN ),
- JS_CFUNC_MAGIC_DEF("atan2", 2, js_bigfloat_fop2, MATH_OP_ATAN2 ),
- JS_CFUNC_MAGIC_DEF("cos", 1, js_bigfloat_fop, MATH_OP_COS ),
- JS_CFUNC_MAGIC_DEF("exp", 1, js_bigfloat_fop, MATH_OP_EXP ),
- JS_CFUNC_MAGIC_DEF("log", 1, js_bigfloat_fop, MATH_OP_LOG ),
- JS_CFUNC_MAGIC_DEF("pow", 2, js_bigfloat_fop2, MATH_OP_POW ),
- JS_CFUNC_MAGIC_DEF("sin", 1, js_bigfloat_fop, MATH_OP_SIN ),
- JS_CFUNC_MAGIC_DEF("tan", 1, js_bigfloat_fop, MATH_OP_TAN ),
- JS_CFUNC_MAGIC_DEF("sign", 1, js_bigfloat_fop, MATH_OP_SIGN ),
- JS_CFUNC_MAGIC_DEF("add", 2, js_bigfloat_fop2, MATH_OP_ADD ),
- JS_CFUNC_MAGIC_DEF("sub", 2, js_bigfloat_fop2, MATH_OP_SUB ),
- JS_CFUNC_MAGIC_DEF("mul", 2, js_bigfloat_fop2, MATH_OP_MUL ),
- JS_CFUNC_MAGIC_DEF("div", 2, js_bigfloat_fop2, MATH_OP_DIV ),
- JS_CFUNC_MAGIC_DEF("fmod", 2, js_bigfloat_fop2, MATH_OP_FMOD ),
- JS_CFUNC_MAGIC_DEF("remainder", 2, js_bigfloat_fop2, MATH_OP_REM ),
-};
-
-/* FloatEnv */
-
-static JSValue js_float_env_constructor(JSContext *ctx,
- JSValueConst new_target,
- int argc, JSValueConst *argv)
-{
- JSValue obj;
- JSFloatEnv *fe;
- int64_t prec;
- int flags, rndmode;
-
- prec = ctx->fp_env.prec;
- flags = ctx->fp_env.flags;
- if (!JS_IsUndefined(argv[0])) {
- if (JS_ToInt64Sat(ctx, &prec, argv[0]))
- return JS_EXCEPTION;
- if (prec < BF_PREC_MIN || prec > BF_PREC_MAX)
- return JS_ThrowRangeError(ctx, "invalid precision");
- flags = BF_RNDN; /* RNDN, max exponent size, no subnormal */
- if (argc > 1 && !JS_IsUndefined(argv[1])) {
- if (JS_ToInt32Sat(ctx, &rndmode, argv[1]))
- return JS_EXCEPTION;
- if (rndmode < BF_RNDN || rndmode > BF_RNDF)
- return JS_ThrowRangeError(ctx, "invalid rounding mode");
- flags = rndmode;
- }
- }
-
- obj = JS_NewObjectClass(ctx, JS_CLASS_FLOAT_ENV);
- if (JS_IsException(obj))
- return JS_EXCEPTION;
- fe = js_malloc(ctx, sizeof(*fe));
- if (!fe)
- return JS_EXCEPTION;
- fe->prec = prec;
- fe->flags = flags;
- fe->status = 0;
- JS_SetOpaque(obj, fe);
- return obj;
-}
-
-static void js_float_env_finalizer(JSRuntime *rt, JSValue val)
-{
- JSFloatEnv *fe = JS_GetOpaque(val, JS_CLASS_FLOAT_ENV);
- js_free_rt(rt, fe);
-}
-
-static JSValue js_float_env_get_prec(JSContext *ctx, JSValueConst this_val)
-{
- return JS_NewInt64(ctx, ctx->fp_env.prec);
-}
-
-static JSValue js_float_env_get_expBits(JSContext *ctx, JSValueConst this_val)
-{
- return JS_NewInt32(ctx, bf_get_exp_bits(ctx->fp_env.flags));
-}
-
-static JSValue js_float_env_setPrec(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValueConst func;
- int exp_bits, flags, saved_flags;
- JSValue ret;
- limb_t saved_prec;
- int64_t prec;
-
- func = argv[0];
- if (JS_ToInt64Sat(ctx, &prec, argv[1]))
- return JS_EXCEPTION;
- if (prec < BF_PREC_MIN || prec > BF_PREC_MAX)
- return JS_ThrowRangeError(ctx, "invalid precision");
- exp_bits = BF_EXP_BITS_MAX;
-
- if (argc > 2 && !JS_IsUndefined(argv[2])) {
- if (JS_ToInt32Sat(ctx, &exp_bits, argv[2]))
- return JS_EXCEPTION;
- if (exp_bits < BF_EXP_BITS_MIN || exp_bits > BF_EXP_BITS_MAX)
- return JS_ThrowRangeError(ctx, "invalid number of exponent bits");
- }
-
- flags = BF_RNDN | BF_FLAG_SUBNORMAL | bf_set_exp_bits(exp_bits);
-
- saved_prec = ctx->fp_env.prec;
- saved_flags = ctx->fp_env.flags;
-
- ctx->fp_env.prec = prec;
- ctx->fp_env.flags = flags;
-
- ret = JS_Call(ctx, func, JS_UNDEFINED, 0, NULL);
- /* always restore the floating point precision */
- ctx->fp_env.prec = saved_prec;
- ctx->fp_env.flags = saved_flags;
- return ret;
-}
-
-#define FE_PREC (-1)
-#define FE_EXP (-2)
-#define FE_RNDMODE (-3)
-#define FE_SUBNORMAL (-4)
-
-static JSValue js_float_env_proto_get_status(JSContext *ctx, JSValueConst this_val, int magic)
-{
- JSFloatEnv *fe;
- fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV);
- if (!fe)
- return JS_EXCEPTION;
- switch(magic) {
- case FE_PREC:
- return JS_NewInt64(ctx, fe->prec);
- case FE_EXP:
- return JS_NewInt32(ctx, bf_get_exp_bits(fe->flags));
- case FE_RNDMODE:
- return JS_NewInt32(ctx, fe->flags & BF_RND_MASK);
- case FE_SUBNORMAL:
- return JS_NewBool(ctx, fe->flags & BF_FLAG_SUBNORMAL);
- default:
- return JS_NewBool(ctx, fe->status & magic);
- }
-}
-
-static JSValue js_float_env_proto_set_status(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic)
-{
- JSFloatEnv *fe;
- int b;
- int64_t prec;
-
- fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV);
- if (!fe)
- return JS_EXCEPTION;
- switch(magic) {
- case FE_PREC:
- if (JS_ToInt64Sat(ctx, &prec, val))
- return JS_EXCEPTION;
- if (prec < BF_PREC_MIN || prec > BF_PREC_MAX)
- return JS_ThrowRangeError(ctx, "invalid precision");
- fe->prec = prec;
- break;
- case FE_EXP:
- if (JS_ToInt32Sat(ctx, &b, val))
- return JS_EXCEPTION;
- if (b < BF_EXP_BITS_MIN || b > BF_EXP_BITS_MAX)
- return JS_ThrowRangeError(ctx, "invalid number of exponent bits");
- fe->flags = (fe->flags & ~(BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)) |
- bf_set_exp_bits(b);
- break;
- case FE_RNDMODE:
- b = bigfloat_get_rnd_mode(ctx, val);
- if (b < 0)
- return JS_EXCEPTION;
- fe->flags = (fe->flags & ~BF_RND_MASK) | b;
- break;
- case FE_SUBNORMAL:
- b = JS_ToBool(ctx, val);
- fe->flags = (fe->flags & ~BF_FLAG_SUBNORMAL) | (b ? BF_FLAG_SUBNORMAL: 0);
- break;
- default:
- b = JS_ToBool(ctx, val);
- fe->status = (fe->status & ~magic) & ((-b) & magic);
- break;
- }
- return JS_UNDEFINED;
-}
-
-static JSValue js_float_env_clearStatus(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSFloatEnv *fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV);
- if (!fe)
- return JS_EXCEPTION;
- fe->status = 0;
- return JS_UNDEFINED;
-}
-
-static const JSCFunctionListEntry js_float_env_funcs[] = {
- JS_CGETSET_DEF("prec", js_float_env_get_prec, NULL ),
- JS_CGETSET_DEF("expBits", js_float_env_get_expBits, NULL ),
- JS_CFUNC_DEF("setPrec", 2, js_float_env_setPrec ),
- JS_PROP_INT32_DEF("RNDN", BF_RNDN, 0 ),
- JS_PROP_INT32_DEF("RNDZ", BF_RNDZ, 0 ),
- JS_PROP_INT32_DEF("RNDU", BF_RNDU, 0 ),
- JS_PROP_INT32_DEF("RNDD", BF_RNDD, 0 ),
- JS_PROP_INT32_DEF("RNDNA", BF_RNDNA, 0 ),
- JS_PROP_INT32_DEF("RNDA", BF_RNDA, 0 ),
- JS_PROP_INT32_DEF("RNDF", BF_RNDF, 0 ),
- JS_PROP_INT32_DEF("precMin", BF_PREC_MIN, 0 ),
- JS_PROP_INT64_DEF("precMax", BF_PREC_MAX, 0 ),
- JS_PROP_INT32_DEF("expBitsMin", BF_EXP_BITS_MIN, 0 ),
- JS_PROP_INT32_DEF("expBitsMax", BF_EXP_BITS_MAX, 0 ),
-};
-
-static const JSCFunctionListEntry js_float_env_proto_funcs[] = {
- JS_CGETSET_MAGIC_DEF("prec", js_float_env_proto_get_status,
- js_float_env_proto_set_status, FE_PREC ),
- JS_CGETSET_MAGIC_DEF("expBits", js_float_env_proto_get_status,
- js_float_env_proto_set_status, FE_EXP ),
- JS_CGETSET_MAGIC_DEF("rndMode", js_float_env_proto_get_status,
- js_float_env_proto_set_status, FE_RNDMODE ),
- JS_CGETSET_MAGIC_DEF("subnormal", js_float_env_proto_get_status,
- js_float_env_proto_set_status, FE_SUBNORMAL ),
- JS_CGETSET_MAGIC_DEF("invalidOperation", js_float_env_proto_get_status,
- js_float_env_proto_set_status, BF_ST_INVALID_OP ),
- JS_CGETSET_MAGIC_DEF("divideByZero", js_float_env_proto_get_status,
- js_float_env_proto_set_status, BF_ST_DIVIDE_ZERO ),
- JS_CGETSET_MAGIC_DEF("overflow", js_float_env_proto_get_status,
- js_float_env_proto_set_status, BF_ST_OVERFLOW ),
- JS_CGETSET_MAGIC_DEF("underflow", js_float_env_proto_get_status,
- js_float_env_proto_set_status, BF_ST_UNDERFLOW ),
- JS_CGETSET_MAGIC_DEF("inexact", js_float_env_proto_get_status,
- js_float_env_proto_set_status, BF_ST_INEXACT ),
- JS_CFUNC_DEF("clearStatus", 0, js_float_env_clearStatus ),
-};
-
-void JS_AddIntrinsicBigFloat(JSContext *ctx)
-{
- JSRuntime *rt = ctx->rt;
- JSValueConst obj1;
-
- rt->bigfloat_ops.to_string = js_bigfloat_to_string;
- rt->bigfloat_ops.from_string = js_string_to_bigfloat;
- rt->bigfloat_ops.unary_arith = js_unary_arith_bigfloat;
- rt->bigfloat_ops.binary_arith = js_binary_arith_bigfloat;
- rt->bigfloat_ops.compare = js_compare_bigfloat;
- rt->bigfloat_ops.mul_pow10_to_float64 = js_mul_pow10_to_float64;
- rt->bigfloat_ops.mul_pow10 = js_mul_pow10;
-
- ctx->class_proto[JS_CLASS_BIG_FLOAT] = JS_NewObject(ctx);
- JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT],
- js_bigfloat_proto_funcs,
- countof(js_bigfloat_proto_funcs));
- obj1 = JS_NewGlobalCConstructor(ctx, "BigFloat", js_bigfloat_constructor, 1,
- ctx->class_proto[JS_CLASS_BIG_FLOAT]);
- JS_SetPropertyFunctionList(ctx, obj1, js_bigfloat_funcs,
- countof(js_bigfloat_funcs));
-
- ctx->class_proto[JS_CLASS_FLOAT_ENV] = JS_NewObject(ctx);
- JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_FLOAT_ENV],
- js_float_env_proto_funcs,
- countof(js_float_env_proto_funcs));
- obj1 = JS_NewGlobalCConstructorOnly(ctx, "BigFloatEnv",
- js_float_env_constructor, 1,
- ctx->class_proto[JS_CLASS_FLOAT_ENV]);
- JS_SetPropertyFunctionList(ctx, obj1, js_float_env_funcs,
- countof(js_float_env_funcs));
-}
-
-/* BigDecimal */
-
-static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,
- BOOL allow_null_or_undefined)
-{
- redo:
- switch(JS_VALUE_GET_NORM_TAG(val)) {
- case JS_TAG_BIG_DECIMAL:
- break;
- case JS_TAG_NULL:
- if (!allow_null_or_undefined)
- goto fail;
- /* fall thru */
- case JS_TAG_BOOL:
- case JS_TAG_INT:
- {
- bfdec_t *r;
- int32_t v = JS_VALUE_GET_INT(val);
-
- val = JS_NewBigDecimal(ctx);
- if (JS_IsException(val))
- break;
- r = JS_GetBigDecimal(val);
- if (bfdec_set_si(r, v)) {
- JS_FreeValue(ctx, val);
- val = JS_EXCEPTION;
- break;
- }
- }
- break;
- case JS_TAG_FLOAT64:
- case JS_TAG_BIG_INT:
- case JS_TAG_BIG_FLOAT:
- val = JS_ToStringFree(ctx, val);
- if (JS_IsException(val))
- break;
- goto redo;
- case JS_TAG_STRING:
- {
- const char *str, *p;
- size_t len;
- int err;
-
- str = JS_ToCStringLen(ctx, &len, val);
- JS_FreeValue(ctx, val);
- if (!str)
- return JS_EXCEPTION;
- p = str;
- p += skip_spaces(p);
- if ((p - str) == len) {
- bfdec_t *r;
- val = JS_NewBigDecimal(ctx);
- if (JS_IsException(val))
- break;
- r = JS_GetBigDecimal(val);
- bfdec_set_zero(r, 0);
- err = 0;
- } else {
- val = js_atof(ctx, p, &p, 0, ATOD_TYPE_BIG_DECIMAL);
- if (JS_IsException(val)) {
- JS_FreeCString(ctx, str);
- return JS_EXCEPTION;
- }
- p += skip_spaces(p);
- err = ((p - str) != len);
- }
- JS_FreeCString(ctx, str);
- if (err) {
- JS_FreeValue(ctx, val);
- return JS_ThrowSyntaxError(ctx, "invalid bigdecimal literal");
- }
- }
- break;
- case JS_TAG_OBJECT:
- val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);
- if (JS_IsException(val))
- break;
- goto redo;
- case JS_TAG_UNDEFINED:
- {
- bfdec_t *r;
- if (!allow_null_or_undefined)
- goto fail;
- val = JS_NewBigDecimal(ctx);
- if (JS_IsException(val))
- break;
- r = JS_GetBigDecimal(val);
- bfdec_set_nan(r);
- }
- break;
- default:
- fail:
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert to bigdecimal");
- }
- return val;
-}
-
-static JSValue js_bigdecimal_constructor(JSContext *ctx,
- JSValueConst new_target,
- int argc, JSValueConst *argv)
-{
- JSValue val;
- if (!JS_IsUndefined(new_target))
- return JS_ThrowTypeError(ctx, "not a constructor");
- if (argc == 0) {
- bfdec_t *r;
- val = JS_NewBigDecimal(ctx);
- if (JS_IsException(val))
- return val;
- r = JS_GetBigDecimal(val);
- bfdec_set_zero(r, 0);
- } else {
- val = JS_ToBigDecimalFree(ctx, JS_DupValue(ctx, argv[0]), FALSE);
- }
- return val;
-}
-
-static JSValue js_thisBigDecimalValue(JSContext *ctx, JSValueConst this_val)
-{
- if (JS_IsBigDecimal(this_val))
- return JS_DupValue(ctx, this_val);
-
- if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
- JSObject *p = JS_VALUE_GET_OBJ(this_val);
- if (p->class_id == JS_CLASS_BIG_DECIMAL) {
- if (JS_IsBigDecimal(p->u.object_data))
- return JS_DupValue(ctx, p->u.object_data);
- }
- }
- return JS_ThrowTypeError(ctx, "not a bigdecimal");
-}
-
-static JSValue js_bigdecimal_toString(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue val;
-
- val = js_thisBigDecimalValue(ctx, this_val);
- if (JS_IsException(val))
- return val;
- return JS_ToStringFree(ctx, val);
-}
-
-static JSValue js_bigdecimal_valueOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return js_thisBigDecimalValue(ctx, this_val);
-}
-
-static int js_bigdecimal_get_rnd_mode(JSContext *ctx, JSValueConst obj)
-{
- const char *str;
- size_t size;
- int rnd_mode;
-
- str = JS_ToCStringLen(ctx, &size, obj);
- if (!str)
- return -1;
- if (strlen(str) != size)
- goto invalid_rounding_mode;
- if (!strcmp(str, "floor")) {
- rnd_mode = BF_RNDD;
- } else if (!strcmp(str, "ceiling")) {
- rnd_mode = BF_RNDU;
- } else if (!strcmp(str, "down")) {
- rnd_mode = BF_RNDZ;
- } else if (!strcmp(str, "up")) {
- rnd_mode = BF_RNDA;
- } else if (!strcmp(str, "half-even")) {
- rnd_mode = BF_RNDN;
- } else if (!strcmp(str, "half-up")) {
- rnd_mode = BF_RNDNA;
- } else {
- invalid_rounding_mode:
- JS_FreeCString(ctx, str);
- JS_ThrowTypeError(ctx, "invalid rounding mode");
- return -1;
- }
- JS_FreeCString(ctx, str);
- return rnd_mode;
-}
-
-typedef struct {
- int64_t prec;
- bf_flags_t flags;
-} BigDecimalEnv;
-
-static int js_bigdecimal_get_env(JSContext *ctx, BigDecimalEnv *fe,
- JSValueConst obj)
-{
- JSValue prop;
- int64_t val;
- BOOL has_prec;
- int rnd_mode;
-
- if (!JS_IsObject(obj)) {
- JS_ThrowTypeErrorNotAnObject(ctx);
- return -1;
- }
- prop = JS_GetProperty(ctx, obj, JS_ATOM_roundingMode);
- if (JS_IsException(prop))
- return -1;
- rnd_mode = js_bigdecimal_get_rnd_mode(ctx, prop);
- JS_FreeValue(ctx, prop);
- if (rnd_mode < 0)
- return -1;
- fe->flags = rnd_mode;
-
- prop = JS_GetProperty(ctx, obj, JS_ATOM_maximumSignificantDigits);
- if (JS_IsException(prop))
- return -1;
- has_prec = FALSE;
- if (!JS_IsUndefined(prop)) {
- if (JS_ToInt64SatFree(ctx, &val, prop))
- return -1;
- if (val < 1 || val > BF_PREC_MAX)
- goto invalid_precision;
- fe->prec = val;
- has_prec = TRUE;
- }
-
- prop = JS_GetProperty(ctx, obj, JS_ATOM_maximumFractionDigits);
- if (JS_IsException(prop))
- return -1;
- if (!JS_IsUndefined(prop)) {
- if (has_prec) {
- JS_FreeValue(ctx, prop);
- JS_ThrowTypeError(ctx, "cannot provide both maximumSignificantDigits and maximumFractionDigits");
- return -1;
- }
- if (JS_ToInt64SatFree(ctx, &val, prop))
- return -1;
- if (val < 0 || val > BF_PREC_MAX) {
- invalid_precision:
- JS_ThrowTypeError(ctx, "invalid precision");
- return -1;
- }
- fe->prec = val;
- fe->flags |= BF_FLAG_RADPNT_PREC;
- has_prec = TRUE;
- }
- if (!has_prec) {
- JS_ThrowTypeError(ctx, "precision must be present");
- return -1;
- }
- return 0;
-}
-
-
-static JSValue js_bigdecimal_fop(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
-{
- bfdec_t *a, *b, r_s, *r = &r_s;
- JSValue op1, op2, res;
- BigDecimalEnv fe_s, *fe = &fe_s;
- int op_count, ret;
-
- if (magic == MATH_OP_SQRT ||
- magic == MATH_OP_ROUND)
- op_count = 1;
- else
- op_count = 2;
-
- op1 = JS_ToNumeric(ctx, argv[0]);
- if (JS_IsException(op1))
- return op1;
- a = JS_ToBigDecimal(ctx, op1);
- if (!a) {
- JS_FreeValue(ctx, op1);
- return JS_EXCEPTION;
- }
- if (op_count >= 2) {
- op2 = JS_ToNumeric(ctx, argv[1]);
- if (JS_IsException(op2)) {
- JS_FreeValue(ctx, op1);
- return op2;
- }
- b = JS_ToBigDecimal(ctx, op2);
- if (!b)
- goto fail;
- } else {
- op2 = JS_UNDEFINED;
- b = NULL;
- }
- fe->flags = BF_RNDZ;
- fe->prec = BF_PREC_INF;
- if (op_count < argc) {
- if (js_bigdecimal_get_env(ctx, fe, argv[op_count]))
- goto fail;
- }
-
- res = JS_NewBigDecimal(ctx);
- if (JS_IsException(res)) {
- fail:
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- return JS_EXCEPTION;
- }
- r = JS_GetBigDecimal(res);
- switch (magic) {
- case MATH_OP_ADD:
- ret = bfdec_add(r, a, b, fe->prec, fe->flags);
- break;
- case MATH_OP_SUB:
- ret = bfdec_sub(r, a, b, fe->prec, fe->flags);
- break;
- case MATH_OP_MUL:
- ret = bfdec_mul(r, a, b, fe->prec, fe->flags);
- break;
- case MATH_OP_DIV:
- ret = bfdec_div(r, a, b, fe->prec, fe->flags);
- break;
- case MATH_OP_FMOD:
- ret = bfdec_rem(r, a, b, fe->prec, fe->flags, BF_RNDZ);
- break;
- case MATH_OP_SQRT:
- ret = bfdec_sqrt(r, a, fe->prec, fe->flags);
- break;
- case MATH_OP_ROUND:
- ret = bfdec_set(r, a);
- if (!(ret & BF_ST_MEM_ERROR))
- ret = bfdec_round(r, fe->prec, fe->flags);
- break;
- default:
- abort();
- }
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- ret &= BF_ST_MEM_ERROR | BF_ST_DIVIDE_ZERO | BF_ST_INVALID_OP |
- BF_ST_OVERFLOW;
- if (ret != 0) {
- JS_FreeValue(ctx, res);
- return throw_bf_exception(ctx, ret);
- } else {
- return res;
- }
-}
-
-static JSValue js_bigdecimal_toFixed(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue val, ret;
- int64_t f;
- int rnd_mode;
-
- val = js_thisBigDecimalValue(ctx, this_val);
- if (JS_IsException(val))
- return val;
- if (JS_ToInt64Sat(ctx, &f, argv[0]))
- goto fail;
- if (f < 0 || f > BF_PREC_MAX) {
- JS_ThrowRangeError(ctx, "invalid number of digits");
- goto fail;
- }
- rnd_mode = BF_RNDNA;
- if (argc > 1) {
- rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]);
- if (rnd_mode < 0)
- goto fail;
- }
- ret = js_bigdecimal_to_string1(ctx, val, f, rnd_mode | BF_FTOA_FORMAT_FRAC);
- JS_FreeValue(ctx, val);
- return ret;
- fail:
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
-}
-
-static JSValue js_bigdecimal_toExponential(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue val, ret;
- int64_t f;
- int rnd_mode;
-
- val = js_thisBigDecimalValue(ctx, this_val);
- if (JS_IsException(val))
- return val;
- if (JS_ToInt64Sat(ctx, &f, argv[0]))
- goto fail;
- if (JS_IsUndefined(argv[0])) {
- ret = js_bigdecimal_to_string1(ctx, val, 0,
- BF_RNDN | BF_FTOA_FORMAT_FREE_MIN | BF_FTOA_FORCE_EXP);
- } else {
- if (f < 0 || f > BF_PREC_MAX) {
- JS_ThrowRangeError(ctx, "invalid number of digits");
- goto fail;
- }
- rnd_mode = BF_RNDNA;
- if (argc > 1) {
- rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]);
- if (rnd_mode < 0)
- goto fail;
- }
- ret = js_bigdecimal_to_string1(ctx, val, f + 1,
- rnd_mode | BF_FTOA_FORMAT_FIXED | BF_FTOA_FORCE_EXP);
- }
- JS_FreeValue(ctx, val);
- return ret;
- fail:
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
-}
-
-static JSValue js_bigdecimal_toPrecision(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue val, ret;
- int64_t p;
- int rnd_mode;
-
- val = js_thisBigDecimalValue(ctx, this_val);
- if (JS_IsException(val))
- return val;
- if (JS_IsUndefined(argv[0])) {
- return JS_ToStringFree(ctx, val);
- }
- if (JS_ToInt64Sat(ctx, &p, argv[0]))
- goto fail;
- if (p < 1 || p > BF_PREC_MAX) {
- JS_ThrowRangeError(ctx, "invalid number of digits");
- goto fail;
- }
- rnd_mode = BF_RNDNA;
- if (argc > 1) {
- rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]);
- if (rnd_mode < 0)
- goto fail;
- }
- ret = js_bigdecimal_to_string1(ctx, val, p,
- rnd_mode | BF_FTOA_FORMAT_FIXED);
- JS_FreeValue(ctx, val);
- return ret;
- fail:
- JS_FreeValue(ctx, val);
- return JS_EXCEPTION;
-}
-
-static const JSCFunctionListEntry js_bigdecimal_proto_funcs[] = {
- JS_CFUNC_DEF("toString", 0, js_bigdecimal_toString ),
- JS_CFUNC_DEF("valueOf", 0, js_bigdecimal_valueOf ),
- JS_CFUNC_DEF("toPrecision", 1, js_bigdecimal_toPrecision ),
- JS_CFUNC_DEF("toFixed", 1, js_bigdecimal_toFixed ),
- JS_CFUNC_DEF("toExponential", 1, js_bigdecimal_toExponential ),
-};
-
-static const JSCFunctionListEntry js_bigdecimal_funcs[] = {
- JS_CFUNC_MAGIC_DEF("add", 2, js_bigdecimal_fop, MATH_OP_ADD ),
- JS_CFUNC_MAGIC_DEF("sub", 2, js_bigdecimal_fop, MATH_OP_SUB ),
- JS_CFUNC_MAGIC_DEF("mul", 2, js_bigdecimal_fop, MATH_OP_MUL ),
- JS_CFUNC_MAGIC_DEF("div", 2, js_bigdecimal_fop, MATH_OP_DIV ),
- JS_CFUNC_MAGIC_DEF("mod", 2, js_bigdecimal_fop, MATH_OP_FMOD ),
- JS_CFUNC_MAGIC_DEF("round", 1, js_bigdecimal_fop, MATH_OP_ROUND ),
- JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigdecimal_fop, MATH_OP_SQRT ),
-};
-
-void JS_AddIntrinsicBigDecimal(JSContext *ctx)
-{
- JSRuntime *rt = ctx->rt;
- JSValueConst obj1;
-
- rt->bigdecimal_ops.to_string = js_bigdecimal_to_string;
- rt->bigdecimal_ops.from_string = js_string_to_bigdecimal;
- rt->bigdecimal_ops.unary_arith = js_unary_arith_bigdecimal;
- rt->bigdecimal_ops.binary_arith = js_binary_arith_bigdecimal;
- rt->bigdecimal_ops.compare = js_compare_bigdecimal;
-
- ctx->class_proto[JS_CLASS_BIG_DECIMAL] = JS_NewObject(ctx);
- JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL],
- js_bigdecimal_proto_funcs,
- countof(js_bigdecimal_proto_funcs));
- obj1 = JS_NewGlobalCConstructor(ctx, "BigDecimal",
- js_bigdecimal_constructor, 1,
- ctx->class_proto[JS_CLASS_BIG_DECIMAL]);
- JS_SetPropertyFunctionList(ctx, obj1, js_bigdecimal_funcs,
- countof(js_bigdecimal_funcs));
-}
-
-void JS_EnableBignumExt(JSContext *ctx, BOOL enable)
-{
- ctx->bignum_ext = enable;
-}
-
-#endif /* CONFIG_BIGNUM */
-
static const char * const native_error_name[JS_NATIVE_ERROR_COUNT] = {
"EvalError", "RangeError", "ReferenceError",
"SyntaxError", "TypeError", "URIError",
@@ -52833,18 +51474,8 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx)
ctx->function_proto = JS_NewCFunction3(ctx, js_function_proto, "", 0,
JS_CFUNC_generic, 0,
ctx->class_proto[JS_CLASS_OBJECT]);
- ctx->class_proto[JS_CLASS_BYTECODE_FUNCTION] = JS_DupValue(ctx, ctx->function_proto);
+ ctx->class_proto[JS_CLASS_BYTECODE_FUNCTION] = js_dup(ctx->function_proto);
ctx->class_proto[JS_CLASS_ERROR] = JS_NewObject(ctx);
-#if 0
- /* these are auto-initialized from js_error_proto_funcs,
- but delaying might be a problem */
- JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ERROR], JS_ATOM_name,
- JS_AtomToString(ctx, JS_ATOM_Error),
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ERROR], JS_ATOM_message,
- JS_AtomToString(ctx, JS_ATOM_empty_string),
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
-#endif
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ERROR],
js_error_proto_funcs,
countof(js_error_proto_funcs));
@@ -52881,7 +51512,7 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx)
void JS_AddIntrinsicBaseObjects(JSContext *ctx)
{
int i;
- JSValueConst obj, number_obj;
+ JSValue obj, number_obj;
JSValue obj1;
ctx->throw_type_error = JS_NewCFunction(ctx, js_throw_type_error, NULL, 0);
@@ -52897,7 +51528,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_PROP_HAS_GET | JS_PROP_HAS_SET |
JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);
JS_FreeValue(ctx, obj1);
- JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, (JSValueConst *)&ctx->throw_type_error, 1));
+ JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, &ctx->throw_type_error, 1));
ctx->global_obj = JS_NewObject(ctx);
ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL);
@@ -52914,14 +51545,15 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
ctx->function_ctor = JS_NewCFunctionMagic(ctx, js_function_constructor,
"Function", 1, JS_CFUNC_constructor_or_func_magic,
JS_FUNC_NORMAL);
- JS_NewGlobalCConstructor2(ctx, JS_DupValue(ctx, ctx->function_ctor), "Function",
+ JS_NewGlobalCConstructor2(ctx, js_dup(ctx->function_ctor), "Function",
ctx->function_proto);
/* Error */
- obj1 = JS_NewCFunctionMagic(ctx, js_error_constructor,
- "Error", 1, JS_CFUNC_constructor_or_func_magic, -1);
- JS_NewGlobalCConstructor2(ctx, obj1,
+ ctx->error_ctor = JS_NewCFunctionMagic(ctx, js_error_constructor,
+ "Error", 1, JS_CFUNC_constructor_or_func_magic, -1);
+ JS_NewGlobalCConstructor2(ctx, js_dup(ctx->error_ctor),
"Error", ctx->class_proto[JS_CLASS_ERROR]);
+ JS_SetPropertyFunctionList(ctx, ctx->error_ctor, js_error_funcs, countof(js_error_funcs));
/* Used to squelch a -Wcast-function-type warning. */
JSCFunctionType ft = { .generic_magic = js_error_constructor };
@@ -52931,16 +51563,36 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
n_args = 1 + (i == JS_AGGREGATE_ERROR);
func_obj = JS_NewCFunction3(ctx, ft.generic,
native_error_name[i], n_args,
- JS_CFUNC_constructor_or_func_magic, i, obj1);
+ JS_CFUNC_constructor_or_func_magic, i,
+ ctx->error_ctor);
JS_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i],
ctx->native_error_proto[i]);
}
- /* Iterator prototype */
- ctx->iterator_proto = JS_NewObject(ctx);
- JS_SetPropertyFunctionList(ctx, ctx->iterator_proto,
+ /* CallSite */
+ _JS_AddIntrinsicCallSite(ctx);
+
+ /* Iterator */
+ ctx->class_proto[JS_CLASS_ITERATOR] = JS_NewObject(ctx);
+ JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR],
js_iterator_proto_funcs,
countof(js_iterator_proto_funcs));
+ obj = JS_NewGlobalCConstructor(ctx, "Iterator", js_iterator_constructor, 0,
+ ctx->class_proto[JS_CLASS_ITERATOR]);
+ ctx->iterator_ctor = js_dup(obj);
+ JS_SetPropertyFunctionList(ctx, obj,
+ js_iterator_funcs,
+ countof(js_iterator_funcs));
+
+ ctx->class_proto[JS_CLASS_ITERATOR_HELPER] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
+ JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_HELPER],
+ js_iterator_helper_proto_funcs,
+ countof(js_iterator_helper_proto_funcs));
+
+ ctx->class_proto[JS_CLASS_ITERATOR_WRAP] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
+ JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_WRAP],
+ js_iterator_wrap_proto_funcs,
+ countof(js_iterator_wrap_proto_funcs));
/* Array */
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY],
@@ -52949,7 +51601,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
obj = JS_NewGlobalCConstructor(ctx, "Array", js_array_constructor, 1,
ctx->class_proto[JS_CLASS_ARRAY]);
- ctx->array_ctor = JS_DupValue(ctx, obj);
+ ctx->array_ctor = js_dup(obj);
JS_SetPropertyFunctionList(ctx, obj, js_array_funcs,
countof(js_array_funcs));
@@ -52986,7 +51638,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
ctx->array_proto_values =
JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_values);
- ctx->class_proto[JS_CLASS_ARRAY_ITERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto);
+ ctx->class_proto[JS_CLASS_ARRAY_ITERATOR] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY_ITERATOR],
js_array_iterator_proto_funcs,
countof(js_array_iterator_proto_funcs));
@@ -53000,7 +51652,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
/* Number */
ctx->class_proto[JS_CLASS_NUMBER] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],
JS_CLASS_NUMBER);
- JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_NUMBER], JS_NewInt32(ctx, 0));
+ JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_NUMBER], js_int32(0));
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_NUMBER],
js_number_proto_funcs,
countof(js_number_proto_funcs));
@@ -53011,7 +51663,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
/* Boolean */
ctx->class_proto[JS_CLASS_BOOLEAN] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],
JS_CLASS_BOOLEAN);
- JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], JS_NewBool(ctx, FALSE));
+ JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], JS_FALSE);
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], js_boolean_proto_funcs,
countof(js_boolean_proto_funcs));
JS_NewGlobalCConstructor(ctx, "Boolean", js_boolean_constructor, 1,
@@ -53028,7 +51680,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_funcs,
countof(js_string_proto_funcs));
- ctx->class_proto[JS_CLASS_STRING_ITERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto);
+ ctx->class_proto[JS_CLASS_STRING_ITERATOR] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING_ITERATOR],
js_string_iterator_proto_funcs,
countof(js_string_iterator_proto_funcs));
@@ -53060,7 +51712,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
}
/* ES6 Generator */
- ctx->class_proto[JS_CLASS_GENERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto);
+ ctx->class_proto[JS_CLASS_GENERATOR] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_GENERATOR],
js_generator_proto_funcs,
countof(js_generator_proto_funcs));
@@ -53083,11 +51735,11 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
/* global properties */
ctx->eval_obj = JS_NewCFunction(ctx, js_global_eval, "eval", 1);
JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_eval,
- JS_DupValue(ctx, ctx->eval_obj),
+ js_dup(ctx->eval_obj),
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis,
- JS_DupValue(ctx, ctx->global_obj),
+ js_dup(ctx->global_obj),
JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
}
@@ -53095,21 +51747,30 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT] = {
0, 0, 0, 1, 1, 2, 2,
- 3, 3, /* BigInt64Array, BigUint64Array */
- 2, 3
+ 3, 3, // BigInt64Array, BigUint64Array
+ 1, 2, 3 // Float16Array, Float32Array, Float64Array
};
static JSValue js_array_buffer_constructor3(JSContext *ctx,
- JSValueConst new_target,
- uint64_t len, JSClassID class_id,
+ JSValue new_target,
+ uint64_t len, uint64_t *max_len,
+ JSClassID class_id,
uint8_t *buf,
JSFreeArrayBufferDataFunc *free_func,
- void *opaque, BOOL alloc_flag)
+ void *opaque, bool alloc_flag)
{
JSRuntime *rt = ctx->rt;
JSValue obj;
JSArrayBuffer *abuf = NULL;
+ uint64_t sab_alloc_len;
+ if (!alloc_flag && buf && max_len && free_func != js_array_buffer_free) {
+ // not observable from JS land, only through C API misuse;
+ // JS code cannot create externally managed buffers directly
+ return JS_ThrowInternalError(ctx,
+ "resizable ArrayBuffers not supported "
+ "for externally managed buffers");
+ }
obj = js_create_from_ctor(ctx, new_target, class_id);
if (JS_IsException(obj))
return obj;
@@ -53118,18 +51779,26 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx,
JS_ThrowRangeError(ctx, "invalid array buffer length");
goto fail;
}
+ if (max_len && *max_len > INT32_MAX) {
+ JS_ThrowRangeError(ctx, "invalid max array buffer length");
+ goto fail;
+ }
abuf = js_malloc(ctx, sizeof(*abuf));
if (!abuf)
goto fail;
abuf->byte_length = len;
+ abuf->max_byte_length = max_len ? *max_len : -1;
if (alloc_flag) {
if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER &&
rt->sab_funcs.sab_alloc) {
+ // TOOD(bnoordhuis) resizing backing memory for SABs atomically
+ // is hard so we cheat and allocate |maxByteLength| bytes upfront
+ sab_alloc_len = max_len ? *max_len : len;
abuf->data = rt->sab_funcs.sab_alloc(rt->sab_funcs.sab_opaque,
- max_int(len, 1));
+ max_int(sab_alloc_len, 1));
if (!abuf->data)
goto fail;
- memset(abuf->data, 0, len);
+ memset(abuf->data, 0, sab_alloc_len);
} else {
/* the allocation must be done after the object creation */
abuf->data = js_mallocz(ctx, max_int(len, 1));
@@ -53144,13 +51813,13 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx,
abuf->data = buf;
}
init_list_head(&abuf->array_list);
- abuf->detached = FALSE;
+ abuf->detached = false;
abuf->shared = (class_id == JS_CLASS_SHARED_ARRAY_BUFFER);
abuf->opaque = opaque;
abuf->free_func = free_func;
if (alloc_flag && buf)
memcpy(abuf->data, buf, len);
- JS_SetOpaque(obj, abuf);
+ JS_SetOpaqueInternal(obj, abuf);
return obj;
fail:
JS_FreeValue(ctx, obj);
@@ -53164,59 +51833,94 @@ static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr)
}
static JSValue js_array_buffer_constructor2(JSContext *ctx,
- JSValueConst new_target,
- uint64_t len, JSClassID class_id)
+ JSValue new_target,
+ uint64_t len, uint64_t *max_len,
+ JSClassID class_id)
{
- return js_array_buffer_constructor3(ctx, new_target, len, class_id,
- NULL, js_array_buffer_free, NULL,
- TRUE);
+ return js_array_buffer_constructor3(ctx, new_target, len, max_len,
+ class_id, NULL, js_array_buffer_free,
+ NULL, true);
}
static JSValue js_array_buffer_constructor1(JSContext *ctx,
- JSValueConst new_target,
- uint64_t len)
+ JSValue new_target,
+ uint64_t len, uint64_t *max_len)
{
- return js_array_buffer_constructor2(ctx, new_target, len,
+ return js_array_buffer_constructor2(ctx, new_target, len, max_len,
JS_CLASS_ARRAY_BUFFER);
}
JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
JSFreeArrayBufferDataFunc *free_func, void *opaque,
- BOOL is_shared)
+ bool is_shared)
{
- return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len,
- is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER,
- buf, free_func, opaque, FALSE);
+ JSClassID class_id =
+ is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER;
+ return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL, class_id,
+ buf, free_func, opaque, false);
+}
+
+bool JS_IsArrayBuffer(JSValue obj) {
+ return JS_GetClassID(obj) == JS_CLASS_ARRAY_BUFFER;
}
/* create a new ArrayBuffer of length 'len' and copy 'buf' to it */
JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len)
{
- return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len,
+ return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL,
JS_CLASS_ARRAY_BUFFER,
(uint8_t *)buf,
js_array_buffer_free, NULL,
- TRUE);
+ true);
}
-static JSValue js_array_buffer_constructor(JSContext *ctx,
- JSValueConst new_target,
- int argc, JSValueConst *argv)
+static JSValue js_array_buffer_constructor0(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv,
+ JSClassID class_id)
{
- uint64_t len;
+ uint64_t len, max_len, *pmax_len = NULL;
+ JSValue obj, val;
+ int64_t i;
+
if (JS_ToIndex(ctx, &len, argv[0]))
return JS_EXCEPTION;
- return js_array_buffer_constructor1(ctx, new_target, len);
+ if (argc < 2)
+ goto next;
+ if (!JS_IsObject(argv[1]))
+ goto next;
+ obj = JS_ToObject(ctx, argv[1]);
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+ val = JS_GetProperty(ctx, obj, JS_ATOM_maxByteLength);
+ JS_FreeValue(ctx, obj);
+ if (JS_IsException(val))
+ return JS_EXCEPTION;
+ if (JS_IsUndefined(val))
+ goto next;
+ if (JS_ToInt64Free(ctx, &i, val))
+ return JS_EXCEPTION;
+ // don't have to check i < 0 because len >= 0
+ if (len > i || i > MAX_SAFE_INTEGER)
+ return JS_ThrowRangeError(ctx, "invalid array buffer max length");
+ max_len = i;
+ pmax_len = &max_len;
+next:
+ return js_array_buffer_constructor2(ctx, new_target, len, pmax_len,
+ class_id);
+}
+
+static JSValue js_array_buffer_constructor(JSContext *ctx, JSValue new_target,
+ int argc, JSValue *argv)
+{
+ return js_array_buffer_constructor0(ctx, new_target, argc, argv,
+ JS_CLASS_ARRAY_BUFFER);
}
static JSValue js_shared_array_buffer_constructor(JSContext *ctx,
- JSValueConst new_target,
- int argc, JSValueConst *argv)
+ JSValue new_target,
+ int argc, JSValue *argv)
{
- uint64_t len;
- if (JS_ToIndex(ctx, &len, argv[0]))
- return JS_EXCEPTION;
- return js_array_buffer_constructor2(ctx, new_target, len,
+ return js_array_buffer_constructor0(ctx, new_target, argc, argv,
JS_CLASS_SHARED_ARRAY_BUFFER);
}
@@ -53256,20 +51960,17 @@ static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val)
}
static JSValue js_array_buffer_isView(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv)
+ JSValue this_val,
+ int argc, JSValue *argv)
{
JSObject *p;
- BOOL res;
- res = FALSE;
+
if (JS_VALUE_GET_TAG(argv[0]) == JS_TAG_OBJECT) {
p = JS_VALUE_GET_OBJ(argv[0]);
- if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_DATAVIEW) {
- res = TRUE;
- }
+ return js_bool(is_typed_array(p->class_id) ||
+ p->class_id == JS_CLASS_DATAVIEW);
}
- return JS_NewBool(ctx, res);
+ return JS_FALSE;
}
static const JSCFunctionListEntry js_array_buffer_funcs[] = {
@@ -53282,18 +51983,56 @@ static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx)
return JS_ThrowTypeError(ctx, "ArrayBuffer is detached");
}
+static JSValue JS_ThrowTypeErrorArrayBufferOOB(JSContext *ctx)
+{
+ return JS_ThrowTypeError(ctx, "ArrayBuffer is detached or resized");
+}
+
+// #sec-get-arraybuffer.prototype.detached
+static JSValue js_array_buffer_get_detached(JSContext *ctx,
+ JSValue this_val)
+{
+ JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_BUFFER);
+ if (!abuf)
+ return JS_EXCEPTION;
+ if (abuf->shared)
+ return JS_ThrowTypeError(ctx, "detached called on SharedArrayBuffer");
+ return js_bool(abuf->detached);
+}
+
static JSValue js_array_buffer_get_byteLength(JSContext *ctx,
- JSValueConst this_val,
+ JSValue this_val,
int class_id)
{
JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id);
if (!abuf)
return JS_EXCEPTION;
/* return 0 if detached */
- return JS_NewUint32(ctx, abuf->byte_length);
+ return js_uint32(abuf->byte_length);
+}
+
+static JSValue js_array_buffer_get_maxByteLength(JSContext *ctx,
+ JSValue this_val,
+ int class_id)
+{
+ JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id);
+ if (!abuf)
+ return JS_EXCEPTION;
+ if (array_buffer_is_resizable(abuf))
+ return js_uint32(abuf->max_byte_length);
+ return js_uint32(abuf->byte_length);
+}
+
+static JSValue js_array_buffer_get_resizable(JSContext *ctx, JSValue this_val,
+ int class_id)
+{
+ JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id);
+ if (!abuf)
+ return JS_EXCEPTION;
+ return js_bool(array_buffer_is_resizable(abuf));
}
-void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj)
+void JS_DetachArrayBuffer(JSContext *ctx, JSValue obj)
{
JSArrayBuffer *abuf = JS_GetOpaque(obj, JS_CLASS_ARRAY_BUFFER);
struct list_head *el;
@@ -53304,7 +52043,7 @@ void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj)
abuf->free_func(ctx->rt, abuf->opaque, abuf->data);
abuf->data = NULL;
abuf->byte_length = 0;
- abuf->detached = TRUE;
+ abuf->detached = true;
list_for_each(el, &abuf->array_list) {
JSTypedArray *ta;
@@ -53321,7 +52060,7 @@ void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj)
}
/* get an ArrayBuffer or SharedArrayBuffer */
-static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj)
+static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValue obj)
{
JSObject *p;
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
@@ -53338,7 +52077,7 @@ static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj)
/* return NULL if exception. WARNING: any JS call can detach the
buffer and render the returned pointer invalid */
-uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj)
+uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValue obj)
{
JSArrayBuffer *abuf = js_get_array_buffer(ctx, obj);
if (!abuf)
@@ -53354,9 +52093,148 @@ uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj)
return NULL;
}
+static bool array_buffer_is_resizable(const JSArrayBuffer *abuf)
+{
+ return abuf->max_byte_length >= 0;
+}
+
+// ES #sec-arraybuffer.prototype.transfer
+static JSValue js_array_buffer_transfer(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
+{
+ bool transfer_to_fixed_length = magic & 1;
+ JSArrayBuffer *abuf;
+ uint64_t new_len, old_len, max_len, *pmax_len;
+ uint8_t *bs, *new_bs;
+
+ abuf = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_BUFFER);
+ if (!abuf)
+ return JS_EXCEPTION;
+ if (abuf->shared)
+ return JS_ThrowTypeError(ctx, "cannot transfer a SharedArrayBuffer");
+ if (argc < 1 || JS_IsUndefined(argv[0]))
+ new_len = abuf->byte_length;
+ else if (JS_ToIndex(ctx, &new_len, argv[0]))
+ return JS_EXCEPTION;
+ if (abuf->detached)
+ return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ pmax_len = NULL;
+ if (!transfer_to_fixed_length) {
+ if (array_buffer_is_resizable(abuf)) { // carry over maxByteLength
+ max_len = abuf->max_byte_length;
+ if (new_len > max_len)
+ return JS_ThrowTypeError(ctx, "invalid array buffer length");
+ // TODO(bnoordhuis) support externally managed RABs
+ if (abuf->free_func == js_array_buffer_free)
+ pmax_len = &max_len;
+ }
+ }
+ /* create an empty AB */
+ if (new_len == 0) {
+ JS_DetachArrayBuffer(ctx, this_val);
+ return js_array_buffer_constructor2(ctx, JS_UNDEFINED, 0, pmax_len,
+ JS_CLASS_ARRAY_BUFFER);
+ }
+ bs = abuf->data;
+ old_len = abuf->byte_length;
+ /* if length mismatch, realloc. Otherwise, use the same backing buffer. */
+ if (new_len != old_len) {
+ new_bs = js_realloc(ctx, bs, new_len);
+ if (!new_bs)
+ return JS_EXCEPTION;
+ bs = new_bs;
+ if (new_len > old_len)
+ memset(bs + old_len, 0, new_len - old_len);
+ }
+ /* neuter the backing buffer */
+ abuf->data = NULL;
+ abuf->byte_length = 0;
+ abuf->detached = true;
+ return js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len, pmax_len,
+ JS_CLASS_ARRAY_BUFFER,
+ bs, abuf->free_func,
+ NULL, false);
+}
+
+static JSValue js_array_buffer_resize(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int class_id)
+{
+ uint32_t size_log2, size_elem;
+ struct list_head *el;
+ JSArrayBuffer *abuf;
+ JSTypedArray *ta;
+ JSObject *p;
+ uint8_t *data;
+ int64_t len;
+
+ abuf = JS_GetOpaque2(ctx, this_val, class_id);
+ if (!abuf)
+ return JS_EXCEPTION;
+ if (JS_ToInt64(ctx, &len, argv[0]))
+ return JS_EXCEPTION;
+ if (abuf->detached)
+ return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ if (!array_buffer_is_resizable(abuf))
+ return JS_ThrowTypeError(ctx, "array buffer is not resizable");
+ // TODO(bnoordhuis) support externally managed RABs
+ if (abuf->free_func != js_array_buffer_free)
+ return JS_ThrowTypeError(ctx, "external array buffer is not resizable");
+ if (len < 0 || len > abuf->max_byte_length) {
+ bad_length:
+ return JS_ThrowRangeError(ctx, "invalid array buffer length");
+ }
+ // SABs can only grow and we don't need to realloc because
+ // js_array_buffer_constructor3 commits all memory upfront;
+ // regular RABs are resizable both ways and realloc
+ if (abuf->shared) {
+ if (len < abuf->byte_length)
+ goto bad_length;
+ // Note this is off-spec; there's supposed to be a single atomic
+ // |byteLength| property that's shared across SABs but we store
+ // it per SAB instead. That means when thread A calls sab.grow(2)
+ // at time t0, and thread B calls sab.grow(1) at time t1, we don't
+ // throw a TypeError in thread B as the spec says we should,
+ // instead both threads get their own view of the backing memory,
+ // 2 bytes big in A, and 1 byte big in B
+ abuf->byte_length = len;
+ } else {
+ data = js_realloc(ctx, abuf->data, max_int(len, 1));
+ if (!data)
+ return JS_EXCEPTION;
+ if (len > abuf->byte_length)
+ memset(&data[abuf->byte_length], 0, len - abuf->byte_length);
+ abuf->byte_length = len;
+ abuf->data = data;
+ }
+ data = abuf->data;
+ // update lengths of all typed arrays backed by this array buffer
+ list_for_each(el, &abuf->array_list) {
+ ta = list_entry(el, JSTypedArray, link);
+ p = ta->obj;
+ if (p->class_id == JS_CLASS_DATAVIEW)
+ continue;
+ p->u.array.count = 0;
+ p->u.array.u.ptr = NULL;
+ size_log2 = typed_array_size_log2(p->class_id);
+ size_elem = 1 << size_log2;
+ if (ta->track_rab) {
+ if (len >= (int64_t)ta->offset + size_elem) {
+ p->u.array.count = (len - ta->offset) >> size_log2;
+ p->u.array.u.ptr = &data[ta->offset];
+ }
+ } else {
+ if (len >= (int64_t)ta->offset + ta->length) {
+ p->u.array.count = ta->length >> size_log2;
+ p->u.array.u.ptr = &data[ta->offset];
+ }
+ }
+ }
+ return JS_UNDEFINED;
+}
+
static JSValue js_array_buffer_slice(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv, int class_id)
+ JSValue this_val,
+ int argc, JSValue *argv, int class_id)
{
JSArrayBuffer *abuf, *new_abuf;
int64_t len, start, end, new_len;
@@ -53383,11 +52261,11 @@ static JSValue js_array_buffer_slice(JSContext *ctx,
return ctor;
if (JS_IsUndefined(ctor)) {
new_obj = js_array_buffer_constructor2(ctx, JS_UNDEFINED, new_len,
- class_id);
+ NULL, class_id);
} else {
JSValue args[1];
- args[0] = JS_NewInt64(ctx, new_len);
- new_obj = JS_CallConstructor(ctx, ctor, 1, (JSValueConst *)args);
+ args[0] = js_int64(new_len);
+ new_obj = JS_CallConstructor(ctx, ctor, 1, args);
JS_FreeValue(ctx, ctor);
JS_FreeValue(ctx, args[0]);
}
@@ -53422,7 +52300,13 @@ static JSValue js_array_buffer_slice(JSContext *ctx,
static const JSCFunctionListEntry js_array_buffer_proto_funcs[] = {
JS_CGETSET_MAGIC_DEF("byteLength", js_array_buffer_get_byteLength, NULL, JS_CLASS_ARRAY_BUFFER ),
+ JS_CGETSET_MAGIC_DEF("maxByteLength", js_array_buffer_get_maxByteLength, NULL, JS_CLASS_ARRAY_BUFFER ),
+ JS_CGETSET_MAGIC_DEF("resizable", js_array_buffer_get_resizable, NULL, JS_CLASS_ARRAY_BUFFER ),
+ JS_CGETSET_DEF("detached", js_array_buffer_get_detached, NULL ),
+ JS_CFUNC_MAGIC_DEF("resize", 1, js_array_buffer_resize, JS_CLASS_ARRAY_BUFFER ),
JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_ARRAY_BUFFER ),
+ JS_CFUNC_MAGIC_DEF("transfer", 0, js_array_buffer_transfer, 0 ),
+ JS_CFUNC_MAGIC_DEF("transferToFixedLength", 0, js_array_buffer_transfer, 1 ),
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "ArrayBuffer", JS_PROP_CONFIGURABLE ),
};
@@ -53434,40 +52318,43 @@ static const JSCFunctionListEntry js_shared_array_buffer_funcs[] = {
static const JSCFunctionListEntry js_shared_array_buffer_proto_funcs[] = {
JS_CGETSET_MAGIC_DEF("byteLength", js_array_buffer_get_byteLength, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ),
+ JS_CGETSET_MAGIC_DEF("maxByteLength", js_array_buffer_get_maxByteLength, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ),
+ JS_CGETSET_MAGIC_DEF("growable", js_array_buffer_get_resizable, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ),
+ JS_CFUNC_MAGIC_DEF("grow", 1, js_array_buffer_resize, JS_CLASS_SHARED_ARRAY_BUFFER ),
JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_SHARED_ARRAY_BUFFER ),
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "SharedArrayBuffer", JS_PROP_CONFIGURABLE ),
};
-static JSObject *get_typed_array(JSContext *ctx,
- JSValueConst this_val,
- int is_dataview)
+static bool is_typed_array(JSClassID class_id)
{
- JSObject *p;
- if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
- goto fail;
- p = JS_VALUE_GET_OBJ(this_val);
- if (is_dataview) {
- if (p->class_id != JS_CLASS_DATAVIEW)
- goto fail;
- } else {
- if (!(p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_FLOAT64_ARRAY)) {
- fail:
- JS_ThrowTypeError(ctx, "not a %s", is_dataview ? "DataView" : "TypedArray");
- return NULL;
- }
- }
- return p;
+ return class_id >= JS_CLASS_UINT8C_ARRAY && class_id <= JS_CLASS_FLOAT64_ARRAY;
}
-/* WARNING: 'p' must be a typed array */
-static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p)
+// is the typed array detached or out of bounds relative to its RAB?
+// |p| must be a typed array, *not* a DataView
+static bool typed_array_is_oob(JSObject *p)
{
- JSTypedArray *ta = p->u.typed_array;
- JSArrayBuffer *abuf = ta->buffer->u.array_buffer;
- /* XXX: could simplify test by ensuring that
- p->u.array.u.ptr is NULL iff it is detached */
- return abuf->detached;
+ JSArrayBuffer *abuf;
+ JSTypedArray *ta;
+ int len, size_elem;
+ int64_t end;
+
+ assert(is_typed_array(p->class_id));
+
+ ta = p->u.typed_array;
+ abuf = ta->buffer->u.array_buffer;
+ if (abuf->detached)
+ return true;
+ len = abuf->byte_length;
+ if (ta->offset > len)
+ return true;
+ if (ta->track_rab)
+ return false;
+ if (len < (int64_t)ta->offset + ta->length)
+ return true;
+ size_elem = 1 << typed_array_size_log2(p->class_id);
+ end = (int64_t)ta->offset + (int64_t)p->u.array.count * size_elem;
+ return end > len;
}
/* WARNING: 'p' must be a typed array. Works even if the array buffer
@@ -53479,82 +52366,71 @@ static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p)
return ta->length >> size_log2;
}
-static int validate_typed_array(JSContext *ctx, JSValueConst this_val)
+static int validate_typed_array(JSContext *ctx, JSValue this_val)
{
JSObject *p;
- p = get_typed_array(ctx, this_val, 0);
+ p = get_typed_array(ctx, this_val);
if (!p)
return -1;
- if (typed_array_is_detached(ctx, p)) {
- JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ if (typed_array_is_oob(p)) {
+ JS_ThrowTypeErrorArrayBufferOOB(ctx);
return -1;
}
return 0;
}
-static JSValue js_typed_array_get_length(JSContext *ctx,
- JSValueConst this_val)
+static JSValue js_typed_array_get_length(JSContext *ctx, JSValue this_val)
{
JSObject *p;
- p = get_typed_array(ctx, this_val, 0);
+ p = get_typed_array(ctx, this_val);
if (!p)
return JS_EXCEPTION;
- return JS_NewInt32(ctx, p->u.array.count);
+ return js_int32(p->u.array.count);
}
-static JSValue js_typed_array_get_buffer(JSContext *ctx,
- JSValueConst this_val, int is_dataview)
+static JSValue js_typed_array_get_buffer(JSContext *ctx, JSValue this_val)
{
JSObject *p;
JSTypedArray *ta;
- p = get_typed_array(ctx, this_val, is_dataview);
+ p = get_typed_array(ctx, this_val);
if (!p)
return JS_EXCEPTION;
ta = p->u.typed_array;
- return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer));
+ return js_dup(JS_MKPTR(JS_TAG_OBJECT, ta->buffer));
}
-static JSValue js_typed_array_get_byteLength(JSContext *ctx,
- JSValueConst this_val,
- int is_dataview)
+static JSValue js_typed_array_get_byteLength(JSContext *ctx, JSValue this_val)
{
- JSObject *p;
+ uint32_t size_log2;
JSTypedArray *ta;
- p = get_typed_array(ctx, this_val, is_dataview);
+ JSObject *p;
+
+ p = get_typed_array(ctx, this_val);
if (!p)
return JS_EXCEPTION;
- if (typed_array_is_detached(ctx, p)) {
- if (is_dataview) {
- return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
- } else {
- return JS_NewInt32(ctx, 0);
- }
- }
+ if (typed_array_is_oob(p))
+ return js_int32(0);
ta = p->u.typed_array;
- return JS_NewInt32(ctx, ta->length);
+ if (!ta->track_rab)
+ return js_uint32(ta->length);
+ size_log2 = typed_array_size_log2(p->class_id);
+ return js_int64((int64_t)p->u.array.count << size_log2);
}
-static JSValue js_typed_array_get_byteOffset(JSContext *ctx,
- JSValueConst this_val,
- int is_dataview)
+static JSValue js_typed_array_get_byteOffset(JSContext *ctx, JSValue this_val)
{
JSObject *p;
JSTypedArray *ta;
- p = get_typed_array(ctx, this_val, is_dataview);
+ p = get_typed_array(ctx, this_val);
if (!p)
return JS_EXCEPTION;
- if (typed_array_is_detached(ctx, p)) {
- if (is_dataview) {
- return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
- } else {
- return JS_NewInt32(ctx, 0);
- }
- }
+ if (typed_array_is_oob(p))
+ return js_int32(0);
ta = p->u.typed_array;
- return JS_NewInt32(ctx, ta->offset);
+ return js_uint32(ta->offset);
}
-JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv,
+JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValue *argv,
JSTypedArrayEnum type)
{
if (type < JS_TYPED_ARRAY_UINT8C || type > JS_TYPED_ARRAY_FLOAT64)
@@ -53567,18 +52443,18 @@ JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv,
/* Return the buffer associated to the typed array or an exception if
it is not a typed array or if the buffer is detached. pbyte_offset,
pbyte_length or pbytes_per_element can be NULL. */
-JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj,
+JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValue obj,
size_t *pbyte_offset,
size_t *pbyte_length,
size_t *pbytes_per_element)
{
JSObject *p;
JSTypedArray *ta;
- p = get_typed_array(ctx, obj, FALSE);
+ p = get_typed_array(ctx, obj);
if (!p)
return JS_EXCEPTION;
- if (typed_array_is_detached(ctx, p))
- return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ if (typed_array_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
ta = p->u.typed_array;
if (pbyte_offset)
*pbyte_offset = ta->offset;
@@ -53587,62 +52463,89 @@ JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj,
if (pbytes_per_element) {
*pbytes_per_element = 1 << typed_array_size_log2(p->class_id);
}
- return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer));
+ return js_dup(JS_MKPTR(JS_TAG_OBJECT, ta->buffer));
+}
+
+/* return NULL if exception. WARNING: any JS call can detach the
+ buffer and render the returned pointer invalid */
+uint8_t *JS_GetUint8Array(JSContext *ctx, size_t *psize, JSValue obj)
+{
+ JSObject *p;
+ JSTypedArray *ta;
+ JSArrayBuffer *abuf;
+ p = get_typed_array(ctx, obj);
+ if (!p)
+ goto fail;
+ if (typed_array_is_oob(p)) {
+ JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ goto fail;
+ }
+ if (p->class_id != JS_CLASS_UINT8_ARRAY && p->class_id != JS_CLASS_UINT8C_ARRAY) {
+ JS_ThrowTypeError(ctx, "not a Uint8Array");
+ goto fail;
+ }
+ ta = p->u.typed_array;
+ abuf = ta->buffer->u.array_buffer;
+
+ *psize = ta->length;
+ return abuf->data + ta->offset;
+ fail:
+ *psize = 0;
+ return NULL;
}
static JSValue js_typed_array_get_toStringTag(JSContext *ctx,
- JSValueConst this_val)
+ JSValue this_val)
{
JSObject *p;
if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
return JS_UNDEFINED;
p = JS_VALUE_GET_OBJ(this_val);
- if (!(p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_FLOAT64_ARRAY))
+ if (!is_typed_array(p->class_id))
return JS_UNDEFINED;
return JS_AtomToString(ctx, ctx->rt->class_array[p->class_id].class_name);
}
static JSValue js_typed_array_set_internal(JSContext *ctx,
- JSValueConst dst,
- JSValueConst src,
- JSValueConst off)
+ JSValue dst,
+ JSValue src,
+ JSValue off)
{
JSObject *p;
JSObject *src_p;
uint32_t i;
- int64_t src_len, offset;
+ int64_t dst_len, src_len, offset;
JSValue val, src_obj = JS_UNDEFINED;
- p = get_typed_array(ctx, dst, 0);
+ p = get_typed_array(ctx, dst);
if (!p)
goto fail;
if (JS_ToInt64Sat(ctx, &offset, off))
goto fail;
if (offset < 0)
goto range_error;
- if (typed_array_is_detached(ctx, p)) {
+ if (typed_array_is_oob(p)) {
detached:
- JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ JS_ThrowTypeErrorArrayBufferOOB(ctx);
goto fail;
}
+ dst_len = p->u.array.count;
src_obj = JS_ToObject(ctx, src);
if (JS_IsException(src_obj))
goto fail;
src_p = JS_VALUE_GET_OBJ(src_obj);
- if (src_p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- src_p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
+ if (is_typed_array(src_p->class_id)) {
JSTypedArray *dest_ta = p->u.typed_array;
JSArrayBuffer *dest_abuf = dest_ta->buffer->u.array_buffer;
JSTypedArray *src_ta = src_p->u.typed_array;
JSArrayBuffer *src_abuf = src_ta->buffer->u.array_buffer;
int shift = typed_array_size_log2(p->class_id);
- if (src_abuf->detached)
+ if (typed_array_is_oob(src_p))
goto detached;
src_len = src_p->u.array.count;
- if (offset > (int64_t)(p->u.array.count - src_len))
+ if (offset > dst_len - src_len)
goto range_error;
/* copying between typed objects */
@@ -53658,9 +52561,11 @@ static JSValue js_typed_array_set_internal(JSContext *ctx,
}
/* otherwise, default behavior is slow but correct */
} else {
+ // can change |dst| as a side effect; per spec,
+ // perform the range check against its old length
if (js_get_length64(ctx, &src_len, src_obj))
goto fail;
- if (offset > (int64_t)(p->u.array.count - src_len)) {
+ if (offset > dst_len - src_len) {
range_error:
JS_ThrowRangeError(ctx, "invalid array length");
goto fail;
@@ -53670,8 +52575,14 @@ static JSValue js_typed_array_set_internal(JSContext *ctx,
val = JS_GetPropertyUint32(ctx, src_obj, i);
if (JS_IsException(val))
goto fail;
- if (JS_SetPropertyUint32(ctx, dst, offset + i, val) < 0)
+ // Per spec: detaching the TA mid-iteration is allowed and should
+ // not throw an exception. Because iteration over the source array is
+ // observable, we cannot bail out early when the TA is first detached.
+ if (typed_array_is_oob(p)) {
+ JS_FreeValue(ctx, val);
+ } else if (JS_SetPropertyUint32(ctx, dst, offset + i, val) < 0) {
goto fail;
+ }
}
done:
JS_FreeValue(ctx, src_obj);
@@ -53681,63 +52592,95 @@ fail:
return JS_EXCEPTION;
}
-static JSValue js_typed_array_at(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_at(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSObject *p;
int64_t idx, len;
- p = get_typed_array(ctx, this_val, 0);
+ p = get_typed_array(ctx, this_val);
if (!p)
return JS_EXCEPTION;
+ if (typed_array_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ len = p->u.array.count;
- if (typed_array_is_detached(ctx, p)) {
- JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
- return JS_EXCEPTION;
- }
-
+ // note: can change p->u.array.count
if (JS_ToInt64Sat(ctx, &idx, argv[0]))
return JS_EXCEPTION;
- len = p->u.array.count;
if (idx < 0)
idx = len + idx;
- if (idx < 0 || idx >= len)
+
+ if (idx < 0 || idx >= p->u.array.count)
return JS_UNDEFINED;
- return JS_GetPropertyInt64(ctx, this_val, idx);
+
+ switch (p->class_id) {
+ case JS_CLASS_INT8_ARRAY:
+ return js_int32(p->u.array.u.int8_ptr[idx]);
+ case JS_CLASS_UINT8C_ARRAY:
+ case JS_CLASS_UINT8_ARRAY:
+ return js_int32(p->u.array.u.uint8_ptr[idx]);
+ case JS_CLASS_INT16_ARRAY:
+ return js_int32(p->u.array.u.int16_ptr[idx]);
+ case JS_CLASS_UINT16_ARRAY:
+ return js_int32(p->u.array.u.uint16_ptr[idx]);
+ case JS_CLASS_INT32_ARRAY:
+ return js_int32(p->u.array.u.int32_ptr[idx]);
+ case JS_CLASS_UINT32_ARRAY:
+ return js_uint32(p->u.array.u.uint32_ptr[idx]);
+ case JS_CLASS_FLOAT16_ARRAY:
+ return js_float64(fromfp16(p->u.array.u.fp16_ptr[idx]));
+ case JS_CLASS_FLOAT32_ARRAY:
+ return js_float64(p->u.array.u.float_ptr[idx]);
+ case JS_CLASS_FLOAT64_ARRAY:
+ return js_float64(p->u.array.u.double_ptr[idx]);
+ case JS_CLASS_BIG_INT64_ARRAY:
+ return JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]);
+ case JS_CLASS_BIG_UINT64_ARRAY:
+ return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]);
+ }
+
+ abort(); /* unreachable */
+ return JS_UNDEFINED;
}
-static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_with(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue arr, val;
JSObject *p;
- int64_t idx, len;
+ int64_t idx;
+ uint32_t len, oldlen, newlen;
- p = get_typed_array(ctx, this_val, /*is_dataview*/0);
+ p = get_typed_array(ctx, this_val);
if (!p)
return JS_EXCEPTION;
+ oldlen = p->u.array.count;
if (JS_ToInt64Sat(ctx, &idx, argv[0]))
return JS_EXCEPTION;
- len = p->u.array.count;
- if (idx < 0)
- idx = len + idx;
- if (idx < 0 || idx >= len)
- return JS_ThrowRangeError(ctx, "invalid array index");
-
val = JS_ToPrimitive(ctx, argv[1], HINT_NUMBER);
if (JS_IsException(val))
return JS_EXCEPTION;
+ newlen = p->u.array.count;
+ if (idx < 0)
+ idx = newlen + idx;
+ if (idx < 0 || idx >= newlen) {
+ JS_FreeValue(ctx, val);
+ return JS_ThrowRangeError(ctx, "invalid array index");
+ }
+
+ len = min_uint32(oldlen, newlen);
arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val,
- p->class_id);
+ p->class_id, len);
if (JS_IsException(arr)) {
JS_FreeValue(ctx, val);
return JS_EXCEPTION;
}
- if (JS_SetPropertyInt64(ctx, arr, idx, val) < 0) {
+ if (idx < len && JS_SetPropertyInt64(ctx, arr, idx, val) < 0) {
JS_FreeValue(ctx, arr);
return JS_EXCEPTION;
}
@@ -53745,61 +52688,26 @@ static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val,
}
static JSValue js_typed_array_set(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv)
+ JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst offset = JS_UNDEFINED;
+ JSValue offset = JS_UNDEFINED;
if (argc > 1) {
offset = argv[1];
}
return js_typed_array_set_internal(ctx, this_val, argv[0], offset);
}
-static JSValue js_create_typed_array_iterator(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic)
+static JSValue js_create_typed_array_iterator(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int magic)
{
if (validate_typed_array(ctx, this_val))
return JS_EXCEPTION;
return js_create_array_iterator(ctx, this_val, argc, argv, magic);
}
-/* return < 0 if exception */
-static int js_typed_array_get_length_internal(JSContext *ctx,
- JSValueConst obj)
-{
- JSObject *p;
- p = get_typed_array(ctx, obj, 0);
- if (!p)
- return -1;
- if (typed_array_is_detached(ctx, p)) {
- JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
- return -1;
- }
- return p->u.array.count;
-}
-
-#if 0
-/* validate a typed array and return its length */
-static JSValue js_typed_array___getLength(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- BOOL ignore_detached = JS_ToBool(ctx, argv[1]);
-
- if (ignore_detached) {
- return js_typed_array_get_length(ctx, argv[0]);
- } else {
- int len;
- len = js_typed_array_get_length_internal(ctx, argv[0]);
- if (len < 0)
- return JS_EXCEPTION;
- return JS_NewInt32(ctx, len);
- }
-}
-#endif
-
-static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_create(JSContext *ctx, JSValue ctor,
+ int argc, JSValue *argv)
{
JSValue ret;
int new_len;
@@ -53809,12 +52717,12 @@ static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor,
if (JS_IsException(ret))
return ret;
/* validate the typed array */
- new_len = js_typed_array_get_length_internal(ctx, ret);
+ new_len = js_typed_array_get_length_unsafe(ctx, ret);
if (new_len < 0)
goto fail;
if (argc == 1) {
/* ensure that it is large enough */
- if (JS_ToLengthFree(ctx, &len, JS_DupValue(ctx, argv[0])))
+ if (JS_ToLengthFree(ctx, &len, js_dup(argv[0])))
goto fail;
if (new_len < len) {
JS_ThrowTypeError(ctx, "TypedArray length is too small");
@@ -53826,26 +52734,17 @@ static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor,
return ret;
}
-#if 0
-static JSValue js_typed_array___create(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- return js_typed_array_create(ctx, argv[0], max_int(argc - 1, 0), argv + 1);
-}
-#endif
-
static JSValue js_typed_array___speciesCreate(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv)
+ JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst obj;
+ JSValue obj;
JSObject *p;
JSValue ctor, ret;
int argc1;
obj = argv[0];
- p = get_typed_array(ctx, obj, 0);
+ p = get_typed_array(ctx, obj);
if (!p)
return JS_EXCEPTION;
ctor = JS_SpeciesConstructor(ctx, obj, JS_UNDEFINED);
@@ -53862,18 +52761,18 @@ static JSValue js_typed_array___speciesCreate(JSContext *ctx,
return ret;
}
-static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_from(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
// from(items, mapfn = void 0, this_arg = void 0)
- JSValueConst items = argv[0], mapfn, this_arg;
- JSValueConst args[2];
+ JSValue items = argv[0], mapfn, this_arg;
+ JSValue args[2];
JSValue stack[2];
JSValue iter, arr, r, v, v2;
int64_t k, len;
int done, mapping;
- mapping = FALSE;
+ mapping = false;
mapfn = JS_UNDEFINED;
this_arg = JS_UNDEFINED;
r = JS_UNDEFINED;
@@ -53899,8 +52798,8 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val,
arr = JS_NewArray(ctx);
if (JS_IsException(arr))
goto exception;
- stack[0] = JS_DupValue(ctx, items);
- if (js_for_of_start(ctx, &stack[1], FALSE))
+ stack[0] = js_dup(items);
+ if (js_for_of_start(ctx, &stack[1], false))
goto exception;
for (k = 0;; k++) {
v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done);
@@ -53918,7 +52817,7 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val,
}
if (js_get_length64(ctx, &len, arr) < 0)
goto exception;
- v = JS_NewInt64(ctx, len);
+ v = js_int64(len);
args[0] = v;
r = js_typed_array_create(ctx, this_val, 1, args);
JS_FreeValue(ctx, v);
@@ -53930,7 +52829,7 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val,
goto exception;
if (mapping) {
args[0] = v;
- args[1] = JS_NewInt32(ctx, k);
+ args[1] = js_int32(k);
v2 = JS_Call(ctx, mapfn, this_arg, 2, args);
JS_FreeValue(ctx, v);
v = v2;
@@ -53944,7 +52843,7 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val,
exception_close:
if (!JS_IsUndefined(stack[0]))
- JS_IteratorClose(ctx, stack[0], TRUE);
+ JS_IteratorClose(ctx, stack[0], true);
exception:
JS_FreeValue(ctx, r);
r = JS_EXCEPTION;
@@ -53955,20 +52854,20 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val,
return r;
}
-static JSValue js_typed_array_of(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_of(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue obj;
- JSValueConst args[1];
+ JSValue args[1];
int i;
- args[0] = JS_NewInt32(ctx, argc);
+ args[0] = js_int32(argc);
obj = js_typed_array_create(ctx, this_val, 1, args);
if (JS_IsException(obj))
return obj;
for(i = 0; i < argc; i++) {
- if (JS_SetPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i])) < 0) {
+ if (JS_SetPropertyUint32(ctx, obj, i, js_dup(argv[i])) < 0) {
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
@@ -53976,15 +52875,18 @@ static JSValue js_typed_array_of(JSContext *ctx, JSValueConst this_val,
return obj;
}
-static JSValue js_typed_array_copyWithin(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_copyWithin(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSObject *p;
- int len, to, from, final, count, shift;
+ int len, to, from, final, count, shift, space;
- len = js_typed_array_get_length_internal(ctx, this_val);
- if (len < 0)
+ p = get_typed_array(ctx, this_val);
+ if (!p)
return JS_EXCEPTION;
+ if (typed_array_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ len = p->u.array.count;
if (JS_ToInt32Clamp(ctx, &to, argv[0], 0, len, len))
return JS_EXCEPTION;
@@ -53998,34 +52900,39 @@ static JSValue js_typed_array_copyWithin(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
+ if (typed_array_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+
+ // RAB may have been resized by evil .valueOf method
+ space = p->u.array.count - max_int(to, from);
count = min_int(final - from, len - to);
+ count = min_int(count, space);
if (count > 0) {
- p = JS_VALUE_GET_OBJ(this_val);
- if (typed_array_is_detached(ctx, p))
- return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
shift = typed_array_size_log2(p->class_id);
memmove(p->u.array.u.uint8_ptr + (to << shift),
p->u.array.u.uint8_ptr + (from << shift),
count << shift);
}
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
}
-static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_fill(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSObject *p;
int len, k, final, shift;
uint64_t v64;
- len = js_typed_array_get_length_internal(ctx, this_val);
- if (len < 0)
+ p = get_typed_array(ctx, this_val);
+ if (!p)
return JS_EXCEPTION;
- p = JS_VALUE_GET_OBJ(this_val);
+ if (typed_array_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ len = p->u.array.count;
if (p->class_id == JS_CLASS_UINT8C_ARRAY) {
int32_t v;
- if (JS_ToUint8ClampFree(ctx, &v, JS_DupValue(ctx, argv[0])))
+ if (JS_ToUint8ClampFree(ctx, &v, js_dup(argv[0])))
return JS_EXCEPTION;
v64 = v;
} else if (p->class_id <= JS_CLASS_UINT32_ARRAY) {
@@ -54033,14 +52940,17 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val,
if (JS_ToUint32(ctx, &v, argv[0]))
return JS_EXCEPTION;
v64 = v;
- } else if (p->class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
+ } else
+ if (p->class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
if (JS_ToBigInt64(ctx, (int64_t *)&v64, argv[0]))
return JS_EXCEPTION;
} else {
double d;
if (JS_ToFloat64(ctx, &d, argv[0]))
return JS_EXCEPTION;
- if (p->class_id == JS_CLASS_FLOAT32_ARRAY) {
+ if (p->class_id == JS_CLASS_FLOAT16_ARRAY) {
+ v64 = tofp16(d);
+ } else if (p->class_id == JS_CLASS_FLOAT32_ARRAY) {
union {
float f;
uint32_t u32;
@@ -54066,9 +52976,11 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
- if (typed_array_is_detached(ctx, p))
- return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ if (typed_array_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ // RAB may have been resized by evil .valueOf method
+ final = min_int(final, p->u.array.count);
shift = typed_array_size_log2(p->class_id);
switch(shift) {
case 0:
@@ -54094,20 +53006,20 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val,
default:
abort();
}
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
}
-static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int mode)
+static JSValue js_typed_array_find(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int mode)
{
- JSValueConst func, this_arg;
- JSValueConst args[3];
+ JSValue func, this_arg;
+ JSValue args[3];
JSValue val, index_val, res;
int len, k, end;
int dir;
val = JS_UNDEFINED;
- len = js_typed_array_get_length_internal(ctx, this_val);
+ len = js_typed_array_get_length_unsafe(ctx, this_val);
if (len < 0)
goto exception;
@@ -54129,7 +53041,7 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
}
for(; k != end; k += dir) {
- index_val = JS_NewInt32(ctx, k);
+ index_val = js_int32(k);
val = JS_GetPropertyValue(ctx, this_val, index_val);
if (JS_IsException(val))
goto exception;
@@ -54150,7 +53062,7 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, val);
}
if (mode == ArrayFindIndex || mode == ArrayFindLastIndex)
- return JS_NewInt32(ctx, -1);
+ return js_int32(-1);
else
return JS_UNDEFINED;
@@ -54163,21 +53075,28 @@ exception:
#define special_lastIndexOf 1
#define special_includes -1
-static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int special)
+static JSValue js_typed_array_indexOf(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int special)
{
JSObject *p;
int len, tag, is_int, is_bigint, k, stop, inc, res = -1;
int64_t v64;
double d;
float f;
+ uint16_t hf;
+ bool oob;
+
+ p = get_typed_array(ctx, this_val);
+ if (!p)
+ return JS_EXCEPTION;
+ if (typed_array_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ len = p->u.array.count;
- len = js_typed_array_get_length_internal(ctx, this_val);
- if (len < 0)
- goto exception;
if (len == 0)
goto done;
+ oob = false;
if (special == special_lastIndexOf) {
k = len - 1;
if (argc > 1) {
@@ -54203,23 +53122,37 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
} else {
k = 0;
if (argc > 1) {
- if (JS_ToInt32Clamp(ctx, &k, argv[1], 0, len, len))
+ if (JS_ToInt32Sat(ctx, &k, argv[1]))
goto exception;
+ if (k < 0) {
+ k += len;
+ if (k < 0)
+ k = 0;
+ } else if (k > len) {
+ k = len;
+ oob = true;
+ }
}
stop = len;
inc = 1;
}
- p = JS_VALUE_GET_OBJ(this_val);
/* if the array was detached, no need to go further (but no
exception is raised) */
- if (typed_array_is_detached(ctx, p)) {
+ if (typed_array_is_oob(p) || len > p->u.array.count) {
/* "includes" scans all the properties, so "undefined" can match */
if (special == special_includes && JS_IsUndefined(argv[0]) && len > 0)
- res = 0;
+ res = oob ? -1 : 0;
goto done;
}
+ // RAB may have been resized by evil .valueOf method
+ len = min_int(len, p->u.array.count);
+ if (len == 0)
+ goto done;
+ k = min_int(k, len);
+ stop = min_int(stop, len);
+
is_bigint = 0;
is_int = 0; /* avoid warning */
v64 = 0; /* avoid warning */
@@ -54235,8 +53168,9 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
v64 = d;
is_int = (v64 == d);
}
- } else if (tag == JS_TAG_BIG_INT) {
- JSBigFloat *p1 = JS_VALUE_GET_PTR(argv[0]);
+ } else
+ if (tag == JS_TAG_BIG_INT) {
+ JSBigInt *p1 = JS_VALUE_GET_PTR(argv[0]);
if (p->class_id == JS_CLASS_BIG_INT64_ARRAY) {
if (bf_get_int64(&v64, &p1->num, 0) != 0)
@@ -54267,7 +53201,9 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
pv = p->u.array.u.uint8_ptr;
v = v64;
if (inc > 0) {
- pp = memchr(pv + k, v, len - k);
+ pp = NULL;
+ if (pv)
+ pp = memchr(pv + k, v, len - k);
if (pp)
res = pp - pv;
} else {
@@ -54318,6 +53254,39 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
}
}
break;
+ case JS_CLASS_FLOAT16_ARRAY:
+ if (is_bigint)
+ break;
+ if (isnan(d)) {
+ const uint16_t *pv = p->u.array.u.fp16_ptr;
+ /* special case: indexOf returns -1, includes finds NaN */
+ if (special != special_includes)
+ goto done;
+ for (; k != stop; k += inc) {
+ if (isfp16nan(pv[k])) {
+ res = k;
+ break;
+ }
+ }
+ } else if (d == 0) {
+ // special case: includes also finds negative zero
+ const uint16_t *pv = p->u.array.u.fp16_ptr;
+ for (; k != stop; k += inc) {
+ if (isfp16zero(pv[k])) {
+ res = k;
+ break;
+ }
+ }
+ } else if (hf = tofp16(d), d == fromfp16(hf)) {
+ const uint16_t *pv = p->u.array.u.fp16_ptr;
+ for (; k != stop; k += inc) {
+ if (pv[k] == hf) {
+ res = k;
+ break;
+ }
+ }
+ }
+ break;
case JS_CLASS_FLOAT32_ARRAY:
if (is_bigint)
break;
@@ -54367,15 +53336,12 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
}
break;
case JS_CLASS_BIG_INT64_ARRAY:
- if (is_bigint || (is_math_mode(ctx) && is_int &&
- v64 >= -MAX_SAFE_INTEGER &&
- v64 <= MAX_SAFE_INTEGER)) {
+ if (is_bigint) {
goto scan64;
}
break;
case JS_CLASS_BIG_UINT64_ARRAY:
- if (is_bigint || (is_math_mode(ctx) && is_int &&
- v64 >= 0 && v64 <= MAX_SAFE_INTEGER)) {
+ if (is_bigint) {
const uint64_t *pv;
uint64_t v;
scan64:
@@ -54393,48 +53359,55 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
done:
if (special == special_includes)
- return JS_NewBool(ctx, res >= 0);
+ return js_bool(res >= 0);
else
- return JS_NewInt32(ctx, res);
+ return js_int32(res);
exception:
return JS_EXCEPTION;
}
-static JSValue js_typed_array_join(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int toLocaleString)
+static JSValue js_typed_array_join(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int toLocaleString)
{
JSValue sep = JS_UNDEFINED, el;
StringBuffer b_s, *b = &b_s;
- JSString *p = NULL;
- int i, n;
+ JSString *s = NULL;
+ JSObject *p;
+ int i, len, oldlen, newlen;
int c;
- n = js_typed_array_get_length_internal(ctx, this_val);
- if (n < 0)
- goto exception;
+ p = get_typed_array(ctx, this_val);
+ if (!p)
+ return JS_EXCEPTION;
+ if (typed_array_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ len = oldlen = newlen = p->u.array.count;
c = ','; /* default separator */
if (!toLocaleString && argc > 0 && !JS_IsUndefined(argv[0])) {
sep = JS_ToString(ctx, argv[0]);
if (JS_IsException(sep))
goto exception;
- p = JS_VALUE_GET_STRING(sep);
- if (p->len == 1 && !p->is_wide_char)
- c = p->u.str8[0];
+ s = JS_VALUE_GET_STRING(sep);
+ if (s->len == 1 && !s->is_wide_char)
+ c = s->u.str8[0];
else
c = -1;
+ // ToString(sep) can detach or resize the arraybuffer as a side effect
+ newlen = p->u.array.count;
+ len = min_int(len, newlen);
}
string_buffer_init(ctx, b, 0);
/* XXX: optimize with direct access */
- for(i = 0; i < n; i++) {
+ for(i = 0; i < len; i++) {
if (i > 0) {
if (c >= 0) {
if (string_buffer_putc8(b, c))
goto fail;
} else {
- if (string_buffer_concat(b, p, 0, p->len))
+ if (string_buffer_concat(b, s, 0, s->len))
goto fail;
}
}
@@ -54450,6 +53423,19 @@ static JSValue js_typed_array_join(JSContext *ctx, JSValueConst this_val,
goto fail;
}
}
+
+ // add extra separators in case RAB was resized by evil .valueOf method
+ i = max_int(1, newlen);
+ for(/*empty*/; i < oldlen; i++) {
+ if (c >= 0) {
+ if (string_buffer_putc8(b, c))
+ goto fail;
+ } else {
+ if (string_buffer_concat(b, s, 0, s->len))
+ goto fail;
+ }
+ }
+
JS_FreeValue(ctx, sep);
return string_buffer_end(b);
@@ -54460,13 +53446,13 @@ exception:
return JS_EXCEPTION;
}
-static JSValue js_typed_array_reverse(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_reverse(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSObject *p;
int len;
- len = js_typed_array_get_length_internal(ctx, this_val);
+ len = js_typed_array_get_length_unsafe(ctx, this_val);
if (len < 0)
return JS_EXCEPTION;
if (len > 0) {
@@ -54520,20 +53506,20 @@ static JSValue js_typed_array_reverse(JSContext *ctx, JSValueConst this_val,
abort();
}
}
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
}
-static JSValue js_typed_array_toReversed(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_toReversed(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue arr, ret;
JSObject *p;
- p = get_typed_array(ctx, this_val, /*is_dataview*/0);
+ p = get_typed_array(ctx, this_val);
if (!p)
return JS_EXCEPTION;
arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val,
- p->class_id);
+ p->class_id, p->u.array.count);
if (JS_IsException(arr))
return JS_EXCEPTION;
ret = js_typed_array_reverse(ctx, arr, argc, argv);
@@ -54541,18 +53527,21 @@ static JSValue js_typed_array_toReversed(JSContext *ctx, JSValueConst this_val,
return ret;
}
-static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_slice(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst args[2];
+ JSValue args[2];
JSValue arr, val;
JSObject *p, *p1;
- int n, len, start, final, count, shift;
+ int n, len, start, final, count, shift, space;
arr = JS_UNDEFINED;
- len = js_typed_array_get_length_internal(ctx, this_val);
- if (len < 0)
- goto exception;
+ p = get_typed_array(ctx, this_val);
+ if (!p)
+ return JS_EXCEPTION;
+ if (typed_array_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ len = p->u.array.count;
if (JS_ToInt32Clamp(ctx, &start, argv[0], 0, len, len))
goto exception;
@@ -54563,13 +53552,8 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val,
}
count = max_int(final - start, 0);
- p = get_typed_array(ctx, this_val, 0);
- if (p == NULL)
- goto exception;
- shift = typed_array_size_log2(p->class_id);
-
args[0] = this_val;
- args[1] = JS_NewInt32(ctx, count);
+ args[1] = js_int32(count);
arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args);
if (JS_IsException(arr))
goto exception;
@@ -54579,19 +53563,26 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val,
|| validate_typed_array(ctx, arr))
goto exception;
- p1 = get_typed_array(ctx, arr, 0);
+ if (len != p->u.array.count)
+ goto slow_path;
+
+ p1 = get_typed_array(ctx, arr);
if (p1 != NULL && p->class_id == p1->class_id &&
typed_array_get_length(ctx, p1) >= count &&
typed_array_get_length(ctx, p) >= start + count) {
- memcpy(p1->u.array.u.uint8_ptr,
- p->u.array.u.uint8_ptr + (start << shift),
- count << shift);
+ shift = typed_array_size_log2(p->class_id);
+ memmove(p1->u.array.u.uint8_ptr,
+ p->u.array.u.uint8_ptr + (start << shift),
+ count << shift);
} else {
+ slow_path:
+ space = max_int(0, p->u.array.count - start);
+ count = min_int(count, space);
for (n = 0; n < count; n++) {
- val = JS_GetPropertyValue(ctx, this_val, JS_NewInt32(ctx, start + n));
+ val = JS_GetPropertyValue(ctx, this_val, js_int32(start + n));
if (JS_IsException(val))
goto exception;
- if (JS_SetPropertyValue(ctx, arr, JS_NewInt32(ctx, n), val,
+ if (JS_SetPropertyValue(ctx, arr, js_int32(n), val,
JS_PROP_THROW) < 0)
goto exception;
}
@@ -54604,44 +53595,56 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
-static JSValue js_typed_array_subarray(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_subarray(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- JSValueConst args[4];
+ JSArrayBuffer *abuf;
+ JSTypedArray *ta;
+ JSValue args[4];
JSValue arr, byteOffset, ta_buffer;
JSObject *p;
int len, start, final, count, shift, offset;
- p = get_typed_array(ctx, this_val, 0);
+ p = get_typed_array(ctx, this_val);
if (!p)
goto exception;
len = p->u.array.count;
if (JS_ToInt32Clamp(ctx, &start, argv[0], 0, len, len))
goto exception;
-
final = len;
if (!JS_IsUndefined(argv[1])) {
if (JS_ToInt32Clamp(ctx, &final, argv[1], 0, len, len))
goto exception;
}
count = max_int(final - start, 0);
- byteOffset = js_typed_array_get_byteOffset(ctx, this_val, 0);
+ byteOffset = js_typed_array_get_byteOffset(ctx, this_val);
if (JS_IsException(byteOffset))
goto exception;
+ ta = p->u.typed_array;
+ abuf = ta->buffer->u.array_buffer;
+ if (ta->offset > abuf->byte_length)
+ goto range_error;
+ if (ta->offset == abuf->byte_length && count > 0) {
+ range_error:
+ JS_ThrowRangeError(ctx, "invalid offset");
+ goto exception;
+ }
shift = typed_array_size_log2(p->class_id);
offset = JS_VALUE_GET_INT(byteOffset) + (start << shift);
JS_FreeValue(ctx, byteOffset);
- ta_buffer = js_typed_array_get_buffer(ctx, this_val, 0);
+ ta_buffer = js_typed_array_get_buffer(ctx, this_val);
if (JS_IsException(ta_buffer))
goto exception;
args[0] = this_val;
args[1] = ta_buffer;
- args[2] = JS_NewInt32(ctx, offset);
- args[3] = JS_NewInt32(ctx, count);
+ args[2] = js_int32(offset);
+ args[3] = js_int32(count);
+ // result is length-tracking if source TA is and no explicit count is given
+ if (ta->track_rab && JS_IsUndefined(argv[1]))
+ args[3] = JS_UNDEFINED;
arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 4, args);
JS_FreeValue(ctx, ta_buffer);
return arr;
-
exception:
return JS_EXCEPTION;
}
@@ -54699,6 +53702,11 @@ static int js_TA_cmp_uint64(const void *a, const void *b, void *opaque) {
return (y < x) - (y > x);
}
+static int js_TA_cmp_float16(const void *a, const void *b, void *opaque) {
+ return js_cmp_doubles(fromfp16(*(const uint16_t *)a),
+ fromfp16(*(const uint16_t *)b));
+}
+
static int js_TA_cmp_float32(const void *a, const void *b, void *opaque) {
return js_cmp_doubles(*(const float *)a, *(const float *)b);
}
@@ -54708,27 +53716,27 @@ static int js_TA_cmp_float64(const void *a, const void *b, void *opaque) {
}
static JSValue js_TA_get_int8(JSContext *ctx, const void *a) {
- return JS_NewInt32(ctx, *(const int8_t *)a);
+ return js_int32(*(const int8_t *)a);
}
static JSValue js_TA_get_uint8(JSContext *ctx, const void *a) {
- return JS_NewInt32(ctx, *(const uint8_t *)a);
+ return js_int32(*(const uint8_t *)a);
}
static JSValue js_TA_get_int16(JSContext *ctx, const void *a) {
- return JS_NewInt32(ctx, *(const int16_t *)a);
+ return js_int32(*(const int16_t *)a);
}
static JSValue js_TA_get_uint16(JSContext *ctx, const void *a) {
- return JS_NewInt32(ctx, *(const uint16_t *)a);
+ return js_int32(*(const uint16_t *)a);
}
static JSValue js_TA_get_int32(JSContext *ctx, const void *a) {
- return JS_NewInt32(ctx, *(const int32_t *)a);
+ return js_int32(*(const int32_t *)a);
}
static JSValue js_TA_get_uint32(JSContext *ctx, const void *a) {
- return JS_NewUint32(ctx, *(const uint32_t *)a);
+ return js_uint32(*(const uint32_t *)a);
}
static JSValue js_TA_get_int64(JSContext *ctx, const void *a) {
@@ -54739,21 +53747,24 @@ static JSValue js_TA_get_uint64(JSContext *ctx, const void *a) {
return JS_NewBigUint64(ctx, *(uint64_t *)a);
}
+static JSValue js_TA_get_float16(JSContext *ctx, const void *a) {
+ return js_float64(fromfp16(*(const uint16_t *)a));
+}
+
static JSValue js_TA_get_float32(JSContext *ctx, const void *a) {
- return __JS_NewFloat64(ctx, *(const float *)a);
+ return js_float64(*(const float *)a);
}
static JSValue js_TA_get_float64(JSContext *ctx, const void *a) {
- return __JS_NewFloat64(ctx, *(const double *)a);
+ return js_float64(*(const double *)a);
}
struct TA_sort_context {
JSContext *ctx;
- int exception; /* 1 = exception, 2 = detached typed array */
- JSValueConst arr;
- JSValueConst cmp;
+ int exception;
+ JSValue arr;
+ JSValue cmp;
JSValue (*getfun)(JSContext *ctx, const void *a);
- uint8_t *array_ptr; /* cannot change unless the array is detached */
int elt_size;
};
@@ -54761,19 +53772,24 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
struct TA_sort_context *psc = opaque;
JSContext *ctx = psc->ctx;
uint32_t a_idx, b_idx;
- JSValueConst argv[2];
+ JSValue argv[2];
JSValue res;
+ JSObject *p;
int cmp;
+ p = JS_VALUE_GET_OBJ(psc->arr);
+ if (typed_array_is_oob(p))
+ return 0;
+
cmp = 0;
if (!psc->exception) {
- /* Note: the typed array can be detached without causing an
- error */
a_idx = *(uint32_t *)a;
b_idx = *(uint32_t *)b;
- argv[0] = psc->getfun(ctx, psc->array_ptr +
+ if (a_idx >= p->u.array.count || b_idx >= p->u.array.count)
+ return 0;
+ argv[0] = psc->getfun(ctx, (char *)p->u.array.u.ptr +
a_idx * (size_t)psc->elt_size);
- argv[1] = psc->getfun(ctx, psc->array_ptr +
+ argv[1] = psc->getfun(ctx, (char *)p->u.array.u.ptr +
b_idx * (size_t)(psc->elt_size));
res = JS_Call(ctx, psc->cmp, JS_UNDEFINED, 2, argv);
if (JS_IsException(res)) {
@@ -54796,10 +53812,6 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
/* make sort stable: compare array offsets */
cmp = (a_idx > b_idx) - (a_idx < b_idx);
}
- if (unlikely(typed_array_is_detached(ctx,
- JS_VALUE_GET_PTR(psc->arr)))) {
- psc->exception = 2;
- }
done:
JS_FreeValue(ctx, argv[0]);
JS_FreeValue(ctx, argv[1]);
@@ -54807,16 +53819,21 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
return cmp;
}
-static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_sort(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSObject *p;
int len;
size_t elt_size;
struct TA_sort_context tsc;
- void *array_ptr;
int (*cmpfun)(const void *a, const void *b, void *opaque);
+ p = get_typed_array(ctx, this_val);
+ if (!p)
+ return JS_EXCEPTION;
+ if (typed_array_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+
tsc.ctx = ctx;
tsc.exception = 0;
tsc.arr = this_val;
@@ -54824,12 +53841,9 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
if (!JS_IsUndefined(tsc.cmp) && check_function(ctx, tsc.cmp))
return JS_EXCEPTION;
- len = js_typed_array_get_length_internal(ctx, this_val);
- if (len < 0)
- return JS_EXCEPTION;
+ len = p->u.array.count;
if (len > 1) {
- p = JS_VALUE_GET_OBJ(this_val);
switch (p->class_id) {
case JS_CLASS_INT8_ARRAY:
tsc.getfun = js_TA_get_int8;
@@ -54864,6 +53878,10 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
tsc.getfun = js_TA_get_uint64;
cmpfun = js_TA_cmp_uint64;
break;
+ case JS_CLASS_FLOAT16_ARRAY:
+ tsc.getfun = js_TA_get_float16;
+ cmpfun = js_TA_cmp_float16;
+ break;
case JS_CLASS_FLOAT32_ARRAY:
tsc.getfun = js_TA_get_float32;
cmpfun = js_TA_cmp_float32;
@@ -54875,7 +53893,6 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
default:
abort();
}
- array_ptr = p->u.array.u.ptr;
elt_size = 1 << typed_array_size_log2(p->class_id);
if (!JS_IsUndefined(tsc.cmp)) {
uint32_t *array_idx;
@@ -54888,73 +53905,75 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
for(i = 0; i < len; i++)
array_idx[i] = i;
- tsc.array_ptr = array_ptr;
tsc.elt_size = elt_size;
rqsort(array_idx, len, sizeof(array_idx[0]),
js_TA_cmp_generic, &tsc);
- if (tsc.exception) {
- if (tsc.exception == 1)
- goto fail;
- /* detached typed array during the sort: no error */
- } else {
- array_tmp = js_malloc(ctx, len * elt_size);
- if (!array_tmp) {
- fail:
- js_free(ctx, array_idx);
- return JS_EXCEPTION;
+ if (tsc.exception)
+ goto fail;
+ // per spec: typed array can be detached mid-iteration
+ if (typed_array_is_oob(p))
+ goto done;
+ len = min_int(len, p->u.array.count);
+ if (len == 0)
+ goto done;
+ array_tmp = js_malloc(ctx, len * elt_size);
+ if (!array_tmp) {
+ fail:
+ js_free(ctx, array_idx);
+ return JS_EXCEPTION;
+ }
+ memcpy(array_tmp, p->u.array.u.ptr, len * elt_size);
+ switch(elt_size) {
+ case 1:
+ for(i = 0; i < len; i++) {
+ j = array_idx[i];
+ p->u.array.u.uint8_ptr[i] = ((uint8_t *)array_tmp)[j];
}
- memcpy(array_tmp, array_ptr, len * elt_size);
- switch(elt_size) {
- case 1:
- for(i = 0; i < len; i++) {
- j = array_idx[i];
- ((uint8_t *)array_ptr)[i] = ((uint8_t *)array_tmp)[j];
- }
- break;
- case 2:
- for(i = 0; i < len; i++) {
- j = array_idx[i];
- ((uint16_t *)array_ptr)[i] = ((uint16_t *)array_tmp)[j];
- }
- break;
- case 4:
- for(i = 0; i < len; i++) {
- j = array_idx[i];
- ((uint32_t *)array_ptr)[i] = ((uint32_t *)array_tmp)[j];
- }
- break;
- case 8:
- for(i = 0; i < len; i++) {
- j = array_idx[i];
- ((uint64_t *)array_ptr)[i] = ((uint64_t *)array_tmp)[j];
- }
- break;
- default:
- abort();
+ break;
+ case 2:
+ for(i = 0; i < len; i++) {
+ j = array_idx[i];
+ p->u.array.u.uint16_ptr[i] = ((uint16_t *)array_tmp)[j];
+ }
+ break;
+ case 4:
+ for(i = 0; i < len; i++) {
+ j = array_idx[i];
+ p->u.array.u.uint32_ptr[i] = ((uint32_t *)array_tmp)[j];
}
- js_free(ctx, array_tmp);
+ break;
+ case 8:
+ for(i = 0; i < len; i++) {
+ j = array_idx[i];
+ p->u.array.u.uint64_ptr[i] = ((uint64_t *)array_tmp)[j];
+ }
+ break;
+ default:
+ abort();
}
+ js_free(ctx, array_tmp);
+ done:
js_free(ctx, array_idx);
} else {
- rqsort(array_ptr, len, elt_size, cmpfun, &tsc);
+ rqsort(p->u.array.u.ptr, len, elt_size, cmpfun, &tsc);
if (tsc.exception)
return JS_EXCEPTION;
}
}
- return JS_DupValue(ctx, this_val);
+ return js_dup(this_val);
}
-static JSValue js_typed_array_toSorted(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_typed_array_toSorted(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
JSValue arr, ret;
JSObject *p;
- p = get_typed_array(ctx, this_val, /*is_dataview*/0);
+ p = get_typed_array(ctx, this_val);
if (!p)
return JS_EXCEPTION;
arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val,
- p->class_id);
+ p->class_id, p->u.array.count);
if (JS_IsException(arr))
return JS_EXCEPTION;
ret = js_typed_array_sort(ctx, arr, argc, argv);
@@ -54966,18 +53985,15 @@ static const JSCFunctionListEntry js_typed_array_base_funcs[] = {
JS_CFUNC_DEF("from", 1, js_typed_array_from ),
JS_CFUNC_DEF("of", 0, js_typed_array_of ),
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
- //JS_CFUNC_DEF("__getLength", 2, js_typed_array___getLength ),
- //JS_CFUNC_DEF("__create", 2, js_typed_array___create ),
- //JS_CFUNC_DEF("__speciesCreate", 2, js_typed_array___speciesCreate ),
};
static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = {
JS_CGETSET_DEF("length", js_typed_array_get_length, NULL ),
JS_CFUNC_DEF("at", 1, js_typed_array_at ),
JS_CFUNC_DEF("with", 2, js_typed_array_with ),
- JS_CGETSET_MAGIC_DEF("buffer", js_typed_array_get_buffer, NULL, 0 ),
- JS_CGETSET_MAGIC_DEF("byteLength", js_typed_array_get_byteLength, NULL, 0 ),
- JS_CGETSET_MAGIC_DEF("byteOffset", js_typed_array_get_byteOffset, NULL, 0 ),
+ JS_CGETSET_DEF("buffer", js_typed_array_get_buffer, NULL ),
+ JS_CGETSET_DEF("byteLength", js_typed_array_get_byteLength, NULL ),
+ JS_CGETSET_DEF("byteOffset", js_typed_array_get_byteOffset, NULL ),
JS_CFUNC_DEF("set", 1, js_typed_array_set ),
JS_CFUNC_MAGIC_DEF("values", 0, js_create_typed_array_iterator, JS_ITERATOR_KIND_VALUE ),
JS_ALIAS_DEF("[Symbol.iterator]", "values" ),
@@ -55012,15 +54028,15 @@ static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = {
};
static JSValue js_typed_array_base_constructor(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv)
+ JSValue this_val,
+ int argc, JSValue *argv)
{
return JS_ThrowTypeError(ctx, "cannot be called");
}
/* 'obj' must be an allocated typed array object */
-static int typed_array_init(JSContext *ctx, JSValueConst obj,
- JSValue buffer, uint64_t offset, uint64_t len)
+static int typed_array_init(JSContext *ctx, JSValue obj, JSValue buffer,
+ uint64_t offset, uint64_t len, bool track_rab)
{
JSTypedArray *ta;
JSObject *p, *pbuffer;
@@ -55040,6 +54056,7 @@ static int typed_array_init(JSContext *ctx, JSValueConst obj,
ta->buffer = pbuffer;
ta->offset = offset;
ta->length = len << size_log2;
+ ta->track_rab = track_rab;
list_add_tail(&ta->link, &abuf->array_list);
p->u.typed_array = ta;
p->u.array.count = len;
@@ -55049,10 +54066,10 @@ static int typed_array_init(JSContext *ctx, JSValueConst obj,
static JSValue js_array_from_iterator(JSContext *ctx, uint32_t *plen,
- JSValueConst obj, JSValueConst method)
+ JSValue obj, JSValue method)
{
JSValue arr, iter, next_method = JS_UNDEFINED, val;
- BOOL done;
+ int done;
uint32_t k;
*plen = 0;
@@ -55090,8 +54107,8 @@ static JSValue js_array_from_iterator(JSContext *ctx, uint32_t *plen,
}
static JSValue js_typed_array_constructor_obj(JSContext *ctx,
- JSValueConst new_target,
- JSValueConst obj,
+ JSValue new_target,
+ JSValue obj,
int classid)
{
JSValue iter, ret, arr = JS_UNDEFINED, val, buffer;
@@ -55117,14 +54134,15 @@ static JSValue js_typed_array_constructor_obj(JSContext *ctx,
} else {
if (js_get_length64(ctx, &len, obj))
goto fail;
- arr = JS_DupValue(ctx, obj);
+ arr = js_dup(obj);
}
buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED,
- len << size_log2);
+ len << size_log2,
+ NULL);
if (JS_IsException(buffer))
goto fail;
- if (typed_array_init(ctx, ret, buffer, 0, len))
+ if (typed_array_init(ctx, ret, buffer, 0, len, /*track_rab*/false))
goto fail;
for(i = 0; i < len; i++) {
@@ -55143,14 +54161,14 @@ static JSValue js_typed_array_constructor_obj(JSContext *ctx,
}
static JSValue js_typed_array_constructor_ta(JSContext *ctx,
- JSValueConst new_target,
- JSValueConst src_obj,
- int classid)
+ JSValue new_target,
+ JSValue src_obj,
+ int classid, uint32_t len)
{
JSObject *p, *src_buffer;
JSTypedArray *ta;
JSValue obj, buffer;
- uint32_t len, i;
+ uint32_t i;
int size_log2;
JSArrayBuffer *src_abuf, *abuf;
@@ -55158,27 +54176,27 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx,
if (JS_IsException(obj))
return obj;
p = JS_VALUE_GET_OBJ(src_obj);
- if (typed_array_is_detached(ctx, p)) {
- JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ if (typed_array_is_oob(p)) {
+ JS_ThrowTypeErrorArrayBufferOOB(ctx);
goto fail;
}
ta = p->u.typed_array;
- len = p->u.array.count;
src_buffer = ta->buffer;
src_abuf = src_buffer->u.array_buffer;
size_log2 = typed_array_size_log2(classid);
buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED,
- (uint64_t)len << size_log2);
+ (uint64_t)len << size_log2,
+ NULL);
if (JS_IsException(buffer))
goto fail;
/* necessary because it could have been detached */
- if (typed_array_is_detached(ctx, p)) {
+ if (typed_array_is_oob(p)) {
JS_FreeValue(ctx, buffer);
- JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ JS_ThrowTypeErrorArrayBufferOOB(ctx);
goto fail;
}
abuf = JS_GetOpaque(buffer, JS_CLASS_ARRAY_BUFFER);
- if (typed_array_init(ctx, obj, buffer, 0, len))
+ if (typed_array_init(ctx, obj, buffer, 0, len, /*track_rab*/false))
goto fail;
if (p->class_id == classid) {
/* same type: copy the content */
@@ -55200,10 +54218,11 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx,
}
static JSValue js_typed_array_constructor(JSContext *ctx,
- JSValueConst new_target,
- int argc, JSValueConst *argv,
+ JSValue new_target,
+ int argc, JSValue *argv,
int classid)
{
+ bool track_rab = false;
JSValue buffer, obj;
JSArrayBuffer *abuf;
int size_log2;
@@ -55214,7 +54233,8 @@ static JSValue js_typed_array_constructor(JSContext *ctx,
if (JS_ToIndex(ctx, &len, argv[0]))
return JS_EXCEPTION;
buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED,
- len << size_log2);
+ len << size_log2,
+ NULL);
if (JS_IsException(buffer))
return JS_EXCEPTION;
offset = 0;
@@ -55231,8 +54251,10 @@ static JSValue js_typed_array_constructor(JSContext *ctx,
offset > abuf->byte_length)
return JS_ThrowRangeError(ctx, "invalid offset");
if (JS_IsUndefined(argv[2])) {
- if ((abuf->byte_length & ((1 << size_log2) - 1)) != 0)
- goto invalid_length;
+ track_rab = array_buffer_is_resizable(abuf);
+ if (!track_rab)
+ if ((abuf->byte_length & ((1 << size_log2) - 1)) != 0)
+ goto invalid_length;
len = (abuf->byte_length - offset) >> size_log2;
} else {
if (JS_ToIndex(ctx, &len, argv[2]))
@@ -55244,11 +54266,11 @@ static JSValue js_typed_array_constructor(JSContext *ctx,
return JS_ThrowRangeError(ctx, "invalid length");
}
}
- buffer = JS_DupValue(ctx, argv[0]);
+ buffer = js_dup(argv[0]);
} else {
- if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
- p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
- return js_typed_array_constructor_ta(ctx, new_target, argv[0], classid);
+ if (is_typed_array(p->class_id)) {
+ return js_typed_array_constructor_ta(ctx, new_target, argv[0],
+ classid, p->u.array.count);
} else {
return js_typed_array_constructor_obj(ctx, new_target, argv[0], classid);
}
@@ -55260,7 +54282,7 @@ static JSValue js_typed_array_constructor(JSContext *ctx,
JS_FreeValue(ctx, buffer);
return JS_EXCEPTION;
}
- if (typed_array_init(ctx, obj, buffer, offset, len)) {
+ if (typed_array_init(ctx, obj, buffer, offset, len, track_rab)) {
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
@@ -55282,7 +54304,7 @@ static void js_typed_array_finalizer(JSRuntime *rt, JSValue val)
}
}
-static void js_typed_array_mark(JSRuntime *rt, JSValueConst val,
+static void js_typed_array_mark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -55293,13 +54315,15 @@ static void js_typed_array_mark(JSRuntime *rt, JSValueConst val,
}
static JSValue js_dataview_constructor(JSContext *ctx,
- JSValueConst new_target,
- int argc, JSValueConst *argv)
+ JSValue new_target,
+ int argc, JSValue *argv)
{
+ bool recompute_len = false;
+ bool track_rab = false;
JSArrayBuffer *abuf;
uint64_t offset;
uint32_t len;
- JSValueConst buffer;
+ JSValue buffer;
JSValue obj;
JSTypedArray *ta;
JSObject *p;
@@ -55325,6 +54349,9 @@ static JSValue js_dataview_constructor(JSContext *ctx,
if (l > len)
return JS_ThrowRangeError(ctx, "invalid byteLength");
len = l;
+ } else {
+ recompute_len = true;
+ track_rab = array_buffer_is_resizable(abuf);
}
obj = js_create_from_ctor(ctx, new_target, JS_CLASS_DATAVIEW);
@@ -55335,6 +54362,16 @@ static JSValue js_dataview_constructor(JSContext *ctx,
JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
goto fail;
}
+ // RAB could have been resized in js_create_from_ctor()
+ if (offset > abuf->byte_length) {
+ goto out_of_bound;
+ } else if (recompute_len) {
+ len = abuf->byte_length - offset;
+ } else if (offset + len > abuf->byte_length) {
+ out_of_bound:
+ JS_ThrowRangeError(ctx, "invalid byteOffset or byteLength");
+ goto fail;
+ }
ta = js_malloc(ctx, sizeof(*ta));
if (!ta) {
fail:
@@ -55343,21 +54380,98 @@ static JSValue js_dataview_constructor(JSContext *ctx,
}
p = JS_VALUE_GET_OBJ(obj);
ta->obj = p;
- ta->buffer = JS_VALUE_GET_OBJ(JS_DupValue(ctx, buffer));
+ ta->buffer = JS_VALUE_GET_OBJ(js_dup(buffer));
ta->offset = offset;
ta->length = len;
+ ta->track_rab = track_rab;
list_add_tail(&ta->link, &abuf->array_list);
p->u.typed_array = ta;
return obj;
}
+// is the DataView out of bounds relative to its parent arraybuffer?
+static bool dataview_is_oob(JSObject *p)
+{
+ JSArrayBuffer *abuf;
+ JSTypedArray *ta;
+
+ assert(p->class_id == JS_CLASS_DATAVIEW);
+ ta = p->u.typed_array;
+ abuf = ta->buffer->u.array_buffer;
+ if (abuf->detached)
+ return true;
+ if (ta->offset > abuf->byte_length)
+ return true;
+ if (ta->track_rab)
+ return false;
+ return (int64_t)ta->offset + ta->length > abuf->byte_length;
+}
+
+static JSObject *get_dataview(JSContext *ctx, JSValue this_val)
+{
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
+ goto fail;
+ p = JS_VALUE_GET_OBJ(this_val);
+ if (p->class_id != JS_CLASS_DATAVIEW) {
+ fail:
+ JS_ThrowTypeError(ctx, "not a DataView");
+ return NULL;
+ }
+ return p;
+}
+
+static JSValue js_dataview_get_buffer(JSContext *ctx, JSValue this_val)
+{
+ JSObject *p;
+ JSTypedArray *ta;
+ p = get_dataview(ctx, this_val);
+ if (!p)
+ return JS_EXCEPTION;
+ ta = p->u.typed_array;
+ return js_dup(JS_MKPTR(JS_TAG_OBJECT, ta->buffer));
+}
+
+static JSValue js_dataview_get_byteLength(JSContext *ctx, JSValue this_val)
+{
+ JSArrayBuffer *abuf;
+ JSTypedArray *ta;
+ JSObject *p;
+
+ p = get_dataview(ctx, this_val);
+ if (!p)
+ return JS_EXCEPTION;
+ if (dataview_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ ta = p->u.typed_array;
+ if (ta->track_rab) {
+ abuf = ta->buffer->u.array_buffer;
+ return js_uint32(abuf->byte_length - ta->offset);
+ }
+ return js_uint32(ta->length);
+}
+
+static JSValue js_dataview_get_byteOffset(JSContext *ctx, JSValue this_val)
+{
+ JSTypedArray *ta;
+ JSObject *p;
+
+ p = get_dataview(ctx, this_val);
+ if (!p)
+ return JS_EXCEPTION;
+ if (dataview_is_oob(p))
+ return JS_ThrowTypeErrorArrayBufferOOB(ctx);
+ ta = p->u.typed_array;
+ return js_uint32(ta->offset);
+}
+
static JSValue js_dataview_getValue(JSContext *ctx,
- JSValueConst this_obj,
- int argc, JSValueConst *argv, int class_id)
+ JSValue this_obj,
+ int argc, JSValue *argv, int class_id)
{
JSTypedArray *ta;
JSArrayBuffer *abuf;
- BOOL littleEndian, is_swap;
+ bool littleEndian, is_swap;
int size;
uint8_t *ptr;
uint32_t v;
@@ -55374,35 +54488,41 @@ static JSValue js_dataview_getValue(JSContext *ctx,
abuf = ta->buffer->u.array_buffer;
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ // order matters: this check should come before the next one
if ((pos + size) > ta->length)
return JS_ThrowRangeError(ctx, "out of bound");
+ // test262 expects a TypeError for this and V8, in its infinite wisdom,
+ // throws a "detached array buffer" exception, but IMO that doesn't make
+ // sense because the buffer is not in fact detached, it's still there
+ if ((int64_t)ta->offset + ta->length > abuf->byte_length)
+ return JS_ThrowTypeError(ctx, "out of bound");
ptr = abuf->data + ta->offset + pos;
switch(class_id) {
case JS_CLASS_INT8_ARRAY:
- return JS_NewInt32(ctx, *(int8_t *)ptr);
+ return js_int32(*(int8_t *)ptr);
case JS_CLASS_UINT8_ARRAY:
- return JS_NewInt32(ctx, *(uint8_t *)ptr);
+ return js_int32(*(uint8_t *)ptr);
case JS_CLASS_INT16_ARRAY:
v = get_u16(ptr);
if (is_swap)
v = bswap16(v);
- return JS_NewInt32(ctx, (int16_t)v);
+ return js_int32((int16_t)v);
case JS_CLASS_UINT16_ARRAY:
v = get_u16(ptr);
if (is_swap)
v = bswap16(v);
- return JS_NewInt32(ctx, v);
+ return js_int32(v);
case JS_CLASS_INT32_ARRAY:
v = get_u32(ptr);
if (is_swap)
v = bswap32(v);
- return JS_NewInt32(ctx, v);
+ return js_int32(v);
case JS_CLASS_UINT32_ARRAY:
v = get_u32(ptr);
if (is_swap)
v = bswap32(v);
- return JS_NewUint32(ctx, v);
+ return js_uint32(v);
case JS_CLASS_BIG_INT64_ARRAY:
{
uint64_t v;
@@ -55421,6 +54541,14 @@ static JSValue js_dataview_getValue(JSContext *ctx,
return JS_NewBigUint64(ctx, v);
}
break;
+ case JS_CLASS_FLOAT16_ARRAY:
+ {
+ uint16_t v;
+ v = get_u16(ptr);
+ if (is_swap)
+ v = bswap16(v);
+ return js_float64(fromfp16(v));
+ }
case JS_CLASS_FLOAT32_ARRAY:
{
union {
@@ -55431,7 +54559,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
if (is_swap)
v = bswap32(v);
u.i = v;
- return __JS_NewFloat64(ctx, u.f);
+ return js_float64(u.f);
}
case JS_CLASS_FLOAT64_ARRAY:
{
@@ -55442,26 +54570,27 @@ static JSValue js_dataview_getValue(JSContext *ctx,
u.i = get_u64(ptr);
if (is_swap)
u.i = bswap64(u.i);
- return __JS_NewFloat64(ctx, u.f);
+ return js_float64(u.f);
}
default:
abort();
}
+ return JS_EXCEPTION; // pacify compiler
}
static JSValue js_dataview_setValue(JSContext *ctx,
- JSValueConst this_obj,
- int argc, JSValueConst *argv, int class_id)
+ JSValue this_obj,
+ int argc, JSValue *argv, int class_id)
{
JSTypedArray *ta;
JSArrayBuffer *abuf;
- BOOL littleEndian, is_swap;
+ bool littleEndian, is_swap;
int size;
uint8_t *ptr;
uint64_t v64;
uint32_t v;
uint64_t pos;
- JSValueConst val;
+ JSValue val;
ta = JS_GetOpaque2(ctx, this_obj, JS_CLASS_DATAVIEW);
if (!ta)
@@ -55475,14 +54604,17 @@ static JSValue js_dataview_setValue(JSContext *ctx,
if (class_id <= JS_CLASS_UINT32_ARRAY) {
if (JS_ToUint32(ctx, &v, val))
return JS_EXCEPTION;
- } else if (class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
+ } else
+ if (class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
if (JS_ToBigInt64(ctx, (int64_t *)&v64, val))
return JS_EXCEPTION;
} else {
double d;
if (JS_ToFloat64(ctx, &d, val))
return JS_EXCEPTION;
- if (class_id == JS_CLASS_FLOAT32_ARRAY) {
+ if (class_id == JS_CLASS_FLOAT16_ARRAY) {
+ v = tofp16(d);
+ } else if (class_id == JS_CLASS_FLOAT32_ARRAY) {
union {
float f;
uint32_t i;
@@ -55500,8 +54632,14 @@ static JSValue js_dataview_setValue(JSContext *ctx,
abuf = ta->buffer->u.array_buffer;
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ // order matters: this check should come before the next one
if ((pos + size) > ta->length)
return JS_ThrowRangeError(ctx, "out of bound");
+ // test262 expects a TypeError for this and V8, in its infinite wisdom,
+ // throws a "detached array buffer" exception, but IMO that doesn't make
+ // sense because the buffer is not in fact detached, it's still there
+ if ((int64_t)ta->offset + ta->length > abuf->byte_length)
+ return JS_ThrowTypeError(ctx, "out of bound");
ptr = abuf->data + ta->offset + pos;
switch(class_id) {
@@ -55511,6 +54649,7 @@ static JSValue js_dataview_setValue(JSContext *ctx,
break;
case JS_CLASS_INT16_ARRAY:
case JS_CLASS_UINT16_ARRAY:
+ case JS_CLASS_FLOAT16_ARRAY:
if (is_swap)
v = bswap16(v);
put_u16(ptr, v);
@@ -55536,9 +54675,9 @@ static JSValue js_dataview_setValue(JSContext *ctx,
}
static const JSCFunctionListEntry js_dataview_proto_funcs[] = {
- JS_CGETSET_MAGIC_DEF("buffer", js_typed_array_get_buffer, NULL, 1 ),
- JS_CGETSET_MAGIC_DEF("byteLength", js_typed_array_get_byteLength, NULL, 1 ),
- JS_CGETSET_MAGIC_DEF("byteOffset", js_typed_array_get_byteOffset, NULL, 1 ),
+ JS_CGETSET_DEF("buffer", js_dataview_get_buffer, NULL ),
+ JS_CGETSET_DEF("byteLength", js_dataview_get_byteLength, NULL ),
+ JS_CGETSET_DEF("byteOffset", js_dataview_get_byteOffset, NULL ),
JS_CFUNC_MAGIC_DEF("getInt8", 1, js_dataview_getValue, JS_CLASS_INT8_ARRAY ),
JS_CFUNC_MAGIC_DEF("getUint8", 1, js_dataview_getValue, JS_CLASS_UINT8_ARRAY ),
JS_CFUNC_MAGIC_DEF("getInt16", 1, js_dataview_getValue, JS_CLASS_INT16_ARRAY ),
@@ -55547,6 +54686,7 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("getUint32", 1, js_dataview_getValue, JS_CLASS_UINT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("getBigInt64", 1, js_dataview_getValue, JS_CLASS_BIG_INT64_ARRAY ),
JS_CFUNC_MAGIC_DEF("getBigUint64", 1, js_dataview_getValue, JS_CLASS_BIG_UINT64_ARRAY ),
+ JS_CFUNC_MAGIC_DEF("getFloat16", 1, js_dataview_getValue, JS_CLASS_FLOAT16_ARRAY ),
JS_CFUNC_MAGIC_DEF("getFloat32", 1, js_dataview_getValue, JS_CLASS_FLOAT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("getFloat64", 1, js_dataview_getValue, JS_CLASS_FLOAT64_ARRAY ),
JS_CFUNC_MAGIC_DEF("setInt8", 2, js_dataview_setValue, JS_CLASS_INT8_ARRAY ),
@@ -55557,11 +54697,62 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("setUint32", 2, js_dataview_setValue, JS_CLASS_UINT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("setBigInt64", 2, js_dataview_setValue, JS_CLASS_BIG_INT64_ARRAY ),
JS_CFUNC_MAGIC_DEF("setBigUint64", 2, js_dataview_setValue, JS_CLASS_BIG_UINT64_ARRAY ),
+ JS_CFUNC_MAGIC_DEF("setFloat16", 2, js_dataview_setValue, JS_CLASS_FLOAT16_ARRAY ),
JS_CFUNC_MAGIC_DEF("setFloat32", 2, js_dataview_setValue, JS_CLASS_FLOAT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("setFloat64", 2, js_dataview_setValue, JS_CLASS_FLOAT64_ARRAY ),
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "DataView", JS_PROP_CONFIGURABLE ),
};
+static JSValue js_new_uint8array(JSContext *ctx, JSValue buffer)
+{
+ if (JS_IsException(buffer))
+ return JS_EXCEPTION;
+ JSValue obj = js_create_from_ctor(ctx, JS_UNDEFINED, JS_CLASS_UINT8_ARRAY);
+ if (JS_IsException(obj)) {
+ JS_FreeValue(ctx, buffer);
+ return JS_EXCEPTION;
+ }
+ JSArrayBuffer *abuf = js_get_array_buffer(ctx, buffer);
+ assert(abuf != NULL);
+ if (typed_array_init(ctx, obj, buffer, 0, abuf->byte_length, /*track_rab*/false)) {
+ // 'buffer' is freed on error above.
+ JS_FreeValue(ctx, obj);
+ return JS_EXCEPTION;
+ }
+ return obj;
+}
+
+JSValue JS_NewUint8Array(JSContext *ctx, uint8_t *buf, size_t len,
+ JSFreeArrayBufferDataFunc *free_func, void *opaque,
+ bool is_shared)
+{
+ JSClassID class_id =
+ is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER;
+ JSValue buffer = js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL,
+ class_id, buf, free_func,
+ opaque, false);
+ return js_new_uint8array(ctx, buffer);
+}
+
+JSValue JS_NewUint8ArrayCopy(JSContext *ctx, const uint8_t *buf, size_t len)
+{
+ JSValue buffer = js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL,
+ JS_CLASS_ARRAY_BUFFER,
+ (uint8_t *)buf,
+ js_array_buffer_free, NULL,
+ true);
+ return js_new_uint8array(ctx, buffer);
+}
+
+int JS_GetTypedArrayType(JSValue obj)
+{
+ JSClassID class_id = JS_GetClassID(obj);
+ if (is_typed_array(class_id))
+ return class_id - JS_CLASS_UINT8C_ARRAY;
+ else
+ return -1;
+}
+
/* Atomics */
#ifdef CONFIG_ATOMICS
@@ -55579,7 +54770,7 @@ typedef enum AtomicsOpEnum {
static void *js_atomics_get_ptr(JSContext *ctx,
JSArrayBuffer **pabuf,
int *psize_log2, JSClassID *pclass_id,
- JSValueConst obj, JSValueConst idx_val,
+ JSValue obj, JSValue idx_val,
int is_waitable)
{
JSObject *p;
@@ -55587,7 +54778,7 @@ static void *js_atomics_get_ptr(JSContext *ctx,
JSArrayBuffer *abuf;
void *ptr;
uint64_t idx;
- BOOL err;
+ bool err;
int size_log2;
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
@@ -55636,8 +54827,8 @@ static void *js_atomics_get_ptr(JSContext *ctx,
}
static JSValue js_atomics_op(JSContext *ctx,
- JSValueConst this_obj,
- int argc, JSValueConst *argv, int op)
+ JSValue this_obj,
+ int argc, JSValue *argv, int op)
{
int size_log2;
uint64_t v, a, rep_val;
@@ -55665,15 +54856,15 @@ static JSValue js_atomics_op(JSContext *ctx,
rep_val = v64;
}
} else {
- uint32_t v32;
- if (JS_ToUint32(ctx, &v32, argv[2]))
- return JS_EXCEPTION;
- v = v32;
- if (op == ATOMICS_OP_COMPARE_EXCHANGE) {
- if (JS_ToUint32(ctx, &v32, argv[3]))
- return JS_EXCEPTION;
- rep_val = v32;
- }
+ uint32_t v32;
+ if (JS_ToUint32(ctx, &v32, argv[2]))
+ return JS_EXCEPTION;
+ v = v32;
+ if (op == ATOMICS_OP_COMPARE_EXCHANGE) {
+ if (JS_ToUint32(ctx, &v32, argv[3]))
+ return JS_EXCEPTION;
+ rep_val = v32;
+ }
}
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
@@ -55683,18 +54874,17 @@ static JSValue js_atomics_op(JSContext *ctx,
#define OP(op_name, func_name) \
case ATOMICS_OP_ ## op_name | (0 << 3): \
- a = func_name((_Atomic(uint8_t) *)ptr, v); \
+ a = func_name((_Atomic uint8_t *)ptr, v); \
break; \
case ATOMICS_OP_ ## op_name | (1 << 3): \
- a = func_name((_Atomic(uint16_t) *)ptr, v); \
+ a = func_name((_Atomic uint16_t *)ptr, v); \
break; \
case ATOMICS_OP_ ## op_name | (2 << 3): \
- a = func_name((_Atomic(uint32_t) *)ptr, v); \
+ a = func_name((_Atomic uint32_t *)ptr, v); \
break; \
case ATOMICS_OP_ ## op_name | (3 << 3): \
- a = func_name((_Atomic(uint64_t) *)ptr, v); \
+ a = func_name((_Atomic uint64_t *)ptr, v); \
break;
-
OP(ADD, atomic_fetch_add)
OP(AND, atomic_fetch_and)
OP(OR, atomic_fetch_or)
@@ -55704,43 +54894,42 @@ static JSValue js_atomics_op(JSContext *ctx,
#undef OP
case ATOMICS_OP_LOAD | (0 << 3):
- a = atomic_load((_Atomic(uint8_t) *)ptr);
+ a = atomic_load((_Atomic uint8_t *)ptr);
break;
case ATOMICS_OP_LOAD | (1 << 3):
- a = atomic_load((_Atomic(uint16_t) *)ptr);
+ a = atomic_load((_Atomic uint16_t *)ptr);
break;
case ATOMICS_OP_LOAD | (2 << 3):
- a = atomic_load((_Atomic(uint32_t) *)ptr);
+ a = atomic_load((_Atomic uint32_t *)ptr);
break;
case ATOMICS_OP_LOAD | (3 << 3):
- a = atomic_load((_Atomic(uint64_t) *)ptr);
+ a = atomic_load((_Atomic uint64_t *)ptr);
break;
-
case ATOMICS_OP_COMPARE_EXCHANGE | (0 << 3):
{
uint8_t v1 = v;
- atomic_compare_exchange_strong((_Atomic(uint8_t) *)ptr, &v1, rep_val);
+ atomic_compare_exchange_strong((_Atomic uint8_t *)ptr, &v1, rep_val);
a = v1;
}
break;
case ATOMICS_OP_COMPARE_EXCHANGE | (1 << 3):
{
uint16_t v1 = v;
- atomic_compare_exchange_strong((_Atomic(uint16_t) *)ptr, &v1, rep_val);
+ atomic_compare_exchange_strong((_Atomic uint16_t *)ptr, &v1, rep_val);
a = v1;
}
break;
case ATOMICS_OP_COMPARE_EXCHANGE | (2 << 3):
{
uint32_t v1 = v;
- atomic_compare_exchange_strong((_Atomic(uint32_t) *)ptr, &v1, rep_val);
+ atomic_compare_exchange_strong((_Atomic uint32_t *)ptr, &v1, rep_val);
a = v1;
}
break;
case ATOMICS_OP_COMPARE_EXCHANGE | (3 << 3):
{
uint64_t v1 = v;
- atomic_compare_exchange_strong((_Atomic(uint64_t) *)ptr, &v1, rep_val);
+ atomic_compare_exchange_strong((_Atomic uint64_t *)ptr, &v1, rep_val);
a = v1;
}
break;
@@ -55763,10 +54952,10 @@ static JSValue js_atomics_op(JSContext *ctx,
goto done;
case JS_CLASS_INT32_ARRAY:
done:
- ret = JS_NewInt32(ctx, a);
+ ret = js_int32(a);
break;
case JS_CLASS_UINT32_ARRAY:
- ret = JS_NewUint32(ctx, a);
+ ret = js_uint32(a);
break;
case JS_CLASS_BIG_INT64_ARRAY:
ret = JS_NewBigInt64(ctx, a);
@@ -55781,8 +54970,8 @@ static JSValue js_atomics_op(JSContext *ctx,
}
static JSValue js_atomics_store(JSContext *ctx,
- JSValueConst this_obj,
- int argc, JSValueConst *argv)
+ JSValue this_obj,
+ int argc, JSValue *argv)
{
int size_log2;
void *ptr;
@@ -55795,7 +54984,7 @@ static JSValue js_atomics_store(JSContext *ctx,
return JS_EXCEPTION;
if (size_log2 == 3) {
int64_t v64;
- ret = JS_ToBigIntValueFree(ctx, JS_DupValue(ctx, argv[2]));
+ ret = JS_ToBigIntValueFree(ctx, js_dup(argv[2]));
if (JS_IsException(ret))
return ret;
if (JS_ToBigInt64(ctx, &v64, ret)) {
@@ -55804,11 +54993,11 @@ static JSValue js_atomics_store(JSContext *ctx,
}
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
- atomic_store((_Atomic(uint64_t) *)ptr, v64);
+ atomic_store((_Atomic uint64_t *)ptr, v64);
} else {
uint32_t v;
/* XXX: spec, would be simpler to return the written value */
- ret = JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[2]));
+ ret = JS_ToIntegerFree(ctx, js_dup(argv[2]));
if (JS_IsException(ret))
return ret;
if (JS_ToUint32(ctx, &v, ret)) {
@@ -55819,13 +55008,13 @@ static JSValue js_atomics_store(JSContext *ctx,
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
switch(size_log2) {
case 0:
- atomic_store((_Atomic(uint8_t) *)ptr, v);
+ atomic_store((_Atomic uint8_t *)ptr, v);
break;
case 1:
- atomic_store((_Atomic(uint16_t) *)ptr, v);
+ atomic_store((_Atomic uint16_t *)ptr, v);
break;
case 2:
- atomic_store((_Atomic(uint32_t) *)ptr, v);
+ atomic_store((_Atomic uint32_t *)ptr, v);
break;
default:
abort();
@@ -55835,36 +55024,62 @@ static JSValue js_atomics_store(JSContext *ctx,
}
static JSValue js_atomics_isLockFree(JSContext *ctx,
- JSValueConst this_obj,
- int argc, JSValueConst *argv)
+ JSValue this_obj,
+ int argc, JSValue *argv)
{
int v, ret;
if (JS_ToInt32Sat(ctx, &v, argv[0]))
return JS_EXCEPTION;
ret = (v == 1 || v == 2 || v == 4 || v == 8);
- return JS_NewBool(ctx, ret);
+ return js_bool(ret);
}
typedef struct JSAtomicsWaiter {
struct list_head link;
- BOOL linked;
- pthread_cond_t cond;
+ bool linked;
+ js_cond_t cond;
int32_t *ptr;
} JSAtomicsWaiter;
-static pthread_mutex_t js_atomics_mutex = PTHREAD_MUTEX_INITIALIZER;
+static js_once_t js_atomics_once = JS_ONCE_INIT;
+static js_mutex_t js_atomics_mutex;
static struct list_head js_atomics_waiter_list =
LIST_HEAD_INIT(js_atomics_waiter_list);
+// no-op: Atomics.pause() is not allowed to block or yield to another
+// thread, only to hint the CPU that it should back off for a bit;
+// the amount of work we do here is a good enough substitute
+static JSValue js_atomics_pause(JSContext *ctx, JSValue this_obj,
+ int argc, JSValue *argv)
+{
+ double d;
+
+ if (argc > 0) {
+ switch (JS_VALUE_GET_TAG(argv[0])) {
+ case JS_TAG_FLOAT64: // accepted if and only if fraction == 0.0
+ d = JS_VALUE_GET_FLOAT64(argv[0]);
+ if (isfinite(d))
+ if (0 == modf(d, &d))
+ break;
+ // fallthru
+ default:
+ return JS_ThrowTypeError(ctx, "not an integral number");
+ case JS_TAG_UNDEFINED:
+ case JS_TAG_INT:
+ break;
+ }
+ }
+ return JS_UNDEFINED;
+}
+
static JSValue js_atomics_wait(JSContext *ctx,
- JSValueConst this_obj,
- int argc, JSValueConst *argv)
+ JSValue this_obj,
+ int argc, JSValue *argv)
{
int64_t v;
int32_t v32;
void *ptr;
int64_t timeout;
- struct timespec ts;
JSAtomicsWaiter waiter_s, *waiter;
int ret, size_log2, res;
double d;
@@ -55883,7 +55098,6 @@ static JSValue js_atomics_wait(JSContext *ctx,
}
if (JS_ToFloat64(ctx, &d, argv[3]))
return JS_EXCEPTION;
- /* must use INT64_MAX + 1 because INT64_MAX cannot be exactly represented as a double */
if (isnan(d) || d >= 0x1p63)
timeout = INT64_MAX;
else if (d < 0)
@@ -55895,44 +55109,34 @@ static JSValue js_atomics_wait(JSContext *ctx,
/* XXX: inefficient if large number of waiters, should hash on
'ptr' value */
- /* XXX: use Linux futexes when available ? */
- pthread_mutex_lock(&js_atomics_mutex);
+ js_mutex_lock(&js_atomics_mutex);
if (size_log2 == 3) {
res = *(int64_t *)ptr != v;
} else {
res = *(int32_t *)ptr != v;
}
if (res) {
- pthread_mutex_unlock(&js_atomics_mutex);
+ js_mutex_unlock(&js_atomics_mutex);
return JS_AtomToString(ctx, JS_ATOM_not_equal);
}
waiter = &waiter_s;
waiter->ptr = ptr;
- pthread_cond_init(&waiter->cond, NULL);
- waiter->linked = TRUE;
+ js_cond_init(&waiter->cond);
+ waiter->linked = true;
list_add_tail(&waiter->link, &js_atomics_waiter_list);
if (timeout == INT64_MAX) {
- pthread_cond_wait(&waiter->cond, &js_atomics_mutex);
+ js_cond_wait(&waiter->cond, &js_atomics_mutex);
ret = 0;
} else {
- /* XXX: use clock monotonic */
- clock_gettime(CLOCK_REALTIME, &ts);
- ts.tv_sec += timeout / 1000;
- ts.tv_nsec += (timeout % 1000) * 1000000;
- if (ts.tv_nsec >= 1000000000) {
- ts.tv_nsec -= 1000000000;
- ts.tv_sec++;
- }
- ret = pthread_cond_timedwait(&waiter->cond, &js_atomics_mutex,
- &ts);
+ ret = js_cond_timedwait(&waiter->cond, &js_atomics_mutex, timeout * 1e6 /* to ns */);
}
if (waiter->linked)
list_del(&waiter->link);
- pthread_mutex_unlock(&js_atomics_mutex);
- pthread_cond_destroy(&waiter->cond);
- if (ret == ETIMEDOUT) {
+ js_mutex_unlock(&js_atomics_mutex);
+ js_cond_destroy(&waiter->cond);
+ if (ret == -1) {
return JS_AtomToString(ctx, JS_ATOM_timed_out);
} else {
return JS_AtomToString(ctx, JS_ATOM_ok);
@@ -55940,8 +55144,8 @@ static JSValue js_atomics_wait(JSContext *ctx,
}
static JSValue js_atomics_notify(JSContext *ctx,
- JSValueConst this_obj,
- int argc, JSValueConst *argv)
+ JSValue this_obj,
+ int argc, JSValue *argv)
{
struct list_head *el, *el1, waiter_list;
int32_t count, n;
@@ -55964,13 +55168,13 @@ static JSValue js_atomics_notify(JSContext *ctx,
n = 0;
if (abuf->shared && count > 0) {
- pthread_mutex_lock(&js_atomics_mutex);
+ js_mutex_lock(&js_atomics_mutex);
init_list_head(&waiter_list);
list_for_each_safe(el, el1, &js_atomics_waiter_list) {
waiter = list_entry(el, JSAtomicsWaiter, link);
if (waiter->ptr == ptr) {
list_del(&waiter->link);
- waiter->linked = FALSE;
+ waiter->linked = false;
list_add_tail(&waiter->link, &waiter_list);
n++;
if (n >= count)
@@ -55979,11 +55183,11 @@ static JSValue js_atomics_notify(JSContext *ctx,
}
list_for_each(el, &waiter_list) {
waiter = list_entry(el, JSAtomicsWaiter, link);
- pthread_cond_signal(&waiter->cond);
+ js_cond_signal(&waiter->cond);
}
- pthread_mutex_unlock(&js_atomics_mutex);
+ js_mutex_unlock(&js_atomics_mutex);
}
- return JS_NewInt32(ctx, n);
+ return js_int32(n);
}
static const JSCFunctionListEntry js_atomics_funcs[] = {
@@ -55997,6 +55201,7 @@ static const JSCFunctionListEntry js_atomics_funcs[] = {
JS_CFUNC_MAGIC_DEF("load", 2, js_atomics_op, ATOMICS_OP_LOAD ),
JS_CFUNC_DEF("store", 3, js_atomics_store ),
JS_CFUNC_DEF("isLockFree", 1, js_atomics_isLockFree ),
+ JS_CFUNC_DEF("pause", 0, js_atomics_pause ),
JS_CFUNC_DEF("wait", 4, js_atomics_wait ),
JS_CFUNC_DEF("notify", 3, js_atomics_notify ),
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Atomics", JS_PROP_CONFIGURABLE ),
@@ -56006,8 +55211,15 @@ static const JSCFunctionListEntry js_atomics_obj[] = {
JS_OBJECT_DEF("Atomics", js_atomics_funcs, countof(js_atomics_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),
};
+static void js__atomics_init(void) {
+ js_mutex_init(&js_atomics_mutex);
+}
+
+/* TODO(saghul) make this public and not dependent on typed arrays? */
void JS_AddIntrinsicAtomics(JSContext *ctx)
{
+ js_once(&js_atomics_once, js__atomics_init);
+
/* add Atomics as autoinit object */
JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj));
}
@@ -56017,7 +55229,7 @@ void JS_AddIntrinsicAtomics(JSContext *ctx)
void JS_AddIntrinsicTypedArrays(JSContext *ctx)
{
JSValue typed_array_base_proto, typed_array_base_func;
- JSValueConst array_buffer_func, shared_array_buffer_func;
+ JSValue array_buffer_func, shared_array_buffer_func;
int i;
ctx->class_proto[JS_CLASS_ARRAY_BUFFER] = JS_NewObject(ctx);
@@ -56072,7 +55284,7 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx)
ctx->class_proto[i] = JS_NewObjectProto(ctx, typed_array_base_proto);
JS_DefinePropertyValueStr(ctx, ctx->class_proto[i],
"BYTES_PER_ELEMENT",
- JS_NewInt32(ctx, 1 << typed_array_size_log2(i)),
+ js_int32(1 << typed_array_size_log2(i)),
0);
name = JS_AtomGetStr(ctx, buf, sizeof(buf),
JS_ATOM_Uint8ClampedArray + i - JS_CLASS_UINT8C_ARRAY);
@@ -56082,7 +55294,7 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx)
JS_NewGlobalCConstructor2(ctx, func_obj, name, ctx->class_proto[i]);
JS_DefinePropertyValueStr(ctx, func_obj,
"BYTES_PER_ELEMENT",
- JS_NewInt32(ctx, 1 << typed_array_size_log2(i)),
+ js_int32(1 << typed_array_size_log2(i)),
0);
}
JS_FreeValue(ctx, typed_array_base_proto);
@@ -56102,166 +55314,678 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx)
#endif
}
-#ifndef NDEBUG
-static void *watchedRefCount = NULL;
+/* Performance */
-void notifyRefCountIncrease(JSRefCountHeader *p)
+static double js__now_ms(void)
{
- if (p == watchedRefCount)
- fprintf(stderr, "increasing ref count %d for %p\n", p->ref_count, watchedRefCount);
+ return js__hrtime_ns() / 1e6;
}
-void notifyRefCountDecrease(JSRefCountHeader *p)
+static JSValue js_perf_now(JSContext *ctx, JSValue this_val, int argc, JSValue *argv)
{
- if (p == watchedRefCount)
- fprintf(stderr, "decreasing ref count %d for %p\n", p->ref_count, watchedRefCount);
+ return js_float64(js__now_ms() - ctx->time_origin);
}
-void watchRefCount(void *p)
+static const JSCFunctionListEntry js_perf_proto_funcs[] = {
+ JS_CFUNC_DEF2("now", 0, js_perf_now, JS_PROP_ENUMERABLE),
+};
+
+void JS_AddPerformance(JSContext *ctx)
{
- watchedRefCount = p;
+ ctx->time_origin = js__now_ms();
+
+ JSValue performance = JS_NewObject(ctx);
+ JS_SetPropertyFunctionList(ctx, performance, js_perf_proto_funcs, countof(js_perf_proto_funcs));
+ JS_DefinePropertyValueStr(ctx, performance, "timeOrigin",
+ js_float64(ctx->time_origin),
+ JS_PROP_ENUMERABLE);
+ JS_DefinePropertyValueStr(ctx, ctx->global_obj, "performance",
+ js_dup(performance),
+ JS_PROP_WRITABLE | JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE);
+ JS_FreeValue(ctx, performance);
}
-#endif
-void setScopeLookup(JSContext *ctx, ScopeLookup *scopeLookup)
+/* Equality comparisons and sameness */
+int JS_IsEqual(JSContext *ctx, JSValue op1, JSValue op2)
{
- ctx->scopeLookup = scopeLookup;
+ JSValue sp[2] = { js_dup(op1), js_dup(op2) };
+ if (js_eq_slow(ctx, endof(sp), 0))
+ return -1;
+ return JS_VALUE_GET_BOOL(sp[0]);
}
-void setFoundUndefinedHandler(JSContext *ctx, FoundUndefinedHandler *handler)
+bool JS_IsStrictEqual(JSContext *ctx, JSValue op1, JSValue op2)
{
- ctx->handleUndefined = handler;
+ return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_STRICT);
}
-void setFunctionEnteredHandler(JSContext *ctx, FunctionEnteredHandler *handler)
+bool JS_IsSameValue(JSContext *ctx, JSValue op1, JSValue op2)
{
- ctx->handleFunctionEntered = handler;
+ return js_same_value(ctx, op1, op2);
}
-void setFunctionExitedHandler(JSContext *ctx, FunctionExitedHandler *handler)
+bool JS_IsSameValueZero(JSContext *ctx, JSValue op1, JSValue op2)
{
- ctx->handleFunctionExited = handler;
+ return js_same_value_zero(ctx, op1, op2);
}
-int isSimpleValue(JSValue v)
+/* WeakRef */
+
+typedef struct JSWeakRefData {
+ JSValue target;
+ JSValue obj;
+} JSWeakRefData;
+
+static JSWeakRefData js_weakref_sentinel;
+
+static void js_weakref_finalizer(JSRuntime *rt, JSValue val)
{
- JSObject *p;
- if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
- return 1;
- p = JS_VALUE_GET_OBJ(v);
- return p->class_id >= JS_CLASS_OBJECT && p->class_id <= JS_CLASS_BOOLEAN;
+ JSWeakRefData *wrd = JS_GetOpaque(val, JS_CLASS_WEAK_REF);
+ if (!wrd || wrd == &js_weakref_sentinel)
+ return;
+
+ /* Delete weak ref */
+ JSWeakRefRecord **pwr, *wr;
+
+ pwr = get_first_weak_ref(wrd->target);
+ for(;;) {
+ wr = *pwr;
+ assert(wr != NULL);
+ if (wr->kind == JS_WEAK_REF_KIND_WEAK_REF && wr->u.weak_ref_data == wrd)
+ break;
+ pwr = &wr->next_weak_ref;
+ }
+ *pwr = wr->next_weak_ref;
+ js_free_rt(rt, wrd);
+ js_free_rt(rt, wr);
}
-JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
- const char *name, int length,
- JSCFunctionEnum cproto, int magic)
+static JSValue js_weakref_constructor(JSContext *ctx, JSValue new_target, int argc, JSValue *argv)
{
- return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto,
- magic);
+ if (JS_IsUndefined(new_target))
+ return JS_ThrowTypeError(ctx, "constructor requires 'new'");
+ JSValue arg = argv[0];
+ if (!is_valid_weakref_target(arg))
+ return JS_ThrowTypeError(ctx, "invalid target");
+ // TODO(saghul): short-circuit if the refcount is 1?
+ JSValue obj = js_create_from_ctor(ctx, new_target, JS_CLASS_WEAK_REF);
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+ JSWeakRefData *wrd = js_malloc(ctx, sizeof(*wrd));
+ if (!wrd) {
+ JS_FreeValue(ctx, obj);
+ return JS_EXCEPTION;
+ }
+ JSWeakRefRecord *wr = js_malloc(ctx, sizeof(*wr));
+ if (!wr) {
+ JS_FreeValue(ctx, obj);
+ js_free(ctx, wrd);
+ return JS_EXCEPTION;
+ }
+ wrd->target = arg;
+ wrd->obj = obj;
+ wr->kind = JS_WEAK_REF_KIND_WEAK_REF;
+ wr->u.weak_ref_data = wrd;
+ insert_weakref_record(arg, wr);
+
+ JS_SetOpaqueInternal(obj, wrd);
+ return obj;
}
-#ifdef JS_NAN_BOXING
-JSValue mkVal(int32_t tag, int32_t val)
+static JSValue js_weakref_deref(JSContext *ctx, JSValue this_val, int argc, JSValue *argv)
{
- return ((uint64_t)(tag) << 32) | (uint32_t)(val);
+ JSWeakRefData *wrd = JS_GetOpaque2(ctx, this_val, JS_CLASS_WEAK_REF);
+ if (!wrd)
+ return JS_EXCEPTION;
+ if (wrd == &js_weakref_sentinel)
+ return JS_UNDEFINED;
+ return js_dup(wrd->target);
}
-JSValue mkPtr(int32_t tag, void *p)
+static const JSCFunctionListEntry js_weakref_proto_funcs[] = {
+ JS_CFUNC_DEF("deref", 0, js_weakref_deref ),
+ JS_PROP_STRING_DEF("[Symbol.toStringTag]", "WeakRef", JS_PROP_CONFIGURABLE ),
+};
+
+static const JSClassShortDef js_weakref_class_def[] = {
+ { JS_ATOM_WeakRef, js_weakref_finalizer, NULL }, /* JS_CLASS_WEAK_REF */
+};
+
+typedef struct JSFinRecEntry {
+ struct list_head link;
+ JSValue obj;
+ JSValue target;
+ JSValue held_val;
+ JSValue token;
+} JSFinRecEntry;
+
+typedef struct JSFinalizationRegistryData {
+ struct list_head entries;
+ JSContext *ctx;
+ JSValue cb;
+} JSFinalizationRegistryData;
+
+static void delete_finrec_weakref(JSRuntime *rt, JSFinRecEntry *fre)
{
- return ((uint64_t)(tag) << 32) | (uintptr_t)(p);
+ JSWeakRefRecord **pwr, *wr;
+
+ pwr = get_first_weak_ref(fre->target);
+ for(;;) {
+ wr = *pwr;
+ assert(wr != NULL);
+ if (wr->kind == JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY && wr->u.fin_rec_entry == fre)
+ break;
+ pwr = &wr->next_weak_ref;
+ }
+ *pwr = wr->next_weak_ref;
+ js_free_rt(rt, wr);
}
-#else
-JSValue mkVal(int32_t tag, int32_t val)
+
+static void js_finrec_finalizer(JSRuntime *rt, JSValue val)
{
- return (JSValue){ (JSValueUnion){ .int32 = val }, tag };
+ JSFinalizationRegistryData *frd = JS_GetOpaque(val, JS_CLASS_FINALIZATION_REGISTRY);
+ if (frd) {
+ struct list_head *el, *el1;
+ /* first pass to remove the weak ref entries and avoid having them modified
+ by freeing a token / held value. */
+ list_for_each_safe(el, el1, &frd->entries) {
+ JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link);
+ delete_finrec_weakref(rt, fre);
+ }
+ /* second pass to actually free all objects. */
+ list_for_each_safe(el, el1, &frd->entries) {
+ JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link);
+ list_del(&fre->link);
+ JS_FreeValueRT(rt, fre->held_val);
+ JS_FreeValueRT(rt, fre->token);
+ js_free_rt(rt, fre);
+ }
+ JS_FreeValueRT(rt, frd->cb);
+ js_free_rt(rt, frd);
+ }
}
-JSValue mkPtr(int32_t tag, void *p)
+static void js_finrec_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func)
{
- return (JSValue){ (JSValueUnion){ .ptr = p }, tag };
+ JSFinalizationRegistryData *frd = JS_GetOpaque(val, JS_CLASS_FINALIZATION_REGISTRY);
+ if (frd) {
+ JS_MarkValue(rt, frd->cb, mark_func);
+ struct list_head *el;
+ list_for_each(el, &frd->entries) {
+ JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link);
+ JS_MarkValue(rt, fre->held_val, mark_func);
+ JS_MarkValue(rt, fre->token, mark_func);
+ }
+ }
}
-#endif
-void JS_FreeValue(JSContext *ctx, JSValue v) {
- if (JS_VALUE_HAS_REF_COUNT(v)) {
- JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-#ifndef NDEBUG
- notifyRefCountDecrease(p);
-#endif
- if (--p->ref_count <= 0) {
- __JS_FreeValue(ctx, v);
+static JSValue js_finrec_constructor(JSContext *ctx, JSValue new_target, int argc, JSValue *argv)
+{
+ if (JS_IsUndefined(new_target))
+ return JS_ThrowTypeError(ctx, "constructor requires 'new'");
+ JSValue cb = argv[0];
+ if (!JS_IsFunction(ctx, cb))
+ return JS_ThrowTypeError(ctx, "argument must be a function");
+
+ JSValue obj = js_create_from_ctor(ctx, new_target, JS_CLASS_FINALIZATION_REGISTRY);
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+ JSFinalizationRegistryData *frd = js_malloc(ctx, sizeof(*frd));
+ if (!frd) {
+ JS_FreeValue(ctx, obj);
+ return JS_EXCEPTION;
+ }
+ init_list_head(&frd->entries);
+ frd->ctx = ctx;
+ frd->cb = js_dup(cb);
+ JS_SetOpaqueInternal(obj, frd);
+ return obj;
+}
+
+static JSValue js_finrec_register(JSContext *ctx, JSValue this_val, int argc, JSValue *argv)
+{
+ JSFinalizationRegistryData *frd = JS_GetOpaque2(ctx, this_val, JS_CLASS_FINALIZATION_REGISTRY);
+ if (!frd)
+ return JS_EXCEPTION;
+
+ JSValue target = argv[0];
+ JSValue held_val = argv[1];
+ // The function length needs to return 2, so the 3rd argument won't be initialized.
+ JSValue token = argc > 2 ? argv[2] : JS_UNDEFINED;
+
+ if (!is_valid_weakref_target(target))
+ return JS_ThrowTypeError(ctx, "invalid target");
+ if (js_same_value(ctx, target, this_val))
+ return JS_UNDEFINED;
+ if (!JS_IsUndefined(held_val) && js_same_value(ctx, target, held_val))
+ return JS_ThrowTypeError(ctx, "held value cannot be the target");
+ if (!JS_IsUndefined(token) && !is_valid_weakref_target(token))
+ return JS_ThrowTypeError(ctx, "invalid unregister token");
+
+ JSFinRecEntry *fre = js_malloc(ctx, sizeof(*fre));
+ if (!fre)
+ return JS_EXCEPTION;
+ JSWeakRefRecord *wr = js_malloc(ctx, sizeof(*wr));
+ if (!wr) {
+ js_free(ctx, fre);
+ return JS_EXCEPTION;
+ }
+ fre->obj = this_val;
+ fre->target = target;
+ fre->held_val = js_dup(held_val);
+ fre->token = js_dup(token);
+ list_add_tail(&fre->link, &frd->entries);
+ wr->kind = JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY;
+ wr->u.fin_rec_entry = fre;
+ insert_weakref_record(target, wr);
+
+ return JS_UNDEFINED;
+}
+
+static JSValue js_finrec_unregister(JSContext *ctx, JSValue this_val, int argc, JSValue *argv)
+{
+ JSFinalizationRegistryData *frd = JS_GetOpaque2(ctx, this_val, JS_CLASS_FINALIZATION_REGISTRY);
+ if (!frd)
+ return JS_EXCEPTION;
+
+ JSValue token = argv[0];
+ if (!is_valid_weakref_target(token))
+ return JS_ThrowTypeError(ctx, "invalid unregister token");
+
+ struct list_head *el, *el1;
+ bool removed = false;
+ list_for_each_safe(el, el1, &frd->entries) {
+ JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link);
+ if (js_same_value(ctx, fre->token, token)) {
+ list_del(&fre->link);
+ delete_finrec_weakref(ctx->rt, fre);
+ JS_FreeValue(ctx, fre->held_val);
+ JS_FreeValue(ctx, fre->token);
+ js_free(ctx, fre);
+ removed = true;
}
}
+
+ return js_bool(removed);
}
-void JS_FreeValueRT(JSRuntime *rt, JSValue v) {
- if (JS_VALUE_HAS_REF_COUNT(v)) {
- JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-#ifndef NDEBUG
- notifyRefCountDecrease(p);
-#endif
- if (--p->ref_count <= 0) {
- __JS_FreeValueRT(rt, v);
+
+static const JSCFunctionListEntry js_finrec_proto_funcs[] = {
+ JS_CFUNC_DEF("register", 2, js_finrec_register ),
+ JS_CFUNC_DEF("unregister", 1, js_finrec_unregister ),
+ JS_PROP_STRING_DEF("[Symbol.toStringTag]", "FinalizationRegistry", JS_PROP_CONFIGURABLE ),
+};
+
+static const JSClassShortDef js_finrec_class_def[] = {
+ { JS_ATOM_FinalizationRegistry, js_finrec_finalizer, js_finrec_mark }, /* JS_CLASS_FINALIZATION_REGISTRY */
+};
+
+static JSValue js_finrec_job(JSContext *ctx, int argc, JSValue *argv)
+{
+ return JS_Call(ctx, argv[0], JS_UNDEFINED, 1, &argv[1]);
+}
+
+void JS_AddIntrinsicWeakRef(JSContext *ctx)
+{
+ JSRuntime *rt = ctx->rt;
+
+ /* WeakRef */
+ if (!JS_IsRegisteredClass(rt, JS_CLASS_WEAK_REF)) {
+ init_class_range(rt, js_weakref_class_def, JS_CLASS_WEAK_REF,
+ countof(js_weakref_class_def));
+ }
+ ctx->class_proto[JS_CLASS_WEAK_REF] = JS_NewObject(ctx);
+ JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_WEAK_REF],
+ js_weakref_proto_funcs,
+ countof(js_weakref_proto_funcs));
+ JS_NewGlobalCConstructor(ctx, "WeakRef", js_weakref_constructor, 1, ctx->class_proto[JS_CLASS_WEAK_REF]);
+
+ /* FinalizationRegistry */
+ if (!JS_IsRegisteredClass(rt, JS_CLASS_FINALIZATION_REGISTRY)) {
+ init_class_range(rt, js_finrec_class_def, JS_CLASS_FINALIZATION_REGISTRY,
+ countof(js_finrec_class_def));
+ }
+ ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY] = JS_NewObject(ctx);
+ JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY],
+ js_finrec_proto_funcs,
+ countof(js_finrec_proto_funcs));
+ JS_NewGlobalCConstructor(ctx, "FinalizationRegistry", js_finrec_constructor, 1, ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY]);
+}
+
+static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref)
+{
+ JSWeakRefRecord *wr, *wr_next;
+ JSWeakRefData *wrd;
+ JSMapRecord *mr;
+ JSMapState *s;
+ JSFinRecEntry *fre;
+
+ /* first pass to remove the records from the WeakMap/WeakSet
+ lists */
+ for(wr = *first_weak_ref; wr != NULL; wr = wr->next_weak_ref) {
+ switch(wr->kind) {
+ case JS_WEAK_REF_KIND_MAP:
+ mr = wr->u.map_record;
+ s = mr->map;
+ assert(s->is_weak);
+ assert(!mr->empty); /* no iterator on WeakMap/WeakSet */
+ list_del(&mr->hash_link);
+ list_del(&mr->link);
+ break;
+ case JS_WEAK_REF_KIND_WEAK_REF:
+ wrd = wr->u.weak_ref_data;
+ wrd->target = JS_UNDEFINED;
+ break;
+ case JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY:
+ fre = wr->u.fin_rec_entry;
+ list_del(&fre->link);
+ break;
+ default:
+ abort();
}
}
+
+ /* second pass to free the values to avoid modifying the weak
+ reference list while traversing it. */
+ for(wr = *first_weak_ref; wr != NULL; wr = wr_next) {
+ wr_next = wr->next_weak_ref;
+ switch(wr->kind) {
+ case JS_WEAK_REF_KIND_MAP:
+ mr = wr->u.map_record;
+ JS_FreeValueRT(rt, mr->value);
+ js_free_rt(rt, mr);
+ break;
+ case JS_WEAK_REF_KIND_WEAK_REF:
+ wrd = wr->u.weak_ref_data;
+ JS_SetOpaqueInternal(wrd->obj, &js_weakref_sentinel);
+ js_free_rt(rt, wrd);
+ break;
+ case JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY: {
+ fre = wr->u.fin_rec_entry;
+ JSFinalizationRegistryData *frd = JS_GetOpaque(fre->obj, JS_CLASS_FINALIZATION_REGISTRY);
+ assert(frd != NULL);
+ /**
+ * During the GC sweep phase the held object might be collected first.
+ */
+ if (!rt->in_free && (!JS_IsObject(fre->held_val) || JS_IsLiveObject(rt, fre->held_val))) {
+ JSValue args[2];
+ args[0] = frd->cb;
+ args[1] = fre->held_val;
+ JS_EnqueueJob(frd->ctx, js_finrec_job, 2, args);
+ }
+ JS_FreeValueRT(rt, fre->held_val);
+ JS_FreeValueRT(rt, fre->token);
+ js_free_rt(rt, fre);
+ break;
+ }
+ default:
+ abort();
+ }
+ js_free_rt(rt, wr);
+ }
+
+ *first_weak_ref = NULL; /* fail safe */
}
-JSValue JS_NewBool(JSContext *ctx, JS_BOOL val) {
- (void)ctx;
- return JS_MKVAL(JS_TAG_BOOL, (val != 0));
+
+static bool is_valid_weakref_target(JSValue val)
+{
+ switch (JS_VALUE_GET_TAG(val)) {
+ case JS_TAG_OBJECT:
+ break;
+ case JS_TAG_SYMBOL: {
+ // Per spec: prohibit symbols registered with Symbol.for()
+ JSAtomStruct *p = JS_VALUE_GET_PTR(val);
+ if (p->atom_type != JS_ATOM_TYPE_GLOBAL_SYMBOL)
+ break;
+ // fallthru
+ }
+ default:
+ return false;
+ }
+
+ return true;
}
-JSValue JS_NewInt32(JSContext *ctx, int32_t val) {
- (void)ctx;
- return JS_MKVAL(JS_TAG_INT, val);
+
+static void insert_weakref_record(JSValue target, struct JSWeakRefRecord *wr)
+{
+ JSWeakRefRecord **pwr = get_first_weak_ref(target);
+ /* Add the weak reference */
+ wr->next_weak_ref = *pwr;
+ *pwr = wr;
}
-JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) {
- (void)ctx;
- return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
+
+/* CallSite */
+
+static void js_callsite_finalizer(JSRuntime *rt, JSValue val)
+{
+ JSCallSiteData *csd = JS_GetOpaque(val, JS_CLASS_CALL_SITE);
+ if (csd) {
+ JS_FreeValueRT(rt, csd->filename);
+ JS_FreeValueRT(rt, csd->func);
+ JS_FreeValueRT(rt, csd->func_name);
+ js_free_rt(rt, csd);
+ }
}
-JSValue JS_NewInt64(JSContext *ctx, int64_t val) {
- JSValue v;
- if (val == (int32_t)val) {
- v = JS_NewInt32(ctx, (int32_t)val);
- } else {
- v = __JS_NewFloat64(ctx, (double)val);
+
+static void js_callsite_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func)
+{
+ JSCallSiteData *csd = JS_GetOpaque(val, JS_CLASS_CALL_SITE);
+ if (csd) {
+ JS_MarkValue(rt, csd->filename, mark_func);
+ JS_MarkValue(rt, csd->func, mark_func);
+ JS_MarkValue(rt, csd->func_name, mark_func);
}
- return v;
}
-JSValue JS_NewUint32(JSContext *ctx, uint32_t val) {
- JSValue v;
- if (val <= 0x7fffffff) {
- v = JS_NewInt32(ctx, val);
+
+static JSValue js_new_callsite(JSContext *ctx, JSCallSiteData *csd) {
+ JSValue obj = js_create_from_ctor(ctx, JS_UNDEFINED, JS_CLASS_CALL_SITE);
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+
+ JSCallSiteData *csd1 = js_malloc(ctx, sizeof(*csd));
+ if (!csd1) {
+ JS_FreeValue(ctx, obj);
+ return JS_EXCEPTION;
+ }
+
+ memcpy(csd1, csd, sizeof(*csd));
+
+ JS_SetOpaqueInternal(obj, csd1);
+
+ return obj;
+}
+
+static void js_new_callsite_data(JSContext *ctx, JSCallSiteData *csd, JSStackFrame *sf)
+{
+ const char *func_name_str;
+ JSObject *p;
+
+ csd->func = js_dup(sf->cur_func);
+ /* func_name_str is UTF-8 encoded if needed */
+ func_name_str = get_func_name(ctx, sf->cur_func);
+ if (!func_name_str || func_name_str[0] == '\0')
+ csd->func_name = JS_NULL;
+ else
+ csd->func_name = JS_NewString(ctx, func_name_str);
+ JS_FreeCString(ctx, func_name_str);
+ if (JS_IsException(csd->func_name))
+ csd->func_name = JS_NULL;
+
+ p = JS_VALUE_GET_OBJ(sf->cur_func);
+ if (js_class_has_bytecode(p->class_id)) {
+ JSFunctionBytecode *b = p->u.func.function_bytecode;
+ int line_num1, col_num1;
+ line_num1 = find_line_num(ctx, b,
+ sf->cur_pc - b->byte_code_buf - 1,
+ &col_num1);
+ csd->native = false;
+ csd->line_num = line_num1;
+ csd->col_num = col_num1;
+ csd->filename = JS_AtomToString(ctx, b->filename);
+ if (JS_IsException(csd->filename)) {
+ csd->filename = JS_NULL;
+ JS_FreeValue(ctx, JS_GetException(ctx)); // Clear exception.
+ }
} else {
- v = __JS_NewFloat64(ctx, val);
+ csd->native = true;
+ csd->line_num = -1;
+ csd->col_num = -1;
+ csd->filename = JS_NULL;
}
- return v;
}
-JSValue JS_NewFloat64(JSContext *ctx, double d)
+
+static void js_new_callsite_data2(JSContext *ctx, JSCallSiteData *csd, const char *filename, int line_num, int col_num)
{
- int32_t val;
- union {
- double d;
- uint64_t u;
- } u, t;
- if (d >= INT32_MIN && d <= INT32_MAX) {
- u.d = d;
- val = (int32_t)d;
- t.d = val;
- /* -0 cannot be represented as integer, so we compare the bit
- representation */
- if (u.u == t.u)
- return JS_MKVAL(JS_TAG_INT, val);
+ csd->func = JS_NULL;
+ csd->func_name = JS_NULL;
+ csd->native = false;
+ csd->line_num = line_num;
+ csd->col_num = col_num;
+ /* filename is UTF-8 encoded if needed (original argument to __JS_EvalInternal()) */
+ csd->filename = JS_NewString(ctx, filename);
+ if (JS_IsException(csd->filename)) {
+ csd->filename = JS_NULL;
+ JS_FreeValue(ctx, JS_GetException(ctx)); // Clear exception.
}
- return __JS_NewFloat64(ctx, d);
}
-JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
- int length) {
- return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
+static JSValue js_callsite_getfield(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic)
+{
+ JSCallSiteData *csd = JS_GetOpaque2(ctx, this_val, JS_CLASS_CALL_SITE);
+ if (!csd)
+ return JS_EXCEPTION;
+ JSValue *field = (void *)((char *)csd + magic);
+ return js_dup(*field);
}
-JS_BOOL JS_IsRegExp(JSContext *ctx, JSValue val)
+static JSValue js_callsite_isnative(JSContext *ctx, JSValue this_val, int argc, JSValue *argv)
{
- JSObject *p;
- if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
- return FALSE;
- return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_REGEXP;
+ JSCallSiteData *csd = JS_GetOpaque2(ctx, this_val, JS_CLASS_CALL_SITE);
+ if (!csd)
+ return JS_EXCEPTION;
+ return JS_NewBool(ctx, csd->native);
+}
+
+static JSValue js_callsite_getnumber(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic)
+{
+ JSCallSiteData *csd = JS_GetOpaque2(ctx, this_val, JS_CLASS_CALL_SITE);
+ if (!csd)
+ return JS_EXCEPTION;
+ int *field = (void *)((char *)csd + magic);
+ return JS_NewInt32(ctx, *field);
+}
+
+static const JSCFunctionListEntry js_callsite_proto_funcs[] = {
+ JS_CFUNC_DEF("isNative", 0, js_callsite_isnative),
+ JS_CFUNC_MAGIC_DEF("getFileName", 0, js_callsite_getfield, offsetof(JSCallSiteData, filename)),
+ JS_CFUNC_MAGIC_DEF("getFunction", 0, js_callsite_getfield, offsetof(JSCallSiteData, func)),
+ JS_CFUNC_MAGIC_DEF("getFunctionName", 0, js_callsite_getfield, offsetof(JSCallSiteData, func_name)),
+ JS_CFUNC_MAGIC_DEF("getColumnNumber", 0, js_callsite_getnumber, offsetof(JSCallSiteData, col_num)),
+ JS_CFUNC_MAGIC_DEF("getLineNumber", 0, js_callsite_getnumber, offsetof(JSCallSiteData, line_num)),
+ JS_PROP_STRING_DEF("[Symbol.toStringTag]", "CallSite", JS_PROP_CONFIGURABLE ),
+};
+
+static const JSClassShortDef js_callsite_class_def[] = {
+ { JS_ATOM_CallSite, js_callsite_finalizer, js_callsite_mark }, /* JS_CLASS_CALL_SITE */
+};
+
+static void _JS_AddIntrinsicCallSite(JSContext *ctx)
+{
+ JSRuntime *rt = ctx->rt;
+
+ if (!JS_IsRegisteredClass(rt, JS_CLASS_CALL_SITE)) {
+ init_class_range(rt, js_callsite_class_def, JS_CLASS_CALL_SITE,
+ countof(js_callsite_class_def));
+ }
+ ctx->class_proto[JS_CLASS_CALL_SITE] = JS_NewObject(ctx);
+ JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_CALL_SITE],
+ js_callsite_proto_funcs,
+ countof(js_callsite_proto_funcs));
+}
+
+bool JS_DetectModule(const char *input, size_t input_len)
+{
+ JSRuntime *rt;
+ JSContext *ctx;
+ JSValue val;
+ bool is_module;
+
+ is_module = true;
+ rt = JS_NewRuntime();
+ if (!rt)
+ return false;
+ ctx = JS_NewContextRaw(rt);
+ if (!ctx) {
+ JS_FreeRuntime(rt);
+ return false;
+ }
+ JS_AddIntrinsicRegExpCompiler(ctx); // otherwise regexp literals don't parse
+ val = __JS_EvalInternal(ctx, JS_UNDEFINED, input, input_len, "<unnamed>", 1,
+ JS_EVAL_TYPE_MODULE|JS_EVAL_FLAG_COMPILE_ONLY, -1);
+ if (JS_IsException(val)) {
+ const char *msg = JS_ToCString(ctx, rt->current_exception);
+ // gruesome hack to recognize exceptions from import statements;
+ // necessary because we don't pass in a module loader
+ is_module = !!strstr(msg, "ReferenceError: could not load module");
+ JS_FreeCString(ctx, msg);
+ }
+ JS_FreeValue(ctx, val);
+ JS_FreeContext(ctx);
+ JS_FreeRuntime(rt);
+ return is_module;
+}
+
+void setScopeLookup(JSContext *ctx, ScopeLookup *scopeLookup)
+{
+ ctx->scopeLookup = scopeLookup;
+}
+
+void setFoundUndefinedHandler(JSContext *ctx, FoundUndefinedHandler *handler)
+{
+ ctx->handleUndefined = handler;
+}
+
+void setFunctionEnteredHandler(JSContext *ctx, FunctionEnteredHandler *handler)
+{
+ ctx->handleFunctionEntered = handler;
}
+
+void setFunctionExitedHandler(JSContext *ctx, FunctionExitedHandler *handler)
+{
+ ctx->handleFunctionExited = handler;
+}
+
+uintptr_t js_std_cmd(int cmd, ...) {
+ JSContext *ctx;
+ JSRuntime *rt;
+ JSValue *pv;
+ uintptr_t rv;
+ va_list ap;
+
+ rv = 0;
+ va_start(ap, cmd);
+ switch (cmd) {
+ case 0: // GetOpaque
+ rt = va_arg(ap, JSRuntime *);
+ rv = (uintptr_t)rt->libc_opaque;
+ break;
+ case 1: // SetOpaque
+ rt = va_arg(ap, JSRuntime *);
+ rt->libc_opaque = va_arg(ap, void *);
+ break;
+ case 2: // ErrorBackTrace
+ ctx = va_arg(ap, JSContext *);
+ pv = va_arg(ap, JSValue *);
+ *pv = ctx->error_back_trace;
+ ctx->error_back_trace = JS_UNDEFINED;
+ break;
+ default:
+ rv = -1;
+ }
+ va_end(ap);
+
+ return rv;
+}
+
+#undef malloc
+#undef free
+#undef realloc
diff --git a/src/shared/quickjs/quickjs.h b/src/shared/quickjs/quickjs.h
index 3a22f5b7b..55215ee4f 100644
--- a/src/shared/quickjs/quickjs.h
+++ b/src/shared/quickjs/quickjs.h
@@ -1,8 +1,10 @@
/*
* QuickJS Javascript Engine
*
- * Copyright (c) 2017-2021 Fabrice Bellard
- * Copyright (c) 2017-2021 Charlie Gordon
+ * Copyright (c) 2017-2024 Fabrice Bellard
+ * Copyright (c) 2017-2024 Charlie Gordon
+ * Copyright (c) 2023-2025 Ben Noordhuis
+ * Copyright (c) 2023-2025 Saúl Ibarra Corretgé
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,26 +27,43 @@
#ifndef QUICKJS_H
#define QUICKJS_H
+#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
+#include <string.h>
+#include <math.h>
#ifdef __cplusplus
extern "C" {
#endif
+#define QUICKJS_NG 1
+
#if defined(__GNUC__) || defined(__clang__)
-#define js_likely(x) __builtin_expect(!!(x), 1)
-#define js_unlikely(x) __builtin_expect(!!(x), 0)
#define js_force_inline inline __attribute__((always_inline))
-#define __js_printf_like(f, a) __attribute__((format(printf, f, a)))
+#define JS_EXTERN __attribute__((visibility("default")))
#else
-#define js_likely(x) (x)
-#define js_unlikely(x) (x)
#define js_force_inline inline
-#define __js_printf_like(a, b)
+#define JS_EXTERN /* nothing */
#endif
-#define JS_BOOL int
+/* Borrowed from Folly */
+#ifndef JS_PRINTF_FORMAT
+#ifdef _MSC_VER
+#include <sal.h>
+#define JS_PRINTF_FORMAT _Printf_format_string_
+#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param)
+#else
+#define JS_PRINTF_FORMAT
+#if !defined(__clang__) && defined(__GNUC__)
+#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \
+ __attribute__((format(gnu_printf, format_param, dots_param)))
+#else
+#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \
+ __attribute__((format(printf, format_param, dots_param)))
+#endif
+#endif
+#endif
typedef struct JSRuntime JSRuntime;
typedef struct JSContext JSContext;
@@ -53,23 +72,23 @@ typedef struct JSClass JSClass;
typedef uint32_t JSClassID;
typedef uint32_t JSAtom;
-#if INTPTR_MAX >= INT64_MAX
-#define JS_PTR64
-#define JS_PTR64_DEF(a) a
-#else
-#define JS_PTR64_DEF(a)
-#endif
+/* Unless documented otherwise, C string pointers (`char *` or `const char *`)
+ are assumed to verify these constraints:
+ - unless a length is passed separately, the string has a null terminator
+ - string contents is either pure ASCII or is UTF-8 encoded.
+ */
-#ifndef JS_PTR64
-#define JS_NAN_BOXING
+/* Overridable purely for testing purposes; don't touch. */
+#ifndef JS_NAN_BOXING
+#if INTPTR_MAX < INT64_MAX
+#define JS_NAN_BOXING 1 /* Use NAN boxing for 32bit builds. */
+#endif
#endif
enum {
/* all tags with a reference count are negative */
- JS_TAG_FIRST = -11, /* first negative tag */
- JS_TAG_BIG_DECIMAL = -11,
- JS_TAG_BIG_INT = -10,
- JS_TAG_BIG_FLOAT = -9,
+ JS_TAG_FIRST = -9, /* first negative tag */
+ JS_TAG_BIG_INT = -9,
JS_TAG_SYMBOL = -8,
JS_TAG_STRING = -7,
JS_TAG_MODULE = -3, /* used internally */
@@ -87,52 +106,12 @@ enum {
/* any larger tag is FLOAT64 if JS_NAN_BOXING */
};
-typedef struct JSRefCountHeader {
- int ref_count;
-} JSRefCountHeader;
-
-#define JS_FLOAT64_NAN NAN
+#define JSValueConst JSValue /* For backwards compatibility. */
-#ifdef CONFIG_CHECK_JSVALUE
-/* JSValue consistency : it is not possible to run the code in this
- mode, but it is useful to detect simple reference counting
- errors. It would be interesting to modify a static C analyzer to
- handle specific annotations (clang has such annotations but only
- for objective C) */
-typedef struct __JSValue *JSValue;
-typedef const struct __JSValue *JSValueConst;
-
-#define JS_VALUE_GET_TAG(v) (int)((uintptr_t)(v) & 0xf)
-/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
-#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
-#define JS_VALUE_GET_INT(v) (int)((intptr_t)(v) >> 4)
-#define JS_VALUE_GET_BOOL(v) JS_VALUE_GET_INT(v)
-#define JS_VALUE_GET_FLOAT64(v) (double)JS_VALUE_GET_INT(v)
-#define JS_VALUE_GET_PTR(v) (void *)((intptr_t)(v) & ~0xf)
-
-#define JS_MKVAL(tag, val) (JSValue)(intptr_t)(((val) << 4) | (tag))
-#define JS_MKPTR(tag, p) (JSValue)((intptr_t)(p) | (tag))
-
-#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
-
-#define JS_NAN JS_MKVAL(JS_TAG_FLOAT64, 1)
-
-static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
-{
- return JS_MKVAL(JS_TAG_FLOAT64, (int)d);
-}
-
-static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
-{
- return 0;
-}
-
-#elif defined(JS_NAN_BOXING)
+#if defined(JS_NAN_BOXING) && JS_NAN_BOXING
typedef uint64_t JSValue;
-#define JSValueConst JSValue
-
#define JS_VALUE_GET_TAG(v) (int)((v) >> 32)
#define JS_VALUE_GET_INT(v) (int)(v)
#define JS_VALUE_GET_BOOL(v) (int)(v)
@@ -156,9 +135,8 @@ static inline double JS_VALUE_GET_FLOAT64(JSValue v)
#define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32))
-static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
+static inline JSValue __JS_NewFloat64(double d)
{
- (void) ctx;
union {
double d;
uint64_t u64;
@@ -166,7 +144,7 @@ static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
JSValue v;
u.d = d;
/* normalize NaN */
- if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000))
+ if ((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000)
v = JS_NAN;
else
v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32);
@@ -186,7 +164,7 @@ static inline int JS_VALUE_GET_NORM_TAG(JSValue v)
return tag;
}
-static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
+static inline bool JS_VALUE_IS_NAN(JSValue v)
{
uint32_t tag;
tag = JS_VALUE_GET_TAG(v);
@@ -206,8 +184,6 @@ typedef struct JSValue {
int64_t tag;
} JSValue;
-#define JSValueConst JSValue
-
#define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag)
/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
@@ -216,26 +192,50 @@ typedef struct JSValue {
#define JS_VALUE_GET_FLOAT64(v) ((v).u.float64)
#define JS_VALUE_GET_PTR(v) ((v).u.ptr)
-JSValue mkVal(int32_t tag, int32_t val);
-JSValue mkPtr(int32_t tag, void *p);
-
-#define JS_MKVAL(tag, val) mkVal(tag, val)
-#define JS_MKPTR(tag, p) mkPtr(tag, p)
+/* msvc doesn't understand designated initializers without /std:c++20 */
+#ifdef __cplusplus
+static inline JSValue JS_MKPTR(int64_t tag, void *ptr)
+{
+ JSValue v;
+ v.u.ptr = ptr;
+ v.tag = tag;
+ return v;
+}
+static inline JSValue JS_MKVAL(int64_t tag, int32_t int32)
+{
+ JSValue v;
+ v.u.int32 = int32;
+ v.tag = tag;
+ return v;
+}
+static inline JSValue JS_MKNAN(void)
+{
+ JSValue v;
+ v.u.float64 = NAN;
+ v.tag = JS_TAG_FLOAT64;
+ return v;
+}
+/* provide as macros for consistency and backward compat reasons */
+#define JS_MKPTR(tag, ptr) JS_MKPTR(tag, ptr)
+#define JS_MKVAL(tag, val) JS_MKVAL(tag, val)
+#define JS_NAN JS_MKNAN() /* alas, not a constant expression */
+#else
+#define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag }
+#define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag }
+#define JS_NAN (JSValue){ (JSValueUnion){ .float64 = NAN }, JS_TAG_FLOAT64 }
+#endif
#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
-#define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 }
-
-static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
+static inline JSValue __JS_NewFloat64(double d)
{
- (void) ctx;
JSValue v;
v.tag = JS_TAG_FLOAT64;
v.u.float64 = d;
return v;
}
-static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
+static inline bool JS_VALUE_IS_NAN(JSValue v)
{
union {
double d;
@@ -253,7 +253,6 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
#define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2)))
#define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v))
-#define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v))
#define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST)
/* special values */
@@ -294,8 +293,12 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
#define JS_PROP_NO_ADD (1 << 16) /* internal use */
#define JS_PROP_NO_EXOTIC (1 << 17) /* internal use */
+#define JS_PROP_DEFINE_PROPERTY (1 << 18) /* internal use */
+#define JS_PROP_REFLECT_DEFINE_PROPERTY (1 << 19) /* internal use */
-#define JS_DEFAULT_STACK_SIZE (256 * 1024)
+#ifndef JS_DEFAULT_STACK_SIZE
+#define JS_DEFAULT_STACK_SIZE (1024 * 1024)
+#endif
/* JS_Eval() flags */
#define JS_EVAL_TYPE_GLOBAL (0 << 0) /* global code (default) */
@@ -305,7 +308,7 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
#define JS_EVAL_TYPE_MASK (3 << 0)
#define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */
-#define JS_EVAL_FLAG_STRIP (1 << 4) /* force 'strip' mode */
+#define JS_EVAL_FLAG_UNUSED (1 << 4) /* unused */
/* compile but do not run. The result is an object with a
JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed
with JS_EvalFunction(). */
@@ -316,93 +319,127 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
promise. Only allowed with JS_EVAL_TYPE_GLOBAL */
#define JS_EVAL_FLAG_ASYNC (1 << 7)
-typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
-typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
-typedef JSValue JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValue *func_data);
-
-typedef struct JSMallocState {
- size_t malloc_count;
- size_t malloc_size;
- size_t malloc_limit;
- void *opaque; /* user opaque */
-} JSMallocState;
+typedef JSValue JSCFunction(JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
+typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic);
+typedef JSValue JSCFunctionData(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic, JSValue *func_data);
typedef struct JSMallocFunctions {
- void *(*js_malloc)(JSMallocState *s, size_t size);
- void (*js_free)(JSMallocState *s, void *ptr);
- void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size);
+ void *(*js_calloc)(void *opaque, size_t count, size_t size);
+ void *(*js_malloc)(void *opaque, size_t size);
+ void (*js_free)(void *opaque, void *ptr);
+ void *(*js_realloc)(void *opaque, void *ptr, size_t size);
size_t (*js_malloc_usable_size)(const void *ptr);
} JSMallocFunctions;
+// Debug trace system: the debug output will be produced to the dump stream (currently
+// stdout) if dumps are enabled and JS_SetDumpFlags is invoked with the corresponding
+// bit set.
+#define JS_DUMP_BYTECODE_FINAL 0x01 /* dump pass 3 final byte code */
+#define JS_DUMP_BYTECODE_PASS2 0x02 /* dump pass 2 code */
+#define JS_DUMP_BYTECODE_PASS1 0x04 /* dump pass 1 code */
+#define JS_DUMP_BYTECODE_HEX 0x10 /* dump bytecode in hex */
+#define JS_DUMP_BYTECODE_PC2LINE 0x20 /* dump line number table */
+#define JS_DUMP_BYTECODE_STACK 0x40 /* dump compute_stack_size */
+#define JS_DUMP_BYTECODE_STEP 0x80 /* dump executed bytecode */
+#define JS_DUMP_READ_OBJECT 0x100 /* dump the marshalled objects at load time */
+#define JS_DUMP_FREE 0x200 /* dump every object free */
+#define JS_DUMP_GC 0x400 /* dump the occurrence of the automatic GC */
+#define JS_DUMP_GC_FREE 0x800 /* dump objects freed by the GC */
+#define JS_DUMP_MODULE_RESOLVE 0x1000 /* dump module resolution steps */
+#define JS_DUMP_PROMISE 0x2000 /* dump promise steps */
+#define JS_DUMP_LEAKS 0x4000 /* dump leaked objects and strings in JS_FreeRuntime */
+#define JS_DUMP_ATOM_LEAKS 0x8000 /* dump leaked atoms in JS_FreeRuntime */
+#define JS_DUMP_MEM 0x10000 /* dump memory usage in JS_FreeRuntime */
+#define JS_DUMP_OBJECTS 0x20000 /* dump objects in JS_FreeRuntime */
+#define JS_DUMP_ATOMS 0x40000 /* dump atoms in JS_FreeRuntime */
+#define JS_DUMP_SHAPES 0x80000 /* dump shapes in JS_FreeRuntime */
+
+// Finalizers run in LIFO order at the very end of JS_FreeRuntime.
+// Intended for cleanup of associated resources; the runtime itself
+// is no longer usable.
+typedef void JSRuntimeFinalizer(JSRuntime *rt, void *arg);
+
typedef struct JSGCObjectHeader JSGCObjectHeader;
-JSRuntime *JS_NewRuntime(void);
+JS_EXTERN JSRuntime *JS_NewRuntime(void);
/* info lifetime must exceed that of rt */
-void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
-void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
-void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
+JS_EXTERN void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
+/* use 0 to disable memory limit */
+JS_EXTERN void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
+JS_EXTERN void JS_SetDumpFlags(JSRuntime *rt, uint64_t flags);
+JS_EXTERN uint64_t JS_GetDumpFlags(JSRuntime *rt);
+JS_EXTERN size_t JS_GetGCThreshold(JSRuntime *rt);
+JS_EXTERN void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
/* use 0 to disable maximum stack size check */
-void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size);
+JS_EXTERN void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size);
/* should be called when changing thread to update the stack top value
used to check stack overflow. */
-void JS_UpdateStackTop(JSRuntime *rt);
-JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
-void JS_FreeRuntime(JSRuntime *rt);
-void *JS_GetRuntimeOpaque(JSRuntime *rt);
-void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque);
+JS_EXTERN void JS_UpdateStackTop(JSRuntime *rt);
+JS_EXTERN JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
+JS_EXTERN void JS_FreeRuntime(JSRuntime *rt);
+JS_EXTERN void *JS_GetRuntimeOpaque(JSRuntime *rt);
+JS_EXTERN void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque);
+JS_EXTERN int JS_AddRuntimeFinalizer(JSRuntime *rt,
+ JSRuntimeFinalizer *finalizer, void *arg);
typedef void JS_MarkFunc(JSRuntime *rt, JSGCObjectHeader *gp);
-void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
-void JS_RunGC(JSRuntime *rt);
-JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj);
-
-JSContext *JS_NewContext(JSRuntime *rt);
-void JS_FreeContext(JSContext *s);
-JSContext *JS_DupContext(JSContext *ctx);
-void *JS_GetContextOpaque(JSContext *ctx);
-void JS_SetContextOpaque(JSContext *ctx, void *opaque);
-JSRuntime *JS_GetRuntime(JSContext *ctx);
-void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj);
-JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id);
+JS_EXTERN void JS_MarkValue(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func);
+JS_EXTERN void JS_RunGC(JSRuntime *rt);
+JS_EXTERN bool JS_IsLiveObject(JSRuntime *rt, JSValue obj);
+
+JS_EXTERN JSContext *JS_NewContext(JSRuntime *rt);
+JS_EXTERN void JS_FreeContext(JSContext *s);
+JS_EXTERN JSContext *JS_DupContext(JSContext *ctx);
+JS_EXTERN void *JS_GetContextOpaque(JSContext *ctx);
+JS_EXTERN void JS_SetContextOpaque(JSContext *ctx, void *opaque);
+JS_EXTERN JSRuntime *JS_GetRuntime(JSContext *ctx);
+JS_EXTERN void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj);
+JS_EXTERN JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id);
+JS_EXTERN JSValue JS_GetFunctionProto(JSContext *ctx);
/* the following functions are used to select the intrinsic object to
save memory */
-JSContext *JS_NewContextRaw(JSRuntime *rt);
-void JS_AddIntrinsicBaseObjects(JSContext *ctx);
-void JS_AddIntrinsicDate(JSContext *ctx);
-void JS_AddIntrinsicEval(JSContext *ctx);
-void JS_AddIntrinsicStringNormalize(JSContext *ctx);
-void JS_AddIntrinsicRegExpCompiler(JSContext *ctx);
-void JS_AddIntrinsicRegExp(JSContext *ctx);
-void JS_AddIntrinsicJSON(JSContext *ctx);
-void JS_AddIntrinsicProxy(JSContext *ctx);
-void JS_AddIntrinsicMapSet(JSContext *ctx);
-void JS_AddIntrinsicTypedArrays(JSContext *ctx);
-void JS_AddIntrinsicPromise(JSContext *ctx);
-void JS_AddIntrinsicBigInt(JSContext *ctx);
-void JS_AddIntrinsicBigFloat(JSContext *ctx);
-void JS_AddIntrinsicBigDecimal(JSContext *ctx);
-/* enable operator overloading */
-void JS_AddIntrinsicOperators(JSContext *ctx);
-/* enable "use math" */
-void JS_EnableBignumExt(JSContext *ctx, JS_BOOL enable);
-
-JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv);
-
-void *js_malloc_rt(JSRuntime *rt, size_t size);
-void js_free_rt(JSRuntime *rt, void *ptr);
-void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size);
-size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr);
-void *js_mallocz_rt(JSRuntime *rt, size_t size);
-
-void *js_malloc(JSContext *ctx, size_t size);
-void js_free(JSContext *ctx, void *ptr);
-void *js_realloc(JSContext *ctx, void *ptr, size_t size);
-size_t js_malloc_usable_size(JSContext *ctx, const void *ptr);
-void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack);
-void *js_mallocz(JSContext *ctx, size_t size);
-char *js_strdup(JSContext *ctx, const char *str);
-char *js_strndup(JSContext *ctx, const char *s, size_t n);
+JS_EXTERN JSContext *JS_NewContextRaw(JSRuntime *rt);
+JS_EXTERN void JS_AddIntrinsicBaseObjects(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicDate(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicEval(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicRegExpCompiler(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicRegExp(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicJSON(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicProxy(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicMapSet(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicTypedArrays(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicPromise(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicBigInt(JSContext *ctx);
+JS_EXTERN void JS_AddIntrinsicWeakRef(JSContext *ctx);
+JS_EXTERN void JS_AddPerformance(JSContext *ctx);
+
+/* for equality comparisons and sameness */
+JS_EXTERN int JS_IsEqual(JSContext *ctx, JSValue op1, JSValue op2);
+JS_EXTERN bool JS_IsStrictEqual(JSContext *ctx, JSValue op1, JSValue op2);
+JS_EXTERN bool JS_IsSameValue(JSContext *ctx, JSValue op1, JSValue op2);
+/* Similar to same-value equality, but +0 and -0 are considered equal. */
+JS_EXTERN bool JS_IsSameValueZero(JSContext *ctx, JSValue op1, JSValue op2);
+
+/* Only used for running 262 tests. TODO(saghul) add build time flag. */
+JS_EXTERN JSValue js_string_codePointRange(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv);
+
+JS_EXTERN void *js_calloc_rt(JSRuntime *rt, size_t count, size_t size);
+JS_EXTERN void *js_malloc_rt(JSRuntime *rt, size_t size);
+JS_EXTERN void js_free_rt(JSRuntime *rt, void *ptr);
+JS_EXTERN void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size);
+JS_EXTERN size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr);
+JS_EXTERN void *js_mallocz_rt(JSRuntime *rt, size_t size);
+
+JS_EXTERN void *js_calloc(JSContext *ctx, size_t count, size_t size);
+JS_EXTERN void *js_malloc(JSContext *ctx, size_t size);
+JS_EXTERN void js_free(JSContext *ctx, void *ptr);
+JS_EXTERN void *js_realloc(JSContext *ctx, void *ptr, size_t size);
+JS_EXTERN size_t js_malloc_usable_size(JSContext *ctx, const void *ptr);
+JS_EXTERN void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack);
+JS_EXTERN void *js_mallocz(JSContext *ctx, size_t size);
+JS_EXTERN char *js_strdup(JSContext *ctx, const char *str);
+JS_EXTERN char *js_strndup(JSContext *ctx, const char *s, size_t n);
typedef struct JSMemoryUsage {
int64_t malloc_size, malloc_limit, memory_used_size;
@@ -420,27 +457,27 @@ typedef struct JSMemoryUsage {
int64_t binary_object_count, binary_object_size;
} JSMemoryUsage;
-void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s);
-void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
+JS_EXTERN void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s);
+JS_EXTERN void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
/* atom support */
#define JS_ATOM_NULL 0
-JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len);
-JSAtom JS_NewAtom(JSContext *ctx, const char *str);
-JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n);
-JSAtom JS_DupAtom(JSContext *ctx, JSAtom v);
-void JS_FreeAtom(JSContext *ctx, JSAtom v);
-void JS_FreeAtomRT(JSRuntime *rt, JSAtom v);
-JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom);
-JSValue JS_AtomToString(JSContext *ctx, JSAtom atom);
-const char *JS_AtomToCString(JSContext *ctx, JSAtom atom);
-JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val);
+JS_EXTERN JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len);
+JS_EXTERN JSAtom JS_NewAtom(JSContext *ctx, const char *str);
+JS_EXTERN JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n);
+JS_EXTERN JSAtom JS_DupAtom(JSContext *ctx, JSAtom v);
+JS_EXTERN void JS_FreeAtom(JSContext *ctx, JSAtom v);
+JS_EXTERN void JS_FreeAtomRT(JSRuntime *rt, JSAtom v);
+JS_EXTERN JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom);
+JS_EXTERN JSValue JS_AtomToString(JSContext *ctx, JSAtom atom);
+JS_EXTERN const char *JS_AtomToCString(JSContext *ctx, JSAtom atom);
+JS_EXTERN JSAtom JS_ValueToAtom(JSContext *ctx, JSValue val);
/* object class support */
typedef struct JSPropertyEnum {
- JS_BOOL is_enumerable;
+ bool is_enumerable;
JSAtom atom;
} JSPropertyEnum;
@@ -453,44 +490,44 @@ typedef struct JSPropertyDescriptor {
typedef struct JSClassExoticMethods {
/* Return -1 if exception (can only happen in case of Proxy object),
- FALSE if the property does not exists, TRUE if it exists. If 1 is
+ false if the property does not exists, true if it exists. If 1 is
returned, the property descriptor 'desc' is filled if != NULL. */
int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc,
- JSValueConst obj, JSAtom prop);
+ JSValue obj, JSAtom prop);
/* '*ptab' should hold the '*plen' property keys. Return 0 if OK,
-1 if exception. The 'is_enumerable' field is ignored.
*/
int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab,
uint32_t *plen,
- JSValueConst obj);
- /* return < 0 if exception, or TRUE/FALSE */
- int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop);
- /* return < 0 if exception or TRUE/FALSE */
- int (*define_own_property)(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop, JSValueConst val,
- JSValueConst getter, JSValueConst setter,
+ JSValue obj);
+ /* return < 0 if exception, or true/false */
+ int (*delete_property)(JSContext *ctx, JSValue obj, JSAtom prop);
+ /* return < 0 if exception or true/false */
+ int (*define_own_property)(JSContext *ctx, JSValue this_obj,
+ JSAtom prop, JSValue val,
+ JSValue getter, JSValue setter,
int flags);
/* The following methods can be emulated with the previous ones,
so they are usually not needed */
- /* return < 0 if exception or TRUE/FALSE */
- int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom);
- JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
- JSValueConst receiver);
- /* return < 0 if exception or TRUE/FALSE */
- int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
- JSValueConst value, JSValueConst receiver, int flags);
+ /* return < 0 if exception or true/false */
+ int (*has_property)(JSContext *ctx, JSValue obj, JSAtom atom);
+ JSValue (*get_property)(JSContext *ctx, JSValue obj, JSAtom atom,
+ JSValue receiver);
+ /* return < 0 if exception or true/false */
+ int (*set_property)(JSContext *ctx, JSValue obj, JSAtom atom,
+ JSValue value, JSValue receiver, int flags);
} JSClassExoticMethods;
typedef void JSClassFinalizer(JSRuntime *rt, JSValue val);
-typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val,
+typedef void JSClassGCMark(JSRuntime *rt, JSValue val,
JS_MarkFunc *mark_func);
#define JS_CALL_FLAG_CONSTRUCTOR (1 << 0)
-typedef JSValue JSClassCall(JSContext *ctx, JSValueConst func_obj,
- JSValueConst this_val, int argc, JSValueConst *argv,
+typedef JSValue JSClassCall(JSContext *ctx, JSValue func_obj,
+ JSValue this_val, int argc, JSValue *argv,
int flags);
typedef struct JSClassDef {
- const char *class_name;
+ const char *class_name; /* pure ASCII only! */
JSClassFinalizer *finalizer;
JSClassGCMark *gc_mark;
/* if call != NULL, the object is a function. If (flags &
@@ -504,224 +541,246 @@ typedef struct JSClassDef {
JSClassExoticMethods *exotic;
} JSClassDef;
+#define JS_EVAL_OPTIONS_VERSION 1
+
+typedef struct JSEvalOptions {
+ int version;
+ int eval_flags;
+ const char *filename;
+ int line_num;
+ // can add new fields in ABI-compatible manner by incrementing JS_EVAL_OPTIONS_VERSION
+} JSEvalOptions;
+
#define JS_INVALID_CLASS_ID 0
-JSClassID JS_NewClassID(JSClassID *pclass_id);
+JS_EXTERN JSClassID JS_NewClassID(JSRuntime *rt, JSClassID *pclass_id);
/* Returns the class ID if `v` is an object, otherwise returns JS_INVALID_CLASS_ID. */
-JSClassID JS_GetClassID(JSValue v);
-int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def);
-int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id);
+JS_EXTERN JSClassID JS_GetClassID(JSValue v);
+JS_EXTERN int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def);
+JS_EXTERN bool JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id);
/* value handling */
-JSValue JS_NewBool(JSContext *ctx, JS_BOOL val);
-JSValue JS_NewInt32(JSContext *ctx, int32_t val);
-JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val);
-JSValue JS_NewInt64(JSContext *ctx, int64_t val);
-JSValue JS_NewUint32(JSContext *ctx, uint32_t val);
-JSValue JS_NewBigInt64(JSContext *ctx, int64_t v);
-JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v);
+static js_force_inline JSValue JS_NewBool(JSContext *ctx, bool val)
+{
+ (void)&ctx;
+ return JS_MKVAL(JS_TAG_BOOL, (val != 0));
+}
-JSValue JS_NewFloat64(JSContext *ctx, double d);
+static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val)
+{
+ (void)&ctx;
+ return JS_MKVAL(JS_TAG_INT, val);
+}
-static inline JS_BOOL JS_IsNumber(JSValueConst v)
+static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double val)
{
- int tag = JS_VALUE_GET_TAG(v);
- return tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag);
+ (void)&ctx;
+ return __JS_NewFloat64(val);
}
-static inline JS_BOOL JS_IsBigInt(JSContext *ctx, JSValueConst v)
+static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val)
{
- (void) ctx;
- int tag = JS_VALUE_GET_TAG(v);
- return tag == JS_TAG_BIG_INT;
+ (void)&ctx;
+ return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
}
-static inline JS_BOOL JS_IsBigFloat(JSValueConst v)
+static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val)
{
- int tag = JS_VALUE_GET_TAG(v);
- return tag == JS_TAG_BIG_FLOAT;
+ JSValue v;
+ if (val >= INT32_MIN && val <= INT32_MAX) {
+ v = JS_NewInt32(ctx, (int32_t)val);
+ } else {
+ v = JS_NewFloat64(ctx, (double)val);
+ }
+ return v;
}
-static inline JS_BOOL JS_IsBigDecimal(JSValueConst v)
+static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val)
+{
+ JSValue v;
+ if (val <= INT32_MAX) {
+ v = JS_NewInt32(ctx, (int32_t)val);
+ } else {
+ v = JS_NewFloat64(ctx, (double)val);
+ }
+ return v;
+}
+
+JS_EXTERN JSValue JS_NewNumber(JSContext *ctx, double d);
+JS_EXTERN JSValue JS_NewBigInt64(JSContext *ctx, int64_t v);
+JS_EXTERN JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v);
+
+static inline bool JS_IsNumber(JSValue v)
{
int tag = JS_VALUE_GET_TAG(v);
- return tag == JS_TAG_BIG_DECIMAL;
+ return tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag);
+}
+
+static inline bool JS_IsBigInt(JSContext *ctx, JSValue v)
+{
+ (void)&ctx;
+ return JS_VALUE_GET_TAG(v) == JS_TAG_BIG_INT;
}
-static inline JS_BOOL JS_IsBool(JSValueConst v)
+static inline bool JS_IsBool(JSValue v)
{
return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL;
}
-static inline JS_BOOL JS_IsNull(JSValueConst v)
+static inline bool JS_IsNull(JSValue v)
{
return JS_VALUE_GET_TAG(v) == JS_TAG_NULL;
}
-static inline JS_BOOL JS_IsUndefined(JSValueConst v)
+static inline bool JS_IsUndefined(JSValue v)
{
return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED;
}
-static inline JS_BOOL JS_IsException(JSValueConst v)
+static inline bool JS_IsException(JSValue v)
{
- return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION);
+ return JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION;
}
-static inline JS_BOOL JS_IsUninitialized(JSValueConst v)
+static inline bool JS_IsUninitialized(JSValue v)
{
- return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED);
+ return JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED;
}
-static inline JS_BOOL JS_IsString(JSValueConst v)
+static inline bool JS_IsString(JSValue v)
{
return JS_VALUE_GET_TAG(v) == JS_TAG_STRING;
}
-static inline JS_BOOL JS_IsSymbol(JSValueConst v)
+static inline bool JS_IsSymbol(JSValue v)
{
return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL;
}
-static inline JS_BOOL JS_IsObject(JSValueConst v)
+static inline bool JS_IsObject(JSValue v)
{
return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT;
}
-JSValue JS_Throw(JSContext *ctx, JSValue obj);
-JSValue JS_GetException(JSContext *ctx);
-JS_BOOL JS_HasException(JSContext *ctx);
-JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
-void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, JS_BOOL flag);
-void JS_ResetUncatchableError(JSContext *ctx);
-JSValue JS_NewError(JSContext *ctx);
-JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
-JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...);
-JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...);
-JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...);
-JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
-JSValue JS_ThrowOutOfMemory(JSContext *ctx);
-
-#ifndef NDEBUG
-void notifyRefCountIncrease(JSRefCountHeader *p);
-void notifyRefCountDecrease(JSRefCountHeader *p);
-#endif
-
-void JS_FreeValue(JSContext *ctx, JSValue v);
-void JS_FreeValueRT(JSRuntime *rt, JSValue v);
-
-static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v)
+JS_EXTERN JSValue JS_Throw(JSContext *ctx, JSValue obj);
+JS_EXTERN JSValue JS_GetException(JSContext *ctx);
+JS_EXTERN bool JS_HasException(JSContext *ctx);
+JS_EXTERN JSValue JS_GetBacktrace(JSContext *ctx);
+JS_EXTERN bool JS_IsError(JSContext *ctx, JSValue val);
+JS_EXTERN bool JS_IsUncatchableError(JSContext* ctx, JSValue val);
+JS_EXTERN void JS_SetUncatchableError(JSContext *ctx, JSValue val);
+JS_EXTERN void JS_ClearUncatchableError(JSContext *ctx, JSValue val);
+// Shorthand for:
+// JSValue exc = JS_GetException(ctx);
+// JS_ClearUncatchableError(ctx, exc);
+// JS_Throw(ctx, exc);
+JS_EXTERN void JS_ResetUncatchableError(JSContext *ctx);
+JS_EXTERN JSValue JS_NewError(JSContext *ctx);
+JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowPlainError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...);
+JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowSyntaxError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...);
+JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowTypeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...);
+JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...);
+JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...);
+JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...);
+JS_EXTERN JSValue JS_ThrowOutOfMemory(JSContext *ctx);
+JS_EXTERN void JS_FreeValue(JSContext *ctx, JSValue v);
+JS_EXTERN void JS_FreeValueRT(JSRuntime *rt, JSValue v);
+JS_EXTERN JSValue JS_DupValue(JSContext *ctx, JSValue v);
+JS_EXTERN JSValue JS_DupValueRT(JSRuntime *rt, JSValue v);
+JS_EXTERN int JS_ToBool(JSContext *ctx, JSValue val); /* return -1 for JS_EXCEPTION */
+static inline JSValue JS_ToBoolean(JSContext *ctx, JSValue val)
{
- (void) ctx;
- if (JS_VALUE_HAS_REF_COUNT(v)) {
- JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-#ifndef NDEBUG
- notifyRefCountIncrease(p);
-#endif
- p->ref_count++;
- }
- return v;
+ return JS_NewBool(ctx, JS_ToBool(ctx, val));
}
-
-static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
-{
- (void) rt;
- if (JS_VALUE_HAS_REF_COUNT(v)) {
- JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-#ifndef NDEBUG
- notifyRefCountIncrease(p);
-#endif
- p->ref_count++;
- }
- return v;
-}
-
-JS_BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2);
-JS_BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2);
-JS_BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2);
-
-int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
-int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
-static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
+JS_EXTERN JSValue JS_ToNumber(JSContext *ctx, JSValue val);
+JS_EXTERN int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValue val);
+static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValue val)
{
return JS_ToInt32(ctx, (int32_t*)pres, val);
}
-int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
-int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val);
-int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val);
+JS_EXTERN int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValue val);
+JS_EXTERN int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValue val);
+JS_EXTERN int JS_ToFloat64(JSContext *ctx, double *pres, JSValue val);
/* return an exception if 'val' is a Number */
-int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
+JS_EXTERN int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValue val);
+JS_EXTERN int JS_ToBigUint64(JSContext *ctx, uint64_t *pres, JSValue val);
/* same as JS_ToInt64() but allow BigInt */
-int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val);
-
-JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1);
-JSValue JS_NewString(JSContext *ctx, const char *str);
-JSValue JS_NewAtomString(JSContext *ctx, const char *str);
-JSValue JS_ToString(JSContext *ctx, JSValueConst val);
-JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val);
-const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, JS_BOOL cesu8);
-static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValueConst val1)
+JS_EXTERN int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValue val);
+
+JS_EXTERN JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1);
+static inline JSValue JS_NewString(JSContext *ctx, const char *str) {
+ return JS_NewStringLen(ctx, str, strlen(str));
+}
+JS_EXTERN JSValue JS_NewAtomString(JSContext *ctx, const char *str);
+JS_EXTERN JSValue JS_ToString(JSContext *ctx, JSValue val);
+JS_EXTERN JSValue JS_ToPropertyKey(JSContext *ctx, JSValue val);
+JS_EXTERN const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValue val1, bool cesu8);
+static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValue val1)
{
return JS_ToCStringLen2(ctx, plen, val1, 0);
}
-static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1)
+static inline const char *JS_ToCString(JSContext *ctx, JSValue val1)
{
return JS_ToCStringLen2(ctx, NULL, val1, 0);
}
-void JS_FreeCString(JSContext *ctx, const char *ptr);
-
-JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto, JSClassID class_id);
-JSValue JS_NewObjectClass(JSContext *ctx, int class_id);
-JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto);
-JSValue JS_NewObject(JSContext *ctx);
-
-JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val);
-JS_BOOL JS_IsRegExp(JSContext* ctx, JSValueConst val);
-JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val);
-JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val);
-JS_BOOL JS_IsArrayBuffer(JSValueConst v);
-
-JSValue JS_NewArray(JSContext *ctx);
-int JS_IsArray(JSContext *ctx, JSValueConst val);
-
-JSValue JS_NewDate(JSContext *ctx, double epoch_ms);
-JS_BOOL JS_IsDate(JSValueConst v);
-
-JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
- JSAtom prop, JSValueConst receiver,
- JS_BOOL throw_ref_error);
-static js_force_inline JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop)
-{
- return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, 0);
-}
-JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,
- const char *prop);
-JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
- uint32_t idx);
-
-int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
- JSAtom prop, JSValue val, JSValueConst this_obj,
- int flags);
-static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop, JSValue val)
-{
- return JS_SetPropertyInternal(ctx, this_obj, prop, val, this_obj, JS_PROP_THROW);
-}
-int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
- uint32_t idx, JSValue val);
-int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj,
- int64_t idx, JSValue val);
-int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,
- const char *prop, JSValue val);
-int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop);
-int JS_IsExtensible(JSContext *ctx, JSValueConst obj);
-int JS_PreventExtensions(JSContext *ctx, JSValueConst obj);
-int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags);
-int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val);
-JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val);
-
-JSValue JS_ObjectSeal(JSContext *ctx, JSValueConst obj, int freeze);
+JS_EXTERN void JS_FreeCString(JSContext *ctx, const char *ptr);
+
+JS_EXTERN JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValue proto, JSClassID class_id);
+JS_EXTERN JSValue JS_NewObjectClass(JSContext *ctx, int class_id);
+JS_EXTERN JSValue JS_NewObjectProto(JSContext *ctx, JSValue proto);
+JS_EXTERN JSValue JS_NewObject(JSContext *ctx);
+JS_EXTERN JSValue JS_NewObjectFrom(JSContext *ctx, int count,
+ const JSAtom *props,
+ const JSValue *values);
+JS_EXTERN JSValue JS_NewObjectFromStr(JSContext *ctx, int count,
+ const char **props,
+ const JSValue *values);
+JS_EXTERN JSValue JS_ToObject(JSContext *ctx, JSValue val);
+JS_EXTERN JSValue JS_ToObjectString(JSContext *ctx, JSValue val);
+
+JS_EXTERN bool JS_IsFunction(JSContext* ctx, JSValue val);
+JS_EXTERN bool JS_IsConstructor(JSContext* ctx, JSValue val);
+JS_EXTERN bool JS_SetConstructorBit(JSContext *ctx, JSValue func_obj, bool val);
+
+JS_EXTERN bool JS_IsRegExp(JSValue val);
+JS_EXTERN bool JS_IsMap(JSValue val);
+JS_EXTERN int JS_IsSimpleValue(JSContext* ctx, JSValue v);
+
+JS_EXTERN JSValue JS_NewArray(JSContext *ctx);
+// takes ownership of the values
+JS_EXTERN JSValue JS_NewArrayFrom(JSContext *ctx, int count,
+ const JSValue *values);
+JS_EXTERN int JS_IsArray(JSContext *ctx, JSValue val);
+
+JS_EXTERN JSValue JS_NewDate(JSContext *ctx, double epoch_ms);
+JS_EXTERN bool JS_IsDate(JSValue v);
+
+JS_EXTERN JSValue JS_GetProperty(JSContext *ctx, JSValue this_obj, JSAtom prop);
+JS_EXTERN JSValue JS_GetPropertyUint32(JSContext *ctx, JSValue this_obj,
+ uint32_t idx);
+JS_EXTERN JSValue JS_GetPropertyInt64(JSContext *ctx, JSValue this_obj,
+ int64_t idx);
+JS_EXTERN JSValue JS_GetPropertyStr(JSContext *ctx, JSValue this_obj,
+ const char *prop);
+
+JS_EXTERN int JS_SetProperty(JSContext *ctx, JSValue this_obj,
+ JSAtom prop, JSValue val);
+JS_EXTERN int JS_SetPropertyUint32(JSContext *ctx, JSValue this_obj,
+ uint32_t idx, JSValue val);
+JS_EXTERN int JS_SetPropertyInt64(JSContext *ctx, JSValue this_obj,
+ int64_t idx, JSValue val);
+JS_EXTERN int JS_SetPropertyStr(JSContext *ctx, JSValue this_obj,
+ const char *prop, JSValue val);
+JS_EXTERN int JS_HasProperty(JSContext *ctx, JSValue this_obj, JSAtom prop);
+JS_EXTERN int JS_IsExtensible(JSContext *ctx, JSValue obj);
+JS_EXTERN int JS_PreventExtensions(JSContext *ctx, JSValue obj);
+JS_EXTERN int JS_DeleteProperty(JSContext *ctx, JSValue obj, JSAtom prop, int flags);
+JS_EXTERN int JS_SetPrototype(JSContext *ctx, JSValue obj, JSValue proto_val);
+JS_EXTERN JSValue JS_GetPrototype(JSContext *ctx, JSValue val);
+JS_EXTERN int JS_GetLength(JSContext *ctx, JSValue obj, int64_t *pres);
+JS_EXTERN int JS_SetLength(JSContext *ctx, JSValue obj, int64_t len);
+JS_EXTERN int JS_SealObject(JSContext *ctx, JSValue obj);
+JS_EXTERN int JS_FreezeObject(JSContext *ctx, JSValue obj);
#define JS_GPN_STRING_MASK (1 << 0)
#define JS_GPN_SYMBOL_MASK (1 << 1)
@@ -731,62 +790,75 @@ JSValue JS_ObjectSeal(JSContext *ctx, JSValueConst obj, int freeze);
/* set theJSPropertyEnum.is_enumerable field */
#define JS_GPN_SET_ENUM (1 << 5)
-int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab,
- uint32_t *plen, JSValueConst obj, int flags);
-int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc,
- JSValueConst obj, JSAtom prop);
-
-JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv);
-JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom,
- int argc, JSValueConst *argv);
-JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,
- int argc, JSValueConst *argv);
-JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,
- JSValueConst new_target,
- int argc, JSValueConst *argv);
-JS_BOOL JS_DetectModule(const char *input, size_t input_len);
+JS_EXTERN int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab,
+ uint32_t *plen, JSValue obj, int flags);
+JS_EXTERN int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc,
+ JSValue obj, JSAtom prop);
+JS_EXTERN void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab,
+ uint32_t len);
+
+JS_EXTERN JSValue JS_Call(JSContext *ctx, JSValue func_obj, JSValue this_obj,
+ int argc, JSValue *argv);
+JS_EXTERN JSValue JS_Invoke(JSContext *ctx, JSValue this_val, JSAtom atom,
+ int argc, JSValue *argv);
+JS_EXTERN JSValue JS_CallConstructor(JSContext *ctx, JSValue func_obj,
+ int argc, JSValue *argv);
+JS_EXTERN JSValue JS_CallConstructor2(JSContext *ctx, JSValue func_obj,
+ JSValue new_target,
+ int argc, JSValue *argv);
+/* Try to detect if the input is a module. Returns true if parsing the input
+ * as a module produces no syntax errors. It's a naive approach that is not
+ * wholly infallible: non-strict classic scripts may _parse_ okay as a module
+ * but not _execute_ as one (different runtime semantics.) Use with caution.
+ * |input| can be either ASCII or UTF-8 encoded source code.
+ */
+JS_EXTERN bool JS_DetectModule(const char *input, size_t input_len);
/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
-JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
- const char *filename, int eval_flags);
-/* same as JS_Eval() but with an explicit 'this_obj' parameter */
-JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
- const char *filename, int line, int eval_flags);
-JSValue JS_GetGlobalObject(JSContext *ctx);
-int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj);
-int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop, JSValueConst val,
- JSValueConst getter, JSValueConst setter, int flags);
-int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop, JSValue val, int flags);
-int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj,
- uint32_t idx, JSValue val, int flags);
-int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,
- const char *prop, JSValue val, int flags);
-int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop, JSValue getter, JSValue setter,
- int flags);
-void JS_SetOpaque(JSValue obj, void *opaque);
-void *JS_GetOpaque(JSValueConst obj, JSClassID class_id);
-void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id);
+JS_EXTERN JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
+ const char *filename, int eval_flags);
+JS_EXTERN JSValue JS_Eval2(JSContext *ctx, const char *input, size_t input_len,
+ JSEvalOptions *options);
+JS_EXTERN JSValue JS_EvalThis(JSContext *ctx, JSValue this_obj,
+ const char *input, size_t input_len,
+ const char *filename, int eval_flags);
+JS_EXTERN JSValue JS_EvalThis2(JSContext *ctx, JSValue this_obj,
+ const char *input, size_t input_len,
+ JSEvalOptions *options);
+JS_EXTERN JSValue JS_GetGlobalObject(JSContext *ctx);
+JS_EXTERN int JS_IsInstanceOf(JSContext *ctx, JSValue val, JSValue obj);
+JS_EXTERN int JS_DefineProperty(JSContext *ctx, JSValue this_obj,
+ JSAtom prop, JSValue val,
+ JSValue getter, JSValue setter, int flags);
+JS_EXTERN int JS_DefinePropertyValue(JSContext *ctx, JSValue this_obj,
+ JSAtom prop, JSValue val, int flags);
+JS_EXTERN int JS_DefinePropertyValueUint32(JSContext *ctx, JSValue this_obj,
+ uint32_t idx, JSValue val, int flags);
+JS_EXTERN int JS_DefinePropertyValueStr(JSContext *ctx, JSValue this_obj,
+ const char *prop, JSValue val, int flags);
+JS_EXTERN int JS_DefinePropertyGetSet(JSContext *ctx, JSValue this_obj,
+ JSAtom prop, JSValue getter, JSValue setter,
+ int flags);
+/* Only supported for custom classes, returns 0 on success < 0 otherwise. */
+JS_EXTERN int JS_SetOpaque(JSValue obj, void *opaque);
+JS_EXTERN void *JS_GetOpaque(JSValue obj, JSClassID class_id);
+JS_EXTERN void *JS_GetOpaque2(JSContext *ctx, JSValue obj, JSClassID class_id);
+JS_EXTERN void *JS_GetAnyOpaque(JSValue obj, JSClassID *class_id);
/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */
-JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
- const char *filename);
-#define JS_PARSE_JSON_EXT (1 << 0) /* allow extended JSON */
-JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,
- const char *filename, int flags);
-JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
- JSValueConst replacer, JSValueConst space0);
+JS_EXTERN JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
+ const char *filename);
+JS_EXTERN JSValue JS_JSONStringify(JSContext *ctx, JSValue obj,
+ JSValue replacer, JSValue space0);
typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr);
-JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
- JSFreeArrayBufferDataFunc *free_func, void *opaque,
- JS_BOOL is_shared);
-JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
-void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj);
-uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj);
+JS_EXTERN JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
+ JSFreeArrayBufferDataFunc *free_func, void *opaque,
+ bool is_shared);
+JS_EXTERN JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
+JS_EXTERN void JS_DetachArrayBuffer(JSContext *ctx, JSValue obj);
+JS_EXTERN uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValue obj);
+JS_EXTERN bool JS_IsArrayBuffer(JSValue obj);
+JS_EXTERN uint8_t *JS_GetUint8Array(JSContext *ctx, size_t *psize, JSValue obj);
typedef enum JSTypedArrayEnum {
JS_TYPED_ARRAY_UINT8C = 0,
@@ -798,24 +870,30 @@ typedef enum JSTypedArrayEnum {
JS_TYPED_ARRAY_UINT32,
JS_TYPED_ARRAY_BIG_INT64,
JS_TYPED_ARRAY_BIG_UINT64,
+ JS_TYPED_ARRAY_FLOAT16,
JS_TYPED_ARRAY_FLOAT32,
JS_TYPED_ARRAY_FLOAT64,
} JSTypedArrayEnum;
-JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv,
+JS_EXTERN JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValue *argv,
JSTypedArrayEnum array_type);
-JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj,
- size_t *pbyte_offset,
- size_t *pbyte_length,
- size_t *pbytes_per_element);
+JS_EXTERN JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValue obj,
+ size_t *pbyte_offset,
+ size_t *pbyte_length,
+ size_t *pbytes_per_element);
+JS_EXTERN JSValue JS_NewUint8Array(JSContext *ctx, uint8_t *buf, size_t len,
+ JSFreeArrayBufferDataFunc *free_func, void *opaque,
+ bool is_shared);
+/* returns -1 if not a typed array otherwise return a JSTypedArrayEnum value */
+JS_EXTERN int JS_GetTypedArrayType(JSValue obj);
+JS_EXTERN JSValue JS_NewUint8ArrayCopy(JSContext *ctx, const uint8_t *buf, size_t len);
typedef struct {
void *(*sab_alloc)(void *opaque, size_t size);
void (*sab_free)(void *opaque, void *ptr);
void (*sab_dup)(void *opaque, void *ptr);
void *sab_opaque;
} JSSharedArrayBufferFunctions;
-void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,
- const JSSharedArrayBufferFunctions *sf);
+JS_EXTERN void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, const JSSharedArrayBufferFunctions *sf);
typedef enum JSPromiseStateEnum {
JS_PROMISE_PENDING,
@@ -823,23 +901,26 @@ typedef enum JSPromiseStateEnum {
JS_PROMISE_REJECTED,
} JSPromiseStateEnum;
-JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);
-JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise);
-JSValue JS_PromiseResult(JSContext *ctx, JSValue promise);
+JS_EXTERN JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);
+JS_EXTERN JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise);
+JS_EXTERN JSValue JS_PromiseResult(JSContext *ctx, JSValue promise);
+JS_EXTERN bool JS_IsPromise(JSValue val);
-/* is_handled = TRUE means that the rejection is handled */
-typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise,
- JSValueConst reason,
- JS_BOOL is_handled, void *opaque);
-void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque);
+JS_EXTERN JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global);
+
+/* is_handled = true means that the rejection is handled */
+typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValue promise,
+ JSValue reason,
+ bool is_handled, void *opaque);
+JS_EXTERN void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque);
/* return != 0 if the JS code needs to be interrupted */
typedef int JSInterruptHandler(JSRuntime *rt, void *opaque);
-void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque);
-/* if can_block is TRUE, Atomics.wait() can be used */
-void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block);
+JS_EXTERN void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque);
+/* if can_block is true, Atomics.wait() can be used */
+JS_EXTERN void JS_SetCanBlock(JSRuntime *rt, bool can_block);
/* set the [IsHTMLDDA] internal slot */
-void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj);
+JS_EXTERN void JS_SetIsHTMLDDA(JSContext *ctx, JSValue obj);
typedef struct JSModuleDef JSModuleDef;
@@ -853,51 +934,57 @@ typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx,
/* module_normalize = NULL is allowed and invokes the default module
filename normalizer */
-void JS_SetModuleLoaderFunc(JSRuntime *rt,
- JSModuleNormalizeFunc *module_normalize,
- JSModuleLoaderFunc *module_loader, void *opaque);
+JS_EXTERN void JS_SetModuleLoaderFunc(JSRuntime *rt,
+ JSModuleNormalizeFunc *module_normalize,
+ JSModuleLoaderFunc *module_loader, void *opaque);
/* return the import.meta object of a module */
-JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m);
-JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m);
-JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m);
+JS_EXTERN JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m);
+JS_EXTERN JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m);
+JS_EXTERN JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m);
/* JS Job support */
-typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValueConst *argv);
-int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv);
+typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValue *argv);
+JS_EXTERN int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValue *argv);
+
+JS_EXTERN bool JS_IsJobPending(JSRuntime *rt);
+JS_EXTERN int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx);
-JS_BOOL JS_IsJobPending(JSRuntime *rt);
-int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx);
+/* Structure to retrieve (de)serialized SharedArrayBuffer objects. */
+typedef struct JSSABTab {
+ uint8_t **tab;
+ size_t len;
+} JSSABTab;
/* Object Writer/Reader (currently only used to handle precompiled code) */
#define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */
-#define JS_WRITE_OBJ_BSWAP (1 << 1) /* byte swapped output */
+#define JS_WRITE_OBJ_BSWAP (0) /* byte swapped output (obsolete, handled transparently) */
#define JS_WRITE_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */
-#define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to
- encode arbitrary object
- graph */
-uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,
- int flags);
-uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
- int flags, uint8_t ***psab_tab, size_t *psab_tab_len);
+#define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to encode arbitrary object graph */
+#define JS_WRITE_OBJ_STRIP_SOURCE (1 << 4) /* do not write source code information */
+#define JS_WRITE_OBJ_STRIP_DEBUG (1 << 5) /* do not write debug information */
+JS_EXTERN uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValue obj, int flags);
+JS_EXTERN uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValue obj,
+ int flags, JSSABTab *psab_tab);
#define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */
-#define JS_READ_OBJ_ROM_DATA (1 << 1) /* avoid duplicating 'buf' data */
+#define JS_READ_OBJ_ROM_DATA (0) /* avoid duplicating 'buf' data (obsolete, broken by ICs) */
#define JS_READ_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */
#define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */
-JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
- int flags);
+JS_EXTERN JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, int flags);
+JS_EXTERN JSValue JS_ReadObject2(JSContext *ctx, const uint8_t *buf, size_t buf_len,
+ int flags, JSSABTab *psab_tab);
/* instantiate and evaluate a bytecode function. Only used when
reading a script or module with JS_ReadObject() */
-JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj);
+JS_EXTERN JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj);
/* load the dependencies of the module 'obj'. Useful when JS_ReadObject()
returns a module. */
-int JS_ResolveModule(JSContext *ctx, JSValueConst obj);
+JS_EXTERN int JS_ResolveModule(JSContext *ctx, JSValue obj);
/* only exported for os.Worker() */
-JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels);
+JS_EXTERN JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels);
/* only exported for os.Worker() */
-JSValue JS_LoadModule(JSContext *ctx, const char *basename,
+JS_EXTERN JSValue JS_LoadModule(JSContext *ctx, const char *basename,
const char *filename);
/* C function definition */
@@ -919,39 +1006,53 @@ typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */
typedef union JSCFunctionType {
JSCFunction *generic;
- JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
+ JSValue (*generic_magic)(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic);
JSCFunction *constructor;
- JSValue (*constructor_magic)(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic);
+ JSValue (*constructor_magic)(JSContext *ctx, JSValue new_target, int argc, JSValue *argv, int magic);
JSCFunction *constructor_or_func;
double (*f_f)(double);
double (*f_f_f)(double, double);
- JSValue (*getter)(JSContext *ctx, JSValueConst this_val);
- JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val);
- JSValue (*getter_magic)(JSContext *ctx, JSValueConst this_val, int magic);
- JSValue (*setter_magic)(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic);
- JSValue (*iterator_next)(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int *pdone, int magic);
+ JSValue (*getter)(JSContext *ctx, JSValue this_val);
+ JSValue (*setter)(JSContext *ctx, JSValue this_val, JSValue val);
+ JSValue (*getter_magic)(JSContext *ctx, JSValue this_val, int magic);
+ JSValue (*setter_magic)(JSContext *ctx, JSValue this_val, JSValue val, int magic);
+ JSValue (*iterator_next)(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv, int *pdone, int magic);
} JSCFunctionType;
-JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func,
- const char *name,
- int length, JSCFunctionEnum cproto, int magic);
-JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
- int length, int magic, int data_len,
- JSValueConst *data);
-
-JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
- int length);
+JS_EXTERN JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func,
+ const char *name,
+ int length, JSCFunctionEnum cproto, int magic);
+JS_EXTERN JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
+ const char *name,
+ int length, JSCFunctionEnum cproto, int magic,
+ JSValue proto_val);
+JS_EXTERN JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
+ int length, int magic, int data_len,
+ JSValue *data);
+
+static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
+ int length)
+{
+ return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
+}
-JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
- const char *name, int length, JSCFunctionEnum cproto, int magic);
-void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj,
- JSValueConst proto);
+static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
+ const char *name,
+ int length, JSCFunctionEnum cproto, int magic)
+{
+ /* Used to squelch a -Wcast-function-type warning. */
+ JSCFunctionType ft;
+ ft.generic_magic = func;
+ return JS_NewCFunction2(ctx, ft.generic, name, length, cproto, magic);
+}
+JS_EXTERN void JS_SetConstructor(JSContext *ctx, JSValue func_obj,
+ JSValue proto);
/* C property definition */
typedef struct JSCFunctionListEntry {
- const char *name;
+ const char *name; /* pure ASCII or UTF-8 encoded */
uint8_t prop_flags;
uint8_t def_type;
int16_t magic;
@@ -973,9 +1074,10 @@ typedef struct JSCFunctionListEntry {
const struct JSCFunctionListEntry *tab;
int len;
} prop_list;
- const char *str;
+ const char *str; /* pure ASCII or UTF-8 encoded */
int32_t i32;
int64_t i64;
+ uint64_t u64;
double f64;
} u;
} JSCFunctionListEntry;
@@ -992,41 +1094,43 @@ typedef struct JSCFunctionListEntry {
#define JS_DEF_ALIAS 9
/* Note: c++ does not like nested designators */
-#define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } }
-#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } }
-#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } }
-#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } }
-#define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } }
-#define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, .u = { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } }
-#define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u = { .str = cstr } }
-#define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u = { .i32 = val } }
-#define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u = { .i64 = val } }
-#define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, .u = { .f64 = val } }
-#define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, .u = { .i32 = 0 } }
-#define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, .u = { .prop_list = { tab, len } } }
-#define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, -1 } } }
-#define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, base } } }
-
-void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
- const JSCFunctionListEntry *tab,
- int len);
+#define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } }
+#define JS_CFUNC_DEF2(name, length, func1, prop_flags) { name, prop_flags, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } }
+#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } }
+#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } }
+#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } }
+#define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } }
+#define JS_CGETSET_DEF2(name, fgetter, fsetter, prop_flags) { name, prop_flags, JS_DEF_CGETSET, 0, { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } }
+#define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } }
+#define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, { .str = cstr } }
+#define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, { .i32 = val } }
+#define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, { .i64 = val } }
+#define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, { .f64 = val } }
+#define JS_PROP_U2D_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, { .u64 = val } }
+#define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, { .i32 = 0 } }
+#define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, { .prop_list = { tab, len } } }
+#define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, { .alias = { from, -1 } } }
+#define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, { .alias = { from, base } } }
+
+JS_EXTERN void JS_SetPropertyFunctionList(JSContext *ctx, JSValue obj,
+ const JSCFunctionListEntry *tab,
+ int len);
/* C module definition */
typedef int JSModuleInitFunc(JSContext *ctx, JSModuleDef *m);
-JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,
- JSModuleInitFunc *func);
+JS_EXTERN JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,
+ JSModuleInitFunc *func);
/* can only be called before the module is instantiated */
-int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str);
-int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m,
- const JSCFunctionListEntry *tab, int len);
+JS_EXTERN int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str);
+JS_EXTERN int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m,
+ const JSCFunctionListEntry *tab, int len);
/* can only be called after the module is instantiated */
-int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
- JSValue val);
-int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
- const JSCFunctionListEntry *tab, int len);
-
+JS_EXTERN int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
+ JSValue val);
+JS_EXTERN int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
+ const JSCFunctionListEntry *tab, int len);
/* Qbs extensions */
struct LookupResult
@@ -1041,22 +1145,24 @@ void setScopeLookup(JSContext *ctx, ScopeLookup *scopeLookup);
// Alternative: Request with throw in script engine
typedef void FoundUndefinedHandler(JSContext *ctx);
void setFoundUndefinedHandler(JSContext *ctx, FoundUndefinedHandler *handler);
-
typedef void FunctionEnteredHandler(JSContext *ctx, JSValue this_val);
typedef void FunctionExitedHandler(JSContext *ctx);
void setFunctionEnteredHandler(JSContext *ctx, FunctionEnteredHandler *handler);
void setFunctionExitedHandler(JSContext *ctx, FunctionExitedHandler *handler);
-int isSimpleValue(JSValue v);
-#ifndef NDEBUG
-void watchRefCount(void *p);
-#endif
+/* Version */
+
+#define QJS_VERSION_MAJOR 0
+#define QJS_VERSION_MINOR 8
+#define QJS_VERSION_PATCH 0
+#define QJS_VERSION_SUFFIX ""
+
+JS_EXTERN const char* JS_GetVersion(void);
-void build_backtrace(JSContext *ctx, JSValueConst error_obj,
- const char *filename, int line_num,
- int backtrace_flags);
+/* Integration point for quickjs-libc.c, not for public use. */
+JS_EXTERN uintptr_t js_std_cmd(int cmd, ...);
-#undef js_unlikely
+#undef JS_EXTERN
#undef js_force_inline
#ifdef __cplusplus
diff --git a/src/shared/quickjs/quickjs.qbs b/src/shared/quickjs/quickjs.qbs
index e6a102458..160886fd7 100644
--- a/src/shared/quickjs/quickjs.qbs
+++ b/src/shared/quickjs/quickjs.qbs
@@ -22,6 +22,7 @@ StaticLibrary {
"libunicode.h",
"list.h",
"quickjs-atom.h",
+ "quickjs-c-atomics.h",
"quickjs-opcode.h",
"quickjs.c",
"quickjs.h",
diff --git a/src/shared/quickjs/sync.sh b/src/shared/quickjs/sync.sh
new file mode 100755
index 000000000..908ef7a46
--- /dev/null
+++ b/src/shared/quickjs/sync.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+SOURCE_DIR=$1
+if [[ -z "${SOURCE_DIR}" ]]; then
+ echo "Usage: ./sync path/to/quickjs/"
+ exit 1
+fi;
+
+TARGET_DIR=$(dirname "$0")
+
+FILES="
+LICENSE
+cutils.h
+libbf.h
+libregexp.h
+libunicode.c
+libunicode-table.h
+list.h
+quickjs.c
+quickjs.h
+cutils.c
+libbf.c
+libregexp.c
+libregexp-opcode.h
+libunicode.h
+quickjs-atom.h
+quickjs-c-atomics.h
+quickjs-opcode.h"
+
+for FILE in $FILES
+do
+ echo "$SOURCE_DIR/$FILE -> $TARGET_DIR/$FILE"
+ cp "$SOURCE_DIR/$FILE" "$TARGET_DIR/$FILE"
+done \ No newline at end of file
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 0bc983f66..93b936294 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -2712,7 +2712,7 @@ void TestBlackbox::referenceErrorInExport()
m_qbsStderr.contains("referenceErrorInExport.qbs:5:27 While evaluating here"),
m_qbsStderr.constData());
QVERIFY2(
- m_qbsStderr.contains("referenceErrorInExport.qbs:15:31 'includePaths' is not defined"),
+ m_qbsStderr.contains("referenceErrorInExport.qbs:15:31 includePaths is not defined"),
m_qbsStderr.constData());
}
diff --git a/tests/auto/language/tst_language.cpp b/tests/auto/language/tst_language.cpp
index 8a9c2e456..2f70580ea 100644
--- a/tests/auto/language/tst_language.cpp
+++ b/tests/auto/language/tst_language.cpp
@@ -1042,12 +1042,9 @@ void TestLanguage::erroneousFiles_data()
"is allowed.";
QTest::newRow("importloop1")
<< "Loop detected when importing";
- QTest::newRow("nonexistentouter")
- << "'outer' is not defined";
- QTest::newRow("invalid_file")
- << "does not exist";
- QTest::newRow("invalid-parameter-rhs")
- << "'access' is not defined";
+ QTest::newRow("nonexistentouter") << "outer is not defined";
+ QTest::newRow("invalid_file") << "does not exist";
+ QTest::newRow("invalid-parameter-rhs") << "access is not defined";
QTest::newRow("invalid-parameter-type")
<< "Value assigned to property 'stringParameter' does not have type 'string'.";
QTest::newRow("invalid_property_type")
@@ -1125,7 +1122,7 @@ void TestLanguage::erroneousFiles_data()
QTest::newRow("missing-colon")
<< "Invalid item 'dummy.cxxFlags'. Did you mean to set a module property?";
QTest::newRow("syntax-error-in-probe")
- << "syntax-error-in-probe.qbs:4:20.*'fngkgsdjfgklkf' is not defined";
+ << "syntax-error-in-probe.qbs:4:20.*fngkgsdjfgklkf is not defined";
QTest::newRow("wrong-toplevel-item")
<< "wrong-toplevel-item.qbs:1:1.*The top-level item must be of type 'Project' or "
"'Product', but it is of type 'Artifact'.";