Skip to content

Commit 1565ca9

Browse files
Support for shorthand object literal notation.
JerryScript-DCO-1.0-Signed-off-by: Anthony Calandra anthony@anthony-calandra.com
1 parent 76ff084 commit 1565ca9

File tree

7 files changed

+156
-8
lines changed

7 files changed

+156
-8
lines changed

jerry-core/config.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@
3737
*/
3838
#ifdef CONFIG_DISABLE_ES2015
3939
# define CONFIG_DISABLE_ES2015_ARROW_FUNCTION
40-
# define CONFIG_DISABLE_ES2015_CLASS
4140
# define CONFIG_DISABLE_ES2015_BUILTIN
41+
# define CONFIG_DISABLE_ES2015_CLASS
4242
# define CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
43+
# define CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION
4344
# define CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS
4445
# define CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
4546
#endif /* CONFIG_DISABLE_ES2015 */

jerry-core/parser/js/js-lexer.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,7 +1326,7 @@ lexer_check_colon (parser_context_t *context_p) /**< context */
13261326
&& context_p->source_p[0] == (uint8_t) LIT_CHAR_COLON);
13271327
} /* lexer_check_colon */
13281328

1329-
#ifndef CONFIG_DISABLE_ES2015_CLASS
1329+
#if !defined (CONFIG_DISABLE_ES2015_CLASS) || !defined (CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION)
13301330
/**
13311331
* Checks whether the next token is a left parenthesis.
13321332
*
@@ -1343,7 +1343,7 @@ lexer_check_left_paren (parser_context_t *context_p) /**< context */
13431343
return (context_p->source_p < context_p->source_end_p
13441344
&& context_p->source_p[0] == (uint8_t) LIT_CHAR_LEFT_PAREN);
13451345
} /* lexer_check_left_paren */
1346-
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
1346+
#endif /* !CONFIG_DISABLE_ES2015_CLASS || !CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION */
13471347

13481348
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
13491349

@@ -2290,8 +2290,17 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
22902290
{
22912291
lexer_skip_spaces (context_p);
22922292

2293-
if (context_p->source_p < context_p->source_end_p
2294-
&& context_p->source_p[0] != LIT_CHAR_COLON)
2293+
#ifndef CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION
2294+
bool not_end_of_literal = (context_p->source_p < context_p->source_end_p
2295+
&& context_p->source_p[0] != LIT_CHAR_COLON
2296+
&& context_p->source_p[0] != LIT_CHAR_RIGHT_BRACE
2297+
&& context_p->source_p[0] != LIT_CHAR_COMMA);
2298+
#else /* CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION */
2299+
bool not_end_of_literal = (context_p->source_p < context_p->source_end_p
2300+
&& context_p->source_p[0] != LIT_CHAR_COLON);
2301+
#endif /* !CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION */
2302+
2303+
if (not_end_of_literal)
22952304
{
22962305
if (lexer_compare_raw_identifier_to_current (context_p, "get", 3))
22972306
{

jerry-core/parser/js/js-parser-expr.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,61 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
666666
literal_index,
667667
PARSER_OBJECT_PROPERTY_VALUE);
668668

669+
#ifndef CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION
670+
if (lexer_check_colon (context_p))
671+
{
672+
/* If there's a colon ahead, then we have { prop: val } */
673+
lexer_next_token (context_p); /* Skip colon. */
674+
lexer_next_token (context_p);
675+
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
676+
677+
if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
678+
{
679+
context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY;
680+
context_p->last_cbc.value = literal_index;
681+
}
682+
else
683+
{
684+
parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, literal_index);
685+
}
686+
}
687+
else if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
688+
{
689+
/* If we have an identifier literal, then we have { prop } or { prop() {...} }
690+
(a.k.a shorthand notation) */
691+
if (lexer_check_left_paren (context_p))
692+
{
693+
parser_flush_cbc (context_p);
694+
uint32_t status_flags = PARSER_IS_FUNCTION | PARSER_IS_FUNC_EXPRESSION | PARSER_IS_CLOSURE;
695+
uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags);
696+
parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, function_literal_index);
697+
lexer_next_token (context_p);
698+
}
699+
else
700+
{
701+
lexer_construct_literal_object (context_p,
702+
&context_p->token.lit_location,
703+
context_p->token.lit_location.type);
704+
lexer_next_token (context_p);
705+
706+
/* We have a literal, but there is ill-formed syntax after it, so just error out. */
707+
if (context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_COMMA)
708+
{
709+
parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED);
710+
}
711+
712+
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
713+
}
714+
715+
context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY;
716+
context_p->last_cbc.value = literal_index;
717+
}
718+
else
719+
{
720+
/* Else, we have something that isn't a valid object literal. */
721+
parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED);
722+
}
723+
#else /* CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION */
669724
lexer_next_token (context_p);
670725
if (context_p->token.type != LEXER_COLON)
671726
{
@@ -684,6 +739,7 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
684739
{
685740
parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, literal_index);
686741
}
742+
#endif /* !CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION */
687743
}
688744

689745
if (context_p->token.type == LEXER_RIGHT_BRACE)

