Drop support for "use strip"

Ref: https://github.com/quickjs-ng/quickjs/issues/20
This commit is contained in:
Saúl Ibarra Corretgé 2023-11-07 00:29:11 +01:00 committed by GitHub
parent 1fb9a5010f
commit e2ae8746ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 114 deletions

View file

@ -286,8 +286,6 @@ ECMA402 (Internationalization API) is not supported.
@itemize @itemize
@item The directive @code{"use strip"} indicates that the debug information (including the source code of the functions) should not be retained to save memory. As @code{"use strict"}, the directive can be global to a script or local to a function.
@item The first line of a script beginning with @code{#!} is ignored. @item The first line of a script beginning with @code{#!} is ignored.
@end itemize @end itemize
@ -305,10 +303,6 @@ standard Javascript. See @code{jsbignum.pdf} for more information.
@item Operator overloading. @item Operator overloading.
@item The directive @code{"use bigint"} enables the bigint mode where integers are @code{BigInt} by default.
@item The directive @code{"use math"} enables the math mode where the division and power operators on integers produce fractions. Floating point literals are @code{BigFloat} by default and integers are @code{BigInt} by default.
@end itemize @end itemize
@section Modules @section Modules

162
quickjs.c
View file

@ -313,7 +313,6 @@ struct JSClass {
}; };
#define JS_MODE_STRICT (1 << 0) #define JS_MODE_STRICT (1 << 0)
#define JS_MODE_STRIP (1 << 1)
typedef struct JSStackFrame { typedef struct JSStackFrame {
struct JSStackFrame *prev_frame; /* NULL if first stack frame */ struct JSStackFrame *prev_frame; /* NULL if first stack frame */
@ -22961,14 +22960,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); put_u32(fd->byte_code.buf + ctor_cpool_offset, ctor_fd->parent_cpool_idx);
/* store the class source code in the constructor. */ /* store the class source code in the constructor. */
if (!(fd->js_mode & JS_MODE_STRIP)) { js_free(ctx, ctor_fd->source);
js_free(ctx, ctor_fd->source); ctor_fd->source_len = s->buf_ptr - class_start_ptr;
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);
ctor_fd->source = js_strndup(ctx, (const char *)class_start_ptr, if (!ctor_fd->source)
ctor_fd->source_len); goto fail;
if (!ctor_fd->source)
goto fail;
}
/* consume the '}' */ /* consume the '}' */
if (next_token(s)) if (next_token(s))
@ -30871,7 +30867,7 @@ static void add_pc2line_info(JSFunctionDef *s, uint32_t pc, int line_num)
static void compute_pc2line_info(JSFunctionDef *s) static void compute_pc2line_info(JSFunctionDef *s)
{ {
if (!(s->js_mode & JS_MODE_STRIP) && s->line_number_slots) { if (s->line_number_slots) {
int last_line_num = s->line_num; int last_line_num = s->line_num;
uint32_t last_pc = 0; uint32_t last_pc = 0;
int i; int i;
@ -31098,7 +31094,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
} }
#endif #endif
/* XXX: Should skip this phase if not generating SHORT_OPCODES */ /* XXX: Should skip this phase if not generating SHORT_OPCODES */
if (s->line_number_size && !(s->js_mode & JS_MODE_STRIP)) { if (s->line_number_size) {
s->line_number_slots = js_mallocz(s->ctx, sizeof(*s->line_number_slots) * s->line_number_size); 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->line_number_slots == NULL)
return -1; return -1;
@ -32243,30 +32239,26 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
} }
#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 4) #if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 4)
if (!(fd->js_mode & JS_MODE_STRIP)) { printf("pass 1\n");
printf("pass 1\n"); dump_byte_code(ctx, 1, fd->byte_code.buf, fd->byte_code.size,
dump_byte_code(ctx, 1, fd->byte_code.buf, fd->byte_code.size, fd->args, fd->arg_count, fd->vars, fd->var_count,
fd->args, fd->arg_count, fd->vars, fd->var_count, fd->closure_var, fd->closure_var_count,
fd->closure_var, fd->closure_var_count, fd->cpool, fd->cpool_count, fd->source, fd->line_num,
fd->cpool, fd->cpool_count, fd->source, fd->line_num, fd->label_slots, NULL);
fd->label_slots, NULL); printf("\n");
printf("\n");
}
#endif #endif
if (resolve_variables(ctx, fd)) if (resolve_variables(ctx, fd))
goto fail; goto fail;
#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 2) #if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 2)
if (!(fd->js_mode & JS_MODE_STRIP)) { printf("pass 2\n");
printf("pass 2\n"); dump_byte_code(ctx, 2, fd->byte_code.buf, fd->byte_code.size,
dump_byte_code(ctx, 2, fd->byte_code.buf, fd->byte_code.size, fd->args, fd->arg_count, fd->vars, fd->var_count,
fd->args, fd->arg_count, fd->vars, fd->var_count, fd->closure_var, fd->closure_var_count,
fd->closure_var, fd->closure_var_count, fd->cpool, fd->cpool_count, fd->source, fd->line_num,
fd->cpool, fd->cpool_count, fd->source, fd->line_num, fd->label_slots, NULL);
fd->label_slots, NULL); printf("\n");
printf("\n");
}
#endif #endif
if (resolve_labels(ctx, fd)) if (resolve_labels(ctx, fd))
@ -32275,17 +32267,11 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
if (compute_stack_size(ctx, fd, &stack_size) < 0) if (compute_stack_size(ctx, fd, &stack_size) < 0)
goto fail; goto fail;
if (fd->js_mode & JS_MODE_STRIP) { function_size = sizeof(*b);
function_size = offsetof(JSFunctionBytecode, debug);
} else {
function_size = sizeof(*b);
}
cpool_offset = function_size; cpool_offset = function_size;
function_size += fd->cpool_count * sizeof(*fd->cpool); function_size += fd->cpool_count * sizeof(*fd->cpool);
vardefs_offset = function_size; 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; closure_var_offset = function_size;
function_size += fd->closure_var_count * sizeof(*fd->closure_var); function_size += fd->closure_var_count * sizeof(*fd->closure_var);
byte_code_offset = function_size; byte_code_offset = function_size;
@ -32304,26 +32290,11 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->func_name = fd->func_name; b->func_name = fd->func_name;
if (fd->arg_count + fd->var_count > 0) { if (fd->arg_count + fd->var_count > 0) {
if ((fd->js_mode & JS_MODE_STRIP) && !fd->has_eval_call) { b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
/* Strip variable definitions not needed at runtime */ if (fd->arg_count > 0)
int i; memcpy(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));
for(i = 0; i < fd->var_count; i++) { if (fd->var_count > 0)
JS_FreeAtom(ctx, fd->vars[i].var_name); memcpy(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));
}
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);
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->var_count = fd->var_count;
b->arg_count = fd->arg_count; b->arg_count = fd->arg_count;
b->defined_arg_count = fd->defined_arg_count; b->defined_arg_count = fd->defined_arg_count;
@ -32340,27 +32311,23 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->stack_size = stack_size; b->stack_size = stack_size;
if (fd->js_mode & JS_MODE_STRIP) { /* XXX: source and pc2line info should be packed at the end of the
JS_FreeAtom(ctx, fd->filename); JSFunctionBytecode structure, avoiding allocation overhead
dbuf_free(&fd->pc2line); // probably useless */
} else { b->has_debug = 1;
/* XXX: source and pc2line info should be packed at the end of the b->debug.filename = fd->filename;
JSFunctionBytecode structure, avoiding allocation overhead b->debug.line_num = fd->line_num;
*/
b->has_debug = 1; //DynBuf pc2line;
b->debug.filename = fd->filename; //compute_pc2line_info(fd, &pc2line);
b->debug.line_num = fd->line_num; //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;
//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;
}
if (fd->scopes != fd->def_scope_array) if (fd->scopes != fd->def_scope_array)
js_free(ctx, fd->scopes); js_free(ctx, fd->scopes);
@ -32389,9 +32356,7 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 1) #if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 1)
if (!(fd->js_mode & JS_MODE_STRIP)) { js_dump_function_bytecode(ctx, b);
js_dump_function_bytecode(ctx, b);
}
#endif #endif
if (fd->parent) { if (fd->parent) {
@ -32531,11 +32496,6 @@ static __exception int js_parse_directives(JSParseState *s)
s->cur_func->has_use_strict = TRUE; s->cur_func->has_use_strict = TRUE;
s->cur_func->js_mode |= JS_MODE_STRICT; 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;
}
#endif
} }
return js_parse_seek_token(s, &pos); return js_parse_seek_token(s, &pos);
} }
@ -33009,15 +32969,14 @@ static __exception int js_parse_function_decl2(JSParseState *s,
else else
emit_op(s, OP_return); emit_op(s, OP_return);
if (!(fd->js_mode & JS_MODE_STRIP)) { /* save the function source code */
/* save the function source code */ /* the end of the function source code is after the last
/* the end of the function source code is after the last token of the function source stored into s->last_ptr */
token of the function source stored into s->last_ptr */ fd->source_len = s->last_ptr - ptr;
fd->source_len = s->last_ptr - ptr; fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len);
fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len); if (!fd->source)
if (!fd->source) goto fail;
goto fail;
}
goto done; goto done;
} }
} }
@ -33036,13 +32995,12 @@ static __exception int js_parse_function_decl2(JSParseState *s,
if (js_parse_source_element(s)) if (js_parse_source_element(s))
goto fail; goto fail;
} }
if (!(fd->js_mode & JS_MODE_STRIP)) {
/* save the function source code */ /* save the function source code */
fd->source_len = s->buf_ptr - ptr; fd->source_len = s->buf_ptr - ptr;
fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len); fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len);
if (!fd->source) if (!fd->source)
goto fail; goto fail;
}
if (next_token(s)) { if (next_token(s)) {
/* consume the '}' */ /* consume the '}' */
@ -33331,8 +33289,6 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
js_mode = 0; js_mode = 0;
if (flags & JS_EVAL_FLAG_STRICT) if (flags & JS_EVAL_FLAG_STRICT)
js_mode |= JS_MODE_STRICT; js_mode |= JS_MODE_STRICT;
if (flags & JS_EVAL_FLAG_STRIP)
js_mode |= JS_MODE_STRIP;
if (eval_type == JS_EVAL_TYPE_MODULE) { if (eval_type == JS_EVAL_TYPE_MODULE) {
JSAtom module_name = JS_NewAtom(ctx, filename); JSAtom module_name = JS_NewAtom(ctx, filename);
if (module_name == JS_ATOM_NULL) if (module_name == JS_ATOM_NULL)

View file

@ -300,7 +300,7 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
#define JS_EVAL_TYPE_MASK (3 << 0) #define JS_EVAL_TYPE_MASK (3 << 0)
#define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */ #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 /* 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 JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed
with JS_EvalFunction(). */ with JS_EvalFunction(). */

View file

@ -22,8 +22,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
"use strip";
import * as std from "std"; import * as std from "std";
import * as os from "os"; import * as os from "os";

View file

@ -1550,8 +1550,7 @@ int run_test_buf(const char *filename, char *harness, namelist_t *ip,
add_helpers(ctx); add_helpers(ctx);
for (i = 0; i < ip->count; i++) { for (i = 0; i < ip->count; i++) {
if (eval_file(ctx, harness, ip->array[i], if (eval_file(ctx, harness, ip->array[i], JS_EVAL_TYPE_GLOBAL)) {
JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAG_STRIP)) {
fatal(1, "error including %s for %s", ip->array[i], filename); fatal(1, "error including %s for %s", ip->array[i], filename);
} }
} }