ref: bb6a85a31c46f82577bacc1cc21d3c3b9df02b82
parent: 32f3e71169acdf4955b859f68c128b2c6c3635f5
author: Tor Andersson <tor.andersson@artifex.com>
date: Thu Jan 5 10:32:17 EST 2023
Issue #171: Compile sparse array initializers correctly. Don't initialize the holes with "undefined". Elided array entries should be skipped altogether.
--- a/astnames.h
+++ b/astnames.h
@@ -5,7 +5,7 @@
"exp_number",
"exp_string",
"exp_regexp",
-"exp_undef",
+"exp_elision",
"exp_null",
"exp_true",
"exp_false",
--- a/jscompile.c
+++ b/jscompile.c
@@ -284,8 +284,12 @@
{
while (list) {
emitline(J, F, list->a);
- cexp(J, F, list->a);
- emit(J, F, OP_INITARRAY);
+ if (list->a->type == EXP_ELISION) {
+ emit(J, F, OP_SKIPARRAY);
+ } else {
+ cexp(J, F, list->a);
+ emit(J, F, OP_INITARRAY);
+ }
list = list->b;
}
}
@@ -580,9 +584,7 @@
emitline(J, F, exp);
emitnumber(J, F, exp->number);
break;
- case EXP_UNDEF:
- emitline(J, F, exp);
- emit(J, F, OP_UNDEF);
+ case EXP_ELISION:
break;
case EXP_NULL:
emitline(J, F, exp);
--- a/jsi.h
+++ b/jsi.h
@@ -578,7 +578,7 @@
EXP_REGEXP,
/* literals */
- EXP_UNDEF, /* for array elisions */
+ EXP_ELISION, /* for array elisions */
EXP_NULL,
EXP_TRUE,
EXP_FALSE,
@@ -743,6 +743,7 @@
OP_IN, /* <name> <obj> -- <exists?> */
+ OP_SKIPARRAY, /* <obj> -- <obj> */
OP_INITARRAY, /* <obj> <val> -- <obj> */
OP_INITPROP, /* <obj> <key> <val> -- <obj> */
OP_INITGETTER, /* <obj> <key> <closure> -- <obj> */
--- a/jsparse.c
+++ b/jsparse.c
@@ -187,7 +187,7 @@
{
int line = J->lexline;
if (J->lookahead == ',')
- return EXP0(UNDEF);
+ return EXP0(ELISION);
return assignment(J, 0);
}
--- a/jsrun.c
+++ b/jsrun.c
@@ -1690,6 +1690,9 @@
js_pushboolean(J, b);
break;
+ case OP_SKIPARRAY:
+ js_setlength(J, -1, js_getlength(J, -1) + 1);
+ break;
case OP_INITARRAY:
js_setindex(J, -2, js_getlength(J, -2));
break;
--- a/opnames.h
+++ b/opnames.h
@@ -25,6 +25,7 @@
"setvar",
"delvar",
"in",
+"skiparray",
"initarray",
"initprop",
"initgetter",
--- a/pp.c
+++ b/pp.c
@@ -209,7 +209,7 @@
case EXP_NUMBER:
case EXP_STRING:
case EXP_REGEXP:
- case EXP_UNDEF:
+ case EXP_ELISION:
case EXP_NULL:
case EXP_TRUE:
case EXP_FALSE:
@@ -415,7 +415,7 @@
case EXP_STRING: pstr(exp->string); break;
case EXP_REGEXP: pregexp(exp->string, exp->number); break;
- case EXP_UNDEF: break;
+ case EXP_ELISION: ps("elision"); break;
case EXP_NULL: ps("null"); break;
case EXP_TRUE: ps("true"); break;
case EXP_FALSE: ps("false"); break;