#include <njs_variable.h>
#include <njs_parser.h>
#include <string.h>
-#include <stdio.h>
static nxt_int_t njs_generator(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *node);
static nxt_int_t njs_generate_regexp(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *node);
-static nxt_int_t njs_generate_delete(njs_vm_t *vm, njs_parser_t *parser,
- njs_parser_node_t *node);
static nxt_int_t njs_generate_test_jump_expression(njs_vm_t *vm,
njs_parser_t *parser, njs_parser_node_t *node);
static nxt_int_t njs_generate_3addr_operation(njs_vm_t *vm,
return njs_generate_test_jump_expression(vm, parser, node);
case NJS_TOKEN_DELETE:
- return njs_generate_delete(vm, parser, node);
-
case NJS_TOKEN_VOID:
case NJS_TOKEN_TYPEOF:
case NJS_TOKEN_UNARY_PLUS:
}
-static nxt_int_t
-njs_generate_delete(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
-{
- double n;
- nxt_int_t ret;
- njs_index_t index;
- njs_parser_node_t *operand;
- njs_vmcode_2addr_t *delete;
-
- operand = node->left;
-
- /*
- * The "delete" operator returns "false" for "undefined", "NaN", and
- * "Infinity" constants but not for values, expressions and "-Infinity".
- */
-
- switch (operand->token) {
-
- case NJS_TOKEN_NAME:
- if (operand->u.variable->state == NJS_VARIABLE_DECLARED) {
- index = njs_value_index(vm, parser, &njs_value_false);
- goto done;
- }
-
- /* A property of the global object. */
-
- njs_generate_code(parser, njs_vmcode_2addr_t, delete);
- delete->code.operation = njs_vmcode_delete;
- delete->code.operands = NJS_VMCODE_2OPERANDS;
- delete->code.retval = NJS_VMCODE_RETVAL;
- delete->dst = njs_generator_node_temp_index_get(parser, node);
- delete->src = operand->u.variable->index;
-
- return NXT_OK;
-
- case NJS_TOKEN_NUMBER:
- n = operand->u.value.data.u.number;
-
- if (!njs_is_nan(n) && !(njs_is_infinity(n) && n > 0.0)) {
- break;
- }
-
- /* Fall through. */
-
- case NJS_TOKEN_UNDEFINED:
- index = njs_value_index(vm, parser, &njs_value_false);
- goto done;
-
- default:
- ret = njs_generator(vm, parser, operand);
- if (nxt_slow_path(ret != NXT_OK)) {
- return ret;
- }
-
- ret = njs_generator_node_index_release(vm, parser, operand);
- if (nxt_slow_path(ret != NXT_OK)) {
- return ret;
- }
-
- break;
- }
-
- index = njs_value_index(vm, parser, &njs_value_true);
-
-done:
-
- node->index = index;
-
- return NXT_OK;
-}
-
-
static nxt_int_t
njs_generate_test_jump_expression(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *node)
return next;
}
- if (token == NJS_TOKEN_TYPEOF
- && parser->node->token == NJS_TOKEN_NAME)
- {
- parser->node->state = NJS_VARIABLE_TYPEOF;
+ if (token == NJS_TOKEN_DELETE) {
- } else if (token == NJS_TOKEN_DELETE
- && parser->node->token == NJS_TOKEN_PROPERTY)
- {
- parser->node->token = NJS_TOKEN_PROPERTY_DELETE;
- parser->node->u.operation = njs_vmcode_property_delete;
- parser->code_size += sizeof(njs_vmcode_3addr_t);
+ switch (parser->node->token) {
- return next;
+ case NJS_TOKEN_PROPERTY:
+ parser->node->token = NJS_TOKEN_PROPERTY_DELETE;
+ parser->node->u.operation = njs_vmcode_property_delete;
+ parser->code_size += sizeof(njs_vmcode_3addr_t);
+
+ return next;
+
+ case NJS_TOKEN_NAME:
+ case NJS_TOKEN_UNDEFINED:
+ nxt_alert(&vm->trace, NXT_LEVEL_ERROR,
+ "SyntaxError: Delete of an unqualified identifier");
+
+ return NJS_TOKEN_ILLEGAL;
+
+ default:
+ break;
+ }
+ }
+
+ if (token == NJS_TOKEN_TYPEOF && parser->node->token == NJS_TOKEN_NAME) {
+ parser->node->state = NJS_VARIABLE_TYPEOF;
}
node = njs_parser_node_alloc(vm);
{
njs_release(vm, value);
- njs_set_invalid(value);
-
vm->retval = njs_value_true;
return sizeof(njs_vmcode_2addr_t);
nxt_string("true") },
{ nxt_string("var a; delete a"),
- nxt_string("false") },
+ nxt_string("SyntaxError: Delete of an unqualified identifier in 1") },
{ nxt_string("delete undefined"),
- nxt_string("false") },
+ nxt_string("SyntaxError: Delete of an unqualified identifier in 1") },
+
+ /* ES5FIX: "SyntaxError". */
{ nxt_string("delete NaN"),
- nxt_string("false") },
+ nxt_string("true") },
+
+ /* ES5FIX: "SyntaxError". */
{ nxt_string("delete Infinity"),
- nxt_string("false") },
+ nxt_string("true") },
{ nxt_string("delete -Infinity"),
nxt_string("true") },
{ nxt_string("delete 1"),
nxt_string("true") },
- { nxt_string("delete (a = 1); a"),
+ { nxt_string("var a; delete (a = 1); a"),
nxt_string("1") },
{ nxt_string("delete a"),
- nxt_string("true") },
+ nxt_string("SyntaxError: Delete of an unqualified identifier in 1") },
{ nxt_string("a = 1; delete a"),
- nxt_string("true") },
+ nxt_string("SyntaxError: Delete of an unqualified identifier in 1") },
- { nxt_string("a = 1; delete a; typeof a"),
- nxt_string("undefined") },
+ { nxt_string("function f(){} delete f"),
+ nxt_string("SyntaxError: Delete of an unqualified identifier in 1") },
{ nxt_string("a = { x:1 }; ('x' in a) +' '+ (1 in a)"),
nxt_string("true false") },
+ { nxt_string("delete --[][1]"),
+ nxt_string("true") },
+
{ nxt_string("a = {}; 1 in a"),
nxt_string("false") },