static nxt_int_t njs_parser_boolean_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, const void *data) { njs_parser_node_t *node; node = njs_parser_node_alloc(vm); if (nxt_fast_path(node != NULL)) { node->token = token; node->u.value = (parser->lexer->number == 0.0) ? njs_value_false: njs_value_true; parser->node = node; return NXT_OK; } return NXT_ERROR; }
njs_value_t * njs_array_add(njs_vm_t *vm, njs_value_t *value, u_char *start, size_t size) { njs_ret_t ret; njs_array_t *array; if (value != NULL) { array = value->data.u.array; if (array->size == array->length) { ret = njs_array_realloc(vm, array, 0, array->size + 1); if (nxt_slow_path(ret != NXT_OK)) { return NULL; } } } else { value = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t), sizeof(njs_value_t)); if (nxt_slow_path(value == NULL)) { return NULL; } array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE); if (nxt_slow_path(array == NULL)) { return NULL; } value->data.u.array = array; value->type = NJS_ARRAY; value->data.truth = 1; } ret = njs_string_create(vm, &array->start[array->length++], start, size, 0); if (nxt_fast_path(ret == NXT_OK)) { return value; } return NULL; }
static nxt_int_t njs_parser_node(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, const void *data) { njs_parser_node_t *node; token = (njs_token_t) data; node = njs_parser_node_alloc(vm); if (nxt_fast_path(node != NULL)) { node->token = token; node->left = parser->node; parser->node = node; return NXT_OK; } return NXT_ERROR; }
nxt_noinline njs_object_t * njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value, nxt_uint_t type) { nxt_uint_t index; njs_object_value_t *ov; ov = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_object_value_t)); if (nxt_fast_path(ov != NULL)) { nxt_lvlhsh_init(&ov->object.hash); nxt_lvlhsh_init(&ov->object.shared_hash); index = njs_primitive_prototype_index(type); ov->object.__proto__ = &vm->prototypes[index]; ov->value = *value; } return &ov->object; }
static int njs_regexp_pattern_compile(njs_vm_t *vm, nxt_regex_t *regex, u_char *source, int options) { nxt_int_t ret; nxt_trace_handler_t handler; handler = vm->trace.handler; vm->trace.handler = njs_regexp_compile_trace_handler; /* Zero length means a zero-terminated string. */ ret = nxt_regex_compile(regex, source, 0, options, vm->regex_context); vm->trace.handler = handler; if (nxt_fast_path(ret == NXT_OK)) { return regex->ncaptures; } return ret; }
static nxt_int_t njs_parser_number_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, const void *data) { double num; njs_parser_node_t *node; node = njs_parser_node_alloc(vm); if (nxt_fast_path(node != NULL)) { node->token = token; num = parser->lexer->number; node->u.value.data.u.number = num; node->u.value.type = NJS_NUMBER; node->u.value.data.truth = njs_is_number_true(num); parser->node = node; return NXT_OK; } return NXT_ERROR; }
static nxt_int_t njs_parser_unary_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, const void *data) { njs_parser_node_t *node; njs_vmcode_operation_t operation; operation = (njs_vmcode_operation_t) data; node = njs_parser_node_alloc(vm); if (nxt_fast_path(node != NULL)) { node->token = token; node->u.operation = operation; parser->node = node; parser->code_size += sizeof(njs_vmcode_2addr_t); return NXT_OK; } return NXT_ERROR; }
static nxt_int_t nxt_lvlhsh_new_bucket(nxt_lvlhsh_query_t *lhq, void **slot) { uint32_t *bucket; bucket = lhq->proto->alloc(lhq->pool, nxt_lvlhsh_bucket_size(lhq->proto), lhq->proto->nalloc); if (nxt_fast_path(bucket != NULL)) { nxt_lvlhsh_set_entry_value(bucket, lhq->value); nxt_lvlhsh_set_entry_key(bucket, lhq->key_hash); *nxt_lvlhsh_next_bucket(lhq->proto, bucket) = NULL; nxt_lvlhsh_store_bucket(*slot, bucket); return NXT_OK; } return NXT_ERROR; }
njs_object_prop_t * njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name) { njs_object_prop_t *prop; prop = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t), sizeof(njs_object_prop_t)); if (nxt_fast_path(prop != NULL)) { prop->value = njs_value_void; /* GC: retain. */ prop->name = *name; prop->type = NJS_PROPERTY; prop->enumerable = 1; prop->writable = 1; prop->configurable = 1; } return prop; }
static nxt_int_t njs_parser_condition_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, const void *data) { njs_parser_node_t *node; node = njs_parser_node_alloc(vm); if (nxt_fast_path(node != NULL)) { node->token = token; node->left = parser->node; parser->node = node; parser->code_size += sizeof(njs_vmcode_cond_jump_t) + sizeof(njs_vmcode_move_t) + sizeof(njs_vmcode_jump_t) + sizeof(njs_vmcode_move_t); parser->branch = 1; return NXT_OK; } return NXT_ERROR; }
static nxt_int_t njs_parser_string_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, const void *data) { nxt_int_t ret; njs_parser_node_t *node; node = njs_parser_node_alloc(vm); if (nxt_fast_path(node != NULL)) { node->token = token; ret = njs_parser_string_create(vm, &node->u.value); if (nxt_slow_path(ret != NXT_OK)) { return NJS_TOKEN_ERROR; } parser->node = node; return NXT_OK; } return NXT_ERROR; }
static njs_ret_t njs_regexp_exec_result(njs_vm_t *vm, njs_regexp_t *regexp, u_char *string, nxt_regex_match_data_t *match_data, nxt_uint_t utf8) { int *captures; u_char *start; int32_t size, length; njs_ret_t ret; nxt_uint_t i, n; njs_array_t *array; njs_object_prop_t *prop; nxt_lvlhsh_query_t lhq; static const njs_value_t njs_string_index = njs_string("index"); static const njs_value_t njs_string_input = njs_string("input"); array = njs_array_alloc(vm, regexp->pattern->ncaptures, 0); if (nxt_slow_path(array == NULL)) { goto fail; } captures = nxt_regex_captures(match_data); for (i = 0; i < regexp->pattern->ncaptures; i++) { n = 2 * i; if (captures[n] != -1) { start = &string[captures[n]]; size = captures[n + 1] - captures[n]; switch (utf8) { case 0: length = 0; break; case 1: length = size; break; default: length = nxt_utf8_length(start, size); break; } ret = njs_regexp_string_create(vm, &array->start[i], start, size, length); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } } else { array->start[i] = njs_value_void; } } prop = njs_object_prop_alloc(vm, &njs_string_index); if (nxt_slow_path(prop == NULL)) { goto fail; } /* TODO: Non UTF-8 position */ njs_number_set(&prop->value, regexp->last_index + captures[0]); if (regexp->pattern->global) { regexp->last_index += captures[1]; } lhq.key_hash = NJS_INDEX_HASH; lhq.key.len = sizeof("index") - 1; lhq.key.data = (u_char *) "index"; lhq.replace = 0; lhq.value = prop; lhq.pool = vm->mem_cache_pool; lhq.proto = &njs_object_hash_proto; ret = nxt_lvlhsh_insert(&array->object.hash, &lhq); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } prop = njs_object_prop_alloc(vm, &njs_string_input); if (nxt_slow_path(prop == NULL)) { goto fail; } njs_string_copy(&prop->value, ®exp->string); lhq.key_hash = NJS_INPUT_HASH; lhq.key.len = sizeof("input") - 1; lhq.key.data = (u_char *) "input"; lhq.value = prop; ret = nxt_lvlhsh_insert(&array->object.hash, &lhq); if (nxt_fast_path(ret == NXT_OK)) { vm->retval.data.u.array = array; vm->retval.type = NJS_ARRAY; vm->retval.data.truth = 1; ret = NXT_OK; goto done; } fail: ret = NXT_ERROR; done: nxt_regex_match_data_free(match_data, vm->regex_context); return ret; }
njs_regexp_pattern_t * njs_regexp_pattern_create(njs_vm_t *vm, u_char *start, size_t length, njs_regexp_flags_t flags) { int options, ret; u_char *p, *end; size_t size; njs_regexp_pattern_t *pattern; size = 1; /* A trailing "/". */ size += ((flags & NJS_REGEXP_GLOBAL) != 0); size += ((flags & NJS_REGEXP_IGNORE_CASE) != 0); size += ((flags & NJS_REGEXP_MULTILINE) != 0); pattern = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_regexp_pattern_t) + 1 + length + size + 1); if (nxt_slow_path(pattern == NULL)) { return NULL; } pattern->flags = size; pattern->next = NULL; p = (u_char *) pattern + sizeof(njs_regexp_pattern_t); pattern->source = p; *p++ = '/'; p = memcpy(p, start, length); p += length; end = p; *p++ = '\0'; pattern->global = ((flags & NJS_REGEXP_GLOBAL) != 0); if (pattern->global) { *p++ = 'g'; } #ifdef PCRE_JAVASCRIPT_COMPAT /* JavaScript compatibility has been introduced in PCRE-7.7. */ options = PCRE_JAVASCRIPT_COMPAT; #else options = 0; #endif pattern->ignore_case = ((flags & NJS_REGEXP_IGNORE_CASE) != 0); if (pattern->ignore_case) { *p++ = 'i'; options |= PCRE_CASELESS; } pattern->multiline = ((flags & NJS_REGEXP_MULTILINE) != 0); if (pattern->multiline) { *p++ = 'm'; options |= PCRE_MULTILINE; } *p++ = '\0'; ret = njs_regexp_pattern_compile(vm, &pattern->regex[0], &pattern->source[1], options); if (nxt_slow_path(ret < 0)) { return NULL; } pattern->ncaptures = ret; ret = njs_regexp_pattern_compile(vm, &pattern->regex[1], &pattern->source[1], options | PCRE_UTF8); if (nxt_fast_path(ret >= 0)) { if (nxt_slow_path((u_int) ret != pattern->ncaptures)) { vm->exception = &njs_exception_internal_error; nxt_mem_cache_free(vm->mem_cache_pool, pattern); return NULL; } } else if (ret != NXT_DECLINED) { nxt_mem_cache_free(vm->mem_cache_pool, pattern); return NULL; } *end = '/'; return pattern; }
static njs_ret_t njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value) { int32_t index; nxt_int_t ret; njs_value_t *constructor; njs_object_t *prototype; njs_object_prop_t *prop; nxt_lvlhsh_query_t lhq; static const njs_value_t constructor_string = njs_string("constructor"); if (njs_is_object(value)) { prototype = value->data.u.object; do { index = prototype - vm->prototypes; if (index >= 0 && index < NJS_PROTOTYPE_MAX) { goto found; } prototype = prototype->__proto__; } while (prototype != NULL); nxt_thread_log_alert("prototype not found"); return NXT_ERROR; } else { index = njs_primitive_prototype_index(value->type); prototype = &vm->prototypes[index]; } found: prop = njs_object_prop_alloc(vm, &constructor_string); if (nxt_slow_path(prop == NULL)) { return NXT_ERROR; } /* GC */ constructor = &vm->scopes[NJS_SCOPE_GLOBAL][index]; prop->value = *constructor; prop->enumerable = 0; lhq.value = prop; lhq.key_hash = NJS_CONSTRUCTOR_HASH; lhq.key.len = sizeof("constructor") - 1; lhq.key.data = (u_char *) "constructor"; lhq.replace = 0; lhq.pool = vm->mem_cache_pool; lhq.proto = &njs_object_hash_proto; ret = nxt_lvlhsh_insert(&prototype->hash, &lhq); if (nxt_fast_path(ret == NXT_OK)) { vm->retval = *constructor; } return ret; }