Skip to content

Commit

Permalink
Improve location info for syntax errors.
Browse files Browse the repository at this point in the history
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
  • Loading branch information
zherczeg committed Nov 4, 2021
1 parent 7ea0000 commit b27ea39
Show file tree
Hide file tree
Showing 17 changed files with 533 additions and 169 deletions.
91 changes: 89 additions & 2 deletions docs/02.API-REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1462,6 +1462,30 @@ typedef struct
- [jerry_source_info_enabled_fields_t](#jerry_source_info_enabled_fields_t)
- [jerry_get_source_info](#jerry_get_source_info)

## jerry_syntax_error_location_t

**Summary**

Detailed location info for SyntaxErrors. It contains the
start and end location of the token which caused the SyntaxError.

**Prototype**

```c
typedef struct
{
uint32_t line; /**< start line of the invalid token */
uint32_t column_start; /**< start column of the invalid token */
uint32_t column_end; /**< end column of the invalid token */
} jerry_syntax_error_location_t;
```

*New in version [[NEXT_RELEASE]]*.

**See also**

- [jerry_get_syntax_error_location](#jerry_get_syntax_error_location)

## jerry_arraybuffer_type_t

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

*Notes*:
- Returned value must be freed with [jerry_free_source_info](#jerry_free_source_info) when it
is no longer needed.
- Returned value must be freed with [jerry_free_source_info](#jerry_free_source_info)
when it is no longer needed.
- This API depends on a build option (`JERRY_FUNCTION_TO_STRING`) and can be checked
in runtime with the `JERRY_FEATURE_FUNCTION_TO_STRING` feature enum value,
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
Expand Down Expand Up @@ -12320,6 +12344,69 @@ See [jerry_get_source_info](#jerry_get_source_info)
- [jerry_get_source_info](#jerry_get_source_info)
- [jerry_source_info_t](#jerry_source_info_t)

## jerry_get_syntax_error_location

**Summary**

Gets the resource name and location info assigned to a SyntaxError object generated by the parser.

*Notes*:
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
when it is no longer needed.
- This API depends on a build option (`JERRY_ERROR_MESSAGES`) and can be checked
in runtime with the `JERRY_FEATURE_ERROR_MESSAGES` feature enum value,
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).

**Prototype**

```c
jerry_value_t jerry_get_syntax_error_location (jerry_value_t value,
jerry_syntax_error_location_t *error_location_p);
```
- `value` - SyntaxError object
- `error_location_p` - output location info
- return
- resource name - if the `value` object has a location info data
- error - otherwise

*New in version [[NEXT_RELEASE]]*.

**Example**

[doctest]: # ()

```c
#include "jerryscript.h"

int
main (void)
{
jerry_init (JERRY_INIT_EMPTY);

const jerry_char_t script[] = "aa bb";

jerry_value_t result_value = jerry_parse (script, sizeof (script) - 1, NULL);

jerry_syntax_error_location_t error_location;
jerry_value_t resource_value = jerry_get_syntax_error_location (result_value, &error_location);

if (jerry_value_is_string (resource_value))
{
/* Prints the location of the error. */
}

jerry_release_value (resource_value);
jerry_release_value (result_value);

jerry_cleanup ();
return 0;
}
```

**See also**

- [jerry_syntax_error_location_t](#jerry_syntax_error_location_t)


# Functions for realm objects

Expand Down
58 changes: 58 additions & 0 deletions jerry-core/api/jerry.c
Original file line number Diff line number Diff line change
Expand Up @@ -5773,6 +5773,64 @@ jerry_free_source_info (jerry_source_info_t *source_info_p) /**< source info blo
#endif /* JERRY_FUNCTION_TO_STRING */
} /* jerry_free_source_info */

/**
* Gets the resource name and location info assigned to a SyntaxError object generated by the parser.
*
* @return resource name, if a location info is available
* error, otherwise
*/
jerry_value_t
jerry_get_syntax_error_location (jerry_value_t value, /**< SyntaxError object */
jerry_syntax_error_location_t *error_location_p) /**< [out] location info */
{
jerry_assert_api_available ();

#if JERRY_ERROR_MESSAGES
if (ecma_is_value_error_reference (value))
{
value = ecma_get_extended_primitive_from_value (value)->u.value;
}

if (ecma_is_value_object (value))
{
ecma_object_t *object_p = ecma_get_object_from_value (value);

ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_SYNTAX_ERROR_LOCATION);
ecma_property_t *property_p = ecma_find_named_property (object_p, name_p);

if (property_p != NULL)
{
ecma_value_t error_property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value;
uint8_t *location_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (uint8_t, error_property_value);
ecma_value_t result = *(ecma_value_t *) location_p;

if (error_location_p != NULL)
{
size_t size_data = error_property_value & ECMA_SYNTAX_ERROR_ALLOCATION_SIZE_MASK;
location_p += ((size_data + 1) << ECMA_SYNTAX_ERROR_ALLOCATION_UNIT_SHIFT);

error_location_p->line = ecma_extended_info_decode_vlq (&location_p);
error_location_p->column_start = ecma_extended_info_decode_vlq (&location_p);

uint32_t difference = ecma_extended_info_decode_vlq (&location_p);

error_location_p->column_end = error_location_p->column_start + difference;
}

ecma_ref_ecma_string (ecma_get_string_from_value (result));
return result;
}
}

return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Location is not available")));
#else /* !JERRY_ERROR_MESSAGES */
JERRY_UNUSED (value);
JERRY_UNUSED (error_location_p);

return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Location is not available")));
#endif /* JERRY_ERROR_MESSAGES */
} /* jerry_get_syntax_error_location */

/**
* Replaces the currently active realm with another realm.
*
Expand Down
6 changes: 5 additions & 1 deletion jerry-core/ecma/base/ecma-extended-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "ecma-helpers.h"
#include "ecma-extended-info.h"

#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
#if JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING

/** \addtogroup ecma ECMA
* @{
Expand Down Expand Up @@ -107,6 +107,10 @@ ecma_extended_info_get_encoded_length (uint32_t value) /**< encoded value */
return length;
} /* ecma_extended_info_get_encoded_length */

#endif /* JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING */

#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING

/**
* Get the extended info from a byte code
*
Expand Down
6 changes: 5 additions & 1 deletion jerry-core/ecma/base/ecma-extended-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @{
*/

#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
#if JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING

#include "ecma-globals.h"

Expand All @@ -46,6 +46,10 @@ uint32_t ecma_extended_info_decode_vlq (uint8_t **buffer_p);
void ecma_extended_info_encode_vlq (uint8_t **buffer_p, uint32_t value);
uint32_t ecma_extended_info_get_encoded_length (uint32_t value);

#endif /* JERRY_ESNEXT || JERRY_ERROR_MESSAGES || JERRY_FUNCTION_TO_STRING */

#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING

uint8_t *ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p);

#endif /* JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING */
Expand Down
12 changes: 12 additions & 0 deletions jerry-core/ecma/base/ecma-gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1633,6 +1633,18 @@ ecma_gc_free_property (ecma_object_t *object_p, /**< object */
break;
}
#endif /* JERRY_BUILTIN_CONTAINER */
#if JERRY_ERROR_MESSAGES
case LIT_INTERNAL_MAGIC_STRING_SYNTAX_ERROR_LOCATION:
{
uint8_t *location_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (uint8_t, value);

ecma_deref_ecma_string (ecma_get_string_from_value (*(ecma_value_t *) location_p));

size_t size_data = value & ECMA_SYNTAX_ERROR_ALLOCATION_SIZE_MASK;
jmem_heap_free_block (location_p, (size_data + 1) << ECMA_SYNTAX_ERROR_ALLOCATION_UNIT_SHIFT);
break;
}
#endif /* JERRY_ERROR_MESSAGES */
default:
{
JERRY_ASSERT (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER
Expand Down
14 changes: 14 additions & 0 deletions jerry-core/ecma/base/ecma-globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -1953,6 +1953,20 @@ typedef struct
ecma_stringbuilder_header_t *header_p; /**< pointer to header */
} ecma_stringbuilder_t;

#if JERRY_ERROR_MESSAGES

/**
* Allocation block size shift for SyntaxError line info data.
*/
#define ECMA_SYNTAX_ERROR_ALLOCATION_UNIT_SHIFT 3

/**
* Mask for extracting allocation size.
*/
#define ECMA_SYNTAX_ERROR_ALLOCATION_SIZE_MASK 0x3

#endif /* JERRY_ERROR_MESSAGES */

#ifndef JERRY_BUILTIN_BIGINT
/**
* BigInt type.
Expand Down
2 changes: 2 additions & 0 deletions jerry-core/include/jerryscript-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ jerry_value_t jerry_get_user_value (const jerry_value_t value);
bool jerry_is_eval_code (const jerry_value_t value);
jerry_source_info_t *jerry_get_source_info (const jerry_value_t value);
void jerry_free_source_info (jerry_source_info_t *source_info_p);
jerry_value_t jerry_get_syntax_error_location (jerry_value_t value,
jerry_syntax_error_location_t *error_location_p);

/**
* Array buffer components.
Expand Down
10 changes: 10 additions & 0 deletions jerry-core/include/jerryscript-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,16 @@ typedef struct
uint32_t source_range_length; /**< source length of the function in the source code */
} jerry_source_info_t;

/**
* Detailed location info for SyntaxErrors.
*/
typedef struct
{
uint32_t line; /**< start line of the invalid token */
uint32_t column_start; /**< start column of the invalid token */
uint32_t column_end; /**< end column of the invalid token */
} jerry_syntax_error_location_t;

/**
* Array buffer types.
*/
Expand Down
2 changes: 1 addition & 1 deletion jerry-core/jmem/jmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ void * JERRY_ATTR_PURE jmem_decompress_pointer (uintptr_t compressed_pointer);
{ \
JERRY_ASSERT ((uintptr_t) tag < (uintptr_t) (JMEM_ALIGNMENT)); \
jmem_cpointer_tag_t compressed_ptr = jmem_compress_pointer (pointer); \
(cp_value) = (jmem_cpointer_tag_t) ((compressed_ptr << JMEM_TAG_SHIFT) | tag); \
(cp_value) = (jmem_cpointer_tag_t) ((compressed_ptr << JMEM_TAG_SHIFT) | (tag)); \
} while (false);

/**
Expand Down
1 change: 1 addition & 0 deletions jerry-core/lit/lit-magic-strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ typedef enum
* data properties */
LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES, /**< native pointer info associated with an object
* which contains references to other values */
LIT_INTERNAL_MAGIC_STRING_SYNTAX_ERROR_LOCATION, /**< location info for syntax error */
LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD, /**< dynamic environment record needed by class constructors */
LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED, /**< computed class field name list */
LIT_INTERNAL_MAGIC_STRING_CONTAINER_WEAK_REFS, /**< Weak references to the current container object */
Expand Down
Loading

0 comments on commit b27ea39

Please sign in to comment.