jerry-core/parser/js/js-parser-internal.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,10 @@ void parser_set_continues_to_current_position (parser_context_t *context_p, pars
436436

437437
void lexer_next_token (parser_context_t *context_p);
438438
bool lexer_check_colon (parser_context_t *context_p);
439-
#ifndef CONFIG_DISABLE_ES2015_CLASS
439+
#if !defined (CONFIG_DISABLE_ES2015_CLASS) || !defined (CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION)
440440
bool lexer_check_left_paren (parser_context_t *context_p);
441+
#endif /* !CONFIG_DISABLE_ES2015_CLASS || !CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION */
442+
#ifndef CONFIG_DISABLE_ES2015_CLASS
441443
void lexer_skip_empty_statements (parser_context_t *context_p);
442444
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
443445
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION

jerry-core/parser/js/js-parser-scanner.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,16 @@ parser_scan_until (parser_context_t *context_p, /**< context */
841841
}
842842

843843
lexer_next_token (context_p);
844-
if (context_p->token.type != LEXER_COLON)
844+
845+
#ifndef CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION
846+
bool not_end_of_property_name = (context_p->token.type != LEXER_COLON
847+
&& context_p->token.type != LEXER_RIGHT_BRACE
848+
&& context_p->token.type != LEXER_COMMA);
849+
#else /* CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION */
850+
bool not_end_of_property_name = context_p->token.type != LEXER_COLON;
851+
#endif /* !CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION */
852+
853+
if (not_end_of_property_name)
845854
{
846855
parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED);
847856
}

jerry-core/profiles/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,7 @@ In JerryScript all of the features are enabled by default, so an empty profile f
9393
Disable the [template strings](http://www.ecma-international.org/ecma-262/6.0/#sec-static-semantics-templatestrings).
9494
* `CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN`:
9595
Disable the [ArrayBuffer](http://www.ecma-international.org/ecma-262/6.0/#sec-arraybuffer-objects) and [TypedArray](http://www.ecma-international.org/ecma-262/6.0/#sec-typedarray-objects) built-ins.
96+
* `CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION`:
97+
Disable the [object literal shorthand notation](https://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer).
9698
* `CONFIG_DISABLE_ES2015`: Disable all of the implemented [ECMAScript2015 features](http://www.ecma-international.org/ecma-262/6.0/).
97-
(equivalent to `CONFIG_DISABLE_ES2015_ARROW_FUNCTION`, `CONFIG_DISABLE_ES2015_BUILTIN`, `CONFIG_DISABLE_ES2015_CLASS`, `CONFIG_DISABLE_ES2015_PROMISE_BUILTIN`, `CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS`, and `CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN`).
99+
(equivalent to `CONFIG_DISABLE_ES2015_ARROW_FUNCTION`, `CONFIG_DISABLE_ES2015_BUILTIN`, `CONFIG_DISABLE_ES2015_CLASS`, `CONFIG_DISABLE_ES2015_PROMISE_BUILTIN`, `CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS`, `CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN`, and `CONFIG_DISABLE_ES2015_SHORTHAND_OBJ_LITERAL_NOTATION`).
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright JS Foundation and other contributors, http://js.foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
var x = 1, y = 2, z = 3;
16+
var obj = { x, y, z: { z } };
17+
assert(obj.x === 1);
18+
assert(obj.y === 2);
19+
assert(obj.z.z === 3);
20+
21+
try {
22+
var a = { get, set };
23+
assert(false);
24+
} catch (e) {
25+
assert(e instanceof ReferenceError);
26+
}
27+
28+
function checkReservedAsVars() {
29+
var get = 1, set = 2;
30+
var a = { get, set };
31+
assert(a.get + a.set === 3);
32+
}
33+
checkReservedAsVars();
34+
35+
var one = 1;
36+
assert({ one, one }.one === 1);
37+
assert({ one: 0, one }.one === 1);
38+
assert({ one, one: 0 }.one === 0);
39+
40+
var obj2 = { one };
41+
assert({ obj2 }.obj2.one === 1);
42+
43+
try {
44+
var a = { true, false, null };
45+
assert(false);
46+
} catch (e) {
47+
// FIXME
48+
/*assert(e instanceof SyntaxError);*/
49+
}
50+
51+
var obj3 = { f() { return 1; } };
52+
assert(obj3.f() === 1);
53+
54+
var obj4 = { one, one() { return one; } };
55+
assert(typeof obj4.one === 'function');
56+
assert(obj4.one() === 1);
57+
58+
var obj5 = { x: 123, getX() { return this.x; } };
59+
assert(obj5.getX() === 123);
60+
61+
var obj6 = {
62+
if() { return 0; }, else() { return 1; }, try() { return 2; }, catch() { return 3; },
63+
finally() { return 4; }, let() { return 5; }, true() { return 6; }, false() { return 7; },
64+
null() { return 8; }
65+
};
66+
assert(
67+
obj6.if() + obj6.else() + obj6.try() + obj6.catch() + obj6.finally() + obj6.let() +
68+
obj6.true() + obj6.false() + obj6.null() === 36
69+
);

0 commit comments

Comments
 (0)