[njs] encodeURI() and encodeURIComponent() functions.
Igor Sysoev
igor at sysoev.ru
Wed Aug 31 12:54:31 UTC 2016
details: http://hg.nginx.org/njs/rev/d63ecb57f164
branches:
changeset: 160:d63ecb57f164
user: Igor Sysoev <igor at sysoev.ru>
date: Tue Aug 30 12:02:31 2016 +0300
description:
encodeURI() and encodeURIComponent() functions.
diffstat:
njs/njs_builtin.c | 16 +++--
njs/njs_generator.c | 2 +
njs/njs_lexer_keyword.c | 2 +
njs/njs_parser.c | 2 +
njs/njs_parser.h | 2 +
njs/njs_string.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++
njs/njs_string.h | 4 +
njs/njs_vm.h | 20 +++---
njs/test/njs_unit_test.c | 12 ++++
9 files changed, 178 insertions(+), 15 deletions(-)
diffs (309 lines):
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_builtin.c
--- a/njs/njs_builtin.c Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_builtin.c Tue Aug 30 12:02:31 2016 +0300
@@ -82,12 +82,14 @@ njs_builtin_objects_create(njs_vm_t *vm)
};
static const njs_object_init_t *function_init[] = {
- &njs_eval_function_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
+ &njs_eval_function_init, /* eval */
+ NULL, /* toString */
+ NULL, /* isNaN */
+ NULL, /* isFinite */
+ NULL, /* parseInt */
+ NULL, /* parseFloat */
+ NULL, /* encodeURI */
+ NULL, /* encodeURIComponent */
};
static const njs_function_init_t native_functions[] = {
@@ -99,6 +101,8 @@ njs_builtin_objects_create(njs_vm_t *vm)
{ njs_number_parse_int,
{ NJS_SKIP_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG } },
{ njs_number_parse_float, { NJS_SKIP_ARG, NJS_STRING_ARG } },
+ { njs_string_encode_uri, { NJS_SKIP_ARG, NJS_STRING_ARG } },
+ { njs_string_encode_uri_component, { NJS_SKIP_ARG, NJS_STRING_ARG } },
};
static const njs_object_prop_t null_proto_property = {
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_generator.c
--- a/njs/njs_generator.c Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_generator.c Tue Aug 30 12:02:31 2016 +0300
@@ -300,6 +300,8 @@ njs_generator(njs_vm_t *vm, njs_parser_t
case NJS_TOKEN_IS_FINITE:
case NJS_TOKEN_PARSE_INT:
case NJS_TOKEN_PARSE_FLOAT:
+ case NJS_TOKEN_ENCODE_URI:
+ case NJS_TOKEN_ENCODE_URI_COMPONENT:
return njs_generate_builtin_object(vm, parser, node);
case NJS_TOKEN_FUNCTION:
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_lexer_keyword.c
--- a/njs/njs_lexer_keyword.c Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_lexer_keyword.c Tue Aug 30 12:02:31 2016 +0300
@@ -93,6 +93,8 @@ static const njs_keyword_t njs_keywords
{ nxt_string("isFinite"), NJS_TOKEN_IS_FINITE, 0 },
{ nxt_string("parseInt"), NJS_TOKEN_PARSE_INT, 0 },
{ nxt_string("parseFloat"), NJS_TOKEN_PARSE_FLOAT, 0 },
+ { nxt_string("encodeURI"), NJS_TOKEN_ENCODE_URI, 0 },
+ { nxt_string("encodeURIComponent"), NJS_TOKEN_ENCODE_URI_COMPONENT, 0 },
/* Reserved words. */
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_parser.c
--- a/njs/njs_parser.c Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_parser.c Tue Aug 30 12:02:31 2016 +0300
@@ -1671,6 +1671,8 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
case NJS_TOKEN_IS_FINITE:
case NJS_TOKEN_PARSE_INT:
case NJS_TOKEN_PARSE_FLOAT:
+ case NJS_TOKEN_ENCODE_URI:
+ case NJS_TOKEN_ENCODE_URI_COMPONENT:
return njs_parser_builtin_function(vm, parser, node);
default:
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_parser.h
--- a/njs/njs_parser.h Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_parser.h Tue Aug 30 12:02:31 2016 +0300
@@ -181,6 +181,8 @@ typedef enum {
NJS_TOKEN_IS_FINITE,
NJS_TOKEN_PARSE_INT,
NJS_TOKEN_PARSE_FLOAT,
+ NJS_TOKEN_ENCODE_URI,
+ NJS_TOKEN_ENCODE_URI_COMPONENT,
NJS_TOKEN_RESERVED,
} njs_token_t;
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_string.c
--- a/njs/njs_string.c Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_string.c Tue Aug 30 12:02:31 2016 +0300
@@ -45,6 +45,8 @@ static njs_ret_t njs_string_match_multip
njs_regexp_pattern_t *pattern);
static njs_ret_t njs_string_split_part_add(njs_vm_t *vm, njs_array_t *array,
u_char *start, size_t size, nxt_uint_t utf8);
+static njs_ret_t njs_string_encode(njs_vm_t *vm, njs_value_t *value,
+ const uint32_t *escape);
njs_ret_t
@@ -2105,6 +2107,137 @@ const njs_object_init_t njs_string_prot
};
+/*
+ * encodeURI(string)
+ */
+
+njs_ret_t
+njs_string_encode_uri(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ static const uint32_t escape[] = {
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+
+ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
+ 0x50000025, /* 0101 0000 0000 0000 0000 0000 0010 0101 */
+
+ /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
+ 0x78000000, /* 0111 1000 0000 0000 0000 0000 0000 0000 */
+
+ /* ~}| {zyx wvut srqp onml kjih gfed cba` */
+ 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
+
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+ };
+
+ if (nargs > 1) {
+ return njs_string_encode(vm, &args[1], escape);
+ }
+
+ vm->retval = njs_string_void;
+
+ return NXT_OK;
+}
+
+
+/*
+ * encodeURIComponent(string)
+ */
+
+njs_ret_t
+njs_string_encode_uri_component(njs_vm_t *vm, njs_value_t *args,
+ nxt_uint_t nargs, njs_index_t unused)
+{
+ static const uint32_t escape[] = {
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+
+ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
+ 0xfc00987d, /* 1111 1100 0000 0000 1001 1000 0111 1101 */
+
+ /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
+ 0x78000001, /* 0111 1000 0000 0000 0000 0000 0000 0001 */
+
+ /* ~}| {zyx wvut srqp onml kjih gfed cba` */
+ 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
+
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+ };
+
+ if (nargs > 1) {
+ return njs_string_encode(vm, &args[1], escape);
+ }
+
+ vm->retval = njs_string_void;
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_string_encode(njs_vm_t *vm, njs_value_t *value, const uint32_t *escape)
+{
+ u_char byte, *src, *dst;
+ size_t n, size;
+ njs_string_prop_t string;
+ static const u_char hex[16] = "0123456789ABCDEF";
+
+ nxt_prefetch(escape);
+
+ (void) njs_string_prop(&string, value);
+
+ src = string.start;
+ n = 0;
+
+ for (size = string.size; size != 0; size--) {
+ byte = *src++;
+
+ if ((escape[byte >> 5] & ((uint32_t) 1 << (byte & 0x1f))) != 0) {
+ n += 2;
+ }
+ }
+
+ if (n == 0) {
+ /* GC: retain src. */
+ vm->retval = *value;
+ return NXT_OK;
+ }
+
+ size = string.size + n;
+
+ dst = njs_string_alloc(vm, &vm->retval, size, size);
+ if (nxt_slow_path(dst == NULL)) {
+ return NXT_ERROR;
+ }
+
+ size = string.size;
+ src = string.start;
+
+ do {
+ byte = *src++;
+
+ if ((escape[byte >> 5] & ((uint32_t) 1 << (byte & 0x1f))) != 0) {
+ *dst++ = '%';
+ *dst++ = hex[byte >> 4];
+ *dst++ = hex[byte & 0xf];
+
+ } else {
+ *dst++ = byte;
+ }
+
+ size--;
+
+ } while (size != 0);
+
+ return NXT_OK;
+}
+
+
static nxt_int_t
njs_values_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
{
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_string.h
--- a/njs/njs_string.h Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_string.h Tue Aug 30 12:02:31 2016 +0300
@@ -104,6 +104,10 @@ nxt_noinline uint32_t njs_string_index(n
njs_ret_t njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst,
const njs_value_t *src);
double njs_string_to_number(njs_value_t *value, nxt_bool_t exact);
+njs_ret_t njs_string_encode_uri(njs_vm_t *vm, njs_value_t *args,
+ nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_string_encode_uri_component(njs_vm_t *vm, njs_value_t *args,
+ nxt_uint_t nargs, njs_index_t unused);
njs_index_t njs_value_index(njs_vm_t *vm, njs_parser_t *parser,
const njs_value_t *src);
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_vm.h
--- a/njs/njs_vm.h Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_vm.h Tue Aug 30 12:02:31 2016 +0300
@@ -668,7 +668,7 @@ typedef enum {
enum njs_prototypes_e {
- NJS_PROTOTYPE_OBJECT = 0,
+ NJS_PROTOTYPE_OBJECT = 0,
NJS_PROTOTYPE_ARRAY,
NJS_PROTOTYPE_BOOLEAN,
NJS_PROTOTYPE_NUMBER,
@@ -698,19 +698,21 @@ enum njs_constructor_e {
enum njs_object_e {
- NJS_OBJECT_MATH = 0,
+ NJS_OBJECT_MATH = 0,
#define NJS_OBJECT_MAX (NJS_OBJECT_MATH + 1)
};
enum njs_function_e {
- NJS_FUNCTION_EVAL = 0,
- NJS_FUNCTION_TO_STRING = 1,
- NJS_FUNCTION_IS_NAN = 2,
- NJS_FUNCTION_IS_FINITE = 3,
- NJS_FUNCTION_PARSE_INT = 4,
- NJS_FUNCTION_PARSE_FLOAT = 5,
-#define NJS_FUNCTION_MAX (NJS_FUNCTION_PARSE_FLOAT + 1)
+ NJS_FUNCTION_EVAL = 0,
+ NJS_FUNCTION_TO_STRING,
+ NJS_FUNCTION_IS_NAN,
+ NJS_FUNCTION_IS_FINITE,
+ NJS_FUNCTION_PARSE_INT,
+ NJS_FUNCTION_PARSE_FLOAT,
+ NJS_FUNCTION_STRING_ENCODE_URI,
+ NJS_FUNCTION_STRING_ENCODE_URI_COMPONENT,
+#define NJS_FUNCTION_MAX (NJS_FUNCTION_STRING_ENCODE_URI_COMPONENT + 1)
};
diff -r 7cce82b6b40b -r d63ecb57f164 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/test/njs_unit_test.c Tue Aug 30 12:02:31 2016 +0300
@@ -3297,6 +3297,18 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("'0123456789'.split('').reverse().join('')"),
nxt_string("9876543210") },
+ { nxt_string("encodeURI()"),
+ nxt_string("undefined")},
+
+ { nxt_string("encodeURI('012абв')"),
+ nxt_string("012%D0%B0%D0%B1%D0%B2")},
+
+ { nxt_string("encodeURI('~}|{`_^]\\\\[@?>=<;:/.-,+*)(\\\'&%$#\"! ')"),
+ nxt_string("~%7D%7C%7B%60_%5E%5D%5C%5B@?%3E=%3C;:/.-,+*)('&%25$#%22!%20")},
+
+ { nxt_string("encodeURIComponent('~}|{`_^]\\\\[@?>=<;:/.-,+*)(\\\'&%$#\"! ')"),
+ nxt_string("~%7D%7C%7B%60_%5E%5D%5C%5B%40%3F%3E%3D%3C%3B%3A%2F.-%2C%2B*)('%26%25%24%23%22!%20")},
+
/* Functions. */
{ nxt_string("return"),
More information about the nginx-devel
mailing list