Ejemplo n.º 1
0
static njs_vm_t *
ngx_http_js_compile(ngx_conf_t *cf, ngx_str_t *script)
{
    u_char               *start, *end;
    nxt_int_t              rc;
    nxt_str_t              s;
    njs_vm_t             *vm;
    nxt_lvlhsh_t           externals;
    njs_vm_shared_t      *shared;
    nxt_mem_cache_pool_t  *mcp;

    mcp = ngx_http_js_create_mem_cache_pool();
    if (mcp == NULL) {
        return NULL;
    }

    shared = NULL;

    nxt_lvlhsh_init(&externals);

    if (njs_add_external(&externals, mcp, 0, ngx_http_js_externals,
                         nxt_nitems(ngx_http_js_externals))
        != NJS_OK)
    {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "could not add js externals");
        return NULL;
    }

    vm = njs_vm_create(mcp, &shared, &externals);
    if (vm == NULL) {
        return NULL;
    }

    start = script->data;
    end = start + script->len;

    rc = njs_vm_compile(vm, &start, end);

    if (rc != NJS_OK) {
        njs_vm_exception(vm, &s);

        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "js compilation error: \"%*s\"", s.len, s.data);
        return NULL;
    }

    if (start != end) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "extra characters in js script: \"%*s\"",
                           end - start, start);
        return NULL;
    }

    return vm;
}
Ejemplo n.º 2
0
nxt_int_t
njs_array_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
{
    return njs_object_hash_create(vm, hash, njs_array_prototype_properties,
                                  nxt_nitems(njs_array_prototype_properties));
}
Ejemplo n.º 3
0
static void
njs_disassemble(u_char *start, u_char *end)
{
    u_char                     *p;
    nxt_str_t                  *name;
    nxt_uint_t                 n;
    const char                 *sign;
    njs_code_name_t            *code_name;
    njs_vmcode_jump_t          *jump;
    njs_vmcode_1addr_t         *code1;
    njs_vmcode_2addr_t         *code2;
    njs_vmcode_3addr_t         *code3;
    njs_vmcode_array_t         *array;
    njs_vmcode_catch_t         *catch;
    njs_vmcode_try_end_t       *try_end;
    njs_vmcode_try_start_t     *try_start;
    njs_vmcode_operation_t     operation;
    njs_vmcode_cond_jump_t     *cond_jump;
    njs_vmcode_test_jump_t     *test_jump;
    njs_vmcode_prop_next_t     *prop_next;
    njs_vmcode_equal_jump_t    *equal;
    njs_vmcode_prop_foreach_t  *prop_foreach;
    njs_vmcode_method_frame_t  *method;

    p = start;

    /*
     * On some 32-bit platform uintptr_t is int and compilers warn
     * about %l format modifier.  size_t has the size as pointer so
     * there is no run-time overhead.
     */

    while (p < end) {
        operation = *(njs_vmcode_operation_t *) p;

        if (operation == njs_vmcode_array) {
            array = (njs_vmcode_array_t *) p;
            p += sizeof(njs_vmcode_array_t);

            printf("ARRAY             %04zX %zd\n",
                   (size_t) array->retval, (size_t) array->length);

            continue;
        }

        if (operation == njs_vmcode_if_true_jump) {
            cond_jump = (njs_vmcode_cond_jump_t *) p;
            p += sizeof(njs_vmcode_cond_jump_t);
            sign = (cond_jump->offset >= 0) ? "+" : "";

            printf("JUMP IF TRUE      %04zX %s%zd\n",
                   (size_t) cond_jump->cond, sign, (size_t) cond_jump->offset);

            continue;
        }

        if (operation == njs_vmcode_if_false_jump) {
            cond_jump = (njs_vmcode_cond_jump_t *) p;
            p += sizeof(njs_vmcode_cond_jump_t);
            sign = (cond_jump->offset >= 0) ? "+" : "";

            printf("JUMP IF FALSE     %04zX %s%zd\n",
                   (size_t) cond_jump->cond, sign, (size_t) cond_jump->offset);

            continue;
        }

        if (operation == njs_vmcode_jump) {
            jump = (njs_vmcode_jump_t *) p;
            p += sizeof(njs_vmcode_jump_t);
            sign = (jump->offset >= 0) ? "+" : "";

            printf("JUMP              %s%zd\n", sign, (size_t) jump->offset);

            continue;
        }

        if (operation == njs_vmcode_if_equal_jump) {
            equal = (njs_vmcode_equal_jump_t *) p;
            p += sizeof(njs_vmcode_equal_jump_t);

            printf("JUMP IF EQUAL     %04zX %04zX +%zd\n",
                   (size_t) equal->value1, (size_t) equal->value2,
                   (size_t) equal->offset);

            continue;
        }

        if (operation == njs_vmcode_test_if_true) {
            test_jump = (njs_vmcode_test_jump_t *) p;
            p += sizeof(njs_vmcode_test_jump_t);

            printf("TEST IF TRUE      %04zX %04zX +%zd\n",
                   (size_t) test_jump->retval, (size_t) test_jump->value,
                   (size_t) test_jump->offset);

            continue;
        }

        if (operation == njs_vmcode_test_if_false) {
            test_jump = (njs_vmcode_test_jump_t *) p;
            p += sizeof(njs_vmcode_test_jump_t);

            printf("TEST IF FALSE     %04zX %04zX +%zd\n",
                   (size_t) test_jump->retval, (size_t) test_jump->value,
                   (size_t) test_jump->offset);

            continue;
        }

        if (operation == njs_vmcode_method_frame) {
            method = (njs_vmcode_method_frame_t *) p;
            p += sizeof(njs_vmcode_method_frame_t);

            printf("METHOD FRAME      %04zX %04zX %d\n",
                   (size_t) method->object, (size_t) method->method,
                   method->code.nargs);

            continue;
        }

        if (operation == njs_vmcode_property_foreach) {
            prop_foreach = (njs_vmcode_prop_foreach_t *) p;
            p += sizeof(njs_vmcode_prop_foreach_t);

            printf("PROPERTY FOREACH  %04zX %04zX +%zd\n",
                   (size_t) prop_foreach->next, (size_t) prop_foreach->object,
                   (size_t) prop_foreach->offset);

            continue;
        }

        if (operation == njs_vmcode_property_next) {
            prop_next = (njs_vmcode_prop_next_t *) p;
            p += sizeof(njs_vmcode_prop_next_t);

            printf("PROPERTY NEXT     %04zX %04zX %04zX %zd\n",
                   (size_t) prop_next->retval, (size_t) prop_next->object,
                   (size_t) prop_next->next, (size_t) prop_next->offset);

            continue;
        }

        if (operation == njs_vmcode_try_start) {
            try_start = (njs_vmcode_try_start_t *) p;
            p += sizeof(njs_vmcode_try_start_t);

            printf("TRY START         %04zX +%zd\n",
                   (size_t) try_start->value, (size_t) try_start->offset);

            continue;
        }

        if (operation == njs_vmcode_catch) {
            catch = (njs_vmcode_catch_t *) p;
            p += sizeof(njs_vmcode_catch_t);

            printf("CATCH             %04zX +%zd\n",
                   (size_t) catch->exception, (size_t) catch->offset);

            continue;
        }

        if (operation == njs_vmcode_try_end) {
            try_end = (njs_vmcode_try_end_t *) p;
            p += sizeof(njs_vmcode_try_end_t);

            printf("TRY END           +%zd\n", (size_t) try_end->offset);

            continue;
        }

        code_name = code_names;
        n = nxt_nitems(code_names);

        do {
             if (operation == code_name->operation) {
                 name = &code_name->name;

                 if (code_name->size == sizeof(njs_vmcode_3addr_t)) {
                     code3 = (njs_vmcode_3addr_t *) p;

                     printf("%*s  %04zX %04zX %04zX\n",
                            (int) name->len, name->data, (size_t) code3->dst,
                            (size_t) code3->src1, (size_t) code3->src2);

                 } else if (code_name->size == sizeof(njs_vmcode_2addr_t)) {
                     code2 = (njs_vmcode_2addr_t *) p;

                     printf("%*s  %04zX %04zX\n",
                            (int) name->len, name->data,
                            (size_t) code2->dst, (size_t) code2->src);

                 } else if (code_name->size == sizeof(njs_vmcode_1addr_t)) {
                     code1 = (njs_vmcode_1addr_t *) p;

                     printf("%*s  %04zX\n",
                            (int) name->len, name->data,
                            (size_t) code1->index);
                 }

                 p += code_name->size;

                 goto next;
             }

             code_name++;
             n--;

        } while (n != 0);

        p += sizeof(njs_vmcode_operation_t);

        printf("UNKNOWN           %04zX\n", (size_t) (uintptr_t) operation);

    next:

        continue;
    }
Ejemplo n.º 4
0
        .name = njs_string("length"),
        .value = njs_value(NJS_NUMBER, 1, 2.0),
    },

    /* RegExp.prototype. */
    {
        .type = NJS_NATIVE_GETTER,
        .name = njs_string("prototype"),
        .value = njs_native_getter(njs_object_prototype_create),
    },
};


