mirror of
https://github.com/bellard/quickjs.git
synced 2026-05-27 19:09:36 +00:00
Add Uint8Array base64/hex methods (initial patch by saghul)
Some checks failed
ci / Linux (Ubuntu) (push) Has been cancelled
ci / Linux LTO (push) Has been cancelled
ci / Linux 32bit (push) Has been cancelled
ci / linux-asan (push) Has been cancelled
ci / linux-msan (push) Has been cancelled
ci / linux-ubsan (push) Has been cancelled
ci / macOS (push) Has been cancelled
ci / macos-asan (push) Has been cancelled
ci / macos-ubsan (push) Has been cancelled
ci / freebsd (push) Has been cancelled
ci / Cosmopolitan (push) Has been cancelled
ci / MinGW Windows target (push) Has been cancelled
ci / Windows MSYS2 (push) Has been cancelled
ci / qemu-alpine (linux/386) (push) Has been cancelled
ci / qemu-alpine (linux/arm/v6) (push) Has been cancelled
ci / qemu-alpine (linux/arm/v7) (push) Has been cancelled
ci / qemu-alpine (linux/arm64) (push) Has been cancelled
ci / qemu-alpine (linux/ppc64le) (push) Has been cancelled
ci / qemu-alpine (linux/riscv64) (push) Has been cancelled
ci / qemu-alpine (linux/s390x) (push) Has been cancelled
Some checks failed
ci / Linux (Ubuntu) (push) Has been cancelled
ci / Linux LTO (push) Has been cancelled
ci / Linux 32bit (push) Has been cancelled
ci / linux-asan (push) Has been cancelled
ci / linux-msan (push) Has been cancelled
ci / linux-ubsan (push) Has been cancelled
ci / macOS (push) Has been cancelled
ci / macos-asan (push) Has been cancelled
ci / macos-ubsan (push) Has been cancelled
ci / freebsd (push) Has been cancelled
ci / Cosmopolitan (push) Has been cancelled
ci / MinGW Windows target (push) Has been cancelled
ci / Windows MSYS2 (push) Has been cancelled
ci / qemu-alpine (linux/386) (push) Has been cancelled
ci / qemu-alpine (linux/arm/v6) (push) Has been cancelled
ci / qemu-alpine (linux/arm/v7) (push) Has been cancelled
ci / qemu-alpine (linux/arm64) (push) Has been cancelled
ci / qemu-alpine (linux/ppc64le) (push) Has been cancelled
ci / qemu-alpine (linux/riscv64) (push) Has been cancelled
ci / qemu-alpine (linux/s390x) (push) Has been cancelled
This commit is contained in:
parent
1f50b39e99
commit
e182e3df5c
2
TODO
2
TODO
@ -63,4 +63,4 @@ Test262o: 0/11262 errors, 463 excluded
|
||||
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
||||
|
||||
Test262:
|
||||
Result: 60/83436 errors, 3348 excluded, 6069 skipped
|
||||
Result: 58/83574 errors, 3348 excluded, 6000 skipped
|
||||
|
||||
@ -190,6 +190,10 @@ DEF(unicodeSets, "unicodeSets")
|
||||
DEF(not_equal, "not-equal")
|
||||
DEF(timed_out, "timed-out")
|
||||
DEF(ok, "ok")
|
||||
DEF(toISOString, "toISOString")
|
||||
DEF(alphabet, "alphabet")
|
||||
DEF(lastChunkHandling, "lastChunkHandling")
|
||||
DEF(omitPadding, "omitPadding")
|
||||
/* */
|
||||
DEF(toJSON, "toJSON")
|
||||
DEF(maxByteLength, "maxByteLength")
|
||||
|
||||
835
quickjs.c
835
quickjs.c
@ -1345,6 +1345,10 @@ static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv);
|
||||
static JSVarRef *js_global_object_find_uninitialized_var(JSContext *ctx, JSObject *p,
|
||||
JSAtom atom, BOOL is_lexical);
|
||||
static int typed_array_init(JSContext *ctx, JSValueConst obj,
|
||||
JSValue buffer, uint64_t offset, uint64_t len,
|
||||
BOOL track_rab);
|
||||
|
||||
|
||||
static const JSClassExoticMethods js_arguments_exotic_methods;
|
||||
static const JSClassExoticMethods js_string_exotic_methods;
|
||||
@ -55371,7 +55375,7 @@ static JSValue js_date_toJSON(JSContext *ctx, JSValueConst this_val,
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
method = JS_GetPropertyStr(ctx, obj, "toISOString");
|
||||
method = JS_GetProperty(ctx, obj, JS_ATOM_toISOString);
|
||||
if (JS_IsException(method))
|
||||
goto exception;
|
||||
if (!JS_IsFunction(ctx, method)) {
|
||||
@ -58247,6 +58251,797 @@ static JSValue js_typed_array_toSorted(JSContext *ctx, JSValueConst this_val,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Uint8Array base64/hex (tc39 proposal-arraybuffer-base64) */
|
||||
|
||||
enum {
|
||||
B64_ALPHABET_BASE64 = 0,
|
||||
B64_ALPHABET_BASE64URL = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
B64_LAST_LOOSE = 0,
|
||||
B64_LAST_STRICT = 1,
|
||||
B64_LAST_STOP_BEFORE_PARTIAL = 2,
|
||||
};
|
||||
|
||||
static const unsigned char b64_enc[64] = {
|
||||
'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',
|
||||
'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',
|
||||
'0','1','2','3','4','5','6','7','8','9',
|
||||
'+','/'
|
||||
};
|
||||
|
||||
static const unsigned char b64url_enc[64] = {
|
||||
'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',
|
||||
'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',
|
||||
'0','1','2','3','4','5','6','7','8','9',
|
||||
'-','_'
|
||||
};
|
||||
|
||||
#define K_WS 64
|
||||
#define K_ER 65
|
||||
|
||||
static const uint8_t b64_dec[256] = {
|
||||
[ 0]=K_ER, [ 1]=K_ER, [ 2]=K_ER, [ 3]=K_ER, [ 4]=K_ER, [ 5]=K_ER, [ 6]=K_ER, [ 7]=K_ER,
|
||||
[ 8]=K_ER, [ 9]=K_WS, [ 10]=K_WS, [ 11]=K_ER, [ 12]=K_WS, [ 13]=K_WS, [ 14]=K_ER, [ 15]=K_ER,
|
||||
[ 16]=K_ER, [ 17]=K_ER, [ 18]=K_ER, [ 19]=K_ER, [ 20]=K_ER, [ 21]=K_ER, [ 22]=K_ER, [ 23]=K_ER,
|
||||
[ 24]=K_ER, [ 25]=K_ER, [ 26]=K_ER, [ 27]=K_ER, [ 28]=K_ER, [ 29]=K_ER, [ 30]=K_ER, [ 31]=K_ER,
|
||||
[' ']=K_WS, ['!']=K_ER, ['"']=K_ER, ['#']=K_ER, ['$']=K_ER, ['%']=K_ER, ['&']=K_ER, [ 39]=K_ER,
|
||||
['(']=K_ER, [')']=K_ER, ['*']=K_ER, ['+']= 62, [',']=K_ER, ['-']=K_ER, ['.']=K_ER, ['/']= 63,
|
||||
['0']= 52, ['1']= 53, ['2']= 54, ['3']= 55, ['4']= 56, ['5']= 57, ['6']= 58, ['7']= 59,
|
||||
['8']= 60, ['9']= 61, [':']=K_ER, [';']=K_ER, ['<']=K_ER, ['=']=K_ER, ['>']=K_ER, ['?']=K_ER,
|
||||
['@']=K_ER, ['A']= 0, ['B']= 1, ['C']= 2, ['D']= 3, ['E']= 4, ['F']= 5, ['G']= 6,
|
||||
['H']= 7, ['I']= 8, ['J']= 9, ['K']= 10, ['L']= 11, ['M']= 12, ['N']= 13, ['O']= 14,
|
||||
['P']= 15, ['Q']= 16, ['R']= 17, ['S']= 18, ['T']= 19, ['U']= 20, ['V']= 21, ['W']= 22,
|
||||
['X']= 23, ['Y']= 24, ['Z']= 25, ['[']=K_ER, [ 92]=K_ER, [']']=K_ER, ['^']=K_ER, ['_']=K_ER,
|
||||
['`']=K_ER, ['a']= 26, ['b']= 27, ['c']= 28, ['d']= 29, ['e']= 30, ['f']= 31, ['g']= 32,
|
||||
['h']= 33, ['i']= 34, ['j']= 35, ['k']= 36, ['l']= 37, ['m']= 38, ['n']= 39, ['o']= 40,
|
||||
['p']= 41, ['q']= 42, ['r']= 43, ['s']= 44, ['t']= 45, ['u']= 46, ['v']= 47, ['w']= 48,
|
||||
['x']= 49, ['y']= 50, ['z']= 51, ['{']=K_ER, ['|']=K_ER, ['}']=K_ER, ['~']=K_ER, [127]=K_ER,
|
||||
[128]=K_ER, [129]=K_ER, [130]=K_ER, [131]=K_ER, [132]=K_ER, [133]=K_ER, [134]=K_ER, [135]=K_ER,
|
||||
[136]=K_ER, [137]=K_ER, [138]=K_ER, [139]=K_ER, [140]=K_ER, [141]=K_ER, [142]=K_ER, [143]=K_ER,
|
||||
[144]=K_ER, [145]=K_ER, [146]=K_ER, [147]=K_ER, [148]=K_ER, [149]=K_ER, [150]=K_ER, [151]=K_ER,
|
||||
[152]=K_ER, [153]=K_ER, [154]=K_ER, [155]=K_ER, [156]=K_ER, [157]=K_ER, [158]=K_ER, [159]=K_ER,
|
||||
[160]=K_ER, [161]=K_ER, [162]=K_ER, [163]=K_ER, [164]=K_ER, [165]=K_ER, [166]=K_ER, [167]=K_ER,
|
||||
[168]=K_ER, [169]=K_ER, [170]=K_ER, [171]=K_ER, [172]=K_ER, [173]=K_ER, [174]=K_ER, [175]=K_ER,
|
||||
[176]=K_ER, [177]=K_ER, [178]=K_ER, [179]=K_ER, [180]=K_ER, [181]=K_ER, [182]=K_ER, [183]=K_ER,
|
||||
[184]=K_ER, [185]=K_ER, [186]=K_ER, [187]=K_ER, [188]=K_ER, [189]=K_ER, [190]=K_ER, [191]=K_ER,
|
||||
[192]=K_ER, [193]=K_ER, [194]=K_ER, [195]=K_ER, [196]=K_ER, [197]=K_ER, [198]=K_ER, [199]=K_ER,
|
||||
[200]=K_ER, [201]=K_ER, [202]=K_ER, [203]=K_ER, [204]=K_ER, [205]=K_ER, [206]=K_ER, [207]=K_ER,
|
||||
[208]=K_ER, [209]=K_ER, [210]=K_ER, [211]=K_ER, [212]=K_ER, [213]=K_ER, [214]=K_ER, [215]=K_ER,
|
||||
[216]=K_ER, [217]=K_ER, [218]=K_ER, [219]=K_ER, [220]=K_ER, [221]=K_ER, [222]=K_ER, [223]=K_ER,
|
||||
[224]=K_ER, [225]=K_ER, [226]=K_ER, [227]=K_ER, [228]=K_ER, [229]=K_ER, [230]=K_ER, [231]=K_ER,
|
||||
[232]=K_ER, [233]=K_ER, [234]=K_ER, [235]=K_ER, [236]=K_ER, [237]=K_ER, [238]=K_ER, [239]=K_ER,
|
||||
[240]=K_ER, [241]=K_ER, [242]=K_ER, [243]=K_ER, [244]=K_ER, [245]=K_ER, [246]=K_ER, [247]=K_ER,
|
||||
[248]=K_ER, [249]=K_ER, [250]=K_ER, [251]=K_ER, [252]=K_ER, [253]=K_ER, [254]=K_ER, [255]=K_ER,
|
||||
};
|
||||
|
||||
static const uint8_t b64url_dec[256] = {
|
||||
[ 0]=K_ER, [ 1]=K_ER, [ 2]=K_ER, [ 3]=K_ER, [ 4]=K_ER, [ 5]=K_ER, [ 6]=K_ER, [ 7]=K_ER,
|
||||
[ 8]=K_ER, [ 9]=K_WS, [ 10]=K_WS, [ 11]=K_ER, [ 12]=K_WS, [ 13]=K_WS, [ 14]=K_ER, [ 15]=K_ER,
|
||||
[ 16]=K_ER, [ 17]=K_ER, [ 18]=K_ER, [ 19]=K_ER, [ 20]=K_ER, [ 21]=K_ER, [ 22]=K_ER, [ 23]=K_ER,
|
||||
[ 24]=K_ER, [ 25]=K_ER, [ 26]=K_ER, [ 27]=K_ER, [ 28]=K_ER, [ 29]=K_ER, [ 30]=K_ER, [ 31]=K_ER,
|
||||
[' ']=K_WS, ['!']=K_ER, ['"']=K_ER, ['#']=K_ER, ['$']=K_ER, ['%']=K_ER, ['&']=K_ER, [ 39]=K_ER,
|
||||
['(']=K_ER, [')']=K_ER, ['*']=K_ER, ['+']=K_ER, [',']=K_ER, ['-']= 62, ['.']=K_ER, ['/']=K_ER,
|
||||
['0']= 52, ['1']= 53, ['2']= 54, ['3']= 55, ['4']= 56, ['5']= 57, ['6']= 58, ['7']= 59,
|
||||
['8']= 60, ['9']= 61, [':']=K_ER, [';']=K_ER, ['<']=K_ER, ['=']=K_ER, ['>']=K_ER, ['?']=K_ER,
|
||||
['@']=K_ER, ['A']= 0, ['B']= 1, ['C']= 2, ['D']= 3, ['E']= 4, ['F']= 5, ['G']= 6,
|
||||
['H']= 7, ['I']= 8, ['J']= 9, ['K']= 10, ['L']= 11, ['M']= 12, ['N']= 13, ['O']= 14,
|
||||
['P']= 15, ['Q']= 16, ['R']= 17, ['S']= 18, ['T']= 19, ['U']= 20, ['V']= 21, ['W']= 22,
|
||||
['X']= 23, ['Y']= 24, ['Z']= 25, ['[']=K_ER, [ 92]=K_ER, [']']=K_ER, ['^']=K_ER, ['_']= 63,
|
||||
['`']=K_ER, ['a']= 26, ['b']= 27, ['c']= 28, ['d']= 29, ['e']= 30, ['f']= 31, ['g']= 32,
|
||||
['h']= 33, ['i']= 34, ['j']= 35, ['k']= 36, ['l']= 37, ['m']= 38, ['n']= 39, ['o']= 40,
|
||||
['p']= 41, ['q']= 42, ['r']= 43, ['s']= 44, ['t']= 45, ['u']= 46, ['v']= 47, ['w']= 48,
|
||||
['x']= 49, ['y']= 50, ['z']= 51, ['{']=K_ER, ['|']=K_ER, ['}']=K_ER, ['~']=K_ER, [127]=K_ER,
|
||||
[128]=K_ER, [129]=K_ER, [130]=K_ER, [131]=K_ER, [132]=K_ER, [133]=K_ER, [134]=K_ER, [135]=K_ER,
|
||||
[136]=K_ER, [137]=K_ER, [138]=K_ER, [139]=K_ER, [140]=K_ER, [141]=K_ER, [142]=K_ER, [143]=K_ER,
|
||||
[144]=K_ER, [145]=K_ER, [146]=K_ER, [147]=K_ER, [148]=K_ER, [149]=K_ER, [150]=K_ER, [151]=K_ER,
|
||||
[152]=K_ER, [153]=K_ER, [154]=K_ER, [155]=K_ER, [156]=K_ER, [157]=K_ER, [158]=K_ER, [159]=K_ER,
|
||||
[160]=K_ER, [161]=K_ER, [162]=K_ER, [163]=K_ER, [164]=K_ER, [165]=K_ER, [166]=K_ER, [167]=K_ER,
|
||||
[168]=K_ER, [169]=K_ER, [170]=K_ER, [171]=K_ER, [172]=K_ER, [173]=K_ER, [174]=K_ER, [175]=K_ER,
|
||||
[176]=K_ER, [177]=K_ER, [178]=K_ER, [179]=K_ER, [180]=K_ER, [181]=K_ER, [182]=K_ER, [183]=K_ER,
|
||||
[184]=K_ER, [185]=K_ER, [186]=K_ER, [187]=K_ER, [188]=K_ER, [189]=K_ER, [190]=K_ER, [191]=K_ER,
|
||||
[192]=K_ER, [193]=K_ER, [194]=K_ER, [195]=K_ER, [196]=K_ER, [197]=K_ER, [198]=K_ER, [199]=K_ER,
|
||||
[200]=K_ER, [201]=K_ER, [202]=K_ER, [203]=K_ER, [204]=K_ER, [205]=K_ER, [206]=K_ER, [207]=K_ER,
|
||||
[208]=K_ER, [209]=K_ER, [210]=K_ER, [211]=K_ER, [212]=K_ER, [213]=K_ER, [214]=K_ER, [215]=K_ER,
|
||||
[216]=K_ER, [217]=K_ER, [218]=K_ER, [219]=K_ER, [220]=K_ER, [221]=K_ER, [222]=K_ER, [223]=K_ER,
|
||||
[224]=K_ER, [225]=K_ER, [226]=K_ER, [227]=K_ER, [228]=K_ER, [229]=K_ER, [230]=K_ER, [231]=K_ER,
|
||||
[232]=K_ER, [233]=K_ER, [234]=K_ER, [235]=K_ER, [236]=K_ER, [237]=K_ER, [238]=K_ER, [239]=K_ER,
|
||||
[240]=K_ER, [241]=K_ER, [242]=K_ER, [243]=K_ER, [244]=K_ER, [245]=K_ER, [246]=K_ER, [247]=K_ER,
|
||||
[248]=K_ER, [249]=K_ER, [250]=K_ER, [251]=K_ER, [252]=K_ER, [253]=K_ER, [254]=K_ER, [255]=K_ER,
|
||||
};
|
||||
|
||||
static size_t b64_encode(const uint8_t *src, size_t len, char *dst,
|
||||
const unsigned char *alpha)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0, j = 0; i + 3 <= len; i += 3, j += 4) {
|
||||
uint32_t v = 65536*src[i] + 256*src[i + 1] + src[i + 2];
|
||||
dst[j + 0] = alpha[(v >> 18) & 63];
|
||||
dst[j + 1] = alpha[(v >> 12) & 63];
|
||||
dst[j + 2] = alpha[(v >> 6) & 63];
|
||||
dst[j + 3] = alpha[v & 63];
|
||||
}
|
||||
|
||||
size_t rem = len - i;
|
||||
if (rem == 1) {
|
||||
uint32_t v = 65536*src[i];
|
||||
dst[j++] = alpha[(v >> 18) & 63];
|
||||
dst[j++] = alpha[(v >> 12) & 63];
|
||||
dst[j++] = '=';
|
||||
dst[j++] = '=';
|
||||
} else if (rem == 2) {
|
||||
uint32_t v = 65536*src[i] + 256*src[i + 1];
|
||||
dst[j++] = alpha[(v >> 18) & 63];
|
||||
dst[j++] = alpha[(v >> 12) & 63];
|
||||
dst[j++] = alpha[(v >> 6) & 63];
|
||||
dst[j++] = '=';
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
static size_t b64_skip_ws(const char *src, size_t len, size_t index,
|
||||
const uint8_t *dec_table)
|
||||
{
|
||||
while (index < len && dec_table[(unsigned char)src[index]] == K_WS)
|
||||
index++;
|
||||
return index;
|
||||
}
|
||||
|
||||
/* Implements the FromBase64 abstract operation.
|
||||
src/src_len: the input string (must be ASCII/latin1)
|
||||
dst/max_len: output buffer
|
||||
flags: b64_flags or b64_flags_url (selects valid characters)
|
||||
last_chunk: B64_LAST_LOOSE, B64_LAST_STRICT, or B64_LAST_STOP_BEFORE_PARTIAL
|
||||
*p_read: set to number of input characters consumed
|
||||
*p_err: set to 1 on error, 0 on success
|
||||
Returns: number of bytes written to dst */
|
||||
static size_t from_base64(const char *src, size_t src_len,
|
||||
uint8_t *dst, size_t max_len,
|
||||
const uint8_t *dec_table, int last_chunk,
|
||||
size_t *p_read, int *p_err)
|
||||
{
|
||||
size_t read = 0, written = 0;
|
||||
uint32_t v, acc = 0;
|
||||
int seen = 0;
|
||||
size_t index = 0;
|
||||
uint8_t ch;
|
||||
|
||||
*p_err = 0;
|
||||
|
||||
if (max_len == 0) {
|
||||
*p_read = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (seen == 0) {
|
||||
/* Fast path: decode complete groups of 4 valid characters.
|
||||
Breaks out on whitespace, padding, invalid chars, or capacity. */
|
||||
while (index + 4 <= src_len && written + 3 <= max_len) {
|
||||
uint32_t v0, v1, v2, v3;
|
||||
v0 = dec_table[(unsigned char)src[index]];
|
||||
v1 = dec_table[(unsigned char)src[index + 1]];
|
||||
v2 = dec_table[(unsigned char)src[index + 2]];
|
||||
v3 = dec_table[(unsigned char)src[index + 3]];
|
||||
if ((v0 | v1 | v2 | v3) >= 64)
|
||||
break;
|
||||
v = (v0 << 18) | (v1 << 12) | (v2 << 6) | v3;
|
||||
dst[written] = (uint8_t)(v >> 16);
|
||||
dst[written + 1] = (uint8_t)(v >> 8);
|
||||
dst[written + 2] = (uint8_t)(v);
|
||||
written += 3;
|
||||
index += 4;
|
||||
}
|
||||
read = index;
|
||||
|
||||
if (written >= max_len) {
|
||||
*p_read = read;
|
||||
return written;
|
||||
}
|
||||
}
|
||||
|
||||
/* Slow path: handle whitespace, padding, partial groups, capacity. */
|
||||
index = b64_skip_ws(src, src_len, index, dec_table);
|
||||
|
||||
if (index == src_len) {
|
||||
if (seen > 0) {
|
||||
if (last_chunk == B64_LAST_STOP_BEFORE_PARTIAL) {
|
||||
*p_read = read;
|
||||
return written;
|
||||
}
|
||||
if (last_chunk == B64_LAST_STRICT) {
|
||||
*p_err = 1;
|
||||
return 0;
|
||||
}
|
||||
/* loose */
|
||||
if (seen == 1) {
|
||||
*p_err = 1;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
*p_read = src_len;
|
||||
return written;
|
||||
}
|
||||
|
||||
ch = src[index++];
|
||||
|
||||
if (ch == '=') {
|
||||
if (seen < 2) {
|
||||
*p_err = 1;
|
||||
return 0;
|
||||
}
|
||||
index = b64_skip_ws(src, src_len, index, dec_table);
|
||||
if (seen == 2) {
|
||||
if (index == src_len) {
|
||||
if (last_chunk == B64_LAST_STOP_BEFORE_PARTIAL) {
|
||||
*p_read = read;
|
||||
return written;
|
||||
}
|
||||
*p_err = 1;
|
||||
return 0;
|
||||
}
|
||||
if (src[index] == '=') {
|
||||
index++;
|
||||
index = b64_skip_ws(src, src_len, index, dec_table);
|
||||
} else {
|
||||
*p_err = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* After padding, only whitespace is allowed */
|
||||
if (index != src_len) {
|
||||
*p_err = 1;
|
||||
return 0;
|
||||
}
|
||||
if (last_chunk == B64_LAST_STRICT) {
|
||||
uint32_t mask = (seen == 2) ? 0xF : 0x3;
|
||||
if (acc & mask) {
|
||||
*p_err = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
v = dec_table[ch];
|
||||
if (v >= 64) {
|
||||
*p_err = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check remaining capacity before committing to this group */
|
||||
{
|
||||
size_t remaining = max_len - written;
|
||||
if ((remaining == 1 && seen == 2) ||
|
||||
(remaining == 2 && seen == 3)) {
|
||||
*p_read = read;
|
||||
return written;
|
||||
}
|
||||
}
|
||||
|
||||
acc = (acc << 6) | v;
|
||||
seen++;
|
||||
|
||||
if (seen == 4) {
|
||||
dst[written] = (uint8_t)(acc >> 16);
|
||||
dst[written + 1] = (uint8_t)(acc >> 8);
|
||||
dst[written + 2] = (uint8_t)(acc);
|
||||
written += 3;
|
||||
acc = 0;
|
||||
seen = 0;
|
||||
read = index;
|
||||
if (written >= max_len) {
|
||||
*p_read = read;
|
||||
return written;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (seen == 2) {
|
||||
dst[written++] = (uint8_t)(acc >> 4);
|
||||
} else if (seen == 3) {
|
||||
dst[written] = (uint8_t)(acc >> 10);
|
||||
dst[written + 1] = (uint8_t)(acc >> 2);
|
||||
written += 2;
|
||||
}
|
||||
*p_read = src_len;
|
||||
return written;
|
||||
}
|
||||
|
||||
/* Hex helpers */
|
||||
static const char u8a_hex_digits[] = "0123456789abcdef";
|
||||
|
||||
static size_t u8a_hex_encode(const uint8_t *src, size_t len, char *dst)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
dst[i * 2] = u8a_hex_digits[src[i] >> 4];
|
||||
dst[i * 2 + 1] = u8a_hex_digits[src[i] & 0xF];
|
||||
}
|
||||
return len * 2;
|
||||
}
|
||||
|
||||
/* Decode hex string to bytes.
|
||||
Returns bytes written. Sets *p_read to chars consumed, *p_err on error. */
|
||||
static size_t u8a_hex_decode(const char *src, size_t src_len,
|
||||
uint8_t *dst, size_t max_len,
|
||||
size_t *p_read, int *p_err)
|
||||
{
|
||||
size_t written = 0, i = 0;
|
||||
*p_err = 0;
|
||||
|
||||
if (src_len & 1) {
|
||||
*p_err = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (i < src_len && written < max_len) {
|
||||
int hi = from_hex(src[i]);
|
||||
int lo = from_hex(src[i + 1]);
|
||||
if (hi < 0 || lo < 0) {
|
||||
*p_err = 1;
|
||||
return 0;
|
||||
}
|
||||
dst[written++] = (uint8_t)((hi << 4) | lo);
|
||||
i += 2;
|
||||
}
|
||||
|
||||
*p_read = i;
|
||||
return written;
|
||||
}
|
||||
|
||||
static JSValue JS_NewUint8ArrayCopy(JSContext *ctx, const uint8_t *buf, size_t len)
|
||||
{
|
||||
JSValue buffer, obj;
|
||||
JSArrayBuffer *abuf;
|
||||
|
||||
buffer = js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL,
|
||||
JS_CLASS_ARRAY_BUFFER,
|
||||
(uint8_t *)buf,
|
||||
js_array_buffer_free, NULL,
|
||||
TRUE);
|
||||
if (JS_IsException(buffer))
|
||||
return JS_EXCEPTION;
|
||||
obj = js_create_from_ctor(ctx, JS_UNDEFINED, JS_CLASS_UINT8_ARRAY);
|
||||
if (JS_IsException(obj)) {
|
||||
JS_FreeValue(ctx, buffer);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* Validate that this_val is a Uint8Array (type check only, no detach check).
|
||||
Returns the JSObject pointer or NULL on error (throws). */
|
||||
static JSObject *check_uint8array(JSContext *ctx, JSValueConst 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_UINT8_ARRAY)
|
||||
goto fail;
|
||||
return p;
|
||||
fail:
|
||||
JS_ThrowTypeError(ctx, "not a Uint8Array");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the data pointer and length of a Uint8Array, checking for detached
|
||||
buffers. Must be called after options are read (per spec ordering).
|
||||
Returns 0 on success, -1 on error (throws). */
|
||||
static int get_uint8array_bytes(JSContext *ctx, JSObject *p,
|
||||
uint8_t **pdata, size_t *plen)
|
||||
{
|
||||
if (typed_array_is_oob(p)) {
|
||||
JS_ThrowTypeErrorArrayBufferOOB(ctx);
|
||||
*pdata = NULL; /* fail safe */
|
||||
*plen = 0;
|
||||
return -1;
|
||||
}
|
||||
*pdata = p->u.array.u.uint8_ptr;
|
||||
*plen = p->u.array.count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Validate options is undefined or an object (GetOptionsObject).
|
||||
Returns 0 on success, -1 on error (throws). */
|
||||
static int check_options_object(JSContext *ctx, JSValueConst options)
|
||||
{
|
||||
if (JS_IsUndefined(options))
|
||||
return 0;
|
||||
if (!JS_IsObject(options)) {
|
||||
JS_ThrowTypeError(ctx, "options must be an object");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse the 'alphabet' option from an options object.
|
||||
Returns B64_ALPHABET_BASE64 or B64_ALPHABET_BASE64URL, or -1 on error. */
|
||||
static int parse_alphabet_option(JSContext *ctx, JSValueConst options)
|
||||
{
|
||||
JSValue val;
|
||||
const char *str;
|
||||
int ret;
|
||||
|
||||
if (JS_IsUndefined(options))
|
||||
return B64_ALPHABET_BASE64;
|
||||
|
||||
val = JS_GetProperty(ctx, options, JS_ATOM_alphabet);
|
||||
if (JS_IsException(val))
|
||||
return -1;
|
||||
if (JS_IsUndefined(val))
|
||||
return B64_ALPHABET_BASE64;
|
||||
if (!JS_IsString(val)) {
|
||||
JS_FreeValue(ctx, val);
|
||||
JS_ThrowTypeError(ctx, "expected string for alphabet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
str = JS_ToCString(ctx, val);
|
||||
JS_FreeValue(ctx, val);
|
||||
if (!str)
|
||||
return -1;
|
||||
|
||||
if (!strcmp(str, "base64"))
|
||||
ret = B64_ALPHABET_BASE64;
|
||||
else if (!strcmp(str, "base64url"))
|
||||
ret = B64_ALPHABET_BASE64URL;
|
||||
else {
|
||||
JS_ThrowTypeError(ctx, "invalid alphabet");
|
||||
ret = -1;
|
||||
}
|
||||
JS_FreeCString(ctx, str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Parse the 'lastChunkHandling' option. Returns mode or -1 on error. */
|
||||
static int parse_last_chunk_option(JSContext *ctx, JSValueConst options)
|
||||
{
|
||||
JSValue val;
|
||||
const char *str;
|
||||
int ret;
|
||||
|
||||
if (JS_IsUndefined(options))
|
||||
return B64_LAST_LOOSE;
|
||||
|
||||
val = JS_GetProperty(ctx, options, JS_ATOM_lastChunkHandling);
|
||||
if (JS_IsException(val))
|
||||
return -1;
|
||||
if (JS_IsUndefined(val))
|
||||
return B64_LAST_LOOSE;
|
||||
if (!JS_IsString(val)) {
|
||||
JS_FreeValue(ctx, val);
|
||||
JS_ThrowTypeError(ctx, "expected string for lastChunkHandling");
|
||||
return -1;
|
||||
}
|
||||
|
||||
str = JS_ToCString(ctx, val);
|
||||
JS_FreeValue(ctx, val);
|
||||
if (!str)
|
||||
return -1;
|
||||
|
||||
if (!strcmp(str, "loose"))
|
||||
ret = B64_LAST_LOOSE;
|
||||
else if (!strcmp(str, "strict"))
|
||||
ret = B64_LAST_STRICT;
|
||||
else if (!strcmp(str, "stop-before-partial"))
|
||||
ret = B64_LAST_STOP_BEFORE_PARTIAL;
|
||||
else {
|
||||
JS_ThrowTypeError(ctx, "invalid lastChunkHandling option");
|
||||
ret = -1;
|
||||
}
|
||||
JS_FreeCString(ctx, str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Uint8Array.prototype.toBase64([options]) */
|
||||
static JSValue js_uint8array_to_base64(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
JSValueConst options;
|
||||
JSObject *p;
|
||||
int alphabet, omit_padding;
|
||||
size_t out_len, written;
|
||||
JSString *ostr;
|
||||
char *dst;
|
||||
|
||||
p = check_uint8array(ctx, this_val);
|
||||
if (!p)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
options = argc > 0 ? argv[0] : JS_UNDEFINED;
|
||||
if (check_options_object(ctx, options))
|
||||
return JS_EXCEPTION;
|
||||
alphabet = parse_alphabet_option(ctx, options);
|
||||
if (alphabet < 0)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
omit_padding = 0;
|
||||
if (!JS_IsUndefined(options)) {
|
||||
JSValue op_val = JS_GetProperty(ctx, options, JS_ATOM_omitPadding);
|
||||
if (JS_IsException(op_val))
|
||||
return JS_EXCEPTION;
|
||||
omit_padding = JS_ToBool(ctx, op_val);
|
||||
JS_FreeValue(ctx, op_val);
|
||||
}
|
||||
|
||||
if (get_uint8array_bytes(ctx, p, &data, &len))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
out_len = 4 * ((len + 2) / 3);
|
||||
|
||||
if (unlikely(out_len > JS_STRING_LEN_MAX))
|
||||
return JS_ThrowRangeError(ctx, "output too large");
|
||||
|
||||
ostr = js_alloc_string(ctx, out_len, 0);
|
||||
if (!ostr)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
dst = (char *)ostr->u.str8;
|
||||
written = b64_encode(data, len, dst,
|
||||
alphabet == B64_ALPHABET_BASE64URL ? b64url_enc : b64_enc);
|
||||
if (omit_padding) {
|
||||
while (written > 0 && dst[written - 1] == '=')
|
||||
written--;
|
||||
}
|
||||
dst[written] = '\0';
|
||||
|
||||
ostr->len = written;
|
||||
return JS_MKPTR(JS_TAG_STRING, ostr);
|
||||
}
|
||||
|
||||
/* Uint8Array.prototype.toHex() */
|
||||
static JSValue js_uint8array_to_hex(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t len, out_len;
|
||||
JSObject *p;
|
||||
JSString *ostr;
|
||||
|
||||
p = check_uint8array(ctx, this_val);
|
||||
if (!p)
|
||||
return JS_EXCEPTION;
|
||||
if (get_uint8array_bytes(ctx, p, &data, &len))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
out_len = len * 2;
|
||||
if (unlikely(out_len > JS_STRING_LEN_MAX))
|
||||
return JS_ThrowRangeError(ctx, "output too large");
|
||||
|
||||
ostr = js_alloc_string(ctx, out_len, 0);
|
||||
if (!ostr)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
u8a_hex_encode(data, len, (char *)ostr->u.str8);
|
||||
ostr->u.str8[out_len] = '\0';
|
||||
return JS_MKPTR(JS_TAG_STRING, ostr);
|
||||
}
|
||||
|
||||
/* Uint8Array.fromBase64(string[, options]) */
|
||||
static JSValue js_uint8array_from_base64(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
const char *str;
|
||||
size_t str_len, read_pos, decoded_len, out_cap;
|
||||
int alphabet, last_chunk, err;
|
||||
uint8_t *buf;
|
||||
JSValue result;
|
||||
JSValueConst options;
|
||||
|
||||
if (!JS_IsString(argv[0]))
|
||||
return JS_ThrowTypeError(ctx, "expected string");
|
||||
|
||||
str = JS_ToCStringLen(ctx, &str_len, argv[0]);
|
||||
if (!str)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
options = argc > 1 ? argv[1] : JS_UNDEFINED;
|
||||
if (check_options_object(ctx, options)) {
|
||||
JS_FreeCString(ctx, str);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
alphabet = parse_alphabet_option(ctx, options);
|
||||
if (alphabet < 0) {
|
||||
JS_FreeCString(ctx, str);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
last_chunk = parse_last_chunk_option(ctx, options);
|
||||
if (last_chunk < 0) {
|
||||
JS_FreeCString(ctx, str);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
out_cap = (str_len / 4) * 3 + 3;
|
||||
buf = js_malloc(ctx, out_cap);
|
||||
if (!buf) {
|
||||
JS_FreeCString(ctx, str);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
decoded_len = from_base64(str, str_len, buf, out_cap,
|
||||
alphabet == B64_ALPHABET_BASE64URL
|
||||
? b64url_dec : b64_dec,
|
||||
last_chunk, &read_pos, &err);
|
||||
JS_FreeCString(ctx, str);
|
||||
|
||||
if (err) {
|
||||
js_free(ctx, buf);
|
||||
return JS_ThrowSyntaxError(ctx, "invalid base64 string");
|
||||
}
|
||||
|
||||
result = JS_NewUint8ArrayCopy(ctx, buf, decoded_len);
|
||||
js_free(ctx, buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Uint8Array.fromHex(string) */
|
||||
static JSValue js_uint8array_from_hex(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
const char *str;
|
||||
size_t str_len, read_pos, decoded_len, out_cap;
|
||||
int err;
|
||||
uint8_t *buf;
|
||||
JSValue result;
|
||||
|
||||
if (!JS_IsString(argv[0]))
|
||||
return JS_ThrowTypeError(ctx, "expected string");
|
||||
|
||||
str = JS_ToCStringLen(ctx, &str_len, argv[0]);
|
||||
if (!str)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
out_cap = str_len / 2 + 1;
|
||||
buf = js_malloc(ctx, out_cap);
|
||||
if (!buf) {
|
||||
JS_FreeCString(ctx, str);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
decoded_len = u8a_hex_decode(str, str_len, buf, out_cap, &read_pos, &err);
|
||||
JS_FreeCString(ctx, str);
|
||||
|
||||
if (err) {
|
||||
js_free(ctx, buf);
|
||||
return JS_ThrowSyntaxError(ctx, "invalid hex string");
|
||||
}
|
||||
|
||||
/* XXX: could avoid the copy */
|
||||
result = JS_NewUint8ArrayCopy(ctx, buf, decoded_len);
|
||||
js_free(ctx, buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return a { read, written } result object */
|
||||
static JSValue js_make_read_written(JSContext *ctx, size_t read, size_t written)
|
||||
{
|
||||
JSValue obj = JS_NewObject(ctx);
|
||||
if (JS_IsException(obj))
|
||||
return JS_EXCEPTION;
|
||||
if (JS_DefinePropertyValueStr(ctx, obj, "read",
|
||||
JS_NewUint32(ctx, read), JS_PROP_C_W_E) < 0)
|
||||
goto fail;
|
||||
if (JS_DefinePropertyValueStr(ctx, obj, "written",
|
||||
JS_NewUint32(ctx, written), JS_PROP_C_W_E) < 0)
|
||||
goto fail;
|
||||
return obj;
|
||||
fail:
|
||||
JS_FreeValue(ctx, obj);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
/* Uint8Array.prototype.setFromBase64(string[, options]) */
|
||||
static JSValue js_uint8array_set_from_base64(JSContext *ctx,
|
||||
JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
const char *str;
|
||||
size_t str_len, read_pos, decoded_len;
|
||||
JSObject *p;
|
||||
int alphabet, last_chunk, err;
|
||||
JSValueConst options;
|
||||
|
||||
p = check_uint8array(ctx, this_val);
|
||||
if (!p)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
if (!JS_IsString(argv[0]))
|
||||
return JS_ThrowTypeError(ctx, "expected string");
|
||||
|
||||
str = JS_ToCStringLen(ctx, &str_len, argv[0]);
|
||||
if (!str)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
options = argc > 1 ? argv[1] : JS_UNDEFINED;
|
||||
if (check_options_object(ctx, options)) {
|
||||
JS_FreeCString(ctx, str);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
alphabet = parse_alphabet_option(ctx, options);
|
||||
if (alphabet < 0) {
|
||||
JS_FreeCString(ctx, str);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
last_chunk = parse_last_chunk_option(ctx, options);
|
||||
if (last_chunk < 0) {
|
||||
JS_FreeCString(ctx, str);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
if (get_uint8array_bytes(ctx, p, &data, &len)) {
|
||||
JS_FreeCString(ctx, str);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
decoded_len = from_base64(str, str_len, data, len,
|
||||
alphabet == B64_ALPHABET_BASE64URL
|
||||
? b64url_dec : b64_dec,
|
||||
last_chunk, &read_pos, &err);
|
||||
JS_FreeCString(ctx, str);
|
||||
|
||||
if (err)
|
||||
return JS_ThrowSyntaxError(ctx, "invalid base64 string");
|
||||
|
||||
return js_make_read_written(ctx, read_pos, decoded_len);
|
||||
}
|
||||
|
||||
/* Uint8Array.prototype.setFromHex(string) */
|
||||
static JSValue js_uint8array_set_from_hex(JSContext *ctx,
|
||||
JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
const char *str;
|
||||
size_t str_len, read_pos, decoded_len;
|
||||
JSObject *p;
|
||||
int err;
|
||||
|
||||
p = check_uint8array(ctx, this_val);
|
||||
if (!p)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
if (!JS_IsString(argv[0]))
|
||||
return JS_ThrowTypeError(ctx, "expected string");
|
||||
|
||||
str = JS_ToCStringLen(ctx, &str_len, argv[0]);
|
||||
if (!str)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
if (get_uint8array_bytes(ctx, p, &data, &len)) {
|
||||
JS_FreeCString(ctx, str);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
decoded_len = u8a_hex_decode(str, str_len, data, len, &read_pos, &err);
|
||||
JS_FreeCString(ctx, str);
|
||||
|
||||
if (err)
|
||||
return JS_ThrowSyntaxError(ctx, "invalid hex string");
|
||||
|
||||
return js_make_read_written(ctx, read_pos, decoded_len);
|
||||
}
|
||||
|
||||
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 ),
|
||||
@ -58300,6 +59095,20 @@ static const JSCFunctionListEntry js_typed_array_funcs[] = {
|
||||
JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 8, 0),
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_uint8array_proto_funcs[] = {
|
||||
JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 1, 0),
|
||||
JS_CFUNC_DEF("toBase64", 0, js_uint8array_to_base64),
|
||||
JS_CFUNC_DEF("toHex", 0, js_uint8array_to_hex),
|
||||
JS_CFUNC_DEF("setFromBase64", 1, js_uint8array_set_from_base64),
|
||||
JS_CFUNC_DEF("setFromHex", 1, js_uint8array_set_from_hex),
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_uint8array_funcs[] = {
|
||||
JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 1, 0),
|
||||
JS_CFUNC_DEF("fromBase64", 1, js_uint8array_from_base64),
|
||||
JS_CFUNC_DEF("fromHex", 1, js_uint8array_from_hex),
|
||||
};
|
||||
|
||||
static JSValue js_typed_array_base_constructor(JSContext *ctx,
|
||||
JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
@ -59560,17 +60369,25 @@ int JS_AddIntrinsicTypedArrays(JSContext *ctx)
|
||||
for(i = JS_CLASS_UINT8C_ARRAY; i < JS_CLASS_UINT8C_ARRAY + JS_TYPED_ARRAY_COUNT; i++) {
|
||||
char buf[ATOM_GET_STR_BUF_SIZE];
|
||||
const char *name;
|
||||
const JSCFunctionListEntry *bpe;
|
||||
|
||||
name = JS_AtomGetStr(ctx, buf, sizeof(buf),
|
||||
JS_ATOM_Uint8ClampedArray + i - JS_CLASS_UINT8C_ARRAY);
|
||||
bpe = js_typed_array_funcs + typed_array_size_log2(i);
|
||||
obj = JS_NewCConstructor(ctx, i, name,
|
||||
ft.generic, 3, JS_CFUNC_constructor_magic, i,
|
||||
typed_array_base_func,
|
||||
bpe, 1,
|
||||
bpe, 1,
|
||||
0);
|
||||
if (i == JS_CLASS_UINT8_ARRAY) {
|
||||
obj = JS_NewCConstructor(ctx, i, name,
|
||||
ft.generic, 3, JS_CFUNC_constructor_magic, i,
|
||||
typed_array_base_func,
|
||||
js_uint8array_funcs, countof(js_uint8array_funcs),
|
||||
js_uint8array_proto_funcs, countof(js_uint8array_proto_funcs),
|
||||
0);
|
||||
} else {
|
||||
const JSCFunctionListEntry *bpe = js_typed_array_funcs + typed_array_size_log2(i);
|
||||
obj = JS_NewCConstructor(ctx, i, name,
|
||||
ft.generic, 3, JS_CFUNC_constructor_magic, i,
|
||||
typed_array_base_func,
|
||||
bpe, 1,
|
||||
bpe, 1,
|
||||
0);
|
||||
}
|
||||
if (JS_IsException(obj)) {
|
||||
fail:
|
||||
JS_FreeValue(ctx, typed_array_base_func);
|
||||
|
||||
@ -236,7 +236,7 @@ u180e
|
||||
Uint16Array
|
||||
Uint32Array
|
||||
Uint8Array
|
||||
uint8array-base64=skip
|
||||
uint8array-base64
|
||||
Uint8ClampedArray
|
||||
upsert
|
||||
WeakMap
|
||||
|
||||
@ -31,8 +31,6 @@ test262/test/staging/sm/Function/function-name-for.js:13: Test262Error: Expected
|
||||
test262/test/staging/sm/Function/implicit-this-in-parameter-expression.js:12: Test262Error: Expected SameValue(«[object Object]», «undefined») to be true
|
||||
test262/test/staging/sm/Function/invalid-parameter-list.js:13: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/staging/sm/Function/invalid-parameter-list.js:13: strict mode: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/staging/sm/TypedArray/prototype-constructor-identity.js:17: Test262Error: Expected SameValue(«2», «6») to be true
|
||||
test262/test/staging/sm/TypedArray/prototype-constructor-identity.js:17: strict mode: Test262Error: Expected SameValue(«2», «6») to be true
|
||||
test262/test/staging/sm/async-functions/async-contains-unicode-escape.js:11: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/staging/sm/async-functions/async-contains-unicode-escape.js:11: strict mode: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/staging/sm/async-functions/await-in-arrow-parameters.js:10: Test262Error: AsyncFunction:(a = (b = await/r/g) => {}) => {} Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
|
||||
Loading…
Reference in New Issue
Block a user