Skip to content

Commit b27ea39

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

17 files changed

+533
-169
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/jerry.c

+58
Original file line numberDiff line numberDiff line change
@@ -5773,6 +5773,64 @@ jerry_free_source_info (jerry_source_info_t *source_info_p) /**< source info blo
57735773
#endif /* JERRY_FUNCTION_TO_STRING */
57745774
} /* jerry_free_source_info */
57755775

5776+
/**
5777+
* Gets the resource name and location info assigned to a SyntaxError object generated by the parser.
5778+
*
5779+
* @return resource name, if a location info is available
5780+
* error, otherwise
5781+
*/
5782+
jerry_value_t
5783+
jerry_get_syntax_error_location (jerry_value_t value, /**< SyntaxError object */
5784+
jerry_syntax_error_location_t *error_location_p) /**< [out] location info */
5785+
{
5786+
jerry_assert_api_available ();
5787+
5788+
#if JERRY_ERROR_MESSAGES
5789+
if (ecma_is_value_error_reference (value))
5790+
{
5791+
value = ecma_get_extended_primitive_from_value (value)->u.value;
5792+
}
5793+
5794+
if (ecma_is_value_object (value))
5795+
{
5796+
ecma_object_t *object_p = ecma_get_object_from_value (value);
5797+
5798+
ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_SYNTAX_ERROR_LOCATION);
5799+
ecma_property_t *property_p = ecma_find_named_property (object_p, name_p);
5800+
5801+
if (property_p != NULL)
5802+
{
5803+
ecma_value_t error_property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value;
5804+
uint8_t *location_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (uint8_t, error_property_value);
5805+
ecma_value_t result = *(ecma_value_t *) location_p;
5806+
5807+
if (error_location_p != NULL)
5808+
{
5809+
size_t size_data = error_property_value & ECMA_SYNTAX_ERROR_ALLOCATION_SIZE_MASK;
5810+
location_p += ((size_data + 1) << ECMA_SYNTAX_ERROR_ALLOCATION_UNIT_SHIFT);
5811+
5812+
error_location_p->line = ecma_extended_info_decode_vlq (&location_p);
5813+
error_location_p->column_start = ecma_extended_info_decode_vlq (&location_p);
5814+
5815+
uint32_t difference = ecma_extended_info_decode_vlq (&location_p);
5816+
5817+
error_location_p->column_end = error_location_p->column_start + difference;
5818+
}
5819+
5820+
ecma_ref_ecma_string (ecma_get_string_from_value (result));
5821+
return result;
5822+
}
5823+
}
5824+
5825+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Location is not available")));
5826+
#else /* !JERRY_ERROR_MESSAGES */
5827+
JERRY_UNUSED (value);
5828+
JERRY_UNUSED (error_location_p);
5829+
5830+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Location is not available")));
5831+
#endif /* JERRY_ERROR_MESSAGES */
5832+
} /* jerry_get_syntax_error_location */
5833+
57765834
/**
57775835
* Replaces the currently active realm with another realm.
57785836
*

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "ecma-helpers.h"
1818
#include "ecma-extended-info.h"
1919

20-
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
20+
#if JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING
2121

2222
/** \addtogroup ecma ECMA
2323
* @{
@@ -107,6 +107,10 @@ ecma_extended_info_get_encoded_length (uint32_t value) /**< encoded value */
107107
return length;
108108
} /* ecma_extended_info_get_encoded_length */
109109

110+
#endif /* JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING */
111+
112+
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
113+
110114
/**
111115
* Get the extended info from a byte code
112116
*

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
* @{
2424
*/
2525

26-
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
26+
#if JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING
2727

2828
#include "ecma-globals.h"
2929

@@ -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
@@ -1633,6 +1633,18 @@ ecma_gc_free_property (ecma_object_t *object_p, /**< object */
16331633
break;
16341634
}
16351635
#endif /* JERRY_BUILTIN_CONTAINER */
1636+
#if JERRY_ERROR_MESSAGES
1637+
case LIT_INTERNAL_MAGIC_STRING_SYNTAX_ERROR_LOCATION:
1638+
{
1639+
uint8_t *location_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (uint8_t, value);
1640+
1641+
ecma_deref_ecma_string (ecma_get_string_from_value (*(ecma_value_t *) location_p));
1642+
1643+
size_t size_data = value & ECMA_SYNTAX_ERROR_ALLOCATION_SIZE_MASK;
1644+
jmem_heap_free_block (location_p, (size_data + 1) << ECMA_SYNTAX_ERROR_ALLOCATION_UNIT_SHIFT);
1645+
break;
1646+
}
1647+
#endif /* JERRY_ERROR_MESSAGES */
16361648
default:
16371649
{
16381650
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
@@ -1953,6 +1953,20 @@ typedef struct
19531953
ecma_stringbuilder_header_t *header_p; /**< pointer to header */
19541954
} ecma_stringbuilder_t;
19551955

1956+
#if JERRY_ERROR_MESSAGES
1957+
1958+
/**
1959+
* Allocation block size shift for SyntaxError line info data.
1960+
*/
1961+
#define ECMA_SYNTAX_ERROR_ALLOCATION_UNIT_SHIFT 3
1962+
1963+
/**
1964+
* Mask for extracting allocation size.
1965+
*/
1966+
#define ECMA_SYNTAX_ERROR_ALLOCATION_SIZE_MASK 0x3
1967+
1968+
#endif /* JERRY_ERROR_MESSAGES */
1969+
19561970
#ifndef JERRY_BUILTIN_BIGINT
19571971
/**
19581972
* BigInt type.

jerry-core/include/jerryscript-core.h

+2
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ jerry_value_t jerry_get_user_value (const jerry_value_t value);
367367
bool jerry_is_eval_code (const jerry_value_t value);
368368
jerry_source_info_t *jerry_get_source_info (const jerry_value_t value);
369369
void jerry_free_source_info (jerry_source_info_t *source_info_p);
370+
jerry_value_t jerry_get_syntax_error_location (jerry_value_t value,
371+
jerry_syntax_error_location_t *error_location_p);
370372

371373
/**
372374
* Array buffer components.

jerry-core/include/jerryscript-types.h

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

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

jerry-core/jmem/jmem.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ void * JERRY_ATTR_PURE jmem_decompress_pointer (uintptr_t compressed_pointer);
268268
{ \
269269
JERRY_ASSERT ((uintptr_t) tag < (uintptr_t) (JMEM_ALIGNMENT)); \
270270
jmem_cpointer_tag_t compressed_ptr = jmem_compress_pointer (pointer); \
271-
(cp_value) = (jmem_cpointer_tag_t) ((compressed_ptr << JMEM_TAG_SHIFT) | tag); \
271+
(cp_value) = (jmem_cpointer_tag_t) ((compressed_ptr << JMEM_TAG_SHIFT) | (tag)); \
272272
} while (false);
273273

274274
/**

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

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

0 commit comments

Comments
 (0)