const njs_object_init_t  njs_regexp_constructor_init = {
    njs_regexp_constructor_properties,
    nxt_nitems(njs_regexp_constructor_properties),
};


static const njs_object_prop_t  njs_regexp_prototype_properties[] =
{
    {
        .type = NJS_NATIVE_GETTER,
        .name = njs_string("lastIndex"),
        .value = njs_native_getter(njs_regexp_prototype_last_index),
    },

    {
        .type = NJS_NATIVE_GETTER,
        .name = njs_string("global"),
        .value = njs_native_getter(njs_regexp_prototype_global),
Ejemplo n.º 5
0
static char *
ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_js_loc_conf_t *jlcf = conf;

    size_t                 size;
    u_char                *start, *end;
    ssize_t                n;
    ngx_fd_t               fd;
    ngx_str_t             *value, file;
    nxt_int_t              rc;
    nxt_str_t              text, ext, *export;
    nxt_lvlhsh_t           externals;
    ngx_file_info_t        fi;
    njs_vm_shared_t       *shared;
    ngx_pool_cleanup_t    *cln;
    nxt_mem_cache_pool_t  *mcp;

    if (jlcf->vm) {
        return "is duplicate";
    }

    value = cf->args->elts;
    file = value[1];

    if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    fd = ngx_open_file(file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
    if (fd == NGX_INVALID_FILE) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
                           ngx_open_file_n " \"%s\" failed", file.data);
        return NGX_CONF_ERROR;
    }

    if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
                      ngx_fd_info_n " \"%s\" failed", file.data);
        (void) ngx_close_file(fd);
        return NGX_CONF_ERROR;
    }

    size = ngx_file_size(&fi);

    start = ngx_pnalloc(cf->pool, size);
    if (start == NULL) {
        (void) ngx_close_file(fd);
        return NGX_CONF_ERROR;
    }

    n = ngx_read_fd(fd, start,  size);

    if (n == -1) {
        ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                      ngx_read_fd_n " \"%s\" failed", file.data);

        (void) ngx_close_file(fd);
        return NGX_CONF_ERROR;
    }

    if ((size_t) n != size) {
        ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
                      ngx_read_fd_n " has read only %z of %O from \"%s\"",
                      n, size, file.data);

        (void) ngx_close_file(fd);
        return NGX_CONF_ERROR;
    }

    if (ngx_close_file(fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                      ngx_close_file_n " %s failed", file.data);
    }

    end = start + size;

    mcp = ngx_http_js_create_mem_cache_pool();
    if (mcp == NULL) {
        return NGX_CONF_ERROR;
    }

    cln = ngx_pool_cleanup_add(cf->pool, 0);
    if (cln == NULL) {
        return NULL;
    }

    cln->handler = ngx_http_js_cleanup_mem_cache_pool;
    cln->data = mcp;

    shared = NULL;

    nxt_lvlhsh_init(&externals);

    if (njs_vm_external_add(&externals, mcp, 0, ngx_http_js_externals,
                            nxt_nitems(ngx_http_js_externals))
        != NJS_OK)
    {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "could not add js externals");
        return NGX_CONF_ERROR;
    }

    jlcf->vm = njs_vm_create(mcp, &shared, &externals);
    if (jlcf->vm == NULL) {
        return NGX_CONF_ERROR;
    }

    rc = njs_vm_compile(jlcf->vm, &start, end, NULL, &export);

    if (rc != NJS_OK) {
        njs_vm_exception(jlcf->vm, &text);

        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "%*s, included",
                           text.length, text.start);
        return NGX_CONF_ERROR;
    }

    if (start != end) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "extra characters in js script: \"%*s\", included",
                           end - start, start);
        return NGX_CONF_ERROR;
    }

    ext = nxt_string_value("$r");

    if (njs_vm_external(jlcf->vm, NULL, &ext, &jlcf->args[0]) != NJS_OK) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "js external \"%*s\" not found",
                           ext.length, ext.start);
        return NGX_CONF_ERROR;
    }

    ext = nxt_string_value("response");

    rc = njs_vm_external(jlcf->vm, &jlcf->args[0], &ext, &jlcf->args[1]);
    if (rc != NXT_OK) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "js external \"$r.%*s\" not found",
                           ext.length, ext.start);
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;
}
Ejemplo n.º 6
0
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      ngx_http_js_ext_finish,
      0 },
};


static njs_external_t  ngx_http_js_ext_request[] = {

    { nxt_string("response"),
      NJS_EXTERN_OBJECT,
      ngx_http_js_ext_response,
      nxt_nitems(ngx_http_js_ext_response),
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      0 },

    { nxt_string("log"),
      NJS_EXTERN_METHOD,
      NULL,
      0,
      NULL,
      NULL,
      NULL,
Ejemplo n.º 7
0
    /* Object.prototype. */
    { njs_native_getter(njs_object_prototype_create),
      njs_string("prototype"),
      NJS_NATIVE_GETTER, 0, 0, 0, },

    /* Object.create(). */
    { njs_native_function(njs_object_create, 0),
      njs_string("create"),
      NJS_METHOD, 0, 0, 0, },
};


const njs_object_init_t  njs_object_constructor_init = {
     njs_object_constructor_properties,
     nxt_nitems(njs_object_constructor_properties),
};


static njs_ret_t
njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
{
    njs_object_t  *proto;

    proto = value->data.u.object->__proto__;

    if (nxt_fast_path(proto != NULL)) {
        vm->retval.data.u.object = proto;
        vm->retval.type = NJS_OBJECT;
        vm->retval.data.truth = 1;