Skip to content

Commit 048874e

Browse files
committed
Improve location info for syntax errors.
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent badfdf4 commit 048874e

17 files changed

+547
-179
lines changed

docs/02.API-REFERENCE.md

+89-2
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,30 @@ typedef struct
14621462
- [jerry_source_info_enabled_fields_t](#jerry_source_info_enabled_fields_t)
14631463
- [jerry_get_source_info](#jerry_get_source_info)
14641464

1465+
## jerry_syntax_error_location_t
1466+
1467+
**Summary**
1468+
1469+
Detailed location info for SyntaxErrors. It contains the
1470+
start and end location of the token which caused the SyntaxError.
1471+
1472+
**Prototype**
1473+
1474+
```c
1475+
typedef struct
1476+
{
1477+
uint32_t line; /**< start line of the invalid token */
1478+
uint32_t column_start; /**< start column of the invalid token */
1479+
uint32_t column_end; /**< end column of the invalid token */
1480+
} jerry_syntax_error_location_t;
1481+
```
1482+
1483+
*New in version [[NEXT_RELEASE]]*.
1484+
1485+
**See also**
1486+
1487+
- [jerry_get_syntax_error_location](#jerry_get_syntax_error_location)
1488+
14651489
## jerry_arraybuffer_type_t
14661490

14671491
**Summary**
@@ -12236,8 +12260,8 @@ Returns a newly created source info structure corresponding to the passed script
1223612260
The function is lower level than `toString()` operation, but provides more contextual information.
1223712261

1223812262
*Notes*:
12239-
- Returned value must be freed with [jerry_free_source_info](#jerry_free_source_info) when it
12240-
is no longer needed.
12263+
- Returned value must be freed with [jerry_free_source_info](#jerry_free_source_info)
12264+
when it is no longer needed.
1224112265
- This API depends on a build option (`JERRY_FUNCTION_TO_STRING`) and can be checked
1224212266
in runtime with the `JERRY_FEATURE_FUNCTION_TO_STRING` feature enum value,
1224312267
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
@@ -12320,6 +12344,69 @@ See [jerry_get_source_info](#jerry_get_source_info)
1232012344
- [jerry_get_source_info](#jerry_get_source_info)
1232112345
- [jerry_source_info_t](#jerry_source_info_t)
1232212346

12347+
## jerry_get_syntax_error_location
12348+
12349+
**Summary**
12350+
12351+
Gets the resource name and location info assigned to a SyntaxError object generated by the parser.
12352+
12353+
*Notes*:
12354+
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
12355+
when it is no longer needed.
12356+
- This API depends on a build option (`JERRY_ERROR_MESSAGES`) and can be checked
12357+
in runtime with the `JERRY_FEATURE_ERROR_MESSAGES` feature enum value,
12358+
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
12359+
12360+
**Prototype**
12361+
12362+
```c
12363+
jerry_value_t jerry_get_syntax_error_location (jerry_value_t value,
12364+
jerry_syntax_error_location_t *error_location_p);
12365+
```
12366+
- `value` - SyntaxError object
12367+
- `error_location_p` - output location info
12368+
- return
12369+
- resource name - if the `value` object has a location info data
12370+
- error - otherwise
12371+
12372+
*New in version [[NEXT_RELEASE]]*.
12373+
12374+
**Example**
12375+
12376+
[doctest]: # ()
12377+
12378+
```c
12379+
#include "jerryscript.h"
12380+
12381+
int
12382+
main (void)
12383+
{
12384+
jerry_init (JERRY_INIT_EMPTY);
12385+
12386+
const jerry_char_t script[] = "aa bb";
12387+
12388+
jerry_value_t result_value = jerry_parse (script, sizeof (script) - 1, NULL);
12389+
12390+
jerry_syntax_error_location_t error_location;
12391+
jerry_value_t resource_value = jerry_get_syntax_error_location (result_value, &error_location);
12392+
12393+
if (jerry_value_is_string (resource_value))
12394+
{
12395+
/* Prints the location of the error. */
12396+
}
12397+
12398+
jerry_release_value (resource_value);
12399+
jerry_release_value (result_value);
12400+
12401+
jerry_cleanup ();
12402+
return 0;
12403+
}
12404+
```
12405+
12406+
**See also**
12407+
12408+
- [jerry_syntax_error_location_t](#jerry_syntax_error_location_t)
12409+
1232312410

1232412411
# Functions for realm objects
1232512412

jerry-core/api/jerryscript.c

+58
Original file line numberDiff line numberDiff line change
@@ -5645,6 +5645,64 @@ jerry_free_source_info (jerry_source_info_t *source_info_p) /**< source info blo
56455645
#endif /* JERRY_FUNCTION_TO_STRING */
56465646
} /* jerry_free_source_info */
56475647

5648+
/**
5649+
* Gets the resource name and location info assigned to a SyntaxError object generated by the parser.
5650+
*
5651+
* @return resource name, if a location info is available
5652+
* error, otherwise
5653+
*/
5654+
jerry_value_t
5655+
jerry_get_syntax_error_location (jerry_value_t value, /**< SyntaxError object */
5656+
jerry_syntax_error_location_t *error_location_p) /**< [out] location info */
5657+
{
5658+
jerry_assert_api_available ();
5659+
5660+
#if JERRY_ERROR_MESSAGES
5661+
if (ecma_is_value_error_reference (value))
5662+
{
5663+
value = ecma_get_extended_primitive_from_value (value)->u.value;
5664+
}
5665+
5666+
if (ecma_is_value_object (value))
5667+
{
5668+
ecma_object_t *object_p = ecma_get_object_from_value (value);
5669+
5670+
ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_SYNTAX_ERROR_LOCATION);
5671+
ecma_property_t *property_p = ecma_find_named_property (object_p, name_p);
5672+
5673+
if (property_p != NULL)
5674+
{
5675+
ecma_value_t error_property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value;
5676+
uint8_t *location_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (uint8_t, error_property_value);
5677+
ecma_value_t result = *(ecma_value_t *) location_p;
5678+
5679+
if (error_location_p != NULL)
5680+
{
5681+
size_t size_data = error_property_value & ECMA_SYNTAX_ERROR_ALLOCATION_SIZE_MASK;
5682+
location_p += ((size_data + 1) << ECMA_SYNTAX_ERROR_ALLOCATION_UNIT_SHIFT);
5683+
5684+
error_location_p->line = ecma_extended_info_decode_vlq (&location_p);
5685+
error_location_p->column_start = ecma_extended_info_decode_vlq (&location_p);
5686+
5687+
uint32_t difference = ecma_extended_info_decode_vlq (&location_p);
5688+
5689+
error_location_p->column_end = error_location_p->column_start + difference;
5690+
}
5691+
5692+
ecma_ref_ecma_string (ecma_get_string_from_value (result));
5693+
return result;
5694+
}
5695+
}
5696+
5697+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Location is not available")));
5698+
#else /* !JERRY_ERROR_MESSAGES */
5699+
JERRY_UNUSED (value);
5700+
JERRY_UNUSED (error_location_p);
5701+
5702+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Location is not available")));
5703+
#endif /* JERRY_ERROR_MESSAGES */
5704+
} /* jerry_get_syntax_error_location */
5705+
56485706
/**
56495707
* Replaces the currently active realm with another realm.
56505708
*

jerry-core/ecma/base/ecma-extended-info.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#include "byte-code.h"
2121

22-
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
22+
#if JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING
2323

2424
/** \addtogroup ecma ECMA
2525
* @{
@@ -105,6 +105,10 @@ ecma_extended_info_get_encoded_length (uint32_t value) /**< encoded value */
105105
return length;
106106
} /* ecma_extended_info_get_encoded_length */
107107

108+
#endif /* JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING */
109+
110+
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
111+
108112
/**
109113
* Get the extended info from a byte code
110114
*

jerry-core/ecma/base/ecma-extended-info.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
#include "ecma-globals.h"
2727

28-
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
28+
#if JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING
2929

3030
/**
3131
* Vlq encoding: flag which is set for all bytes except the last one.
@@ -46,6 +46,10 @@ uint32_t ecma_extended_info_decode_vlq (uint8_t **buffer_p);
4646
void ecma_extended_info_encode_vlq (uint8_t **buffer_p, uint32_t value);
4747
uint32_t ecma_extended_info_get_encoded_length (uint32_t value);
4848

49+
#endif /* JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING */
50+
51+
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
52+
4953
uint8_t *ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p);
5054

5155
#endif /* JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING */

jerry-core/ecma/base/ecma-gc.c

+12
Original file line numberDiff line numberDiff line change
@@ -1618,6 +1618,18 @@ ecma_gc_free_property (ecma_object_t *object_p, /**< object */
16181618
break;
16191619
}
16201620
#endif /* JERRY_BUILTIN_CONTAINER */
1621+
#if JERRY_ERROR_MESSAGES
1622+
case LIT_INTERNAL_MAGIC_STRING_SYNTAX_ERROR_LOCATION:
1623+
{
1624+
uint8_t *location_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (uint8_t, value);
1625+
1626+
ecma_deref_ecma_string (ecma_get_string_from_value (*(ecma_value_t *) location_p));
1627+
1628+
size_t size_data = value & ECMA_SYNTAX_ERROR_ALLOCATION_SIZE_MASK;
1629+
jmem_heap_free_block (location_p, (size_data + 1) << ECMA_SYNTAX_ERROR_ALLOCATION_UNIT_SHIFT);
1630+
break;
1631+
}
1632+
#endif /* JERRY_ERROR_MESSAGES */
16211633
default:
16221634
{
16231635
JERRY_ASSERT (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER

jerry-core/ecma/base/ecma-globals.h

+14
Original file line numberDiff line numberDiff line change
@@ -1920,6 +1920,20 @@ typedef struct
19201920
ecma_stringbuilder_header_t *header_p; /**< pointer to header */
19211921
} ecma_stringbuilder_t;
19221922

1923+
#if JERRY_ERROR_MESSAGES
1924+
1925+
/**
1926+
* Allocation block size shift for SyntaxError line info data.
1927+
*/
1928+
#define ECMA_SYNTAX_ERROR_ALLOCATION_UNIT_SHIFT 3
1929+
1930+
/**
1931+
* Mask for extracting allocation size.
1932+
*/
1933+
#define ECMA_SYNTAX_ERROR_ALLOCATION_SIZE_MASK 0x3
1934+
1935+
#endif /* JERRY_ERROR_MESSAGES */
1936+
19231937
#ifndef JERRY_BUILTIN_BIGINT
19241938
/**
19251939
* BigInt type.

jerry-core/include/jerryscript-core.h

+1
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ jerry_value_t jerry_get_user_value (const jerry_value_t value);
361361
bool jerry_is_eval_code (const jerry_value_t value);
362362
jerry_source_info_t *jerry_get_source_info (const jerry_value_t value);
363363
void jerry_free_source_info (jerry_source_info_t *source_info_p);
364+
jerry_value_t jerry_get_syntax_error_location (jerry_value_t value, jerry_syntax_error_location_t *error_location_p);
364365

365366
/**
366367
* Array buffer components.

jerry-core/include/jerryscript-types.h

+10
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,16 @@ typedef struct
817817
uint32_t source_range_length; /**< source length of the function in the source code */
818818
} jerry_source_info_t;
819819

820+
/**
821+
* Detailed location info for SyntaxErrors.
822+
*/
823+
typedef struct
824+
{
825+
uint32_t line; /**< start line of the invalid token */
826+
uint32_t column_start; /**< start column of the invalid token */
827+
uint32_t column_end; /**< end column of the invalid token */
828+
} jerry_syntax_error_location_t;
829+
820830
/**
821831
* Array buffer types.
822832
*/

jerry-core/jmem/jmem.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -262,12 +262,12 @@ void *JERRY_ATTR_PURE jmem_decompress_pointer (uintptr_t compressed_pointer);
262262
* Set value of pointer-tag value so that it will correspond
263263
* to specified non_compressed_pointer along with tag
264264
*/
265-
#define JMEM_CP_SET_NON_NULL_POINTER_TAG(cp_value, pointer, tag) \
266-
do \
267-
{ \
268-
JERRY_ASSERT ((uintptr_t) tag < (uintptr_t) (JMEM_ALIGNMENT)); \
269-
jmem_cpointer_tag_t compressed_ptr = jmem_compress_pointer (pointer); \
270-
(cp_value) = (jmem_cpointer_tag_t) ((compressed_ptr << JMEM_TAG_SHIFT) | tag); \
265+
#define JMEM_CP_SET_NON_NULL_POINTER_TAG(cp_value, pointer, tag) \
266+
do \
267+
{ \
268+
JERRY_ASSERT ((uintptr_t) tag < (uintptr_t) (JMEM_ALIGNMENT)); \
269+
jmem_cpointer_tag_t compressed_ptr = jmem_compress_pointer (pointer); \
270+
(cp_value) = (jmem_cpointer_tag_t) ((compressed_ptr << JMEM_TAG_SHIFT) | (tag)); \
271271
} while (false);
272272

273273
/**

jerry-core/lit/lit-magic-strings.h

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ typedef enum
6464
* data properties */
6565
LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES, /**< native pointer info associated with an object
6666
* which contains references to other values */
67+
LIT_INTERNAL_MAGIC_STRING_SYNTAX_ERROR_LOCATION, /**< location info for syntax error */
6768
LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD, /**< dynamic environment record needed by class constructors */
6869
LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED, /**< computed class field name list */
6970
LIT_INTERNAL_MAGIC_STRING_CONTAINER_WEAK_REFS, /**< Weak references to the current container object */

0 commit comments

Comments
 (0)